Flexible models

This commit is contained in:
Eelke Klein 2018-09-02 10:30:30 +00:00
parent 50cb21b6f9
commit 8b7bbec807
24 changed files with 333 additions and 51 deletions

10
pglab/CustomDataRole.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef CUSTOMDATAROLE_H
#define CUSTOMDATAROLE_H
#include <Qt>
enum CustomDataRole {
CustomDataTypeRole = Qt::UserRole,
};
#endif // CUSTOMDATAROLE_H

View file

@ -3,6 +3,7 @@
#include "PgIndexContainer.h"
#include "Pgsql_oids.h"
#include "ScopeGuard.h"
#include "CustomDataRole.h"
void IndexModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table)
{
@ -96,7 +97,7 @@ QVariant IndexModel::data(const QModelIndex &index, int role) const
QVariant v;
if (role == Qt::DisplayRole)
v = getData(index);
else if (role == Qt::UserRole)
else if (role == CustomDataTypeRole)
v = getType(index.column());
return v;
}

View file

@ -83,7 +83,7 @@ void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option,
Oid oid = InvalidOid;
value = index.data(Qt::UserRole); // get OID
if (value.isValid())
oid = value.toInt(); //getType(index.column());
oid = value.toUInt(); //getType(index.column());
value = index.data(Qt::DisplayRole);
@ -112,7 +112,7 @@ void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option,
// option->backgroundBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));
// disable style animations for checkboxes etc. within itemviews (QTBUG-30146)
option->styleObject = 0;
option->styleObject = nullptr;
}
void PgLabItemDelegate::paint(QPainter *painter,

View file

@ -3,6 +3,12 @@
#include <QStyledItemDelegate>
/** Delegate for rendering SQL data types in tableviews
*
* This delegate removes the need for the model to provide formatting information
* which in many cases solely based on the datatype so this delegate can determine
* on its own what the correct formatting is.
*/
class PgLabItemDelegate : public QStyledItemDelegate
{
public:

View file

@ -0,0 +1,104 @@
#include "PropertyProxyModel.h"
/*
* Code borrowed from: https://stackoverflow.com/questions/21653253/how-to-change-orientation-of-qt-tableview
*
* Originally it was called Horizontal_proxy_model however some adjustments were made to it.
* Instead of the column headers becoming row headers we now convert them to the first column.
* The second column show the values of a single row from the source model. Which is determined
* by the setActiveRow call.
*/
PropertyProxyModel::PropertyProxyModel(QObject *parent)
: QIdentityProxyModel(parent)
{
}
QModelIndex PropertyProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
if (sourceModel()) {
if (activeRow >= 0) {
if (proxyIndex.column() == valueColumn) {
return sourceModel()->index(activeRow, proxyIndex.row());
}
}
}
return QModelIndex();
}
QModelIndex PropertyProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
if (activeRow >= 0) {
if (sourceIndex.row() == activeRow) {
return index(sourceIndex.column(), valueColumn);
}
}
return QModelIndex();
}
QModelIndex PropertyProxyModel::index(int row, int column, const QModelIndex &) const
{
return createIndex(row, column, nullptr);
}
QModelIndex PropertyProxyModel::parent(const QModelIndex &) const
{
return QModelIndex();
}
int PropertyProxyModel::rowCount(const QModelIndex &) const
{
return sourceModel() ? sourceModel()->columnCount() : 0;
}
int PropertyProxyModel::columnCount(const QModelIndex &) const
{
return 2;
}
QVariant PropertyProxyModel::headerData(
int section, Qt::Orientation orientation, int role) const
{
// if (!sourceModel()) {
// return QVariant();
// }
// Qt::Orientation new_orientation = orientation == Qt::Horizontal ?
// Qt::Vertical : Qt::Horizontal;
// return sourceModel()->headerData(section, new_orientation, role);
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Property");
case 1:
return tr("Value");
}
}
}
return QVariant();
}
QVariant PropertyProxyModel::data(const QModelIndex &proxyIndex, int role) const
{
auto sm = sourceModel();
if (sm) {
switch (proxyIndex.column()) {
case 0:
// return source header data
return sm->headerData(proxyIndex.row(), Qt::Horizontal, role);
case 1:
// return value if activeRow is set
if (activeRow >= 0) {
return QIdentityProxyModel::data(proxyIndex, role);
}
}
}
//return d->model->data(mapToSource(proxyIndex), role);
return QVariant();
}
void PropertyProxyModel::setActiveRow(const QModelIndex &row)
{
activeRow = row.isValid() ? row.row() : -1;
emit dataChanged(index(0, valueColumn), index(rowCount(QModelIndex()), valueColumn), QVector<int>() << Qt::DisplayRole);
}

View file

@ -0,0 +1,35 @@
#ifndef HORIZONTALPROXYMODEL_H
#define HORIZONTALPROXYMODEL_H
#include <QIdentityProxyModel>
class PropertyProxyModel : public QIdentityProxyModel {
Q_OBJECT
public:
PropertyProxyModel(QObject * parent = nullptr);
QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &proxyIndex, int role) const;
public Q_SLOTS:
/** Updates the model (and view) to show the values for row
*
* The column part of the index is not used QModelIndex is used to make is eacy to connect to
* QItemSelectionModel::currentRowChanged
*/
void setActiveRow(const QModelIndex &row);
private:
enum Columns {
propertyColumn = 0,
valueColumn
};
int activeRow = -1;
};
#endif // HORIZONTALPROXYMODEL_H

View file

