]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
Fix renamed file reclaims focus
[dolphin.git] / src / views / dolphinview.cpp
index 4105628ee1d2b9f220eaff355dc2b6d8a0ea2741..e40e49d6e4a755c3032b650d8197feb754527f2b 100644 (file)
@@ -29,6 +29,7 @@
 #include <QGraphicsSceneDragDropEvent>
 #include <QTimer>
 #include <QScrollBar>
+#include <QPixmapCache>
 #include <QPointer>
 #include <QMenu>
 #include <QVBoxLayout>
@@ -86,19 +87,20 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
     m_viewPropertiesContext(),
     m_mode(DolphinView::IconsView),
     m_visibleRoles(),
-    m_topLayout(0),
-    m_model(0),
-    m_view(0),
-    m_container(0),
-    m_toolTipManager(0),
-    m_selectionChangedTimer(0),
+    m_topLayout(nullptr),
+    m_model(nullptr),
+    m_view(nullptr),
+    m_container(nullptr),
+    m_toolTipManager(nullptr),
+    m_selectionChangedTimer(nullptr),
     m_currentItemUrl(),
     m_scrollToCurrentItem(false),
     m_restoredContentsPosition(),
     m_selectedUrls(),
     m_clearSelectionBeforeSelectingNewItems(false),
     m_markFirstNewlySelectedItemAsCurrent(false),
-    m_versionControlObserver(0)
+    m_versionControlObserver(nullptr),
+    m_twoClicksRenamingTimer(nullptr)
 {
     m_topLayout = new QVBoxLayout(this);
     m_topLayout->setSpacing(0);
@@ -149,6 +151,7 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
     connect(controller, &KItemListController::itemDropEvent, this, &DolphinView::slotItemDropEvent);
     connect(controller, &KItemListController::escapePressed, this, &DolphinView::stopLoading);
     connect(controller, &KItemListController::modelChanged, this, &DolphinView::slotModelChanged);
+    connect(controller, &KItemListController::selectedItemTextPressed, this, &DolphinView::slotSelectedItemTextPressed);
 
     connect(m_model, &KFileItemModel::directoryLoadingStarted,       this, &DolphinView::slotDirectoryLoadingStarted);
     connect(m_model, &KFileItemModel::directoryLoadingCompleted,     this, &DolphinView::slotDirectoryLoadingCompleted);
@@ -181,6 +184,7 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
             this, &DolphinView::slotSelectionChanged);
 
     m_toolTipManager = new ToolTipManager(this);
+    connect(m_toolTipManager, &ToolTipManager::urlActivated, this, &DolphinView::urlActivated);
 
     m_versionControlObserver = new VersionControlObserver(this);
     m_versionControlObserver->setModel(m_model);
@@ -188,6 +192,10 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
     connect(m_versionControlObserver, &VersionControlObserver::errorMessage, this, &DolphinView::errorMessage);
     connect(m_versionControlObserver, &VersionControlObserver::operationCompletedMessage, this, &DolphinView::operationCompletedMessage);
 
+    m_twoClicksRenamingTimer = new QTimer(this);
+    m_twoClicksRenamingTimer->setSingleShot(true);
+    connect(m_twoClicksRenamingTimer, &QTimer::timeout, this, &DolphinView::slotTwoClicksRenamingTimerTimeout);
+
     applyViewProperties();
     m_topLayout->addWidget(m_container);
 
@@ -211,19 +219,7 @@ void DolphinView::setActive(bool active)
 
     m_active = active;
 
