Compare commits
6 Commits
3597fcf0b0
...
caffa1c18a
| Author | SHA1 | Date | |
|---|---|---|---|
| caffa1c18a | |||
| c15e5425a7 | |||
| e06170dd59 | |||
| 738e1bdee1 | |||
| d78fc734c1 | |||
| a6512f2c67 |
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
set(TARGET_APP "GenericCore")
|
set(TARGET_APP "GenericCore")
|
||||||
project(${TARGET_APP} VERSION 0.1.0 LANGUAGES CXX)
|
project(${TARGET_APP} VERSION 0.2.0 LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
@ -33,6 +33,7 @@ add_library(${TARGET_APP} STATIC
|
|||||||
formats/csvparser.h formats/csvparser.cpp
|
formats/csvparser.h formats/csvparser.cpp
|
||||||
# 3rd party libraries
|
# 3rd party libraries
|
||||||
../3rdParty/rapidcsv/src/rapidcsv.h
|
../3rdParty/rapidcsv/src/rapidcsv.h
|
||||||
|
model/generalsortfiltermodel.h model/generalsortfiltermodel.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "CoreConfig.h"
|
#include "CoreConfig.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "data/filehandler.h"
|
#include "data/filehandler.h"
|
||||||
|
#include "model/generalsortfiltermodel.h"
|
||||||
#include "model/metadata.h"
|
#include "model/metadata.h"
|
||||||
#include "model/tablemodel.h"
|
#include "model/tablemodel.h"
|
||||||
|
|
||||||
@ -89,6 +90,10 @@ QUndoStack* GenericCore::getModelUndoStack() const { return m_modelUndoStack; }
|
|||||||
|
|
||||||
std::shared_ptr<TableModel> GenericCore::getModel() const { return m_mainModel; }
|
std::shared_ptr<TableModel> GenericCore::getModel() const { return m_mainModel; }
|
||||||
|
|
||||||
|
std::shared_ptr<GeneralSortFilterModel> GenericCore::getSortFilterModel() const {
|
||||||
|
return m_sortFilterModel;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save items to default file (in standard location).
|
* Save items to default file (in standard location).
|
||||||
* @brief GenericCore::saveItems Saves item fo file.
|
* @brief GenericCore::saveItems Saves item fo file.
|
||||||
@ -128,6 +133,8 @@ bool GenericCore::exportCSVFile(const QString& filePath) {
|
|||||||
|
|
||||||
void GenericCore::setupModels() {
|
void GenericCore::setupModels() {
|
||||||
m_mainModel = make_shared<TableModel>(m_modelUndoStack, this);
|
m_mainModel = make_shared<TableModel>(m_modelUndoStack, this);
|
||||||
|
m_sortFilterModel = make_shared<GeneralSortFilterModel>(m_mainModel);
|
||||||
|
|
||||||
// TODO add QAbstractItemModelTester
|
// TODO add QAbstractItemModelTester
|
||||||
initModelData();
|
initModelData();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ class QAbstractItemModel;
|
|||||||
class QString;
|
class QString;
|
||||||
|
|
||||||
class TableModel;
|
class TableModel;
|
||||||
|
class GeneralSortFilterModel;
|
||||||
|
|
||||||
class GenericCore : public QObject {
|
class GenericCore : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -24,6 +25,7 @@ class GenericCore : public QObject {
|
|||||||
|
|
||||||
QUndoStack* getModelUndoStack() const;
|
QUndoStack* getModelUndoStack() const;
|
||||||
std::shared_ptr<TableModel> getModel() const;
|
std::shared_ptr<TableModel> getModel() const;
|
||||||
|
std::shared_ptr<GeneralSortFilterModel> getSortFilterModel() const;
|
||||||
|
|
||||||
void saveItems();
|
void saveItems();
|
||||||
void importCSVFile(const QString& filePath);
|
void importCSVFile(const QString& filePath);
|
||||||
@ -35,6 +37,7 @@ class GenericCore : public QObject {
|
|||||||
private:
|
private:
|
||||||
QUndoStack* m_modelUndoStack;
|
QUndoStack* m_modelUndoStack;
|
||||||
std::shared_ptr<TableModel> m_mainModel;
|
std::shared_ptr<TableModel> m_mainModel;
|
||||||
|
std::shared_ptr<GeneralSortFilterModel> m_sortFilterModel;
|
||||||
|
|
||||||
void setupModels();
|
void setupModels();
|
||||||
void initModelData();
|
void initModelData();
|
||||||
|
|||||||
96
model/generalsortfiltermodel.cpp
Normal file
96
model/generalsortfiltermodel.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include "generalsortfiltermodel.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
#include <QItemSelection>
|
||||||
|
|
||||||
|
GeneralSortFilterModel::GeneralSortFilterModel(std::shared_ptr<TableModel> sourceModel)
|
||||||
|
: QSortFilterProxyModel{sourceModel.get()}
|
||||||
|
, m_tableModel(sourceModel) {
|
||||||
|
setSourceModel(sourceModel.get());
|
||||||
|
|
||||||
|
m_collator.setNumericMode(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QItemSelection GeneralSortFilterModel::findItems(const QString& text) const {
|
||||||
|
QItemSelection result;
|
||||||
|
|
||||||
|
for (int i = 0; i < rowCount(); ++i) {
|
||||||
|
const QModelIndex localIndex = index(i, 0);
|
||||||
|
if (indexContainsText(localIndex, text)) {
|
||||||
|
result.select(localIndex, index(i, columnCount() - 1)); /// select entire row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralSortFilterModel::appendItems(const QByteArray& jsonDoc) {
|
||||||
|
m_tableModel->appendItems(jsonDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeneralSortFilterModel::removeRows(int firstRow, int nRows, const QModelIndex& parentIndex) {
|
||||||
|
const QModelIndex proxyIndex = index(firstRow, 0, parentIndex);
|
||||||
|
const QModelIndex sourceIndex = mapToSource(proxyIndex);
|
||||||
|
return m_tableModel->removeRows(sourceIndex.row(), nRows, sourceIndex.parent());
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeneralSortFilterModel::indexContainsText(const QModelIndex& index,
|
||||||
|
const QString& text) const {
|
||||||
|
// iterate over USER_FACING_ROLES and call roleDataContainsText(...);
|
||||||
|
// ...for each until text is found or no more roles to check;
|
||||||
|
QListIterator<UserRoles> i(USER_FACING_ROLES);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
const UserRoles role = i.next();
|
||||||
|
const bool isTextFound = roleDataContainsText(index, role, text);
|
||||||
|
if (isTextFound) {
|
||||||
|
// qInfo() << "Text is found in role:" << role;
|
||||||
|
return true;
|
||||||
|
// } else {
|
||||||
|
// qDebug() << QString("Can't find text in role %1. Continuing search...").arg(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// qWarning() << "Text not found in any role. Returning false...";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeneralSortFilterModel::roleDataContainsText(const QModelIndex& index,
|
||||||
|
const int role,
|
||||||
|
const QString& text) const {
|
||||||
|
const QString dataString = index.data(role).toString();
|
||||||
|
if (dataString.contains(text, Qt::CaseInsensitive)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
model/generalsortfiltermodel.h
Normal file
36
model/generalsortfiltermodel.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef GENERALSORTFILTERMODEL_H
|
||||||
|
#define GENERALSORTFILTERMODEL_H
|
||||||
|
|
||||||
|
#include <QCollator>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include "tablemodel.h"
|
||||||
|
|
||||||
|
class GeneralSortFilterModel : public QSortFilterProxyModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GeneralSortFilterModel(std::shared_ptr<TableModel> sourceModel = nullptr);
|
||||||
|
|
||||||
|
/** Returns a QItemSelection with all ModelIndexes which contain the given text.
|
||||||
|
* @brief Returns QItemSelection containing all successful ModelIndex results
|
||||||
|
* @param text To search for
|
||||||
|
* @return QItemSelection containing all successful ModelIndex results
|
||||||
|
*/
|
||||||
|
QItemSelection findItems(const QString& text) const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void appendItems(const QByteArray& jsonDoc);
|
||||||
|
bool removeRows(int firstRow, int nRows, const QModelIndex& parentIndex = QModelIndex()) override;
|
||||||
|
/// QSortFilterProxyModel interface
|
||||||
|
protected:
|
||||||
|
bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<TableModel> m_tableModel;
|
||||||
|
QCollator m_collator; /// for sorting
|
||||||
|
|
||||||
|
bool indexContainsText(const QModelIndex& index, const QString& text) const;
|
||||||
|
bool roleDataContainsText(const QModelIndex& index, const int role, const QString& text) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GENERALSORTFILTERMODEL_H
|
||||||
@ -7,7 +7,15 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
/// model data
|
/// model data
|
||||||
enum UserRoles { NameRole = Qt::UserRole + 1, DescriptionRole, InfoRole, AmountRole, FactorRole };
|
enum UserRoles {
|
||||||
|
NameRole = Qt::UserRole + 1,
|
||||||
|
DescriptionRole,
|
||||||
|
InfoRole,
|
||||||
|
AmountRole,
|
||||||
|
FactorRole,
|
||||||
|
/// helper roles
|
||||||
|
ToStringRole
|
||||||
|
};
|
||||||
static UserRoles DEFAULT_ROLE = NameRole;
|
static UserRoles DEFAULT_ROLE = NameRole;
|
||||||
static QList<UserRoles> USER_FACING_ROLES = {NameRole, DescriptionRole, InfoRole, AmountRole,
|
static QList<UserRoles> USER_FACING_ROLES = {NameRole, DescriptionRole, InfoRole, AmountRole,
|
||||||
FactorRole};
|
FactorRole};
|
||||||
|
|||||||
@ -44,6 +44,20 @@ bool ModelItem::setItemData(const QMap<int, QVariant>& changedValues) {
|
|||||||
return valueChanged;
|
return valueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ModelItem::toString() const {
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
QListIterator<UserRoles> i(USER_FACING_ROLES);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
const UserRoles role = i.next();
|
||||||
|
const QString roleName = ROLE_NAMES.value(role);
|
||||||
|
const QVariant value = data(role);
|
||||||
|
// result.append(value.toString());
|
||||||
|
result.append(QString("%1: %2\n").arg(roleName, data(role).toString()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject ModelItem::toJsonObject() const {
|
QJsonObject ModelItem::toJsonObject() const {
|
||||||
QJsonObject itemObject;
|
QJsonObject itemObject;
|
||||||
// TODO add UUID and dates (entry, modification, end)
|
// TODO add UUID and dates (entry, modification, end)
|
||||||
|
|||||||
@ -14,7 +14,7 @@ class ModelItem {
|
|||||||
// TODO change return value to list of changed roles
|
// TODO change return value to list of changed roles
|
||||||
bool setItemData(const QMap<int, QVariant>& changedValues);
|
bool setItemData(const QMap<int, QVariant>& changedValues);
|
||||||
|
|
||||||
// QString toString() const;
|
QString toString() const;
|
||||||
QJsonObject toJsonObject() const;
|
QJsonObject toJsonObject() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -76,6 +76,8 @@ QVariant TableModel::data(const QModelIndex& index, int role) const {
|
|||||||
case AmountRole:
|
case AmountRole:
|
||||||
case FactorRole:
|
case FactorRole:
|
||||||
return m_items.at(row)->data(role);
|
return m_items.at(row)->data(role);
|
||||||
|
case ToStringRole:
|
||||||
|
return m_items.at(row)->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|||||||
Reference in New Issue
Block a user