diff options
-rw-r--r-- | Applications/FileManager/DirectoryView.cpp | 2 | ||||
-rw-r--r-- | Applications/SystemMonitor/ProcessMemoryMapWidget.cpp | 2 | ||||
-rw-r--r-- | Applications/SystemMonitor/main.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractTableView.cpp | 16 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractView.cpp | 12 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractView.h | 5 | ||||
-rw-r--r-- | Libraries/LibGUI/FilePicker.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/Forward.h | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/Model.h | 5 | ||||
-rw-r--r-- | Libraries/LibGUI/MultiView.cpp | 7 | ||||
-rw-r--r-- | Libraries/LibGUI/MultiView.h | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/ProcessChooser.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/SortingProxyModel.cpp | 68 | ||||
-rw-r--r-- | Libraries/LibGUI/SortingProxyModel.h | 11 | ||||
-rw-r--r-- | Libraries/LibGUI/TableView.cpp | 2 |
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) |