X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/b7fa85a33d6b5c1b2a5b60b64a78f7f208ea304c..aded2d716d7cd154c757dcfd7ef8618ce7ca030a:/src/views/dolphinview.cpp diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 18d2137e3..13c8b4df2 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -78,6 +78,7 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent) , m_assureVisibleCurrentIndex(false) , m_isFolderWritable(true) , m_dragging(false) + , m_selectNextItem(false) , m_url(url) , m_viewPropertiesContext() , m_mode(DolphinView::IconsView) @@ -87,11 +88,11 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent) , m_view(nullptr) , m_container(nullptr) , m_toolTipManager(nullptr) - , m_selectNextItem(false) , m_selectionChangedTimer(nullptr) , m_currentItemUrl() , m_scrollToCurrentItem(false) , m_restoredContentsPosition() + , m_controlWheelAccumulatedDelta(0) , m_selectedUrls() , m_clearSelectionBeforeSelectingNewItems(false) , m_markFirstNewlySelectedItemAsCurrent(false) @@ -210,6 +211,13 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent) connect(m_view, &DolphinItemListView::sortRoleChanged, this, &DolphinView::slotSortRoleChangedByHeader); connect(m_view, &DolphinItemListView::visibleRolesChanged, this, &DolphinView::slotVisibleRolesChangedByHeader); connect(m_view, &DolphinItemListView::roleEditingCanceled, this, &DolphinView::slotRoleEditingCanceled); + + connect(m_view, &DolphinItemListView::columnHovered, this, [this](int columnIndex) { + m_hoveredColumnHeaderIndex = columnIndex; + }); + connect(m_view, &DolphinItemListView::columnUnHovered, this, [this](int /* columnIndex */) { + m_hoveredColumnHeaderIndex = std::nullopt; + }); connect(m_view->header(), &KItemListHeader::columnWidthChangeFinished, this, &DolphinView::slotHeaderColumnWidthChangeFinished); connect(m_view->header(), &KItemListHeader::sidePaddingChanged, this, &DolphinView::slotSidePaddingWidthChanged); @@ -292,7 +300,9 @@ DolphinView::Mode DolphinView::viewMode() const void DolphinView::setSelectionModeEnabled(const bool enabled) { if (enabled) { - m_proxyStyle = std::make_unique(); + if (!m_proxyStyle) { + m_proxyStyle = std::make_unique(); + } setStyle(m_proxyStyle.get()); m_view->setStyle(m_proxyStyle.get()); m_view->setEnabledSelectionToggles(DolphinItemListView::SelectionTogglesEnabled::False); @@ -415,6 +425,7 @@ int DolphinView::selectedItemsCount() const void DolphinView::markUrlsAsSelected(const QList &urls) { m_selectedUrls = urls; + m_selectJobCreatedItems = false; } void DolphinView::markUrlAsCurrent(const QUrl &url) @@ -702,6 +713,7 @@ void DolphinView::invertSelection() void DolphinView::clearSelection() { + m_selectJobCreatedItems = false; m_selectedUrls.clear(); m_container->controller()->selectionManager()->clearSelection(); } @@ -802,21 +814,39 @@ void DolphinView::copySelectedItemsToClipboard() void DolphinView::copySelectedItems(const KFileItemList &selection, const QUrl &destinationUrl) { + if (selection.isEmpty() || !destinationUrl.isValid()) { + return; + } + + m_clearSelectionBeforeSelectingNewItems = true; + m_markFirstNewlySelectedItemAsCurrent = true; + m_selectJobCreatedItems = true; + KIO::CopyJob *job = KIO::copy(selection.urlList(), destinationUrl, KIO::DefaultFlags); KJobWidgets::setWindow(job, this); connect(job, &KIO::DropJob::result, this, &DolphinView::slotJobResult); - connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotCopyingDone); + connect(job, &KIO::CopyJob::copying, this, &DolphinView::slotItemCreatedFromJob); + connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob); KIO::FileUndoManager::self()->recordCopyJob(job); } void DolphinView::moveSelectedItems(const KFileItemList &selection, const QUrl &destinationUrl) { + if (selection.isEmpty() || !destinationUrl.isValid()) { + return; + } + + m_clearSelectionBeforeSelectingNewItems = true; + m_markFirstNewlySelectedItemAsCurrent = true; + m_selectJobCreatedItems = true; + KIO::CopyJob *job = KIO::move(selection.urlList(), destinationUrl, KIO::DefaultFlags); KJobWidgets::setWindow(job, this); connect(job, &KIO::DropJob::result, this, &DolphinView::slotJobResult); - connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotCopyingDone); + connect(job, &KIO::CopyJob::moving, this, &DolphinView::slotItemCreatedFromJob); + connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob); KIO::FileUndoManager::self()->recordCopyJob(job); } @@ -961,9 +991,24 @@ bool DolphinView::eventFilter(QObject *watched, QEvent *event) } break; - case QEvent::ToolTip: - tryShowNameToolTip(static_cast(event)); + case QEvent::ToolTip: { + const auto helpEvent = static_cast(event); + if (tryShowNameToolTip(helpEvent)) { + return true; + + } else if (m_hoveredColumnHeaderIndex) { + const auto rolesInfo = KFileItemModel::rolesInformation(); + const auto visibleRole = m_visibleRoles.value(*m_hoveredColumnHeaderIndex); + for (const KFileItemModel::RoleInfo &info : rolesInfo) { + if (visibleRole == info.role) { + QToolTip::showText(helpEvent->globalPos(), info.tooltip, this); + return true; + } + } + } + break; + } default: break; } @@ -1331,7 +1376,17 @@ void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget * // Mark the dropped urls as selected. m_clearSelectionBeforeSelectingNewItems = true; m_markFirstNewlySelectedItemAsCurrent = true; + m_selectJobCreatedItems = true; connect(job, &KIO::DropJob::itemCreated, this, &DolphinView::slotItemCreated); + connect(job, &KIO::DropJob::copyJobStarted, this, [this](const KIO::CopyJob *copyJob) { + connect(copyJob, &KIO::CopyJob::copying, this, &DolphinView::slotItemCreatedFromJob); + connect(copyJob, &KIO::CopyJob::moving, this, &DolphinView::slotItemCreatedFromJob); + connect(copyJob, &KIO::CopyJob::linking, this, [this](KIO::Job *job, const QString &src, const QUrl &dest) { + Q_UNUSED(job) + Q_UNUSED(src) + slotItemCreated(dest); + }); + }); } } } @@ -1378,7 +1433,7 @@ void DolphinView::slotSelectedItemTextPressed(int index) } } -void DolphinView::slotCopyingDone(KIO::Job *, const QUrl &, const QUrl &to) +void DolphinView::slotItemCreatedFromJob(KIO::Job *, const QUrl &, const QUrl &to) { slotItemCreated(to); } @@ -1389,7 +1444,9 @@ void DolphinView::slotItemCreated(const QUrl &url) markUrlAsCurrent(url); m_markFirstNewlySelectedItemAsCurrent = false; } - m_selectedUrls << url; + if (m_selectJobCreatedItems && !m_selectedUrls.contains(url)) { + m_selectedUrls << url; + } } void DolphinView::slotJobResult(KJob *job) @@ -1397,8 +1454,35 @@ void DolphinView::slotJobResult(KJob *job) if (job->error() && job->error() != KIO::ERR_USER_CANCELED) { Q_EMIT errorMessage(job->errorString()); } + if (!m_selectJobCreatedItems) { + m_selectedUrls.clear(); + return; + } if (!m_selectedUrls.isEmpty()) { m_selectedUrls = KDirModel::simplifiedUrlList(m_selectedUrls); + + updateSelectionState(); + if (!m_selectedUrls.isEmpty()) { + // not all urls were found, the model may not be up to date + // TODO KF6 replace with Qt::singleShotConnection + QMetaObject::Connection *const connection = new QMetaObject::Connection; + *connection = connect( + m_model, + &KFileItemModel::directoryLoadingCompleted, + this, + [this, connection]() { + // the model should now contain all the items created by the job + updateSelectionState(); + m_selectJobCreatedItems = false; + m_selectedUrls.clear(); + QObject::disconnect(*connection); + delete connection; + }, + Qt::UniqueConnection); + } else { + m_selectJobCreatedItems = false; + m_selectedUrls.clear(); + } } } @@ -1660,6 +1744,40 @@ void DolphinView::slotDirectoryRedirection(const QUrl &oldUrl, const QUrl &newUr } } +void DolphinView::updateSelectionState() +{ + if (!m_selectedUrls.isEmpty()) { + KItemListSelectionManager *selectionManager = m_container->controller()->selectionManager(); + + // if there is a selection already, leave it that way + // unless some drop/paste job are in the process of creating items + if (!selectionManager->hasSelection() || m_selectJobCreatedItems) { + if (m_clearSelectionBeforeSelectingNewItems) { + selectionManager->clearSelection(); + m_clearSelectionBeforeSelectingNewItems = false; + } + + 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; + } + } + + if (!selectedItems.isEmpty()) { + selectionManager->beginAnchoredSelection(selectionManager->currentItem()); + selectionManager->setSelectedItems(selectedItems); + } + } + } +} + void DolphinView::updateViewState() { if (m_currentItemUrl != QUrl()) { @@ -1694,35 +1812,7 @@ void DolphinView::updateViewState() m_container->verticalScrollBar()->setValue(y); } - if (!m_selectedUrls.isEmpty()) { - KItemListSelectionManager *selectionManager = m_container->controller()->selectionManager(); - - // 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(); - - 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; - } - } - - if (!selectedItems.isEmpty()) { - selectionManager->beginAnchoredSelection(selectionManager->currentItem()); - selectionManager->setSelectedItems(selectedItems); - } - } - } + updateSelectionState(); } void DolphinView::hideToolTip(const ToolTipManager::HideBehavior behavior) @@ -1738,6 +1828,11 @@ void DolphinView::hideToolTip(const ToolTipManager::HideBehavior behavior) } } +bool DolphinView::handleSpaceAsNormalKey() const +{ + return !m_container->hasFocus() || m_container->controller()->isSearchAsYouTypeActive(); +} + void DolphinView::slotTwoClicksRenamingTimerTimeout() { const KItemListSelectionManager *selectionManager = m_container->controller()->selectionManager(); @@ -1969,9 +2064,9 @@ void DolphinView::slotRoleEditingFinished(int index, const QByteArray &role, con KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); - forceUrlsSelection(newUrl, {newUrl}); - if (!newNameExistsAlready) { + forceUrlsSelection(newUrl, {newUrl}); + // Only connect the result signal if there is no item with the new name // in the model yet, see bug 328262. connect(job, &KJob::result, this, &DolphinView::slotRenamingResult); @@ -2136,6 +2231,8 @@ void DolphinView::pasteToUrl(const QUrl &url) KJobWidgets::setWindow(job, this); m_clearSelectionBeforeSelectingNewItems = true; m_markFirstNewlySelectedItemAsCurrent = true; + m_selectJobCreatedItems = true; + // TODO KF6 use KIO::PasteJob::copyJobStarted to hook to earlier events copying/moving connect(job, &KIO::PasteJob::itemCreated, this, &DolphinView::slotItemCreated); connect(job, &KIO::PasteJob::result, this, &DolphinView::slotJobResult); } @@ -2247,7 +2344,7 @@ void DolphinView::slotSwipeUp() void DolphinView::showLoadingPlaceholder() { - m_placeholderLabel->setText(i18n("Loading...")); + m_placeholderLabel->setText(i18n("Loading…")); m_placeholderLabel->setVisible(true); } @@ -2300,13 +2397,13 @@ void DolphinView::updatePlaceholderLabel() m_placeholderLabel->setVisible(true); } -void DolphinView::tryShowNameToolTip(QHelpEvent *event) +bool DolphinView::tryShowNameToolTip(QHelpEvent *event) { if (!GeneralSettings::showToolTips() && m_mode == DolphinView::IconsView) { const std::optional index = m_view->itemAt(event->pos()); if (!index.has_value()) { - return; + return false; } // Check whether the filename has been elided @@ -2317,6 +2414,10 @@ void DolphinView::tryShowNameToolTip(QHelpEvent *event) const QString text = item.text(); const QPoint pos = mapToGlobal(event->pos()); QToolTip::showText(pos, text); + return true; } } + return false; } + +#include "moc_dolphinview.cpp"