From 669ee3250d233b96bc2f2e63865b048d33215674 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Tue, 2 Jul 2013 19:27:06 +0200 Subject: [PATCH] Fix crash when dropping URLs on the URL navigator's drop down menus The problem was that the files were copied/moved inside the nested event loop of the drag, which caused problems if the "File exists" dialog was shown. The solution is to make the copy/move operation delayed, such that it is executed in the main event loop. Note that dropping files on these menus does apparently not work at the moment when using the Oxygen style (see bug 310016). BUG: 192139 BUG: 256338 BUG: 293220 BUG: 309076 FIXED-IN: 4.11.0 REVIEW: 111273 --- dolphin/src/dolphinviewcontainer.cpp | 32 ++++++++++++++++++++++++++-- dolphin/src/dolphinviewcontainer.h | 15 +++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/dolphin/src/dolphinviewcontainer.cpp b/dolphin/src/dolphinviewcontainer.cpp index 71dc5fd7b5..1e9e79ae7a 100644 --- a/dolphin/src/dolphinviewcontainer.cpp +++ b/dolphin/src/dolphinviewcontainer.cpp @@ -68,7 +68,9 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) : m_statusBar(0), m_statusBarTimer(0), m_statusBarTimestamp(), - m_autoGrabFocus(true) + m_autoGrabFocus(true), + m_dropDestination(), + m_dropEvent(0) #ifdef KActivities_FOUND , m_activityResourceInstance(0) #endif @@ -597,11 +599,37 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url) void DolphinViewContainer::dropUrls(const KUrl& destination, QDropEvent* event) { + m_dropDestination = destination; + + const QMimeData* mimeData = event->mimeData(); + QMimeData* mimeDataCopy = new QMimeData; + foreach (const QString& format, mimeData->formats()) { + mimeDataCopy->setData(format, mimeData->data(format)); + } + + m_dropEvent.reset(new QDropEvent(event->pos(), + event->possibleActions(), + mimeDataCopy, + event->mouseButtons(), + event->keyboardModifiers())); + + QTimer::singleShot(0, this, SLOT(dropUrlsDelayed())); +} + +void DolphinViewContainer::dropUrlsDelayed() +{ + if (m_dropEvent.isNull()) { + return; + } + QString error; - DragAndDropHelper::dropUrls(KFileItem(), destination, event, error); + DragAndDropHelper::dropUrls(KFileItem(), m_dropDestination, m_dropEvent.data(), error); if (!error.isEmpty()) { showMessage(error, Error); } + + delete m_dropEvent->mimeData(); + m_dropEvent.reset(); } void DolphinViewContainer::redirect(const KUrl& oldUrl, const KUrl& newUrl) diff --git a/dolphin/src/dolphinviewcontainer.h b/dolphin/src/dolphinviewcontainer.h index bc58531a27..e5597ccc61 100644 --- a/dolphin/src/dolphinviewcontainer.h +++ b/dolphin/src/dolphinviewcontainer.h @@ -261,9 +261,21 @@ private slots: /** * Is connected with the URL navigator and drops the URLs * above the destination \a destination. + * + * Creates a copy of \a event and invokes \a dropUrlsDelayed with a + * queued connection. */ void dropUrls(const KUrl& destination, QDropEvent* event); + /** + * Is invoked with a queued connection by \a dropUrls to prevent that the + * drop actions are executed in the URL navigator menu's nested event loop, + * which might cause a crash. Simply using a queued connection from the URL + * navigator to \a dropUrls would not work because the \a event pointer + * would be dangling then. + */ + void dropUrlsDelayed(); + /** * Is invoked when a redirection is done and changes the * URL of the URL navigator to \a newUrl without triggering @@ -330,6 +342,9 @@ private: QElapsedTimer m_statusBarTimestamp; // Time in ms since last update bool m_autoGrabFocus; + KUrl m_dropDestination; + QScopedPointer m_dropEvent; + #ifdef KActivities_FOUND private: KActivities::ResourceInstance * m_activityResourceInstance;