-    QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
-    if (!active) {
-        color.setAlpha(150);
-    }
-
-    QWidget* viewport = m_container->viewport();
-    if (viewport) {
-        QPalette palette;
-        palette.setColor(viewport->backgroundRole(), color);
-        viewport->setPalette(palette);
-    }
-
-    update();
+    updatePalette();
 
     if (active) {
         m_container->setFocus();
@@ -465,10 +461,6 @@ void DolphinView::reload()
     QDataStream saveStream(&viewState, QIODevice::WriteOnly);
     saveState(saveStream);
 
-    const KFileItemList itemList = selectedItems();
-    m_selectedUrls.clear();
-    m_selectedUrls = itemList.urlList();
-
     setUrl(url());
     loadDirectory(url(), true);
 
@@ -596,7 +588,6 @@ void DolphinView::setUrl(const QUrl& url)
 
     clearSelection();
 
-    emit urlAboutToBeChanged(url);
     m_url = url;
 
     hideToolTip();
@@ -650,6 +641,9 @@ void DolphinView::renameSelectedItems()
                 this, &DolphinView::slotRoleEditingFinished);
     } else {
         RenameDialog* dialog = new RenameDialog(this, items);
+
+        connect(dialog, &RenameDialog::renamingFinished, this, &DolphinView::slotRenameDialogRenamingFinished);
+
         dialog->setAttribute(Qt::WA_DeleteOnClose);
         dialog->show();
         dialog->raise();
@@ -721,14 +715,42 @@ void DolphinView::stopLoading()
     m_model->cancelDirectoryLoading();
 }
 
