114 lines
3.1 KiB
C++
114 lines
3.1 KiB
C++
#ifndef MODEL_MANAGER_H
|
|
#define MODEL_MANAGER_H
|
|
|
|
#include <QMap>
|
|
#include <QSqlDatabase>
|
|
#include <QSqlTableModel>
|
|
#include <QString>
|
|
|
|
// The model manager inherits the QObject class to delete child objects
|
|
class ModelManager : public QObject {
|
|
Q_OBJECT
|
|
|
|
private:
|
|
QMap<QString, QSqlTableModel *> models_;
|
|
QSqlDatabase database_;
|
|
|
|
public:
|
|
// Get the singleton instance
|
|
static ModelManager &instance();
|
|
|
|
QStringList registeredModelTableNames() const;
|
|
|
|
QStringList registeredModelTableNames(QString databaseTableName) const;
|
|
|
|
// Get a model
|
|
QSqlTableModel *getModel(const QString &modelTableName) const;
|
|
|
|
// Get a model with a specific type
|
|
template <typename T> T *getModelAs(const QString &modelTableName) const;
|
|
|
|
// Configure filters
|
|
void resetFilter(const QString &modelTableName);
|
|
|
|
void setMultiColumnFilter(const QString &modelTableName,
|
|
const QString &filter);
|
|
|
|
private:
|
|
// Register a model
|
|
template <typename T>
|
|
bool registerModel(const QString &modelTableName, const QSqlDatabase &db);
|
|
|
|
// Initialize all models
|
|
void initialize();
|
|
|
|
// Initialize a specific model
|
|
template <typename T> void initializeIfExists(T *model);
|
|
|
|
// Private constructor for singleton pattern
|
|
ModelManager();
|
|
|
|
// Private destructor
|
|
~ModelManager();
|
|
|
|
// Disable copy constructor and assignment operator
|
|
ModelManager(const ModelManager &) = delete;
|
|
ModelManager &operator=(const ModelManager &) = delete;
|
|
};
|
|
|
|
// NOTE: Implementation of template methods
|
|
|
|
template <typename T> void ModelManager::initializeIfExists(T *model) {
|
|
if constexpr (std::is_invocable_v<decltype(&T::initialize), T *>) {
|
|
model->initialize();
|
|
} else {
|
|
qDebug() << "Method initialize() is not available, skipping...";
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
T *ModelManager::getModelAs(const QString &modelTableName) const {
|
|
auto *model = dynamic_cast<T *>(getModel(modelTableName));
|
|
if (!model) {
|
|
qFatal() << "Failed to downcast model for" << modelTableName
|
|
<< "(typeid name):" << typeid(T).name();
|
|
return nullptr;
|
|
}
|
|
qInfo() << "Successfully downcast model for" << modelTableName;
|
|
|
|
return model;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ModelManager::registerModel(const QString &modelTableName,
|
|
const QSqlDatabase &db) {
|
|
static_assert(std::is_base_of_v<QSqlTableModel, T>,
|
|
"Registered model must be derived from QSqlTableModel");
|
|
|
|
static_assert(
|
|
std::is_constructible<T, QObject *, const QSqlDatabase &>::value,
|
|
"Model class must have a constructor accepting QObject* and const "
|
|
"QSqlDatabase&");
|
|
|
|
qInfo() << "Registering model:" << modelTableName;
|
|
|
|
if (models_.contains(modelTableName)) {
|
|
qInfo() << "Model" << modelTableName << "is already registered";
|
|
return true;
|
|
}
|
|
|
|
T *model = new T(this, db); // Qt will delete the model
|
|
model->setObjectName(modelTableName);
|
|
initializeIfExists(model);
|
|
|
|
models_.insert(modelTableName, model);
|
|
|
|
qInfo() << "Model" << modelTableName
|
|
<< "with database table name:" << model->tableName()
|
|
<< "was registered successfully";
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif // MODEL_MANAGER_H
|