From: Elvis Angelaccio Date: Sun, 6 Oct 2019 09:51:34 +0000 (+0200) Subject: Merge branch 'Applications/19.08' X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/fcf2d98447a1103af2dae5b1da0e673a6a42122e?hp=31fd775f368f61f6dde54c0c3a2e83d65599c3c2 Merge branch 'Applications/19.08' --- diff --git a/.gitignore b/.gitignore index 59d534347..c48f92390 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ doxygen.log CMakeLists.txt.user .directory *.kdev4 +/build*/ diff --git a/CMakeLists.txt b/CMakeLists.txt index ad3598fbb..90c1df10e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.0) # KDE Application Version, managed by release script set (KDE_APPLICATIONS_VERSION_MAJOR "19") -set (KDE_APPLICATIONS_VERSION_MINOR "08") -set (KDE_APPLICATIONS_VERSION_MICRO "2") +set (KDE_APPLICATIONS_VERSION_MINOR "11") +set (KDE_APPLICATIONS_VERSION_MICRO "70") set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") project(Dolphin VERSION ${KDE_APPLICATIONS_VERSION}) -set(QT_MIN_VERSION "5.8.0") -set(KF5_MIN_VERSION "5.57.0") +set(QT_MIN_VERSION "5.11.0") +set(KF5_MIN_VERSION "5.61.0") # ECM setup find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) @@ -149,12 +149,7 @@ configure_file(org.kde.dolphin.FileManager1.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.dolphin.FileManager1.service) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.dolphin.FileManager1.service DESTINATION ${DBUS_SERVICES_INSTALL_DIR}) - -if (NOT ECM_VERSION VERSION_LESS "5.59.0") - install(FILES dolphin.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) -else() - install(FILES dolphin.categories DESTINATION ${KDE_INSTALL_CONFDIR}) -endif() +install(FILES dolphin.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/doc/index.docbook b/doc/index.docbook index f2b5c70a3..b85001180 100644 --- a/doc/index.docbook +++ b/doc/index.docbook @@ -70,8 +70,8 @@ &FDLNotice; -2019-06-26 -Applications 19.08 +2019-09-30 +Applications 19.12 @@ -681,7 +681,7 @@ the path starting with the current places entry. &dolphin; allows a number of panels to be placed next to the view. These can -be enabled in ViewPanels. +be enabled in ViewShow Panels. By unlocking the panels and clicking and dragging a panel title, the panel can be moved to a different position, even outside the window. @@ -1078,7 +1078,10 @@ be shown inside a folder's icon. Confirmations Tab In the ask for confirmation section, you can enable warning dialogs that -are shown before potentially harmful actions . +are shown before potentially harmful actions. + + +It is also possible to choose the default action When opening an executable file. There are three options, namely Always ask, Open in application, and Run script. The confirmation settings for Moving files or folders to trash and Deleting files or folders affect file operations in &dolphin;, &konqueror;, @@ -1758,6 +1761,17 @@ Selects all unselected items and deselects all selected items in the current fol Decreases the size of icons in the view. + + + +&Ctrl;0 + +View +Zoom Reset + +Resets the size of icons in the view to default. + + View @@ -1784,7 +1798,7 @@ or other criteria described in Informat View -Additional Information +Show Additional Information Displays additional information described in Information in the View. @@ -1794,7 +1808,7 @@ described in Information in the View View -Preview +Show Previews Displays a symbolic preview of the file contents in the different view modes. @@ -1816,7 +1830,7 @@ current folder grouped by the option selected in Sort By&Alt;. View -Hidden Files +Show Hidden Files Shows all the hidden files and sub-folders within the current folder.There is an alternate shortcut &Ctrl;H @@ -1857,7 +1871,7 @@ folder. View -Panels +Show Panels Enables and disables the different panels: Places (F9), Information diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp index 1dfbe054d..783abc71f 100644 --- a/src/dolphincontextmenu.cpp +++ b/src/dolphincontextmenu.cpp @@ -1,4 +1,4 @@ -/*************************************************************************** + /*************************************************************************** * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) and * * Cvetoslav Ludmiloff * * * @@ -192,7 +192,6 @@ void DolphinContextMenu::openItemContextMenu() QAction* openParentAction = nullptr; QAction* openParentInNewWindowAction = nullptr; QAction* openParentInNewTabAction = nullptr; - QAction* addToPlacesAction = nullptr; const KFileItemListProperties& selectedItemsProps = selectedItemsProperties(); KFileItemActions fileItemActions; @@ -208,32 +207,23 @@ void DolphinContextMenu::openItemContextMenu() // Insert 'Open With' entries addOpenWithActions(fileItemActions); - // insert 'Add to Places' entry - if (!placeExists(m_fileInfo.url())) { - addToPlacesAction = addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), - i18nc("@action:inmenu Add selected folder to places", - "Add to Places")); - } - - addSeparator(); - // set up 'Create New' menu - DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow->actionCollection(), m_mainWindow); - const DolphinView* view = m_mainWindow->activeViewContainer()->view(); - newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown()); - newFileMenu->checkUpToDate(); - newFileMenu->setPopupFiles(m_fileInfo.url()); - newFileMenu->setEnabled(selectedItemsProps.supportsWriting()); - connect(newFileMenu, &DolphinNewFileMenu::fileCreated, newFileMenu, &DolphinNewFileMenu::deleteLater); - connect(newFileMenu, &DolphinNewFileMenu::directoryCreated, newFileMenu, &DolphinNewFileMenu::deleteLater); - - QMenu* menu = newFileMenu->menu(); - menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New")); - menu->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); - addMenu(menu); - - addSeparator(); - } else if (m_baseUrl.scheme().contains(QStringLiteral("search")) || m_baseUrl.scheme().contains(QStringLiteral("timeline"))) { + DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow->actionCollection(), m_mainWindow); + const DolphinView* view = m_mainWindow->activeViewContainer()->view(); + newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown()); + newFileMenu->checkUpToDate(); + newFileMenu->setPopupFiles(m_fileInfo.url()); + newFileMenu->setEnabled(selectedItemsProps.supportsWriting()); + connect(newFileMenu, &DolphinNewFileMenu::fileCreated, newFileMenu, &DolphinNewFileMenu::deleteLater); + connect(newFileMenu, &DolphinNewFileMenu::directoryCreated, newFileMenu, &DolphinNewFileMenu::deleteLater); + + QMenu* menu = newFileMenu->menu(); + menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New")); + menu->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); + addMenu(menu); + + addSeparator(); + } else if (m_baseUrl.scheme().contains(QLatin1String("search")) || m_baseUrl.scheme().contains(QLatin1String("timeline"))) { addOpenWithActions(fileItemActions); openParentAction = new QAction(QIcon::fromTheme(QStringLiteral("document-open-folder")), @@ -254,15 +244,6 @@ void DolphinContextMenu::openItemContextMenu() this); addAction(openParentInNewTabAction); - addSeparator(); - } else if (!DolphinView::openItemAsFolderUrl(m_fileInfo).isEmpty()) { - // Insert 'Open With" entries - addOpenWithActions(fileItemActions); - - // insert 'Open in new window' and 'Open in new tab' entries - addAction(m_mainWindow->actionCollection()->action(QStringLiteral("open_in_new_window"))); - addAction(m_mainWindow->actionCollection()->action(QStringLiteral("open_in_new_tab"))); - addSeparator(); } else { // Insert 'Open With" entries @@ -292,6 +273,15 @@ void DolphinContextMenu::openItemContextMenu() insertDefaultItemActions(selectedItemsProps); + // insert 'Add to Places' entry if appropriate + if (m_selectedItems.count() == 1) { + if (m_fileInfo.isDir()) { + if (!placeExists(m_fileInfo.url())) { + addAction(m_mainWindow->actionCollection()->action(QStringLiteral("add_to_places"))); + } + } + } + addSeparator(); fileItemActions.addServiceActionsTo(this); @@ -314,14 +304,7 @@ void DolphinContextMenu::openItemContextMenu() QAction* activatedAction = exec(m_pos); if (activatedAction) { - if (activatedAction == addToPlacesAction) { - const QUrl selectedUrl(m_fileInfo.url()); - if (selectedUrl.isValid()) { - PlacesItemModel model; - const QString text = selectedUrl.fileName(); - model.createPlacesItem(text, selectedUrl, KIO::iconNameForUrl(selectedUrl)); - } - } else if (activatedAction == openParentAction) { + if (activatedAction == openParentAction) { m_command = OpenParentFolder; } else if (activatedAction == openParentInNewWindowAction) { m_command = OpenParentFolderInNewWindow; @@ -333,14 +316,7 @@ void DolphinContextMenu::openItemContextMenu() void DolphinContextMenu::openViewportContextMenu() { - // setup 'Create New' menu - KNewFileMenu* newFileMenu = m_mainWindow->newFileMenu(); const DolphinView* view = m_mainWindow->activeViewContainer()->view(); - newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown()); - newFileMenu->checkUpToDate(); - newFileMenu->setPopupFiles(m_baseUrl); - addMenu(newFileMenu->menu()); - addSeparator(); // Insert 'Open With' entries KFileItem baseItem = view->rootItem(); @@ -359,22 +335,20 @@ void DolphinContextMenu::openViewportContextMenu() addOpenWithActions(fileItemActions); } - // Insert 'New Window' and 'New Tab' entries. Don't use "open_in_new_window" and - // "open_in_new_tab" here, as the current selection should get ignored. - addAction(m_mainWindow->actionCollection()->action(QStringLiteral("file_new"))); - addAction(m_mainWindow->actionCollection()->action(QStringLiteral("new_tab"))); - - // Insert 'Add to Places' entry if exactly one item is selected - QAction* addToPlacesAction = nullptr; - if (!placeExists(m_mainWindow->activeViewContainer()->url())) { - addToPlacesAction = addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), - i18nc("@action:inmenu Add current folder to places", "Add to Places")); - } - - addSeparator(); + // Set up and insert 'Create New' menu + KNewFileMenu* newFileMenu = m_mainWindow->newFileMenu(); + newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown()); + newFileMenu->checkUpToDate(); + newFileMenu->setPopupFiles(m_baseUrl); + addMenu(newFileMenu->menu()); QAction* pasteAction = createPasteAction(); addAction(pasteAction); + + // Insert 'Add to Places' entry if it's not already in the places panel + if (!placeExists(m_mainWindow->activeViewContainer()->url())) { + addAction(m_mainWindow->actionCollection()->action(QStringLiteral("add_to_places"))); + } addSeparator(); // Insert 'Sort By' and 'View Mode' @@ -391,26 +365,14 @@ void DolphinContextMenu::openViewportContextMenu() addCustomActions(); + addSeparator(); + QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties")); addAction(propertiesAction); addShowMenuBarAction(); - QAction* action = exec(m_pos); - if (addToPlacesAction && (action == addToPlacesAction)) { - const DolphinViewContainer* container = m_mainWindow->activeViewContainer(); - const QUrl url = container->url(); - if (url.isValid()) { - PlacesItemModel model; - QString icon; - if (container->isSearchModeEnabled()) { - icon = QStringLiteral("folder-saved-search-symbolic"); - } else { - icon = KIO::iconNameForUrl(url); - } - model.createPlacesItem(container->placesText(), url, icon); - } - } + exec(m_pos); } void DolphinContextMenu::insertDefaultItemActions(const KFileItemListProperties& properties) diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index c9ed9c5cd..ce2013798 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -32,6 +32,7 @@ #include "dolphintabpage.h" #include "middleclickactioneventfilter.h" #include "panels/folders/folderspanel.h" +#include "panels/places/placesitemmodel.h" #include "panels/places/placespanel.h" #include "panels/information/informationpanel.h" #include "panels/terminal/terminalpanel.h" @@ -64,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -89,10 +91,12 @@ namespace { // Used for GeneralSettings::version() to determine whether // an updated version of Dolphin is running. const int CurrentDolphinVersion = 200; + // The maximum number of entries in the back/forward popup menu + const int MaxNumberOfNavigationentries = 12; } DolphinMainWindow::DolphinMainWindow() : - KXmlGuiWindow(nullptr, Qt::WindowContextHelpButtonHint), + KXmlGuiWindow(nullptr), m_newFileMenu(nullptr), m_helpMenu(nullptr), m_tabWidget(nullptr), @@ -106,9 +110,14 @@ DolphinMainWindow::DolphinMainWindow() : m_lastHandleUrlStatJob(nullptr), m_terminalPanel(nullptr), m_placesPanel(nullptr), - m_tearDownFromPlacesRequested(false) + m_tearDownFromPlacesRequested(false), + m_backAction(nullptr), + m_forwardAction(nullptr) { Q_INIT_RESOURCE(dolphin); +#ifndef Q_OS_WIN + setWindowFlags(Qt::WindowContextHelpButtonHint); +#endif setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName()); setObjectName(QStringLiteral("Dolphin#")); @@ -272,7 +281,7 @@ void DolphinMainWindow::changeUrl(const QUrl &url) } m_activeViewContainer->setUrl(url); - updateEditActions(); + updateFileAndEditActions(); updatePasteAction(); updateViewActions(); updateGoActions(); @@ -301,7 +310,7 @@ void DolphinMainWindow::slotEditableStateChanged(bool editable) void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection) { - updateEditActions(); + updateFileAndEditActions(); const int selectedUrlsCount = m_tabWidget->currentTabPage()->selectedItemsCount(); @@ -352,6 +361,32 @@ void DolphinMainWindow::openNewActivatedTab() m_tabWidget->openNewActivatedTab(); } +void DolphinMainWindow::addToPlaces() +{ + QUrl url; + QString name; + + // If nothing is selected, act on the current dir + if (m_activeViewContainer->view()->selectedItems().isEmpty()) { + url = m_activeViewContainer->url(); + name = m_activeViewContainer->placesText(); + } else { + const auto dirToAdd = m_activeViewContainer->view()->selectedItems().first(); + url = dirToAdd.url(); + name = dirToAdd.name(); + } + if (url.isValid()) { + PlacesItemModel model; + QString icon; + if (m_activeViewContainer->isSearchModeEnabled()) { + icon = QStringLiteral("folder-saved-search-symbolic"); + } else { + icon = KIO::iconNameForUrl(url); + } + model.createPlacesItem(name, url, icon); + } +} + void DolphinMainWindow::openNewTab(const QUrl& url, DolphinTabWidget::TabPlacement tabPlacement) { m_tabWidget->openNewTab(url, QUrl(), tabPlacement); @@ -482,7 +517,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) } } - if (m_terminalPanel->hasProgramRunning() && GeneralSettings::confirmClosingTerminalRunningProgram() && closedByUser) { + if (m_terminalPanel && m_terminalPanel->hasProgramRunning() && GeneralSettings::confirmClosingTerminalRunningProgram() && closedByUser) { // Ask if the user really wants to quit Dolphin with a program that is still running in the Terminal panel // Open a confirmation dialog with 3 buttons: // QDialogButtonBox::Yes -> Quit @@ -500,7 +535,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event) if (!m_terminalPanel->isVisible()) { KGuiItem::assign( buttons->button(QDialogButtonBox::No), - KGuiItem(i18n("Show &Terminal Panel"), QIcon::fromTheme(QStringLiteral("utilities-terminal")))); + KGuiItem(i18n("Show &Terminal Panel"), QIcon::fromTheme(QStringLiteral("dialog-scripts")))); } KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); @@ -617,6 +652,12 @@ void DolphinMainWindow::find() m_activeViewContainer->setSearchModeEnabled(true); } +void DolphinMainWindow::updateSearchAction() +{ + QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search")); + toggleSearchAction->setChecked(m_activeViewContainer->isSearchModeEnabled()); +} + void DolphinMainWindow::updatePasteAction() { QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste)); @@ -643,6 +684,56 @@ void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action) } } +void DolphinMainWindow::slotAboutToShowBackPopupMenu() +{ + KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator(); + int entries = 0; + m_backAction->menu()->clear(); + for (int i = urlNavigator->historyIndex() + 1; i < urlNavigator->historySize() && entries < MaxNumberOfNavigationentries; ++i, ++entries) { + QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_backAction->menu()); + action->setData(i); + m_backAction->menu()->addAction(action); + } +} + +void DolphinMainWindow::slotGoBack(QAction* action) +{ + int gotoIndex = action->data().value(); + KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator(); + for (int i = gotoIndex - urlNavigator->historyIndex(); i > 0; --i) { + goBack(); + } +} + +void DolphinMainWindow::slotBackForwardActionMiddleClicked(QAction* action) +{ + if (action) { + KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator(); + openNewTabAfterCurrentTab(urlNavigator->locationUrl(action->data().value())); + } +} + +void DolphinMainWindow::slotAboutToShowForwardPopupMenu() +{ + KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator(); + int entries = 0; + m_forwardAction->menu()->clear(); + for (int i = urlNavigator->historyIndex() - 1; i >= 0 && entries < MaxNumberOfNavigationentries; --i, ++entries) { + QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_forwardAction->menu()); + action->setData(i); + m_forwardAction->menu()->addAction(action); + } +} + +void DolphinMainWindow::slotGoForward(QAction* action) +{ + int gotoIndex = action->data().value(); + KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator(); + for (int i = urlNavigator->historyIndex() - gotoIndex; i > 0; --i) { + goForward(); + } +} + void DolphinMainWindow::selectAll() { clearStatusBar(); @@ -751,7 +842,7 @@ void DolphinMainWindow::togglePanelLockState() void DolphinMainWindow::slotTerminalPanelVisibilityChanged() { - if (m_terminalPanel->isHiddenInVisibleWindow()) { + if (m_terminalPanel->isHiddenInVisibleWindow() && m_activeViewContainer) { m_activeViewContainer->view()->setFocus(); } } @@ -961,18 +1052,15 @@ void DolphinMainWindow::updateControlMenu() KActionCollection* ac = actionCollection(); - // Add "Create New" menu menu->addMenu(m_newFileMenu->menu()); + addActionToMenu(ac->action(QStringLiteral("file_new")), menu); + addActionToMenu(ac->action(QStringLiteral("new_tab")), menu); + addActionToMenu(ac->action(QStringLiteral("closed_tabs")), menu); menu->addSeparator(); - // Overwrite Find action to Search action - QAction *searchAction = ac->action(KStandardAction::name(KStandardAction::Find)); - searchAction->setText(i18n("Search...")); - // Add "Edit" actions bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) | - addActionToMenu(searchAction, menu) | addActionToMenu(ac->action(KStandardAction::name(KStandardAction::SelectAll)), menu) | addActionToMenu(ac->action(QStringLiteral("invert_selection")), menu); @@ -983,66 +1071,40 @@ void DolphinMainWindow::updateControlMenu() // Add "View" actions if (!GeneralSettings::showZoomSlider()) { addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomIn)), menu); + addActionToMenu(ac->action(QStringLiteral("view_zoom_reset")), menu); addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomOut)), menu); menu->addSeparator(); } - added = addActionToMenu(ac->action(QStringLiteral("sort")), menu) | - addActionToMenu(ac->action(QStringLiteral("view_mode")), menu) | - addActionToMenu(ac->action(QStringLiteral("additional_info")), menu) | - addActionToMenu(ac->action(QStringLiteral("show_preview")), menu) | + added = addActionToMenu(ac->action(QStringLiteral("show_preview")), menu) | addActionToMenu(ac->action(QStringLiteral("show_in_groups")), menu) | - addActionToMenu(ac->action(QStringLiteral("show_hidden_files")), menu); - - if (added) { - menu->addSeparator(); - } - - added = addActionToMenu(ac->action(QStringLiteral("split_view")), menu) | - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Redisplay)), menu) | + addActionToMenu(ac->action(QStringLiteral("show_hidden_files")), menu) | + addActionToMenu(ac->action(QStringLiteral("additional_info")), menu) | addActionToMenu(ac->action(QStringLiteral("view_properties")), menu); + if (added) { menu->addSeparator(); } - addActionToMenu(ac->action(QStringLiteral("panels")), menu); - QMenu* locationBarMenu = new QMenu(i18nc("@action:inmenu", "Location Bar"), menu); - locationBarMenu->addAction(ac->action(QStringLiteral("editable_location"))); - locationBarMenu->addAction(ac->action(QStringLiteral("replace_location"))); - menu->addMenu(locationBarMenu); + // Add a curated assortment of items from the "Tools" menu + addActionToMenu(ac->action(QStringLiteral("show_filter_bar")), menu); + addActionToMenu(ac->action(QStringLiteral("open_terminal")), menu); menu->addSeparator(); - // Add "Go" menu - QMenu* goMenu = new QMenu(i18nc("@action:inmenu", "Go"), menu); - goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Back))); - goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Forward))); - goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Up))); - goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Home))); - goMenu->addAction(ac->action(QStringLiteral("closed_tabs"))); - KActionMenu *bookmarkMenu = new KActionMenu(i18nc("@title:menu", "&Bookmarks"), goMenu); - m_bookmarkHandler->fillControlMenu(bookmarkMenu->menu(), ac); - goMenu->addAction(bookmarkMenu); - menu->addMenu(goMenu); - - // Add "Tool" menu - QMenu* toolsMenu = new QMenu(i18nc("@action:inmenu", "Tools"), menu); - toolsMenu->addAction(ac->action(QStringLiteral("show_filter_bar"))); - toolsMenu->addAction(ac->action(QStringLiteral("compare_files"))); - toolsMenu->addAction(ac->action(QStringLiteral("open_terminal"))); - toolsMenu->addAction(ac->action(QStringLiteral("change_remote_encoding"))); - menu->addMenu(toolsMenu); + // Add "Show Panels" menu + addActionToMenu(ac->action(QStringLiteral("panels")), menu); // Add "Settings" menu entries addActionToMenu(ac->action(KStandardAction::name(KStandardAction::KeyBindings)), menu); addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ConfigureToolbars)), menu); addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Preferences)), menu); + addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu); // Add "Help" menu - menu->addMenu(m_helpMenu->menu()); - - menu->addSeparator(); - addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu); + auto helpMenu = m_helpMenu->menu(); + helpMenu->setIcon(QIcon::fromTheme(QStringLiteral("system-help"))); + menu->addMenu(helpMenu); } void DolphinMainWindow::updateToolBar() @@ -1084,6 +1146,9 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer) m_activeViewContainer = viewContainer; if (oldViewContainer) { + const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search")); + toggleSearchAction->disconnect(oldViewContainer); + // Disconnect all signals between the old view container (container, // view and url navigator) and main window. oldViewContainer->disconnect(this); @@ -1100,10 +1165,11 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer) m_actionHandler->setCurrentView(viewContainer->view()); updateHistory(); - updateEditActions(); + updateFileAndEditActions(); updatePasteAction(); updateViewActions(); updateGoActions(); + updateSearchAction(); const QUrl url = viewContainer->url(); emit urlChanged(url); @@ -1126,7 +1192,7 @@ void DolphinMainWindow::updateWindowTitle() void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mountPath) { - if (m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) { + if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) { m_tearDownFromPlacesRequested = true; m_terminalPanel->goHome(); // m_placesPanel->proceedWithTearDown() will be called in slotTerminalDirectoryChanged @@ -1137,7 +1203,7 @@ void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mo void DolphinMainWindow::slotStorageTearDownExternallyRequested(const QString& mountPath) { - if (m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) { + if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) { m_tearDownFromPlacesRequested = false; m_terminalPanel->goHome(); } @@ -1156,6 +1222,7 @@ void DolphinMainWindow::setupActions() QAction* newWindow = KStandardAction::openNew(this, &DolphinMainWindow::openNewMainWindow, actionCollection()); newWindow->setText(i18nc("@action:inmenu File", "New &Window")); + newWindow->setToolTip(i18nc("@info", "Open a new Dolphin window")); newWindow->setWhatsThis(xi18nc("@info:whatsthis", "This opens a new " "window just like this one with the current location and view." "You can drag and drop items between windows.")); @@ -1171,6 +1238,12 @@ void DolphinMainWindow::setupActions() actionCollection()->setDefaultShortcuts(newTab, {Qt::CTRL + Qt::Key_T, Qt::CTRL + Qt::SHIFT + Qt::Key_N}); connect(newTab, &QAction::triggered, this, &DolphinMainWindow::openNewActivatedTab); + QAction* addToPlaces = actionCollection()->addAction(QStringLiteral("add_to_places")); + addToPlaces->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new"))); + addToPlaces->setWhatsThis(xi18nc("@info:whatsthis", "This adds the selected folder " + "to the Places panel.")); + connect(addToPlaces, &QAction::triggered, this, &DolphinMainWindow::addToPlaces); + QAction* closeTab = KStandardAction::close(m_tabWidget, QOverload<>::of(&DolphinTabWidget::closeTab), actionCollection()); closeTab->setText(i18nc("@action:inmenu File", "Close Tab")); closeTab->setWhatsThis(i18nc("@info:whatsthis", "This closes the " @@ -1224,6 +1297,17 @@ void DolphinMainWindow::setupActions() "the find bar so we can have a look at it while the settings are " "explained.")); + // toggle_search acts as a copy of the main searchAction to be used mainly + // in the toolbar, with no default shortcut attached, to avoid messing with + // existing workflows (search bar always open and Ctrl-F to focus) + QAction *toggleSearchAction = actionCollection()->addAction(QStringLiteral("toggle_search")); + toggleSearchAction->setText(i18nc("@action:inmenu", "Toggle Search Bar")); + toggleSearchAction->setIconText(i18nc("@action:intoolbar", "Search")); + toggleSearchAction->setIcon(searchAction->icon()); + toggleSearchAction->setToolTip(searchAction->toolTip()); + toggleSearchAction->setWhatsThis(searchAction->whatsThis()); + toggleSearchAction->setCheckable(true); + QAction* selectAllAction = KStandardAction::selectAll(this, &DolphinMainWindow::selectAll, actionCollection()); selectAllAction->setWhatsThis(xi18nc("@info:whatsthis", "This selects all " "files and folders in the current location.")); @@ -1287,10 +1371,22 @@ void DolphinMainWindow::setupActions() connect(replaceLocation, &QAction::triggered, this, &DolphinMainWindow::replaceLocation); // setup 'Go' menu - QAction* backAction = KStandardAction::back(this, &DolphinMainWindow::goBack, actionCollection()); - auto backShortcuts = backAction->shortcuts(); + { + QScopedPointer backAction(KStandardAction::back(nullptr, nullptr, nullptr)); + m_backAction = new KToolBarPopupAction(backAction->icon(), backAction->text(), actionCollection()); + m_backAction->setObjectName(backAction->objectName()); + m_backAction->setShortcuts(backAction->shortcuts()); + } + m_backAction->setDelayed(true); + m_backAction->setStickyMenu(false); + connect(m_backAction, &QAction::triggered, this, &DolphinMainWindow::goBack); + connect(m_backAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowBackPopupMenu); + connect(m_backAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoBack); + actionCollection()->addAction(m_backAction->objectName(), m_backAction); + + auto backShortcuts = m_backAction->shortcuts(); backShortcuts.append(QKeySequence(Qt::Key_Backspace)); - actionCollection()->setDefaultShortcuts(backAction, backShortcuts); + actionCollection()->setDefaultShortcuts(m_backAction, backShortcuts); DolphinRecentTabsMenu* recentTabsMenu = new DolphinRecentTabsMenu(this); actionCollection()->addAction(QStringLiteral("closed_tabs"), recentTabsMenu); @@ -1319,7 +1415,25 @@ void DolphinMainWindow::setupActions() "be undone will ask for your confirmation.")); undoAction->setEnabled(false); // undo should be disabled by default - KStandardAction::forward(this, &DolphinMainWindow::goForward, actionCollection()); + { + QScopedPointer forwardAction(KStandardAction::forward(nullptr, nullptr, nullptr)); + m_forwardAction = new KToolBarPopupAction(forwardAction->icon(), forwardAction->text(), actionCollection()); + m_forwardAction->setObjectName(forwardAction->objectName()); + m_forwardAction->setShortcuts(forwardAction->shortcuts()); + } + m_forwardAction->setDelayed(true); + m_forwardAction->setStickyMenu(false); + connect(m_forwardAction, &QAction::triggered, this, &DolphinMainWindow::goForward); + connect(m_forwardAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowForwardPopupMenu); + connect(m_forwardAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoForward); + actionCollection()->addAction(m_forwardAction->objectName(), m_forwardAction); + actionCollection()->setDefaultShortcuts(m_forwardAction, m_forwardAction->shortcuts()); + + // enable middle-click to open in a new tab + auto *middleClickEventFilter = new MiddleClickActionEventFilter(this); + connect(middleClickEventFilter, &MiddleClickActionEventFilter::actionMiddleClicked, this, &DolphinMainWindow::slotBackForwardActionMiddleClicked); + m_backAction->menu()->installEventFilter(middleClickEventFilter); + m_forwardAction->menu()->installEventFilter(middleClickEventFilter); KStandardAction::up(this, &DolphinMainWindow::goUp, actionCollection()); QAction* homeAction = KStandardAction::home(this, &DolphinMainWindow::goHome, actionCollection()); homeAction->setWhatsThis(xi18nc("@info:whatsthis", "Go to your " @@ -1351,7 +1465,7 @@ void DolphinMainWindow::setupActions() openTerminal->setWhatsThis(xi18nc("@info:whatsthis", "This opens a terminal application for the viewed location." "To learn more about terminals use the help in the terminal application.")); - openTerminal->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal"))); + openTerminal->setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts"))); actionCollection()->setDefaultShortcut(openTerminal, Qt::SHIFT + Qt::Key_F4); connect(openTerminal, &QAction::triggered, this, &DolphinMainWindow::openTerminal); } @@ -1538,7 +1652,7 @@ void DolphinMainWindow::setupDockWidgets() this, &DolphinMainWindow::slotTerminalPanelVisibilityChanged); QAction* terminalAction = terminalDock->toggleViewAction(); - createPanelAction(QIcon::fromTheme(QStringLiteral("utilities-terminal")), Qt::Key_F4, terminalAction, QStringLiteral("show_terminal_panel")); + createPanelAction(QIcon::fromTheme(QStringLiteral("dialog-scripts")), Qt::Key_F4, terminalAction, QStringLiteral("show_terminal_panel")); addDockWidget(Qt::BottomDockWidgetArea, terminalDock); connect(this, &DolphinMainWindow::urlChanged, @@ -1603,7 +1717,7 @@ void DolphinMainWindow::setupDockWidgets() this, &DolphinMainWindow::slotStorageTearDownExternallyRequested); m_tabWidget->slotPlacesPanelVisibilityChanged(m_placesPanel->isVisible()); - auto actionShowAllPlaces = new QAction(QIcon::fromTheme(QStringLiteral("hint")), i18nc("@item:inmenu", "Show Hidden Places"), this); + auto actionShowAllPlaces = new QAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18nc("@item:inmenu", "Show Hidden Places"), this); actionShowAllPlaces->setCheckable(true); actionShowAllPlaces->setDisabled(true); actionShowAllPlaces->setWhatsThis(i18nc("@info:whatsthis", "This displays " @@ -1611,13 +1725,13 @@ void DolphinMainWindow::setupDockWidgets() "appear semi-transparent unless you uncheck their hide property.")); connect(actionShowAllPlaces, &QAction::triggered, this, [actionShowAllPlaces, this](bool checked){ - actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("visibility") : QStringLiteral("hint"))); + actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); m_placesPanel->showHiddenEntries(checked); }); connect(m_placesPanel, &PlacesPanel::showHiddenEntriesChanged, this, [actionShowAllPlaces] (bool checked){ actionShowAllPlaces->setChecked(checked); - actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("visibility") : QStringLiteral("hint"))); + actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); }); actionCollection()->action(QStringLiteral("show_places_panel")) @@ -1640,8 +1754,9 @@ void DolphinMainWindow::setupDockWidgets() " to display it again.") + panelWhatsThis); // Add actions into the "Panels" menu - KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Panels"), this); + KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Show Panels"), this); actionCollection()->addAction(QStringLiteral("panels"), panelsMenu); + panelsMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-sidetree"))); panelsMenu->setDelayed(false); const KActionCollection* ac = actionCollection(); panelsMenu->addAction(ac->action(QStringLiteral("show_places_panel"))); @@ -1659,15 +1774,20 @@ void DolphinMainWindow::setupDockWidgets() }); } -void DolphinMainWindow::updateEditActions() + +void DolphinMainWindow::updateFileAndEditActions() { const KFileItemList list = m_activeViewContainer->view()->selectedItems(); + const KActionCollection* col = actionCollection(); + QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places")); + if (list.isEmpty()) { stateChanged(QStringLiteral("has_no_selection")); + + addToPlacesAction->setText(i18nc("@action:inmenu Add current folder to places", "Add '%1' to Places", m_activeViewContainer->placesText())); } else { stateChanged(QStringLiteral("has_selection")); - KActionCollection* col = actionCollection(); QAction* renameAction = col->action(KStandardAction::name(KStandardAction::RenameFile)); QAction* moveToTrashAction = col->action(KStandardAction::name(KStandardAction::MoveToTrash)); QAction* deleteAction = col->action(KStandardAction::name(KStandardAction::DeleteFile)); @@ -1675,6 +1795,14 @@ void DolphinMainWindow::updateEditActions() QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler QAction* showTarget = col->action(QStringLiteral("show_target")); + if (list.length() == 1 && list.first().isDir()) { + addToPlacesAction->setEnabled(true); + addToPlacesAction->setText(i18nc("@action:inmenu Add current folder to places", "Add '%1' to Places", list.first().name())); + } else { + addToPlacesAction->setEnabled(false); + addToPlacesAction->setText(i18nc("@action:inmenu Add current folder to places", "Add to Places")); + } + KFileItemListProperties capabilities(list); const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); @@ -1727,10 +1855,9 @@ void DolphinMainWindow::createControlButton() m_controlButton = new QToolButton(this); m_controlButton->setIcon(QIcon::fromTheme(QStringLiteral("application-menu"))); - m_controlButton->setText(i18nc("@action", "Control")); + m_controlButton->setToolTip(i18nc("@action", "Show menu")); m_controlButton->setAttribute(Qt::WidgetAttribute::WA_CustomWhatsThis); m_controlButton->setPopupMode(QToolButton::InstantPopup); - m_controlButton->setToolButtonStyle(toolBar()->toolButtonStyle()); QMenu* controlMenu = new QMenu(m_controlButton); connect(controlMenu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateControlMenu); @@ -1741,8 +1868,6 @@ void DolphinMainWindow::createControlButton() toolBar()->addWidget(m_controlButton); connect(toolBar(), &KToolBar::iconSizeChanged, m_controlButton, &QToolButton::setIconSize); - connect(toolBar(), &KToolBar::toolButtonStyleChanged, - m_controlButton, &QToolButton::setToolButtonStyle); // The added widgets are owned by the toolbar and may get deleted when e.g. the toolbar // gets edited. In this case we must add them again. The adding is done asynchronously by @@ -1805,6 +1930,11 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container) this, &DolphinMainWindow::updateFilterBarAction); connect(container, &DolphinViewContainer::writeStateChanged, this, &DolphinMainWindow::slotWriteStateChanged); + connect(container, &DolphinViewContainer::searchModeEnabledChanged, + this, &DolphinMainWindow::updateSearchAction); + + const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search")); + connect(toggleSearchAction, &QAction::triggered, container, &DolphinViewContainer::setSearchModeEnabled); const DolphinView* view = container->view(); connect(view, &DolphinView::selectionChanged, @@ -2089,10 +2219,6 @@ void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job) bool DolphinMainWindow::isUrlOpen(const QString& url) { - if (m_tabWidget->getIndexByUrl(QUrl::fromUserInput((url))).first >= 0) { - return true; - } else { - return false; - } + return m_tabWidget->isUrlOpen(QUrl::fromUserInput((url))); } diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index dcfd9bce2..3d86340d6 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -47,6 +47,7 @@ class KFileItemList; class KJob; class KNewFileMenu; class KHelpMenu; +class KToolBarPopupAction; class QToolButton; class QIcon; class PlacesPanel; @@ -255,6 +256,9 @@ private slots: /** Replaces the URL navigator by a search box to find files. */ void find(); + /** Updates the state of the search action according to the view container. */ + void updateSearchAction(); + /** * Updates the text of the paste action dependent on * the number of items which are in the clipboard. @@ -381,6 +385,11 @@ private slots: */ void openNewActivatedTab(); + /** + * Adds the current URL as an entry to the Places panel + */ + void addToPlaces(); + /** * Opens a new tab in the background showing the URL \a url. */ @@ -501,6 +510,36 @@ private slots: */ void slotToolBarActionMiddleClicked(QAction *action); + /** + * Is called before the Back popup menu is shown. This slot will populate + * the menu with history data + */ + void slotAboutToShowBackPopupMenu(); + + /** + * This slot is used by the Back Popup Menu to go back to a specific + * history index. The QAction::data will carry an int with the index + * to go to. + */ + void slotGoBack(QAction* action); + + /** + * Middle clicking Back/Forward will open the resulting folder in a new tab. + */ + void slotBackForwardActionMiddleClicked(QAction *action); + + /** + * Is called before the Forward popup menu is shown. This slot will populate + * the menu with history data + */ + void slotAboutToShowForwardPopupMenu(); + + /** + * This slot is used by the Forward Popup Menu to go forward to a specific + * history index. The QAction::data will carry an int with the index + * to go to. + */ + void slotGoForward(QAction* action); private: /** * Sets up the various menus and actions and connects them. @@ -512,7 +551,7 @@ private: */ void setupDockWidgets(); - void updateEditActions(); + void updateFileAndEditActions(); void updateViewActions(); void updateGoActions(); @@ -591,6 +630,9 @@ private: TerminalPanel* m_terminalPanel; PlacesPanel* m_placesPanel; bool m_tearDownFromPlacesRequested; + + KToolBarPopupAction* m_backAction; + KToolBarPopupAction* m_forwardAction; }; inline DolphinViewContainer* DolphinMainWindow::activeViewContainer() const diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp index a4d7fdf78..607917f9a 100644 --- a/src/dolphinpart.cpp +++ b/src/dolphinpart.cpp @@ -222,7 +222,7 @@ void DolphinPart::createActions() #ifndef Q_OS_WIN if (KAuthorized::authorize(QStringLiteral("shell_access"))) { m_openTerminalAction = actionCollection()->addAction(QStringLiteral("open_terminal")); - m_openTerminalAction->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal"))); + m_openTerminalAction->setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts"))); m_openTerminalAction->setText(i18nc("@action:inmenu Tools", "Open &Terminal")); connect(m_openTerminalAction, &QAction::triggered, this, &DolphinPart::slotOpenTerminal); actionCollection()->setDefaultShortcut(m_openTerminalAction, Qt::Key_F4); diff --git a/src/dolphinpart.desktop b/src/dolphinpart.desktop index 19c072a02..3d53ecbd6 100644 --- a/src/dolphinpart.desktop +++ b/src/dolphinpart.desktop @@ -22,7 +22,7 @@ Name[id]=Tampilan Dolphin Name[it]=Vista di Dolphin Name[ja]=Dolphin ビュー Name[ko]=Dolphin 보기 -Name[lt]=Dolphin žiūryklė +Name[lt]=Dolphin rodinys Name[ml]=ഡോള്‍ഫിന്‍ അവതരണരീതി Name[nb]=Dolphin visning Name[nl]=Dolphin-weergave @@ -82,7 +82,7 @@ Name[id]=Ikon Name[it]=Icone Name[ja]=アイコン Name[ko]=아이콘 -Name[lt]=Ženkliukai +Name[lt]=Piktogramos Name[ml]=സൂചനാചിത്രങ്ങള്‍ Name[nb]=Ikoner Name[nl]=Pictogrammen @@ -183,7 +183,7 @@ Name[id]=Perincian Name[it]=Dettagli Name[ja]=詳細 Name[ko]=자세히 -Name[lt]=Informacija +Name[lt]=Išsamus Name[ml]=വിശദമായി Name[nb]=Detaljer Name[nl]=Details diff --git a/src/dolphintabwidget.cpp b/src/dolphintabwidget.cpp index 7928c510e..ec0c783bc 100644 --- a/src/dolphintabwidget.cpp +++ b/src/dolphintabwidget.cpp @@ -130,6 +130,11 @@ void DolphinTabWidget::refreshViews() } } +bool DolphinTabWidget::isUrlOpen(const QUrl &url) const +{ + return indexByUrl(url).first >= 0; +} + void DolphinTabWidget::openNewActivatedTab() { const DolphinViewContainer* oldActiveViewContainer = currentTabPage()->activeViewContainer(); @@ -161,6 +166,7 @@ void DolphinTabWidget::openNewTab(const QUrl& primaryUrl, const QUrl& secondaryU QWidget* focusWidget = QApplication::focusWidget(); DolphinTabPage* tabPage = new DolphinTabPage(primaryUrl, secondaryUrl, this); + tabPage->setActive(false); tabPage->setPlacesSelectorVisible(m_placesSelectorVisible); connect(tabPage, &DolphinTabPage::activeViewChanged, this, &DolphinTabWidget::activeViewChanged); @@ -170,7 +176,7 @@ void DolphinTabWidget::openNewTab(const QUrl& primaryUrl, const QUrl& secondaryU if (tabPlacement == AfterCurrentTab) { newTabIndex = currentIndex() + 1; } - insertTab(newTabIndex, tabPage, QIcon::fromTheme(KIO::iconNameForUrl(primaryUrl)), tabName(tabPage)); + insertTab(newTabIndex, tabPage, QIcon() /* loaded in tabInserted */, tabName(tabPage)); if (focusWidget) { // The DolphinViewContainer grabbed the keyboard focus. As the tab is opened @@ -186,11 +192,13 @@ void DolphinTabWidget::openDirectories(const QList& dirs, bool splitView) QList::const_iterator it = dirs.constBegin(); while (it != dirs.constEnd()) { const QUrl& primaryUrl = *(it++); - const QPair viewLocation = getIndexByUrl(primaryUrl); - if (viewLocation.first >= 0) { - setCurrentIndex(viewLocation.first); - const auto tabPage = tabPageAt(viewLocation.first); - if (viewLocation.second) { + const QPair indexInfo = indexByUrl(primaryUrl); + const int index = indexInfo.first; + const bool isInPrimaryView = indexInfo.second; + if (index >= 0) { + setCurrentIndex(index); + const auto tabPage = tabPageAt(index); + if (isInPrimaryView) { tabPage->primaryViewContainer()->setActive(true); } else { tabPage->secondaryViewContainer()->setActive(true); @@ -329,7 +337,12 @@ void DolphinTabWidget::tabUrlChanged(const QUrl& url) const int index = indexOf(qobject_cast(sender())); if (index >= 0) { tabBar()->setTabText(index, tabName(tabPageAt(index))); - tabBar()->setTabIcon(index, QIcon::fromTheme(KIO::iconNameForUrl(url))); + if (tabBar()->isVisible()) { + tabBar()->setTabIcon(index, QIcon::fromTheme(KIO::iconNameForUrl(url))); + } else { + // Mark as dirty, actually load once the tab bar actually gets shown + tabBar()->setTabIcon(index, QIcon()); + } // Emit the currentUrlChanged signal if the url of the current tab has been changed. if (index == currentIndex()) { @@ -357,6 +370,13 @@ void DolphinTabWidget::tabInserted(int index) QTabWidget::tabInserted(index); if (count() > 1) { + // Resolve all pending tab icons + for (int i = 0; i < count(); ++i) { + if (tabBar()->tabIcon(i).isNull()) { + tabBar()->setTabIcon(i, QIcon::fromTheme(KIO::iconNameForUrl(tabPageAt(i)->activeViewContainer()->url()))); + } + } + tabBar()->show(); } @@ -387,7 +407,7 @@ QString DolphinTabWidget::tabName(DolphinTabPage* tabPage) const return name.replace('&', QLatin1String("&&")); } -QPair DolphinTabWidget::getIndexByUrl(const QUrl& url) const +QPair DolphinTabWidget::indexByUrl(const QUrl& url) const { for (int i = 0; i < count(); i++) { const auto tabPage = tabPageAt(i); diff --git a/src/dolphintabwidget.h b/src/dolphintabwidget.h index 7eb001b21..4351a40a8 100644 --- a/src/dolphintabwidget.h +++ b/src/dolphintabwidget.h @@ -79,14 +79,10 @@ public: void refreshViews(); /** - * @param url The URL that we would like - * @return a QPair with first containing the index of the tab with the - * desired URL or -1 if not found. Second says true if URL is in primary - * view container, false otherwise. False means the URL is in the secondary - * view container, unless first == -1. In that case the value of second - * is meaningless. + * @return Whether any of the tab pages contains @p url in their primary + * or secondary view. */ - QPair getIndexByUrl(const QUrl& url) const; + bool isUrlOpen(const QUrl& url) const; signals: /** @@ -221,6 +217,16 @@ private: */ QString tabName(DolphinTabPage* tabPage) const; + /** + * @param url The URL that we would like + * @return a QPair with first containing the index of the tab with the + * desired URL or -1 if not found. Second says true if URL is in primary + * view container, false otherwise. False means the URL is in the secondary + * view container, unless first == -1. In that case the value of second + * is meaningless. + */ + QPair indexByUrl(const QUrl& url) const; + private: /** Caches the (negated) places panel visibility */ bool m_placesSelectorVisible; diff --git a/src/dolphinui.rc b/src/dolphinui.rc index b90321d05..dcacc56c4 100644 --- a/src/dolphinui.rc +++ b/src/dolphinui.rc @@ -1,5 +1,5 @@ - + @@ -8,6 +8,8 @@ + + @@ -21,6 +23,10 @@ + + + + @@ -34,7 +40,7 @@ - + Location Bar @@ -98,10 +104,11 @@ - - + + + @@ -113,9 +120,11 @@ + + diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 536ab0fa8..41706288c 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -414,6 +414,8 @@ void DolphinViewContainer::setSearchModeEnabled(bool enabled) } m_searchModeEnabled = enabled; + + emit searchModeEnabledChanged(enabled); } bool DolphinViewContainer::isSearchModeEnabled() const @@ -456,7 +458,7 @@ QString DolphinViewContainer::caption() const } KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel(); - const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, url(), 1, Qt::MatchExactly); + const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegExp); if (!matchedPlaces.isEmpty()) { return placesModel->text(matchedPlaces.first()); @@ -699,7 +701,7 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url) app = browser; if (app.startsWith('!')) { // a literal command has been configured, remove the '!' prefix - app = app.mid(1); + app.remove(0, 1); } } } else { @@ -787,7 +789,7 @@ void DolphinViewContainer::showErrorMessage(const QString& msg) bool DolphinViewContainer::isSearchUrl(const QUrl& url) const { - return url.scheme().contains(QStringLiteral("search")); + return url.scheme().contains(QLatin1String("search")); } void DolphinViewContainer::saveViewState() diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h index 2c4c7a7e1..5207d2d35 100644 --- a/src/dolphinviewcontainer.h +++ b/src/dolphinviewcontainer.h @@ -118,11 +118,8 @@ public: /** Returns true, if the filter bar is visible. */ bool isFilterBarVisible() const; - /** - * Enables the search mode, if \p enabled is true. In the search mode the URL navigator - * will be hidden and replaced by a line editor that allows to enter a search term. - */ - void setSearchModeEnabled(bool enabled); + + /** Returns true if the search mode is enabled. */ bool isSearchModeEnabled() const; /** @@ -160,11 +157,21 @@ public slots: */ void setFilterBarVisible(bool visible); + /** + * Enables the search mode, if \p enabled is true. In the search mode the URL navigator + * will be hidden and replaced by a line editor that allows to enter a search term. + */ + void setSearchModeEnabled(bool enabled); + signals: /** * Is emitted whenever the filter bar has changed its visibility state. */ void showFilterBarChanged(bool shown); + /** + * Is emitted whenever the search mode has changed its state. + */ + void searchModeEnabledChanged(bool enabled); /** * Is emitted when the write state of the folder has been changed. The application diff --git a/src/global.cpp b/src/global.cpp index 21660a828..48e78e9ea 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -77,12 +77,6 @@ bool Dolphin::attachToExistingInstance(const QList& inputUrls, bool openFi return false; } - const QStringList services = QDBusConnection::sessionBus().interface()->registeredServiceNames().value(); - - // Don't match the service without trailing "-" (unique instance) - const QString pattern = QStringLiteral("org.kde.dolphin-"); - // Don't match the pid without leading "-" - const QString myPid = QStringLiteral("-") + QString::number(QCoreApplication::applicationPid()); QVector, QStringList>> dolphinServices; if (!preferredService.isEmpty()) { QSharedPointer preferred( @@ -91,11 +85,16 @@ bool Dolphin::attachToExistingInstance(const QList& inputUrls, bool openFi QStringLiteral("org.kde.dolphin.MainWindow")) ); if (preferred->isValid() && !preferred->lastError().isValid()) { - dolphinServices.append(qMakePair(preferred, QStringList() )); + dolphinServices.append(qMakePair(preferred, QStringList())); } } // find all dolphin instances + const QStringList services = QDBusConnection::sessionBus().interface()->registeredServiceNames().value(); + // Don't match the service without trailing "-" (unique instance) + const QString pattern = QStringLiteral("org.kde.dolphin-"); + // Don't match the pid without leading "-" + const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid()); for (const QString& service : services) { if (service.startsWith(pattern) && !service.endsWith(myPid)) { // Check if instance can handle our URLs @@ -104,10 +103,9 @@ bool Dolphin::attachToExistingInstance(const QList& inputUrls, bool openFi QStringLiteral("/dolphin/Dolphin_1"), QStringLiteral("org.kde.dolphin.MainWindow")) ); - if (!instance->isValid() || instance->lastError().isValid()) { - continue; + if (instance->isValid() && !instance->lastError().isValid()) { + dolphinServices.append(qMakePair(instance, QStringList())); } - dolphinServices.append(qMakePair(instance, QStringList())); } } @@ -124,9 +122,9 @@ bool Dolphin::attachToExistingInstance(const QList& inputUrls, bool openFi for (auto& service: dolphinServices) { QDBusReply isUrlOpen = service.first->call(QStringLiteral("isUrlOpen"), url); if (isUrlOpen.isValid() && isUrlOpen.value()) { - service.second.append(url); - urlFound = true; - break; + service.second.append(url); + urlFound = true; + break; } } if (!urlFound) { diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index 8145a00f1..c11aae3d2 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -917,6 +917,7 @@ void KFileItemModel::resortAllItems() void KFileItemModel::slotCompleted() { + m_maximumUpdateIntervalTimer->stop(); dispatchPendingItemsToInsert(); if (!m_urlsToExpand.isEmpty()) { @@ -1007,7 +1008,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis } } - if (useMaximumUpdateInterval() && !m_maximumUpdateIntervalTimer->isActive()) { + if (!m_maximumUpdateIntervalTimer->isActive()) { // Assure that items get dispatched if no completed() or canceled() signal is // emitted during the maximum update interval. m_maximumUpdateIntervalTimer->start(); @@ -1606,7 +1607,7 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, if (m_requestRole[DestinationRole]) { QString destination = item.linkDest(); if (destination.isEmpty()) { - destination = QStringLiteral("-"); + destination = QLatin1Char('-'); } data.insert(sharedValue("destination"), destination); } @@ -1828,8 +1829,15 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const default: { const QByteArray role = roleForType(m_sortRole); - result = QString::compare(a->values.value(role).toString(), - b->values.value(role).toString()); + const QString roleValueA = a->values.value(role).toString(); + const QString roleValueB = b->values.value(role).toString(); + if (!roleValueA.isEmpty() && roleValueB.isEmpty()) { + result = -1; + } else if (roleValueA.isEmpty() && !roleValueB.isEmpty()) { + result = +1; + } else { + result = QString::compare(roleValueA, roleValueB); + } break; } @@ -1875,11 +1883,6 @@ int KFileItemModel::stringCompare(const QString& a, const QString& b, const QCol return QString::compare(a, b, Qt::CaseSensitive); } -bool KFileItemModel::useMaximumUpdateInterval() const -{ - return !m_dirLister->url().isLocalFile(); -} - QList > KFileItemModel::nameRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); @@ -1905,28 +1908,35 @@ QList > KFileItemModel::nameRoleGroups() const if (firstChar != newFirstChar) { QString newGroupValue; if (newFirstChar.isLetter()) { - // Try to find a matching group in the range 'A' to 'Z'. - static std::vector lettersAtoZ; - lettersAtoZ.reserve('Z' - 'A' + 1); - if (lettersAtoZ.empty()) { - for (char c = 'A'; c <= 'Z'; ++c) { - lettersAtoZ.push_back(QLatin1Char(c)); + + if (m_collator.compare(newFirstChar, QChar(QLatin1Char('A'))) >= 0 && m_collator.compare(newFirstChar, QChar(QLatin1Char('Z'))) <= 0) { + // WARNING! Symbols based on latin 'Z' like 'Z' with acute are treated wrong as non Latin and put in a new group. + + // Try to find a matching group in the range 'A' to 'Z'. + static std::vector lettersAtoZ; + lettersAtoZ.reserve('Z' - 'A' + 1); + if (lettersAtoZ.empty()) { + for (char c = 'A'; c <= 'Z'; ++c) { + lettersAtoZ.push_back(QLatin1Char(c)); + } } - } - auto localeAwareLessThan = [this](QChar c1, QChar c2) -> bool { - return m_collator.compare(c1, c2) < 0; - }; + auto localeAwareLessThan = [this](QChar c1, QChar c2) -> bool { + return m_collator.compare(c1, c2) < 0; + }; - std::vector::iterator it = std::lower_bound(lettersAtoZ.begin(), lettersAtoZ.end(), newFirstChar, localeAwareLessThan); - if (it != lettersAtoZ.end()) { - if (localeAwareLessThan(newFirstChar, *it) && it != lettersAtoZ.begin()) { - // newFirstChar belongs to the group preceding *it. - // Example: for an umlaut 'A' in the German locale, *it would be 'B' now. - --it; + std::vector::iterator it = std::lower_bound(lettersAtoZ.begin(), lettersAtoZ.end(), newFirstChar, localeAwareLessThan); + if (it != lettersAtoZ.end()) { + if (localeAwareLessThan(newFirstChar, *it)) { + // newFirstChar belongs to the group preceding *it. + // Example: for an umlaut 'A' in the German locale, *it would be 'B' now. + --it; + } + newGroupValue = *it; } - newGroupValue = *it; + } else { + // Symbols from non Latin-based scripts newGroupValue = newFirstChar; } } else if (newFirstChar >= QLatin1Char('0') && newFirstChar <= QLatin1Char('9')) { diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 0f7926aae..c2dfd0167 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -382,8 +382,6 @@ private: int stringCompare(const QString& a, const QString& b, const QCollator& collator) const; - bool useMaximumUpdateInterval() const; - QList > nameRoleGroups() const; QList > sizeRoleGroups() const; QList > timeRoleGroups(const std::function &fileTimeCb) const; diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 15c01726f..c963b7196 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -1165,7 +1165,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() do { QString lastTextLine = nameText.mid(line.textStart()); lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine, - Qt::ElideRight, + Qt::ElideMiddle, elidingWidth); const QString elidedText = nameText.left(line.textStart()) + lastTextLine; nameTextInfo->staticText.setText(elidedText); @@ -1221,7 +1221,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() textLine.setLineWidth(maxWidth); requiredWidth = textLine.naturalTextWidth(); if (requiredWidth > maxWidth) { - const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, maxWidth); textInfo->staticText.setText(elidedText); requiredWidth = m_customizedFontMetrics.width(elidedText); } else if (role == "rating") { @@ -1270,7 +1270,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() qreal requiredWidth = m_customizedFontMetrics.width(text); if (requiredWidth > maxWidth) { requiredWidth = maxWidth; - const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); + const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, maxWidth); textInfo->staticText.setText(elidedText); } @@ -1327,7 +1327,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() } if (requiredWidth > availableTextWidth) { - text = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, availableTextWidth); + text = m_customizedFontMetrics.elidedText(text, Qt::ElideMiddle, availableTextWidth); requiredWidth = m_customizedFontMetrics.width(text); } @@ -1463,33 +1463,16 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStrin { static const QIcon fallbackIcon = QIcon::fromTheme(QStringLiteral("unknown")); - int requestedSize = size; - if (size <= KIconLoader::SizeSmall) { - requestedSize = KIconLoader::SizeSmall; - } else if (size <= KIconLoader::SizeSmallMedium) { - requestedSize = KIconLoader::SizeSmallMedium; - } else if (size <= KIconLoader::SizeMedium) { - requestedSize = KIconLoader::SizeMedium; - } else if (size <= KIconLoader::SizeLarge) { - requestedSize = KIconLoader::SizeLarge; - } else if (size <= KIconLoader::SizeHuge) { - requestedSize = KIconLoader::SizeHuge; - } else if (size <= KIconLoader::SizeEnormous) { - requestedSize = KIconLoader::SizeEnormous; - } else if (size <= KIconLoader::SizeEnormous * 2) { - requestedSize = KIconLoader::SizeEnormous * 2; - } size *= qApp->devicePixelRatio(); - requestedSize *= qApp->devicePixelRatio(); - const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(QStringLiteral(":")) % ":" % QString::number(size) % ":" % QString::number(mode); + const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(QLatin1Char(':')) % ":" % QString::number(size) % ":" % QString::number(mode); QPixmap pixmap; if (!QPixmapCache::find(key, pixmap)) { const QIcon icon = QIcon::fromTheme(name, fallbackIcon); - pixmap = icon.pixmap(requestedSize / qApp->devicePixelRatio(), requestedSize / qApp->devicePixelRatio(), mode); - if (requestedSize != size) { + pixmap = icon.pixmap(size / qApp->devicePixelRatio(), size / qApp->devicePixelRatio(), mode); + if (pixmap.width() != size || pixmap.height() != size) { KPixmapModifier::scale(pixmap, QSize(size, size)); } diff --git a/src/kitemviews/private/kbaloorolesprovider.cpp b/src/kitemviews/private/kbaloorolesprovider.cpp index f3671540d..8a2a64b31 100644 --- a/src/kitemviews/private/kbaloorolesprovider.cpp +++ b/src/kitemviews/private/kbaloorolesprovider.cpp @@ -155,5 +155,5 @@ QString KBalooRolesProvider::tagsFromValues(const QStringList& values) const QCollator coll; coll.setNumericMode(true); std::sort(alphabeticalOrderTags.begin(), alphabeticalOrderTags.end(), [&](const QString& s1, const QString& s2){ return coll.compare(s1, s2) < 0; }); - return alphabeticalOrderTags.join(QStringLiteral(", ")); + return alphabeticalOrderTags.join(QLatin1String(", ")); } diff --git a/src/kitemviews/private/kitemlistheaderwidget.cpp b/src/kitemviews/private/kitemlistheaderwidget.cpp index a3f3f521f..93d1389aa 100644 --- a/src/kitemviews/private/kitemlistheaderwidget.cpp +++ b/src/kitemviews/private/kitemlistheaderwidget.cpp @@ -93,7 +93,6 @@ void KItemListHeaderWidget::setColumns(const QList& roles) { foreach (const QByteArray& role, roles) { if (!m_columnWidths.contains(role)) { - m_columnWidths.remove(role); m_preferredColumnWidths.remove(role); } } diff --git a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp index ffa92a1cf..8f18b92bf 100644 --- a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp +++ b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp @@ -46,7 +46,7 @@ void KItemListKeyboardSearchManager::addKeys(const QString& keys) // Do not start a new search if the user pressed Space. Only add // it to the search string if a search is in progress already. - if (newSearch && keys == QLatin1String(" ")) { + if (newSearch && keys == QLatin1Char(' ')) { return; } diff --git a/src/middleclickactioneventfilter.cpp b/src/middleclickactioneventfilter.cpp index e0917850a..293e16e0c 100644 --- a/src/middleclickactioneventfilter.cpp +++ b/src/middleclickactioneventfilter.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -39,16 +40,32 @@ bool MiddleClickActionEventFilter::eventFilter(QObject *watched, QEvent *event) if (me->button() == Qt::MiddleButton) { QToolBar *toolBar = qobject_cast(watched); - - QAction *action = toolBar->actionAt(me->pos()); - if (action) { - if (event->type() == QEvent::MouseButtonPress) { - m_lastMiddlePressedAction = action; - } else if (event->type() == QEvent::MouseButtonRelease) { - if (m_lastMiddlePressedAction == action) { - emit actionMiddleClicked(action); + if (toolBar) { + QAction *action = toolBar->actionAt(me->pos()); + if (action) { + if (event->type() == QEvent::MouseButtonPress) { + m_lastMiddlePressedAction = action; + } else if (event->type() == QEvent::MouseButtonRelease) { + if (m_lastMiddlePressedAction == action) { + emit actionMiddleClicked(action); + } + m_lastMiddlePressedAction = nullptr; + } + } + } + QMenu *menu = qobject_cast(watched); + if (menu) { + QAction *action = menu->actionAt(me->pos()); + if (action) { + if (event->type() == QEvent::MouseButtonPress) { + m_lastMiddlePressedAction = action; + } else if (event->type() == QEvent::MouseButtonRelease) { + if (m_lastMiddlePressedAction == action) { + emit actionMiddleClicked(action); + return true; + } + m_lastMiddlePressedAction = nullptr; } - m_lastMiddlePressedAction = nullptr; } } } diff --git a/src/org.kde.dolphin.desktop b/src/org.kde.dolphin.desktop index e75eeab99..3e71051ef 100755 --- a/src/org.kde.dolphin.desktop +++ b/src/org.kde.dolphin.desktop @@ -72,7 +72,7 @@ GenericName[id]=Pengelola File GenericName[it]=Gestore dei file GenericName[ja]=ファイルマネージャ GenericName[ko]=파일 관리자 -GenericName[lt]=Failų tvarkyklė +GenericName[lt]=Failų tvarkytuvė GenericName[ml]=ഫയല്‍ മാനേജര്‍ GenericName[nb]=Filbehandler GenericName[nl]=Bestandsbeheerder diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp index 020c41e55..01f338461 100644 --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -111,7 +111,7 @@ void FoldersPanel::rename(const KFileItem& item) bool FoldersPanel::urlChanged() { - if (!url().isValid() || url().scheme().contains(QStringLiteral("search"))) { + if (!url().isValid() || url().scheme().contains(QLatin1String("search"))) { // Skip results shown by a search, as possible identical // directory names are useless without parent-path information. return false; @@ -258,7 +258,7 @@ void FoldersPanel::slotRoleEditingFinished(int index, const QByteArray& role, co if (role == "text") { const KFileItem item = m_model->fileItem(index); const QString newName = value.toString(); - if (!newName.isEmpty() && newName != item.text() && newName != QLatin1String(".") && newName != QLatin1String("..")) { + if (!newName.isEmpty() && newName != item.text() && newName != QLatin1Char('.') && newName != QLatin1String("..")) { const QUrl oldUrl = item.url(); QUrl newUrl = oldUrl.adjusted(QUrl::RemoveFilename); newUrl.setPath(newUrl.path() + KIO::encodeFileName(newName)); diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp index 363ad818d..2a8682a12 100644 --- a/src/panels/information/informationpanelcontent.cpp +++ b/src/panels/information/informationpanelcontent.cpp @@ -46,11 +46,18 @@ #include #include #include +#include +#include +#include +#include #include "dolphin_informationpanelsettings.h" #include "phononwidget.h" #include "pixmapviewer.h" +const int PLAY_ARROW_SIZE = 24; +const int PLAY_ARROW_BORDER_SIZE = 2; + InformationPanelContent::InformationPanelContent(QWidget* parent) : QWidget(parent), m_item(), @@ -61,7 +68,8 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) : m_nameLabel(nullptr), m_metaDataWidget(nullptr), m_metaDataArea(nullptr), - m_placesItemModel(nullptr) + m_placesItemModel(nullptr), + m_isVideo(false) { parent->installEventFilter(this); @@ -161,11 +169,47 @@ void InformationPanelContent::showItem(const KFileItem& item) if (item != m_item) { m_item = item; + m_preview->stopAnimatedImage(); refreshMetaData(); } refreshPreview(); } +void InformationPanelContent::refreshPixmapView() +{ + // If there is a preview job, kill it to prevent that we have jobs for + // multiple items running, and thus a race condition (bug 250787). + if (m_previewJob) { + m_previewJob->kill(); + } + + // try to get a preview pixmap from the item... + + // Mark the currently shown preview as outdated. This is done + // with a small delay to prevent a flickering when the next preview + // can be shown within a short timeframe. This timer is not started + // for directories, as directory previews might fail and return the + // same icon. + if (!m_item.isDir()) { + m_outdatedPreviewTimer->start(); + } + + QStringList plugins = KIO::PreviewJob::availablePlugins(); + m_previewJob = new KIO::PreviewJob(KFileItemList() << m_item, + QSize(m_preview->width(), m_preview->height()), + &plugins); + m_previewJob->setScaleType(KIO::PreviewJob::Unscaled); + m_previewJob->setIgnoreMaximumSize(m_item.isLocalFile()); + if (m_previewJob->uiDelegate()) { + KJobWidgets::setWindow(m_previewJob, this); + } + + connect(m_previewJob.data(), &KIO::PreviewJob::gotPreview, + this, &InformationPanelContent::showPreview); + connect(m_previewJob.data(), &KIO::PreviewJob::failed, + this, &InformationPanelContent::showIcon); +} + void InformationPanelContent::refreshPreview() { // If there is a preview job, kill it to prevent that we have jobs for @@ -174,11 +218,13 @@ void InformationPanelContent::refreshPreview() m_previewJob->kill(); } + m_preview->setCursor(Qt::ArrowCursor); + bool usePhonon = false; setNameLabelText(m_item.text()); if (InformationPanelSettings::previewsShown()) { const QUrl itemUrl = m_item.url(); - const bool isSearchUrl = itemUrl.scheme().contains(QStringLiteral("search")) && m_item.localPath().isEmpty(); + const bool isSearchUrl = itemUrl.scheme().contains(QLatin1String("search")) && m_item.localPath().isEmpty(); if (isSearchUrl) { m_preview->show(); @@ -188,56 +234,54 @@ void InformationPanelContent::refreshPreview() QIcon::fromTheme(QStringLiteral("nepomuk")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous) ); } else { - // try to get a preview pixmap from the item... - - // Mark the currently shown preview as outdated. This is done - // with a small delay to prevent a flickering when the next preview - // can be shown within a short timeframe. This timer is not started - // for directories, as directory previews might fail and return the - // same icon. - if (!m_item.isDir()) { - m_outdatedPreviewTimer->start(); - } - - QStringList plugins = KIO::PreviewJob::availablePlugins(); - m_previewJob = new KIO::PreviewJob(KFileItemList() << m_item, - QSize(m_preview->width(), m_preview->height()), - &plugins); - m_previewJob->setScaleType(KIO::PreviewJob::Unscaled); - m_previewJob->setIgnoreMaximumSize(m_item.isLocalFile()); - if (m_previewJob->uiDelegate()) { - KJobWidgets::setWindow(m_previewJob, this); - } - connect(m_previewJob.data(), &KIO::PreviewJob::gotPreview, - this, &InformationPanelContent::showPreview); - connect(m_previewJob.data(), &KIO::PreviewJob::failed, - this, &InformationPanelContent::showIcon); + refreshPixmapView(); const QString mimeType = m_item.mimetype(); - const bool isVideo = mimeType.startsWith(QLatin1String("video/")); - const bool usePhonon = mimeType.startsWith(QLatin1String("audio/")) || isVideo; + const bool isAnimatedImage = m_preview->isAnimatedImage(itemUrl.toLocalFile()); + m_isVideo = !isAnimatedImage && mimeType.startsWith(QLatin1String("video/")); + usePhonon = m_isVideo || mimeType.startsWith(QLatin1String("audio/")); if (usePhonon) { - - if (InformationPanelSettings::previewsAutoPlay() && isVideo) { - // hides the preview now to avoid flickering when the autoplay video starts - m_preview->hide(); - } else { - // the video won't play before the preview is displayed - m_preview->show(); + // change the cursor of the preview + m_preview->setCursor(Qt::PointingHandCursor); + m_preview->installEventFilter(m_phononWidget); + + // if the video is playing, has been paused or stopped + // we don't need to update the preview/phonon widget states + // unless the previewed file has changed, + // or the setting previewshown has changed + if ((m_phononWidget->state() != Phonon::State::PlayingState && + m_phononWidget->state() != Phonon::State::PausedState && + m_phononWidget->state() != Phonon::State::StoppedState) || + m_item.targetUrl() != m_phononWidget->url() || + (!m_preview->isVisible() &&! m_phononWidget->isVisible())) { + + if (InformationPanelSettings::previewsAutoPlay() && m_isVideo) { + // hides the preview now to avoid flickering when the autoplay video starts + m_preview->hide(); + } else { + // the video won't play before the preview is displayed + m_preview->show(); + } + + m_phononWidget->show(); + m_phononWidget->setUrl(m_item.targetUrl(), m_isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio); + adjustWidgetSizes(parentWidget()->width()); } - - m_phononWidget->show(); - m_phononWidget->setUrl(m_item.targetUrl(), isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio); - m_phononWidget->setVideoSize(m_preview->size()); } else { + if (isAnimatedImage) { + m_preview->setAnimatedImageFileName(itemUrl.toLocalFile()); + } // When we don't need it, hide the phonon widget first to avoid flickering m_phononWidget->hide(); m_preview->show(); + m_preview->removeEventFilter(m_phononWidget); + m_phononWidget->clearUrl(); } } } else { + m_preview->stopAnimatedImage(); m_preview->hide(); m_phononWidget->hide(); } @@ -265,6 +309,8 @@ void InformationPanelContent::showItems(const KFileItemList& items) m_previewJob->kill(); } + m_preview->stopAnimatedImage(); + m_preview->setPixmap( QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous) ); @@ -319,10 +365,45 @@ void InformationPanelContent::showPreview(const KFileItem& item, const QPixmap& pixmap) { m_outdatedPreviewTimer->stop(); - Q_UNUSED(item); QPixmap p = pixmap; KIconLoader::global()->drawOverlays(item.overlays(), p, KIconLoader::Desktop); + + if (m_isVideo) { + // adds a play arrow + + // compute relative pixel positions + const int zeroX = static_cast(p.width() / 2 - PLAY_ARROW_SIZE / 2 / devicePixelRatio()); + const int zeroY = static_cast(p.height() / 2 - PLAY_ARROW_SIZE / 2 / devicePixelRatio()); + + QPolygon arrow; + arrow << QPoint(zeroX, zeroY); + arrow << QPoint(zeroX, zeroY + PLAY_ARROW_SIZE); + arrow << QPoint(zeroX + PLAY_ARROW_SIZE, zeroY + PLAY_ARROW_SIZE / 2); + + QPainterPath path; + path.addPolygon(arrow); + + QLinearGradient gradient(QPointF(zeroX, zeroY), + QPointF(zeroX + PLAY_ARROW_SIZE,zeroY + PLAY_ARROW_SIZE)); + + QColor whiteColor = Qt::white; + QColor blackColor = Qt::black; + gradient.setColorAt(0, whiteColor); + gradient.setColorAt(1, blackColor); + + QBrush brush(gradient); + + QPainter painter(&p); + + QPen pen(blackColor, PLAY_ARROW_BORDER_SIZE, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + painter.setPen(pen); + + painter.setRenderHint(QPainter::Antialiasing); + painter.drawPolygon(arrow); + painter.fillPath(path, brush); + } + m_preview->setPixmap(p); } @@ -343,6 +424,11 @@ KFileItemList InformationPanelContent::items() void InformationPanelContent::slotHasVideoChanged(bool hasVideo) { m_preview->setVisible(InformationPanelSettings::previewsShown() && !hasVideo); + if (m_preview->isVisible() && m_preview->size().width() != m_preview->pixmap().size().width()) { + // in case the information panel has been resized when the preview was not displayed + // we need to refresh its content + refreshPixmapView(); + } } void InformationPanelContent::setPreviewAutoPlay(bool autoPlay) { diff --git a/src/panels/information/informationpanelcontent.h b/src/panels/information/informationpanelcontent.h index 0d838b268..8daeb95b0 100644 --- a/src/panels/information/informationpanelcontent.h +++ b/src/panels/information/informationpanelcontent.h @@ -139,6 +139,11 @@ private: */ void adjustWidgetSizes(int width); + /** + * Refreshes the image in the PixmapViewer + */ + void refreshPixmapView(); + private: KFileItem m_item; @@ -154,6 +159,7 @@ private: QDialogButtonBox* m_configureButtons; PlacesItemModel* m_placesItemModel; + bool m_isVideo; }; #endif // INFORMATIONPANELCONTENT_H diff --git a/src/panels/information/phononwidget.cpp b/src/panels/information/phononwidget.cpp index 4ea2e6666..6911f79bd 100644 --- a/src/panels/information/phononwidget.cpp +++ b/src/panels/information/phononwidget.cpp @@ -60,7 +60,7 @@ PhononWidget::PhononWidget(QWidget *parent) : QWidget(parent), m_url(), m_playButton(nullptr), - m_stopButton(nullptr), + m_pauseButton(nullptr), m_topLayout(nullptr), m_media(nullptr), m_seekSlider(nullptr), @@ -95,6 +95,34 @@ QUrl PhononWidget::url() const return m_url; } +void PhononWidget::clearUrl() +{ + m_url.clear(); +} + +void PhononWidget::togglePlayback() +{ + if (m_media && m_media->state() == Phonon::State::PlayingState) { + m_media->pause(); + } else { + play(); + } +} + +bool PhononWidget::eventFilter(QObject *object, QEvent *event) +{ + Q_UNUSED(object) + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) { + // toggle playback + togglePlayback(); + return true; + } + } + return false; +} + void PhononWidget::setVideoSize(const QSize& size) { if (m_videoSize != size) { @@ -124,11 +152,11 @@ void PhononWidget::showEvent(QShowEvent *event) controlsLayout->setSpacing(0); m_playButton = new QToolButton(this); - m_stopButton = new QToolButton(this); + m_pauseButton = new QToolButton(this); m_seekSlider = new Phonon::SeekSlider(this); controlsLayout->addWidget(m_playButton); - controlsLayout->addWidget(m_stopButton); + controlsLayout->addWidget(m_pauseButton); controlsLayout->addWidget(m_seekSlider); m_topLayout->addLayout(controlsLayout); @@ -142,12 +170,12 @@ void PhononWidget::showEvent(QShowEvent *event) m_playButton->setAutoRaise(true); connect(m_playButton, &QToolButton::clicked, this, &PhononWidget::play); - m_stopButton->setToolTip(i18n("stop")); - m_stopButton->setIconSize(buttonSize); - m_stopButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-stop"))); - m_stopButton->setAutoRaise(true); - m_stopButton->hide(); - connect(m_stopButton, &QToolButton::clicked, this, &PhononWidget::stop); + m_pauseButton->setToolTip(i18n("pause")); + m_pauseButton->setIconSize(buttonSize); + m_pauseButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause"))); + m_pauseButton->setAutoRaise(true); + m_pauseButton->hide(); + connect(m_pauseButton, &QToolButton::clicked, this, &PhononWidget::togglePlayback); m_seekSlider->setIconVisible(false); @@ -172,11 +200,11 @@ void PhononWidget::stateChanged(Phonon::State newstate) switch (newstate) { case Phonon::PlayingState: case Phonon::BufferingState: - m_stopButton->show(); m_playButton->hide(); + m_pauseButton->show(); break; default: - m_stopButton->hide(); + m_pauseButton->hide(); m_playButton->show(); break; } @@ -196,6 +224,7 @@ void PhononWidget::play() if (!m_videoPlayer) { m_videoPlayer = new EmbeddedVideoPlayer(this); + m_videoPlayer->setCursor(Qt::PointingHandCursor); m_videoPlayer->installEventFilter(this); m_topLayout->insertWidget(0, m_videoPlayer); Phonon::createPath(m_media, m_videoPlayer); @@ -227,6 +256,11 @@ void PhononWidget::finished() } } +Phonon::State PhononWidget::state() const +{ + return m_media == nullptr ? Phonon::State::StoppedState : m_media->state(); +} + void PhononWidget::stop() { if (m_media) { diff --git a/src/panels/information/phononwidget.h b/src/panels/information/phononwidget.h index b9e7d4f05..961443d2e 100644 --- a/src/panels/information/phononwidget.h +++ b/src/panels/information/phononwidget.h @@ -53,11 +53,14 @@ class PhononWidget : public QWidget void setUrl(const QUrl &url, MediaKind kind); QUrl url() const; + void clearUrl(); void setVideoSize(const QSize& size); QSize videoSize() const; + Phonon::State state() const; void setAutoPlay(bool autoPlay); + bool eventFilter(QObject *object, QEvent *event) override; signals: /** @@ -86,11 +89,13 @@ class PhononWidget : public QWidget void applyVideoSize(); private: + void togglePlayback(); + QUrl m_url; QSize m_videoSize; QToolButton *m_playButton; - QToolButton *m_stopButton; + QToolButton *m_pauseButton; QVBoxLayout *m_topLayout; Phonon::MediaObject *m_media; diff --git a/src/panels/information/pixmapviewer.cpp b/src/panels/information/pixmapviewer.cpp index 311995ec2..2601e82ae 100644 --- a/src/panels/information/pixmapviewer.cpp +++ b/src/panels/information/pixmapviewer.cpp @@ -21,14 +21,18 @@ #include +#include +#include #include #include PixmapViewer::PixmapViewer(QWidget* parent, Transition transition) : QWidget(parent), + m_animatedImage(nullptr), m_transition(transition), m_animationStep(0), - m_sizeHint() + m_sizeHint(), + m_hasAnimatedImage(false) { setMinimumWidth(KIconLoader::SizeEnormous); setMinimumHeight(KIconLoader::SizeEnormous); @@ -52,6 +56,11 @@ void PixmapViewer::setPixmap(const QPixmap& pixmap) return; } + // Avoid flicker with static pixmap if an animated image is running + if (m_animatedImage && m_animatedImage->state() == QMovie::Running) { + return; + } + if ((m_transition != NoTransition) && (m_animation.state() == QTimeLine::Running)) { m_pendingPixmaps.enqueue(pixmap); if (m_pendingPixmaps.count() > 5) { @@ -65,15 +74,26 @@ void PixmapViewer::setPixmap(const QPixmap& pixmap) m_pixmap = pixmap; update(); - const bool animate = (m_transition != NoTransition) && - (m_pixmap.size() != m_oldPixmap.size()); - if (animate) { + const bool animateTransition = (m_transition != NoTransition) && + (m_pixmap.size() != m_oldPixmap.size()); + if (animateTransition) { m_animation.start(); + } else if (m_hasAnimatedImage) { + // If there is no transition animation but an animatedImage + // and it is not already running, start animating now + if (m_animatedImage->state() != QMovie::Running) { + m_animatedImage->setScaledSize(m_pixmap.size()); + m_animatedImage->start(); + } } } void PixmapViewer::setSizeHint(const QSize& size) { + if (m_animatedImage && size != m_sizeHint) { + m_animatedImage->stop(); + } + m_sizeHint = size; updateGeometry(); } @@ -83,13 +103,37 @@ QSize PixmapViewer::sizeHint() const return m_sizeHint; } +void PixmapViewer::setAnimatedImageFileName(const QString &fileName) +{ + if (!m_animatedImage) { + m_animatedImage = new QMovie(this); + connect(m_animatedImage, &QMovie::frameChanged, this, &PixmapViewer::updateAnimatedImageFrame); + } + + if (m_animatedImage->fileName() != fileName) { + m_animatedImage->stop(); + m_animatedImage->setFileName(fileName); + } + + m_hasAnimatedImage = m_animatedImage->isValid() && (m_animatedImage->frameCount() > 1); +} + + +QString PixmapViewer::animatedImageFileName() const +{ + if (!m_hasAnimatedImage) { + return QString(); + } + return m_animatedImage->fileName(); +} + void PixmapViewer::paintEvent(QPaintEvent* event) { QWidget::paintEvent(event); QPainter painter(this); - if (m_transition != NoTransition) { + if (m_transition != NoTransition || (m_hasAnimatedImage && m_animatedImage->state() != QMovie::Running)) { const float value = m_animation.currentValue(); const int scaledWidth = static_cast((m_oldPixmap.width() * (1.0 - value)) + (m_pixmap.width() * value)); const int scaledHeight = static_cast((m_oldPixmap.height() * (1.0 - value)) + (m_pixmap.height() * value)); @@ -118,8 +162,32 @@ void PixmapViewer::checkPendingPixmaps() m_pixmap = pixmap; update(); m_animation.start(); + } else if (m_hasAnimatedImage) { + m_animatedImage->setScaledSize(m_pixmap.size()); + m_animatedImage->start(); } else { m_oldPixmap = m_pixmap; } } +void PixmapViewer::updateAnimatedImageFrame() +{ + Q_ASSERT (m_animatedImage); + + m_pixmap = m_animatedImage->currentPixmap(); + update(); +} + +void PixmapViewer::stopAnimatedImage() +{ + if (m_hasAnimatedImage) { + m_animatedImage->stop(); + m_hasAnimatedImage = false; + } +} + +bool PixmapViewer::isAnimatedImage(const QString &fileName) +{ + const QByteArray imageFormat = QImageReader::imageFormat(fileName); + return !imageFormat.isEmpty() && QMovie::supportedFormats().contains(imageFormat); +} diff --git a/src/panels/information/pixmapviewer.h b/src/panels/information/pixmapviewer.h index 46e5cf5fc..37071045f 100644 --- a/src/panels/information/pixmapviewer.h +++ b/src/panels/information/pixmapviewer.h @@ -26,6 +26,7 @@ #include class QPaintEvent; +class QMovie; /** * @brief Widget which shows a pixmap centered inside the boundaries. @@ -73,20 +74,33 @@ public: void setSizeHint(const QSize& size); QSize sizeHint() const override; + void setAnimatedImageFileName(const QString& fileName); + QString animatedImageFileName() const; + + void stopAnimatedImage(); + + /** + * Checks if \a fileName contains an animated image supported by QMovie. + */ + static bool isAnimatedImage(const QString &fileName); + protected: void paintEvent(QPaintEvent* event) override; private Q_SLOTS: void checkPendingPixmaps(); + void updateAnimatedImageFrame(); private: QPixmap m_pixmap; QPixmap m_oldPixmap; + QMovie* m_animatedImage; QQueue m_pendingPixmaps; QTimeLine m_animation; Transition m_transition; int m_animationStep; QSize m_sizeHint; + bool m_hasAnimatedImage; }; inline QPixmap PixmapViewer::pixmap() const diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index a2f0e0655..8469399a7 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -77,7 +77,7 @@ void PlacesPanel::proceedWithTearDown() bool PlacesPanel::urlChanged() { - if (!url().isValid() || url().scheme().contains(QStringLiteral("search"))) { + if (!url().isValid() || url().scheme().contains(QLatin1String("search"))) { // Skip results shown by a search, as possible identical // directory names are useless without parent-path information. return false; @@ -232,7 +232,7 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) removeAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18nc("@item:inmenu", "Remove")); } - QAction* hideAction = menu.addAction(QIcon::fromTheme(QStringLiteral("hint")), i18nc("@item:inmenu", "Hide")); + QAction* hideAction = menu.addAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18nc("@item:inmenu", "Hide")); hideAction->setCheckable(true); hideAction->setChecked(item->isHidden()); @@ -293,7 +293,7 @@ void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos) QAction* showAllAction = menu.addAction(i18nc("@item:inmenu", "Show Hidden Places")); showAllAction->setCheckable(true); showAllAction->setChecked(m_model->hiddenItemsShown()); - showAllAction->setIcon(QIcon::fromTheme(m_model->hiddenItemsShown() ? QStringLiteral("visibility") : QStringLiteral("hint"))); + showAllAction->setIcon(QIcon::fromTheme(m_model->hiddenItemsShown() ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); showAllAction->setEnabled(m_model->hiddenCount()); buildGroupContextMenu(&menu, m_controller->indexCloseToMousePressedPosition()); @@ -358,7 +358,7 @@ QAction *PlacesPanel::buildGroupContextMenu(QMenu *menu, int index) } KFilePlacesModel::GroupType groupType = m_model->groupType(index); - QAction *hideGroupAction = menu->addAction(QIcon::fromTheme(QStringLiteral("hint")), i18nc("@item:inmenu", "Hide Section '%1'", m_model->item(index)->group())); + QAction *hideGroupAction = menu->addAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18nc("@item:inmenu", "Hide Section '%1'", m_model->item(index)->group())); hideGroupAction->setCheckable(true); hideGroupAction->setChecked(m_model->isGroupHidden(groupType)); diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index 52d2a77df..86974d200 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -82,16 +82,14 @@ void TerminalPanel::terminalExited() bool TerminalPanel::isHiddenInVisibleWindow() const { return parentWidget() - && parentWidget()->isHidden() - && m_terminal - && !hasProgramRunning(); + && parentWidget()->isHidden(); } void TerminalPanel::dockVisibilityChanged() { // Only react when the DockWidget itself (not some parent) is hidden. This way we don't // respond when e.g. Dolphin is minimized. - if (isHiddenInVisibleWindow()) { + if (isHiddenInVisibleWindow() && m_terminal && !hasProgramRunning()) { // Make sure that the following "cd /" command will not affect the view. disconnect(m_konsolePart, SIGNAL(currentDirectoryChanged(QString)), this, SLOT(slotKonsolePartCurrentDirectoryChanged(QString))); diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index 7c0e97f86..e4388f2e7 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -150,7 +150,7 @@ QString DolphinFacetsWidget::ratingTerm() const terms << QStringLiteral("modified>=%1").arg(date.toString(Qt::ISODate)); } - return terms.join(QStringLiteral(" AND ")); + return terms.join(QLatin1String(" AND ")); } QString DolphinFacetsWidget::facetType() const diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index d846e5b6c..f3dd20462 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -505,7 +505,7 @@ QUrl DolphinSearchBox::balooUrlForSearching() const query.setIncludeFolder(m_searchPath.toLocalFile()); } - query.setSearchString(queryStrings.join(QStringLiteral(" "))); + query.setSearchString(queryStrings.join(QLatin1Char(' '))); return query.toSearchUrl(i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.", "Query Results from '%1'", text)); diff --git a/src/settings/applyviewpropsjob.cpp b/src/settings/applyviewpropsjob.cpp index b274bb8fb..183c85225 100644 --- a/src/settings/applyviewpropsjob.cpp +++ b/src/settings/applyviewpropsjob.cpp @@ -54,7 +54,7 @@ void ApplyViewPropsJob::slotEntries(KIO::Job*, const KIO::UDSEntryList& list) { foreach (const KIO::UDSEntry& entry, list) { const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME); - if (name != QLatin1String(".") && name != QLatin1String("..") && entry.isDir()) { + if (name != QLatin1Char('.') && name != QLatin1String("..") && entry.isDir()) { ++m_progress; QUrl url(m_dir); diff --git a/src/settings/dolphinsettingsdialog.cpp b/src/settings/dolphinsettingsdialog.cpp index f4da53c9d..01cfd9f86 100644 --- a/src/settings/dolphinsettingsdialog.cpp +++ b/src/settings/dolphinsettingsdialog.cpp @@ -61,35 +61,35 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent) : GeneralSettingsPage* generalSettingsPage = new GeneralSettingsPage(url, this); KPageWidgetItem* generalSettingsFrame = addPage(generalSettingsPage, i18nc("@title:group General settings", "General")); - generalSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("view-preview"))); + generalSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); connect(generalSettingsPage, &GeneralSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); // Startup StartupSettingsPage* startupSettingsPage = new StartupSettingsPage(url, this); KPageWidgetItem* startupSettingsFrame = addPage(startupSettingsPage, i18nc("@title:group", "Startup")); - startupSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("go-home"))); + startupSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-launch-feedback"))); connect(startupSettingsPage, &StartupSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); // View Modes ViewSettingsPage* viewSettingsPage = new ViewSettingsPage(this); KPageWidgetItem* viewSettingsFrame = addPage(viewSettingsPage, i18nc("@title:group", "View Modes")); - viewSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("view-choose"))); + viewSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-icons"))); connect(viewSettingsPage, &ViewSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); // Navigation NavigationSettingsPage* navigationSettingsPage = new NavigationSettingsPage(this); KPageWidgetItem* navigationSettingsFrame = addPage(navigationSettingsPage, i18nc("@title:group", "Navigation")); - navigationSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("edit-select"))); + navigationSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-navigation"))); connect(navigationSettingsPage, &NavigationSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); // Services ServicesSettingsPage* servicesSettingsPage = new ServicesSettingsPage(this); KPageWidgetItem* servicesSettingsFrame = addPage(servicesSettingsPage, i18nc("@title:group", "Services")); - servicesSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("flag"))); + servicesSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-services"))); connect(servicesSettingsPage, &ServicesSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); // Trash @@ -97,7 +97,7 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent) : if (trashSettingsPage) { KPageWidgetItem* trashSettingsFrame = addPage(trashSettingsPage, i18nc("@title:group", "Trash")); - trashSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("trash-empty"))); + trashSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); connect(trashSettingsPage, &TrashSettingsPage::changed, this, &DolphinSettingsDialog::enableApply); } diff --git a/src/settings/general/behaviorsettingspage.cpp b/src/settings/general/behaviorsettingspage.cpp index c7a909eca..df7ea2113 100644 --- a/src/settings/general/behaviorsettingspage.cpp +++ b/src/settings/general/behaviorsettingspage.cpp @@ -50,7 +50,7 @@ BehaviorSettingsPage::BehaviorSettingsPage(const QUrl& url, QWidget* parent) : // View properties m_globalViewProps = new QRadioButton(i18nc("@option:radio", "Use common properties for all folders")); m_localViewProps = new QRadioButton(i18nc("@option:radio", "Remember properties for each folder")); - m_localViewProps->setToolTip(i18nc("@info", "Dolphin will create an hidden .directory file in each folder you change view properties for.")); + m_localViewProps->setToolTip(i18nc("@info", "Dolphin will create a hidden .directory file in each folder you change view properties for.")); QButtonGroup* viewGroup = new QButtonGroup(this); viewGroup->addButton(m_globalViewProps); diff --git a/src/settings/general/confirmationssettingspage.cpp b/src/settings/general/confirmationssettingspage.cpp index 1d0eebdd3..dd4d60f3b 100644 --- a/src/settings/general/confirmationssettingspage.cpp +++ b/src/settings/general/confirmationssettingspage.cpp @@ -25,14 +25,23 @@ #include #include +#include #include +#include #include namespace { + enum ScriptExecution + { + AlwaysAsk = 0, + Open = 1, + Execute = 2 + }; + const bool ConfirmEmptyTrash = true; const bool ConfirmTrash = false; const bool ConfirmDelete = true; - const bool ConfirmScriptExecution = true; + const int ConfirmScriptExecution = ScriptExecution::AlwaysAsk; } ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget* parent) : @@ -58,8 +67,6 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget* parent) : "Emptying trash"), this); m_confirmDelete = new QCheckBox(i18nc("@option:check Ask for confirmation when", "Deleting files or folders"), this); - m_confirmScriptExecution = new QCheckBox(i18nc("@option:check Ask for confirmation when", - "Executing scripts or desktop files"), this); QLabel* confirmLabelDolphin = new QLabel(i18nc("@title:group", "Ask for confirmation in Dolphin when:"), this); confirmLabelDolphin->setWordWrap(true); @@ -72,11 +79,19 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget* parent) : "Closing windows with a program running in the Terminal panel"), this); #endif + QHBoxLayout* executableScriptLayout = new QHBoxLayout(); + QLabel* executableScriptLabel = new QLabel(i18nc("@title:group", "When opening an executable file:"), this); + confirmLabelKde->setWordWrap(true); + executableScriptLayout->addWidget(executableScriptLabel); + + m_confirmScriptExecution = new QComboBox(this); + m_confirmScriptExecution->addItems({i18n("Always ask"), i18n("Open in application"), i18n("Run script")}); + executableScriptLayout->addWidget(m_confirmScriptExecution); + topLayout->addWidget(confirmLabelKde); topLayout->addWidget(m_confirmMoveToTrash); topLayout->addWidget(m_confirmEmptyTrash); topLayout->addWidget(m_confirmDelete); - topLayout->addWidget(m_confirmScriptExecution); topLayout->addSpacing(Dolphin::VERTICAL_SPACER_HEIGHT); topLayout->addWidget(confirmLabelDolphin); topLayout->addWidget(m_confirmClosingMultipleTabs); @@ -85,6 +100,9 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget* parent) : topLayout->addWidget(m_confirmClosingTerminalRunningProgram); #endif + topLayout->addSpacing(Dolphin::VERTICAL_SPACER_HEIGHT); + topLayout->addLayout(executableScriptLayout); + topLayout->addStretch(); loadSettings(); @@ -92,7 +110,7 @@ ConfirmationsSettingsPage::ConfirmationsSettingsPage(QWidget* parent) : connect(m_confirmMoveToTrash, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); connect(m_confirmEmptyTrash, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); connect(m_confirmDelete, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); - connect(m_confirmScriptExecution, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); + connect(m_confirmScriptExecution, QOverload::of(&QComboBox::currentIndexChanged), this, &ConfirmationsSettingsPage::changed); connect(m_confirmClosingMultipleTabs, &QCheckBox::toggled, this, &ConfirmationsSettingsPage::changed); #ifdef HAVE_TERMINAL @@ -113,10 +131,17 @@ void ConfirmationsSettingsPage::applySettings() confirmationGroup.writeEntry("ConfirmDelete", m_confirmDelete->isChecked()); KConfigGroup scriptExecutionGroup(kioConfig, "Executable scripts"); - if (m_confirmScriptExecution->isChecked()) { + const int index = m_confirmScriptExecution->currentIndex(); + switch (index) { + case ScriptExecution::AlwaysAsk: scriptExecutionGroup.writeEntry("behaviourOnLaunch", "alwaysAsk"); - } else { + break; + case ScriptExecution::Open: scriptExecutionGroup.writeEntry("behaviourOnLaunch", "dontAsk"); + break; + case ScriptExecution::Execute: + scriptExecutionGroup.writeEntry("behaviourOnLaunch", "execute"); + break; } kioConfig->sync(); @@ -140,7 +165,7 @@ void ConfirmationsSettingsPage::restoreDefaults() m_confirmMoveToTrash->setChecked(ConfirmTrash); m_confirmEmptyTrash->setChecked(ConfirmEmptyTrash); m_confirmDelete->setChecked(ConfirmDelete); - m_confirmScriptExecution->setChecked(ConfirmScriptExecution); + m_confirmScriptExecution->setCurrentIndex(ConfirmScriptExecution); } void ConfirmationsSettingsPage::loadSettings() @@ -153,7 +178,13 @@ void ConfirmationsSettingsPage::loadSettings() const KConfigGroup scriptExecutionGroup(KSharedConfig::openConfig(QStringLiteral("kiorc")), "Executable scripts"); const QString value = scriptExecutionGroup.readEntry("behaviourOnLaunch", "alwaysAsk"); - m_confirmScriptExecution->setChecked(value == QLatin1String("alwaysAsk")); + if (value == QLatin1String("dontAsk")) { + m_confirmScriptExecution->setCurrentIndex(ScriptExecution::Open); + } else if (value == QLatin1String("execute")) { + m_confirmScriptExecution->setCurrentIndex(ScriptExecution::Execute); + } else /* if (value == QLatin1String("alwaysAsk"))*/ { + m_confirmScriptExecution->setCurrentIndex(ScriptExecution::AlwaysAsk); + } m_confirmClosingMultipleTabs->setChecked(GeneralSettings::confirmClosingMultipleTabs()); diff --git a/src/settings/general/confirmationssettingspage.h b/src/settings/general/confirmationssettingspage.h index 52b101b2a..c15afdc38 100644 --- a/src/settings/general/confirmationssettingspage.h +++ b/src/settings/general/confirmationssettingspage.h @@ -23,6 +23,7 @@ #include "settings/settingspagebase.h" class QCheckBox; +class QComboBox; /** * @brief Page for the enabling or disabling confirmation dialogs. @@ -54,7 +55,7 @@ private: #endif QCheckBox* m_confirmClosingMultipleTabs; - QCheckBox* m_confirmScriptExecution; + QComboBox* m_confirmScriptExecution; }; #endif diff --git a/src/settings/kcm/kcmdolphingeneral.desktop b/src/settings/kcm/kcmdolphingeneral.desktop index ac3956144..75a5aaf0c 100644 --- a/src/settings/kcm/kcmdolphingeneral.desktop +++ b/src/settings/kcm/kcmdolphingeneral.desktop @@ -20,7 +20,7 @@ Name[id]=Dolphin Umum Name[it]=Impostazioni generali di Dolphin Name[ja]=Dolphin 全般 Name[ko]=Dolphin 일반 -Name[lt]=Dolphin bendrieji +Name[lt]=Dolphin bendrosios Name[ml]=പൊതു സജ്ജീകരണങ്ങള്‍ Name[nb]=Dolphin generelt Name[nl]=Dolphin algemeen @@ -65,7 +65,7 @@ Comment[id]=Layanan ini memungkinkan konfigurasi pengaturan umum Dolphin. Comment[it]=Questo servizio permette di configurare le impostazioni generali di Dolphin. Comment[ja]=Dolphin の全般的な設定を行います Comment[ko]=이 서비스는 일반 Dolphin 설정을 담당합니다. -Comment[lt]=Ši tarnyba leidžia konfigūruoti Dolphin bendrąsias nuostatas. +Comment[lt]=Ši paslauga leidžia bendrųjų Dolphin nuostatų konfigūravimą. Comment[ml]=പൊതുവായ ഡോള്‍ഫിന്‍ സജ്ജീകരണങ്ങള്‍ ക്രമീകരിയ്ക്കാന്‍ ഈ സേവനം അനുവദിക്കുന്നു. Comment[nb]=Med denne tjenesten kan du sette opp generelle innstillinger for Dolphin. Comment[nl]=Met deze dienst kunt u algemene Dolphin-instellingen configureren. @@ -89,7 +89,7 @@ Comment[zh_CN]=此服务允许您配置 Dolphin 的常规设置。 Comment[zh_TW]=此服務允許設定 Dolphin 的一般設定。 [Desktop Entry] -Icon=system-run +Icon=system-file-manager Type=Service X-KDE-ServiceTypes=KCModule Exec=kcmshell5 kcmdolphingeneral @@ -122,7 +122,7 @@ Name[id]=Umum Name[it]=Generale Name[ja]=全般 Name[ko]=일반 -Name[lt]=Bendra +Name[lt]=Bendrosios Name[ml]=പൊതുവായതു് Name[nb]=Generelt Name[nl]=Algemeen @@ -166,7 +166,7 @@ Comment[id]=Konfigurasikan pengaturan pengelola file umum Comment[it]=Configura le impostazioni generali del gestore dei file Comment[ja]=ファイルマネージャの全般的な設定を行います Comment[ko]=일반 파일 관리자 설정 -Comment[lt]=Bendrųjų failų tvarkyklės nuostatų konfigūravimas +Comment[lt]=Konfigūruoti bendras failų tvarkytuvės nuostatas Comment[ml]=ഫയൽ മാനേജറിന്റെ പൊതുവായ സജ്ജീകരണങ്ങള്‍ ക്രമീകരിയ്ക്കുക Comment[nb]=Sett opp generelle innstillinger for filbehandleren Comment[nl]=Algemene bestandsbeheerderinstellingen configureren @@ -211,7 +211,7 @@ X-KDE-Keywords[id]=pengelola file X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[ja]=ファイルマネージャ X-KDE-Keywords[ko]=파일 관리자 -X-KDE-Keywords[lt]=Failų tvarkyklė +X-KDE-Keywords[lt]=failų tvarkytuvė X-KDE-Keywords[ml]=ഫയൽ മാനേജർ X-KDE-Keywords[nb]=filbehandler X-KDE-Keywords[nl]=bestandsbeheerder diff --git a/src/settings/kcm/kcmdolphinnavigation.desktop b/src/settings/kcm/kcmdolphinnavigation.desktop index f6686fbc8..24bf0dff5 100644 --- a/src/settings/kcm/kcmdolphinnavigation.desktop +++ b/src/settings/kcm/kcmdolphinnavigation.desktop @@ -20,7 +20,7 @@ Name[id]=Navigasi Dolphin Name[it]=Navigazione di Dolphin Name[ja]=Dolphin ナビゲーション Name[ko]=Dolphin 탐색 -Name[lt]=Dolphin navigacija +Name[lt]=Dolphin naršymas Name[ml]=ഡോള്‍ഫിന്‍ നാവിഗേഷന്‍ Name[nb]=Navigasjon i Dolphin Name[nl]=Dolphin-navigatie @@ -65,7 +65,7 @@ Comment[id]=Layanan ini memungkinkan konfigurasi navigasi Dolphin. Comment[it]=Questo servizio permette di configurare la navigazione con Dolphin. Comment[ja]=Dolphin でのナビゲーションを設定します Comment[ko]=이 서비스는 Dolphin 탐색을 설정합니다. -Comment[lt]=Ši tarnyba leidžia konfigūruoti Dolphin navigaciją. +Comment[lt]=Ši paslauga leidžia Dolphin naršymo konfigūravimą. Comment[ml]=ഡോള്‍ഫിന്‍ നാവിഗേഷൻ ക്രമീകരിയ്ക്കാന്‍ ഈ സേവനം അനുവദിയ്ക്കുന്നു. Comment[nb]=Med denne tjenesten kan du sette opp navigasjon for Dolphin. Comment[nl]=Met deze dienst kunt u Dolphin-navigatie configureren. @@ -89,7 +89,7 @@ Comment[zh_CN]=此服务允许您配置 Dolphin 的导航。 Comment[zh_TW]=此服務允許設定 Dolphin 的導覽。 [Desktop Entry] -Icon=input-mouse +Icon=preferences-desktop-navigation Type=Service X-KDE-ServiceTypes=KCModule Exec=kcmshell5 kcmdolphinnavigation @@ -121,7 +121,7 @@ Name[id]=Navigasi Name[it]=Navigazione Name[ja]=ナビゲーション Name[ko]=탐색 -Name[lt]=Navigacija +Name[lt]=Naršymas Name[ml]=നാവിഗേഷന്‍ Name[nb]=Navigasjon Name[nl]=Navigatie @@ -166,7 +166,7 @@ Comment[id]=Konfigurasikan navigasi pengelola file Comment[it]=Configura la navigazione col gestore dei file Comment[ja]=ファイルマネージャでのナビゲーションを設定します Comment[ko]=파일 관리자 탐색 설정 -Comment[lt]=Konfigūruokite failų tvarkyklės navigaciją +Comment[lt]=Konfigūruoti failų tvarkytuvės naršymą Comment[ml]=ഫയല്‍ മാനേജർ നാവിഗേഷൻ ക്രമീകരിയ്ക്കുക Comment[nb]=Sett opp navigasjon i filbehandleren Comment[nl]=Bestandsbeheerdernavigatie configureren @@ -212,7 +212,7 @@ X-KDE-Keywords[id]=pengelola file X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[ja]=ファイルマネージャ X-KDE-Keywords[ko]=파일 관리자 -X-KDE-Keywords[lt]=Failų tvarkyklė +X-KDE-Keywords[lt]=failų tvarkytuvė X-KDE-Keywords[ml]=ഫയൽ മാനേജർ X-KDE-Keywords[nb]=filbehandler X-KDE-Keywords[nl]=bestandsbeheerder diff --git a/src/settings/kcm/kcmdolphinservices.desktop b/src/settings/kcm/kcmdolphinservices.desktop index 07ac89c52..e3330af5d 100644 --- a/src/settings/kcm/kcmdolphinservices.desktop +++ b/src/settings/kcm/kcmdolphinservices.desktop @@ -20,7 +20,7 @@ Name[id]=Layanan Dolphin Name[it]=Servizi di Dolphin Name[ja]=Dolphin サービス Name[ko]=Dolphin 서비스 -Name[lt]=Dolphin tarnybos +Name[lt]=Dolphin paslaugos Name[ml]=ഡോള്‍ഫിന്‍ സേവനങ്ങള്‍ Name[nb]=Dolphin-tjenester Name[nl]=Dolphin-services @@ -44,7 +44,7 @@ Name[zh_CN]=Dolphin 服务 Name[zh_TW]=Dolphin 服務 [Desktop Entry] -Icon=services +Icon=preferences-system-services Type=Service X-KDE-ServiceTypes=KCModule Exec=kcmshell5 kcmdolphinservices @@ -120,7 +120,7 @@ Comment[id]=Konfigurasikan layanan pengelola file Comment[it]=Configura i servizi del gestore dei file Comment[ja]=ファイルマネージャのサービスを設定します Comment[ko]=파일 관리자 서비스 설정 -Comment[lt]=Konfigūruokite failų tvarkyklės tarnybas +Comment[lt]=Konfigūruoti failų tvarkytuvės paslaugas Comment[ml]=ഫയല്‍ മാനേജർ സേവനങ്ങള്‍ ക്രമീകരിയ്ക്കുക Comment[nb]=Sett opp tjenester i filbehandleren Comment[nl]=Bestandsbeheerderservices configureren @@ -165,7 +165,7 @@ X-KDE-Keywords[id]=pengelola file X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[ja]=ファイルマネージャ X-KDE-Keywords[ko]=파일 관리자 -X-KDE-Keywords[lt]=Failų tvarkyklė +X-KDE-Keywords[lt]=failų tvarkytuvė X-KDE-Keywords[ml]=ഫയൽ മാനേജർ X-KDE-Keywords[nb]=filbehandler X-KDE-Keywords[nl]=bestandsbeheerder diff --git a/src/settings/kcm/kcmdolphinviewmodes.desktop b/src/settings/kcm/kcmdolphinviewmodes.desktop index c50fa3800..f093f49a1 100644 --- a/src/settings/kcm/kcmdolphinviewmodes.desktop +++ b/src/settings/kcm/kcmdolphinviewmodes.desktop @@ -20,7 +20,7 @@ Name[id]=Mode Tampilan Dolphin Name[it]=Viste di Dolphin Name[ja]=Dolphin 表示モード Name[ko]=Dolphin 보기 모드 -Name[lt]=Dolphin rodymo būdai +Name[lt]=Dolphin rodinio veiksenos Name[ml]=ഡോള്‍ഫിന്‍ അവതരണദശകള്‍ Name[nb]=Dolphin visningsmåter Name[nl]=Dolphin-weergavemodussen @@ -65,7 +65,7 @@ Comment[id]=Layanan ini memungkinkan konfigurasi mode tampilan Dolphin. Comment[it]=Questo servizio permette di configurare le viste di Dolphin. Comment[ja]=Dolphin の表示モードを設定します Comment[ko]=이 서비스는 Dolphin 보기 모드를 설정합니다. -Comment[lt]=Ši tarnyba leidžia konfigūruoti Dolphin rodymo būdus. +Comment[lt]=Ši paslauga leidžia Dolphin rodinio veiksenų konfigūravimą. Comment[ml]=ഡോള്‍ഫിന്‍ അവതരണദശകള്‍ ക്രമീകരിയ്ക്കാന്‍ ഈ സേവനം അനുവദിയ്ക്കുന്നു. Comment[nb]=Med denne tjenesten kan du sette opp Dolphins visningsmåter. Comment[nl]=Met deze dienst kunt u Dolphin-weergavemodussen configureren. @@ -89,7 +89,7 @@ Comment[zh_CN]=此服务允许您配置 Dolphin 的视图模式。 Comment[zh_TW]=此服務允許設定 Dolphin 的檢視模式。 [Desktop Entry] -Icon=view-choose +Icon=preferences-desktop-icons Type=Service X-KDE-ServiceTypes=KCModule Exec=kcmshell5 kcmdolphinviewmodes @@ -120,7 +120,7 @@ Name[id]=Mode Tampilan Name[it]=Viste Name[ja]=表示モード Name[ko]=보기 모드 -Name[lt]=Rodymo būdai +Name[lt]=Rodinio veiksenos Name[ml]=അവതരണ ദശകള്‍ Name[nb]=Visningsmåter Name[nl]=Weergavemodi @@ -165,7 +165,7 @@ Comment[id]=Konfigurasikan mode tampilan pengelola file Comment[it]=Configura le viste del gestore dei file Comment[ja]=ファイルマネージャの表示モードを設定します Comment[ko]=파일 관리자 보기 모드 설정 -Comment[lt]=Failų tvarkyklės rodymo būdų konfigūravimas +Comment[lt]=Konfigūruoti failų tvarkytuvės rodinio veiksenas Comment[ml]=ഫയല്‍ മാനേജറിന്റെ അവതരണ ദശകള്‍ ക്രമീകരിയ്ക്കുക Comment[nb]=Tilpass filbehandlerens visningsmåter Comment[nl]=Bestandsbeheerderweergavemodussen configureren @@ -211,7 +211,7 @@ X-KDE-Keywords[id]=pengelola file X-KDE-Keywords[it]=gestore dei file X-KDE-Keywords[ja]=ファイルマネージャ X-KDE-Keywords[ko]=파일 관리자 -X-KDE-Keywords[lt]=Failų tvarkyklė +X-KDE-Keywords[lt]=failų tvarkytuvė X-KDE-Keywords[ml]=ഫയൽ മാനേജർ X-KDE-Keywords[nb]=filbehandler X-KDE-Keywords[nl]=bestandsbeheerder diff --git a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp index 037874539..1144a50b8 100644 --- a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp +++ b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -42,41 +43,6 @@ Q_NORETURN void fail(const QString &str) exit(1); } -bool evaluateShell(const QString &program, const QStringList &arguments, QString &output, QString &errorText) -{ - QProcess process; - process.start(program, arguments, QIODevice::ReadOnly); - if (!process.waitForStarted()) { - fail(i18n("Failed to run process: %1 %2", program, arguments.join(" "))); - } - - if (!process.waitForFinished()) { - fail(i18n("Process did not finish in reasonable time: %1 %2", program, arguments.join(" "))); - } - - const auto stdoutResult = QString::fromUtf8(process.readAllStandardOutput()).trimmed(); - const auto stderrResult = QString::fromUtf8(process.readAllStandardError()).trimmed(); - - if (process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0) { - output = stdoutResult; - return true; - } else { - errorText = stderrResult + stdoutResult; - return false; - } -} - -QString mimeType(const QString &path) -{ - QString result; - QString errorText; - if (evaluateShell("xdg-mime", QStringList{"query", "filetype", path}, result, errorText)) { - return result; - } else { - fail(i18n("Failed to run xdg-mime %1: %2", path, errorText)); - } -} - QString getServiceMenusDir() { const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); @@ -114,7 +80,7 @@ void runUncompress(const QString &inputPath, const QString &outputPath) { "multipart/x-zip"}, UncompressCommand{"unzip", QStringList{}, QStringList{"-d"}}}); - const auto mime = mimeType(inputPath); + const auto mime = QMimeDatabase().mimeTypeForFile(inputPath).name(); UncompressCommand command{}; for (const auto &pair : mimeTypeToCommand) { diff --git a/src/settings/services/servicessettingspage.cpp b/src/settings/services/servicessettingspage.cpp index ff00ca177..83672b556 100644 --- a/src/settings/services/servicessettingspage.cpp +++ b/src/settings/services/servicessettingspage.cpp @@ -222,7 +222,7 @@ void ServicesSettingsPage::loadServices() // Load JSON-based plugins that implement the KFileItemActionPlugin interface const auto jsonPlugins = KPluginLoader::findPlugins(QStringLiteral("kf5/kfileitemaction"), [](const KPluginMetaData& metaData) { - return metaData.serviceTypes().contains(QStringLiteral("KFileItemAction/Plugin")); + return metaData.serviceTypes().contains(QLatin1String("KFileItemAction/Plugin")); }); foreach (const auto& jsonMetadata, jsonPlugins) { diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 44a413bd9..6ecac1f1e 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -71,7 +71,7 @@ LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) ecm_add_test(draganddrophelpertest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) # PlacesItemModelTest -if (KF5_VERSION VERSION_GREATER_EQUAL "5.60.0") +if (KF5_VERSION VERSION_GREATER_EQUAL 5.63.0) ecm_add_test(placesitemmodeltest.cpp TEST_NAME placesitemmodeltest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index 3d09699fe..e57c79b02 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -44,6 +44,9 @@ private slots: void testOpenInNewTabTitle(); void testNewFileMenuEnabled_data(); void testNewFileMenuEnabled(); + void testWindowTitle_data(); + void testWindowTitle(); + private: @@ -250,6 +253,29 @@ void DolphinMainWindowTest::testNewFileMenuEnabled() QTRY_COMPARE(newFileMenu->isEnabled(), expectedEnabled); } +void DolphinMainWindowTest::testWindowTitle_data() +{ + QTest::addColumn("activeViewUrl"); + QTest::addColumn("expectedWindowTitle"); + + // TODO: this test should enforce the english locale. + QTest::newRow("home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("Home"); + QTest::newRow("home with trailing slash") << QUrl::fromLocalFile(QStringLiteral("%1/").arg(QDir::homePath())) << QStringLiteral("Home"); + QTest::newRow("trash") << QUrl::fromUserInput(QStringLiteral("trash:/")) << QStringLiteral("Trash"); +} + +void DolphinMainWindowTest::testWindowTitle() +{ + QFETCH(QUrl, activeViewUrl); + m_mainWindow->openDirectories({ activeViewUrl }, false); + m_mainWindow->show(); + QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); + QVERIFY(m_mainWindow->isVisible()); + + QFETCH(QString, expectedWindowTitle); + QCOMPARE(m_mainWindow->windowTitle(), expectedWindowTitle); +} + QTEST_MAIN(DolphinMainWindowTest) #include "dolphinmainwindowtest.moc" diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index c53979970..f081eba86 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -460,7 +460,7 @@ void KFileItemModelTest::testModelConsistencyWhenInsertingItems() } m_model->m_dirLister->updateDirectory(m_testDir->url()); - if (itemsInsertedSpy.count() == 0) { + if (itemsInsertedSpy.isEmpty()) { QVERIFY(itemsInsertedSpy.wait()); } diff --git a/src/tests/kitemsettest.cpp b/src/tests/kitemsettest.cpp index 27f8413a7..ca2c16b27 100644 --- a/src/tests/kitemsettest.cpp +++ b/src/tests/kitemsettest.cpp @@ -203,7 +203,7 @@ void KItemSetTest::testIterators() QVERIFY(itemSet.isValid()); QVERIFY(itemSet.count() == itemsQVector.count()); - if (itemSet.count() == 0) { + if (itemSet.isEmpty()) { QVERIFY(itemSet.isEmpty()); QVERIFY(itemSet.begin() == itemSet.end()); QVERIFY(itemSet.constBegin() == itemSet.constEnd()); @@ -342,7 +342,7 @@ void KItemSetTest::testFind() int min; int max; - if (itemSet.count() == 0) { + if (itemSet.isEmpty()) { // Use some arbitrary values for the upcoming tests. min = 0; max = 5; @@ -401,7 +401,7 @@ void KItemSetTest::testChangingOneItem() int min; int max; - if (itemSet.count() == 0) { + if (itemSet.isEmpty()) { // Use some arbitrary values for the upcoming tests. min = 0; max = 5; diff --git a/src/tests/placesitemmodeltest.cpp b/src/tests/placesitemmodeltest.cpp index cc66c5aa0..d066b2ec9 100644 --- a/src/tests/placesitemmodeltest.cpp +++ b/src/tests/placesitemmodeltest.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "dolphin_generalsettings.h" #include "panels/places/placesitemmodel.h" @@ -79,7 +80,7 @@ private: PlacesItemModel* m_model; QSet m_tobeRemoved; QMap m_interfacesMap; - int m_expectedModelCount = 14; + int m_expectedModelCount = qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused")) ? 16 : 14; bool m_hasDesktopFolder = false; bool m_hasDocumentsFolder = false; bool m_hasDownloadsFolder = false; @@ -175,8 +176,14 @@ QStringList PlacesItemModelTest::initialUrls() const urls << QStringLiteral("trash:/") << QStringLiteral("remote:/") - << QStringLiteral("/media/nfs") - << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday") + << QStringLiteral("/media/nfs"); + + if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) { + urls << QStringLiteral("recentlyused:/files"); + urls << QStringLiteral("recentlyused:/locations"); + } + + urls << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday") << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos") << QStringLiteral("/foreign") << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); @@ -315,7 +322,11 @@ void PlacesItemModelTest::testGroups() QCOMPARE(groups.at(1).second.toString(), QStringLiteral("Remote")); QCOMPARE(groups.at(2).first, expectedRemoteIndex + 2); - QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recently Saved")); + QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recent")); + + if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) { + expectedRemoteIndex += 2; + } QCOMPARE(groups.at(3).first, expectedRemoteIndex + 4); QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For")); @@ -342,7 +353,7 @@ void PlacesItemModelTest::testPlaceItem_data() QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false; // baloo - timeline - QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recently Saved") << false; + QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recent") << false; // devices QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false; diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 5b00fa36d..3597a2aa4 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -128,8 +129,8 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) : m_container = new KItemListContainer(controller, this); m_container->installEventFilter(this); setFocusProxy(m_container); - connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, &DolphinView::hideToolTip); - connect(m_container->verticalScrollBar(), &QScrollBar::valueChanged, this, &DolphinView::hideToolTip); + connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, [=] { hideToolTip(); }); + connect(m_container->verticalScrollBar(), &QScrollBar::valueChanged, this, [=] { hideToolTip(); }); controller->setSelectionBehavior(KItemListController::MultiSelection); connect(controller, &KItemListController::itemActivated, this, &DolphinView::slotItemActivated); @@ -744,6 +745,7 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) break; case QEvent::KeyPress: + hideToolTip(ToolTipManager::HideBehavior::Instantly); if (GeneralSettings::useTabForSwitchingSplitView()) { QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) { @@ -1337,6 +1339,20 @@ QUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseTh return QUrl(); } +void DolphinView::resetZoomLevel() +{ + ViewModeSettings::ViewMode mode; + + switch (m_mode) { + case IconsView: mode = ViewModeSettings::IconsMode; break; + case CompactView: mode = ViewModeSettings::CompactMode; break; + case DetailsView: mode = ViewModeSettings::DetailsMode; break; + } + const ViewModeSettings settings(mode); + const QSize iconSize = QSize(settings.iconSize(), settings.iconSize()); + setZoomLevel(ZoomLevelInfo::zoomLevelForIconSize(iconSize)); +} + void DolphinView::observeCreatedItem(const QUrl& url) { if (m_active) { @@ -1414,11 +1430,11 @@ void DolphinView::updateViewState() } } -void DolphinView::hideToolTip() +void DolphinView::hideToolTip(const ToolTipManager::HideBehavior behavior) { #ifdef HAVE_BALOO if (GeneralSettings::showToolTips()) { - m_toolTipManager->hideToolTip(); + m_toolTipManager->hideToolTip(behavior); } #endif } diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index 7be2eed2d..ba38d3234 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -23,6 +23,7 @@ #include "dolphintabwidget.h" #include "dolphin_export.h" +#include "tooltips/tooltipmanager.h" #include #include @@ -195,6 +196,11 @@ public: void setZoomLevel(int level); int zoomLevel() const; + /** + * Resets the view's icon size to the default value + */ + void resetZoomLevel(); + void setSortRole(const QByteArray& role); QByteArray sortRole() const; @@ -697,8 +703,6 @@ private slots: */ void updateViewState(); - void hideToolTip(); - /** * Calculates the number of currently shown files into * \a fileCount and the number of folders into \a folderCount. @@ -733,6 +737,11 @@ private: */ void applyModeToView(); + /** + * Hides tooltip displayed over element. + */ + void hideToolTip(const ToolTipManager::HideBehavior behavior = ToolTipManager::HideBehavior::Later); + /** * Helper method for DolphinView::paste() and DolphinView::pasteIntoFolder(). * Pastes the clipboard data into the URL \a url. diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp index a79dacb1f..25b7f82cb 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -163,7 +163,7 @@ void DolphinViewActionHandler::createActions() " option is enabled.")); compactAction->setWhatsThis(xi18nc("@info:whatsthis Compact view mode", "This switches to a compact view mode that lists the folders " - "and files in columns with the names beside the icons. " + "and files in columns with the names beside the icons." "This helps to keep the overview in folders with many items.")); detailsAction->setWhatsThis(xi18nc("@info:whatsthis Details view mode", "This switches to a list view mode that focuses on folder " @@ -188,13 +188,21 @@ void DolphinViewActionHandler::createActions() m_actionCollection); zoomInAction->setWhatsThis(i18nc("@info:whatsthis zoom in", "This increases the icon size.")); + QAction* zoomResetAction = m_actionCollection->addAction(QStringLiteral("view_zoom_reset")); + zoomResetAction->setText(i18nc("@action:inmenu View", "Reset Zoom Level")); + zoomResetAction->setToolTip(i18n("Zoom To Default")); + zoomResetAction->setWhatsThis(i18nc("@info:whatsthis zoom reset", "This resets the icon size to default.")); + zoomResetAction->setIcon(QIcon::fromTheme(QStringLiteral("zoom-original"))); + m_actionCollection->setDefaultShortcuts(zoomResetAction, {Qt::CTRL + Qt::Key_0}); + connect(zoomResetAction, &QAction::triggered, this, &DolphinViewActionHandler::zoomReset); + QAction* zoomOutAction = KStandardAction::zoomOut(this, &DolphinViewActionHandler::zoomOut, m_actionCollection); - zoomOutAction->setWhatsThis(i18nc("@info:whatsthis zoom in", "This reduces the icon size.")); + zoomOutAction->setWhatsThis(i18nc("@info:whatsthis zoom out", "This reduces the icon size.")); KToggleAction* showPreview = m_actionCollection->add(QStringLiteral("show_preview")); - showPreview->setText(i18nc("@action:intoolbar", "Preview")); + showPreview->setText(i18nc("@action:intoolbar", "Show Previews")); showPreview->setToolTip(i18nc("@info", "Show preview of files and folders")); showPreview->setWhatsThis(xi18nc("@info:whatsthis", "When this is " "enabled, the icons are based on the actual file or folder " @@ -245,7 +253,8 @@ void DolphinViewActionHandler::createActions() QActionGroup* visibleRolesGroup = createFileItemRolesActionGroup(QStringLiteral("show_")); KActionMenu* visibleRolesMenu = m_actionCollection->add(QStringLiteral("additional_info")); - visibleRolesMenu->setText(i18nc("@action:inmenu View", "Additional Information")); + visibleRolesMenu->setText(i18nc("@action:inmenu View", "Show Additional Information")); + visibleRolesMenu->setIcon(QIcon::fromTheme(QStringLiteral("documentinfo"))); visibleRolesMenu->setDelayed(false); foreach (QAction* action, visibleRolesGroup->actions()) { @@ -259,7 +268,7 @@ void DolphinViewActionHandler::createActions() connect(showInGroups, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleGroupedSorting); KToggleAction* showHiddenFiles = m_actionCollection->add(QStringLiteral("show_hidden_files")); - showHiddenFiles->setText(i18nc("@action:inmenu View", "Hidden Files")); + showHiddenFiles->setText(i18nc("@action:inmenu View", "Show Hidden Files")); showHiddenFiles->setToolTip(i18nc("@info", "Visibility of hidden files and folders")); showHiddenFiles->setWhatsThis(xi18nc("@info:whatsthis", "When " "this is enabled hidden files and folders " @@ -272,6 +281,7 @@ void DolphinViewActionHandler::createActions() QAction* adjustViewProps = m_actionCollection->addAction(QStringLiteral("view_properties")); adjustViewProps->setText(i18nc("@action:inmenu View", "Adjust View Properties...")); + adjustViewProps->setIcon(QIcon::fromTheme(QStringLiteral("view-choose"))); adjustViewProps->setWhatsThis(i18nc("@info:whatsthis", "This opens a window " "in which all folder view properties can be adjusted.")); connect(adjustViewProps, &QAction::triggered, this, &DolphinViewActionHandler::slotAdjustViewProperties); @@ -280,7 +290,7 @@ void DolphinViewActionHandler::createActions() QActionGroup* DolphinViewActionHandler::createFileItemRolesActionGroup(const QString& groupPrefix) { const bool isSortGroup = (groupPrefix == QLatin1String("sort_by_")); - Q_ASSERT(isSortGroup || (!isSortGroup && groupPrefix == QLatin1String("show_"))); + Q_ASSERT(isSortGroup || groupPrefix == QLatin1String("show_")); QActionGroup* rolesActionGroup = new QActionGroup(m_actionCollection); rolesActionGroup->setExclusive(isSortGroup); @@ -391,7 +401,7 @@ void DolphinViewActionHandler::slotPreviewsShownChanged(bool shown) { Q_UNUSED(shown); // It is not enough to update the 'Show Preview' action, also - // the 'Zoom In' and 'Zoom Out' actions must be adapted. + // the 'Zoom In', 'Zoom Out' and 'Zoom Reset' actions must be adapted. updateViewActions(); } @@ -454,6 +464,12 @@ void DolphinViewActionHandler::zoomOut() updateViewActions(); } +void DolphinViewActionHandler::zoomReset() +{ + m_currentView->resetZoomLevel(); + updateViewActions(); +} + void DolphinViewActionHandler::toggleSortFoldersFirst() { const bool sortFirst = m_currentView->sortFoldersFirst(); @@ -535,11 +551,11 @@ void DolphinViewActionHandler::slotHiddenFilesShownChanged(bool shown) // #374508: don't overwrite custom icons. const QString iconName = showHiddenFilesAction->icon().name(); - if (!iconName.isEmpty() && iconName != QLatin1String("visibility") && iconName != QLatin1String("hint")) { + if (!iconName.isEmpty() && iconName != QLatin1String("view-visible") && iconName != QLatin1String("view-hidden")) { return; } - showHiddenFilesAction->setIcon(QIcon::fromTheme(shown ? QStringLiteral("visibility") : QStringLiteral("hint"))); + showHiddenFilesAction->setIcon(QIcon::fromTheme(shown ? QStringLiteral("view-visible") : QStringLiteral("view-hidden"))); } void DolphinViewActionHandler::slotWriteStateChanged(bool isFolderWritable) @@ -639,7 +655,6 @@ void DolphinViewActionHandler::slotSortTriggered(QAction* action) // actions and the sub-menu-actions. If an action gets checked, it must // be assured that all other actions get unchecked, except the ascending/ // descending actions - QAction* sortByMenu = m_actionCollection->action(QStringLiteral("sort")); for (QAction *groupAction : qAsConst(m_sortByActions)) { KActionMenu* actionMenu = qobject_cast(groupAction); if (actionMenu) { diff --git a/src/views/dolphinviewactionhandler.h b/src/views/dolphinviewactionhandler.h index 7d675b7d4..f931b3b9c 100644 --- a/src/views/dolphinviewactionhandler.h +++ b/src/views/dolphinviewactionhandler.h @@ -131,6 +131,9 @@ private Q_SLOTS: /** Decreases the size of the current set view mode. */ void zoomOut(); + + /** Resets the size of the current set view mode to default. */ + void zoomReset(); /** Switches between a separate sorting and a mixed sorting of files and folders. */ void toggleSortFoldersFirst(); diff --git a/src/views/renamedialog.cpp b/src/views/renamedialog.cpp index 5d329c3ce..96068564d 100644 --- a/src/views/renamedialog.cpp +++ b/src/views/renamedialog.cpp @@ -188,7 +188,7 @@ void RenameDialog::slotAccepted() void RenameDialog::slotTextChanged(const QString& newName) { - bool enable = !newName.isEmpty() && (newName != QLatin1String("..")) && (newName != QLatin1String(".")); + bool enable = !newName.isEmpty() && (newName != QLatin1String("..")) && (newName != QLatin1Char('.')); if (enable && !m_renameOneItem) { const int count = newName.count(QLatin1Char('#')); if (count == 0) { diff --git a/src/views/tooltips/tooltipmanager.cpp b/src/views/tooltips/tooltipmanager.cpp index aae97458c..eaa785987 100644 --- a/src/views/tooltips/tooltipmanager.cpp +++ b/src/views/tooltips/tooltipmanager.cpp @@ -104,7 +104,7 @@ void ToolTipManager::showToolTip(const KFileItem& item, const QRectF& itemRect, Q_ASSERT(!m_metaDataRequested); } -void ToolTipManager::hideToolTip() +void ToolTipManager::hideToolTip(const HideBehavior behavior) { if (m_appliedWaitCursor) { QApplication::restoreOverrideCursor(); @@ -116,7 +116,14 @@ void ToolTipManager::hideToolTip() m_showToolTipTimer->stop(); m_contentRetrievalTimer->stop(); if (m_tooltipWidget) { - m_tooltipWidget->hideLater(); + switch (behavior) { + case HideBehavior::Instantly: + m_tooltipWidget->hide(); + break; + case HideBehavior::Later: + m_tooltipWidget->hideLater(); + break; + } } } diff --git a/src/views/tooltips/tooltipmanager.h b/src/views/tooltips/tooltipmanager.h index 10f88ad76..c09a40d31 100644 --- a/src/views/tooltips/tooltipmanager.h +++ b/src/views/tooltips/tooltipmanager.h @@ -42,6 +42,11 @@ class ToolTipManager : public QObject Q_OBJECT public: + enum class HideBehavior { + Instantly, + Later + }; + explicit ToolTipManager(QWidget* parent); ~ToolTipManager() override; @@ -56,7 +61,7 @@ public: /** * Hides the currently shown tooltip. */ - void hideToolTip(); + void hideToolTip(const HideBehavior behavior = HideBehavior::Later); signals: /** diff --git a/src/views/versioncontrol/fileviewversioncontrolplugin.desktop b/src/views/versioncontrol/fileviewversioncontrolplugin.desktop index 72c02b735..a3b45fc42 100644 --- a/src/views/versioncontrol/fileviewversioncontrolplugin.desktop +++ b/src/views/versioncontrol/fileviewversioncontrolplugin.desktop @@ -23,7 +23,7 @@ Comment[id]=Plugin Kendali Versi untuk Tampilan File Comment[it]=Estensione di controllo delle versioni per le viste dei file Comment[ja]=ファイルビューのためのバージョン管理プラグイン Comment[ko]=파일 보기를 위한 버전 관리 플러그인 -Comment[lt]=Versijų kontrolės papildinys failų tvarkyklėms +Comment[lt]=Failo rodinių versijų tvarkymo papildinys Comment[ml]=ഫയല്‍ അവതരണദിശകൾക്കുള്ള പതിപ്പ് നിയന്ത്രണ സംയോജകം Comment[nb]=Versjonskontrollmodul for filvisninger Comment[nl]=Plugin voor versiecontrole op bestandoverzichten diff --git a/src/views/viewproperties.cpp b/src/views/viewproperties.cpp index eddc7225d..e5f3a82c4 100644 --- a/src/views/viewproperties.cpp +++ b/src/views/viewproperties.cpp @@ -26,6 +26,8 @@ #include +#include + namespace { const int AdditionalInfoViewPropertiesVersion = 1; const int NameRolePropertiesVersion = 2; @@ -57,7 +59,7 @@ ViewProperties::ViewProperties(const QUrl& url) : // we store the properties information in a local file. if (useGlobalViewProps) { m_filePath = destinationDir(QStringLiteral("global")); - } else if (url.scheme().contains(QStringLiteral("search"))) { + } else if (url.scheme().contains(QLatin1String("search"))) { m_filePath = destinationDir(QStringLiteral("search/")) + directoryHashForUrl(url); useDetailsViewWithPath = true; } else if (url.scheme() == QLatin1String("trash")) { @@ -70,6 +72,11 @@ ViewProperties::ViewProperties(const QUrl& url) : m_filePath = url.toLocalFile(); bool useDestinationDir = !isPartOfHome(m_filePath); + if (!useDestinationDir) { + const KFileItem fileItem(url); + useDestinationDir = fileItem.isSlow(); + } + if (!useDestinationDir) { const QFileInfo dirInfo(m_filePath); const QFileInfo fileInfo(m_filePath + QDir::separator() + ViewPropertiesFileName);