┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dolphincontextmenu.cpp43
-rw-r--r--src/dolphincontextmenu.h5
-rw-r--r--src/dolphinmainwindow.cpp58
-rw-r--r--src/dolphinmainwindow.h5
-rw-r--r--src/dolphinpart.h2
-rw-r--r--src/dolphintabpage.h4
-rw-r--r--src/dolphintabwidget.h4
-rw-r--r--src/dolphinviewcontainer.cpp30
-rw-r--r--src/dolphinviewcontainer.h1
-rw-r--r--src/kitemviews/kfileitemlistview.cpp25
-rw-r--r--src/kitemviews/kfileitemlistview.h4
-rw-r--r--src/kitemviews/kfileitemlistwidget.cpp11
-rw-r--r--src/kitemviews/kfileitemlistwidget.h3
-rw-r--r--src/kitemviews/kfileitemmodel.cpp7
-rw-r--r--src/kitemviews/kitemlistcontainer.cpp16
-rw-r--r--src/kitemviews/kitemlistcontainer.h2
-rw-r--r--src/kitemviews/kitemlistcontroller.h7
-rw-r--r--src/kitemviews/kitemlistview.cpp22
-rw-r--r--src/kitemviews/kitemlistview.h4
-rw-r--r--src/kitemviews/kitemlistwidget.cpp8
-rw-r--r--src/kitemviews/kstandarditemlistwidget.cpp16
-rw-r--r--src/kitemviews/kstandarditemlistwidget.h5
-rw-r--r--src/kitemviews/private/kitemlistheaderwidget.cpp2
-rw-r--r--src/kitemviews/private/kitemlistrubberband.h2
-rw-r--r--src/org.kde.dolphin.appdata.xml2
-rw-r--r--src/panels/places/placespanel.cpp10
-rw-r--r--src/panels/places/placespanel.h2
-rw-r--r--src/search/dolphinquery.cpp2
-rw-r--r--src/search/dolphinsearchbox.cpp25
-rw-r--r--src/search/dolphinsearchbox.h5
-rw-r--r--src/selectionmode/backgroundcolorhelper.cpp2
-rw-r--r--src/selectionmode/bottombarcontentscontainer.cpp8
-rw-r--r--src/settings/contextmenu/contextmenusettingspage.cpp14
-rw-r--r--src/settings/dolphin_contextmenusettings.kcfg4
-rw-r--r--src/settings/dolphin_generalsettings.kcfg10
-rw-r--r--src/settings/dolphinsettingsdialog.cpp13
-rw-r--r--src/settings/interface/confirmationssettingspage.cpp18
-rw-r--r--src/settings/interface/confirmationssettingspage.h2
-rw-r--r--src/settings/viewmodes/viewsettingstab.h3
-rw-r--r--src/settings/viewpropertiesdialog.cpp8
-rw-r--r--src/tests/kitemlistcontrollerexpandtest.cpp2
-rw-r--r--src/views/dolphinitemlistview.cpp2
-rw-r--r--src/views/dolphinview.cpp57
-rw-r--r--src/views/dolphinview.h2
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);