From fd65a97b0787b23246c9392fdc34173fb604c9ca Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Wed, 9 Jan 2013 15:16:30 +0100 Subject: [PATCH] Fix Bug 233335 - Wrong icons selected after pasting files and renaming them (because there exists items with it's names Fixed the "same" buggy behavior when dropping files/folders Select also putted files (PUT operation - SimpleJob) - e.g. Paste content from clipboard BUG: 233335 REVIEW: 107351 --- dolphin/src/dolphinmainwindow.cpp | 3 +- dolphin/src/dolphinviewcontainer.cpp | 3 +- dolphin/src/panels/folders/folderspanel.cpp | 3 +- dolphin/src/panels/places/placespanel.cpp | 15 +++- dolphin/src/views/dolphinview.cpp | 32 ++++---- dolphin/src/views/dolphinview.h | 13 ++- dolphin/src/views/draganddrophelper.cpp | 16 ++-- dolphin/src/views/draganddrophelper.h | 11 ++- lib/konq/konq_operations.cpp | 87 ++++++++++++++++----- lib/konq/konq_operations.h | 14 ++++ 10 files changed, 138 insertions(+), 59 deletions(-) diff --git a/dolphin/src/dolphinmainwindow.cpp b/dolphin/src/dolphinmainwindow.cpp index 11e03d0f11..d72fb2305e 100644 --- a/dolphin/src/dolphinmainwindow.cpp +++ b/dolphin/src/dolphinmainwindow.cpp @@ -1276,7 +1276,8 @@ void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event) const ViewTab& viewTab = m_viewTab[tab]; const DolphinView* view = viewTab.isPrimaryViewActive ? viewTab.primaryView->view() : viewTab.secondaryView->view(); - const QString error = DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event); + QString error; + DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error); if (!error.isEmpty()) { activeViewContainer()->showMessage(error, DolphinViewContainer::Error); } diff --git a/dolphin/src/dolphinviewcontainer.cpp b/dolphin/src/dolphinviewcontainer.cpp index 26a6803ae0..b2c8605d89 100644 --- a/dolphin/src/dolphinviewcontainer.cpp +++ b/dolphin/src/dolphinviewcontainer.cpp @@ -620,7 +620,8 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url) void DolphinViewContainer::dropUrls(const KUrl& destination, QDropEvent* event) { - const QString error = DragAndDropHelper::dropUrls(KFileItem(), destination, event); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destination, event, error); if (!error.isEmpty()) { showMessage(error, Error); } diff --git a/dolphin/src/panels/folders/folderspanel.cpp b/dolphin/src/panels/folders/folderspanel.cpp index 6e3a7678f6..8ce853a2a8 100644 --- a/dolphin/src/panels/folders/folderspanel.cpp +++ b/dolphin/src/panels/folders/folderspanel.cpp @@ -236,7 +236,8 @@ void FoldersPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* eve event->buttons(), event->modifiers()); - const QString error = DragAndDropHelper::dropUrls(destItem, destItem.url(), &dropEvent); + QString error; + DragAndDropHelper::dropUrls(destItem, destItem.url(), &dropEvent, error); if (!error.isEmpty()) { emit errorMessage(error); } diff --git a/dolphin/src/panels/places/placespanel.cpp b/dolphin/src/panels/places/placespanel.cpp index 61c15a7a12..9f9306946c 100644 --- a/dolphin/src/panels/places/placespanel.cpp +++ b/dolphin/src/panels/places/placespanel.cpp @@ -352,7 +352,11 @@ void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even event->buttons(), event->modifiers()); - DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent, error); + if (!error.isEmpty()) { + emit errorMessage(error); + } } void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) @@ -364,7 +368,11 @@ void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) if (success) { KUrl destUrl = m_model->placesItem(index)->url(); - DragAndDropHelper::dropUrls(KFileItem(), destUrl, m_itemDropEvent); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destUrl, m_itemDropEvent, error); + if (!error.isEmpty()) { + emit errorMessage(error); + } } delete m_itemDropEventMimeData; @@ -384,7 +392,8 @@ void PlacesPanel::slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent) { Q_UNUSED(parent); - const QString error = DragAndDropHelper::dropUrls(KFileItem(), dest, event); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), dest, event, error); if (!error.isEmpty()) { emit errorMessage(error); } diff --git a/dolphin/src/views/dolphinview.cpp b/dolphin/src/views/dolphinview.cpp index f0fad1976e..9575ffba70 100644 --- a/dolphin/src/views/dolphinview.cpp +++ b/dolphin/src/views/dolphinview.cpp @@ -1023,14 +1023,16 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even event->buttons(), event->modifiers()); - const QString error = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent); + QString error; + KonqOperations* op = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent, error); if (!error.isEmpty()) { emit errorMessage(error); } - if (destUrl == url()) { + if (op && destUrl == url()) { // Mark the dropped urls as selected. - markPastedUrlsAsSelected(event->mimeData()); + m_clearSelectionBeforeSelectingNewItems = true; + connect(op, SIGNAL(urlPasted(KUrl)), this, SLOT(slotUrlPasted(KUrl))); } } @@ -1066,6 +1068,11 @@ void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons } } +void DolphinView::slotAboutToCreate(const KUrl::List& urls) +{ + m_selectedUrls << urls; +} + void DolphinView::slotSelectionChanged(const QSet& current, const QSet& previous) { const int currentCount = current.count(); @@ -1523,8 +1530,11 @@ void DolphinView::applyModeToView() void DolphinView::pasteToUrl(const KUrl& url) { - markPastedUrlsAsSelected(QApplication::clipboard()->mimeData()); - KonqOperations::doPaste(this, url); + KonqOperations* op = KonqOperations::doPasteV2(this, url); + if (op) { + m_clearSelectionBeforeSelectingNewItems = true; + connect(op, SIGNAL(aboutToCreate(KUrl::List)), this, SLOT(slotAboutToCreate(KUrl::List))); + } } KUrl::List DolphinView::simplifiedSelectedUrls() const @@ -1552,18 +1562,6 @@ QMimeData* DolphinView::selectionMimeData() const return m_model->createMimeData(selectedIndexes); } -void DolphinView::markPastedUrlsAsSelected(const QMimeData* mimeData) -{ - const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData); - KUrl::List destUrls; - foreach (const KUrl& source, sourceUrls) { - KUrl destination(url().url() + '/' + source.fileName()); - destUrls << destination; - } - markUrlsAsSelected(destUrls); - m_clearSelectionBeforeSelectingNewItems = true; -} - void DolphinView::updateWritableState() { const bool wasFolderWritable = m_isFolderWritable; diff --git a/dolphin/src/views/dolphinview.h b/dolphin/src/views/dolphinview.h index a2fe9f62a1..13cc665455 100644 --- a/dolphin/src/views/dolphinview.h +++ b/dolphin/src/views/dolphinview.h @@ -566,6 +566,11 @@ private slots: void slotModelChanged(KItemModelBase* current, KItemModelBase* previous); void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons); + /* + * Is called when new items get pasted or dropped. + */ + void slotAboutToCreate(const KUrl::List& urls); + /** * Emits the signal \a selectionChanged() with a small delay. This is * because getting all file items for the selection can be an expensive @@ -721,14 +726,6 @@ private: */ QMimeData* selectionMimeData() const; - /** - * Is invoked after a paste operation or a drag & drop - * operation and URLs from \a mimeData as selected. - * This allows to select all newly pasted - * items in restoreViewState(). - */ - void markPastedUrlsAsSelected(const QMimeData* mimeData); - /** * Updates m_isFolderWritable dependent on whether the folder represented by * the current URL is writable. If the state has changed, the signal diff --git a/dolphin/src/views/draganddrophelper.cpp b/dolphin/src/views/draganddrophelper.cpp index f81d4d0bfe..f8ae0ad034 100644 --- a/dolphin/src/views/draganddrophelper.cpp +++ b/dolphin/src/views/draganddrophelper.cpp @@ -28,10 +28,13 @@ #include #include -QString DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destUrl, QDropEvent* event) +KonqOperations* DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destUrl, QDropEvent* event, QString& error) { + error.clear(); + if (!destItem.isNull() && !destItem.isWritable()) { - return i18nc("@info:status", "Access denied. Could not write to %1", destUrl.pathOrUrl()); + error = i18nc("@info:status", "Access denied. Could not write to %1", destUrl.pathOrUrl()); + return 0; } const QMimeData* mimeData = event->mimeData(); @@ -49,15 +52,16 @@ QString DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destU const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); foreach (const KUrl& url, urls) { if (url == destUrl) { - return i18nc("@info:status", "A folder cannot be dropped into itself"); + error = i18nc("@info:status", "A folder cannot be dropped into itself"); + return 0; } } - KonqOperations::doDrop(destItem, destUrl, event, QApplication::activeWindow()); + return KonqOperations::doDrop(destItem, destUrl, event, QApplication::activeWindow(), QList()); } else { - KonqOperations::doDrop(KFileItem(), destUrl, event, QApplication::activeWindow()); + return KonqOperations::doDrop(KFileItem(), destUrl, event, QApplication::activeWindow(), QList()); } - return QString(); + return 0; } diff --git a/dolphin/src/views/draganddrophelper.h b/dolphin/src/views/draganddrophelper.h index ac16f7cf27..eda5fc5c26 100644 --- a/dolphin/src/views/draganddrophelper.h +++ b/dolphin/src/views/draganddrophelper.h @@ -29,6 +29,7 @@ class KFileItem; class KUrl; class QDropEvent; class QWidget; +class KonqOperations; class LIBDOLPHINPRIVATE_EXPORT DragAndDropHelper { @@ -46,13 +47,15 @@ public: * @param destUrl URL of the item destination. Is used only if destItem::isNull() * is true. * @param event Drop event. - * @return Error message intended to be shown for users if dropping is not + * @param error Error message intended to be shown for users if dropping is not * possible. If an empty string is returned, the dropping has been * successful. + * @return KonqOperations pointer */ - static QString dropUrls(const KFileItem& destItem, - const KUrl& destUrl, - QDropEvent* event); + static KonqOperations* dropUrls(const KFileItem& destItem, + const KUrl& destUrl, + QDropEvent* event, + QString& error); }; #endif diff --git a/lib/konq/konq_operations.cpp b/lib/konq/konq_operations.cpp index e0f1ade458..fd2b58a112 100644 --- a/lib/konq/konq_operations.cpp +++ b/lib/konq/konq_operations.cpp @@ -133,25 +133,37 @@ KIO::SimpleJob* KonqOperations::mkdir( QWidget *parent, const KUrl & url ) void KonqOperations::doPaste( QWidget * parent, const KUrl & destUrl, const QPoint &pos ) { - QClipboard* clipboard = QApplication::clipboard(); + (void) KonqOperations::doPasteV2( parent, destUrl, pos ); +} + +KonqOperations *KonqOperations::doPasteV2(QWidget *parent, const KUrl &destUrl, const QPoint &pos) +{ + QClipboard *clipboard = QApplication::clipboard(); const QMimeData *data = clipboard->mimeData(); const bool move = KonqMimeData::decodeIsCutSelection(data); - KIO::Job *job = KIO::pasteClipboard( destUrl, parent, move ); + KIO::Job *job = KIO::pasteClipboard(destUrl, parent, move); if (job) { - KonqOperations * op = new KonqOperations( parent ); - KIOPasteInfo * pi = new KIOPasteInfo; + KonqOperations *op = new KonqOperations(parent); + KIOPasteInfo *pi = new KIOPasteInfo; pi->mousePos = pos; - op->setPasteInfo( pi ); - KIO::CopyJob * copyJob = qobject_cast(job); + op->setPasteInfo(pi); + KIO::CopyJob *copyJob = qobject_cast(job); if (copyJob) { - op->setOperation( job, move ? MOVE : COPY, copyJob->destUrl() ); - KIO::FileUndoManager::self()->recordJob( move ? KIO::FileUndoManager::Move : KIO::FileUndoManager::Copy, KUrl::List(), destUrl, job ); - } else if (KIO::SimpleJob* simpleJob = qobject_cast(job)) { + op->setOperation(job, move ? MOVE : COPY, copyJob->destUrl()); + KIO::FileUndoManager::self()->recordJob(move ? KIO::FileUndoManager::Move : KIO::FileUndoManager::Copy, KUrl::List(), destUrl, job); + connect(copyJob, SIGNAL(copyingDone(KIO::Job*,KUrl,KUrl,time_t,bool,bool)), + op, SLOT(slotCopyingDone(KIO::Job*,KUrl,KUrl))); + connect(copyJob, SIGNAL(copyingLinkDone(KIO::Job*,KUrl,QString,KUrl)), + op, SLOT(slotCopyingLinkDone(KIO::Job*,KUrl,QString,KUrl))); + } else if (KIO::SimpleJob *simpleJob = qobject_cast(job)) { op->setOperation(job, PUT, simpleJob->url()); KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Put, KUrl::List(), simpleJob->url(), job); } + return op; } + + return 0; } void KonqOperations::copy( QWidget * parent, Operation method, const KUrl::List & selectedUrls, const KUrl& destUrl ) @@ -177,6 +189,11 @@ void KonqOperations::copy( QWidget * parent, Operation method, const KUrl::List else job = KIO::copy( selectedUrls, destUrl ); + connect(job, SIGNAL(copyingDone(KIO::Job*,KUrl,KUrl,time_t,bool,bool)), + op, SLOT(slotCopyingDone(KIO::Job*,KUrl,KUrl))); + connect(job, SIGNAL(copyingLinkDone(KIO::Job*,KUrl,QString,KUrl)), + op, SLOT(slotCopyingLinkDone(KIO::Job*,KUrl,QString,KUrl))); + op->setOperation( job, method, destUrl ); KIO::FileUndoManager::self()->recordCopyJob(job); @@ -635,25 +652,42 @@ void KonqOperations::doDropFileCopy() KIO::FileUndoManager::self()->recordJob( m_method == TRASH ? KIO::FileUndoManager::Trash : KIO::FileUndoManager::Move, lst, m_destUrl, job ); - return; // we still have stuff to do -> don't delete ourselves + break; case Qt::CopyAction : job = KIO::copy( lst, m_destUrl ); job->setMetaData( m_info->metaData ); setOperation( job, COPY, m_destUrl ); KIO::FileUndoManager::self()->recordCopyJob(job); - return; + break; case Qt::LinkAction : kDebug(1203) << "lst.count=" << lst.count(); job = KIO::link( lst, m_destUrl ); job->setMetaData( m_info->metaData ); setOperation( job, LINK, m_destUrl ); KIO::FileUndoManager::self()->recordCopyJob(job); - return; + break; default : kError(1203) << "Unknown action " << (int)action << endl; } + if (job) { + connect(job, SIGNAL(copyingDone(KIO::Job*,KUrl,KUrl,time_t,bool,bool)), + this, SLOT(slotCopyingDone(KIO::Job*,KUrl,KUrl))); + connect(job, SIGNAL(copyingLinkDone(KIO::Job*,KUrl,QString,KUrl)), + this, SLOT(slotCopyingLinkDone(KIO::Job*,KUrl,QString,KUrl))); + return; // we still have stuff to do -> don't delete ourselves + } deleteLater(); } +void KonqOperations::slotCopyingDone( KIO::Job*, const KUrl&, const KUrl &to) +{ + m_createdUrls << to; +} + +void KonqOperations::slotCopyingLinkDone(KIO::Job*, const KUrl&, const QString&, const KUrl &to) +{ + m_createdUrls << to; +} + void KonqOperations::_addPluginActions(QList& pluginActions,const KUrl& destination, const KFileItemListProperties& info) { kDebug(1203); @@ -803,16 +837,33 @@ void KonqOperations::slotStatResult( KJob * job ) deleteLater(); } -void KonqOperations::slotResult( KJob * job ) +void KonqOperations::slotResult(KJob *job) { - if (job && job->error()) - { - static_cast( job )->ui()->showErrorMessage(); + if (job && job->error()) { + static_cast(job)->ui()->showErrorMessage(); + job = 0; // The job failed, so set it to 0. All further job related codepaths become disabled } - if ( m_method == EMPTYTRASH ) { + + switch (m_method) { + case PUT: { + KIO::SimpleJob *simpleJob = qobject_cast(job); + if (simpleJob) { + m_createdUrls << simpleJob->url(); + } + } + break; + case EMPTYTRASH: // Update konq windows opened on trash:/ - org::kde::KDirNotify::emitFilesAdded( "trash:/" ); // yeah, files were removed, but we don't know which ones... + org::kde::KDirNotify::emitFilesAdded("trash:/"); // yeah, files were removed, but we don't know which ones... + break; } + + if (!m_createdUrls.isEmpty()) { + // Inform the application about all created urls + emit aboutToCreate(m_createdUrls); + m_createdUrls.clear(); + } + deleteLater(); } diff --git a/lib/konq/konq_operations.h b/lib/konq/konq_operations.h index b82feb4e11..a9aec89800 100644 --- a/lib/konq/konq_operations.h +++ b/lib/konq/konq_operations.h @@ -118,6 +118,16 @@ public: */ static void doPaste( QWidget * parent, const KUrl & destUrl, const QPoint &pos = QPoint() ); + /** + * Paste the clipboard contents + * + * @return The KonqOperations object + * @since 4.10 + * + * @todo TODO KDE 5,0 - Merge doPaste and doPasteV2 + */ + static KonqOperations *doPasteV2(QWidget * parent, const KUrl & destUrl, const QPoint &pos = QPoint()); + /** * Returns the state of the paste action: * first is whether the action should be enabled @@ -218,6 +228,7 @@ public: Q_SIGNALS: void statFinished( const KFileItem & item ); void aboutToCreate(const QPoint &pos, const QList &files); + void aboutToCreate(const KUrl::List &urls); private: QWidget* parentWidget() const; @@ -259,10 +270,13 @@ protected Q_SLOTS: void slotStatResult( KJob * job ); void asyncDrop( const KFileItem & item ); void doDropFileCopy(); + void slotCopyingDone(KIO::Job *job, const KUrl &from, const KUrl &to); + void slotCopyingLinkDone(KIO::Job *job, const KUrl &from, const QString &target, const KUrl &to); private: Operation m_method; //KUrl::List m_srcUrls; + KUrl::List m_createdUrls; KUrl m_destUrl; // for doDrop DropInfo * m_info;