#ifndef CRUDMODEL_H #define CRUDMODEL_H #include #include "ASyncDBConnection.h" #include "PgClass.h" #include "PgConstraint.h" #include "Pgsql_Connection.h" #include #include #include #include class PgConstraint; class OpenDatabase; class ASyncWindow; /** * @brief The CrudModel class * * Features * - order by one or more user selectable columns * - user filter condition * - user limit and offset * - hide columns (will not be retrieved can greatly speed up things when you disable wide columns) * - can use foreign keys to display dropdown * * How to load data? * - 2D array of QVariants won't be efficient * - 2D array of strings * - We do know the type of a single column is fixed * - Keep data in Result and only load data in replacement rows * std::string has short string optimization so this probably means * that a two dimensional array of std::string objects could actually be quite efficient! */ class CrudModel: public QAbstractTableModel { Q_OBJECT public: explicit CrudModel(ASyncWindow *async_win); ~CrudModel(); void setConfig(std::shared_ptr db, const PgClass &table); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; virtual QVariant data(const QModelIndex &index, int role) const override; virtual Qt::ItemFlags flags(const QModelIndex &) const override; private: ASyncWindow * m_asyncWindow; std::shared_ptr m_database; PgClass m_table; boost::optional m_primaryKey; ASyncDBConnection m_dbConn; bool callLoadData = false; // using RowData = std::vector; // using RowDataPtr = std::unique_ptr; // /** Choosen for a vector of pointers while vector is relatively slow with insertion and removal in the middle // * I hope the small size of the elements will make this not much of an issue while the simple linear and sequential // * nature of a vector will keep memory allocation fairly efficient. // */ // using RowList = std::vector; std::shared_ptr m_roData; void loadData(); void loadIntoModel(std::shared_ptr data); // std::shared_ptr resultToRowList(std::shared_ptr result); using Value = boost::optional; /** Remembers the values that have been applies to a row after the original result was retrieved. */ class ModifiedRow { public: private: std::vector m_values; }; using ModifiedRowList = std::map; /** Manages the changes for the current row * */ class PendingChanges { public: private: int m_currentRow; std::vector m_currentPKeyValues; ///< The values to use for updating the row, for new rows this list is empty std::map m_values; ///< values that need to be applied }; using DeletedList = std::vector; // These are the original indexes before there were any modifications PendingChanges m_pendingChanges; /** Maintains a list of all modified rows. * * The key values are the indexes of the row before any rows were deleted. */ ModifiedRowList m_modifiedRowList; // Alternative, vector of rows class Row { public: int resultRow; ///< row index in original result, -1 for new rows std::vector currentValues; /// }; QVariant getData(const QModelIndex &index) const; Oid getType(int column) const; private slots: void connectionStateChanged(ASyncDBConnection::State state); // void queryResult(std::shared_ptr result); // void queryError(); // void dataProcessingFutureFinished(); }; #endif // CRUDMODEL_H