diff --git a/CHANGELOG.md b/CHANGELOG.md index e49cea9ba..078d0ee40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Minor: Improved error messages for channel update commands. (#5429) - Minor: Moderators can now see when users are warned. (#5441) - Minor: Added support for Brave & google-chrome-stable browsers. (#5452) +- Minor: Added drop indicator line while dragging in tables. (#5256) - Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426) - Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378) - Bugfix: Fixed restricted users usernames not being clickable. (#5405) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da690e43a..826343755 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -655,6 +655,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..bf586f198 --- /dev/null +++ b/src/widgets/helper/TableStyles.cpp @@ -0,0 +1,71 @@ +#include "widgets/helper/TableStyles.hpp" + +#include +#include +#include +#include +#include + +namespace chatterino { + +TableRowDragStyle::TableRowDragStyle(const QString &name) + : QProxyStyle(name) +{ +} + +void TableRowDragStyle::applyTo(QTableView *view) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + auto styleName = view->style()->name(); +#else + QString styleName = "fusion"; +#endif + auto *proxyStyle = new TableRowDragStyle(styleName); + 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..a8d264831 --- /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 name The style name to emulate. + /// This should be set to `style()->name()`. + TableRowDragStyle(const QString &name); +}; + +} // namespace chatterino