mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:18:11 +00:00
Make it possible to sort a GTableModel by column+order.
This is accomplished by putting a GSortingProxyTableModel between the model and the view. It's pretty simplistic but it works for this use case. :^)
This commit is contained in:
parent
0680fe2383
commit
7d1142c7d9
16 changed files with 278 additions and 40 deletions
|
@ -76,6 +76,7 @@ public:
|
||||||
|
|
||||||
bool operator==(const String&) const;
|
bool operator==(const String&) const;
|
||||||
bool operator!=(const String& other) const { return !(*this == other); }
|
bool operator!=(const String& other) const { return !(*this == other); }
|
||||||
|
bool operator<(const String&) const;
|
||||||
|
|
||||||
String isolated_copy() const;
|
String isolated_copy() const;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,17 @@ bool String::operator==(const String& other) const
|
||||||
return !memcmp(characters(), other.characters(), length());
|
return !memcmp(characters(), other.characters(), length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool String::operator<(const String& other) const
|
||||||
|
{
|
||||||
|
if (!m_impl)
|
||||||
|
return other.m_impl;
|
||||||
|
|
||||||
|
if (!other.m_impl)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return strcmp(characters(), other.characters());
|
||||||
|
}
|
||||||
|
|
||||||
String String::empty()
|
String String::empty()
|
||||||
{
|
{
|
||||||
return StringImpl::the_empty_stringimpl();
|
return StringImpl::the_empty_stringimpl();
|
||||||
|
|
|
@ -3,19 +3,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
enum Column {
|
|
||||||
Icon = 0,
|
|
||||||
Name,
|
|
||||||
CPU,
|
|
||||||
State,
|
|
||||||
Priority,
|
|
||||||
User,
|
|
||||||
PID,
|
|
||||||
Linear,
|
|
||||||
Physical,
|
|
||||||
__Count
|
|
||||||
};
|
|
||||||
|
|
||||||
ProcessTableModel::ProcessTableModel()
|
ProcessTableModel::ProcessTableModel()
|
||||||
{
|
{
|
||||||
setpwent();
|
setpwent();
|
||||||
|
|
|
@ -8,6 +8,19 @@
|
||||||
|
|
||||||
class ProcessTableModel final : public GTableModel {
|
class ProcessTableModel final : public GTableModel {
|
||||||
public:
|
public:
|
||||||
|
enum Column {
|
||||||
|
Icon = 0,
|
||||||
|
Name,
|
||||||
|
CPU,
|
||||||
|
State,
|
||||||
|
Priority,
|
||||||
|
User,
|
||||||
|
PID,
|
||||||
|
Linear,
|
||||||
|
Physical,
|
||||||
|
__Count
|
||||||
|
};
|
||||||
|
|
||||||
ProcessTableModel();
|
ProcessTableModel();
|
||||||
virtual ~ProcessTableModel() override;
|
virtual ~ProcessTableModel() override;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#include "ProcessTableView.h"
|
#include "ProcessTableView.h"
|
||||||
#include "ProcessTableModel.h"
|
#include "ProcessTableModel.h"
|
||||||
|
#include <LibGUI/GSortingProxyTableModel.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
ProcessTableView::ProcessTableView(GWidget* parent)
|
ProcessTableView::ProcessTableView(GWidget* parent)
|
||||||
: GTableView(parent)
|
: GTableView(parent)
|
||||||
{
|
{
|
||||||
set_model(make<ProcessTableModel>());
|
auto process_model = make<ProcessTableModel>();
|
||||||
|
m_model = process_model.ptr();
|
||||||
|
set_model(make<GSortingProxyTableModel>(move(process_model)));
|
||||||
|
GTableView::model()->set_key_column_and_sort_order(ProcessTableModel::Column::CPU, GSortOrder::Descending);
|
||||||
start_timer(1000);
|
start_timer(1000);
|
||||||
model().update();
|
model().update();
|
||||||
}
|
}
|
||||||
|
@ -32,13 +36,3 @@ pid_t ProcessTableView::selected_pid() const
|
||||||
{
|
{
|
||||||
return model().selected_pid();
|
return model().selected_pid();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ProcessTableModel& ProcessTableView::model()
|
|
||||||
{
|
|
||||||
return static_cast<ProcessTableModel&>(*GTableView::model());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ProcessTableModel& ProcessTableView::model() const
|
|
||||||
{
|
|
||||||
return static_cast<const ProcessTableModel&>(*GTableView::model());
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ protected:
|
||||||
private:
|
private:
|
||||||
virtual void timer_event(GTimerEvent&) override;
|
virtual void timer_event(GTimerEvent&) override;
|
||||||
|
|
||||||
ProcessTableModel& model();
|
ProcessTableModel& model() { return *m_model; }
|
||||||
const ProcessTableModel& model() const;
|
const ProcessTableModel& model() const { return *m_model; }
|
||||||
|
|
||||||
|
ProcessTableModel* m_model { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#define SPAWN_LAUNCHER
|
#define SPAWN_LAUNCHER
|
||||||
//#define SPAWN_GUITEST2
|
//#define SPAWN_GUITEST2
|
||||||
//#define SPAWN_FILE_MANAGER
|
//#define SPAWN_FILE_MANAGER
|
||||||
//#define SPAWN_PROCESS_MANAGER
|
#define SPAWN_PROCESS_MANAGER
|
||||||
#define SPAWN_TEXT_EDITOR
|
//#define SPAWN_TEXT_EDITOR
|
||||||
//#define SPAWN_FONTEDITOR
|
//#define SPAWN_FONTEDITOR
|
||||||
//#define SPAWN_MULTIPLE_SHELLS
|
//#define SPAWN_MULTIPLE_SHELLS
|
||||||
//#define STRESS_TEST_SPAWNING
|
//#define STRESS_TEST_SPAWNING
|
||||||
|
|
|
@ -38,7 +38,8 @@ static char sccsid[] = "@(#)qsort.c 5.9 (Berkeley) 2/23/91";
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
static void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
||||||
|
static void insertion_sort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg);
|
||||||
|
|
||||||
void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
|
void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
|
||||||
{
|
{
|
||||||
|
@ -48,23 +49,23 @@ void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, con
|
||||||
insertion_sort(bot, nmemb, size, compar);
|
insertion_sort(bot, nmemb, size, compar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
|
void qsort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg)
|
||||||
|
{
|
||||||
|
if (nmemb <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
insertion_sort_r(bot, nmemb, size, compar, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*))
|
||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
char *s1, *s2, *t1, *t2, *top;
|
char *s1, *s2, *t1, *t2, *top;
|
||||||
|
|
||||||
/*
|
|
||||||
* A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm
|
|
||||||
* S). Insertion sort has the same worst case as most simple sorts
|
|
||||||
* (O N^2). It gets used here because it is (O N) in the case of
|
|
||||||
* sorted data.
|
|
||||||
*/
|
|
||||||
top = (char*)bot + nmemb * size;
|
top = (char*)bot + nmemb * size;
|
||||||
for (t1 = (char*)bot + size; t1 < top;) {
|
for (t1 = (char*)bot + size; t1 < top;) {
|
||||||
for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;);
|
for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;);
|
||||||
if (t1 != (t2 += size)) {
|
if (t1 != (t2 += size)) {
|
||||||
/* Bubble bytes up through each element. */
|
|
||||||
for (cnt = size; cnt--; ++t1) {
|
for (cnt = size; cnt--; ++t1) {
|
||||||
ch = *t1;
|
ch = *t1;
|
||||||
for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
|
for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
|
||||||
|
@ -75,3 +76,23 @@ void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const vo
|
||||||
t1 += size;
|
t1 += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void insertion_sort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
unsigned char ch;
|
||||||
|
char *s1, *s2, *t1, *t2, *top;
|
||||||
|
top = (char*)bot + nmemb * size;
|
||||||
|
for (t1 = (char*)bot + size; t1 < top;) {
|
||||||
|
for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2, arg) < 0;);
|
||||||
|
if (t1 != (t2 += size)) {
|
||||||
|
for (cnt = size; cnt--; ++t1) {
|
||||||
|
ch = *t1;
|
||||||
|
for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
|
||||||
|
*s1 = *s2;
|
||||||
|
*s1 = ch;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
t1 += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ long atol(const char*);
|
||||||
double strtod(const char*, char** endptr);
|
double strtod(const char*, char** endptr);
|
||||||
long strtol(const char*, char** endptr, int base);
|
long strtol(const char*, char** endptr, int base);
|
||||||
unsigned long strtoul(const char*, char** endptr, int base);
|
unsigned long strtoul(const char*, char** endptr, int base);
|
||||||
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
||||||
|
void qsort_r(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg);
|
||||||
int atexit(void (*function)());
|
int atexit(void (*function)());
|
||||||
__attribute__((noreturn)) void exit(int status);
|
__attribute__((noreturn)) void exit(int status);
|
||||||
__attribute__((noreturn)) void abort();
|
__attribute__((noreturn)) void abort();
|
||||||
|
|
116
LibGUI/GSortingProxyTableModel.cpp
Normal file
116
LibGUI/GSortingProxyTableModel.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#include <LibGUI/GSortingProxyTableModel.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
GSortingProxyTableModel::GSortingProxyTableModel(OwnPtr<GTableModel>&& target)
|
||||||
|
: m_target(move(target))
|
||||||
|
, m_key_column(-1)
|
||||||
|
{
|
||||||
|
m_target->on_model_update = [this] (GTableModel&) {
|
||||||
|
resort();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
GSortingProxyTableModel::~GSortingProxyTableModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int GSortingProxyTableModel::row_count() const
|
||||||
|
{
|
||||||
|
return target().row_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GSortingProxyTableModel::column_count() const
|
||||||
|
{
|
||||||
|
return target().column_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
GModelIndex GSortingProxyTableModel::map_to_target(const GModelIndex& index) const
|
||||||
|
{
|
||||||
|
ASSERT(!m_row_mappings.is_empty());
|
||||||
|
if (!index.is_valid()) {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
if (index.row() >= row_count() || index.column() >= column_count()) {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
return { m_row_mappings[index.row()], index.column() };
|
||||||
|
}
|
||||||
|
|
||||||
|
String GSortingProxyTableModel::row_name(int index) const
|
||||||
|
{
|
||||||
|
return target().row_name(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
String GSortingProxyTableModel::column_name(int index) const
|
||||||
|
{
|
||||||
|
return target().column_name(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTableModel::ColumnMetadata GSortingProxyTableModel::column_metadata(int index) const
|
||||||
|
{
|
||||||
|
return target().column_metadata(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant GSortingProxyTableModel::data(const GModelIndex& index) const
|
||||||
|
{
|
||||||
|
return target().data(map_to_target(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSortingProxyTableModel::activate(const GModelIndex& index)
|
||||||
|
{
|
||||||
|
target().activate(map_to_target(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSortingProxyTableModel::update()
|
||||||
|
{
|
||||||
|
target().update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSortingProxyTableModel::set_key_column_and_sort_order(int column, GSortOrder sort_order)
|
||||||
|
{
|
||||||
|
if (column == m_key_column && sort_order == m_sort_order)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ASSERT(column >= 0 && column < column_count());
|
||||||
|
m_key_column = column;
|
||||||
|
m_sort_order = sort_order;
|
||||||
|
resort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSortingProxyTableModel::resort()
|
||||||
|
{
|
||||||
|
int row_count = target().row_count();
|
||||||
|
m_row_mappings.resize(row_count);
|
||||||
|
for (int i = 0; i < row_count; ++i)
|
||||||
|
m_row_mappings[i] = i;
|
||||||
|
|
||||||
|
if (m_key_column == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
GTableModel* target;
|
||||||
|
int key_column;
|
||||||
|
GSortOrder sort_order;
|
||||||
|
};
|
||||||
|
Context context { m_target.ptr(), m_key_column, m_sort_order };
|
||||||
|
qsort_r(m_row_mappings.data(), m_row_mappings.size(), sizeof(int), [] (const void* a, const void* b, void* ctx) -> int {
|
||||||
|
int row1 = *(const int*)(a);
|
||||||
|
int row2 = *(const int*)(b);
|
||||||
|
auto& context = *(Context*)(ctx);
|
||||||
|
GModelIndex index1 { row1, context.key_column };
|
||||||
|
GModelIndex index2 { row2, context.key_column };
|
||||||
|
auto data1 = context.target->data(index1);
|
||||||
|
auto data2 = context.target->data(index2);
|
||||||
|
if (data1 == data2)
|
||||||
|
return 0;
|
||||||
|
bool is_less_than = data1 < data2;
|
||||||
|
if (context.sort_order == GSortOrder::Ascending)
|
||||||
|
return is_less_than ? -1 : 1;
|
||||||
|
return is_less_than ? 1 : -1;
|
||||||
|
}, &context);
|
||||||
|
|
||||||
|
did_update();
|
||||||
|
}
|
35
LibGUI/GSortingProxyTableModel.h
Normal file
35
LibGUI/GSortingProxyTableModel.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGUI/GTableModel.h>
|
||||||
|
|
||||||
|
class GSortingProxyTableModel final : public GTableModel {
|
||||||
|
public:
|
||||||
|
explicit GSortingProxyTableModel(OwnPtr<GTableModel>&&);
|
||||||
|
virtual ~GSortingProxyTableModel() override;
|
||||||
|
|
||||||
|
virtual int row_count() const override;
|
||||||
|
virtual int column_count() const override;
|
||||||
|
virtual String row_name(int) const override;
|
||||||
|
virtual String column_name(int) const override;
|
||||||
|
virtual ColumnMetadata column_metadata(int) const override;
|
||||||
|
virtual GVariant data(const GModelIndex&) const override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void activate(const GModelIndex&) override;
|
||||||
|
|
||||||
|
virtual int key_column() const override { return m_key_column; }
|
||||||
|
virtual GSortOrder sort_order() const override { return m_sort_order; }
|
||||||
|
virtual void set_key_column_and_sort_order(int, GSortOrder) override;
|
||||||
|
|
||||||
|
GModelIndex map_to_target(const GModelIndex&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTableModel& target() { return *m_target; }
|
||||||
|
const GTableModel& target() const { return *m_target; }
|
||||||
|
|
||||||
|
void resort();
|
||||||
|
|
||||||
|
OwnPtr<GTableModel> m_target;
|
||||||
|
Vector<int> m_row_mappings;
|
||||||
|
int m_key_column { -1 };
|
||||||
|
GSortOrder m_sort_order { GSortOrder::Ascending };
|
||||||
|
};
|
|
@ -27,6 +27,8 @@ void GTableModel::for_each_view(Function<void(GTableView&)> callback)
|
||||||
|
|
||||||
void GTableModel::did_update()
|
void GTableModel::did_update()
|
||||||
{
|
{
|
||||||
|
if (on_model_update)
|
||||||
|
on_model_update(*this);
|
||||||
for_each_view([] (GTableView& view) {
|
for_each_view([] (GTableView& view) {
|
||||||
view.did_update_model();
|
view.did_update_model();
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
class GTableView;
|
class GTableView;
|
||||||
|
|
||||||
|
enum class GSortOrder { None, Ascending, Descending };
|
||||||
|
|
||||||
class GModelNotification {
|
class GModelNotification {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
||||||
|
@ -57,9 +59,15 @@ public:
|
||||||
void set_selected_index(const GModelIndex& index) { m_selected_index = index; }
|
void set_selected_index(const GModelIndex& index) { m_selected_index = index; }
|
||||||
GModelIndex selected_index() const { return m_selected_index; }
|
GModelIndex selected_index() const { return m_selected_index; }
|
||||||
|
|
||||||
|
virtual int key_column() const { return -1; }
|
||||||
|
virtual GSortOrder sort_order() const { return GSortOrder::None; }
|
||||||
|
virtual void set_key_column_and_sort_order(int, GSortOrder) { }
|
||||||
|
|
||||||
void register_view(Badge<GTableView>, GTableView&);
|
void register_view(Badge<GTableView>, GTableView&);
|
||||||
void unregister_view(Badge<GTableView>, GTableView&);
|
void unregister_view(Badge<GTableView>, GTableView&);
|
||||||
|
|
||||||
|
Function<void(GTableModel&)> on_model_update;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GTableModel();
|
GTableModel();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,49 @@ GVariant::GVariant(const GraphicsBitmap& value)
|
||||||
AK::retain_if_not_null(m_value.as_bitmap);
|
AK::retain_if_not_null(m_value.as_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GVariant::operator==(const GVariant& other) const
|
||||||
|
{
|
||||||
|
if (m_type != other.m_type)
|
||||||
|
return to_string() == other.to_string();
|
||||||
|
switch (m_type) {
|
||||||
|
case Type::Bool:
|
||||||
|
return as_bool() == other.as_bool();
|
||||||
|
case Type::Int:
|
||||||
|
return as_int() == other.as_int();
|
||||||
|
case Type::Float:
|
||||||
|
return as_float() == other.as_float();
|
||||||
|
case Type::String:
|
||||||
|
return as_string() == other.as_string();
|
||||||
|
case Type::Bitmap:
|
||||||
|
return m_value.as_bitmap == other.m_value.as_bitmap;
|
||||||
|
case Type::Invalid:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GVariant::operator<(const GVariant& other) const
|
||||||
|
{
|
||||||
|
if (m_type != other.m_type)
|
||||||
|
return to_string() < other.to_string();
|
||||||
|
switch (m_type) {
|
||||||
|
case Type::Bool:
|
||||||
|
return as_bool() < other.as_bool();
|
||||||
|
case Type::Int:
|
||||||
|
return as_int() < other.as_int();
|
||||||
|
case Type::Float:
|
||||||
|
return as_float() < other.as_float();
|
||||||
|
case Type::String:
|
||||||
|
return as_string() < other.as_string();
|
||||||
|
case Type::Bitmap:
|
||||||
|
// FIXME: Maybe compare bitmaps somehow differently?
|
||||||
|
return m_value.as_bitmap < other.m_value.as_bitmap;
|
||||||
|
case Type::Invalid:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
String GVariant::to_string() const
|
String GVariant::to_string() const
|
||||||
{
|
{
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
|
|
|
@ -62,6 +62,9 @@ public:
|
||||||
|
|
||||||
String to_string() const;
|
String to_string() const;
|
||||||
|
|
||||||
|
bool operator==(const GVariant&) const;
|
||||||
|
bool operator<(const GVariant&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
union {
|
union {
|
||||||
StringImpl* as_string;
|
StringImpl* as_string;
|
||||||
|
|
|
@ -34,6 +34,7 @@ LIBGUI_OBJS = \
|
||||||
GShortcut.o \
|
GShortcut.o \
|
||||||
GTextEditor.o \
|
GTextEditor.o \
|
||||||
GClipboard.o \
|
GClipboard.o \
|
||||||
|
GSortingProxyTableModel.o \
|
||||||
GWindow.o
|
GWindow.o
|
||||||
|
|
||||||
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)
|
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue