Reorganization of pgLab project

This commit is contained in:
eelke 2022-04-09 07:10:29 +02:00
parent 7300865c77
commit c71fdc4af7
78 changed files with 204 additions and 148 deletions

View file

@ -0,0 +1,208 @@
#include "util/PgLabItemDelegate.h"
#include <QApplication>
#include "Pgsql_oids.h"
#include "ResultTableModelUtil.h"
#include "CustomDataRole.h"
#include "AbstractEditorFactory.h"
PgLabItemDelegate::PgLabItemDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option,
const QModelIndex &index) const
{
QVariant value;
// value = index.data(Qt::FontRole);
// if (value.isValid() && !value.isNull()) {
// option->font = qvariant_cast<QFont>(value).resolve(option->font);
// option->fontMetrics = QFontMetrics(option->font);
// }
// value = index.data(Qt::TextAlignmentRole);
// if (value.isValid() && !value.isNull())
// option->displayAlignment = Qt::Alignment(value.toInt());
// value = index.data(Qt::ForegroundRole);
// if (value.canConvert<QBrush>())
// option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
option->index = index;
// value = index.data(Qt::CheckStateRole);
// if (value.isValid() && !value.isNull()) {
// option->features |= QStyleOptionViewItem::HasCheckIndicator;
// option->checkState = static_cast<Qt::CheckState>(value.toInt());
// }
// value = index.data(Qt::DecorationRole);
// if (value.isValid() && !value.isNull()) {
// option->features |= QStyleOptionViewItem::HasDecoration;
// switch (value.type()) {
// case QVariant::Icon: {
// option->icon = qvariant_cast<QIcon>(value);
// QIcon::Mode mode;
// if (!(option->state & QStyle::State_Enabled))
// mode = QIcon::Disabled;
// else if (option->state & QStyle::State_Selected)
// mode = QIcon::Selected;
// else
// mode = QIcon::Normal;
// QIcon::State state = option->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
// QSize actualSize = option->icon.actualSize(option->decorationSize, mode, state);
// // For highdpi icons actualSize might be larger than decorationSize, which we don't want. Clamp it to decorationSize.
// option->decorationSize = QSize(qMin(option->decorationSize.width(), actualSize.width()),
// qMin(option->decorationSize.height(), actualSize.height()));
// break;
// }
// case QVariant::Color: {
// QPixmap pixmap(option->decorationSize);
// pixmap.fill(qvariant_cast<QColor>(value));
// option->icon = QIcon(pixmap);
// break;
// }
// case QVariant::Image: {
// QImage image = qvariant_cast<QImage>(value);
// option->icon = QIcon(QPixmap::fromImage(image));
// option->decorationSize = image.size() / image.devicePixelRatio();
// break;
// }
// case QVariant::Pixmap: {
// QPixmap pixmap = qvariant_cast<QPixmap>(value);
// option->icon = QIcon(pixmap);
// option->decorationSize = pixmap.size() / pixmap.devicePixelRatio();
// break;
// }
// default:
// break;
// }
// }
Oid oid = InvalidOid;
value = index.data(CustomDataTypeRole); // get OID
if (value.isValid())
oid = value.toUInt(); //getType(index.column());
value = index.data(CustomDataMeaningRole);
DataMeaning meaning = value.isValid()
? static_cast<DataMeaning>(value.toInt())
: DataMeaningNormal;
value = index.data(Qt::DisplayRole);
option->displayAlignment = GetDefaultAlignmentForType(oid);
if (value.isValid() && ! value.isNull()) {
QColor forground_color = oid == Pgsql::bool_oid
? GetDefaultBoolColor(value.toBool())
: GetDefaultColorForType(oid);
option->features |= QStyleOptionViewItem::HasDisplay;
if (oid == Pgsql::bool_oid) {
bool b = value.toBool();
forground_color = GetDefaultBoolColor(b);
option->text = FormatBoolForDisplay(b);
}
else {
forground_color = GetDefaultColorForType(oid);
if (meaning == DataMeaningBytes) {
QString suffix;
auto s = value.toLongLong();
double val;
if (s > 1024 * 1024 * 1000) {
val = s / (1024 * 1024 * 1024);
suffix = "GiB";
forground_color = QColorConstants::Svg::darkorange;
option->font.setBold(true);
}
else if (s > 1024 * 1000) {
val = s / (1024 * 1024);
suffix = "MiB";
forground_color = QColorConstants::Svg::darkgoldenrod;
}
else if (s > 1000) {
val = s / 1024;
suffix = "KiB";
forground_color = QColorConstants::Svg::darkgreen;
}
else {
val = s;
suffix = "B";
forground_color = QColorConstants::Svg::darkblue;
}
option->text = QString{ "%1 %2" }.arg(val, 3, 'g', -1 ).arg(suffix) ;
}
else {
auto str = value.toString();
auto s = str.left(100);
// auto f = s.indexOf('\n');
// option->text = ((f > 0) ? s.left(f) : s).toString();
option->text = s;
}
}
option->palette.setBrush(QPalette::Text, QBrush(forground_color));
}
else {
option->palette.setBrush(QPalette::Text, QBrush(GetDefaultNullColor()));
option->features |= QStyleOptionViewItem::HasDisplay;
option->text = "null";
}
// option->backgroundBrush = qvariant_cast<QBrush>(index.data(Qt::BackgroundRole));
// disable style animations for checkboxes etc. within itemviews (QTBUG-30146)
option->styleObject = nullptr;
}
void PgLabItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
const QWidget *widget = option.widget; // QStyledItemDelegatePrivate::widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}
QWidget *PgLabItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (m_editorFactory)
return m_editorFactory->createEditor(parent, option, index);
return QStyledItemDelegate::createEditor(parent, option, index);
}
void PgLabItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (m_editorFactory)
m_editorFactory->setEditorData(editor, index);
else
QStyledItemDelegate::setEditorData(editor, index);
}
void PgLabItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if (m_editorFactory)
m_editorFactory->setModelData(editor, model, index);
else
QStyledItemDelegate::setModelData(editor, model, index);
}
AbstractEditorFactory* PgLabItemDelegate::editorFactory()
{
return m_editorFactory;
}
void PgLabItemDelegate::setEditorFactory(AbstractEditorFactory *editor_factory)
{
m_editorFactory = editor_factory;
}

