From: Peter Penz Date: Tue, 12 Aug 2008 18:36:49 +0000 (+0000) Subject: Provide functionality for auto-expanding folders (the whole patch has been provided... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/b94777f9d19b3d515088493a81885082a50be791 Provide functionality for auto-expanding folders (the whole patch has been provided by Simon St James). The setting is currently not offered in the GUI, as some minor remaining issues must be fixed. CCMAIL: kdedevel@etotheipiplusone.com svn path=/trunk/KDE/kdebase/apps/; revision=845975 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a09e5779e..f09810b71 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ set(dolphinprivate_LIB_SRCS dolphincategorydrawer.cpp dolphinview.cpp dolphinviewactionhandler.cpp + folderexpander.cpp iconmanager.cpp ktooltip.cpp kballoontipdelegate.cpp @@ -108,7 +109,7 @@ set(dolphin_SRCS iconsizedialog.cpp iconsviewsettingspage.cpp infosidebarpage.cpp - ktreeview.cpp + ktreeview.cpp main.cpp metadatawidget.cpp metatextlabel.cpp diff --git a/src/dolphin_generalsettings.kcfg b/src/dolphin_generalsettings.kcfg index f7677ffa0..f8daf9339 100644 --- a/src/dolphin_generalsettings.kcfg +++ b/src/dolphin_generalsettings.kcfg @@ -55,5 +55,9 @@ + + + false + diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index 1d4837b12..fe35f5f42 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -28,6 +28,7 @@ #include "dolphin_columnmodesettings.h" #include "dolphin_generalsettings.h" #include "draganddrophelper.h" +#include "folderexpander.h" #include "iconmanager.h" #include "selectionmanager.h" #include "tooltipmanager.h" @@ -141,6 +142,11 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), this, SLOT(updateFont())); + + FolderExpander* folderExpander = new FolderExpander(this, m_proxyModel); + folderExpander->setEnabled(DolphinSettings::instance().generalSettings()->autoExpandFolders()); + connect (folderExpander, SIGNAL(enterDir(const QModelIndex&)), + m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); } DolphinColumnWidget::~DolphinColumnWidget() diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index 24b331d84..610a6d1ff 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -53,9 +53,11 @@ #include "dolphincontroller.h" #include "dolphinsortfilterproxymodel.h" #include "dolphindetailsview.h" +#include "dolphin_detailsmodesettings.h" #include "dolphiniconsview.h" #include "dolphinsettings.h" #include "dolphin_generalsettings.h" +#include "folderexpander.h" #include "iconmanager.h" #include "renamedialog.h" #include "tooltipmanager.h" @@ -741,7 +743,6 @@ void DolphinView::toggleAdditionalInfo(QAction* action) } } - void DolphinView::mouseReleaseEvent(QMouseEvent* event) { QWidget::mouseReleaseEvent(event); @@ -1155,6 +1156,20 @@ void DolphinView::createView() Q_ASSERT(view != 0); view->installEventFilter(this); + if (m_mode != ColumnView) { + // Give the view the ability to auto-expand its directories on hovering + // (the column view takes care about this itself). If the details view + // uses expandable folders, the auto-expanding should be used always. + DolphinSettings& settings = DolphinSettings::instance(); + const bool enabled = settings.generalSettings()->autoExpandFolders() || + ((m_detailsView != 0) && settings.detailsModeSettings()->expandableFolders()); + + FolderExpander* folderExpander = new FolderExpander(view, m_proxyModel); + folderExpander->setEnabled(enabled); + connect(folderExpander, SIGNAL(enterDir(const QModelIndex&)), + m_controller, SLOT(triggerItem(const QModelIndex&))); + } + m_controller->setItemView(view); m_fileItemDelegate = new KFileItemDelegate(view); diff --git a/src/folderexpander.cpp b/src/folderexpander.cpp new file mode 100644 index 000000000..f7b73c1f5 --- /dev/null +++ b/src/folderexpander.cpp @@ -0,0 +1,155 @@ +/*************************************************************************** + * Copyright (C) 2008 by Simon St James * + * * + * 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 "folderexpander.h" +#include "dolphinview.h" + +#include "dolphinsettings.h" +#include "dolphin_generalsettings.h" + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +FolderExpander::FolderExpander(QAbstractItemView *view, QSortFilterProxyModel *proxyModel) : + QObject(view), + m_enabled(true), + m_view(view), + m_proxyModel(proxyModel), + m_autoExpandTriggerTimer(0), + m_autoExpandPos() +{ + // Validation. If these fail, the event filter is never + // installed on the view and the FolderExpander is inactive. + if (m_view == 0) { + kWarning() << "Need a view!"; + return; // Not valid. + } + if (m_proxyModel == 0) { + kWarning() << "Need a proxyModel!"; + return; // Not valid. + } + KDirModel *m_dirModel = qobject_cast< KDirModel* >( m_proxyModel->sourceModel() ); + if (m_dirModel == 0) { + kWarning() << "Expected m_proxyModel's sourceModel() to be a KDirModel!"; + return; // Not valid. + } + + // Initialise auto-expand timer. + m_autoExpandTriggerTimer = new QTimer(this); + m_autoExpandTriggerTimer->setSingleShot(true); + connect(m_autoExpandTriggerTimer, SIGNAL(timeout()), + this, SLOT(autoExpandTimeout())); + + // The view scrolling complicates matters, so we want to + // be informed if they occur. + connect(m_view->horizontalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(viewScrolled())); + connect(m_view->verticalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(viewScrolled())); + + // "Dragging" events are sent to the QAbstractItemView's viewport. + m_view->viewport()->installEventFilter(this); +} + +void FolderExpander::setEnabled(bool enabled) +{ + m_enabled = enabled; +} + +bool FolderExpander::enabled() const +{ + return m_enabled; +} + +FolderExpander::~FolderExpander() +{ +} + +void FolderExpander::viewScrolled() +{ + if (m_autoExpandTriggerTimer->isActive()) { + kDebug() << "Resetting time due to scrolling!"; + // (Re-)set the timer while we're scrolling the view + // (or it's being scrolled by some external mechanism). + // TODO - experiment with this. Cancelling the timer, + // or adding a "penalty" on top of AUTO_EXPAND_DELAY + // might work more nicely when drilling down through the sidebar + // tree. + m_autoExpandTriggerTimer->start(AUTO_EXPAND_DELAY); + } +} + +void FolderExpander::autoExpandTimeout() +{ + if (!m_enabled) { + return; + } + + // We want to find whether the file currently being hovered over is a + // directory. TODO - is there a simpler way, preferably without + // needing to pass in m_proxyModel that has a KDirModel as its sourceModel() ... ? + QModelIndex proxyIndexToExpand = m_view->indexAt(m_autoExpandPos); + QModelIndex indexToExpand = m_proxyModel->mapToSource(proxyIndexToExpand); + KDirModel* m_dirModel = qobject_cast< KDirModel* >(m_proxyModel->sourceModel()); + Q_ASSERT(m_dirModel != 0); + KFileItem itemToExpand = m_dirModel->itemForIndex(indexToExpand ); + + kDebug() << "Need to expand: " << itemToExpand.targetUrl() << " isDir? = " << itemToExpand.isDir(); + + if (itemToExpand.isDir()) { + QTreeView *viewAsTreeView = qobject_cast(m_view); + if (viewAsTreeView != 0) { + // Toggle expanded state of this directory. + viewAsTreeView->setExpanded(proxyIndexToExpand, !viewAsTreeView->isExpanded(proxyIndexToExpand)); + } + else { + // Enter this directory. + emit enterDir(proxyIndexToExpand); + } + } +} + +bool FolderExpander::eventFilter(QObject* watched, QEvent* event) +{ + Q_UNUSED(watched); + // We're interested in reading Drag* events, but not filtering them, + // so always return false. + // We just store the position of the hover, here; actually working out + // what the hovered item is and whether it is expandable is done in + // autoExpandTimeout. + if (event->type() == QEvent::DragMove) { + QDragMoveEvent *dragMoveEvent = static_cast(event); + // (Re-)set the timer while we're still moving and dragging. + m_autoExpandTriggerTimer->start(AUTO_EXPAND_DELAY); + m_autoExpandPos = dragMoveEvent->pos(); + } else if (event->type() == QEvent::DragLeave || event->type() == QEvent::Drop) { + m_autoExpandTriggerTimer->stop(); + } + return false; +} diff --git a/src/folderexpander.h b/src/folderexpander.h new file mode 100644 index 000000000..136b6b152 --- /dev/null +++ b/src/folderexpander.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2008 by Simon St James * + * * + * 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 FOLDEREXPANDER_H +#define FOLDEREXPANDER_H + +// Needs to be exported as treesidebarpage uses it. +#include "libdolphin_export.h" + +#include +#include + +class QAbstractItemView; +class QTreeView; +class QTimer; +class QSortFilterProxyModel; +class QModelIndex; +class KDirModel; + +/* Grants "auto expand"/ "spring-loaded folders" to + the provided view. Qt has its own auto-expand + mechanism, but this works only for QTreeView and + does not play well with our auto-scrolling in + the Folders pane. Auto-expansion is enabled by default. + + If the provided view is a QTreeView, the expanded state + is automatically toggled on hover. Otherwise, the enterDir() + signal is emitted, and the caller needs to ensure that + the requested directory is entered. + + The FolderExpander becomes a child of the provided view */ + +/** + * Grants auto expanding functionality to the provided item view. + * Qt has its own auto expand mechanism, but this works only + * for QTreeView. Auto expanding of folders is turned on + * per default. + * + * If the provided view is an instance of the class QTreeView, the + * expanded of the directory is automatically done on hover. Otherwise + * the enterDir() signal is emitted and the caller needs to ensure that + * the requested directory is entered. + * + * The FolderExpander becomes a child of the provided view. + */ +class LIBDOLPHINPRIVATE_EXPORT FolderExpander : public QObject +{ + Q_OBJECT + +public: + FolderExpander(QAbstractItemView* view, QSortFilterProxyModel* proxyModel); + virtual ~FolderExpander(); + + void setEnabled(bool enabled); + bool enabled() const; + +signals: + /** + * Is emitted if the directory \a dirModelIndex should be entered. The + * signal is not emitted when a QTreeView is used, as the entering of + * the directory is already provided by expanding the tree node. + */ + void enterDir(const QModelIndex& dirModelIndex); + +private slots: + void viewScrolled(); + void autoExpandTimeout(); + +private: + bool m_enabled; + + QAbstractItemView* m_view; + QSortFilterProxyModel* m_proxyModel; + + QTimer* m_autoExpandTriggerTimer; + QPoint m_autoExpandPos; + + static const int AUTO_EXPAND_DELAY = 700; + + /** + * Watchs the drag/move events for the view to decide + * whether auto expanding of a folder should be triggered. + */ + bool eventFilter(QObject* watched, QEvent* event); +}; +#endif diff --git a/src/sidebartreeview.cpp b/src/sidebartreeview.cpp index d1f6d45b4..3018737ab 100644 --- a/src/sidebartreeview.cpp +++ b/src/sidebartreeview.cpp @@ -40,7 +40,6 @@ SidebarTreeView::SidebarTreeView(QWidget* parent) : setFrameStyle(QFrame::NoFrame); setDragDropMode(QAbstractItemView::DragDrop); setDropIndicatorShown(false); - setAutoExpandDelay(300); setVerticalScrollMode(QListView::ScrollPerPixel); setHorizontalScrollMode(QListView::ScrollPerPixel); diff --git a/src/treeviewsidebarpage.cpp b/src/treeviewsidebarpage.cpp index 8258fbfc8..20216b13c 100644 --- a/src/treeviewsidebarpage.cpp +++ b/src/treeviewsidebarpage.cpp @@ -25,6 +25,7 @@ #include "dolphinsettings.h" #include "dolphin_folderspanelsettings.h" #include "dolphin_generalsettings.h" +#include "folderexpander.h" #include "renamedialog.h" #include "sidebartreeview.h" #include "treeviewcontextmenu.h" @@ -157,6 +158,8 @@ void TreeViewSidebarPage::showEvent(QShowEvent* event) m_treeView->setModel(m_proxyModel); m_proxyModel->setSorting(DolphinView::SortByName); m_proxyModel->setSortOrder(Qt::AscendingOrder); + + new FolderExpander(m_treeView, m_proxyModel); connect(m_treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(updateActiveView(const QModelIndex&)));