Skip to content

Commit

Permalink
Show line indicator instead of rectangle while dragging in tables (#5256
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Nerixyz authored Jun 16, 2024
1 parent 9b31246 commit 2b97c64
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/widgets/helper/EditableModelView.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "EditableModelView.hpp"

#include "widgets/helper/RegExpItemDelegate.hpp"
#include "widgets/helper/TableStyles.hpp"

#include <QAbstractItemView>
#include <QAbstractTableModel>
Expand Down Expand Up @@ -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);
Expand Down
71 changes: 71 additions & 0 deletions src/widgets/helper/TableStyles.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "widgets/helper/TableStyles.hpp"

#include <QAbstractItemView>
#include <QPainter>
#include <QStyleOption>
#include <QTableView>
#include <QWidget>

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<const QAbstractItemView *>(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
32 changes: 32 additions & 0 deletions src/widgets/helper/TableStyles.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <QProxyStyle>

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

0 comments on commit 2b97c64

Please sign in to comment.