#include "ui/DiffTableModel.h"
#include "ui/PanelTableView.h"
#include <QAbstractItemModel>
#include <QEvent>
#include <QHeaderView>
#include <QPainter>
#include <QPalette>
#include <QProxyStyle>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
namespace whittle {
namespace {
constexpr int kCellPadding = 3;
constexpr int kCheckGap = 2;
class CellSeparatorDelegate : public QStyledItemDelegate {
public:
using QStyledItemDelegate::QStyledItemDelegate;
void initStyleOption(QStyleOptionViewItem* opt,
const QModelIndex& ix) const override {
QStyledItemDelegate::initStyleOption(opt, ix);
if (ix.column() == DiffTableModel::Name) {
opt->textElideMode = Qt::ElideLeft;
opt->features &= ~QStyleOptionViewItem::WrapText;
}
}
void paint(QPainter* p, const QStyleOptionViewItem& opt,
const QModelIndex& ix) const override {
QStyleOptionViewItem padded = opt;
padded.rect.adjust(kCellPadding, 0, 0, 0);
QStyledItemDelegate::paint(p, padded, ix);
if (!ix.model()) return;
p->save();
p->setPen(opt.palette.color(QPalette::Mid));
p->drawLine(opt.rect.bottomLeft(), opt.rect.bottomRight());
if (ix.column() != ix.model()->columnCount() - 1)
p->drawLine(opt.rect.topRight(), opt.rect.bottomRight());
p->restore();
}
bool editorEvent(QEvent* e, QAbstractItemModel* model,
const QStyleOptionViewItem& opt,
const QModelIndex& ix) override {
QStyleOptionViewItem padded = opt;
padded.rect.adjust(kCellPadding, 0, 0, 0);
return QStyledItemDelegate::editorEvent(e, model, padded, ix);
}
QSize sizeHint(const QStyleOptionViewItem& opt,
const QModelIndex& ix) const override {
QSize s = QStyledItemDelegate::sizeHint(opt, ix);
s.rwidth() += kCellPadding;
if (ix.flags() & Qt::ItemIsUserCheckable) s.rwidth() += kCheckGap;
return s;
}
};
class CheckGapStyle : public QProxyStyle {
public:
QRect subElementRect(SubElement se, const QStyleOption* opt,
const QWidget* w) const override {
QRect r = QProxyStyle::subElementRect(se, opt, w);
if (se == SE_ItemViewItemText)
if (const auto* vi = qstyleoption_cast<const QStyleOptionViewItem*>(opt))
if (vi->features & QStyleOptionViewItem::HasCheckIndicator)
r.adjust(kCheckGap, 0, 0, 0);
return r;
}
};
}
PanelTableView::PanelTableView(QWidget* parent) : QTableView(parent) {
setShowGrid(false);
setItemDelegate(new CellSeparatorDelegate(this));
auto* gapStyle = new CheckGapStyle;
gapStyle->setParent(this);
setStyle(gapStyle);
setSelectionMode(QAbstractItemView::NoSelection);
setFocusPolicy(Qt::NoFocus);
setEditTriggers(QAbstractItemView::NoEditTriggers);
auto* hh = horizontalHeader();
hh->setStretchLastSection(false);
hh->setSectionResizeMode(QHeaderView::Interactive);
hh->setHighlightSections(false);
verticalHeader()->setVisible(false);
connect(hh, &QHeaderView::sectionResized, this, [this](int, int, int) {
if (!m_applying) m_userSized = true;
});
}
void PanelTableView::resetColumnProportions() {
m_userSized = false;
applyProportions();
}
void PanelTableView::resizeEvent(QResizeEvent* e) {
QTableView::resizeEvent(e);
applyProportions();
}
void PanelTableView::applyProportions() {
if (m_userSized || !model()) return;
if (model()->columnCount() < DiffTableModel::ColumnCount) return;
const int w = viewport()->width();
if (w <= 0) return;
const int name = w * 50 / 100;
const int size = w * 13 / 100;
const int mod = w * 24 / 100;
m_applying = true;
setColumnWidth(DiffTableModel::Name, name);
setColumnWidth(DiffTableModel::Size, size);
setColumnWidth(DiffTableModel::Modified, mod);
setColumnWidth(DiffTableModel::TimeDiff, w - name - size - mod);
m_applying = false;
}
}