From: Simon Paul St James Date: Sun, 25 Jan 2009 19:46:08 +0000 (+0000) Subject: Refactor the folder expansion system. Main effect: instead of having a list of m_exp... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/248ce7c57a86f964c82c8e0b48e9c07d52c3934e Refactor the folder expansion system. Main effect: instead of having a list of m_expandedViews which cannot yet be deleted, we more accurately identify the current source of the drag operation if any and store only this for later deletion. This also fixes folder-expansion not working in Column view. svn path=/trunk/KDE/kdebase/apps/; revision=916701 --- diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index bc488b8ae..3b3e86a75 100644 --- a/src/dolphincolumnview.cpp +++ b/src/dolphincolumnview.cpp @@ -26,6 +26,8 @@ #include "dolphin_columnmodesettings.h" +#include + #include #include #include @@ -594,8 +596,16 @@ void DolphinColumnView::deleteColumn(DolphinColumnWidget* column) if (m_controller->itemView() == column) { m_controller->setItemView(0); } + // deleteWhenNotDragSource(column) does not necessarily delete column, + // and we want its preview generator destroyed immediately. + column->m_previewGenerator->deleteLater(); + column->m_previewGenerator = 0; + column->hide(); + // Prevent automatic destruction of column when this DolphinColumnView + // is destroyed. + column->setParent(0); column->disconnect(); - column->deleteLater(); + emit requestColumnDeletion(column); } } diff --git a/src/dolphincolumnview.h b/src/dolphincolumnview.h index 1fdd75850..caa54eab8 100644 --- a/src/dolphincolumnview.h +++ b/src/dolphincolumnview.h @@ -123,6 +123,13 @@ public slots: /** @see QAbstractItemView::selectAll() */ virtual void selectAll(); +signals: + /** + * Requests that the given column be deleted at the discretion + * of the receiver of the signal. + */ + void requestColumnDeletion(QAbstractItemView* column); + protected: virtual bool isIndexHidden(const QModelIndex& index) const; virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); diff --git a/src/dolphincontroller.cpp b/src/dolphincontroller.cpp index 81cec2868..980e16059 100644 --- a/src/dolphincontroller.cpp +++ b/src/dolphincontroller.cpp @@ -26,10 +26,11 @@ #include #include +Qt::MouseButtons DolphinController::m_mouseButtons = Qt::NoButton; + DolphinController::DolphinController(DolphinView* dolphinView) : QObject(dolphinView), m_zoomLevel(0), - m_mouseButtons(Qt::NoButton), m_url(), m_dolphinView(dolphinView), m_itemView(0) diff --git a/src/dolphincontroller.h b/src/dolphincontroller.h index 542f21b3b..3260ab63f 100644 --- a/src/dolphincontroller.h +++ b/src/dolphincontroller.h @@ -359,7 +359,7 @@ private slots: private: int m_zoomLevel; - Qt::MouseButtons m_mouseButtons; // TODO: this is a workaround until Qt-issue 176832 has been fixed + static Qt::MouseButtons m_mouseButtons; // TODO: this is a workaround until Qt-issue 176832 has been fixed KUrl m_url; DolphinView* m_dolphinView; QAbstractItemView* m_itemView; diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index cfe447e37..fdf93a1da 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -103,7 +103,7 @@ DolphinView::DolphinView(QWidget* parent, m_toolTipManager(0), m_rootUrl(), m_currentItemUrl(), - m_expandedViews() + m_expandedDragSource(0) { m_topLayout = new QVBoxLayout(this); m_topLayout->setSpacing(0); @@ -149,7 +149,9 @@ DolphinView::DolphinView(QWidget* parent, DolphinView::~DolphinView() { - deleteExpandedViews(); + kDebug() << "Deleted view " << m_expandedDragSource; + delete m_expandedDragSource; + m_expandedDragSource = 0; } const KUrl& DolphinView::url() const @@ -847,13 +849,16 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) break; case QEvent::MouseButtonPress: - if ((watched == itemView()->viewport()) && (m_expandedViews.count() > 0)) { + kDebug() << "m_expandedDragSource = " << m_expandedDragSource; + if ((watched == itemView()->viewport()) && (m_expandedDragSource != 0)) { // Listening to a mousebutton press event to delete expanded views is a // workaround, as it seems impossible for the FolderExpander to know when // a dragging outside a view has been finished. However it works quite well: // A mousebutton press event indicates that a drag operation must be // finished already. - deleteExpandedViews(); + kDebug() << "Deleted view " << m_expandedDragSource; + m_expandedDragSource->deleteLater(); + m_expandedDragSource = 0; } break; @@ -1061,6 +1066,29 @@ bool DolphinView::itemsExpandable() const return (m_detailsView != 0) && m_detailsView->itemsExpandable(); } +void DolphinView::deleteWhenNotDragSource(QAbstractItemView *view) +{ + if (view == 0) + return; + + if (DragAndDropHelper::instance().isDragSource(view)) { + kDebug() << "Is current drag source"; + // We must store for later deletion. + if (m_expandedDragSource != 0) { + // The old stored view is obviously not the drag source anymore. + kDebug() << "Deleted old view " << m_expandedDragSource; + m_expandedDragSource->deleteLater(); + m_expandedDragSource = 0; + } + view->hide(); + m_expandedDragSource = view; + } + else { + kDebug() << "Deleted new view " << view; + view->deleteLater(); + } +} + void DolphinView::emitContentsMoved() { // only emit the contents moved signal if: @@ -1113,16 +1141,6 @@ void DolphinView::restoreCurrentItem() } } -void DolphinView::enterDir(const QModelIndex& index, QAbstractItemView* view) -{ - // Deleting a view that is the root of a drag operation is not allowed, otherwise - // the dragging gets automatically cancelled by Qt. So before entering a new - // directory, the current view is remembered in m_expandedViews and deleted - // later when the drag operation has been finished (see DolphinView::eventFilter()). - m_expandedViews.append(view); - m_controller->triggerItem(index); -} - void DolphinView::loadDirectory(const KUrl& url, bool reload) { if (!url.isValid()) { @@ -1285,8 +1303,13 @@ void DolphinView::createView() FolderExpander* folderExpander = new FolderExpander(view, m_proxyModel); folderExpander->setEnabled(enabled); - connect(folderExpander, SIGNAL(enterDir(const QModelIndex&, QAbstractItemView*)), - this, SLOT(enterDir(const QModelIndex&, QAbstractItemView*))); + connect(folderExpander, SIGNAL(enterDir(const QModelIndex&)), + m_controller, SLOT(triggerItem(const QModelIndex&))); + } + else { + // Listen out for requests to delete the current column. + connect(m_columnView, SIGNAL(requestColumnDeletion(QAbstractItemView*)), + this, SLOT(deleteWhenNotDragSource(QAbstractItemView*))); } m_controller->setItemView(view); @@ -1342,29 +1365,18 @@ void DolphinView::deleteView() m_topLayout->removeWidget(view); view->close(); + // m_previewGenerator's parent is not always destroyed, and we + // don't want two active at once - manually delete. + delete m_previewGenerator; + m_previewGenerator = 0; + disconnect(view); m_controller->disconnect(view); view->disconnect(); - bool deleteView = true; - foreach (const QAbstractItemView* expandedView, m_expandedViews) { - if (view == expandedView) { - // the current view got already expanded and must stay alive - // until the dragging has been completed - deleteView = false; - break; - } - } - if (deleteView) { - view->deleteLater(); - } + deleteWhenNotDragSource(view); view = 0; - // m_previewGenerator's parent is not always destroyed, and we - // don't want two active at once - manually delete. - delete m_previewGenerator; - m_previewGenerator = 0; - m_iconsView = 0; m_detailsView = 0; m_columnView = 0; @@ -1434,17 +1446,6 @@ KUrl::List DolphinView::simplifiedSelectedUrls() const return list; } -void DolphinView::deleteExpandedViews() -{ - const QAbstractItemView* view = itemView(); - foreach (QAbstractItemView* expandedView, m_expandedViews) { - if (expandedView != view) { - expandedView->deleteLater(); - } - } - m_expandedViews.clear(); -} - QMimeData* DolphinView::selectionMimeData() const { if (isColumnViewActive()) { diff --git a/src/dolphinview.h b/src/dolphinview.h index 9dd001c8e..ea77024a6 100644 --- a/src/dolphinview.h +++ b/src/dolphinview.h @@ -628,10 +628,11 @@ private slots: void restoreCurrentItem(); /** - * Is connected to the enterDir() signal from the FolderExpander - * and triggers the entering of the directory indicated by \a index. + * If \a view can be positively identified as not being the source for the + * current drag operation, deleteLater() it immediately. Else stores + * it for later deletion. */ - void enterDir(const QModelIndex& index, QAbstractItemView* view); + void deleteWhenNotDragSource(QAbstractItemView* view); private: void loadDirectory(const KUrl& url, bool reload = false); @@ -699,12 +700,6 @@ private: */ bool isColumnViewActive() const; - /** - * Deletes all views from m_expandedViews except if the view - * is currently shown. - */ - void deleteExpandedViews(); - /** * Returns the MIME data for all selected items. */ @@ -741,7 +736,7 @@ private: KUrl m_rootUrl; KUrl m_currentItemUrl; - QList m_expandedViews; + QAbstractItemView* m_expandedDragSource; }; inline bool DolphinView::isColumnViewActive() const diff --git a/src/draganddrophelper.cpp b/src/draganddrophelper.cpp index 3ff7d296a..002394155 100644 --- a/src/draganddrophelper.cpp +++ b/src/draganddrophelper.cpp @@ -80,10 +80,18 @@ void DragAndDropHelper::startDrag(QAbstractItemView* itemView, } drag->setPixmap(pixmap); drag->setMimeData(data); + + m_dragSource = itemView; drag->exec(supportedActions, Qt::IgnoreAction); + m_dragSource = 0; } } +bool DragAndDropHelper::isDragSource(QAbstractItemView* itemView) +{ + return (m_dragSource != 0) && (m_dragSource == itemView); +} + void DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destPath, QDropEvent* event, @@ -115,6 +123,7 @@ void DragAndDropHelper::dropUrls(const KFileItem& destItem, } DragAndDropHelper::DragAndDropHelper() + : m_dragSource(0) { } diff --git a/src/draganddrophelper.h b/src/draganddrophelper.h index e362fd508..4859740cd 100644 --- a/src/draganddrophelper.h +++ b/src/draganddrophelper.h @@ -61,6 +61,12 @@ public: Qt::DropActions supportedActions, DolphinController* controller = 0); + /** + * Returns true if and only if the view \a itemView was the last view to + * be passed to startDrag(...), and that drag is still in progress. + */ + bool isDragSource(QAbstractItemView* itemView); + /** * Handles the dropping of URLs to the given * destination. A context menu with the options @@ -80,6 +86,9 @@ signals: private: DragAndDropHelper(); + // The last view passed in startDrag(...), or 0 if + // no startDrag(...) initiated drag is in progress. + QAbstractItemView *m_dragSource; friend class DragAndDropHelperSingleton; }; diff --git a/src/folderexpander.cpp b/src/folderexpander.cpp index 091cd0c2c..1aaf09ded 100644 --- a/src/folderexpander.cpp +++ b/src/folderexpander.cpp @@ -123,7 +123,7 @@ void FolderExpander::autoExpandTimeout() treeView->setExpanded(proxyIndexToExpand, !treeView->isExpanded(proxyIndexToExpand)); } else { - emit enterDir(proxyIndexToExpand, m_view); + emit enterDir(proxyIndexToExpand); } } } diff --git a/src/folderexpander.h b/src/folderexpander.h index 57b8e9e55..73d16c5c4 100644 --- a/src/folderexpander.h +++ b/src/folderexpander.h @@ -63,7 +63,7 @@ signals: * 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, QAbstractItemView* view); + void enterDir(const QModelIndex& dirModelIndex); private slots: