summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Applications/FileManager/DirectoryView.cpp2
-rw-r--r--Applications/SystemMonitor/ProcessMemoryMapWidget.cpp2
-rw-r--r--Applications/SystemMonitor/main.cpp2
-rw-r--r--Libraries/LibGUI/AbstractTableView.cpp16
-rw-r--r--Libraries/LibGUI/AbstractView.cpp12
-rw-r--r--Libraries/LibGUI/AbstractView.h5
-rw-r--r--Libraries/LibGUI/FilePicker.cpp2
-rw-r--r--Libraries/LibGUI/Forward.h2
-rw-r--r--Libraries/LibGUI/Model.h5
-rw-r--r--Libraries/LibGUI/MultiView.cpp7
-rw-r--r--Libraries/LibGUI/MultiView.h2
-rw-r--r--Libraries/LibGUI/ProcessChooser.cpp2
-rw-r--r--Libraries/LibGUI/SortingProxyModel.cpp68
-rw-r--r--Libraries/LibGUI/SortingProxyModel.h11
-rw-r--r--Libraries/LibGUI/TableView.cpp2
15 files changed, 85 insertions, 55 deletions
diff --git a/Applications/FileManager/DirectoryView.cpp b/Applications/FileManager/DirectoryView.cpp
index a9350f6001..d9b0ff07a3 100644
--- a/Applications/FileManager/DirectoryView.cpp
+++ b/Applications/FileManager/DirectoryView.cpp
@@ -127,7 +127,7 @@ DirectoryView::DirectoryView()
m_table_view = add<GUI::TableView>();
m_table_view->set_model(m_sorting_model);
- m_table_view->model()->set_key_column_and_sort_order(GUI::FileSystemModel::Column::Name, GUI::SortOrder::Ascending);
+ m_table_view->set_key_column_and_sort_order(GUI::FileSystemModel::Column::Name, GUI::SortOrder::Ascending);
m_icon_view->set_model_column(GUI::FileSystemModel::Column::Name);
m_columns_view->set_model_column(GUI::FileSystemModel::Column::Name);
diff --git a/Applications/SystemMonitor/ProcessMemoryMapWidget.cpp b/Applications/SystemMonitor/ProcessMemoryMapWidget.cpp
index 37043909ec..d0412954a5 100644
--- a/Applications/SystemMonitor/ProcessMemoryMapWidget.cpp
+++ b/Applications/SystemMonitor/ProcessMemoryMapWidget.cpp
@@ -120,7 +120,7 @@ ProcessMemoryMapWidget::ProcessMemoryMapWidget()
m_table_view->set_cell_painting_delegate(7, make<PagemapPaintingDelegate>());
- m_table_view->model()->set_key_column_and_sort_order(0, GUI::SortOrder::Ascending);
+ m_table_view->set_key_column_and_sort_order(0, GUI::SortOrder::Ascending);
m_timer = add<Core::Timer>(1000, [this] { refresh(); });
}
diff --git a/Applications/SystemMonitor/main.cpp b/Applications/SystemMonitor/main.cpp
index 916daf7c72..9f35c8f835 100644
--- a/Applications/SystemMonitor/main.cpp
+++ b/Applications/SystemMonitor/main.cpp
@@ -179,7 +179,7 @@ int main(int argc, char** argv)
auto& process_table_view = process_table_container.add<GUI::TableView>();
process_table_view.set_headers_visible(true);
process_table_view.set_model(GUI::SortingProxyModel::create(ProcessModel::create()));
- process_table_view.model()->set_key_column_and_sort_order(ProcessModel::Column::CPU, GUI::SortOrder::Descending);
+ process_table_view.set_key_column_and_sort_order(ProcessModel::Column::CPU, GUI::SortOrder::Descending);
process_table_view.model()->update();
auto& refresh_timer = window->add<Core::Timer>(
diff --git a/Libraries/LibGUI/AbstractTableView.cpp b/Libraries/LibGUI/AbstractTableView.cpp
index e254510c60..40d6cac65c 100644
--- a/Libraries/LibGUI/AbstractTableView.cpp
+++ b/Libraries/LibGUI/AbstractTableView.cpp
@@ -65,13 +65,12 @@ void AbstractTableView::update_column_sizes()
auto& model = *this->model();
int column_count = model.column_count();
int row_count = model.row_count();
- int key_column = model.key_column();
for (int column = 0; column < column_count; ++column) {
if (is_column_hidden(column))
continue;
int header_width = header_font().width(model.column_name(column));
- if (column == key_column && model.is_column_sortable(column))
+ if (column == m_key_column && model.is_column_sortable(column))
header_width += font().width(" \xE2\xAC\x86"); // UPWARDS BLACK ARROW
int column_width = header_width;
for (int row = 0; row < row_count; ++row) {
@@ -146,7 +145,7 @@ void AbstractTableView::paint_headers(Painter& painter)
if (is_column_hidden(column_index))
continue;
int column_width = this->column_width(column_index);
- bool is_key_column = model()->key_column() == column_index;
+ bool is_key_column = m_key_column == column_index;
Gfx::IntRect cell_rect(x_offset, 0, column_width + horizontal_padding() * 2, header_height());
bool pressed = column_index == m_pressed_column_header_index && m_pressed_column_header_is_pressed;
bool hovered = column_index == m_hovered_column_header_index && model()->is_column_sortable(column_index);
@@ -155,10 +154,9 @@ void AbstractTableView::paint_headers(Painter& painter)
if (is_key_column) {
StringBuilder builder;
builder.append(model()->column_name(column_index));
- auto sort_order = model()->sort_order();
- if (sort_order == SortOrder::Ascending)
+ if (m_sort_order == SortOrder::Ascending)
builder.append(" \xE2\xAC\x86"); // UPWARDS BLACK ARROW
- else if (sort_order == SortOrder::Descending)
+ else if (m_sort_order == SortOrder::Descending)
builder.append(" \xE2\xAC\x87"); // DOWNWARDS BLACK ARROW
text = builder.to_string();
} else {
@@ -327,11 +325,11 @@ void AbstractTableView::mouseup_event(MouseEvent& event)
auto header_rect = this->header_rect(m_pressed_column_header_index);
if (header_rect.contains(horizontally_adjusted_position)) {
auto new_sort_order = SortOrder::Ascending;
- if (model()->key_column() == m_pressed_column_header_index)
- new_sort_order = model()->sort_order() == SortOrder::Ascending
+ if (m_key_column == m_pressed_column_header_index)
+ new_sort_order = m_sort_order == SortOrder::Ascending
? SortOrder::Descending
: SortOrder::Ascending;
- model()->set_key_column_and_sort_order(m_pressed_column_header_index, new_sort_order);
+ set_key_column_and_sort_order(m_pressed_column_header_index, new_sort_order);
}
m_pressed_column_header_index = -1;
m_pressed_column_header_is_pressed = false;
diff --git a/Libraries/LibGUI/AbstractView.cpp b/Libraries/LibGUI/AbstractView.cpp
index 6635f2d0ea..1fcb9293ae 100644
--- a/Libraries/LibGUI/AbstractView.cpp
+++ b/Libraries/LibGUI/AbstractView.cpp
@@ -37,7 +37,8 @@
namespace GUI {
AbstractView::AbstractView()
- : m_selection(*this)
+ : m_sort_order(SortOrder::Ascending)
+ , m_selection(*this)
{
}
@@ -400,4 +401,13 @@ void AbstractView::set_multi_select(bool multi_select)
}
}
+void AbstractView::set_key_column_and_sort_order(int column, SortOrder sort_order)
+{
+ m_key_column = column;
+ m_sort_order = sort_order;
+
+ if (model())
+ model()->sort(column, sort_order);
+}
+
}
diff --git a/Libraries/LibGUI/AbstractView.h b/Libraries/LibGUI/AbstractView.h
index 7910871952..996e843a80 100644
--- a/Libraries/LibGUI/AbstractView.h
+++ b/Libraries/LibGUI/AbstractView.h
@@ -76,6 +76,8 @@ public:
void set_last_valid_hovered_index(const ModelIndex&);
+ void set_key_column_and_sort_order(int column, SortOrder);
+
protected:
AbstractView();
virtual ~AbstractView() override;
@@ -111,6 +113,9 @@ protected:
ModelIndex m_hovered_index;
ModelIndex m_last_valid_hovered_index;
+ int m_key_column { 0 };
+ SortOrder m_sort_order;
+
private:
RefPtr<Model> m_model;
OwnPtr<ModelEditingDelegate> m_editing_delegate;
diff --git a/Libraries/LibGUI/FilePicker.cpp b/Libraries/LibGUI/FilePicker.cpp
index 74238a8603..e144f19fd3 100644
--- a/Libraries/LibGUI/FilePicker.cpp
+++ b/Libraries/LibGUI/FilePicker.cpp
@@ -127,7 +127,7 @@ FilePicker::FilePicker(Window* parent_window, Mode mode, Options options, const
m_view->set_multi_select(m_mode == Mode::OpenMultiple);
m_view->set_model(SortingProxyModel::create(*m_model));
m_view->set_model_column(FileSystemModel::Column::Name);
- m_view->model()->set_key_column_and_sort_order(GUI::FileSystemModel::Column::Name, GUI::SortOrder::Ascending);
+ m_view->set_key_column_and_sort_order(GUI::FileSystemModel::Column::Name, GUI::SortOrder::Ascending);
m_view->set_column_hidden(FileSystemModel::Column::Owner, true);
m_view->set_column_hidden(FileSystemModel::Column::Group, true);
m_view->set_column_hidden(FileSystemModel::Column::Permissions, true);
diff --git a/Libraries/LibGUI/Forward.h b/Libraries/LibGUI/Forward.h
index ac597af912..209760d0e1 100644
--- a/Libraries/LibGUI/Forward.h
+++ b/Libraries/LibGUI/Forward.h
@@ -92,4 +92,6 @@ class Widget;
class Window;
class WindowServerConnection;
+enum class SortOrder;
+
}
diff --git a/Libraries/LibGUI/Model.h b/Libraries/LibGUI/Model.h
index e322402a74..b6c57437fc 100644
--- a/Libraries/LibGUI/Model.h
+++ b/Libraries/LibGUI/Model.h
@@ -87,6 +87,7 @@ public:
virtual bool accepts_drag(const ModelIndex&, const StringView& data_type);
virtual bool is_column_sortable([[maybe_unused]] int column_index) const { return true; }
+ virtual void sort([[maybe_unused]] int column, SortOrder) { }
bool is_valid(const ModelIndex& index) const
{
@@ -94,10 +95,6 @@ public:
return index.row() >= 0 && index.row() < row_count(parent_index) && index.column() >= 0 && index.column() < column_count(parent_index);
}
- virtual int key_column() const { return -1; }
- virtual SortOrder sort_order() const { return SortOrder::None; }
- virtual void set_key_column_and_sort_order(int, SortOrder) { }
-
virtual StringView drag_data_type() const { return {}; }
void register_view(Badge<AbstractView>, AbstractView&);
diff --git a/Libraries/LibGUI/MultiView.cpp b/Libraries/LibGUI/MultiView.cpp
index 619c8cd1a7..78360cdeac 100644
--- a/Libraries/LibGUI/MultiView.cpp
+++ b/Libraries/LibGUI/MultiView.cpp
@@ -212,4 +212,11 @@ void MultiView::set_multi_select(bool multi_select)
apply_multi_select();
}
+void MultiView::set_key_column_and_sort_order(int column, SortOrder sort_order)
+{
+ for_each_view_implementation([&](auto& view) {
+ view.set_key_column_and_sort_order(column, sort_order);
+ });
+}
+
}
diff --git a/Libraries/LibGUI/MultiView.h b/Libraries/LibGUI/MultiView.h
index d7dbe6ea49..5d9e9d4b8b 100644
--- a/Libraries/LibGUI/MultiView.h
+++ b/Libraries/LibGUI/MultiView.h
@@ -63,6 +63,8 @@ public:
void set_column_hidden(int column_index, bool hidden);
+ void set_key_column_and_sort_order(int column, SortOrder);
+
GUI::AbstractView& current_view()
{
switch (m_view_mode) {
diff --git a/Libraries/LibGUI/ProcessChooser.cpp b/Libraries/LibGUI/ProcessChooser.cpp
index 3d2ab697c3..8cca04732d 100644
--- a/Libraries/LibGUI/ProcessChooser.cpp
+++ b/Libraries/LibGUI/ProcessChooser.cpp
@@ -58,7 +58,7 @@ ProcessChooser::ProcessChooser(const StringView& window_title, const StringView&
m_table_view = widget.add<GUI::TableView>();
auto sorting_model = GUI::SortingProxyModel::create(RunningProcessesModel::create());
sorting_model->set_sort_role(GUI::Model::Role::Display);
- sorting_model->set_key_column_and_sort_order(RunningProcessesModel::Column::PID, GUI::SortOrder::Descending);
+ m_table_view->set_key_column_and_sort_order(RunningProcessesModel::Column::PID, GUI::SortOrder::Descending);
m_table_view->set_model(sorting_model);
m_table_view->on_activation = [this](const ModelIndex& index) { set_pid_from_index_and_close(index); };
diff --git a/Libraries/LibGUI/SortingProxyModel.cpp b/Libraries/LibGUI/SortingProxyModel.cpp
index e2144f8bfd..c2dad94168 100644
--- a/Libraries/LibGUI/SortingProxyModel.cpp
+++ b/Libraries/LibGUI/SortingProxyModel.cpp
@@ -32,7 +32,6 @@ namespace GUI {
SortingProxyModel::SortingProxyModel(NonnullRefPtr<Model> source)
: m_source(move(source))
- , m_key_column(-1)
{
m_source->register_client(*this);
invalidate();
@@ -126,17 +125,6 @@ StringView SortingProxyModel::drag_data_type() const
return source().drag_data_type();
}
-void SortingProxyModel::set_key_column_and_sort_order(int column, SortOrder 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;
- invalidate();
-}
-
bool SortingProxyModel::less_than(const ModelIndex& index1, const ModelIndex& index2) const
{
auto data1 = index1.model() ? index1.model()->data(index1, m_sort_role) : Variant();
@@ -177,6 +165,43 @@ ModelIndex SortingProxyModel::parent_index(const ModelIndex& proxy_index) const
return map_to_proxy(it->value->source_parent);
}
+void SortingProxyModel::sort_mapping(Mapping& mapping, int column, SortOrder sort_order)
+{
+ if (column == -1) {
+ int row_count = source().row_count(mapping.source_parent);
+ for (int i = 0; i < row_count; ++i) {
+ mapping.source_rows[i] = i;
+ mapping.proxy_rows[i] = i;
+ }
+ return;
+ }
+
+ int row_count = source().row_count(mapping.source_parent);
+ for (int i = 0; i < row_count; ++i)
+ mapping.source_rows[i] = i;
+
+ quick_sort(mapping.source_rows, [&](auto row1, auto row2) -> bool {
+ bool is_less_than = less_than(source().index(row1, column, mapping.source_parent), source().index(row2, column, mapping.source_parent));
+ return sort_order == SortOrder::Ascending ? is_less_than : !is_less_than;
+ });
+
+ for (int i = 0; i < row_count; ++i)
+ mapping.proxy_rows[mapping.source_rows[i]] = i;
+}
+
+void SortingProxyModel::sort(int column, SortOrder sort_order)
+{
+ for (auto& it : m_mappings) {
+ auto& mapping = *it.value;
+ sort_mapping(mapping, column, sort_order);
+ }
+
+ m_last_key_column = column;
+ m_last_sort_order = sort_order;
+
+ did_update();
+}
+
SortingProxyModel::InternalMapIterator SortingProxyModel::build_mapping(const ModelIndex& source_parent)
{
auto it = m_mappings.find(source_parent);
@@ -191,24 +216,7 @@ SortingProxyModel::InternalMapIterator SortingProxyModel::build_mapping(const Mo
mapping->source_rows.resize(row_count);
mapping->proxy_rows.resize(row_count);
- for (int i = 0; i < row_count; ++i) {
- mapping->source_rows[i] = i;
- }
-
- // If we don't have a key column, we're not sorting.
- if (m_key_column == -1) {
- m_mappings.set(source_parent, move(mapping));
- return m_mappings.find(source_parent);
- }
-
- quick_sort(mapping->source_rows, [&](auto row1, auto row2) -> bool {
- bool is_less_than = less_than(source().index(row1, m_key_column, source_parent), source().index(row2, m_key_column, source_parent));
- return m_sort_order == SortOrder::Ascending ? is_less_than : !is_less_than;
- });
-
- for (int i = 0; i < row_count; ++i) {
- mapping->proxy_rows[mapping->source_rows[i]] = i;
- }
+ sort_mapping(*mapping, m_last_key_column, m_last_sort_order);
if (source_parent.is_valid()) {
auto source_grand_parent = source_parent.parent();
diff --git a/Libraries/LibGUI/SortingProxyModel.h b/Libraries/LibGUI/SortingProxyModel.h
index 1f50d4f039..04b452210d 100644
--- a/Libraries/LibGUI/SortingProxyModel.h
+++ b/Libraries/LibGUI/SortingProxyModel.h
@@ -46,9 +46,6 @@ public:
virtual ModelIndex parent_index(const ModelIndex&) const override;
virtual ModelIndex index(int row, int column, const ModelIndex& parent) const override;
- virtual int key_column() const override { return m_key_column; }
- virtual SortOrder sort_order() const override { return m_sort_order; }
- virtual void set_key_column_and_sort_order(int, SortOrder) override;
virtual bool is_column_sortable(int column_index) const override;
virtual bool less_than(const ModelIndex&, const ModelIndex&) const;
@@ -59,6 +56,8 @@ public:
Role sort_role() const { return m_sort_role; }
void set_sort_role(Role role) { m_sort_role = role; }
+ virtual void sort(int column, SortOrder) override;
+
private:
explicit SortingProxyModel(NonnullRefPtr<Model> source);
@@ -71,6 +70,8 @@ private:
using InternalMapIterator = HashMap<ModelIndex, NonnullOwnPtr<Mapping>>::IteratorType;
+ void sort_mapping(Mapping&, int column, SortOrder);
+
// ^ModelClient
virtual void model_did_update(unsigned) override;
@@ -83,9 +84,9 @@ private:
NonnullRefPtr<Model> m_source;
HashMap<ModelIndex, NonnullOwnPtr<Mapping>> m_mappings;
- int m_key_column { -1 };
- SortOrder m_sort_order { SortOrder::Ascending };
Role m_sort_role { Role::Sort };
+ int m_last_key_column { -1 };
+ SortOrder m_last_sort_order { SortOrder::Ascending };
};
}
diff --git a/Libraries/LibGUI/TableView.cpp b/Libraries/LibGUI/TableView.cpp
index eb585466d0..8387abb99f 100644
--- a/Libraries/LibGUI/TableView.cpp
+++ b/Libraries/LibGUI/TableView.cpp
@@ -103,7 +103,7 @@ void TableView::paint_event(PaintEvent& event)
if (is_column_hidden(column_index))
continue;
int column_width = this->column_width(column_index);
- bool is_key_column = model()->key_column() == column_index;
+ bool is_key_column = m_key_column == column_index;
Gfx::IntRect cell_rect(horizontal_padding() + x_offset, y, column_width, item_height());
auto cell_rect_for_fill = cell_rect.inflated(horizontal_padding() * 2, 0);
if (is_key_column)