+void DolphinView::updatePalette()
+{
+    QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
+    if (!m_active) {
+        color.setAlpha(150);
+    }
+
+    QWidget* viewport = m_container->viewport();
+    if (viewport) {
+        QPalette palette;
+        palette.setColor(viewport->backgroundRole(), color);
+        viewport->setPalette(palette);
+    }
+
+    update();
+}
+
+void DolphinView::abortTwoClicksRenaming()
+{
+    m_twoClicksRenamingItemUrl.clear();
+    m_twoClicksRenamingTimer->stop();
+}
+
 bool DolphinView::eventFilter(QObject* watched, QEvent* event)
 {
     switch (event->type()) {
+    case QEvent::PaletteChange:
+        updatePalette();
+        QPixmapCache::clear();
+        break;
+
     case QEvent::KeyPress:
         if (GeneralSettings::useTabForSwitchingSplitView()) {
             QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
             if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) {
-                toggleActiveViewRequested();
+                emit toggleActiveViewRequested();
                 return true;
             }
         }
@@ -783,13 +805,14 @@ void DolphinView::hideEvent(QHideEvent* event)
 
 bool DolphinView::event(QEvent* event)
 {
-    /* See Bug 297355
-     * Dolphin leaves file preview tooltips open even when is not visible.
-     *
-     * Hide tool-tip when Dolphin loses focus.
-     */
     if (event->type() == QEvent::WindowDeactivate) {
+        /* See Bug 297355
+         * Dolphin leaves file preview tooltips open even when is not visible.
+         *
+         * Hide tool-tip when Dolphin loses focus.
+         */
         hideToolTip();
+        abortTwoClicksRenaming();
     }
 
     return QWidget::event(event);
@@ -802,6 +825,8 @@ void DolphinView::activate()
 
 void DolphinView::slotItemActivated(int index)
 {
+    abortTwoClicksRenaming();
+
     const KFileItem item = m_model->fileItem(index);
     if (!item.isNull()) {
         emit itemActivated(item);
@@ -812,6 +837,8 @@ void DolphinView::slotItemsActivated(const KItemSet& indexes)
 {
     Q_ASSERT(indexes.count() >= 2);
 
+    abortTwoClicksRenaming();
+
     if (indexes.count() > 5) {
         QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
         const int answer = KMessageBox::warningYesNo(this, question);
@@ -885,7 +912,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
 #endif
 
     QString groupName;
-    QMenu* groupMenu = 0;
+    QMenu* groupMenu = nullptr;
 
     // Add all roles to the menu that can be shown or hidden by the user
     const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
@@ -896,7 +923,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
         }
 
         const QString text = m_model->roleDescription(info.role);
-        QAction* action = 0;
+        QAction* action = nullptr;
         if (info.group.isEmpty()) {
             action = menu->addAction(text);
         } else {
@@ -1012,7 +1039,7 @@ void DolphinView::slotItemHovered(int index)
         const QPoint pos = m_container->mapToGlobal(itemRect.topLeft().toPoint());
         itemRect.moveTo(pos);
 
-        m_toolTipManager->showToolTip(item, itemRect);
+        m_toolTipManager->showToolTip(item, itemRect, nativeParentWidget()->windowHandle());
     }
 
     emit requestItemInfo(item);
@@ -1044,14 +1071,14 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even
                          event->mimeData(),
                          event->buttons(),
                          event->modifiers());
-    dropUrls(destUrl, &dropEvent);
+    dropUrls(destUrl, &dropEvent, this);
 
     setActive(true);
 }
 
-void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent)
+void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget *dropWidget)
 {
-    KIO::DropJob* job = DragAndDropHelper::dropUrls(destUrl, dropEvent, this);
+    KIO::DropJob* job = DragAndDropHelper::dropUrls(destUrl, dropEvent, dropWidget);
 
     if (job) {
         connect(job, &KIO::DropJob::result, this, &DolphinView::slotPasteJobResult);
@@ -1067,11 +1094,11 @@ void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent)
 
 void DolphinView::slotModelChanged(KItemModelBase* current, KItemModelBase* previous)
 {
-    if (previous != 0) {
+    if (previous != nullptr) {
         Q_ASSERT(qobject_cast<KFileItemModel*>(previous));
         KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(previous);
         disconnect(fileItemModel, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted);
-        m_versionControlObserver->setModel(0);
+        m_versionControlObserver->setModel(nullptr);
     }
 
     if (current) {
@@ -1095,6 +1122,18 @@ void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons
     }
 }
 
+void DolphinView::slotSelectedItemTextPressed(int index)
+{
+    if (GeneralSettings::renameInline()) {
+        const KFileItem item = m_model->fileItem(index);
+        const KFileItemListProperties capabilities(KFileItemList() << item);
+        if (capabilities.supportsMoving()) {
+            m_twoClicksRenamingItemUrl = item.url();
+            m_twoClicksRenamingTimer->start(QApplication::doubleClickInterval());
+        }
+    }
+}
+
 void DolphinView::slotItemCreated(const QUrl& url)
 {
     if (m_markFirstNewlySelectedItemAsCurrent) {
@@ -1201,6 +1240,9 @@ void DolphinView::restoreState(QDataStream& stream)
     // Restore the current item that had the keyboard focus
     stream >> m_currentItemUrl;
 
+    // Restore the previously selected items
+    stream >> m_selectedUrls;
+
     // Restore the view position
     stream >> m_restoredContentsPosition;
 
@@ -1225,6 +1267,9 @@ void DolphinView::saveState(QDataStream& stream)
         stream << QUrl();
     }
 
+    // Save the selected urls
+    stream << selectedItems().urlList();
+
     // Save view position
     const qreal x = m_container->horizontalScrollBar()->value();
     const qreal y = m_container->verticalScrollBar()->value();
@@ -1295,9 +1340,7 @@ QUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseTh
 void DolphinView::observeCreatedItem(const QUrl& url)
 {
     if (m_active) {
-        clearSelection();
-        markUrlAsCurrent(url);
-        markUrlsAsSelected({url});
+        forceUrlsSelection(url, {url});
     }
 }
 
@@ -1313,17 +1356,21 @@ void DolphinView::updateViewState()
 {
     if (m_currentItemUrl != QUrl()) {
         KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
-        const int currentIndex = m_model->index(m_currentItemUrl);
-        if (currentIndex != -1) {
-            selectionManager->setCurrentItem(currentIndex);
-
-            // scroll to current item and reset the state
-            if (m_scrollToCurrentItem) {
-                m_view->scrollToItem(currentIndex);
-                m_scrollToCurrentItem = false;
+
+        // if there is a selection already, leave it that way
+        if (!selectionManager->hasSelection()) {
+            const int currentIndex = m_model->index(m_currentItemUrl);
+            if (currentIndex != -1) {
+                selectionManager->setCurrentItem(currentIndex);
+
+                // scroll to current item and reset the state
+                if (m_scrollToCurrentItem) {
+                    m_view->scrollToItem(currentIndex);
+                    m_scrollToCurrentItem = false;
+                }
+            } else {
+                selectionManager->setCurrentItem(0);
             }
-        } else {
-            selectionManager->setCurrentItem(0);
         }
 
         m_currentItemUrl = QUrl();
@@ -1341,25 +1388,29 @@ void DolphinView::updateViewState()
     if (!m_selectedUrls.isEmpty()) {
         KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
 
-        if (m_clearSelectionBeforeSelectingNewItems) {
-            selectionManager->clearSelection();
-            m_clearSelectionBeforeSelectingNewItems = false;
-        }
+        // if there is a selection already, leave it that way
+        if (!selectionManager->hasSelection()) {
+            if (m_clearSelectionBeforeSelectingNewItems) {
+                selectionManager->clearSelection();
+                m_clearSelectionBeforeSelectingNewItems = false;
+            }
 
-        KItemSet selectedItems = selectionManager->selectedItems();
+            KItemSet selectedItems = selectionManager->selectedItems();
 
-        QList<QUrl>::iterator it = m_selectedUrls.begin();
-        while (it != m_selectedUrls.end()) {
-            const int index = m_model->index(*it);
-            if (index >= 0) {
-                selectedItems.insert(index);
-                it = m_selectedUrls.erase(it);
-            } else {
-                 ++it;
+            QList<QUrl>::iterator it = m_selectedUrls.begin();
+            while (it != m_selectedUrls.end()) {
+                const int index = m_model->index(*it);
+                if (index >= 0) {
+                    selectedItems.insert(index);
+                    it = m_selectedUrls.erase(it);
+                } else {
+                    ++it;
+                }
             }
-        }
 
-        selectionManager->setSelectedItems(selectedItems);
+            selectionManager->beginAnchoredSelection(selectionManager->currentItem());
+            selectionManager->setSelectedItems(selectedItems);
+        }
     }
 }
 
@@ -1386,6 +1437,22 @@ void DolphinView::calculateItemCount(int& fileCount,
     }
 }
 
+void DolphinView::slotTwoClicksRenamingTimerTimeout()
+{
+    const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
+
+    // verify that only one item is selected and that no item is dragged
+    if (selectionManager->selectedItems().count() == 1 && !m_dragging) {
+        const int index = selectionManager->currentItem();
+        const QUrl fileItemUrl = m_model->fileItem(index).url();
+
+        // check if the selected item was the same item that started the twoClicksRenaming
+        if (fileItemUrl.isValid() && m_twoClicksRenamingItemUrl == fileItemUrl) {
+            renameSelectedItems();
+        }
+    }
+}
+
 void DolphinView::slotTrashFileFinished(KJob* job)
 {
     if (job->error() == 0) {
@@ -1525,7 +1592,9 @@ void DolphinView::slotRoleEditingFinished(int index, const QByteArray& role, con
             KIO::Job * job = KIO::moveAs(oldUrl, newUrl);
             KJobWidgets::setWindow(job, this);
             KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job);
-            job->ui()->setAutoErrorHandlingEnabled(true);
+            job->uiDelegate()->setAutoErrorHandlingEnabled(true);
+
+            forceUrlsSelection(newUrl, {newUrl});
 
             if (!newNameExistsAlready) {
                 // Only connect the result signal if there is no item with the new name
@@ -1733,3 +1802,16 @@ QUrl DolphinView::viewPropertiesUrl() const
     url.setPath(m_viewPropertiesContext);
     return url;
 }
+
+void DolphinView::slotRenameDialogRenamingFinished(const QList<QUrl>& urls)
+{
+    forceUrlsSelection(urls.first(), urls);
+}
+
+void DolphinView::forceUrlsSelection(const QUrl& current, const QList<QUrl>& selected)
+{
+    clearSelection();
+    m_clearSelectionBeforeSelectingNewItems = true;
+    markUrlAsCurrent(current);
+    markUrlsAsSelected(selected);
+}