From 0322d37650c9b5b3b644ecb22f9c1e54b619bef0 Mon Sep 17 00:00:00 2001 From: nerix Date: Sun, 17 Mar 2024 12:21:15 +0100 Subject: [PATCH] Show line indicator instead of rectangle while dragging in tables (#5252) --- CHANGELOG.md | 1 + src/CMakeLists.txt | 2 + src/widgets/helper/EditableModelView.cpp | 3 ++ src/widgets/helper/TableStyles.cpp | 66 ++++++++++++++++++++++++ src/widgets/helper/TableStyles.hpp | 32 ++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 src/widgets/helper/TableStyles.cpp create mode 100644 src/widgets/helper/TableStyles.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index ce88f1f8f..9a2930dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ - Minor: Add wrappers for Lua `io` library for experimental plugins feature. (#5231) - Minor: Add permissions to experimental plugins feature. (#5231) - Minor: Add support to send /announce[color] commands. (#5250) +- Minor: Added drop indicator line while dragging in tables. (#5252) - Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840) - Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848) - Bugfix: Trimmed custom streamlink paths on all platforms making sure you don't accidentally add spaces at the beginning or end of its path. (#4834) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba5e85b4d..24853e752 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -651,6 +651,8 @@ set(SOURCE_FILES widgets/helper/SettingsDialogTab.hpp widgets/helper/SignalLabel.cpp widgets/helper/SignalLabel.hpp + widgets/helper/TableStyles.cpp + widgets/helper/TableStyles.hpp widgets/helper/TitlebarButton.cpp widgets/helper/TitlebarButton.hpp widgets/helper/TitlebarButtons.cpp diff --git a/src/widgets/helper/EditableModelView.cpp b/src/widgets/helper/EditableModelView.cpp index b549c9e9b..cbc04c03b 100644 --- a/src/widgets/helper/EditableModelView.cpp +++ b/src/widgets/helper/EditableModelView.cpp @@ -1,6 +1,7 @@ #include "EditableModelView.hpp" #include "widgets/helper/RegExpItemDelegate.hpp" +#include "widgets/helper/TableStyles.hpp" #include #include @@ -28,6 +29,8 @@ EditableModelView::EditableModelView(QAbstractTableModel *model, bool movable) this->tableView_->verticalHeader()->setVisible(false); this->tableView_->horizontalHeader()->setSectionsClickable(false); + TableRowDragStyle::applyTo(this->tableView_); + // create layout QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setContentsMargins(0, 0, 0, 0); diff --git a/src/widgets/helper/TableStyles.cpp b/src/widgets/helper/TableStyles.cpp new file mode 100644 index 000000000..27ace07a9 --- /dev/null +++ b/src/widgets/helper/TableStyles.cpp @@ -0,0 +1,66 @@ +#include "widgets/helper/TableStyles.hpp" + +#include +#include +#include +#include +#include + +namespace chatterino { + +TableRowDragStyle::TableRowDragStyle(QStyle *target) + : QProxyStyle(target) +{ +} + +void TableRowDragStyle::applyTo(QTableView *view) +{ + auto *proxyStyle = new TableRowDragStyle(view->style()); + proxyStyle->setParent(view); + view->setStyle(proxyStyle); +} + +void TableRowDragStyle::drawPrimitive(QStyle::PrimitiveElement element, + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + if (element != QStyle::PE_IndicatorItemViewItemDrop) + { + QProxyStyle::drawPrimitive(element, option, painter, widget); + return; + } + + const auto *view = dynamic_cast(widget); + if (!view) + { + assert(false && "TableStyle must be used on a QAbstractItemView"); + return; + } + + if (option->rect.isNull()) + { + return; + } + + // Get the direction a row is dragged in + auto selected = view->currentIndex(); + auto hovered = view->indexAt(option->rect.center()); + if (!selected.isValid() || !hovered.isValid()) + { + // This shouldn't happen as we're in a drag operation + assert(false && "Got bad indices"); + return; + } + + int y = option->rect.top(); // move up + if (hovered.row() >= selected.row()) + { + y = option->rect.bottom(); // move down + } + + painter->setPen({Qt::white, 2}); + painter->drawLine(0, y, widget->width(), y); +} + +} // namespace chatterino diff --git a/src/widgets/helper/TableStyles.hpp b/src/widgets/helper/TableStyles.hpp new file mode 100644 index 000000000..c71d889db --- /dev/null +++ b/src/widgets/helper/TableStyles.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +class QTableView; + +namespace chatterino { + +/// @brief A custom style for drag operations of rows on tables +/// +/// This style overwrites how `PE_IndicatorItemViewItemDrop`, the drop +/// indicator of item-views, is drawn. It's intended to be used on QTableViews +/// where entire rows are moved (not individual cells). The indicator is shown +/// as a line at the position where the dragged item should be inserted. If no +/// such position exists, a red border is drawn around the viewport. +class TableRowDragStyle : public QProxyStyle +{ +public: + /// Applies the style to @a view + static void applyTo(QTableView *view); + + void drawPrimitive(QStyle::PrimitiveElement element, + const QStyleOption *option, QPainter *painter, + const QWidget *widget = nullptr) const override; + +private: + /// @param target The style to wrap. This is **not** the parent of this + /// object. This object will become the parent of @a target. + TableRowDragStyle(QStyle *target); +}; + +} // namespace chatterino