diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-07-04 16:16:50 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-07-04 16:16:50 +0200 |
commit | 04b9dc2d30cfc9b383029f6a4b02e2725108b0ae (patch) | |
tree | e117a998173b767f9fd009d49c4f8573d8b85432 /Libraries/LibGUI/GSortingProxyModel.cpp | |
parent | 63814ffebf16291419745cd8ba29a4d2fd888563 (diff) | |
download | serenity-04b9dc2d30cfc9b383029f6a4b02e2725108b0ae.zip |
Libraries: Create top level directory for libraries.
Things were getting a little crowded in the project root, so this patch
moves the Lib*/ directories into Libraries/.
Diffstat (limited to 'Libraries/LibGUI/GSortingProxyModel.cpp')
-rw-r--r-- | Libraries/LibGUI/GSortingProxyModel.cpp | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/Libraries/LibGUI/GSortingProxyModel.cpp b/Libraries/LibGUI/GSortingProxyModel.cpp new file mode 100644 index 0000000000..5bf379695b --- /dev/null +++ b/Libraries/LibGUI/GSortingProxyModel.cpp @@ -0,0 +1,105 @@ +#include <AK/QuickSort.h> +#include <LibGUI/GSortingProxyModel.h> +#include <stdio.h> +#include <stdlib.h> + +GSortingProxyModel::GSortingProxyModel(NonnullRefPtr<GModel>&& target) + : m_target(move(target)) + , m_key_column(-1) +{ + m_target->on_model_update = [this](GModel&) { + resort(); + }; +} + +GSortingProxyModel::~GSortingProxyModel() +{ +} + +int GSortingProxyModel::row_count(const GModelIndex& index) const +{ + return target().row_count(index); +} + +int GSortingProxyModel::column_count(const GModelIndex& index) const +{ + return target().column_count(index); +} + +GModelIndex GSortingProxyModel::map_to_target(const GModelIndex& index) const +{ + if (!index.is_valid()) + return {}; + if (index.row() >= m_row_mappings.size() || index.column() >= column_count()) + return {}; + return target().index(m_row_mappings[index.row()], index.column()); +} + +String GSortingProxyModel::row_name(int index) const +{ + return target().row_name(index); +} + +String GSortingProxyModel::column_name(int index) const +{ + return target().column_name(index); +} + +GModel::ColumnMetadata GSortingProxyModel::column_metadata(int index) const +{ + return target().column_metadata(index); +} + +GVariant GSortingProxyModel::data(const GModelIndex& index, Role role) const +{ + return target().data(map_to_target(index), role); +} + +void GSortingProxyModel::update() +{ + target().update(); +} + +void GSortingProxyModel::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 GSortingProxyModel::resort() +{ + int previously_selected_target_row = map_to_target(selected_index()).row(); + 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) { + did_update(); + return; + } + quick_sort(m_row_mappings.begin(), m_row_mappings.end(), [&](auto row1, auto row2) -> bool { + auto data1 = target().data(target().index(row1, m_key_column), GModel::Role::Sort); + auto data2 = target().data(target().index(row2, m_key_column), GModel::Role::Sort); + if (data1 == data2) + return 0; + bool is_less_than = data1 < data2; + return m_sort_order == GSortOrder::Ascending ? is_less_than : !is_less_than; + }); + if (previously_selected_target_row != -1) { + // Preserve selection. + ASSERT(m_row_mappings.size() == row_count); + for (int i = 0; i < row_count; ++i) { + if (m_row_mappings[i] == previously_selected_target_row) { + set_selected_index(index(i, 0)); + break; + } + } + } + + did_update(); +} |