From: Peter Penz Date: Sat, 6 Dec 2008 20:06:04 +0000 (+0000) Subject: Fixed serious usability issue: QAbstractItemView::setAutoScroll() is not usable when... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/53bdec9b58131014dcec9d6bc7d48e1aa01be979?ds=inline Fixed serious usability issue: QAbstractItemView::setAutoScroll() is not usable when trying to select items outside the visible view area (reported to Qt Software with bug ID #214542) -> implemented custom auto scrolling algorithm. BUG: 165531 svn path=/trunk/KDE/kdebase/apps/; revision=893546 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 196577fc8..9cd091045 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ set(dolphinprivate_LIB_SRCS dolphincategorydrawer.cpp dolphinview.cpp dolphinviewactionhandler.cpp + dolphinviewautoscroller.cpp draganddrophelper.cpp folderexpander.cpp ktooltip.cpp diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index 86ab88207..8edcf9a80 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -25,6 +25,7 @@ #include "dolphindirlister.h" #include "dolphinsortfilterproxymodel.h" #include "dolphinsettings.h" +#include "dolphinviewautoscroller.h" #include "dolphin_columnmodesettings.h" #include "dolphin_generalsettings.h" #include "draganddrophelper.h" @@ -75,6 +76,8 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, setVerticalScrollMode(QListView::ScrollPerPixel); setHorizontalScrollMode(QListView::ScrollPerPixel); + + new DolphinViewAutoScroller(this); // apply the column mode settings to the widget const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index c4f54cec4..32deb873b 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -25,6 +25,7 @@ #include "dolphinfileitemdelegate.h" #include "dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" +#include "dolphinviewautoscroller.h" #include "draganddrophelper.h" #include "selectionmanager.h" #include "viewproperties.h" @@ -75,6 +76,7 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* contr setEditTriggers(QAbstractItemView::NoEditTriggers); setMouseTracking(true); + new DolphinViewAutoScroller(this); const ViewProperties props(controller->url()); setSortIndicatorSection(props.sorting()); diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp index 6a54bd5c3..54c6ede8c 100644 --- a/src/dolphiniconsview.cpp +++ b/src/dolphiniconsview.cpp @@ -22,6 +22,7 @@ #include "dolphincategorydrawer.h" #include "dolphincontroller.h" #include "dolphinsettings.h" +#include "dolphinviewautoscroller.h" #include "dolphin_iconsmodesettings.h" #include "dolphin_generalsettings.h" #include "draganddrophelper.h" @@ -61,6 +62,7 @@ DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controlle viewport()->setAcceptDrops(true); setMouseTracking(true); + new DolphinViewAutoScroller(this); connect(this, SIGNAL(clicked(const QModelIndex&)), controller, SLOT(requestTab(const QModelIndex&))); diff --git a/src/dolphinviewautoscroller.cpp b/src/dolphinviewautoscroller.cpp new file mode 100644 index 000000000..ce10f92cd --- /dev/null +++ b/src/dolphinviewautoscroller.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2008 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "dolphinviewautoscroller.h" + +#include +#include +#include +#include +#include +#include +#include + +DolphinViewAutoScroller::DolphinViewAutoScroller(QAbstractItemView* parent) : + QObject(parent), + m_rubberBandSelection(false), + m_scrollInc(0), + m_itemView(parent), + m_timer() +{ + m_itemView->setAutoScroll(false); + m_itemView->viewport()->installEventFilter(this); + + m_timer = new QTimer(this); + m_timer->setSingleShot(false); + m_timer->setInterval(1000 / 25); // 25 frames per second + connect(m_timer, SIGNAL(timeout()), this, SLOT(scrollViewport())); +} + +DolphinViewAutoScroller::~DolphinViewAutoScroller() +{ +} + +bool DolphinViewAutoScroller::eventFilter(QObject* watched, QEvent* event) +{ + if (watched == m_itemView->viewport()) { + switch (event->type()) { + case QEvent::MouseButtonPress: + m_rubberBandSelection = true; + break; + + case QEvent::MouseMove: + if (m_rubberBandSelection) { + triggerAutoScroll(); + } + break; + + case QEvent::MouseButtonRelease: + m_rubberBandSelection = false; + stopAutoScroll(); + break; + + case QEvent::DragEnter: + case QEvent::DragMove: + triggerAutoScroll(); + break; + + case QEvent::DragLeave: + stopAutoScroll(); + break; + + default: + break; + } + } + + return QObject::eventFilter(watched, event); +} + +void DolphinViewAutoScroller::scrollViewport() +{ + // TODO: implement horizontal scrolling + QScrollBar* verticalScrollBar = m_itemView->verticalScrollBar(); + if (verticalScrollBar != 0) { + const int value = verticalScrollBar->value(); + verticalScrollBar->setValue(value + m_scrollInc); + + if (m_rubberBandSelection) { + // The scrolling does not lead to an update of the rubberband + // selection. Fake a mouse move event to let the QAbstractItemView + // update the rubberband. + QWidget* viewport = m_itemView->viewport(); + const QPoint pos = viewport->mapFromGlobal(QCursor::pos()); + QMouseEvent event(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QCoreApplication::sendEvent(viewport, &event); + } + } +} + +void DolphinViewAutoScroller::triggerAutoScroll() +{ + // TODO: implement horizontal scrolling + + const int startSpeed = 2; + const int speedLimiter = 8; + const int scrollIncMax = 32; + + const int autoScrollBorder = 32; + + QWidget* viewport = m_itemView->viewport(); + const QPoint pos = viewport->mapFromGlobal(QCursor::pos()); + if (pos.y() < autoScrollBorder) { + // scroll up + m_scrollInc = -startSpeed + (pos.y() - autoScrollBorder) / speedLimiter; + if (m_scrollInc < -scrollIncMax) { + m_scrollInc = -scrollIncMax; + } + } else if (pos.y() > viewport->height() - autoScrollBorder) { + // scroll down + m_scrollInc = startSpeed + (pos.y() - viewport->height() + autoScrollBorder) / speedLimiter; + if (m_scrollInc > scrollIncMax) { + m_scrollInc = scrollIncMax; + } + } else { + // no scrolling + m_scrollInc = 0; + } + + if (m_timer->isActive()) { + if (m_scrollInc == 0) { + m_timer->stop(); + } + } else if (m_scrollInc != 0) { + m_timer->start(); + } +} + +void DolphinViewAutoScroller::stopAutoScroll() +{ + m_timer->stop(); + m_scrollInc = 0; +} + +#include "dolphinviewautoscroller.moc" diff --git a/src/dolphinviewautoscroller.h b/src/dolphinviewautoscroller.h new file mode 100644 index 000000000..c02112b7b --- /dev/null +++ b/src/dolphinviewautoscroller.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2008 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DOLPHINVIEWAUTOSCROLLER_H +#define DOLPHINVIEWAUTOSCROLLER_H + +#include + +class QAbstractItemView; +class QTimer; + +/** + * @brief Assures that an autoscrolling is done for item views. + * + * This is a workaround as QAbstractItemView::setAutoScroll() is not usable + * when selecting items (see Qt issue #214542). + */ +class DolphinViewAutoScroller : public QObject +{ + Q_OBJECT + +public: + DolphinViewAutoScroller(QAbstractItemView* parent); + virtual ~DolphinViewAutoScroller(); + +protected: + virtual bool eventFilter(QObject* watched, QEvent* event); + +private slots: + void scrollViewport(); + +private: + void triggerAutoScroll(); + void stopAutoScroll(); + +private: + bool m_rubberBandSelection; + int m_scrollInc; + QAbstractItemView* m_itemView; + QTimer* m_timer; +}; + +#endif