#include "ColumnTableModel.h" #include "PgDatabaseCatalog.h" #include "PgAttribute.h" #include "PgAttributeContainer.h" #include "PgClassContainer.h" #include "PgConstraintContainer.h" #include "PgType.h" #include "PgTypeContainer.h" #include "PgIndexContainer.h" #include "ScopeGuard.h" #include void ColumnTableModel::setData(std::shared_ptr cat, const PgClass &table) { beginResetModel(); SCOPE_EXIT { endResetModel(); }; m_table = table; m_catalog = cat; m_columns = cat->attributes()->getColumnsForRelation(table.oid); // hide system columns auto si = table.hasoids ? std::remove_if(m_columns.begin(), m_columns.end(), [](PgAttribute &e) { return e.num <= 0 && e.name != "oid"; }) : std::remove_if(m_columns.begin(), m_columns.end(), [](PgAttribute &e) { return e.num <= 0; }); // move columns to end and remove them m_columns.erase(si, m_columns.end()); // sort remaining columns by order in table std::sort(m_columns.begin(), m_columns.end(), [] (auto &l, auto &r) -> bool { return l.num < r.num; }); m_indexes = m_catalog->indexes()->getIndexesForTable(table.oid); std::sort(m_indexes.begin(), m_indexes.end(), [] (const auto &l, const auto &r) -> bool { return l.isprimary > r.isprimary || (l.isprimary == r.isprimary && l.indexrelid < r.indexrelid); }); } QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant v; if (orientation == Qt::Horizontal) { if (role == Qt::DisplayRole) { QString c; if (section >= colCount) { const auto &tbl_idx = m_indexes[section - colCount]; if (tbl_idx.isprimary) c = "PK"; else if (tbl_idx.isunique) c = "UIdx"; else c = "Idx"; } else { switch (section) { case AttnumCol: c = tr("#"); break; case NameCol: c = tr("Name"); break; case TypeCol: c = tr("Type"); break; case NullCol: c = tr("N"); break; case DefaultCol: c = tr("Default"); break; case ForeignKeyCol: c = tr("Refs"); break; case CollationCol: c = tr("Collation"); break; } } v = c; } else if (role == Qt::ToolTipRole) { if (section >= colCount) { const auto &tbl_idx = m_indexes[section - colCount]; //auto idx_cls = m_catalog->classes()->getByKey(tbl_idx.indexrelid); auto idx_class_name = getClassDisplayString(*m_catalog, tbl_idx.indexrelid); QString s; if (tbl_idx.isprimary) s = tr("Primary key"); else if (tbl_idx.isunique) s = tr("Unique index"); else s = tr("Index"); s += "\n" + idx_class_name; v = s; } else { switch (section) { // case NameCol: // c = tr("Name"); // break; // case TypeCol: // c = tr("Type"); // break; case NullCol: v = tr("N = Column is nullable"); break; case DefaultCol: v = tr("Default value for the columns"); break; case ForeignKeyCol: v = tr("Foreign key constraint for this column"); break; // case CollationCol: // c = tr("Collation"); // break; } } } } return v; } int ColumnTableModel::rowCount(const QModelIndex &/*parent*/) const { return m_columns.size(); } int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const { return colCount + m_indexes.size(); } Oid ColumnTableModel::getType(int /*column*/) const { Oid oid = Pgsql::VARCHAROID; // switch (column) { // case TypeCol: // case NameCol: // case NullCol: // case DefaultCol: // case CollationCol: // oid = VARCHAROID; // break; // c = tr("Collation"); // break; // } return oid; } QVariant ColumnTableModel::getData(const QModelIndex &index) const { QVariant v; const int row = index.row(); const auto &t = m_columns[row]; const int col = index.column(); if (col >= colCount) { const auto &tbl_idx = m_indexes[col - colCount]; int i = 1; for (auto attr : tbl_idx.key) { if (attr == t.num) { v = i; break; } ++i; } } else { QString s; switch (col) { case AttnumCol: s = QString::asprintf("%d", (int) t.num); break; case NameCol: s = t.name; break; case TypeCol: s = getTypeDisplayString(*m_catalog, t.typid, t.typmod); break; case NullCol: s = QString::fromStdU16String(t.notnull ? u"" : u"N"); break; case DefaultCol: s = t.defaultValue; break; case ForeignKeyCol: s = getFKey(t); break; case CollationCol: s = ""; //t.collation; break; } v = s; } return v; } QString ColumnTableModel::getFKey(const PgAttribute &column) const { QString result; const PgConstraint *c = m_catalog->constraints()->getFKeyForTableColumn(column.relid, column.num); if (c) { result = c->name; } return result; } QVariant ColumnTableModel::data(const QModelIndex &index, int role) const { if (role == Qt::ForegroundRole && index.column() == TypeCol) { QVariant v; const auto &t = m_columns[index.row()]; auto c = m_catalog->types()->getByKey(t.typid); switch (c.category) { case TypCategory::Boolean: v = QBrush(Qt::darkGreen); break; case TypCategory::Numeric: v = QBrush(Qt::darkBlue); break; case TypCategory::DateTime: case TypCategory::Timespan: v = QBrush(Qt::darkMagenta); break; case TypCategory::String: v = QBrush(Qt::darkYellow); break; case TypCategory::Array: case TypCategory::Composite: case TypCategory::Enum: case TypCategory::Geometric: case TypCategory::NetworkAddress: case TypCategory::Pseudo: case TypCategory::Range: case TypCategory::UserDefined: case TypCategory::BitString: case TypCategory::Unknown: default: v = QBrush(Qt::black); } return v; } if (role == Qt::TextAlignmentRole) { QVariant v; int col = index.column(); if (col == NullCol || col >= colCount) v = Qt::AlignCenter + Qt::AlignVCenter; else v = Qt::AlignLeft + Qt::AlignVCenter; return v; } return BaseTableModel::data(index, role); }