From a6512f2c67e924bf33b92a85a1848c9d3b57564a Mon Sep 17 00:00:00 2001 From: Bent Witthold Date: Mon, 12 Jan 2026 09:56:50 +0100 Subject: [PATCH] Added a QSortFilterProxyModel subclass to enable sorting by different columns in the views. --- CMakeLists.txt | 1 + genericcore.cpp | 9 ++++++- genericcore.h | 3 +++ model/generalsortfiltermodel.cpp | 42 ++++++++++++++++++++++++++++++++ model/generalsortfiltermodel.h | 23 +++++++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 model/generalsortfiltermodel.cpp create mode 100644 model/generalsortfiltermodel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b47cfca..c7a2875 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(${TARGET_APP} STATIC formats/csvparser.h formats/csvparser.cpp # 3rd party libraries ../3rdParty/rapidcsv/src/rapidcsv.h + model/generalsortfiltermodel.h model/generalsortfiltermodel.cpp ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/genericcore.cpp b/genericcore.cpp index 34ef9dd..9a29e04 100644 --- a/genericcore.cpp +++ b/genericcore.cpp @@ -12,6 +12,7 @@ #include "CoreConfig.h" #include "constants.h" #include "data/filehandler.h" +#include "model/generalsortfiltermodel.h" #include "model/metadata.h" #include "model/tablemodel.h" @@ -89,6 +90,10 @@ QUndoStack* GenericCore::getModelUndoStack() const { return m_modelUndoStack; } std::shared_ptr GenericCore::getModel() const { return m_mainModel; } +std::shared_ptr GenericCore::getSortFilterModel() const { + return m_sortFilterModel; +} + /** * Save items to default file (in standard location). * @brief GenericCore::saveItems Saves item fo file. @@ -127,7 +132,9 @@ bool GenericCore::exportCSVFile(const QString& filePath) { } void GenericCore::setupModels() { - m_mainModel = make_shared(m_modelUndoStack, this); + m_mainModel = make_shared(m_modelUndoStack, this); + m_sortFilterModel = make_shared(m_mainModel); + // TODO add QAbstractItemModelTester initModelData(); } diff --git a/genericcore.h b/genericcore.h index b25135c..f4a78b0 100644 --- a/genericcore.h +++ b/genericcore.h @@ -8,6 +8,7 @@ class QAbstractItemModel; class QString; class TableModel; +class GeneralSortFilterModel; class GenericCore : public QObject { Q_OBJECT @@ -24,6 +25,7 @@ class GenericCore : public QObject { QUndoStack* getModelUndoStack() const; std::shared_ptr getModel() const; + std::shared_ptr getSortFilterModel() const; void saveItems(); void importCSVFile(const QString& filePath); @@ -35,6 +37,7 @@ class GenericCore : public QObject { private: QUndoStack* m_modelUndoStack; std::shared_ptr m_mainModel; + std::shared_ptr m_sortFilterModel; void setupModels(); void initModelData(); diff --git a/model/generalsortfiltermodel.cpp b/model/generalsortfiltermodel.cpp new file mode 100644 index 0000000..da593af --- /dev/null +++ b/model/generalsortfiltermodel.cpp @@ -0,0 +1,42 @@ +#include "generalsortfiltermodel.h" +#include "metadata.h" + +GeneralSortFilterModel::GeneralSortFilterModel(std::shared_ptr sourceModel) + : QSortFilterProxyModel{sourceModel.get()} + , m_sourceModel(sourceModel) { + setSourceModel(sourceModel.get()); + + m_collator.setNumericMode(true); +} + +bool GeneralSortFilterModel::lessThan(const QModelIndex& source_left, + const QModelIndex& source_right) const { + if (source_left.column() != source_right.column()) { + return false; + } + + QAbstractItemModel* localSourceModel = sourceModel(); + const int role = GET_ROLE_FOR_COLUMN(source_left.column()); + const QVariant leftData = localSourceModel->data(source_left); + const QVariant rightData = localSourceModel->data(source_right); + + const bool isText = STRING_ROLES.contains(role); + if (isText) { + const QString leftString = leftData.toString(); + const QString rightString = rightData.toString(); + return m_collator.compare(leftString, rightString) > 0; + } + const bool isInt = INT_ROLES.contains(role); + if (isInt) { + const int leftInt = leftData.toInt(); + const int rightInt = rightData.toInt(); + return leftInt > rightInt; + } + const bool isDouble = DOUBLE_ROLES.contains(role); + if (isDouble) { + const int leftInt = leftData.toDouble(); + const int rightInt = rightData.toDouble(); + return leftInt > rightInt; + } + return false; +} diff --git a/model/generalsortfiltermodel.h b/model/generalsortfiltermodel.h new file mode 100644 index 0000000..6084b3e --- /dev/null +++ b/model/generalsortfiltermodel.h @@ -0,0 +1,23 @@ +#ifndef GENERALSORTFILTERMODEL_H +#define GENERALSORTFILTERMODEL_H + +#include +#include + +#include "tablemodel.h" + +class GeneralSortFilterModel : public QSortFilterProxyModel { + Q_OBJECT + public: + explicit GeneralSortFilterModel(std::shared_ptr sourceModel = nullptr); + + /// QSortFilterProxyModel interface + protected: + bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override; + + private: + std::shared_ptr m_sourceModel; + QCollator m_collator; /// for sorting +}; + +#endif // GENERALSORTFILTERMODEL_H