diff --git a/src/kmoretools/kmoretoolsmenufactory.cpp b/src/kmoretools/kmoretoolsmenufactory.cpp index 23084006..b492fc69 100644 --- a/src/kmoretools/kmoretoolsmenufactory.cpp +++ b/src/kmoretools/kmoretoolsmenufactory.cpp @@ -1,314 +1,314 @@ /* Copyright 2015 by Gregor Mi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "kmoretoolsmenufactory.h" #include "kmoretools_p.h" #include "kmoretoolspresets_p.h" #include "knewstuff_debug.h" #include #include #include #include #include #include class KMoreToolsMenuFactoryPrivate { public: // Note that this object must live long enough in case the user opens // the "Configure..." dialog KMoreTools* kmt = nullptr; QMenu* menu = nullptr; QWidget* parentWidget = nullptr; }; class KMoreToolsLazyMenu : public QMenu { private Q_SLOTS: void onAboutToShow() { //qDebug() << "onAboutToShow"; clear(); m_aboutToShowFunc(this); } public: KMoreToolsLazyMenu(QWidget* parent = nullptr) : QMenu(parent) { connect(this, &QMenu::aboutToShow, this, &KMoreToolsLazyMenu::onAboutToShow); } void setAboutToShowAction(std::function aboutToShowFunc) { m_aboutToShowFunc = aboutToShowFunc; } private: std::function m_aboutToShowFunc; }; KMoreToolsMenuFactory::KMoreToolsMenuFactory(const QString& uniqueId) : d(new KMoreToolsMenuFactoryPrivate()) { d->kmt = new KMoreTools(uniqueId); } KMoreToolsMenuFactory::~KMoreToolsMenuFactory() { if (d->menu && !d->menu->parent()) { delete d->menu; } delete d->kmt; delete d; } // "file static" => no symbol will be exported static void addItemFromKmtService(KMoreToolsMenuBuilder* menuBuilder, QMenu* menu, KMoreToolsService* kmtService, const QUrl& url, bool isMoreSection ) { auto menuItem = menuBuilder->addMenuItem(kmtService, isMoreSection ? KMoreTools::MenuSection_More : KMoreTools::MenuSection_Main); if (kmtService->isInstalled()) { auto kService = kmtService->installedService(); if (!kService) { // if the corresponding desktop file is not installed // then the isInstalled was true because of the Exec line check // and we use the desktopfile provided by KMoreTools. // Otherwise *kService would crash. qCDebug(KNEWSTUFF) << "Desktop file not installed:" << kmtService->desktopEntryName() << "=> Use desktop file provided by KMoreTools"; kService = kmtService->kmtProvidedService(); } if (!url.isEmpty() && kmtService->maxUrlArgCount() > 0) { menu->connect(menuItem->action(), &QAction::triggered, menu, [kService, url](bool) { KRun::runApplication(*kService, { url }, nullptr); }); } else { menu->connect(menuItem->action(), &QAction::triggered, menu, [kService](bool) { KRun::runApplication(*kService, { }, nullptr); }); } } } // "file static" => no symbol will be exported static void addItemsFromKmtServiceList(KMoreToolsMenuBuilder* menuBuilder, QMenu* menu, const QList &kmtServiceList, const QUrl& url, bool isMoreSection, QString firstMoreSectionDesktopEntryName ) { for (auto kmtService : kmtServiceList) { // Check the pointer just in case a null pointer got in somewhere if (!kmtService) continue; if (kmtService->desktopEntryName() == firstMoreSectionDesktopEntryName) { // once we reach the potential first "more section desktop entry name" // all remaining services are added to the more section by default isMoreSection = true; } addItemFromKmtService(menuBuilder, menu, kmtService, url, isMoreSection); } } /** * "file static" => no symbol will be exported * @param isMoreSection: true => all items will be added into the more section * @param firstMoreSectionDesktopEntryName: only valid when @p isMoreSection is false: * see KMoreToolsPresets::registerServicesByGroupingNames */ static void addItemsForGroupingNameWithSpecialHandling(KMoreToolsMenuBuilder* menuBuilder, QMenu* menu, QList kmtServiceList, const QString& groupingName, const QUrl& url, bool isMoreSection, QString firstMoreSectionDesktopEntryName ) { // // special handlings // if (groupingName == QLatin1String("disk-usage") && !url.isEmpty()) { // // "disk-usage" plus a given URL. If no url is given there is no need // for special handling // auto filelightAppIter = std::find_if(kmtServiceList.begin(), kmtServiceList.end(), [](KMoreToolsService* s) { return s->desktopEntryName() == QLatin1String("org.kde.filelight"); }); if (filelightAppIter != kmtServiceList.end()) { auto filelightApp = *filelightAppIter; // because we later add all remaining items kmtServiceList.removeOne(filelightApp); if (url.isLocalFile()) { // 2015-01-12: Filelight can handle FTP connections // but KIO/kioexec cannot (bug or feature?), so we // don't offer it in this case const auto filelight1Item = menuBuilder->addMenuItem(filelightApp); if (filelightApp->isInstalled()) { const auto filelightService = filelightApp->installedService(); filelight1Item->action()->setText(filelightApp->formatString( - i18nc("@action:inmenu", "$GenericName - current folder"))); + i18nc("@action:inmenu %1=\"$GenericName\"", "%1 - current folder", QStringLiteral("$GenericName")))); menu->connect(filelight1Item->action(), &QAction::triggered, menu, [filelightService, url](bool) { KRun::runApplication(*filelightService, { url }, nullptr); }); const auto filelight2Item = menuBuilder->addMenuItem(filelightApp); filelight2Item->action()->setText(filelightApp->formatString( - i18nc("@action:inmenu", "$GenericName - current device"))); + i18nc("@action:inmenu %1=\"$GenericName\"", "%1 - current device", QStringLiteral("$GenericName")))); menu->connect(filelight2Item->action(), &QAction::triggered, menu, [filelightService, url](bool) { KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(url.toLocalFile()); KRun::runApplication(*filelightService, { QUrl::fromLocalFile(mountPoint->mountPoint()) }, nullptr); }); } } auto filelight3Item = menuBuilder->addMenuItem(filelightApp, KMoreTools::MenuSection_More); if (filelightApp->isInstalled()) { filelight3Item->action()->setText(filelightApp->formatString( - i18nc("@action:inmenu", "$GenericName - all devices"))); + i18nc("@action:inmenu %1=\"$GenericName\"", "%1 - all devices", QStringLiteral("$GenericName")))); const auto filelightService = filelightApp->installedService(); menu->connect(filelight3Item->action(), &QAction::triggered, menu, [filelightService](bool) { KRun::runApplication(*filelightService, { }, nullptr); }); } } else { qWarning() << "org.kde.filelight should be present in KMoreTools but it is not!"; } } else if (groupingName == QLatin1String("disk-partitions")) { // better because the Partition editors all have the same GenericName menuBuilder->setInitialItemTextTemplate(QStringLiteral("$GenericName ($Name)")); addItemsFromKmtServiceList(menuBuilder, menu, kmtServiceList, url, isMoreSection, firstMoreSectionDesktopEntryName); menuBuilder->setInitialItemTextTemplate(QStringLiteral("$GenericName")); // set back to default return; // skip processing remaining list (would result in duplicates) } else if (groupingName == QLatin1String("git-clients-and-actions")) { // Here we change the default item text and make sure that the url // argument is properly handled. // menuBuilder->setInitialItemTextTemplate(QStringLiteral("$Name")); // just use the application name for (auto kmtService : qAsConst(kmtServiceList)) { // Check the pointer just in case a null pointer got in somewhere if (!kmtService) continue; QUrl argUrl = url; if (url.isLocalFile()) { // this can only be done for local files, remote urls probably won't work for git clients anyway // by default we need an URL pointing to a directory // (this impl currently leads to wrong behaviour if the root dir of a git repo is chosen because it always goes one level up) argUrl = KmtUrlUtil::localFileAbsoluteDir(url); // needs local file if (kmtService->desktopEntryName() == _("git-cola-view-history.kmt-edition")) { // in this case we need the file because we would like to see its history argUrl = url; } } addItemFromKmtService(menuBuilder, menu, kmtService, argUrl, isMoreSection); } menuBuilder->setInitialItemTextTemplate(QStringLiteral("$GenericName")); // set back to default return; // skip processing remaining list (would result in duplicates) } // // default handling (or process remaining list) // menuBuilder->setInitialItemTextTemplate(QStringLiteral("$Name")); // just use the application name addItemsFromKmtServiceList(menuBuilder, menu, kmtServiceList, url, isMoreSection, firstMoreSectionDesktopEntryName); menuBuilder->setInitialItemTextTemplate(QStringLiteral("$GenericName")); // set back to default } QMenu* KMoreToolsMenuFactory::createMenuFromGroupingNames( const QStringList& groupingNames, const QUrl& url) { delete d->menu; auto menu = new KMoreToolsLazyMenu(d->parentWidget); menu->setAboutToShowAction([this, groupingNames, url](QMenu* m) { fillMenuFromGroupingNames(m, groupingNames, url); }); d->menu = menu; return d->menu; } void KMoreToolsMenuFactory::fillMenuFromGroupingNames(QMenu* menu, const QStringList& groupingNames, const QUrl& url) { const auto menuBuilder = d->kmt->menuBuilder(); menuBuilder->clear(); bool isMoreSection = false; for (const auto &groupingName : groupingNames) { if (groupingName == QLatin1String("more:")) { isMoreSection = true; continue; } QString firstMoreSectionDesktopEntryName; auto kmtServiceList = KMoreToolsPresetsPrivate::registerServicesByGroupingNames( &firstMoreSectionDesktopEntryName, d->kmt, { groupingName }); addItemsForGroupingNameWithSpecialHandling(menuBuilder, menu, kmtServiceList, groupingName, url, isMoreSection, firstMoreSectionDesktopEntryName); } menuBuilder->buildByAppendingToMenu(menu); } void KMoreToolsMenuFactory::setParentWidget(QWidget *widget) { d->parentWidget = widget; }