Reorganization of pgLab project
This commit is contained in:
parent
7300865c77
commit
c71fdc4af7
78 changed files with 204 additions and 148 deletions
208
pglab/util/PgLabItemDelegate.cpp
Normal file
208
pglab/util/PgLabItemDelegate.cpp
Normal 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;
|
||||
}
|
||||
35
pglab/util/PgLabItemDelegate.h
Normal file
35
pglab/util/PgLabItemDelegate.h
Normal 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
|
||||
22
pglab/util/PgLabTableView.cpp
Normal file
22
pglab/util/PgLabTableView.cpp
Normal 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);
|
||||
}
|
||||
|
||||
15
pglab/util/PgLabTableView.h
Normal file
15
pglab/util/PgLabTableView.h
Normal 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
|
||||
90
pglab/util/PgLabTableViewHelper.h
Normal file
90
pglab/util/PgLabTableViewHelper.h
Normal 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;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue