diff options
Diffstat (limited to 'src')
39 files changed, 434 insertions, 238 deletions
diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp index 1dfbe054d..50bd9e515 100644 --- a/src/dolphincontextmenu.cpp +++ b/src/dolphincontextmenu.cpp @@ -1,4 +1,4 @@ -/*************************************************************************** + /*************************************************************************** * Copyright (C) 2006 by Peter Penz ([email protected]) 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; @@ -210,9 +209,7 @@ void DolphinContextMenu::openItemContextMenu() // 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")); + addAction(m_mainWindow->actionCollection()->action(QStringLiteral("add_to_places"))); } addSeparator(); @@ -233,7 +230,7 @@ void DolphinContextMenu::openItemContextMenu() addMenu(menu); addSeparator(); - } else if (m_baseUrl.scheme().contains(QStringLiteral("search")) || m_baseUrl.scheme().contains(QStringLiteral("timeline"))) { + } 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")), @@ -314,14 +311,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; @@ -365,10 +355,8 @@ void DolphinContextMenu::openViewportContextMenu() 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")); + addAction(m_mainWindow->actionCollection()->action(QStringLiteral("add_to_places"))); } addSeparator(); @@ -396,21 +384,7 @@ void DolphinContextMenu::openViewportContextMenu() 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..87d041b87 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" @@ -272,7 +273,7 @@ void DolphinMainWindow::changeUrl(const QUrl &url) } m_activeViewContainer->setUrl(url); - updateEditActions(); + updateFileAndEditActions(); updatePasteAction(); updateViewActions(); updateGoActions(); @@ -301,7 +302,7 @@ void DolphinMainWindow::slotEditableStateChanged(bool editable) void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection) { - updateEditActions(); + updateFileAndEditActions(); const int selectedUrlsCount = m_tabWidget->currentTabPage()->selectedItemsCount(); @@ -352,6 +353,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().count() == 0) { + 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); @@ -500,7 +527,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 +644,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)); @@ -751,7 +784,7 @@ void DolphinMainWindow::togglePanelLockState() void DolphinMainWindow::slotTerminalPanelVisibilityChanged() { - if (m_terminalPanel->isHiddenInVisibleWindow()) { + if (m_terminalPanel->isHiddenInVisibleWindow() && m_activeViewContainer) { m_activeViewContainer->view()->setFocus(); } } @@ -1084,6 +1117,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 +1136,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); @@ -1156,6 +1193,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." "<nl/>You can drag and drop items between windows.")); @@ -1171,6 +1209,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 +1268,17 @@ void DolphinMainWindow::setupActions() "the find bar so we can have a look at it while the settings are " "explained.</para>")); + // 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.")); @@ -1351,7 +1406,7 @@ void DolphinMainWindow::setupActions() openTerminal->setWhatsThis(xi18nc("@info:whatsthis", "<para>This opens a <emphasis>terminal</emphasis> application for the viewed location.</para>" "<para>To learn more about terminals use the help in the terminal application.</para>")); - 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 +1593,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 +1658,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 +1666,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")) @@ -1659,15 +1714,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 +1735,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 +1795,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 +1808,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 +1870,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, diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index dcfd9bce2..253fc74d4 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -255,6 +255,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. @@ -382,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. */ void openNewTab(const QUrl& url, DolphinTabWidget::TabPlacement tabPlacement); @@ -512,7 +520,7 @@ private: */ void setupDockWidgets(); - void updateEditActions(); + void updateFileAndEditActions(); void updateViewActions(); void updateGoActions(); 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/dolphintabwidget.cpp b/src/dolphintabwidget.cpp index 7928c510e..0546316f7 100644 --- a/src/dolphintabwidget.cpp +++ b/src/dolphintabwidget.cpp @@ -161,6 +161,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 +171,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 @@ -329,7 +330,12 @@ void DolphinTabWidget::tabUrlChanged(const QUrl& url) const int index = indexOf(qobject_cast<QWidget*>(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 +363,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(); } diff --git a/src/dolphinui.rc b/src/dolphinui.rc index b90321d05..754670a7e 100644 --- a/src/dolphinui.rc +++ b/src/dolphinui.rc @@ -1,5 +1,5 @@ <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> -<kpartgui name="dolphin" version="22"> +<kpartgui name="dolphin" version="25"> <MenuBar> <Menu name="file"> <Action name="new_menu" /> @@ -8,6 +8,8 @@ <Action name="file_close" /> <Action name="undo_close_tab" /> <Separator/> + <Action name="add_to_places" /> + <Separator/> <Action name="renamefile" /> <Action name="movetotrash" /> <Action name="deletefile" /> @@ -98,10 +100,11 @@ <Action name="compact" /> <Action name="details" /> <Separator name="separator_0" /> - <Action name="edit_find"/> - <Action name="show_preview" /> + <Action name="sort" /> + <Spacer name="spacer_0" /> <Action name="split_view" /> <Action name="split_stash" /> + <Action name="toggle_search" /> </ToolBar> <ActionProperties scheme="Default"> <Action priority="0" name="go_back"/> @@ -117,5 +120,6 @@ <Action priority="0" name="edit_cut"/> <Action priority="0" name="edit_copy"/> <Action priority="0" name="edit_paste"/> + <Action priority="0" name="toggle_search"/> </ActionProperties> </kpartgui> diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 6a8ff914b..9af1bc926 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -412,6 +412,8 @@ void DolphinViewContainer::setSearchModeEnabled(bool enabled) } m_searchModeEnabled = enabled; + + emit searchModeEnabledChanged(enabled); } bool DolphinViewContainer::isSearchModeEnabled() const @@ -697,7 +699,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 { @@ -785,7 +787,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<QUrl>& 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<QPair<QSharedPointer<QDBusInterface>, QStringList>> dolphinServices; if (!preferredService.isEmpty()) { QSharedPointer<QDBusInterface> preferred( @@ -91,11 +85,16 @@ bool Dolphin::attachToExistingInstance(const QList<QUrl>& 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<QUrl>& 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<QUrl>& inputUrls, bool openFi for (auto& service: dolphinServices) { QDBusReply<bool> 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<QByteArray, QVariant> 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<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const { Q_ASSERT(!m_itemData.isEmpty()); @@ -1905,28 +1908,35 @@ QList<QPair<int, QVariant> > 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<QChar> 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<QChar> 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<QChar>::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<QChar>::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<QPair<int, QVariant> > nameRoleGroups() const; QList<QPair<int, QVariant> > sizeRoleGroups() const; QList<QPair<int, QVariant> > timeRoleGroups(const std::function<QDateTime(const ItemData *)> &fileTimeCb) const; diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 15c01726f..617ed57f8 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); } @@ -1482,7 +1482,7 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStrin 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)) { 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/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/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..8c5d56da5 100644 --- a/src/panels/information/informationpanelcontent.cpp +++ b/src/panels/information/informationpanelcontent.cpp @@ -46,11 +46,18 @@ #include <QTimer> #include <QVBoxLayout> #include <QStyle> +#include <QPainter> +#include <QBitmap> +#include <QLinearGradient> +#include <QPolygon> #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); @@ -166,6 +174,41 @@ void InformationPanelContent::showItem(const KFileItem& item) 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 +217,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,53 +233,46 @@ 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; + m_isVideo = mimeType.startsWith(QLatin1String("video/")); + usePhonon = m_isVideo || mimeType.startsWith(QLatin1String("audio/")); if (usePhonon) { + // change the cursor of the preview + m_preview->setCursor(Qt::PointingHandCursor); + m_preview->installEventFilter(m_phononWidget); - 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(); - } + // 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(), isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio); - m_phononWidget->setVideoSize(m_preview->size()); + m_phononWidget->show(); + m_phononWidget->setUrl(m_item.targetUrl(), m_isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio); + adjustWidgetSizes(parentWidget()->width()); + } } else { // 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 { @@ -319,10 +357,46 @@ void InformationPanelContent::showPreview(const KFileItem& item, const QPixmap& pixmap) { m_outdatedPreviewTimer->stop(); - Q_UNUSED(item); + 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<int>(p.width() / 2 - PLAY_ARROW_SIZE / 2 / devicePixelRatio()); + const int zeroY = static_cast<int>(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 +417,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<QMouseEvent*>(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/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/kcm/kcmdolphingeneral.desktop b/src/settings/kcm/kcmdolphingeneral.desktop index ac3956144..0d0a0c093 100644 --- a/src/settings/kcm/kcmdolphingeneral.desktop +++ b/src/settings/kcm/kcmdolphingeneral.desktop @@ -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 diff --git a/src/settings/kcm/kcmdolphinnavigation.desktop b/src/settings/kcm/kcmdolphinnavigation.desktop index f6686fbc8..0018e056a 100644 --- a/src/settings/kcm/kcmdolphinnavigation.desktop +++ b/src/settings/kcm/kcmdolphinnavigation.desktop @@ -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 diff --git a/src/settings/kcm/kcmdolphinservices.desktop b/src/settings/kcm/kcmdolphinservices.desktop index 07ac89c52..4f547d5a7 100644 --- a/src/settings/kcm/kcmdolphinservices.desktop +++ b/src/settings/kcm/kcmdolphinservices.desktop @@ -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 diff --git a/src/settings/kcm/kcmdolphinviewmodes.desktop b/src/settings/kcm/kcmdolphinviewmodes.desktop index c50fa3800..15a789af1 100644 --- a/src/settings/kcm/kcmdolphinviewmodes.desktop +++ b/src/settings/kcm/kcmdolphinviewmodes.desktop @@ -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 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 <QDir> #include <QDirIterator> #include <QCommandLineParser> +#include <QMimeDatabase> #include <KLocalizedString> @@ -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/views/dolphinview.cpp b/src/views/dolphinview.cpp index 5b00fa36d..e6b232dcc 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -128,8 +128,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 +744,7 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) break; case QEvent::KeyPress: + hideToolTip(ToolTipManager::HideBehavior::Instantly); if (GeneralSettings::useTabForSwitchingSplitView()) { QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) { @@ -1414,11 +1415,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..a4da92f2d 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 <KFileItem> #include <KIO/Job> @@ -697,8 +698,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. @@ -734,6 +733,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..4aa59911b 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -163,7 +163,7 @@ void DolphinViewActionHandler::createActions() "</interface> option is enabled.</para>")); compactAction->setWhatsThis(xi18nc("@info:whatsthis Compact view mode", "<para>This switches to a compact view mode that lists the folders " - "and files in columns with the names beside the icons. <para></para>" + "and files in columns with the names beside the icons.</para><para>" "This helps to keep the overview in folders with many items.</para>")); detailsAction->setWhatsThis(xi18nc("@info:whatsthis Details view mode", "<para>This switches to a list view mode that focuses on folder " @@ -191,7 +191,7 @@ void DolphinViewActionHandler::createActions() 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<KToggleAction>(QStringLiteral("show_preview")); showPreview->setText(i18nc("@action:intoolbar", "Preview")); @@ -280,7 +280,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); @@ -535,11 +535,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) 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/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 <QCryptographicHash> +#include <KFileItem> + 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")) { @@ -71,6 +73,11 @@ ViewProperties::ViewProperties(const QUrl& url) : 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); useDestinationDir = !dirInfo.isWritable() || (dirInfo.size() > 0 && fileInfo.exists() && !(fileInfo.isReadable() && fileInfo.isWritable())); |
