diff options
Diffstat (limited to 'src')
44 files changed, 314 insertions, 163 deletions
diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp index f20963347..34d2102ef 100644 --- a/src/dolphincontextmenu.cpp +++ b/src/dolphincontextmenu.cpp @@ -7,7 +7,6 @@ #include "dolphincontextmenu.h" #include "dolphin_contextmenusettings.h" -#include "dolphin_generalsettings.h" #include "dolphinmainwindow.h" #include "dolphinnewfilemenu.h" #include "dolphinplacesmodelsingleton.h" @@ -16,7 +15,6 @@ #include "global.h" #include "trash/dolphintrash.h" #include "views/dolphinview.h" -#include "views/viewmodecontroller.h" #include <KActionCollection> #include <KFileItemListProperties> @@ -76,6 +74,8 @@ void DolphinContextMenu::addAllActions() m_context |= SearchContext; } else if (scheme.contains(QLatin1String("timeline"))) { m_context |= TimelineContext; + } else if (scheme == QStringLiteral("recentlyused")) { + m_context |= RecentlyUsedContext; } if (!m_fileInfo.isNull() && !m_selectedItems.isEmpty()) { @@ -164,6 +164,10 @@ void DolphinContextMenu::addDirectoryItemContextMenu() addAction(m_mainWindow->actionCollection()->action(QStringLiteral("open_in_new_window"))); } + if (ContextMenuSettings::showOpenInSplitView()) { + addAction(m_mainWindow->actionCollection()->action(QStringLiteral("open_in_split_view"))); + } + // Insert 'Open With' entries addOpenWithActions(); @@ -183,6 +187,25 @@ void DolphinContextMenu::addDirectoryItemContextMenu() addSeparator(); } +void DolphinContextMenu::addOpenParentFolderActions() +{ + addAction(QIcon::fromTheme(QStringLiteral("document-open-folder")), i18nc("@action:inmenu", "Open Path"), [this]() { + const QUrl url = m_fileInfo.targetUrl(); + const QUrl parentUrl = KIO::upUrl(url); + m_mainWindow->changeUrl(parentUrl); + m_mainWindow->activeViewContainer()->view()->markUrlsAsSelected({url}); + m_mainWindow->activeViewContainer()->view()->markUrlAsCurrent(url); + }); + + addAction(QIcon::fromTheme(QStringLiteral("tab-new")), i18nc("@action:inmenu", "Open Path in New Tab"), [this]() { + m_mainWindow->openNewTab(KIO::upUrl(m_fileInfo.targetUrl())); + }); + + addAction(QIcon::fromTheme(QStringLiteral("window-new")), i18nc("@action:inmenu", "Open Path in New Window"), [this]() { + Dolphin::openNewWindow({m_fileInfo.targetUrl()}, m_mainWindow, Dolphin::OpenNewWindowFlag::Select); + }); +} + void DolphinContextMenu::addItemContextMenu() { Q_ASSERT(!m_fileInfo.isNull()); @@ -195,22 +218,10 @@ void DolphinContextMenu::addItemContextMenu() // single files if (m_fileInfo.isDir()) { addDirectoryItemContextMenu(); - } else if (m_context & TimelineContext || m_context & SearchContext) { + } else if (m_context & TimelineContext || m_context & SearchContext || m_context & RecentlyUsedContext) { addOpenWithActions(); - addAction(QIcon::fromTheme(QStringLiteral("document-open-folder")), i18nc("@action:inmenu", "Open Path"), [this]() { - m_mainWindow->changeUrl(KIO::upUrl(m_fileInfo.url())); - m_mainWindow->activeViewContainer()->view()->markUrlsAsSelected({m_fileInfo.url()}); - m_mainWindow->activeViewContainer()->view()->markUrlAsCurrent(m_fileInfo.url()); - }); - - addAction(QIcon::fromTheme(QStringLiteral("tab-new")), i18nc("@action:inmenu", "Open Path in New Tab"), [this]() { - m_mainWindow->openNewTab(KIO::upUrl(m_fileInfo.url())); - }); - - addAction(QIcon::fromTheme(QStringLiteral("window-new")), i18nc("@action:inmenu", "Open Path in New Window"), [this]() { - Dolphin::openNewWindow({m_fileInfo.url()}, m_mainWindow, Dolphin::OpenNewWindowFlag::Select); - }); + addOpenParentFolderActions(); addSeparator(); } else { diff --git a/src/dolphincontextmenu.h b/src/dolphincontextmenu.h index 04b0697d0..f60be558e 100644 --- a/src/dolphincontextmenu.h +++ b/src/dolphincontextmenu.h @@ -95,6 +95,9 @@ private: void addAdditionalActions(const KFileItemListProperties &props); private: + void addDirectoryItemContextMenu(); + void addOpenParentFolderActions(); + struct Entry { int type; QString name; @@ -110,6 +113,7 @@ private: TrashContext = 2, TimelineContext = 4, SearchContext = 8, + RecentlyUsedContext = 16, }; DolphinMainWindow *m_mainWindow; @@ -126,7 +130,6 @@ private: KFileCopyToMenu m_copyToMenu; DolphinRemoveAction *m_removeAction; // Action that represents either 'Move To Trash' or 'Delete' - void addDirectoryItemContextMenu(); KFileItemActions *m_fileItemActions; }; diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 7064c63c9..a88e1a594 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -506,6 +506,32 @@ void DolphinMainWindow::openInNewWindow() } } +void DolphinMainWindow::openInSplitView(const QUrl &url) +{ + QUrl newSplitViewUrl = url; + + if (newSplitViewUrl.isEmpty()) { + const KFileItemList list = m_activeViewContainer->view()->selectedItems(); + if (list.count() == 1) { + const KFileItem &item = list.first(); + newSplitViewUrl = DolphinView::openItemAsFolderUrl(item); + } + } + + if (newSplitViewUrl.isEmpty()) { + return; + } + + DolphinTabPage *tabPage = m_tabWidget->currentTabPage(); + if (tabPage->splitViewEnabled()) { + tabPage->switchActiveView(); + tabPage->activeViewContainer()->setUrl(newSplitViewUrl); + } else { + tabPage->setSplitViewEnabled(true, WithAnimation, newSplitViewUrl); + updateViewActions(); + } +} + void DolphinMainWindow::showTarget() { const KFileItem link = m_activeViewContainer->view()->selectedItems().at(0); @@ -895,7 +921,6 @@ void DolphinMainWindow::toggleSplitView() { DolphinTabPage *tabPage = m_tabWidget->currentTabPage(); tabPage->setSplitViewEnabled(!tabPage->splitViewEnabled(), WithAnimation); - updateViewActions(); } @@ -1154,7 +1179,8 @@ void DolphinMainWindow::openTerminalHere() { QList<QUrl> urls = {}; - for (const KFileItem &item : m_activeViewContainer->view()->selectedItems()) { + const auto selectedItems = m_activeViewContainer->view()->selectedItems(); + for (const KFileItem &item : selectedItems) { QUrl url = item.targetUrl(); if (item.isFile()) { url.setPath(QFileInfo(url.path()).absolutePath()); @@ -1172,29 +1198,19 @@ void DolphinMainWindow::openTerminalHere() if (urls.count() > 5) { QString question = i18np("Are you sure you want to open 1 terminal window?", "Are you sure you want to open %1 terminal windows?", urls.count()); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) - const int answer = KMessageBox::warningTwoActions( - this, - question, - {}, -#else - const int answer = KMessageBox::warningYesNo( + const int answer = KMessageBox::warningContinueCancel( this, question, {}, -#endif KGuiItem(i18ncp("@action:button", "Open %1 Terminal", "Open %1 Terminals", urls.count()), QStringLiteral("utilities-terminal")), - KStandardGuiItem::cancel()); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) - if (answer != KMessageBox::PrimaryAction) { -#else - if (answer != KMessageBox::Yes) { -#endif + KStandardGuiItem::cancel(), + QStringLiteral("ConfirmOpenManyTerminals")); + if (answer != KMessageBox::PrimaryAction && answer != KMessageBox::Continue) { return; } } - for (const QUrl &url : urls) { + for (const QUrl &url : std::as_const(urls)) { openTerminalJob(url); } } @@ -2005,6 +2021,13 @@ void DolphinMainWindow::setupActions() openInNewWindow->setText(i18nc("@action:inmenu", "Open in New Window")); openInNewWindow->setIcon(QIcon::fromTheme(QStringLiteral("window-new"))); connect(openInNewWindow, &QAction::triggered, this, &DolphinMainWindow::openInNewWindow); + + QAction *openInSplitViewAction = actionCollection()->addAction(QStringLiteral("open_in_split_view")); + openInSplitViewAction->setText(i18nc("@action:inmenu", "Open in Split View")); + openInSplitViewAction->setIcon(QIcon::fromTheme(QStringLiteral("view-right-new"))); + connect(openInSplitViewAction, &QAction::triggered, this, [this]() { + openInSplitView(QUrl()); + }); } void DolphinMainWindow::setupDockWidgets() @@ -2180,6 +2203,7 @@ void DolphinMainWindow::setupDockWidgets() connect(m_placesPanel, &PlacesPanel::newWindowRequested, this, [this](const QUrl &url) { Dolphin::openNewWindow({url}, this); }); + connect(m_placesPanel, &PlacesPanel::openInSplitViewRequested, this, &DolphinMainWindow::openInSplitView); connect(m_placesPanel, &PlacesPanel::errorMessage, this, &DolphinMainWindow::showErrorMessage); connect(this, &DolphinMainWindow::urlChanged, m_placesPanel, &PlacesPanel::setUrl); connect(placesDock, &DolphinDockWidget::visibilityChanged, &DolphinUrlNavigatorsController::slotPlacesPanelVisibilityChanged); diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index 5bb17e79a..b45c846b8 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -477,6 +477,11 @@ private Q_SLOTS: void openInNewWindow(); /** + * Opens the selected folder in the other inactive split view, enables split view if necessary. + */ + void openInSplitView(const QUrl &url); + + /** * Show the target of the selected symlink */ void showTarget(); diff --git a/src/dolphinpart.h b/src/dolphinpart.h index 94f83d0ef..af0acb171 100644 --- a/src/dolphinpart.h +++ b/src/dolphinpart.h @@ -29,7 +29,7 @@ class DolphinPart : public KParts::ReadOnlyPart // Used by konqueror. Technically it means "we want undo enabled if // there are things in the undo history and the current part is a dolphin part". // Even though it's konqueror doing the undo... - Q_PROPERTY(bool supportsUndo READ supportsUndo) + Q_PROPERTY(bool supportsUndo READ supportsUndo CONSTANT) Q_PROPERTY(QString currentViewMode READ currentViewMode WRITE setCurrentViewMode) diff --git a/src/dolphintabpage.h b/src/dolphintabpage.h index 0c691830e..4a8bd365a 100644 --- a/src/dolphintabpage.h +++ b/src/dolphintabpage.h @@ -138,6 +138,8 @@ public: */ void setActive(bool active); + void switchActiveView(); + Q_SIGNALS: void activeViewChanged(DolphinViewContainer *viewContainer); void activeViewUrlChanged(const QUrl &url); @@ -170,8 +172,6 @@ private Q_SLOTS: */ void slotViewUrlRedirection(const QUrl &oldUrl, const QUrl &newUrl); - void switchActiveView(); - private: /** * Creates a new view container and does the default initialization. diff --git a/src/dolphintabwidget.h b/src/dolphintabwidget.h index 75c6e3471..5bc708b38 100644 --- a/src/dolphintabwidget.h +++ b/src/dolphintabwidget.h @@ -123,7 +123,9 @@ public Q_SLOTS: * Opens a new tab in the background showing the URL \a primaryUrl and the * optional URL \a secondaryUrl. */ - void openNewTab(const QUrl &primaryUrl, const QUrl &secondaryUrl = QUrl(), NewTabPosition position = NewTabPosition::FollowSetting); + void openNewTab(const QUrl &primaryUrl, + const QUrl &secondaryUrl = QUrl(), + DolphinTabWidget::NewTabPosition position = DolphinTabWidget::NewTabPosition::FollowSetting); /** * Opens each directory in \p dirs in a separate tab unless it is already open. diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index c0ef1997a..66a9a116a 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -32,6 +32,7 @@ #include <KMessageWidget> #include <KProtocolManager> #include <KShell> +#include <kio_version.h> #include <QApplication> #include <QDesktopServices> @@ -83,6 +84,7 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent) m_searchBox = new DolphinSearchBox(this); m_searchBox->hide(); connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate); + connect(m_searchBox, &DolphinSearchBox::openRequest, this, &DolphinViewContainer::openSearchBox); connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox); connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching); connect(m_searchBox, &DolphinSearchBox::focusViewRequest, this, &DolphinViewContainer::requestFocus); @@ -736,17 +738,28 @@ void DolphinViewContainer::slotfileMiddleClickActivated(const KFileItem &item) { KService::List services = KApplicationTrader::queryByMimeType(item.mimetype()); - if (services.length() >= 2) { - auto service = services.at(1); + int indexOfAppToOpenFileWith = 1; + + // executable scripts + auto mimeType = item.currentMimeType(); + if (item.isLocalFile() && mimeType.inherits(QStringLiteral("application/x-executable")) && mimeType.inherits(QStringLiteral("text/plain")) + && QFileInfo(item.localPath()).isExecutable()) { + KConfigGroup cfgGroup(KSharedConfig::openConfig(QStringLiteral("kiorc")), "Executable scripts"); + const QString value = cfgGroup.readEntry("behaviourOnLaunch", "alwaysAsk"); + + // in case KIO::WidgetsOpenOrExecuteFileHandler::promptUserOpenOrExecute would not open the file + if (value != QLatin1String("open")) { + indexOfAppToOpenFileWith = 0; + } + } + + if (services.length() >= indexOfAppToOpenFileWith + 1) { + auto service = services.at(indexOfAppToOpenFileWith); KIO::ApplicationLauncherJob *job = new KIO::ApplicationLauncherJob(service, this); job->setUrls({item.url()}); -#if KIO_VERSION >= QT_VERSION_CHECK(5, 98, 0) job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); -#else - job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); -#endif connect(job, &KIO::OpenUrlJob::finished, this, &DolphinViewContainer::slotOpenUrlFinished); job->start(); } @@ -879,6 +892,11 @@ void DolphinViewContainer::startSearching() } } +void DolphinViewContainer::openSearchBox() +{ + setSearchModeEnabled(true); +} + void DolphinViewContainer::closeSearchBox() { setSearchModeEnabled(false); diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h index 0c8b184fe..52fd688f6 100644 --- a/src/dolphinviewcontainer.h +++ b/src/dolphinviewcontainer.h @@ -382,6 +382,7 @@ private Q_SLOTS: * Gets the search URL from the searchbox and starts searching. */ void startSearching(); + void openSearchBox(); void closeSearchBox(); /** diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 2ff5c9fb9..954e6ab88 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -326,6 +326,31 @@ void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent *event) triggerVisibleIndexRangeUpdate(); } +void KFileItemListView::focusInEvent(QFocusEvent *event) +{ + Q_UNUSED(event) + updateSelectedWidgets(); +} + +void KFileItemListView::focusOutEvent(QFocusEvent *event) +{ + Q_UNUSED(event) + updateSelectedWidgets(); +} + +void KFileItemListView::updateSelectedWidgets() +{ + const auto visibleWidgets = visibleItemListWidgets(); + for (KItemListWidget *widget : visibleWidgets) { + if (widget->isSelected()) { + auto w = qobject_cast<KFileItemListWidget *>(widget); + if (w) { + w->forceUpdate(); + } + } + } +} + void KFileItemListView::slotItemsRemoved(const KItemRangeList &itemRanges) { KStandardItemListView::slotItemsRemoved(itemRanges); diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h index b4be0093e..4c48c52ab 100644 --- a/src/kitemviews/kfileitemlistview.h +++ b/src/kitemviews/kfileitemlistview.h @@ -98,6 +98,8 @@ protected: void onTransactionBegin() override; void onTransactionEnd() override; void resizeEvent(QGraphicsSceneResizeEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; protected Q_SLOTS: void slotItemsRemoved(const KItemRangeList &itemRanges) override; @@ -127,6 +129,8 @@ private: QSize availableIconSize() const; private: + void updateSelectedWidgets(); + KFileItemModelRolesUpdater *m_modelRolesUpdater; QTimer *m_updateVisibleIndexRangeTimer; QTimer *m_updateIconSizeTimer; diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 771403b70..9802ca7d1 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -203,6 +203,17 @@ void KFileItemListWidget::hoverSequenceStarted() view->setHoverSequenceState(itemUrl, 0); } +void KFileItemListWidget::forceUpdate() +{ + updateAdditionalInfoTextColor(); + // icon layout does not include the icons in the item selection rectangle + // so its icon does not need updating + if (listView()->itemLayout() != KStandardItemListView::ItemLayout::IconsLayout) { + invalidateIconCache(); + } + update(); +} + void KFileItemListWidget::hoverSequenceIndexChanged(int sequenceIndex) { KFileItemListView *view = listView(); diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 27fcf7f29..7f33c5487 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/src/kitemviews/kfileitemlistwidget.h @@ -35,6 +35,9 @@ public: static KItemListWidgetInformant *createInformant(); + /// Force-update the displayed icon + void forceUpdate(); + protected: virtual void hoverSequenceStarted() override; virtual void hoverSequenceIndexChanged(int sequenceIndex) override; diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index a175e0bfe..77d5a319c 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -1196,7 +1196,12 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList &items) for (const KFileItem &item : items) { if (item.url() == currentDir) { - Q_EMIT currentDirectoryRemoved(); + // #473377: Delay emitting currentDirectoryRemoved() to avoid modifying KCoreDirLister + // before KCoreDirListerCache::deleteDir() returns. + QTimer::singleShot(0, this, [this] { + Q_EMIT currentDirectoryRemoved(); + }); + return; } diff --git a/src/kitemviews/kitemlistcontainer.cpp b/src/kitemviews/kitemlistcontainer.cpp index 3893ceaea..f89a6c8ce 100644 --- a/src/kitemviews/kitemlistcontainer.cpp +++ b/src/kitemviews/kitemlistcontainer.cpp @@ -175,6 +175,22 @@ void KItemListContainer::wheelEvent(QWheelEvent *event) smoothScroller->handleWheelEvent(event); } +void KItemListContainer::focusInEvent(QFocusEvent *event) +{ + KItemListView *view = m_controller->view(); + if (view) { + QApplication::sendEvent(view, event); + } +} + +void KItemListContainer::focusOutEvent(QFocusEvent *event) +{ + KItemListView *view = m_controller->view(); + if (view) { + QApplication::sendEvent(view, event); + } +} + void KItemListContainer::slotScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous) { Q_UNUSED(previous) diff --git a/src/kitemviews/kitemlistcontainer.h b/src/kitemviews/kitemlistcontainer.h index 6bb28469e..40b075376 100644 --- a/src/kitemviews/kitemlistcontainer.h +++ b/src/kitemviews/kitemlistcontainer.h @@ -50,6 +50,8 @@ protected: void resizeEvent(QResizeEvent *event) override; void scrollContentsBy(int dx, int dy) override; void wheelEvent(QWheelEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; private Q_SLOTS: void slotScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index 122ef836d..0576fc7fd 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -49,11 +49,8 @@ class QTouchEvent; class DOLPHIN_EXPORT KItemListController : public QObject { Q_OBJECT - Q_PROPERTY(KItemModelBase *model READ model WRITE setModel) - Q_PROPERTY(KItemListView *view READ view WRITE setView) - Q_PROPERTY(SelectionBehavior selectionBehavior READ selectionBehavior WRITE setSelectionBehavior) - Q_PROPERTY(AutoActivationBehavior autoActivationBehavior READ autoActivationBehavior WRITE setAutoActivationBehavior) - Q_PROPERTY(MouseDoubleClickAction mouseDoubleClickAction READ mouseDoubleClickAction WRITE setMouseDoubleClickAction) + Q_PROPERTY(KItemModelBase *model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(KItemListView *view READ view WRITE setView NOTIFY viewChanged) public: enum SelectionBehavior { NoSelection, SingleSelection, MultiSelection }; diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 33a341081..d43438c30 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -361,7 +361,7 @@ void KItemListView::setGeometry(const QRectF &rect) if (m_headerWidget->automaticColumnResizing()) { applyAutomaticColumnWidths(); } else { - const qreal requiredWidth = columnWidthsSum(); + const qreal requiredWidth = columnWidthsSum() + 2 * m_headerWidget->sidePadding(); const QSizeF dynamicItemSize(qMax(newSize.width(), requiredWidth), m_itemSize.height()); m_layouter->setItemSize(dynamicItemSize); } @@ -961,6 +961,18 @@ bool KItemListView::event(QEvent *event) updateFont(); break; + case QEvent::FocusIn: + focusInEvent(static_cast<QFocusEvent *>(event)); + event->accept(); + return true; + break; + + case QEvent::FocusOut: + focusOutEvent(static_cast<QFocusEvent *>(event)); + event->accept(); + return true; + break; + default: // Forward all other events to the controller and handle them there if (!m_editingRole && m_controller && m_controller->processEvent(event, transform())) { @@ -2265,7 +2277,7 @@ QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeLi void KItemListView::applyColumnWidthsFromHeader() { // Apply the new size to the layouter - const qreal requiredWidth = columnWidthsSum() + m_headerWidget->sidePadding(); + const qreal requiredWidth = columnWidthsSum() + 2 * m_headerWidget->sidePadding(); const QSizeF dynamicItemSize(qMax(size().width(), requiredWidth), m_itemSize.height()); m_layouter->setItemSize(dynamicItemSize); @@ -2360,9 +2372,9 @@ void KItemListView::applyAutomaticColumnWidths() qreal firstColumnWidth = m_headerWidget->columnWidth(firstRole); QSizeF dynamicItemSize = m_itemSize; - qreal requiredWidth = columnWidthsSum() + m_headerWidget->sidePadding() - + m_headerWidget->sidePadding(); // Adding the padding a second time so we have the same padding symmetrically on both sides of the view. - // This improves UX, looks better and increases the chances of users figuring out that the padding area can be used for deselecting and dropping files. + qreal requiredWidth = columnWidthsSum() + 2 * m_headerWidget->sidePadding(); // Adding the padding a second time so we have the same padding + // symmetrically on both sides of the view. This improves UX, looks better and increases the chances of users figuring out that the padding + // area can be used for deselecting and dropping files. const qreal availableWidth = size().width(); if (requiredWidth < availableWidth) { // Stretch the first column to use the whole remaining width diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 6c3d3648d..ff51af922 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -53,8 +53,8 @@ class DOLPHIN_EXPORT KItemListView : public QGraphicsWidget { Q_OBJECT - Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset) - Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset) + Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset NOTIFY scrollOffsetChanged) + Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset NOTIFY itemOffsetChanged) public: explicit KItemListView(QGraphicsWidget *parent = nullptr); diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index c8b3d2c3c..cfaf89175 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -111,7 +111,7 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o } if (m_selected && m_editedRole.isEmpty()) { - const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0); + const QStyle::State activeState(isActiveWindow() && widget->hasFocus() ? QStyle::State_Active : 0); drawItemStyleOption(painter, widget, activeState | QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item); } @@ -120,7 +120,7 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o initStyleOption(&focusRectOption); focusRectOption.rect = textFocusRect().toRect(); focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange; - if (m_selected) { + if (m_selected && widget->hasFocus()) { focusRectOption.state |= QStyle::State_Selected; } @@ -135,8 +135,8 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o m_hoverCache->fill(Qt::transparent); QPainter pixmapPainter(m_hoverCache); - const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0); - drawItemStyleOption(&pixmapPainter, widget, activeState | QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Item); + const QStyle::State activeState(isActiveWindow() && widget->hasFocus() ? QStyle::State_Active | QStyle::State_Enabled : 0); + drawItemStyleOption(&pixmapPainter, widget, activeState | QStyle::State_MouseOver | QStyle::State_Item); } const qreal opacity = painter->opacity(); diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 499a50416..52df17ad3 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -386,7 +386,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic } painter->setFont(m_customizedFont); - painter->setPen(textColor()); + painter->setPen(textColor(*widget)); const TextInfo *textInfo = m_textInfo.value("text"); if (!textInfo) { @@ -645,7 +645,7 @@ void KStandardItemListWidget::setTextColor(const QColor &color) } } -QColor KStandardItemListWidget::textColor() const +QColor KStandardItemListWidget::textColor(const QWidget &widget) const { if (!isSelected()) { if (m_isHidden) { @@ -655,7 +655,7 @@ QColor KStandardItemListWidget::textColor() const } } - const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive; + const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); return styleOption().palette.color(group, role); } @@ -1015,8 +1015,11 @@ void KStandardItemListWidget::updatePixmapCache() iconName = QStringLiteral("unknown"); } const QStringList overlays = values["iconOverlays"].toStringList(); - m_pixmap = - pixmapForIcon(iconName, overlays, maxIconHeight, m_layout != IconsLayout && isActiveWindow() && isSelected() ? QIcon::Selected : QIcon::Normal); + const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); + m_pixmap = pixmapForIcon(iconName, + overlays, + maxIconHeight, + m_layout != IconsLayout && isActiveWindow() && isSelected() && hasFocus ? QIcon::Selected : QIcon::Normal); } else if (m_pixmap.width() / m_pixmap.devicePixelRatio() != maxIconWidth || m_pixmap.height() / m_pixmap.devicePixelRatio() != maxIconHeight) { // A custom pixmap has been applied. Assure that the pixmap @@ -1433,9 +1436,10 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() void KStandardItemListWidget::updateAdditionalInfoTextColor() { QColor c1; + const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); if (m_customTextColor.isValid()) { c1 = m_customTextColor; - } else if (isSelected() && (m_layout != DetailsLayout || m_highlightEntireRow)) { + } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { // The detail text colour needs to match the main text (HighlightedText) for the same level // of readability. We short circuit early here to avoid interpolating with another colour. m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index 73bc393f4..1313179c9 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -139,7 +139,7 @@ protected: virtual QPalette::ColorRole normalTextColorRole() const; void setTextColor(const QColor &color); - QColor textColor() const; + QColor textColor(const QWidget &widget) const; void setOverlay(const QPixmap &overlay); QPixmap overlay() const; @@ -181,6 +181,7 @@ protected: QPointF pos; QStaticText staticText; }; + void updateAdditionalInfoTextColor(); public Q_SLOTS: void finishRoleEditing(); @@ -200,8 +201,6 @@ private: void updateCompactLayoutTextCache(); void updateDetailsLayoutTextCache(); - void updateAdditionalInfoTextColor(); - void drawPixmap(QPainter *painter, const QPixmap &pixmap); void drawSiblingsInformation(QPainter *painter); diff --git a/src/kitemviews/private/kitemlistheaderwidget.cpp b/src/kitemviews/private/kitemlistheaderwidget.cpp index 3e1232561..02a4f939d 100644 --- a/src/kitemviews/private/kitemlistheaderwidget.cpp +++ b/src/kitemviews/private/kitemlistheaderwidget.cpp @@ -136,7 +136,7 @@ void KItemListHeaderWidget::setSidePadding(qreal width) { if (m_sidePadding != width) { m_sidePadding = width; - sidePaddingChanged(width); + Q_EMIT sidePaddingChanged(width); update(); } } diff --git a/src/kitemviews/private/kitemlistrubberband.h b/src/kitemviews/private/kitemlistrubberband.h index fd1416b56..64ce9ba29 100644 --- a/src/kitemviews/private/kitemlistrubberband.h +++ b/src/kitemviews/private/kitemlistrubberband.h @@ -18,7 +18,7 @@ class DOLPHIN_EXPORT KItemListRubberBand : public QObject { Q_OBJECT - Q_PROPERTY(QPointF endPosition MEMBER m_endPos READ endPosition WRITE setEndPosition) + Q_PROPERTY(QPointF endPosition MEMBER m_endPos READ endPosition WRITE setEndPosition NOTIFY endPositionChanged) public: explicit KItemListRubberBand(QObject *parent = nullptr); diff --git a/src/org.kde.dolphin.appdata.xml b/src/org.kde.dolphin.appdata.xml index a23b9ddc2..83840d35f 100644 --- a/src/org.kde.dolphin.appdata.xml +++ b/src/org.kde.dolphin.appdata.xml @@ -494,10 +494,10 @@ <binary>dolphin</binary> </provides> <releases> + <release version="23.08.1" date="2023-09-14"/> <release version="23.08.0" date="2023-08-24"/> <release version="23.04.3" date="2023-07-06"/> <release version="23.04.2" date="2023-06-08"/> - <release version="23.04.1" date="2023-05-11"/> </releases> <content_rating type="oars-1.1"/> </component> diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 8b245f0e7..8bdb18ba2 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -47,6 +47,15 @@ PlacesPanel::PlacesPanel(QWidget *parent) connect(m_configureTrashAction, &QAction::triggered, this, &PlacesPanel::slotConfigureTrash); addAction(m_configureTrashAction); + m_openInSplitView = new QAction(QIcon::fromTheme(QStringLiteral("view-right-new")), i18nc("@action:inmenu", "Open in Split View")); + m_openInSplitView->setPriority(QAction::HighPriority); + connect(m_openInSplitView, &QAction::triggered, this, [this]() { + const QUrl url = currentIndex().data(KFilePlacesModel::UrlRole).toUrl(); + Q_EMIT openInSplitViewRequested(url); + }); + + addAction(m_openInSplitView); + connect(this, &PlacesPanel::contextMenuAboutToShow, this, &PlacesPanel::slotContextMenuAboutToShow); connect(this, &PlacesPanel::iconSizeChanged, this, [](const QSize &newSize) { @@ -188,6 +197,7 @@ void PlacesPanel::slotContextMenuAboutToShow(const QModelIndex &index, QMenu *me const Solid::Device device = placesModel->deviceForIndex(index); m_configureTrashAction->setVisible(url.scheme() == QLatin1String("trash")); + m_openInSplitView->setVisible(url.isValid()); // show customContextMenuActions only on the view's context menu if (!url.isValid() && !device.isValid()) { diff --git a/src/panels/places/placespanel.h b/src/panels/places/placespanel.h index 2eb309483..cbd5fc224 100644 --- a/src/panels/places/placespanel.h +++ b/src/panels/places/placespanel.h @@ -51,6 +51,7 @@ Q_SIGNALS: void storageTearDownRequested(const QString &mountPath); void storageTearDownExternallyRequested(const QString &mountPath); void storageTearDownSuccessful(); + void openInSplitViewRequested(const QUrl &url); protected: void showEvent(QShowEvent *event) override; @@ -75,6 +76,7 @@ private: QPersistentModelIndex m_indexToTearDown; QAction *m_configureTrashAction; + QAction *m_openInSplitView; QAction *m_lockPanelsAction; }; diff --git a/src/search/dolphinquery.cpp b/src/search/dolphinquery.cpp index f9e5da84f..ed2a6a766 100644 --- a/src/search/dolphinquery.cpp +++ b/src/search/dolphinquery.cpp @@ -49,7 +49,7 @@ QStringList splitOutsideQuotes(const QString &text) // - Groups with two leading quotes must close both on them (filename:""abc xyz" tuv") // - Groups enclosed in quotes // - Words separated by spaces - const QRegularExpression subTermsRegExp("(\\S*?\"\"[^\"]+\"[^\"]+\"+|\\S*?\"[^\"]+\"+|(?<=\\s|^)\\S+(?=\\s|$))"); + static const QRegularExpression subTermsRegExp("(\\S*?\"\"[^\"]+\"[^\"]+\"+|\\S*?\"[^\"]+\"+|(?<=\\s|^)\\S+(?=\\s|$))"); auto subTermsMatchIterator = subTermsRegExp.globalMatch(text); QStringList textParts; diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index 9df417c4f..a09f25293 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -60,7 +60,9 @@ DolphinSearchBox::~DolphinSearchBox() void DolphinSearchBox::setText(const QString &text) { - m_searchInput->setText(text); + if (m_searchInput->text() != text) { + m_searchInput->setText(text); + } } QString DolphinSearchBox::text() const @@ -201,7 +203,7 @@ void DolphinSearchBox::keyReleaseEvent(QKeyEvent *event) QWidget::keyReleaseEvent(event); if (event->key() == Qt::Key_Escape) { if (m_searchInput->text().isEmpty()) { - Q_EMIT closeRequest(); + emitCloseRequest(); } else { m_searchInput->clear(); } @@ -261,7 +263,11 @@ void DolphinSearchBox::slotConfigurationChanged() void DolphinSearchBox::slotSearchTextChanged(const QString &text) { if (text.isEmpty()) { - m_startSearchTimer->stop(); + // Restore URL when search box is cleared by closing and reopening the box. + emitCloseRequest(); + QTimer::singleShot(0, this, [this] { + Q_EMIT openRequest(); + }); } else { m_startSearchTimer->start(); } @@ -270,6 +276,10 @@ void DolphinSearchBox::slotSearchTextChanged(const QString &text) void DolphinSearchBox::slotReturnPressed() { + if (m_searchInput->text().isEmpty()) { + return; + } + emitSearchRequest(); Q_EMIT focusViewRequest(); } @@ -443,10 +453,10 @@ void DolphinSearchBox::init() loadSettings(); // The searching should be started automatically after the user did not change - // the text within one second + // the text for a while m_startSearchTimer = new QTimer(this); m_startSearchTimer->setSingleShot(true); - m_startSearchTimer->setInterval(1000); + m_startSearchTimer->setInterval(500); connect(m_startSearchTimer, &QTimer::timeout, this, &DolphinSearchBox::emitSearchRequest); } @@ -496,10 +506,7 @@ void DolphinSearchBox::updateFromQuery(const DolphinQuery &query) setSearchPath(QUrl::fromLocalFile(QDir::homePath())); } - // If the input box has focus, do not update to avoid messing with user typing - if (!m_searchInput->hasFocus()) { - setText(query.text()); - } + setText(query.text()); if (query.hasContentSearch()) { m_contentButton->setChecked(true); diff --git a/src/search/dolphinsearchbox.h b/src/search/dolphinsearchbox.h index 4ccb7ac10..b73c2899f 100644 --- a/src/search/dolphinsearchbox.h +++ b/src/search/dolphinsearchbox.h @@ -112,6 +112,11 @@ Q_SIGNALS: void closeRequest(); /** + * Is emitted when the search box should be opened. + */ + void openRequest(); + + /** * Is emitted, if the searchbox has been activated by * an user interaction * @see DolphinSearchBox::setActive() diff --git a/src/selectionmode/backgroundcolorhelper.cpp b/src/selectionmode/backgroundcolorhelper.cpp index 74f5bda1a..fa3e55ac4 100644 --- a/src/selectionmode/backgroundcolorhelper.cpp +++ b/src/selectionmode/backgroundcolorhelper.cpp @@ -46,7 +46,7 @@ void BackgroundColorHelper::controlBackgroundColor(QWidget *widget) BackgroundColorHelper::BackgroundColorHelper() { updateBackgroundColor(); - QObject::connect(qApp, &QGuiApplication::paletteChanged, [=]() { + QObject::connect(qApp, &QGuiApplication::paletteChanged, qApp, [=]() { slotPaletteChanged(); }); } diff --git a/src/selectionmode/bottombarcontentscontainer.cpp b/src/selectionmode/bottombarcontentscontainer.cpp index d53d2e4b9..d571b0302 100644 --- a/src/selectionmode/bottombarcontentscontainer.cpp +++ b/src/selectionmode/bottombarcontentscontainer.cpp @@ -166,7 +166,7 @@ void BottomBarContentsContainer::addCopyContents() auto *copyButton = new QPushButton(this); // We claim to have PasteContents already so triggering the copy action next won't instantly hide the bottom bar. - connect(copyButton, &QAbstractButton::clicked, [this]() { + connect(copyButton, &QAbstractButton::clicked, this, [this]() { if (GeneralSettings::showPasteBarAfterCopying()) { m_contents = BottomBar::Contents::PasteContents; // prevents hiding } @@ -174,7 +174,7 @@ void BottomBarContentsContainer::addCopyContents() // Connect the copy action as a second step. m_mainAction = ActionWithWidget(m_actionCollection->action(KStandardAction::name(KStandardAction::Copy)), copyButton); // Finally connect the lambda that actually changes the contents to the PasteContents. - connect(copyButton, &QAbstractButton::clicked, [this]() { + connect(copyButton, &QAbstractButton::clicked, this, [this]() { if (GeneralSettings::showPasteBarAfterCopying()) { resetContents(BottomBar::Contents::PasteContents); // resetContents() needs to be connected last because // it instantly deletes the button and then the other slots won't be called. @@ -244,7 +244,7 @@ void BottomBarContentsContainer::addCutContents() auto *cutButton = new QPushButton(this); // We claim to have PasteContents already so triggering the cut action next won't instantly hide the bottom bar. - connect(cutButton, &QAbstractButton::clicked, [this]() { + connect(cutButton, &QAbstractButton::clicked, this, [this]() { if (GeneralSettings::showPasteBarAfterCopying()) { m_contents = BottomBar::Contents::PasteContents; // prevents hiding } @@ -252,7 +252,7 @@ void BottomBarContentsContainer::addCutContents() // Connect the cut action as a second step. m_mainAction = ActionWithWidget(m_actionCollection->action(KStandardAction::name(KStandardAction::Cut)), cutButton); // Finally connect the lambda that actually changes the contents to the PasteContents. - connect(cutButton, &QAbstractButton::clicked, [this]() { + connect(cutButton, &QAbstractButton::clicked, this, [this]() { if (GeneralSettings::showPasteBarAfterCopying()) { resetContents(BottomBar::Contents::PasteContents); // resetContents() needs to be connected last because // it instantly deletes the button and then the other slots won't be called. diff --git a/src/settings/contextmenu/contextmenusettingspage.cpp b/src/settings/contextmenu/contextmenusettingspage.cpp index 5e755d249..1c83e477e 100644 --- a/src/settings/contextmenu/contextmenusettingspage.cpp +++ b/src/settings/contextmenu/contextmenusettingspage.cpp @@ -7,7 +7,6 @@ #include "contextmenusettingspage.h" #include "dolphin_contextmenusettings.h" -#include "dolphin_generalsettings.h" #include "dolphin_versioncontrolsettings.h" #include "global.h" #include "settings/servicemodel.h" @@ -118,6 +117,8 @@ bool ContextMenuSettingsPage::entryVisible(const QString &id) return ContextMenuSettings::showOpenInNewTab(); } else if (id == "open_in_new_window") { return ContextMenuSettings::showOpenInNewWindow(); + } else if (id == "open_in_split_view") { + return ContextMenuSettings::showOpenInSplitView(); } else if (id == "copy_location") { return ContextMenuSettings::showCopyLocation(); } else if (id == "duplicate") { @@ -144,6 +145,8 @@ void ContextMenuSettingsPage::setEntryVisible(const QString &id, bool visible) ContextMenuSettings::setShowOpenInNewTab(visible); } else if (id == "open_in_new_window") { ContextMenuSettings::setShowOpenInNewWindow(visible); + } else if (id == "open_in_split_view") { + return ContextMenuSettings::setShowOpenInSplitView(visible); } else if (id == "copy_location") { ContextMenuSettings::setShowCopyLocation(visible); } else if (id == "duplicate") { @@ -201,24 +204,15 @@ void ContextMenuSettingsPage::applySettings() VersionControlSettings::self()->save(); if (!laterSelected) { -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) KMessageBox::ButtonCode promptRestart = KMessageBox::questionTwoActions(window(), -#else - KMessageBox::ButtonCode promptRestart = - KMessageBox::questionYesNo(window(), -#endif i18nc("@info", "Dolphin must be restarted to apply the " "updated version control system settings."), i18nc("@info", "Restart now?"), KGuiItem(QApplication::translate("KStandardGuiItem", "&Restart"), QStringLiteral("dialog-restart")), KGuiItem(QApplication::translate("KStandardGuiItem", "&Later"), QStringLiteral("dialog-later"))); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) if (promptRestart == KMessageBox::ButtonCode::PrimaryAction) { -#else - if (promptRestart == KMessageBox::ButtonCode::Yes) { -#endif Dolphin::openNewWindow(); qApp->quit(); } else { diff --git a/src/settings/dolphin_contextmenusettings.kcfg b/src/settings/dolphin_contextmenusettings.kcfg index 63ca079af..6e45d9bcd 100644 --- a/src/settings/dolphin_contextmenusettings.kcfg +++ b/src/settings/dolphin_contextmenusettings.kcfg @@ -30,6 +30,10 @@ <label>Show 'Open in New Window' in context menu.</label> <default>true</default> </entry> + <entry name="ShowOpenInSplitView" type="Bool"> + <label>Show 'Open In Split View' in context menu.</label> + <default>true</default> + </entry> <entry name="ShowCopyLocation" type="Bool"> <label>Show 'Copy Location' in context menu.</label> <default>true</default> diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg index aedc24ea4..2abd7da49 100644 --- a/src/settings/dolphin_generalsettings.kcfg +++ b/src/settings/dolphin_generalsettings.kcfg @@ -142,4 +142,14 @@ <emit signal="sortingChoiceChanged" /> </entry> </group> + <group name="Notification Messages"> + <entry name="ConfirmOpenManyFolders" type="Bool"> + <label>Ask for confirmation when opening many folders at once.</label> + <default>true</default> + </entry> + <entry name="ConfirmOpenManyTerminals" type="Bool"> + <label>Ask for confirmation when opening many terminals at once.</label> + <default>true</default> + </entry> + </group> </kcfg> diff --git a/src/settings/dolphinsettingsdialog.cpp b/src/settings/dolphinsettingsdialog.cpp index 0d2c76e3c..8c41794e9 100644 --- a/src/settings/dolphinsettingsdialog.cpp +++ b/src/settings/dolphinsettingsdialog.cpp @@ -68,6 +68,7 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl &url, QWidget *parent, K QStringLiteral("view_mode"), QStringLiteral("open_in_new_tab"), QStringLiteral("open_in_new_window"), + QStringLiteral("open_in_split_view"), QStringLiteral("copy_location"), QStringLiteral("duplicate"), QStringLiteral("open_terminal_here"), @@ -160,29 +161,17 @@ void DolphinSettingsDialog::closeEvent(QCloseEvent *event) return; } -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) const auto response = KMessageBox::warningTwoActionsCancel(this, -#else - const auto response = KMessageBox::warningYesNoCancel(this, -#endif i18n("You have unsaved changes. Do you want to apply the changes or discard them?"), i18n("Warning"), KStandardGuiItem::save(), KStandardGuiItem::discard(), KStandardGuiItem::cancel()); switch (response) { -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) case KMessageBox::PrimaryAction: -#else - case KMessageBox::Yes: -#endif applySettings(); Q_FALLTHROUGH(); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) case KMessageBox::SecondaryAction: -#else - case KMessageBox::No: -#endif event->accept(); break; case KMessageBox::Cancel: diff --git a/src/settings/interface/confirmationssettingspage.cpp b/src/settings/interface/confirmationssettingspage.cpp index 61c3a14b6..5f1abb4cd 100644 --- a/src/settings/interface/confirmationssettingspage.cpp +++ b/src/settings/interface/confirmationssettingspage.cpp @@ -60,9 +60,12 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget *parent) new QCheckBox(i18nc("@option:check Ask for confirmation when", "Closing windows with a program running in the Terminal panel"), this); #endif + m_confirmOpenManyFolders = new QCheckBox(i18nc("@option:check Ask for confirmation in Dolphin when", "Opening many folders at once"), this); + m_confirmOpenManyTerminals = new QCheckBox(i18nc("@option:check Ask for confirmation in Dolphin when", "Opening many terminals at once"), this); + QHBoxLayout *executableScriptLayout = new QHBoxLayout(); QLabel *executableScriptLabel = new QLabel(i18nc("@title:group", "When opening an executable file:"), this); - confirmLabelKde->setWordWrap(true); + executableScriptLabel->setWordWrap(true); executableScriptLayout->addWidget(executableScriptLabel); m_confirmScriptExecution = new QComboBox(this); @@ -81,6 +84,9 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget *parent) topLayout->addWidget(m_confirmClosingTerminalRunningProgram); #endif + topLayout->addWidget(m_confirmOpenManyFolders); + topLayout->addWidget(m_confirmOpenManyTerminals); + topLayout->addSpacing(Dolphin::VERTICAL_SPACER_HEIGHT); topLayout->addLayout(executableScriptLayout); @@ -93,6 +99,8 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget *parent) connect(m_confirmDelete, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); connect(m_confirmScriptExecution, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ConfirmationsSettingsPage::changed); connect(m_confirmClosingMultipleTabs, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); + connect(m_confirmOpenManyFolders, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); + connect(m_confirmOpenManyTerminals, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); #if HAVE_TERMINAL connect(m_confirmClosingTerminalRunningProgram, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); @@ -128,6 +136,8 @@ void ConfirmationsSettingsPage::applySettings() GeneralSettings *settings = GeneralSettings::self(); settings->setConfirmClosingMultipleTabs(m_confirmClosingMultipleTabs->isChecked()); + settings->setConfirmOpenManyFolders(m_confirmOpenManyFolders->isChecked()); + settings->setConfirmOpenManyTerminals(m_confirmOpenManyTerminals->isChecked()); #if HAVE_TERMINAL settings->setConfirmClosingTerminalRunningProgram(m_confirmClosingTerminalRunningProgram->isChecked()); @@ -169,6 +179,12 @@ void ConfirmationsSettingsPage::loadSettings() m_confirmClosingMultipleTabs->setChecked(GeneralSettings::confirmClosingMultipleTabs()); + // KMessageBox for its dontshowAgain settings are true => Yes, false => No, No value => ask + // we use default = false to not write false into the rc file, but have no value + // the UI has inversed meaning compared to the interpretation + m_confirmOpenManyFolders->setChecked(GeneralSettings::confirmOpenManyFolders()); + m_confirmOpenManyTerminals->setChecked(GeneralSettings::confirmOpenManyTerminals()); + #if HAVE_TERMINAL m_confirmClosingTerminalRunningProgram->setChecked(GeneralSettings::confirmClosingTerminalRunningProgram()); #endif diff --git a/src/settings/interface/confirmationssettingspage.h b/src/settings/interface/confirmationssettingspage.h index 56dd1a78c..d9413d754 100644 --- a/src/settings/interface/confirmationssettingspage.h +++ b/src/settings/interface/confirmationssettingspage.h @@ -43,6 +43,8 @@ private: QCheckBox *m_confirmClosingMultipleTabs; QComboBox *m_confirmScriptExecution; + QCheckBox *m_confirmOpenManyFolders; + QCheckBox *m_confirmOpenManyTerminals; }; #endif diff --git a/src/settings/viewmodes/viewsettingstab.h b/src/settings/viewmodes/viewsettingstab.h index fd4cc85a7..5181e8018 100644 --- a/src/settings/viewmodes/viewsettingstab.h +++ b/src/settings/viewmodes/viewsettingstab.h @@ -32,9 +32,6 @@ public: void applySettings() override; void restoreDefaults() override; -Q_SIGNALS: - void changed(); - private Q_SLOTS: void slotDefaultSliderMoved(int value); diff --git a/src/settings/viewpropertiesdialog.cpp b/src/settings/viewpropertiesdialog.cpp index f7bd754b1..c630f8113 100644 --- a/src/settings/viewpropertiesdialog.cpp +++ b/src/settings/viewpropertiesdialog.cpp @@ -333,11 +333,7 @@ void ViewPropertiesDialog::applyViewProperties() const bool applyToSubFolders = m_applyToSubFolders && m_applyToSubFolders->isChecked(); if (applyToSubFolders) { const QString text(i18nc("@info", "The view properties of all sub-folders will be changed. Do you want to continue?")); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) if (KMessageBox::questionTwoActions(this, text, {}, KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) { -#else - if (KMessageBox::questionYesNo(this, text, {}, KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::No) { -#endif return; } @@ -367,11 +363,7 @@ void ViewPropertiesDialog::applyViewProperties() if (applyToAllFolders) { const QString text(i18nc("@info", "The view properties of all folders will be changed. Do you want to continue?")); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) if (KMessageBox::questionTwoActions(this, text, {}, KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) { -#else - if (KMessageBox::questionYesNo(this, text, {}, KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::No) { -#endif return; } diff --git a/src/tests/kitemlistcontrollerexpandtest.cpp b/src/tests/kitemlistcontrollerexpandtest.cpp index 20bc0cc0c..368ec67ce 100644 --- a/src/tests/kitemlistcontrollerexpandtest.cpp +++ b/src/tests/kitemlistcontrollerexpandtest.cpp @@ -180,7 +180,7 @@ void KItemListControllerExpandTest::testDirExpand() [this]() { return m_spyDirectoryLoadingCompleted->count() == 6; }, - 100)); + 300)); QCOMPARE(m_model->count(), 18); QCOMPARE(m_selectionManager->currentItem(), 12); diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp index 0efea844c..418c9bfe8 100644 --- a/src/views/dolphinitemlistview.cpp +++ b/src/views/dolphinitemlistview.cpp @@ -22,7 +22,7 @@ DolphinItemListView::DolphinItemListView(QGraphicsWidget *parent) : KFileItemListView(parent) , m_zoomLevel(0) { - updateFont(); + DolphinItemListView::updateFont(); updateGridSize(); } diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 3beb246a1..e27f423f6 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -276,6 +276,10 @@ bool DolphinView::isActive() const void DolphinView::setViewMode(Mode mode) { if (mode != m_mode) { + // Reset scrollbars before changing the view mode. + m_container->horizontalScrollBar()->setValue(0); + m_container->verticalScrollBar()->setValue(0); + ViewProperties props(viewPropertiesUrl()); props.setViewMode(mode); @@ -1055,24 +1059,14 @@ void DolphinView::slotItemsActivated(const KItemSet &indexes) 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()); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) - const int answer = KMessageBox::warningTwoActions( + const int answer = KMessageBox::warningContinueCancel( this, question, {}, -#else - const int answer = - KMessageBox::warningYesNo(this, - question, - {}, -#endif KGuiItem(i18ncp("@action:button", "Open %1 Item", "Open %1 Items", indexes.count()), QStringLiteral("document-open")), - KStandardGuiItem::cancel()); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) - if (answer != KMessageBox::PrimaryAction) { -#else - if (answer != KMessageBox::Yes) { -#endif + KStandardGuiItem::cancel(), + QStringLiteral("ConfirmOpenManyFolders")); + if (answer != KMessageBox::PrimaryAction && answer != KMessageBox::Continue) { return; } } @@ -1426,6 +1420,14 @@ void DolphinView::slotItemCreated(const QUrl &url) } } +void DolphinView::onDirectoryLoadingCompleted() +{ + // the model should now contain all the items created by the job + updateSelectionState(); + m_selectJobCreatedItems = false; + m_selectedUrls.clear(); +} + void DolphinView::slotJobResult(KJob *job) { if (job->error() && job->error() != KIO::ERR_USER_CANCELED) { @@ -1441,21 +1443,7 @@ void DolphinView::slotJobResult(KJob *job) 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); + connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::onDirectoryLoadingCompleted, Qt::UniqueConnection); } else { m_selectJobCreatedItems = false; m_selectedUrls.clear(); @@ -1998,13 +1986,8 @@ void DolphinView::slotRoleEditingFinished(int index, const QByteArray &role, con if (!hiddenFilesShown() && newName.startsWith(QLatin1Char('.')) && !oldItem.name().startsWith(QLatin1Char('.'))) { KGuiItem yesGuiItem(i18nc("@action:button", "Rename and Hide"), QStringLiteral("view-hidden")); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) const auto code = KMessageBox::questionTwoActions(this, -#else - const auto code = - KMessageBox::questionYesNo(this, -#endif oldItem.isFile() ? i18n("Adding a dot to the beginning of this file's name will hide it from view.\n" "Do you still want to rename it?") : i18n("Adding a dot to the beginning of this folder's name will hide it from view.\n" @@ -2014,11 +1997,7 @@ void DolphinView::slotRoleEditingFinished(int index, const QByteArray &role, con KStandardGuiItem::cancel(), QStringLiteral("ConfirmHide")); -#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) if (code == KMessageBox::SecondaryAction) { -#else - if (code == KMessageBox::No) { -#endif return; } } @@ -2301,7 +2280,7 @@ void DolphinView::copyPathToClipboard() if (clipboard == nullptr) { return; } - clipboard->setText(path); + clipboard->setText(QDir::toNativeSeparators(path)); } void DolphinView::slotIncreaseZoom() diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index f851724c2..05b9e009c 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -824,6 +824,8 @@ private Q_SLOTS: void slotTwoClicksRenamingTimerTimeout(); + void onDirectoryLoadingCompleted(); + private: void loadDirectory(const QUrl &url, bool reload = false); |
