diff --git a/applets/taskmanager/plugin/backend.cpp b/applets/taskmanager/plugin/backend.cpp index 1f2eb27ed..5d15fb4a9 100644 --- a/applets/taskmanager/plugin/backend.cpp +++ b/applets/taskmanager/plugin/backend.cpp @@ -1,516 +1,517 @@ /*************************************************************************** * Copyright (C) 2012-2016 by Eike Hein * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "backend.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KAStats = KActivities::Stats; using namespace KAStats; using namespace KAStats::Terms; Backend::Backend(QObject* parent) : QObject(parent) , m_taskManagerItem(0) , m_toolTipItem(0) , m_panelWinId(0) + , m_groupDialog(0) , m_highlightWindows(false) , m_actionGroup(new QActionGroup(this)) { } Backend::~Backend() { } QQuickItem *Backend::taskManagerItem() const { return m_taskManagerItem; } void Backend::setTaskManagerItem(QQuickItem* item) { if (item != m_taskManagerItem) { m_taskManagerItem = item; emit taskManagerItemChanged(); } } QQuickItem *Backend::toolTipItem() const { return m_toolTipItem; } void Backend::setToolTipItem(QQuickItem *item) { if (item != m_toolTipItem) { m_toolTipItem = item; connect(item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(toolTipWindowChanged(QQuickWindow*))); emit toolTipItemChanged(); } } QQuickWindow *Backend::groupDialog() const { return m_groupDialog; } void Backend::setGroupDialog(QQuickWindow *dialog) { if (dialog != m_groupDialog) { m_groupDialog = dialog; emit groupDialogChanged(); } } bool Backend::highlightWindows() const { return m_highlightWindows; } void Backend::setHighlightWindows(bool highlight) { if (highlight != m_highlightWindows) { m_highlightWindows = highlight; updateWindowHighlight(); emit highlightWindowsChanged(); } } QVariantList Backend::jumpListActions(const QUrl &launcherUrl, QObject *parent) { QVariantList actions; if (!parent || !launcherUrl.isValid() || !launcherUrl.isLocalFile() || !KDesktopFile::isDesktopFile(launcherUrl.toLocalFile())) { return actions; } KDesktopFile desktopFile(launcherUrl.toLocalFile()); const QStringList &jumpListActions = desktopFile.readActions(); const QLatin1String kde("KDE"); foreach (const QString &actionName, jumpListActions) { const KConfigGroup &actionGroup = desktopFile.actionGroup(actionName); if (!actionGroup.isValid() || !actionGroup.exists()) { continue; } const QStringList ¬ShowIn = actionGroup.readXdgListEntry(QStringLiteral("NotShowIn")); if (notShowIn.contains(kde)) { continue; } const QStringList &onlyShowIn = actionGroup.readXdgListEntry(QStringLiteral("OnlyShowIn")); if (!onlyShowIn.isEmpty() && !onlyShowIn.contains(kde)) { continue; } const QString &name = actionGroup.readEntry(QStringLiteral("Name")); const QString &exec = actionGroup.readEntry(QStringLiteral("Exec")); if (name.isEmpty() || exec.isEmpty()) { continue; } QAction *action = new QAction(parent); action->setText(name); action->setIcon(QIcon::fromTheme(actionGroup.readEntry("Icon"))); action->setProperty("exec", exec); // so we can show the proper application name and icon when it launches action->setProperty("applicationName", desktopFile.readName()); action->setProperty("applicationIcon", desktopFile.readIcon()); connect(action, &QAction::triggered, this, &Backend::handleJumpListAction); actions << QVariant::fromValue(action); } return actions; } QVariantList Backend::placesActions(const QUrl &launcherUrl, bool showAllPlaces, QObject *parent) { QVariantList actions; if (!parent || !launcherUrl.isValid() || !launcherUrl.isLocalFile() || !KDesktopFile::isDesktopFile(launcherUrl.toLocalFile())) { return actions; } KDesktopFile desktopFile(launcherUrl.toLocalFile()); // Since we can't have dynamic jump list actions, at least add the user's "Places" for file managers. const QStringList &categories = desktopFile.desktopGroup().readXdgListEntry(QStringLiteral("Categories")); if (!categories.contains(QLatin1String("FileManager"))) { return actions; } QScopedPointer placesModel(new KFilePlacesModel()); for (int i = 0; i < placesModel->rowCount(); ++i) { QModelIndex idx = placesModel->index(i, 0); if (placesModel->data(idx, KFilePlacesModel::HiddenRole).toBool()) { continue; } const QString &title = placesModel->data(idx, Qt::DisplayRole).toString(); const QIcon &icon = placesModel->data(idx, Qt::DecorationRole).value(); const QUrl &url = placesModel->data(idx, KFilePlacesModel::UrlRole).toUrl(); QAction *action = new QAction(icon, title, parent); connect(action, &QAction::triggered, this, [this, action, url, launcherUrl] { KService::Ptr service = KService::serviceByDesktopPath(launcherUrl.toLocalFile()); if (!service) { return; } KRun::runService(*service, {url}, QApplication::activeWindow()); }); actions << QVariant::fromValue(action); } // There is nothing more frustrating than having a "More" entry that ends up showing just one or two // additional entries. Therefore we truncate to max. 5 entries only if there are more than 7 in total. if (!showAllPlaces && actions.count() > 7) { const int totalActionCount = actions.count(); while (actions.count() > 5) { actions.removeLast(); } QAction *action = new QAction(parent); action->setText(i18ncp("Show all user Places", "%1 more Place", "%1 more Places", totalActionCount - actions.count())); connect(action, &QAction::triggered, this, &Backend::showAllPlaces); actions << QVariant::fromValue(action); } return actions; } QVariantList Backend::recentDocumentActions(const QUrl &launcherUrl, QObject *parent) { QVariantList actions; if (!parent || !launcherUrl.isValid() || !launcherUrl.isLocalFile() || !KDesktopFile::isDesktopFile(launcherUrl.toLocalFile())) { return actions; } QString desktopName = launcherUrl.fileName(); QString storageId = desktopName; if (storageId.startsWith(QLatin1String("org.kde."))) { storageId = storageId.right(storageId.length() - 8); } if (storageId.endsWith(QLatin1String(".desktop"))) { storageId = storageId.left(storageId.length() - 8); } auto query = UsedResources | RecentlyUsedFirst | Agent(storageId) | Type::any() | Activity::current() | Url::file(); ResultSet results(query); ResultSet::const_iterator resultIt = results.begin(); int actionCount = 0; while (actionCount < 5 && resultIt != results.end()) { const QString resource = (*resultIt).resource(); const QUrl url(resource); if (!url.isValid()) { continue; } const KFileItem fileItem(url); if (!fileItem.isFile()) { continue; } QAction *action = new QAction(parent); action->setText(url.fileName()); action->setIcon(QIcon::fromTheme(fileItem.iconName(), QIcon::fromTheme("unknown"))); action->setProperty("agent", storageId); action->setProperty("entryPath", launcherUrl); action->setData(resource); connect(action, &QAction::triggered, this, &Backend::handleRecentDocumentAction); actions << QVariant::fromValue(action); ++resultIt; ++actionCount; } if (actionCount > 0) { QAction *action = new QAction(parent); action->setText(i18n("Forget Recent Documents")); action->setProperty("agent", storageId); connect(action, &QAction::triggered, this, &Backend::handleRecentDocumentAction); actions << QVariant::fromValue(action); } return actions; } void Backend::toolTipWindowChanged(QQuickWindow *window) { Q_UNUSED(window) updateWindowHighlight(); } void Backend::handleJumpListAction() const { const QAction *action = qobject_cast(sender()); if (!action) { return; } KRun::run(action->property("exec").toString(), {}, nullptr, action->property("applicationName").toString(), action->property("applicationIcon").toString()); } void Backend::handleRecentDocumentAction() const { const QAction *action = qobject_cast(sender()); if (!action) { return; } const QString agent = action->property("agent").toString(); if (agent.isEmpty()) { return; } const QString desktopPath = action->property("entryPath").toUrl().toLocalFile(); const QString resource = action->data().toString(); if (desktopPath.isEmpty() || resource.isEmpty()) { auto query = UsedResources | Agent(agent) | Type::any() | Activity::current() | Url::file(); KAStats::forgetResources(query); return; } KService::Ptr service = KService::serviceByDesktopPath(desktopPath); qDebug() << service; if (!service) { return; } KRun::runService(*service, QList() << QUrl(resource), QApplication::activeWindow()); } void Backend::setActionGroup(QAction *action) const { if (action) { action->setActionGroup(m_actionGroup); } } QRect Backend::globalRect(QQuickItem *item) const { if (!item || !item->window()) { return QRect(); } QRect iconRect(item->x(), item->y(), item->width(), item->height()); iconRect.moveTopLeft(item->parentItem()->mapToScene(iconRect.topLeft()).toPoint()); iconRect.moveTopLeft(item->window()->mapToGlobal(iconRect.topLeft())); return iconRect; } void Backend::ungrabMouse(QQuickItem *item) const { if (item && item->window() && item->window()->mouseGrabberItem()) { item->window()->mouseGrabberItem()->ungrabMouse(); } } bool Backend::canPresentWindows() const { return (KWindowSystem::compositingActive() && KWindowEffects::isEffectAvailable(KWindowEffects::PresentWindowsGroup)); } void Backend::presentWindows(const QVariant &_winIds) { if (!m_taskManagerItem || !m_taskManagerItem->window()) { return; } QList winIds; const QVariantList &_winIdsList = _winIds.toList(); foreach(const QVariant &_winId, _winIdsList) { bool ok = false; qlonglong winId = _winId.toLongLong(&ok); if (ok) { winIds.append(winId); } } if (!winIds.count()) { return; } if (m_windowsToHighlight.count()) { m_windowsToHighlight.clear(); updateWindowHighlight(); } KWindowEffects::presentWindows(m_taskManagerItem->window()->winId(), winIds); } bool Backend::isApplication(const QUrl &url) const { if (!url.isValid() || !url.isLocalFile()) { return false; } const QString &localPath = url.toLocalFile(); if (!KDesktopFile::isDesktopFile(localPath)) { return false; } KDesktopFile desktopFile(localPath); return desktopFile.hasApplicationType(); } QList Backend::jsonArrayToUrlList(const QJsonArray &array) const { QList urls; urls.reserve(array.count()); for (auto it = array.constBegin(), end = array.constEnd(); it != end; ++it) { urls << QUrl(it->toString()); } return urls; } void Backend::cancelHighlightWindows() { m_windowsToHighlight.clear(); updateWindowHighlight(); } void Backend::windowsHovered(const QVariant &_winIds, bool hovered) { m_windowsToHighlight.clear(); if (hovered) { const QVariantList &winIds = _winIds.toList(); foreach(const QVariant &_winId, winIds) { bool ok = false; qlonglong winId = _winId.toLongLong(&ok); if (ok) { m_windowsToHighlight.append(winId); } } } updateWindowHighlight(); } void Backend::updateWindowHighlight() { if (!m_highlightWindows) { if (m_panelWinId) { KWindowEffects::highlightWindows(m_panelWinId, QList()); m_panelWinId = 0; } return; } if (m_taskManagerItem && m_taskManagerItem->window()) { m_panelWinId = m_taskManagerItem->window()->winId(); } else { return; } QList windows = m_windowsToHighlight; if (windows.count() && m_toolTipItem && m_toolTipItem->window()) { windows.append(m_toolTipItem->window()->winId()); } if (windows.count() && m_groupDialog) { windows.append(m_groupDialog->winId()); } KWindowEffects::highlightWindows(m_panelWinId, windows); } diff --git a/org.kde.plasmashell.metainfo.xml b/org.kde.plasmashell.metainfo.xml index 87e453c08..34ecd20d2 100644 --- a/org.kde.plasmashell.metainfo.xml +++ b/org.kde.plasmashell.metainfo.xml @@ -1,105 +1,104 @@ org.kde.plasmashell CC0-1.0 GPL-2.0+ KDE Plasma Desktop سطح مكتب بلازما كدي Escritoriu Plasma de KDE Escriptori Plasma del KDE Escriptori Plasma del KDE Plocha KDE Plasma KDE Plasma skrivebordsmiljø KDE-Plasma-Arbeitsfläche Επιφάνεια εργασίας KDE Plasma KDE Plasma Desktop Escritorio KDE Plasma KDE¤ Plasma töölaud KDE Plasma -työpöytä KDE Plasma Desktop (Scriptorio KDE Plasma) Desktop KDE Plasma KDE Plasma 데스크톱 KDE Plasma Bureaublad KDE Plasma-skrivebord Pulpit Plazmy KDE Área de Trabalho Plasma do KDE Área de trabalho Plasma do KDE Рабочий стол KDE Plasma Plocha KDE Plasma KDE-jevo namizje Plasma КДЕ‑ова плазма површ KDE‑ova plasma površ КДЕ‑ова плазма површ KDE‑ova plasma površ KDE Plasma skrivbord Стільниця Плазми KDE xxKDE Plasma Desktopxx KDE Plasma 桌面 KDE Plasma 桌面 KDE's complete desktop experience. Simple by default, powerful when needed Experiència completa d'escriptori del KDE. Senzilla per omissió, potent quan cal Experiència completa d'escriptori del KDE. Senzilla per omissió, potent quan cal KDE's komplette desktop-oplevelse. Simpelt som standard, kraftfuldt når det behøves Η πλήρης εμπειρία επιφάνειας εργασίας του KDE. Προκαθορισμένα απλή, πανίσχυρη όταν χρειάζεται. KDE's complete desktop experience. Simple by default, powerful when needed Experiencia completa de escritorio de KDE. Sencillo por omisión, potente cuando es necesario. KDE:n täydellinen työpöytäkokemus. Oletuksena yksinkertainen, tarvittaessa tehokas L'esperienza completa del desktop da KDE. Semplice nelle scelte predefinite, potente quando c'è bisogno KDE 데스크톱 사용자 환경입니다. 첫 시작은 간단하게, 필요할 때에는 강력하게. De complete bureaubladervaring van KDE. Standaard eenvoudig, krachtig indien nodig Komplett KDE-oppleving. Enkel som standard og kraftig når nødvendig. Całkowite wrażenie pulpitu KDE. Prosty z natury, zaawansowany gdy potrzeba A experiência completa de trabalho do KDE. Simples por omissão, poderosa quando necessário A experiência da área de trabalho do KDE completa. Simples por padrão, potente quando necessário Kompletná pracovná plocha KDE. Predvolene jednoduchá, pri potrebe silná KDE-jeva popolna namizna izkušnja. Privzeto preprosta, a tudi zmogljiva, če je to zahtevano КДЕ‑ово потпуно искуство површи. Подразумевано једноставно, моћно кад затреба. KDE‑ovo potpuno iskustvo površi. Podrazumevano jednostavno, moćno kad zatreba. КДЕ‑ово потпуно искуство површи. Подразумевано једноставно, моћно кад затреба. KDE‑ovo potpuno iskustvo površi. Podrazumevano jednostavno, moćno kad zatreba. KDE:s fullständiga skrivbordsupplevelse. Normalt enkel, kraftfull vid behov Повноцінне стільничне середовище KDE. Типово просте, але потужне, якщо це потрібно. xxKDE's complete desktop experience. Simple by default, powerful when neededxx KDE 的完整桌面体验。默认简单,需要时强大。 KDE 的完整桌面體驗。預設簡潔,需要時足夠強大 https://www.kde.org/workspaces/plasmadesktop/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=plasmashell KDE plasmashell Plasma Desktop in Folder View with Clock and Notes Widgets سطح مكتب بلازما بمنظور المجلّد بودجتيّ السّاعة والملاحظات Escriptori Plasma en vista de carpeta amb els estris rellotge i notes Escriptori Plasma en vista de carpeta amb els estris rellotge i notes Plasma Desktop i mappevisning med ur- og note-widgets - Plasma-Arbeitsfläche als Ordneransicht mit den Miniprogrammen Uhr und Notizen Επιφάνεια εργασίας Plasma με προβολή φακέλου, ρολόι και συστατικά σημειώσεων Plasma Desktop in Folder View with Clock and Notes Widgets Escritorio Plasma en modo de vista de carpeta con reloj y notas Plasma töölaud kataloogivaates kella ja sedelite vidinaga Plasma-työpöytä kansionäkymällä kello- ja muistiinpanosovelmin Desktop Plasma in modalità vista delle cartelle con oggetti orologio e note 시계와 메모 위젯이 있는 폴더 보기 기반 Plasma 데스크톱 Plasma-bureaublad in mapweergave met klok en notitie-widgets Plasma-skrivebord i mappevising med klokke- og notatelement Pulpit Plazmy w widoku katalogu z zegarem i notatkami. Ecrã do Plasma na Área de Pastas com o Relógio e as Notas Área de trabalho Plasma na visualização por pastas com widgets de relógio e notas Plocha Plasma v zobrazení priečinka s hodinami a widgetmi poznámok Namizje Plasma s prikazom mape in z gradnikoma za uro ter sporočilca. Плазма површ у приказу фасцикле са виџетима сата и бележака Plasma površ u prikazu fascikle sa vidžetima sata i beležaka Плазма површ у приказу фасцикле са виџетима сата и бележака Plasma površ u prikazu fascikle sa vidžetima sata i beležaka Plasma skrivbord i katalogvy med de grafiska komponenterna Klocka och Anteckningar Стільниця Плазми на панелі перегляду тек із віджетами годинника і нотаток xxPlasma Desktop in Folder View with Clock and Notes Widgetsxx 有时钟和便笺部件文件夹视图的 Plasma 桌面 有著時鐘與便條小工具的 Plasma 桌面資料夾檢視 https://www.kde.org/workspaces/plasmadesktop/screenshots/general-desktop.png