View file

@ -0,0 +1,35 @@
#ifndef PGLABITEMDELEGATE_H
#define PGLABITEMDELEGATE_H
#include <QStyledItemDelegate>
class AbstractEditorFactory;
/** 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:
PgLabItemDelegate(QObject *parent = nullptr);
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
AbstractEditorFactory* editorFactory();
void setEditorFactory(AbstractEditorFactory *editor_factory);
protected:
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override;
private:
AbstractEditorFactory *m_editorFactory = nullptr;
};
#endif // PGLABITEMDELEGATE_H

View file

@ -0,0 +1,22 @@
#include "util/PgLabTableView.h"
#include "util/PgLabItemDelegate.h"
#include <QHeaderView>
#include <QSortFilterProxyModel>
PgLabTableView::PgLabTableView(QWidget *parent)
: QTableView(parent)
{
setAlternatingRowColors(true);
setItemDelegate(new PgLabItemDelegate(this));
setWordWrap(false);
auto pal = palette();
pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Active, QPalette::Highlight));
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Active, QPalette::HighlightedText));
setPalette(pal);
auto vertical_header = verticalHeader();
vertical_header->setMinimumSectionSize(16);
vertical_header->setDefaultSectionSize(20);
}

View file

@ -0,0 +1,15 @@
#ifndef PGLABTABLEVIEW_H
#define PGLABTABLEVIEW_H
#include <QTableView>
class QSortFilterProxyModel;
class PgLabTableView : public QTableView {
Q_OBJECT
public:
explicit PgLabTableView(QWidget *parent = nullptr);
};
#endif // PGLABTABLEVIEW_H

View file

@ -0,0 +1,90 @@
#pragma once
#include <QTableWidget>
#include <QSortFilterProxyModel>
#include "util/PgLabTableView.h"
#include <optional>
class PgDatabaseCatalog;
template <typename TableModel>
class PgLabTableViewHelper {
public:
PgLabTableViewHelper(QWidget * parent, TableModel *tableModel)
{
m_tableView = new PgLabTableView(parent);
m_dataModel = tableModel;
m_sortFilter = new QSortFilterProxyModel(parent);
m_sortFilter->setSourceModel(m_dataModel);
m_tableView->setModel(m_sortFilter);
m_tableView->setSortingEnabled(true);
m_sortFilter->sort(0, Qt::AscendingOrder);
}
PgLabTableViewHelper(QWidget * parent)
: PgLabTableViewHelper(parent, new TableModel(parent))
{}
PgLabTableView *tableView() const
{
return m_tableView;
}
TableModel *dataModel() const
{
return m_dataModel;
}
QSortFilterProxyModel *sortFilter() const
{
return m_sortFilter;
}
void setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
{
m_dataModel->setCatalog(cat);
m_tableView->resizeColumnsToContents();
}
QModelIndex currentSourceIndex() const
{
QModelIndex index = m_tableView->selectionModel()->currentIndex();
if (!index.isValid())
return index;
return m_sortFilter->mapToSource(index);
}
typename TableModel::RowItem rowItemForSourceRow(int row) const
{
return m_dataModel->rowItem(row);
}
typename TableModel::RowItem rowItemForProxyIndex(QModelIndex index)
{
QModelIndex sourceIndex = m_sortFilter->mapToSource(index);
return m_dataModel->rowItem(sourceIndex.row());
}
typename TableModel::RowItem rowItemForProxyRow(int row) const
{
return rowItemForProxyIndex(m_sortFilter->index(row, 0, QModelIndex()));
}
std::optional<typename TableModel::RowItem> currentRowItem() const
{
auto index = currentSourceIndex();
if (!index.isValid())
return {};
return rowItemForSourceRow(index.row());
}
private:
PgLabTableView *m_tableView = nullptr;
TableModel *m_dataModel = nullptr;
QSortFilterProxyModel *m_sortFilter = nullptr;
};