mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:02:45 +00:00 
			
		
		
		
	LibGUI: Make model sorting imperative and move order to AbstractView
Instead of SortingProxyModel having a column+order, we move that state to AbstractView. When you click on a column header, the view tells the model to resort the relevant column with the new order. This is implemented in SortingProxyModel by simply walking all the reified source/proxy mappings and resorting their row indexes.
This commit is contained in:
		
							parent
							
								
									370624bc37
								
							
						
					
					
						commit
						e1ed71ef9e
					
				
					 15 changed files with 85 additions and 55 deletions
				
			
		|  | @ -127,7 +127,7 @@ DirectoryView::DirectoryView() | ||||||
|     m_table_view = add<GUI::TableView>(); |     m_table_view = add<GUI::TableView>(); | ||||||
|     m_table_view->set_model(m_sorting_model); |     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_icon_view->set_model_column(GUI::FileSystemModel::Column::Name); | ||||||
|     m_columns_view->set_model_column(GUI::FileSystemModel::Column::Name); |     m_columns_view->set_model_column(GUI::FileSystemModel::Column::Name); | ||||||
|  |  | ||||||
|  | @ -120,7 +120,7 @@ ProcessMemoryMapWidget::ProcessMemoryMapWidget() | ||||||
| 
 | 
 | ||||||
