From d75c8d1cbd79903f8a087c41912fde696b0f54ad Mon Sep 17 00:00:00 2001 From: Luke Memet Date: Sat, 15 Feb 2025 12:04:54 -0500 Subject: [PATCH] GUI: Add macOS shift-click selection handler PR #22284 --- src/gui/CMakeLists.txt | 2 ++ src/gui/macosshiftclickhandler.cpp | 45 ++++++++++++++++++++++++++++++ src/gui/macosshiftclickhandler.h | 23 +++++++++++++++ src/gui/transferlistwidget.cpp | 2 ++ src/gui/transferlistwidget.h | 8 ++++++ 5 files changed, 80 insertions(+) create mode 100644 src/gui/macosshiftclickhandler.cpp create mode 100644 src/gui/macosshiftclickhandler.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 69c9ae1a2..3dc7b1f6a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -289,6 +289,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") macosdockbadge/badgeview.mm macutilities.h macutilities.mm + macosshiftclickhandler.h + macosshiftclickhandler.cpp ) target_link_libraries(qbt_gui PRIVATE objc) endif() diff --git a/src/gui/macosshiftclickhandler.cpp b/src/gui/macosshiftclickhandler.cpp new file mode 100644 index 000000000..cf2ee36e1 --- /dev/null +++ b/src/gui/macosshiftclickhandler.cpp @@ -0,0 +1,45 @@ +#include "macosshiftclickhandler.h" + +#include +#include "transferlistwidget.h" + +MacOSShiftClickHandler::MacOSShiftClickHandler(TransferListWidget *parent) + : QObject(parent) + , m_treeView(parent) +{ + parent->installEventFilter(this); +} + +bool MacOSShiftClickHandler::eventFilter(QObject *watched, QEvent *event) +{ + if ((watched == m_treeView) && (event->type() == QEvent::MouseButtonPress)) + { + auto *mouseEvent = static_cast(event); + if (mouseEvent->button() != Qt::LeftButton) + return false; + + const QModelIndex clickedIndex = m_treeView->indexAt(mouseEvent->pos()); + if (!clickedIndex.isValid()) + return false; + + const Qt::KeyboardModifiers modifiers = mouseEvent->modifiers(); + const bool shiftPressed = modifiers.testFlag(Qt::ShiftModifier); + const bool commandPressed = modifiers.testFlag(Qt::ControlModifier); + + if (shiftPressed && m_lastClickedIndex.isValid()) + { + const QItemSelection selection(m_lastClickedIndex, clickedIndex); + if (commandPressed) + m_treeView->selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows); + else + m_treeView->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + m_treeView->selectionModel()->setCurrentIndex(clickedIndex, QItemSelectionModel::NoUpdate); + return true; + } + + if (!(modifiers & (Qt::AltModifier | Qt::MetaModifier))) + m_lastClickedIndex = clickedIndex; + } + + return false; +} \ No newline at end of file diff --git a/src/gui/macosshiftclickhandler.h b/src/gui/macosshiftclickhandler.h new file mode 100644 index 000000000..8dcc4bb69 --- /dev/null +++ b/src/gui/macosshiftclickhandler.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class TransferListWidget; + +// Workaround for QTBUG-115838: Shift-click range selection not working properly on macOS +class MacOSShiftClickHandler final : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(MacOSShiftClickHandler) + +public: + explicit MacOSShiftClickHandler(TransferListWidget *parent); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + TransferListWidget *m_treeView; + QPersistentModelIndex m_lastClickedIndex; +}; \ No newline at end of file diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index 9435b05be..39d28969c 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -75,6 +75,7 @@ #ifdef Q_OS_MACOS #include "macutilities.h" +#include "macosshiftclickhandler.h" #endif namespace @@ -158,6 +159,7 @@ TransferListWidget::TransferListWidget(IGUIApplication *app, QWidget *parent) setDropIndicatorShown(true); #if defined(Q_OS_MACOS) setAttribute(Qt::WA_MacShowFocusRect, false); + m_shiftClickHandler = new MacOSShiftClickHandler(this); #endif header()->setFirstSectionMovable(true); header()->setStretchLastSection(false); diff --git a/src/gui/transferlistwidget.h b/src/gui/transferlistwidget.h index c5b24ba24..2fbeb64ac 100644 --- a/src/gui/transferlistwidget.h +++ b/src/gui/transferlistwidget.h @@ -52,6 +52,10 @@ enum class CopyInfohashPolicy Version2 }; +#ifdef Q_OS_MACOS +class MacOSShiftClickHandler; // Forward declaration +#endif + class TransferListWidget final : public GUIApplicationComponent { Q_OBJECT @@ -137,6 +141,10 @@ private: QList getVisibleTorrents() const; int visibleColumnsCount() const; +#ifdef Q_OS_MACOS + MacOSShiftClickHandler *m_shiftClickHandler = nullptr; +#endif + TransferListModel *m_listModel = nullptr; TransferListSortModel *m_sortFilterModel = nullptr; };