#ifndef MODEL_MANAGER_H #define MODEL_MANAGER_H #include #include #include #include // The model manager inherits the QObject class to delete child objects class ModelManager : public QObject { Q_OBJECT private: QMap 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 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 bool registerModel(const QString &modelTableName, const QSqlDatabase &db); // Initialize all models void initialize(); // Initialize a specific model template 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 void ModelManager::initializeIfExists(T *model) { if constexpr (std::is_invocable_v) { model->initialize(); } else { qDebug() << "Method initialize() is not available, skipping..."; } } template T *ModelManager::getModelAs(const QString &modelTableName) const { auto *model = dynamic_cast(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 bool ModelManager::registerModel(const QString &modelTableName, const QSqlDatabase &db) { static_assert(std::is_base_of_v, "Registered model must be derived from QSqlTableModel"); static_assert( std::is_constructible::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