#include "CrudModel.h" #include "ASyncWindow.h" #include "OpenDatabase.h" #include "PgDatabaseCatalog.h" #include "PgAttributeContainer.h" #include "PgConstraintContainer.h" #include "GlobalIoService.h" #include "SqlFormattingUtils.h" #include "WorkManager.h" #include #include #include #include "Pgsql_oids.h" #include CrudModel::CrudModel(ASyncWindow *async_window) : m_asyncWindow(async_window) , m_dbConn(*getGlobalAsioIoService()) { connect(&m_dbConn, &ASyncDBConnection::onStateChanged, this, &CrudModel::connectionStateChanged); } CrudModel::~CrudModel() { m_dbConn.closeConnection(); } /* * Strategy * when ordered by primary key, offset and limit work very quickly so we can get away with not loading * everything. */ void CrudModel::setConfig(std::shared_ptr db, const PgClass &table) { m_database = db; m_table = table; m_primaryKey = db->catalogue()->constraints()->getPrimaryForRelation(table.oid); //cat->attributes()->getColumnsForRelation() callLoadData = true; m_dbConn.setupConnection(m_database->config()); } QVariant CrudModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant r; if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { QString s(m_roData->getColName(section)); s += "\n"; s += getTypeDisplayString(*m_database->catalogue(), getType(section)); r = s; } else { r = QString::number(section + 1); } } return r; } // Basic functionality: int CrudModel::rowCount(const QModelIndex &parent) const { return m_roData ? m_roData->rows() : 0; } int CrudModel::columnCount(const QModelIndex &parent) const { return m_roData ? m_roData->cols() : 0; } Oid CrudModel::getType(int column) const { return m_roData ? m_roData->type(column) : InvalidOid; } QVariant CrudModel::getData(const QModelIndex &index) const { QVariant r; if (m_roData) { int rij = index.row(); int col = index.column(); if (m_roData->null(col, rij)) { r = "null"; } else { Oid o = m_roData->type(col); auto value = m_roData->get(col, rij); switch (o) { case Pgsql::bool_oid: r = bool(value); //s = (s == "t") ? "TRUE" : "FALSE"; break; default: { QString s = value; if (s.length() > 256) { s.truncate(256); } r = s; } } } } return r; } QVariant CrudModel::data(const QModelIndex &index, int role) const { QVariant v; if (role == Qt::EditRole || role == Qt::DisplayRole) { v = getData(index); } else if (role == Qt::UserRole) { v = getType(index.column()); } return v; } void CrudModel::loadData() { QString table_name = genFQTableName(*m_database->catalogue(), m_table); std::string q = "SELECT * FROM "; q += table_name.toUtf8(); m_dbConn.send(q, [this] (Expected> res, qint64) { if (res.valid()) { auto dbres = res.get(); if (dbres && *dbres) { // WorkManager::getWorkManager()->addWork( // [dbres, this] () -> void { // std::shared_ptr rl = resultToRowList(dbres); // m_asyncWindow->QueueTask([this, rl]() { loadIntoModel(rl); }); // }); m_asyncWindow->QueueTask([this, dbres]() { loadIntoModel(dbres); }); } } else { // emit onQueryError(); } }); } void CrudModel::loadIntoModel(std::shared_ptr data) { beginResetModel(); m_roData = data; endResetModel(); } void CrudModel::connectionStateChanged(ASyncDBConnection::State state) { switch (state) { case ASyncDBConnection::State::NotConnected: break; case ASyncDBConnection::State::Connecting: break; case ASyncDBConnection::State::Connected: if (callLoadData) { callLoadData = false; loadData(); } break; case ASyncDBConnection::State::QuerySend: break; case ASyncDBConnection::State::CancelSend: break; case ASyncDBConnection::State::Terminating: break; } } Qt::ItemFlags CrudModel::flags(const QModelIndex &) const { return Qt::ItemIsSelectable + Qt::ItemIsEditable + Qt::ItemIsEnabled; }