include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
'frameworks/kwindowsystem': '@stable'
'frameworks/kactivities': '@stable'
'frameworks/kdoctools': '@stable'
- 'frameworks/baloo': '@stable'
'frameworks/kwindowsystem': '@stable'
'frameworks/kfilemetadata': '@stable'
- 'libraries/baloo-widgets': '@same'
'libraries/kuserfeedback': '@stable'
'libraries/phonon': '@stable'
+
+- 'on': ['Linux', 'FreeBSD']
+ 'require':
+ 'frameworks/baloo': '@stable'
+ 'libraries/baloo-widgets': '@same'
+
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "22")
-set (RELEASE_SERVICE_VERSION_MINOR "03")
-set (RELEASE_SERVICE_VERSION_MICRO "90")
+set (RELEASE_SERVICE_VERSION_MINOR "07")
+set (RELEASE_SERVICE_VERSION_MICRO "70")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(Dolphin VERSION ${RELEASE_SERVICE_VERSION})
Notifications
Crash
WindowSystem
+ WidgetsAddons
)
-find_package(KUserFeedback 1.0.0)
+find_package(KUserFeedback 1.2.0)
set_package_properties(KUserFeedback
PROPERTIES TYPE OPTIONAL
PURPOSE "Used for submission of telemetry data"
find_package(Phonon4Qt${QT_MAJOR_VERSION} CONFIG REQUIRED)
-find_package(PackageKitQt5)
-set_package_properties(PackageKitQt5
+find_package(PackageKitQt${QT_MAJOR_VERSION})
+set_package_properties(PackageKitQt${QT_MAJOR_VERSION}
PROPERTIES DESCRIPTION "Software Manager integration"
TYPE OPTIONAL
PURPOSE "Used in the service menu installer"
)
-if(PackageKitQt5_FOUND)
+if(PackageKitQt${QT_MAJOR_VERSION}_FOUND)
set(HAVE_PACKAGEKIT TRUE)
endif()
target_sources(dolphinprivate PRIVATE
kitemviews/kfileitemlistview.cpp
kitemviews/kfileitemlistwidget.cpp
+ kitemviews/kfileitemlisttostring.cpp
kitemviews/kfileitemmodel.cpp
kitemviews/kfileitemmodelrolesupdater.cpp
kitemviews/kitemlistcontainer.cpp
kitemviews/private/kitemlistviewanimation.cpp
kitemviews/private/kitemlistviewlayouter.cpp
kitemviews/private/kpixmapmodifier.cpp
- kitemviews/private/ktwofingerswipe.cpp
- kitemviews/private/ktwofingertap.cpp
settings/applyviewpropsjob.cpp
settings/viewmodes/viewmodesettings.cpp
settings/viewpropertiesdialog.cpp
KF5::NewStuff
KF5::Parts
KF5::WindowSystem
+ KF5::WidgetsAddons
)
if(HAVE_BALOO)
KF5::KCMUtils
KF5::DBusAddons
KF5::Notifications
- Phonon::phonon4qt5
+ Phonon::phonon4qt${QT_MAJOR_VERSION}
)
if (HAVE_KACTIVITIES)
#include "dolphinplacesmodelsingleton.h"
#include "dolphinremoveaction.h"
#include "dolphinviewcontainer.h"
+#include "global.h"
#include "trash/dolphintrash.h"
#include "views/dolphinview.h"
#include "views/viewmodecontroller.h"
#include <QMimeDatabase>
DolphinContextMenu::DolphinContextMenu(DolphinMainWindow* parent,
- const QPoint& pos,
const KFileItem& fileInfo,
+ const KFileItemList &selectedItems,
const QUrl& baseUrl,
KFileItemActions *fileItemActions) :
QMenu(parent),
- m_pos(pos),
m_mainWindow(parent),
m_fileInfo(fileInfo),
m_baseUrl(baseUrl),
m_baseFileItem(nullptr),
- m_selectedItems(),
+ m_selectedItems(selectedItems),
m_selectedItemsProperties(nullptr),
m_context(NoContext),
m_copyToMenu(parent),
- m_customActions(),
- m_command(None),
m_removeAction(nullptr),
m_fileItemActions(fileItemActions)
{
- // The context menu either accesses the URLs of the selected items
- // or the items itself. To increase the performance both lists are cached.
- const DolphinView* view = m_mainWindow->activeViewContainer()->view();
- m_selectedItems = view->selectedItems();
-
QApplication::instance()->installEventFilter(this);
- static_cast<KHamburgerMenu *>(m_mainWindow->actionCollection()->
- action(QStringLiteral("hamburger_menu")))->addToMenu(this);
+ addAllActions();
}
DolphinContextMenu::~DolphinContextMenu()
m_selectedItemsProperties = nullptr;
}
-void DolphinContextMenu::setCustomActions(const QList<QAction*>& actions)
+void DolphinContextMenu::addAllActions()
{
- m_customActions = actions;
-}
+ static_cast<KHamburgerMenu *>(m_mainWindow->actionCollection()->
+ action(QStringLiteral("hamburger_menu")))->addToMenu(this);
-DolphinContextMenu::Command DolphinContextMenu::open()
-{
// get the context information
const auto scheme = m_baseUrl.scheme();
if (scheme == QLatin1String("trash")) {
// open the corresponding popup for the context
if (m_context & TrashContext) {
if (m_context & ItemContext) {
- openTrashItemContextMenu();
+ addTrashItemContextMenu();
} else {
- openTrashContextMenu();
+ addTrashContextMenu();
}
} else if (m_context & ItemContext) {
- openItemContextMenu();
+ addItemContextMenu();
} else {
- openViewportContextMenu();
+ addViewportContextMenu();
}
-
- return m_command;
}
bool DolphinContextMenu::eventFilter(QObject* object, QEvent* event)
return false;
}
-void DolphinContextMenu::openTrashContextMenu()
+void DolphinContextMenu::addTrashContextMenu()
{
Q_ASSERT(m_context & TrashContext);
- QAction* emptyTrashAction = new QAction(QIcon::fromTheme(QStringLiteral("trash-empty")), i18nc("@action:inmenu", "Empty Trash"), this);
+ QAction *emptyTrashAction = addAction(QIcon::fromTheme(QStringLiteral("trash-empty")), i18nc("@action:inmenu", "Empty Trash"), [this](){
+ Trash::empty(m_mainWindow);
+ });
emptyTrashAction->setEnabled(!Trash::isEmpty());
- addAction(emptyTrashAction);
-
- addCustomActions();
QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties"));
addAction(propertiesAction);
-
- if (exec(m_pos) == emptyTrashAction) {
- Trash::empty(m_mainWindow);
- }
}
-void DolphinContextMenu::openTrashItemContextMenu()
+void DolphinContextMenu::addTrashItemContextMenu()
{
Q_ASSERT(m_context & TrashContext);
Q_ASSERT(m_context & ItemContext);
- QAction* restoreAction = new QAction(QIcon::fromTheme("restoration"), i18nc("@action:inmenu", "Restore"), m_mainWindow);
- addAction(restoreAction);
-
- QAction* deleteAction = m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile));
- addAction(deleteAction);
-
- QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties"));
- addAction(propertiesAction);
-
- if (exec(m_pos) == restoreAction) {
+ addAction(QIcon::fromTheme("restoration"), i18nc("@action:inmenu", "Restore"), [this](){
QList<QUrl> selectedUrls;
selectedUrls.reserve(m_selectedItems.count());
for (const KFileItem &item : qAsConst(m_selectedItems)) {
KIO::RestoreJob *job = KIO::restoreFromTrash(selectedUrls);
KJobWidgets::setWindow(job, m_mainWindow);
job->uiDelegate()->setAutoErrorHandlingEnabled(true);
- }
+ });
+
+ QAction* deleteAction = m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::DeleteFile));
+ addAction(deleteAction);
+
+ QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties"));
+ addAction(propertiesAction);
}
void DolphinContextMenu::addDirectoryItemContextMenu()
// set up 'Create New' menu
DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow->actionCollection(), m_mainWindow);
- const DolphinView* view = m_mainWindow->activeViewContainer()->view();
newFileMenu->checkUpToDate();
newFileMenu->setPopupFiles(QList<QUrl>() << m_fileInfo.url());
newFileMenu->setEnabled(selectedItemsProps.supportsWriting());
addSeparator();
}
-void DolphinContextMenu::openItemContextMenu()
+void DolphinContextMenu::addItemContextMenu()
{
Q_ASSERT(!m_fileInfo.isNull());
- QAction* openParentAction = nullptr;
- QAction* openParentInNewWindowAction = nullptr;
- QAction* openParentInNewTabAction = nullptr;
const KFileItemListProperties& selectedItemsProps = selectedItemsProperties();
-
m_fileItemActions->setItemListProperties(selectedItemsProps);
if (m_selectedItems.count() == 1) {
} else if (m_context & TimelineContext || m_context & SearchContext) {
addOpenWithActions();
- openParentAction = new QAction(QIcon::fromTheme(QStringLiteral("document-open-folder")),
+ addAction(QIcon::fromTheme(QStringLiteral("document-open-folder")),
i18nc("@action:inmenu",
"Open Path"),
- this);
- addAction(openParentAction);
+ [this](){
+ m_mainWindow->changeUrl(KIO::upUrl(m_fileInfo.url()));
+ m_mainWindow->activeViewContainer()->view()->markUrlsAsSelected({m_fileInfo.url()});
+ m_mainWindow->activeViewContainer()->view()->markUrlAsCurrent(m_fileInfo.url());
+ });
- openParentInNewWindowAction = new QAction(QIcon::fromTheme(QStringLiteral("window-new")),
+ addAction(QIcon::fromTheme(QStringLiteral("window-new")),
i18nc("@action:inmenu",
"Open Path in New Window"),
- this);
- addAction(openParentInNewWindowAction);
+ [this](){
+ Dolphin::openNewWindow({m_fileInfo.url()}, m_mainWindow, Dolphin::OpenNewWindowFlag::Select);
+ });
- openParentInNewTabAction = new QAction(QIcon::fromTheme(QStringLiteral("tab-new")),
+ addAction(QIcon::fromTheme(QStringLiteral("tab-new")),
i18nc("@action:inmenu",
"Open Path in New Tab"),
- this);
- addAction(openParentInNewTabAction);
+ [this](){
+ m_mainWindow->openNewTab(KIO::upUrl(m_fileInfo.url()));
+ });
addSeparator();
} else {
addSeparator();
QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties"));
addAction(propertiesAction);
-
- QAction* activatedAction = exec(m_pos);
- if (activatedAction) {
- if (activatedAction == openParentAction) {
- m_command = OpenParentFolder;
- } else if (activatedAction == openParentInNewWindowAction) {
- m_command = OpenParentFolderInNewWindow;
- } else if (activatedAction == openParentInNewTabAction) {
- m_command = OpenParentFolderInNewTab;
- }
- }
}
-void DolphinContextMenu::openViewportContextMenu()
+void DolphinContextMenu::addViewportContextMenu()
{
- const DolphinView* view = m_mainWindow->activeViewContainer()->view();
-
const KFileItemListProperties baseUrlProperties(KFileItemList() << baseFileItem());
m_fileItemActions->setItemListProperties(baseUrlProperties);
}
addAdditionalActions(baseUrlProperties);
- addCustomActions();
addSeparator();
QAction* propertiesAction = m_mainWindow->actionCollection()->action(QStringLiteral("properties"));
addAction(propertiesAction);
-
- exec(m_pos);
}
void DolphinContextMenu::insertDefaultItemActions(const KFileItemListProperties& properties)
m_fileItemActions->insertOpenWithActionsTo(nullptr, this, QStringList{qApp->desktopFileName()});
}
-void DolphinContextMenu::addCustomActions()
-{
- addActions(m_customActions);
-}
-
void DolphinContextMenu::addAdditionalActions(const KFileItemListProperties &props)
{
addSeparator();
Q_OBJECT
public:
- enum Command
- {
- None,
- OpenParentFolder,
- OpenParentFolderInNewWindow,
- OpenParentFolderInNewTab
- };
-
/**
* @parent Pointer to the main window the context menu
* belongs to.
- * @pos Position in screen coordinates.
* @fileInfo Pointer to the file item the context menu
* is applied. If 0 is passed, the context menu
* is above the viewport.
+ * @selectedItems The selected items for which the context menu
+ * is opened. This list generally includes \a fileInfo.
* @baseUrl Base URL of the viewport where the context menu
* should be opened.
*/
DolphinContextMenu(DolphinMainWindow* parent,
- const QPoint& pos,
const KFileItem& fileInfo,
+ const KFileItemList &selectedItems,
const QUrl& baseUrl,
KFileItemActions *fileItemActions);
~DolphinContextMenu() override;
- void setCustomActions(const QList<QAction*>& actions);
-
- /**
- * Opens the context menu model and returns the requested
- * command, that should be triggered by the caller. If
- * Command::None has been returned, either the context-menu
- * had been closed without executing an action or an
- * already available action from the main-window has been
- * executed.
- */
- Command open();
-
protected:
bool eventFilter(QObject* object, QEvent* event) override;
private:
- void openTrashContextMenu();
- void openTrashItemContextMenu();
- void openItemContextMenu();
- void openViewportContextMenu();
-
- void insertDefaultItemActions(const KFileItemListProperties&);
-
/**
- * Adds the "Show menubar" action to the menu if the
- * menubar is hidden.
+ * Adds all the actions and menus to this menu based on all given information.
+ * This method calls the other helper methods for adding actions
+ * based on the context given in the constructor.
*/
- void addShowMenuBarAction();
+ void addAllActions();
+
+ void addTrashContextMenu();
+ void addTrashItemContextMenu();
+ void addItemContextMenu();
+ void addViewportContextMenu();
+
+ void insertDefaultItemActions(const KFileItemListProperties&);
bool placeExists(const QUrl& url) const;
*/
void addOpenWithActions();
- /**
- * Adds custom actions e.g. like the "[x] Expandable Folders"-action
- * provided in the details view.
- */
- void addCustomActions();
-
-private:
/**
* Add services, custom actions, plugins and version control items to the menu
*/
void addAdditionalActions(const KFileItemListProperties &props);
+private:
struct Entry
{
int type;
SearchContext = 8,
};
- QPoint m_pos;
DolphinMainWindow* m_mainWindow;
KFileItem m_fileInfo;
int m_context;
KFileCopyToMenu m_copyToMenu;
- QList<QAction*> m_customActions;
-
- Command m_command;
DolphinRemoveAction* m_removeAction; // Action that represents either 'Move To Trash' or 'Delete'
void addDirectoryItemContextMenu();
}
}
+QAction *DolphinMainWindow::urlNavigatorHistoryAction(const KUrlNavigator *urlNavigator, int historyIndex, QObject *parent)
+{
+ const QUrl url = urlNavigator->locationUrl(historyIndex);
+
+ QString text = url.toDisplayString(QUrl::PreferLocalFile);
+
+ if (!urlNavigator->showFullPath()) {
+ const KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
+
+ const QModelIndex closestIdx = placesModel->closestItem(url);
+ if (closestIdx.isValid()) {
+ const QUrl placeUrl = placesModel->url(closestIdx);
+
+ text = placesModel->text(closestIdx);
+
+ QString pathInsidePlace = url.path().mid(placeUrl.path().length());
+
+ if (!pathInsidePlace.isEmpty() && !pathInsidePlace.startsWith(QLatin1Char('/'))) {
+ pathInsidePlace.prepend(QLatin1Char('/'));
+ }
+
+ if (pathInsidePlace != QLatin1Char('/')) {
+ text.append(pathInsidePlace);
+ }
+ }
+ }
+
+ QAction *action = new QAction(QIcon::fromTheme(KIO::iconNameForUrl(url)), text, parent);
+ action->setData(historyIndex);
+ return action;
+}
+
void DolphinMainWindow::slotAboutToShowBackPopupMenu()
{
const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
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).toDisplayString(QUrl::PreferLocalFile), m_backAction->menu());
+ QAction *action = urlNavigatorHistoryAction(urlNavigator, i, m_backAction->menu());
action->setData(i);
m_backAction->menu()->addAction(action);
}
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).toDisplayString(QUrl::PreferLocalFile), m_forwardAction->menu());
+ QAction *action = urlNavigatorHistoryAction(urlNavigator, i, m_forwardAction->menu());
action->setData(i);
m_forwardAction->menu()->addAction(action);
}
void DolphinMainWindow::openContextMenu(const QPoint& pos,
const KFileItem& item,
- const QUrl& url,
- const QList<QAction*>& customActions)
+ const KFileItemList &selectedItems,
+ const QUrl& url)
{
- QPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, pos, item, url, &m_fileItemActions);
- contextMenu.data()->setCustomActions(customActions);
- const DolphinContextMenu::Command command = contextMenu.data()->open();
-
- switch (command) {
- case DolphinContextMenu::OpenParentFolder:
- changeUrl(KIO::upUrl(item.url()));
- m_activeViewContainer->view()->markUrlsAsSelected({item.url()});
- m_activeViewContainer->view()->markUrlAsCurrent(item.url());
- break;
-
- case DolphinContextMenu::OpenParentFolderInNewWindow:
- Dolphin::openNewWindow({item.url()}, this, Dolphin::OpenNewWindowFlag::Select);
- break;
-
- case DolphinContextMenu::OpenParentFolderInNewTab:
- openNewTab(KIO::upUrl(item.url()));
- break;
-
- case DolphinContextMenu::None:
- default:
- break;
- }
+ QPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, item, selectedItems, url, &m_fileItemActions);
+ contextMenu.data()->exec(pos);
// Delete the menu, unless it has been deleted in its own nested event loop already.
if (contextMenu) {
* @pos Position in screen coordinates.
* @item File item context. If item is null, the context menu
* should be applied to \a url.
+ * @selectedItems The selected items for which the context menu
+ * is opened. This list generally includes \a item.
* @url URL which contains \a item.
- * @customActions Actions that should be added to the context menu,
- * if the file item is null.
*/
- void openContextMenu(const QPoint& pos,
- const KFileItem& item,
- const QUrl& url,
- const QList<QAction*>& customActions);
+ void openContextMenu(const QPoint& pos, const KFileItem& item, const KFileItemList &selectedItems, const QUrl& url);
/**
* Updates the menu that is by default at the right end of the toolbar.
*/
bool addHamburgerMenuToToolbar();
+ /** Creates an action representing an item in the URL navigator history */
+ static QAction *urlNavigatorHistoryAction(const KUrlNavigator *urlNavigator, int historyIndex, QObject *parent = nullptr);
+
private:
/**
* Implements a custom error handling for the undo manager. This
void DolphinPart::slotOpenContextMenu(const QPoint& pos,
const KFileItem& _item,
- const QUrl &,
- const QList<QAction*>& customActions)
+ const KFileItemList &selectedItems,
+ const QUrl &)
{
KParts::BrowserExtension::PopupFlags popupFlags = KParts::BrowserExtension::DefaultPopupItems
| KParts::BrowserExtension::ShowProperties
item.setUrl(url()); // ensure we use the view url, not the canonical path (#213799)
}
- // TODO: We should change the signature of the slots (and signals) for being able
- // to tell for which items we want a popup.
KFileItemList items;
- if (m_view->selectedItems().isEmpty()) {
+ if (selectedItems.isEmpty()) {
items.append(item);
} else {
- items = m_view->selectedItems();
+ items = selectedItems;
}
KFileItemListProperties capabilities(items);
KParts::BrowserExtension::ActionGroupMap actionGroups;
QList<QAction *> editActions;
editActions += m_view->versionControlActions(m_view->selectedItems());
- editActions += customActions;
if (!_item.isNull()) { // only for context menu on one or more items
const bool supportsMoving = capabilities.supportsMoving();
* @pos Position in screen coordinates.
* @item File item context. If item is null, the context menu
* should be applied to \a url.
+ * @selectedItems The selected items for which the context menu
+ * is opened. This list generally includes \a item.
* @url URL which contains \a item.
- * @customActions Actions that should be added to the context menu,
- * if the file item is null.
*/
- void slotOpenContextMenu(const QPoint& pos,
- const KFileItem& item,
- const QUrl& url,
- const QList<QAction*>& customActions);
+ void slotOpenContextMenu(const QPoint &pos, const KFileItem &_item, const KFileItemList &selectedItems, const QUrl &);
/**
* Informs the host that we are opening \a url (e.g. after a redirection
--- /dev/null
+/*
+ This file is part of the KDE project
+ SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "kfileitemlisttostring.h"
+
+#include <KFileItem>
+#include <KFileItemListProperties>
+#include <KLocalizedString>
+
+#include <QFontMetrics>
+#include <QString>
+
+QString fileItemListToString(KFileItemList items, int maximumTextWidth, QFontMetrics fontMetrics, ItemsState itemsState)
+{
+ QString text;
+ switch (items.count()) {
+ case 1:
+ text = i18nc("Textual representation of a file. %1 is the name of the file/folder.",
+ "\"%1\"", items.first().name());
+ break;
+ case 2:
+ text = i18nc("Textual representation of two files. %1 and %2 are names of files/folders.",
+ "\"%1\" and \"%2\"", items.first().name(), items.last().name());
+ break;
+ case 3:
+ text = i18nc("Textual representation of three files. %1, %2 and %3 are names of files/folders.",
+ "\"%1\", \"%2\" and \"%3\"",
+ items.first().name(), items.at(1).name(), items.last().name());
+ break;
+ case 4:
+ text = i18nc("Textual representation of four files. %1, %2, %3 and %4 are names of files/folders.",
+ "\"%1\", \"%2\", \"%3\" and \"%4\"",
+ items.first().name(), items.at(1).name(), items.at(2).name(), items.last().name());
+ break;
+ case 5:
+ text = i18nc("Textual representation of five files. %1, %2, %3, %4 and %5 are names of files/folders.",
+ "\"%1\", \"%2\", \"%3\", \"%4\" and \"%5\"",
+ items.first().name(), items.at(1).name(), items.at(2).name(), items.at(3).name(), items.last().name());
+ break;
+ default:
+ text = QString();
+ break;
+ }
+
+ // At some point the added clarity from the text starts being less important than the text width.
+ if (!text.isEmpty() && fontMetrics.horizontalAdvance(text) <= maximumTextWidth) {
+ return text;
+ }
+
+ const KFileItemListProperties properties(items);
+ if (itemsState == Selected) {
+ if (properties.isFile()) {
+ text = i18ncp("Textual representation of selected files. %1 is the number of files.",
+ "One Selected File", "%1 Selected Files", items.count());
+ } else if (properties.isDirectory()) {
+ text = i18ncp("Textual representation of selected folders. %1 is the number of folders.",
+ "One Selected Folder", "%1 Selected Folders", items.count());
+ } else {
+ text = i18ncp("Textual representation of selected fileitems. %1 is the number of files/folders.",
+ "One Selected Item", "%1 Selected Items", items.count());
+ }
+
+ if (fontMetrics.horizontalAdvance(text) <= maximumTextWidth) {
+ return text;
+ }
+ }
+
+ if (properties.isFile()) {
+ return i18ncp("Textual representation of files. %1 is the number of files.",
+ "One File", "%1 Files", items.count());
+ } else if (properties.isDirectory()) {
+ return i18ncp("Textual representation of folders. %1 is the number of folders.",
+ "One Folder", "%1 Folders", items.count());
+ } else {
+ return i18ncp("Textual representation of fileitems. %1 is the number of files/folders.",
+ "One Item", "%1 Items", items.count());
+ }
+}
--- /dev/null
+/*
+ This file is part of the KDE project
+ SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#ifndef KFILEITEMLISTTOSTRING_H
+#define KFILEITEMLISTTOSTRING_H
+
+class KFileItemList;
+class QFontMetrics;
+class QString;
+
+enum ItemsState {
+ None,
+ Selected
+};
+
+/**
+ * @brief Generates a textual representation of the given list of KFileItems.
+ *
+ * This method is especially useful to be very explicit about which items will be affected by an action.
+ * For example can a label for a delete button be enriched to say "Permanantly Delete `picture1` and `picture2`"
+ * but also "Permanently Delete 7 Selected Folders" without requiring a huge amount of new translations for this.
+ *
+ * Unfortunately this doesn't always work.
+ *
+ * For some texts and some languages this wide range of words cannot be inserted into a text while staying
+ * grammatically correct. Because of this you will probably need to write a fallback for these languages.
+ * Something like this:
+ * \code
+ * // i18n: @action:inmenu menu with actions like copy, paste, rename.
+ * // %2 is a textual representation of the currently selected files or folders. This can be the name of
+ * // the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
+ * // If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
+ * // and a fallback will be used.
+ * auto buttonText = i18ncp("@action A more elaborate and clearly worded version of the Delete action", "Permanently Delete %2", "Permanently Delete %2", items.count(), fileItemListToString(items, fontMetrics.averageCharWidth() * 20, fontMetrics));
+ * if (buttonText == QStringLiteral("NULL")) {
+ * buttonText = i18ncp("@action Delete button label. %1 is the number of items to be deleted.",
+ * "Permanently Delete %1 Item", "Permanently Delete %1 Items", items.count())
+ * }
+ * \endcode
+ * (The i18n call should be completely in the line following the i18n: comment without any line breaks within the i18n call or the comment might not be correctly extracted. See: https://commits.kde.org/kxmlgui/a31135046e1b3335b5d7bbbe6aa9a883ce3284c1 )
+ *
+ * @param items The KFileItemList for which a QString should be generated.
+ * @param maximumTextWidth The maximum width/horizontalAdvance the QString should have. Keep scaling in mind.
+ * @param fontMetrics the fontMetrics for the font that is used to calculate the maximumTextWidth.
+ * @param itemsState A state of the @p items that should be spelled out in the returned QString.
+ * @returns the names of the @p items separated by commas if that is below the @p maximumCharacterWidth.
+ * Otherwise returns something like "5 Files", "8 Selected Folders" or "60 Items"
+ * while being as specific as possible.
+ */
+QString fileItemListToString(KFileItemList items, int maximumTextWidth, QFontMetrics fontMetrics, ItemsState itemsState = ItemsState::None);
+
+#endif // KFILEITEMLISTTOSTRING_H
#include <KDirLister>
#include <KIO/Job>
-#include <KIO/kio_version.h>
+#include <kio_version.h>
#include <KLocalizedString>
#include <KLazyLocalizedString>
#include <KUrlMimeData>
#include "kitemlistview.h"
#include "private/kitemlistkeyboardsearchmanager.h"
#include "private/kitemlistrubberband.h"
-#include "private/ktwofingerswipe.h"
-#include "private/ktwofingertap.h"
#include "views/draganddrophelper.h"
+#include <KTwoFingerSwipe>
+#include <KTwoFingerTap>
+
#include <QAccessible>
#include <QApplication>
#include <QDrag>
QString ret = m_customizedFontMetrics.elidedText(text.chopped(extensionLength),
Qt::ElideRight,
elidingWidth - extensionWidth);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
ret.append(text.rightRef(extensionLength));
+#else
+ ret.append(QStringView(text).right(extensionLength));
+#endif
return ret;
}
}
+++ /dev/null
-/*
- * SPDX-FileCopyrightText: 2020 Steffen Hartleib <steffenhartleib@t-online.de>
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-// Self
-#include "ktwofingerswipe.h"
-
-// Qt
-#include <QTouchEvent>
-#include <QLineF>
-
-KTwoFingerSwipeRecognizer::KTwoFingerSwipeRecognizer() :
- QGestureRecognizer(),
- m_touchBeginnTimestamp(0),
- m_gestureAlreadyTriggered(false)
-{
-}
-
-KTwoFingerSwipeRecognizer::~KTwoFingerSwipeRecognizer()
-{
-}
-
-QGesture* KTwoFingerSwipeRecognizer::create(QObject*)
-{
- return static_cast<QGesture*>(new KTwoFingerSwipe());
-}
-
-QGestureRecognizer::Result KTwoFingerSwipeRecognizer::recognize(QGesture* gesture, QObject* watched, QEvent* event)
-{
- Q_UNUSED(watched)
-
- KTwoFingerSwipe* const kTwoFingerSwipe = static_cast<KTwoFingerSwipe*>(gesture);
- const QTouchEvent* touchEvent = static_cast<const QTouchEvent*>(event);
-
- const int maxTimeFrameForSwipe = 90;
- const int minDistanceForSwipe = 30;
-
- switch (event->type()) {
- case QEvent::TouchBegin: {
- m_touchBeginnTimestamp = touchEvent->timestamp();
- m_gestureAlreadyTriggered = false;
- kTwoFingerSwipe->setHotSpot(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerSwipe->setPos(touchEvent->touchPoints().first().startPos());
- kTwoFingerSwipe->setScreenPos(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerSwipe->setScenePos(touchEvent->touchPoints().first().startScenePos());
- return MayBeGesture;
- }
-
- case QEvent::TouchUpdate: {
- const qint64 now = touchEvent->timestamp();
- const qint64 elapsedTime = now - m_touchBeginnTimestamp;
- const QPointF distance = touchEvent->touchPoints().first().startPos() - touchEvent->touchPoints().first().pos();
- kTwoFingerSwipe->setHotSpot(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerSwipe->setPos(touchEvent->touchPoints().first().startPos());
- kTwoFingerSwipe->setScreenPos(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerSwipe->setScenePos(touchEvent->touchPoints().first().startScenePos());
- const QLineF ql = QLineF(touchEvent->touchPoints().first().startPos(), touchEvent->touchPoints().first().pos());
- kTwoFingerSwipe->setSwipeAngle(ql.angle());
-
- if (touchEvent->touchPoints().size() > 2) {
- return CancelGesture;
- }
-
- if (touchEvent->touchPoints().size() == 2) {
- if ((elapsedTime) > maxTimeFrameForSwipe) {
- return CancelGesture;
- }
-
- if (distance.manhattanLength() >= minDistanceForSwipe &&
- (elapsedTime) <= maxTimeFrameForSwipe && !m_gestureAlreadyTriggered) {
- m_gestureAlreadyTriggered = true;
- return FinishGesture;
- } else if ((elapsedTime) <= maxTimeFrameForSwipe && !m_gestureAlreadyTriggered) {
- return TriggerGesture;
- }
- }
- break;
- }
-
- default:
- return Ignore;
- }
- return Ignore;
-}
-
-KTwoFingerSwipe::KTwoFingerSwipe(QObject* parent) :
- QGesture(parent),
- m_pos(QPointF(-1, -1)),
- m_screenPos(QPointF(-1, -1)),
- m_scenePos(QPointF(-1, -1)),
- m_swipeAngle(0.0)
-{
-}
-
-KTwoFingerSwipe::~KTwoFingerSwipe()
-{
-}
-
-QPointF KTwoFingerSwipe::pos() const
-{
- return m_pos;
-}
-
-void KTwoFingerSwipe::setPos(QPointF _pos)
-{
- m_pos = _pos;
-}
-
-QPointF KTwoFingerSwipe::screenPos() const
-{
- return m_screenPos;
-}
-
-void KTwoFingerSwipe::setScreenPos(QPointF _screenPos)
-{
- m_screenPos = _screenPos;
-}
-
-QPointF KTwoFingerSwipe::scenePos() const
-{
- return m_scenePos;
-}
-
-void KTwoFingerSwipe::setScenePos(QPointF _scenePos)
-{
- m_scenePos = _scenePos;
-}
-
-qreal KTwoFingerSwipe::swipeAngle() const
-{
- return m_swipeAngle;
-}
- void KTwoFingerSwipe::setSwipeAngle(qreal _swipeAngle)
-{
- m_swipeAngle = _swipeAngle;
-}
-
+++ /dev/null
-/*
- * SPDX-FileCopyrightText: 2020 Steffen Hartleib <steffenhartleib@t-online.de>
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef KTWOFINGERSWIPE_H
-#define KTWOFINGERSWIPE_H
-
-#include "dolphin_export.h"
-// Qt
-#include <QGesture>
-#include <QGestureRecognizer>
-
-class DOLPHIN_EXPORT KTwoFingerSwipe : public QGesture
-{
- Q_OBJECT
- Q_PROPERTY(QPointF pos READ pos WRITE setPos)
- Q_PROPERTY(QPointF screenPos READ screenPos WRITE setScreenPos)
- Q_PROPERTY(QPointF scenePos READ scenePos WRITE setScenePos)
- Q_PROPERTY(qreal swipeAngle READ swipeAngle WRITE setSwipeAngle)
-public:
- explicit KTwoFingerSwipe(QObject* parent = nullptr);
- ~KTwoFingerSwipe() override;
- QPointF pos() const;
- void setPos(QPointF pos);
- QPointF screenPos() const;
- void setScreenPos(QPointF screenPos);
- QPointF scenePos() const;
- void setScenePos(QPointF scenePos);
- qreal swipeAngle() const;
- void setSwipeAngle(qreal swipeAngle);
-private:
- QPointF m_pos;
- QPointF m_screenPos;
- QPointF m_scenePos;
- qreal m_swipeAngle;
-};
-
-class DOLPHIN_EXPORT KTwoFingerSwipeRecognizer : public QGestureRecognizer
-{
-public:
- explicit KTwoFingerSwipeRecognizer();
- ~KTwoFingerSwipeRecognizer() override;
- QGesture* create(QObject*) override;
- Result recognize(QGesture*, QObject*, QEvent*) override;
-private:
- Q_DISABLE_COPY( KTwoFingerSwipeRecognizer )
- qint64 m_touchBeginnTimestamp;
- bool m_gestureAlreadyTriggered;
-};
-
-#endif /* KTWOFINGERSWIPE_H */
-
+++ /dev/null
-/*
- * SPDX-FileCopyrightText: 2020 Steffen Hartleib <steffenhartleib@t-online.de>
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-// Self
-#include "ktwofingertap.h"
-
-// Qt
-#include <QTouchEvent>
-#include <QApplication>
-#include <QGraphicsWidget>
-
-KTwoFingerTapRecognizer::KTwoFingerTapRecognizer() :
- QGestureRecognizer(),
- m_gestureTriggered(false)
-{
-}
-
-KTwoFingerTapRecognizer::~KTwoFingerTapRecognizer()
-{
-}
-
-QGesture* KTwoFingerTapRecognizer::create(QObject*)
-{
- return static_cast<QGesture*>(new KTwoFingerTap());
-}
-
-QGestureRecognizer::Result KTwoFingerTapRecognizer::recognize(QGesture* gesture, QObject* watched, QEvent* event)
-{
- if (qobject_cast<QGraphicsWidget*>(watched)) {
- return Ignore;
- }
-
- KTwoFingerTap* const kTwoFingerTap = static_cast<KTwoFingerTap*>(gesture);
- const QTouchEvent* touchEvent = static_cast<const QTouchEvent*>(event);
-
- switch (event->type()) {
- case QEvent::TouchBegin: {
- kTwoFingerTap->setHotSpot(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerTap->setPos(touchEvent->touchPoints().first().startPos());
- kTwoFingerTap->setScreenPos(touchEvent->touchPoints().first().startScreenPos());
- kTwoFingerTap->setScenePos(touchEvent->touchPoints().first().startScenePos());
- m_gestureTriggered = false;
- return MayBeGesture;
- }
-
- case QEvent::TouchUpdate: {
-
- if (touchEvent->touchPoints().size() > 2) {
- m_gestureTriggered = false;
- return CancelGesture;
- }
-
- if (touchEvent->touchPoints().size() == 2) {
- if ((touchEvent->touchPoints().first().startPos() - touchEvent->touchPoints().first().pos()).manhattanLength() >= QApplication::startDragDistance()) {
- m_gestureTriggered = false;
- return CancelGesture;
- }
- if ((touchEvent->touchPoints().at(1).startPos() - touchEvent->touchPoints().at(1).pos()).manhattanLength() >= QApplication::startDragDistance()) {
- m_gestureTriggered = false;
- return CancelGesture;
- }
- if (touchEvent->touchPointStates() & Qt::TouchPointPressed) {
- m_gestureTriggered = true;
- }
- if (touchEvent->touchPointStates() & Qt::TouchPointReleased && m_gestureTriggered) {
- m_gestureTriggered = false;
- return FinishGesture;
- }
- }
- break;
- }
-
- default:
- return Ignore;
- }
- return Ignore;
-}
-
-KTwoFingerTap::KTwoFingerTap(QObject* parent) :
- QGesture(parent),
- m_pos(QPointF(-1, -1)),
- m_screenPos(QPointF(-1, -1)),
- m_scenePos(QPointF(-1, -1))
-{
-}
-
-KTwoFingerTap::~KTwoFingerTap()
-{
-}
-
-QPointF KTwoFingerTap::pos() const
-{
- return m_pos;
-}
-
-void KTwoFingerTap::setPos(QPointF _pos)
-{
- m_pos = _pos;
-}
-
-QPointF KTwoFingerTap::screenPos() const
-{
- return m_screenPos;
-}
-
-void KTwoFingerTap::setScreenPos(QPointF _screenPos)
-{
- m_screenPos = _screenPos;
-}
-
-QPointF KTwoFingerTap::scenePos() const
-{
- return m_scenePos;
-}
-
-void KTwoFingerTap::setScenePos(QPointF _scenePos)
-{
- m_scenePos = _scenePos;
-}
+++ /dev/null
-/*
- * SPDX-FileCopyrightText: 2020 Steffen Hartleib <steffenhartleib@t-online.de>
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef KTWOFINGERTAP_H
-#define KTWOFINGERTAP_H
-
-#include <dolphin_export.h>
-// Qt
-#include <QGesture>
-#include <QGestureRecognizer>
-
-class DOLPHIN_EXPORT KTwoFingerTap : public QGesture
-{
- Q_OBJECT
- Q_PROPERTY(QPointF pos READ pos WRITE setPos)
- Q_PROPERTY(QPointF screenPos READ screenPos WRITE setScreenPos)
- Q_PROPERTY(QPointF scenePos READ scenePos WRITE setScenePos)
-public:
- explicit KTwoFingerTap(QObject* parent = nullptr);
- ~KTwoFingerTap() override;
- QPointF pos() const;
- void setPos(QPointF pos);
- QPointF screenPos() const;
- void setScreenPos(QPointF screenPos);
- QPointF scenePos() const;
- void setScenePos(QPointF scenePos);
-private:
- QPointF m_pos;
- QPointF m_screenPos;
- QPointF m_scenePos;
-};
-
-class DOLPHIN_EXPORT KTwoFingerTapRecognizer : public QGestureRecognizer
-{
-public:
- explicit KTwoFingerTapRecognizer();
- ~KTwoFingerTapRecognizer() override;
- QGesture* create(QObject*) override;
- Result recognize(QGesture*, QObject*, QEvent*) override;
-private:
- Q_DISABLE_COPY(KTwoFingerTapRecognizer)
- bool m_gestureTriggered;
-};
-
-#endif /* KTWOFINGERTAP_H */
Keywords[nl]=bestanden;bestandsbeheer;bladeren in bestanden;samba;netwerk-shares;verkenner;zoeksysteem;
Keywords[nn]=filer;filhandsaming;filutforsking;samba;nettverksressursar;Explorer;Finder;
Keywords[pl]=pliki;zarządzenie plikami;przeglądanie plików;samba;udziały sieciowe;Przeglądarka;Finder;
+Keywords[pt]=ficheiros;gestão de ficheiros;navegação de ficheiros;samba;partilhas de rede;Explorador;Pesquisa;
Keywords[pt_BR]=arquivo;gerenciamento de arquivos;navegação de arquivos;samba;compartilhamentos de rede;explorador;localizador;
Keywords[ro]=fișiere;gestiune fișiere;răsfoire fișiere;samba;partajări de rețea;unități de rețea;Explorer;Finder;
Keywords[ru]=files;file management;file browsing;samba;network shares;Explorer;Finder;файлы,управление файлами,просмотр файлов,сетевые папки
-Keywords[sk]=súbory;správa súborov;prehliadanie súborov;samba;sieťové akcie;Prieskumník;Vyhľadávač;
+Keywords[sk]=súbory;správa súborov;prehliadanie súborov;samba;zdieľanie v sieti;Prieskumník;Vyhľadávač;
Keywords[sl]=datoteke;upravljanje z datotekami;brskanje po datotekah;samba;mrežni diski;Raziskovalec;Iskalec;
Keywords[sv]=filer;filhantering;filbläddring;samba;delade nätverksresurser;Utforskare;Finder;
Keywords[tr]=dosyalar;dosya yönetimi;dosya göz at;samba;ağ paylaşımları;Explorer;Finder;
QString getServiceMenusDir()
{
const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
- return QDir(dataLocation).absoluteFilePath("kservices5/ServiceMenus");
+ return QDir(dataLocation).absoluteFilePath("kio/servicemenus");
}
#ifdef HAVE_PACKAGEKIT
errorText = i18n("Failed to copy .desktop file %1 to %2: %3", archive, dest, source.errorString());
return false;
}
+ QFile destFile(dest);
+ destFile.setPermissions(destFile.permissions() | QFile::ExeOwner);
} else {
if (binaryPackages->contains(QMimeDatabase().mimeTypeForFile(archive).name())) {
packageKit(PackageOperation::Install, archive);
#include <QWidget>
#include <KIO/EmptyTrashJob>
-#include <KIOWidgets/KDirLister>
+#include <KDirLister>
class Trash: public QObject
{
}
const KFileItem item = m_model->fileItem(index);
- Q_EMIT requestContextMenu(pos.toPoint(), item, url(), QList<QAction*>());
+ Q_EMIT requestContextMenu(pos.toPoint(), item, selectedItems(), url());
}
void DolphinView::slotViewContextMenuRequested(const QPointF& pos)
{
- Q_EMIT requestContextMenu(pos.toPoint(), KFileItem(), url(), QList<QAction*>());
+ Q_EMIT requestContextMenu(pos.toPoint(), KFileItem(), selectedItems(), url());
}
void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos)
/**
* Is emitted if a context menu is requested for the item \a item,
* which is part of \a url. If the item is null, the context menu
- * for the URL should be shown and the custom actions \a customActions
- * will be added.
+ * for the URL should be shown.
*/
void requestContextMenu(const QPoint& pos,
const KFileItem& item,
- const QUrl& url,
- const QList<QAction*>& customActions);
+ const KFileItemList &selectedItems,
+ const QUrl& url);
/**
* Is emitted if an information message with the content \a msg
#include "dolphinviewactionhandler.h"
#include "dolphindebug.h"
+#include "kitemviews/kfileitemlisttostring.h"
#include "kitemviews/kfileitemmodel.h"
#include "settings/viewpropertiesdialog.h"
#include "views/zoomlevelinfo.h"
void DolphinViewActionHandler::slotSelectionChanged(const KFileItemList& selection)
{
QString basicActionsMenuText;
- switch (selection.count()) {
- case 0:
+ if (selection.isEmpty()) {
basicActionsMenuText =
i18nc("@action:inmenu menu with actions like copy, paste, rename. The user's selection is empty when this text is shown.",
"Actions for Current View");
- break;
- case 1:
- basicActionsMenuText =
- i18nc("@action:inmenu menu with actions like copy, paste, rename. %1 is the name of the singular selected file/folder.",
- "Actions for \"%1\"", selection.first().name());
- break;
- case 2:
- basicActionsMenuText =
- i18nc("@action:inmenu menu with actions like copy, paste, rename. %1 and %2 are names of files/folders.",
- "Actions for \"%1\" and \"%2\"", selection.first().name(), selection.last().name());
- break;
- case 3:
- basicActionsMenuText =
- i18nc("@action:inmenu menu with actions like copy, paste, rename. %1, %2 and %3 are names of files/folders.",
- "Actions for \"%1\", \"%2\" and \"%3\"",
- selection.first().name(), selection.at(1).name(), selection.last().name());
- break;
- default:
- basicActionsMenuText = QString();
- break;
+ } else {
+ QFontMetrics fontMetrics = QMenu().fontMetrics();
+ // i18n: @action:inmenu menu with actions like copy, paste, rename.
+ // %1 is a textual representation of the currently selected files or folders. This can be the name of
+ // the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
+ // If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
+ // and a fallback will be used.
+ basicActionsMenuText = i18n("Actions for %1", fileItemListToString(selection, fontMetrics.averageCharWidth() * 40, fontMetrics, ItemsState::Selected));
}
- // At some point the added clarity from the text starts being less important than the menu width.
- if (basicActionsMenuText.isEmpty() || basicActionsMenuText.length() > 40) {
+ if (basicActionsMenuText == QStringLiteral("NULL")) {
const KFileItemListProperties properties(selection);
- if (properties.isFile()) {
- basicActionsMenuText =
- i18ncp("@action:inmenu menu with actions like copy, paste, rename. %1 is the amount of selected files/folders.",
- "Actions for One Selected File", "Actions for %1 Selected Files", selection.count());
- } else if (properties.isDirectory()) {
- basicActionsMenuText =
- i18ncp("@action:inmenu menu with actions like copy, paste, rename. %1 is the amount of selected files/folders.",
- "Actions for One Selected Folder", "Actions for %1 Selected Folders", selection.count());
- } else {
- basicActionsMenuText =
- i18ncp("@action:inmenu menu with actions like copy, paste, rename. %1 is the amount of selected files/folders.",
- "Actions for One Selected Item", "Actions for %1 Selected Items", selection.count());
- }
+ basicActionsMenuText =
+ i18ncp("@action:inmenu menu with actions like copy, paste, rename. %1 is the amount of selected files/folders.",
+ "Actions for One Selected Item", "Actions for %1 Selected Items", selection.count());
}
QAction *basicActionsMenu = m_actionCollection->action(QStringLiteral("basic_actions"));
m_showToolTipTimer(nullptr),
m_contentRetrievalTimer(nullptr),
m_transientParent(nullptr),
- m_fileMetaDataWidget(nullptr),
m_toolTipRequested(false),
m_metaDataRequested(false),
m_appliedWaitCursor(false),
ToolTipManager::~ToolTipManager()
{
+ if (!m_fileMetaDatWidgetOwnershipTransferred) {
+ delete m_fileMetaDataWidget;
+ }
}
void ToolTipManager::showToolTip(const KFileItem& item, const QRectF& itemRect, QWindow *transientParent)
{
- hideToolTip();
+ hideToolTip(HideBehavior::Instantly);
m_itemRect = itemRect.toRect();
// Only start the retrieving of the content, when the mouse has been over this
// item for 200 milliseconds. This prevents a lot of useless preview jobs and
// meta data retrieval, when passing rapidly over a lot of items.
- m_fileMetaDataWidget.reset(new DolphinFileMetaDataWidget());
- connect(m_fileMetaDataWidget.data(), &DolphinFileMetaDataWidget::metaDataRequestFinished,
- this, &ToolTipManager::slotMetaDataRequestFinished);
- connect(m_fileMetaDataWidget.data(), &DolphinFileMetaDataWidget::urlActivated,
- this, &ToolTipManager::urlActivated);
+ if (!m_fileMetaDataWidget) {
+ m_fileMetaDataWidget = new DolphinFileMetaDataWidget();
+ connect(m_fileMetaDataWidget, &DolphinFileMetaDataWidget::metaDataRequestFinished, this, &ToolTipManager::slotMetaDataRequestFinished);
+ connect(m_fileMetaDataWidget, &DolphinFileMetaDataWidget::urlActivated, this, &ToolTipManager::urlActivated);
+ }
m_contentRetrievalTimer->start();
m_showToolTipTimer->start();
if (!m_tooltipWidget) {
m_tooltipWidget.reset(new KToolTipWidget());
}
- m_tooltipWidget->showBelow(m_itemRect, m_fileMetaDataWidget.data(), m_transientParent);
+ m_tooltipWidget->showBelow(m_itemRect, m_fileMetaDataWidget, m_transientParent);
+ // At this point KToolTipWidget adopted our parent-less metadata widget.
+ m_fileMetaDatWidgetOwnershipTransferred = true;
+
m_toolTipRequested = false;
}
QWindow* m_transientParent;
QScopedPointer<KToolTipWidget> m_tooltipWidget;
- QScopedPointer<DolphinFileMetaDataWidget> m_fileMetaDataWidget;
+ DolphinFileMetaDataWidget *m_fileMetaDataWidget = nullptr;
+
+ /// Whether ownership of the metadata widget was transferred
+ /// over to the KToolTipWidget (i.e. we should not delete it
+ /// anymore)
+ bool m_fileMetaDatWidgetOwnershipTransferred = false;
bool m_toolTipRequested;
bool m_metaDataRequested;