]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Provide functionality for auto-expanding folders (the whole patch has been provided...
authorPeter Penz <peter.penz19@gmail.com>
Tue, 12 Aug 2008 18:36:49 +0000 (18:36 +0000)
committerPeter Penz <peter.penz19@gmail.com>
Tue, 12 Aug 2008 18:36:49 +0000 (18:36 +0000)
CCMAIL: kdedevel@etotheipiplusone.com

svn path=/trunk/KDE/kdebase/apps/; revision=845975

src/CMakeLists.txt
src/dolphin_generalsettings.kcfg
src/dolphincolumnwidget.cpp
src/dolphinview.cpp
src/folderexpander.cpp [new file with mode: 0644]
src/folderexpander.h [new file with mode: 0644]
src/sidebartreeview.cpp
src/treeviewsidebarpage.cpp

index a09e5779e2c0579657e2b9fc2bc8f8a947ed3372..f09810b71608ace5ac21b170e5c6c54559db0c04 100644 (file)
@@ -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
index f7677ffa023a20e065f066607f235bc50dc63a46..f8daf93397145d643420ea5589fd72ba20a87fd9 100644 (file)
@@ -55,5 +55,9 @@
         <entry name="ViewPropsTimestamp" type="DateTime" >
             <label context="@label">Timestamp since when the view properties are valid</label>
         </entry>
+        <entry name="AutoExpandFolders" type="Bool">
+            <label context="@label">Use auto-expanding folders for all view types</label>
+            <default>false</default>
+        </entry>
     </group>
 </kcfg>
index 1d4837b126bc13f0704f925f1183643a4d5736ba..fe35f5f420a6fc427b354d6fc0d7d979e50e3676 100644 (file)
@@ -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()
index 24b331d84b9607a0940f56b79722131979aaf508..610a6d1ffe802fa6a4cf24a28c94126b75f5aac3 100644 (file)
 #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 (file)
index 0000000..f7b73c1
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Simon St James <kdedevel@etotheipiplusone.com>  *
+ *                                                                         *
+ *   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 <QtCore/QTimer>
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QTreeView>
+#include <QtGui/QScrollBar>
+
+#include <QtCore/QEvent>
+#include <QtGui/QDragMoveEvent>
+
+#include <QtGui/QSortFilterProxyModel>
+
+#include <kdirmodel.h>
+#include <kdebug.h>
+
+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<QTreeView*>(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<QDragMoveEvent*>(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 (file)
index 0000000..136b6b1
--- /dev/null
@@ -0,0 +1,102 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Simon St James <kdedevel@etotheipiplusone.com>  *
+ *                                                                         *
+ *   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 <QObject>
+#include <QPoint>
+
+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
index d1f6d45b4f49dfc06944bafd74af2b1c6087f905..3018737ab84b683a59012dad331331b56158e836 100644 (file)
@@ -40,7 +40,6 @@ SidebarTreeView::SidebarTreeView(QWidget* parent) :
     setFrameStyle(QFrame::NoFrame);
     setDragDropMode(QAbstractItemView::DragDrop);
     setDropIndicatorShown(false);
-    setAutoExpandDelay(300);
 
     setVerticalScrollMode(QListView::ScrollPerPixel);
     setHorizontalScrollMode(QListView::ScrollPerPixel);
index 8258fbfc8d390b3896edde13937e693324220524..20216b13cf74a388bc93be627715de5ea31b5281 100644 (file)
@@ -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&)));