|     m_table_view->set_cell_painting_delegate(7, make<PagemapPaintingDelegate>()); |     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(); }); |     m_timer = add<Core::Timer>(1000, [this] { refresh(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -179,7 +179,7 @@ int main(int argc, char** argv) | ||||||
|     auto& process_table_view = process_table_container.add<GUI::TableView>(); |     auto& process_table_view = process_table_container.add<GUI::TableView>(); | ||||||
|     process_table_view.set_headers_visible(true); |     process_table_view.set_headers_visible(true); | ||||||
|     process_table_view.set_model(GUI::SortingProxyModel::create(ProcessModel::create())); |     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(); |     process_table_view.model()->update(); | ||||||
| 
 | 
 | ||||||
|     auto& refresh_timer = window->add<Core::Timer>( |     auto& refresh_timer = window->add<Core::Timer>( | ||||||
|  |  | ||||||
|  | @ -65,13 +65,12 @@ void AbstractTableView::update_column_sizes() | ||||||
|     auto& model = *this->model(); |     auto& model = *this->model(); | ||||||
|     int column_count = model.column_count(); |     int column_count = model.column_count(); | ||||||
|     int row_count = model.row_count(); |     int row_count = model.row_count(); | ||||||
|     int key_column = model.key_column(); |  | ||||||
| 
 | 
 | ||||||
|     for (int column = 0; column < column_count; ++column) { |     for (int column = 0; column < column_count; ++column) { | ||||||
|         if (is_column_hidden(column)) |         if (is_column_hidden(column)) | ||||||
|             continue; |             continue; | ||||||
|         int header_width = header_font().width(model.column_name(column)); |         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
 |             header_width += font().width(" \xE2\xAC\x86"); // UPWARDS BLACK ARROW
 | ||||||
|         int column_width = header_width; |         int column_width = header_width; | ||||||
|         for (int row = 0; row < row_count; ++row) { |         for (int row = 0; row < row_count; ++row) { | ||||||
|  | @ -146,7 +145,7 @@ void AbstractTableView::paint_headers(Painter& painter) | ||||||
|         if (is_column_hidden(column_index)) |         if (is_column_hidden(column_index)) | ||||||
|             continue; |             continue; | ||||||
|         int column_width = this->column_width(column_index); |         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()); |         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 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); |         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) { |         if (is_key_column) { | ||||||
|             StringBuilder builder; |             StringBuilder builder; | ||||||
|             builder.append(model()->column_name(column_index)); |             builder.append(model()->column_name(column_index)); | ||||||
|             auto sort_order = model()->sort_order(); |             if (m_sort_order == SortOrder::Ascending) | ||||||
|             if (sort_order == SortOrder::Ascending) |  | ||||||
|                 builder.append(" \xE2\xAC\x86"); // UPWARDS BLACK ARROW
 |                 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
 |                 builder.append(" \xE2\xAC\x87"); // DOWNWARDS BLACK ARROW
 | ||||||
|             text = builder.to_string(); |             text = builder.to_string(); | ||||||
|         } else { |         } else { | ||||||
|  | @ -327,11 +325,11 @@ void AbstractTableView::mouseup_event(MouseEvent& event) | ||||||
|             auto header_rect = this->header_rect(m_pressed_column_header_index); |             auto header_rect = this->header_rect(m_pressed_column_header_index); | ||||||
|             if (header_rect.contains(horizontally_adjusted_position)) { |             if (header_rect.contains(horizontally_adjusted_position)) { | ||||||
|                 auto new_sort_order = SortOrder::Ascending; |                 auto new_sort_order = SortOrder::Ascending; | ||||||
|                 if (model()->key_column() == m_pressed_column_header_index) |                 if (m_key_column == m_pressed_column_header_index) | ||||||
|                     new_sort_order = model()->sort_order() == SortOrder::Ascending |                     new_sort_order = m_sort_order == SortOrder::Ascending | ||||||
|                         ? SortOrder::Descending |                         ? SortOrder::Descending | ||||||
|                         : SortOrder::Ascending; |                         : 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_index = -1; | ||||||
|             m_pressed_column_header_is_pressed = false; |             m_pressed_column_header_is_pressed = false; | ||||||
|  |  | ||||||
|  | @ -37,7 +37,8 @@ | ||||||
| namespace GUI { | namespace GUI { | ||||||
| 
 | 
 | ||||||
| AbstractView::AbstractView() | 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); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -76,6 +76,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void set_last_valid_hovered_index(const ModelIndex&); |     void set_last_valid_hovered_index(const ModelIndex&); | ||||||
| 
 | 
 | ||||||
|  |     void set_key_column_and_sort_order(int column, SortOrder); | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
|     AbstractView(); |     AbstractView(); | ||||||
|     virtual ~AbstractView() override; |     virtual ~AbstractView() override; | ||||||
|  | @ -111,6 +113,9 @@ protected: | ||||||
|     ModelIndex m_hovered_index; |     ModelIndex m_hovered_index; | ||||||
|     ModelIndex m_last_valid_hovered_index; |     ModelIndex m_last_valid_hovered_index; | ||||||
| 
 | 
 | ||||||
|  |     int m_key_column { 0 }; | ||||||
|  |     SortOrder m_sort_order; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     RefPtr<Model> m_model; |     RefPtr<Model> m_model; | ||||||
|     OwnPtr<ModelEditingDelegate> m_editing_delegate; |     OwnPtr<ModelEditingDelegate> m_editing_delegate; | ||||||
|  |  | ||||||
|  | @ -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_multi_select(m_mode == Mode::OpenMultiple); | ||||||
|     m_view->set_model(SortingProxyModel::create(*m_model)); |     m_view->set_model(SortingProxyModel::create(*m_model)); | ||||||
|     m_view->set_model_column(FileSystemModel::Column::Name); |     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::Owner, true); | ||||||
|     m_view->set_column_hidden(FileSystemModel::Column::Group, true); |     m_view->set_column_hidden(FileSystemModel::Column::Group, true); | ||||||
|     m_view->set_column_hidden(FileSystemModel::Column::Permissions, true); |     m_view->set_column_hidden(FileSystemModel::Column::Permissions, true); | ||||||
|  |  | ||||||
|  | @ -92,4 +92,6 @@ class Widget; | ||||||
| class Window; | class Window; | ||||||
| class WindowServerConnection; | class WindowServerConnection; | ||||||
| 
 | 
 | ||||||
|  | enum class SortOrder; | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ public: | ||||||
|     virtual bool accepts_drag(const ModelIndex&, const StringView& data_type); |     virtual bool accepts_drag(const ModelIndex&, const StringView& data_type); | ||||||
| 
 | 
 | ||||||
|     virtual bool is_column_sortable([[maybe_unused]] int column_index) const { return true; } |     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 |     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); |         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 {}; } |     virtual StringView drag_data_type() const { return {}; } | ||||||
| 
 | 
 | ||||||
|     void register_view(Badge<AbstractView>, AbstractView&); |     void register_view(Badge<AbstractView>, AbstractView&); | ||||||
|  |  | ||||||
|  | @ -212,4 +212,11 @@ void MultiView::set_multi_select(bool multi_select) | ||||||
|     apply_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); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -63,6 +63,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void set_column_hidden(int column_index, bool hidden); |     void set_column_hidden(int column_index, bool hidden); | ||||||
| 
 | 
 | ||||||
|  |     void set_key_column_and_sort_order(int column, SortOrder); | ||||||
|  | 
 | ||||||
|     GUI::AbstractView& current_view() |     GUI::AbstractView& current_view() | ||||||
|     { |     { | ||||||
|         switch (m_view_mode) { |         switch (m_view_mode) { | ||||||
|  |  | ||||||
|  | @ -58,7 +58,7 @@ ProcessChooser::ProcessChooser(const StringView& window_title, const StringView& | ||||||
|     m_table_view = widget.add<GUI::TableView>(); |     m_table_view = widget.add<GUI::TableView>(); | ||||||
|     auto sorting_model = GUI::SortingProxyModel::create(RunningProcessesModel::create()); |     auto sorting_model = GUI::SortingProxyModel::create(RunningProcessesModel::create()); | ||||||
|     sorting_model->set_sort_role(GUI::Model::Role::Display); |     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->set_model(sorting_model); | ||||||
| 
 | 
 | ||||||
|     m_table_view->on_activation = [this](const ModelIndex& index) { set_pid_from_index_and_close(index); }; |     m_table_view->on_activation = [this](const ModelIndex& index) { set_pid_from_index_and_close(index); }; | ||||||
|  |  | ||||||
|  | @ -32,7 +32,6 @@ namespace GUI { | ||||||
| 
 | 
 | ||||||
| SortingProxyModel::SortingProxyModel(NonnullRefPtr<Model> source) | SortingProxyModel::SortingProxyModel(NonnullRefPtr<Model> source) | ||||||
|     : m_source(move(source)) |     : m_source(move(source)) | ||||||
|     , m_key_column(-1) |  | ||||||
| { | { | ||||||
|     m_source->register_client(*this); |     m_source->register_client(*this); | ||||||
|     invalidate(); |     invalidate(); | ||||||
|  | @ -126,17 +125,6 @@ StringView SortingProxyModel::drag_data_type() const | ||||||
|     return source().drag_data_type(); |     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 | bool SortingProxyModel::less_than(const ModelIndex& index1, const ModelIndex& index2) const | ||||||
| { | { | ||||||
|     auto data1 = index1.model() ? index1.model()->data(index1, m_sort_role) : Variant(); |     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); |     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) | SortingProxyModel::InternalMapIterator SortingProxyModel::build_mapping(const ModelIndex& source_parent) | ||||||
| { | { | ||||||
|     auto it = m_mappings.find(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->source_rows.resize(row_count); | ||||||
|     mapping->proxy_rows.resize(row_count); |     mapping->proxy_rows.resize(row_count); | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < row_count; ++i) { |     sort_mapping(*mapping, m_last_key_column, m_last_sort_order); | ||||||
|         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; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (source_parent.is_valid()) { |     if (source_parent.is_valid()) { | ||||||
|         auto source_grand_parent = source_parent.parent(); |         auto source_grand_parent = source_parent.parent(); | ||||||
|  |  | ||||||
|  | @ -46,9 +46,6 @@ public: | ||||||
|     virtual ModelIndex parent_index(const ModelIndex&) const override; |     virtual ModelIndex parent_index(const ModelIndex&) const override; | ||||||
|     virtual ModelIndex index(int row, int column, const ModelIndex& parent) 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 is_column_sortable(int column_index) const override; | ||||||
| 
 | 
 | ||||||
|     virtual bool less_than(const ModelIndex&, const ModelIndex&) const; |     virtual bool less_than(const ModelIndex&, const ModelIndex&) const; | ||||||
|  | @ -59,6 +56,8 @@ public: | ||||||
|     Role sort_role() const { return m_sort_role; } |     Role sort_role() const { return m_sort_role; } | ||||||
|     void set_sort_role(Role role) { m_sort_role = role; } |     void set_sort_role(Role role) { m_sort_role = role; } | ||||||
| 
 | 
 | ||||||
|  |     virtual void sort(int column, SortOrder) override; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     explicit SortingProxyModel(NonnullRefPtr<Model> source); |     explicit SortingProxyModel(NonnullRefPtr<Model> source); | ||||||
| 
 | 
 | ||||||
|  | @ -71,6 +70,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     using InternalMapIterator = HashMap<ModelIndex, NonnullOwnPtr<Mapping>>::IteratorType; |     using InternalMapIterator = HashMap<ModelIndex, NonnullOwnPtr<Mapping>>::IteratorType; | ||||||
| 
 | 
 | ||||||
|  |     void sort_mapping(Mapping&, int column, SortOrder); | ||||||
|  | 
 | ||||||
|     // ^ModelClient
 |     // ^ModelClient
 | ||||||
|     virtual void model_did_update(unsigned) override; |     virtual void model_did_update(unsigned) override; | ||||||
| 
 | 
 | ||||||
|  | @ -83,9 +84,9 @@ private: | ||||||
|     NonnullRefPtr<Model> m_source; |     NonnullRefPtr<Model> m_source; | ||||||
| 
 | 
 | ||||||
|     HashMap<ModelIndex, NonnullOwnPtr<Mapping>> m_mappings; |     HashMap<ModelIndex, NonnullOwnPtr<Mapping>> m_mappings; | ||||||
|     int m_key_column { -1 }; |  | ||||||
|     SortOrder m_sort_order { SortOrder::Ascending }; |  | ||||||
|     Role m_sort_role { Role::Sort }; |     Role m_sort_role { Role::Sort }; | ||||||
|  |     int m_last_key_column { -1 }; | ||||||
|  |     SortOrder m_last_sort_order { SortOrder::Ascending }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -103,7 +103,7 @@ void TableView::paint_event(PaintEvent& event) | ||||||
|             if (is_column_hidden(column_index)) |             if (is_column_hidden(column_index)) | ||||||
|                 continue; |                 continue; | ||||||
|             int column_width = this->column_width(column_index); |             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()); |             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); |             auto cell_rect_for_fill = cell_rect.inflated(horizontal_padding() * 2, 0); | ||||||
|             if (is_key_column) |             if (is_key_column) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling