X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/7f4c3976c0626657362b6324c0dad2867cc24e9b..30bf49d5d1539e9d02944230cf4489ebbccf5a45:/src/views/dolphinview.cpp diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 4129cc217..48f41bb0e 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -20,66 +20,54 @@ #include "dolphinview.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dolphinnewfilemenuobserver.h" #include "dolphin_detailsmodesettings.h" #include "dolphin_generalsettings.h" #include "dolphinitemlistview.h" +#include "dolphinnewfilemenuobserver.h" #include "draganddrophelper.h" +#include "kitemviews/kfileitemlistview.h" +#include "kitemviews/kfileitemmodel.h" +#include "kitemviews/kitemlistcontainer.h" +#include "kitemviews/kitemlistcontroller.h" +#include "kitemviews/kitemlistheader.h" +#include "kitemviews/kitemlistselectionmanager.h" #include "renamedialog.h" #include "versioncontrol/versioncontrolobserver.h" -#include "viewmodecontroller.h" #include "viewproperties.h" #include "views/tooltips/tooltipmanager.h" #include "zoomlevelinfo.h" #ifdef HAVE_BALOO - #include +#include #endif +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -namespace { - const int MaxModeEnum = DolphinView::CompactView; -}; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include DolphinView::DolphinView(const QUrl& url, QWidget* parent) : QWidget(parent), @@ -92,19 +80,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); @@ -155,6 +144,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); @@ -179,14 +169,17 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) : this, &DolphinView::slotVisibleRolesChangedByHeader); connect(m_view, &DolphinItemListView::roleEditingCanceled, this, &DolphinView::slotRoleEditingCanceled); - connect(m_view->header(), &KItemListHeader::columnWidthChanged, - this, &DolphinView::slotHeaderColumnWidthChanged); + connect(m_view->header(), &KItemListHeader::columnWidthChangeFinished, + this, &DolphinView::slotHeaderColumnWidthChangeFinished); KItemListSelectionManager* selectionManager = controller->selectionManager(); connect(selectionManager, &KItemListSelectionManager::selectionChanged, this, &DolphinView::slotSelectionChanged); +#ifdef HAVE_BALOO m_toolTipManager = new ToolTipManager(this); + connect(m_toolTipManager, &ToolTipManager::urlActivated, this, &DolphinView::urlActivated); +#endif m_versionControlObserver = new VersionControlObserver(this); m_versionControlObserver->setModel(m_model); @@ -194,6 +187,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); @@ -217,19 +214,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(); @@ -351,7 +336,9 @@ KFileItemList DolphinView::selectedItems() const const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); KFileItemList selectedItems; - foreach (int index, selectionManager->selectedItems()) { + const auto items = selectionManager->selectedItems(); + selectedItems.reserve(items.count()); + for (int index : items) { selectedItems.append(m_model->fileItem(index)); } return selectedItems; @@ -469,10 +456,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); @@ -600,7 +583,6 @@ void DolphinView::setUrl(const QUrl& url) clearSelection(); - emit urlAboutToBeChanged(url); m_url = url; hideToolTip(); @@ -654,7 +636,8 @@ void DolphinView::renameSelectedItems() this, &DolphinView::slotRoleEditingFinished); } else { RenameDialog* dialog = new RenameDialog(this, items); - dialog->setAttribute(Qt::WA_DeleteOnClose); + connect(dialog, &RenameDialog::renamingFinished, this, &DolphinView::slotRenameDialogRenamingFinished); + dialog->show(); dialog->raise(); dialog->activateWindow(); @@ -673,7 +656,7 @@ void DolphinView::trashSelectedItems() uiDelegate.setWindow(window()); if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) { KIO::Job* job = KIO::trash(list); - KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, list, QUrl("trash:/"), job); + KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, list, QUrl(QStringLiteral("trash:/")), job); KJobWidgets::setWindow(job, this); connect(job, &KIO::Job::result, this, &DolphinView::slotTrashFileFinished); @@ -725,9 +708,46 @@ 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(event); + if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) { + emit toggleActiveViewRequested(); + return true; + } + } + break; case QEvent::FocusIn: if (watched == m_container) { setActive(true); @@ -737,6 +757,7 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) case QEvent::GraphicsSceneDragEnter: if (watched == m_view) { m_dragging = true; + abortTwoClicksRenaming(); } break; @@ -778,13 +799,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); @@ -797,6 +819,8 @@ void DolphinView::activate() void DolphinView::slotItemActivated(int index) { + abortTwoClicksRenaming(); + const KFileItem item = m_model->fileItem(index); if (!item.isNull()) { emit itemActivated(item); @@ -807,6 +831,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); @@ -818,7 +844,7 @@ void DolphinView::slotItemsActivated(const KItemSet& indexes) KFileItemList items; items.reserve(indexes.count()); - foreach (int index, indexes) { + for (int index : indexes) { KFileItem item = m_model->fileItem(index); const QUrl& url = openItemAsFolderUrl(item); @@ -880,7 +906,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 rolesInfo = KFileItemModel::rolesInformation(); @@ -891,7 +917,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 { @@ -941,6 +967,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) // Apply the current column-widths as custom column-widths and turn // off the automatic resizing of the columns QList columnWidths; + columnWidths.reserve(view->visibleRoles().count()); foreach (const QByteArray& role, view->visibleRoles()) { columnWidths.append(header->columnWidth(role)); } @@ -962,6 +989,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) QList columnWidths; if (!header->automaticColumnResizing()) { + columnWidths.reserve(view->visibleRoles().count()); foreach (const QByteArray& role, view->visibleRoles()) { columnWidths.append(header->columnWidth(role)); } @@ -973,10 +1001,8 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) delete menu; } -void DolphinView::slotHeaderColumnWidthChanged(const QByteArray& role, qreal current, qreal previous) +void DolphinView::slotHeaderColumnWidthChangeFinished(const QByteArray& role, qreal current) { - Q_UNUSED(previous); - const QList visibleRoles = m_view->visibleRoles(); ViewProperties props(viewPropertiesUrl()); @@ -1007,7 +1033,9 @@ void DolphinView::slotItemHovered(int index) const QPoint pos = m_container->mapToGlobal(itemRect.topLeft().toPoint()); itemRect.moveTo(pos); - m_toolTipManager->showToolTip(item, itemRect); +#ifdef HAVE_BALOO + m_toolTipManager->showToolTip(item, itemRect, nativeParentWidget()->windowHandle()); +#endif } emit requestItemInfo(item); @@ -1031,7 +1059,7 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even destUrl = url(); } else { // The item represents a directory or desktop-file - destUrl = destItem.url(); + destUrl = destItem.mostLocalUrl(); } QDropEvent dropEvent(event->pos().toPoint(), @@ -1039,14 +1067,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); @@ -1062,11 +1090,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(previous)); KFileItemModel* fileItemModel = static_cast(previous); disconnect(fileItemModel, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted); - m_versionControlObserver->setModel(0); + m_versionControlObserver->setModel(nullptr); } if (current) { @@ -1090,6 +1118,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) { @@ -1196,6 +1236,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; @@ -1220,6 +1263,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(); @@ -1278,7 +1324,7 @@ QUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseTh if (desktopFile.hasLinkType()) { const QString linkUrl = desktopFile.readUrl(); if (!linkUrl.startsWith(QLatin1String("http"))) { - return linkUrl; + return QUrl::fromUserInput(linkUrl); } } } @@ -1290,9 +1336,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}); } } @@ -1308,17 +1352,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(); @@ -1336,33 +1384,39 @@ 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::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::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); + } } } void DolphinView::hideToolTip() { +#ifdef HAVE_BALOO if (GeneralSettings::showToolTips()) { m_toolTipManager->hideToolTip(); } +#endif } void DolphinView::calculateItemCount(int& fileCount, @@ -1381,6 +1435,22 @@ void DolphinView::calculateItemCount(int& fileCount, } } +void DolphinView::slotTwoClicksRenamingTimerTimeout() +{ + const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); + + // verify that only one item is selected + if (selectionManager->selectedItems().count() == 1) { + 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) { @@ -1408,7 +1478,7 @@ void DolphinView::slotRenamingResult(KJob* job) const int index = m_model->index(newUrl); if (index >= 0) { QHash data; - const QUrl oldUrl = copyJob->srcUrls().first(); + const QUrl oldUrl = copyJob->srcUrls().at(0); data.insert("text", oldUrl.fileName()); m_model->setData(index, data); } @@ -1431,7 +1501,7 @@ void DolphinView::slotDirectoryLoadingCompleted() { // Update the view-state. This has to be done asynchronously // because the view might not be in its final state yet. - QTimer::singleShot(0, this, SLOT(updateViewState())); + QTimer::singleShot(0, this, &DolphinView::updateViewState); emit directoryLoadingCompleted(); @@ -1520,7 +1590,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 @@ -1675,6 +1747,7 @@ QList DolphinView::simplifiedSelectedUrls() const QList urls; const KFileItemList items = selectedItems(); + urls.reserve(items.count()); foreach (const KFileItem& item, items) { urls.append(item.url()); } @@ -1727,3 +1800,16 @@ QUrl DolphinView::viewPropertiesUrl() const url.setPath(m_viewPropertiesContext); return url; } + +void DolphinView::slotRenameDialogRenamingFinished(const QList& urls) +{ + forceUrlsSelection(urls.first(), urls); +} + +void DolphinView::forceUrlsSelection(const QUrl& current, const QList& selected) +{ + clearSelection(); + m_clearSelectionBeforeSelectingNewItems = true; + markUrlAsCurrent(current); + markUrlsAsSelected(selected); +}