@ -7,7 +7,7 @@
#include "ResultTableModelUtil.h"
#include "ColumnTableModel.h"
#include "ConstraintModel.h"
//#include "NamespaceFilterWidget.h"
#include "PropertyProxyModel.h"
#include "IconColumnDelegate.h"
#include "IndexModel.h"
#include "SqlFormattingUtils.h"
@ -24,9 +24,13 @@ TablesPage::TablesPage(MainWindow *parent)
{
ui->setupUi(this);
auto pglab_delegate = new PgLabItemDelegate(this);
auto icon_delegate = new IconColumnDelegate(this);
SetTableViewDefault(ui->tableListTable);
m_tablesModel = new TablesTableModel(this);
ui->tableListTable->setModel(m_tablesModel);
ui->tableListTable->setItemDelegate(pglab_delegate);
ui->tableListTable->setSortingEnabled(true);
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
@ -36,9 +40,8 @@ TablesPage::TablesPage(MainWindow *parent)
SetTableViewDefault(ui->constraintsTable);
m_constraintModel = new ConstraintModel(this);
auto delegate = new IconColumnDelegate(this);
ui->constraintsTable->setModel(m_constraintModel);
ui->constraintsTable->setItemDelegateForColumn(0, delegate);
ui->constraintsTable->setItemDelegateForColumn(0, icon_delegate);
QFont font;
font.setFamily("Source Code Pro");
@ -50,8 +53,18 @@ TablesPage::TablesPage(MainWindow *parent)
SetTableViewDefault(ui->indexesTable);
m_indexModel = new IndexModel(this);
ui->indexesTable->setModel(m_indexModel);
ui->indexesTable->setItemDelegate(new PgLabItemDelegate(ui->indexesTable));
ui->indexesTable->setItemDelegateForColumn(0, delegate);
ui->indexesTable->setItemDelegate(pglab_delegate);
ui->indexesTable->setItemDelegateForColumn(0, icon_delegate);
PropertyProxyModel* property_model = new PropertyProxyModel(this);
property_model->setSourceModel(m_tablesModel);
SetTableViewDefault(ui->tablePropertiesTable);
ui->tablePropertiesTable->setModel(property_model);
ui->tablePropertiesTable->setItemDelegate(pglab_delegate);
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
property_model, &PropertyProxyModel::setActiveRow);
//m_namespaceFilterWidget = new NamespaceFilterWidget(this);
//ui->verticalLayoutTableView->addWidget(m_namespaceFilterWidget);

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TablesPage</class>
<widget class="QWidget" name="TablesPage">
@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
@ -38,7 +38,7 @@
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="columnsTab">
<attribute name="title">
@ -90,6 +90,11 @@
<attribute name="title">
<string>Properties</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayoutProperties">
<item>
<widget class="QTableView" name="tablePropertiesTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="statisticsTab">
<attribute name="title">

View file

@ -5,13 +5,12 @@
#include "PgNamespace.h"
#include "PgNamespaceContainer.h"
#include "Pgsql_declare.h"
#include "CustomDataRole.h"
#include <QBrush>
TablesTableModel::TablesTableModel(QObject *parent)
: BaseTableModel(parent)
{
}
: QAbstractTableModel(parent)
{}
void TablesTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
{
@ -166,11 +165,11 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
v = getTablespaceDisplayString(*m_catalog, t.tablespace);
break;
case OptionsCol:
v = t.options;
//v = t.options;
break;
// case AclCol:
// v = t.acl;
// break;
// case AclCol:
// v = t.acl;
// break;
}
return v;
@ -195,19 +194,9 @@ QString TablesTableModel::formatTableName(const PgClass &cls) const
QVariant TablesTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::ForegroundRole) {
const auto &t = m_tables[index.row()];
auto ns = m_catalog->namespaces()->getByKey(t.relnamespace);
if (ns.isSystemCatalog()) {
switch (index.column()) {
case NameCol:
case NamespaceCol:
return QBrush(Qt::blue);
break;
}
}
}
return BaseTableModel::data(index, role);
if (role == Qt::DisplayRole)
return getData(index);
else if (role == CustomDataTypeRole)
return getType(index.column());
return QVariant();
}

View file

@ -9,8 +9,7 @@
class PgClass;
class PgDatabaseCatalog;
class TablesTableModel: public BaseTableModel
{
class TablesTableModel: public QAbstractTableModel {
public:
enum e_Columns : int {
NameCol, ///< either table, ns.table or table (ns) depending on settings/filters
@ -38,9 +37,6 @@ public:
virtual QVariant data(const QModelIndex &index, int role) const override;
PgClass getTable(int row) const;
Oid getTableOid(int row) const;
protected:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;
private:
using t_Tables = std::vector<PgClass>;
@ -48,6 +44,8 @@ private:
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
t_Tables m_tables;
Oid getType(int column) const;
QVariant getData(const QModelIndex &index) const;
QString formatTableName(const PgClass &cls) const;
void doSort(int so);
};

View file

@ -73,7 +73,8 @@ SOURCES += main.cpp\
Module.cpp \
EditorGutter.cpp \
CodeEditor.cpp \
PlgPage.cpp
PlgPage.cpp \
PropertyProxyModel.cpp
HEADERS += \
QueryResultModel.h \
@ -119,7 +120,9 @@ HEADERS += \
EditorGutter.h \
CodeEditor.h \
PlgPage.h \
AbstractCommand.h
AbstractCommand.h \
PropertyProxyModel.h \
CustomDataRole.h
FORMS += mainwindow.ui \
ConnectionManagerWindow.ui \