diff --git a/applets/kicker/package/contents/ui/code/tools.js b/applets/kicker/package/contents/ui/code/tools.js index a7f6a74d4..1aa2a65eb 100644 --- a/applets/kicker/package/contents/ui/code/tools.js +++ b/applets/kicker/package/contents/ui/code/tools.js @@ -1,202 +1,202 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2013-2015 by Eike Hein * * Copyright (C) 2017 by Ivan Cukic * * * * 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 . * ***************************************************************************/ .pragma library function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) { // Accessing actionList can be a costly operation, so we don't // access it until we need the menu. var actions = createFavoriteActions(i18n, favoriteModel, favoriteId); if (actions) { if (actionList && actionList.length > 0) { var separator = { "type": "separator" }; actionList.push(separator); // actionList = actions.concat(actionList); // this crashes Qt O.o actionList.push.apply(actionList, actions); } else { actionList = actions; } } actionMenu.actionList = actionList; } function createFavoriteActions(i18n, favoriteModel, favoriteId) { if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) { return null; } if (favoriteModel.activities === undefined || favoriteModel.activities.runningActivities.length <= 1) { var action = {}; if (favoriteModel.isFavorite(favoriteId)) { action.text = i18n("Remove from Favorites"); action.icon = "bookmark-remove"; action.actionId = "_kicker_favorite_remove"; } else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) { action.text = i18n("Add to Favorites"); action.icon = "bookmark-new"; action.actionId = "_kicker_favorite_add"; } else { return null; } action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId }; return [action]; } else { var actions = []; var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId); var activities = favoriteModel.activities.runningActivities; // Adding the item to link/unlink to all activities var linkedToAllActivities = !(linkedActivities.indexOf(":global") === -1); actions.push({ text : i18n("On All Activities"), checkable : true, actionId : linkedToAllActivities ? "_kicker_favorite_remove_from_activity" : "_kicker_favorite_set_to_activity", checked : linkedToAllActivities, actionArgument : { favoriteModel: favoriteModel, favoriteId: favoriteId, favoriteActivity: "" } }); // Adding items for each activity separately var addActivityItem = function(activityId, activityName) { var linkedToThisActivity = !(linkedActivities.indexOf(activityId) === -1); actions.push({ text : activityName, checkable : true, checked : linkedToThisActivity && !linkedToAllActivities, actionId : // If we are on all activities, and the user clicks just one // specific activity, unlink from everything else linkedToAllActivities ? "_kicker_favorite_set_to_activity" : // If we are linked to the current activity, just unlink from // that single one linkedToThisActivity ? "_kicker_favorite_remove_from_activity" : // Otherwise, link to this activity, but do not unlink from // other ones "_kicker_favorite_add_to_activity", actionArgument : { favoriteModel : favoriteModel, favoriteId : favoriteId, favoriteActivity : activityId } }); }; // Adding the item to link/unlink to the current activity - addActivityItem(favoriteModel.activities.currentActivity, i18n("On The Current Activity")); + addActivityItem(favoriteModel.activities.currentActivity, i18n("On the Current Activity")); actions.push({ type: "separator", actionId: "_kicker_favorite_separator" }); // Adding the items for each activity activities.forEach(function(activityId) { addActivityItem(activityId, favoriteModel.activityNameForId(activityId)); }); return [{ - text : i18n("Show In Favorites"), + text : i18n("Show in Favorites"), icon : "favorite", subActions : actions }]; } } function triggerAction(model, index, actionId, actionArgument) { function startsWith(txt, needle) { return txt.substr(0, needle.length) === needle; } if (startsWith(actionId, "_kicker_favorite_")) { handleFavoriteAction(actionId, actionArgument); return; } var closeRequested = model.trigger(index, actionId, actionArgument); if (closeRequested) { return true; } return false; } function handleFavoriteAction(actionId, actionArgument) { var favoriteId = actionArgument.favoriteId; var favoriteModel = actionArgument.favoriteModel; console.log(actionId); if (favoriteModel === null || favoriteId == null) { return null; } if (actionId == "_kicker_favorite_remove") { console.log("Removing from all activities"); favoriteModel.removeFavorite(favoriteId); } else if (actionId == "_kicker_favorite_add") { console.log("Adding to global activity"); favoriteModel.addFavorite(favoriteId); } else if (actionId == "_kicker_favorite_remove_from_activity") { console.log("Removing from a specific activity"); favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity); } else if (actionId == "_kicker_favorite_add_to_activity") { console.log("Adding to another activity"); favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity); } else if (actionId == "_kicker_favorite_set_to_activity") { console.log("Removing the item from the favourites, and re-adding it just to be on a specific activity"); favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity); } } diff --git a/applets/kicker/plugin/actionlist.cpp b/applets/kicker/plugin/actionlist.cpp index 1f9e4a3be..f6ccccca4 100644 --- a/applets/kicker/plugin/actionlist.cpp +++ b/applets/kicker/plugin/actionlist.cpp @@ -1,414 +1,420 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014 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 "actionlist.h" #include "menuentryeditor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "containmentinterface.h" #ifdef HAVE_APPSTREAMQT #include #endif namespace KAStats = KActivities::Stats; using namespace KAStats; using namespace KAStats::Terms; namespace Kicker { QVariantMap createActionItem(const QString &label, const QString &actionId, const QVariant &argument) { QVariantMap map; map[QStringLiteral("text")] = label; map[QStringLiteral("actionId")] = actionId; if (argument.isValid()) { map[QStringLiteral("actionArgument")] = argument; } return map; } QVariantMap createTitleActionItem(const QString &label) { QVariantMap map; map[QStringLiteral("text")] = label; map[QStringLiteral("type")] = QStringLiteral("title"); return map; } QVariantMap createSeparatorActionItem() { QVariantMap map; map[QStringLiteral("type")] = QStringLiteral("separator"); return map; } QVariantList createActionListForFileItem(const KFileItem &fileItem) { QVariantList list; KService::List services = KMimeTypeTrader::self()->query(fileItem.mimetype(), QStringLiteral("Application")); if (!services.isEmpty()) { list << createTitleActionItem(i18n("Open with:")); foreach (const KService::Ptr service, services) { const QString text = service->name().replace(QLatin1Char('&'), QStringLiteral("&&")); QVariantMap item = createActionItem(text, QStringLiteral("_kicker_fileItem_openWith"), service->entryPath()); item[QStringLiteral("icon")] = service->icon(); list << item; } list << createSeparatorActionItem(); } QVariantMap propertiesItem = createActionItem(i18n("Properties"), QStringLiteral("_kicker_fileItem_properties")); propertiesItem[QStringLiteral("icon")] = QStringLiteral("document-properties"); list << propertiesItem; return list; } bool handleFileItemAction(const KFileItem &fileItem, const QString &actionId, const QVariant &argument, bool *close) { if (actionId == QLatin1String("_kicker_fileItem_properties")) { KPropertiesDialog *dlg = new KPropertiesDialog(fileItem, QApplication::activeWindow()); dlg->setAttribute(Qt::WA_DeleteOnClose); dlg->show(); *close = false; return true; } if (actionId == QLatin1String("_kicker_fileItem_openWith")) { const QString path = argument.toString(); const KService::Ptr service = KService::serviceByDesktopPath(path); if (!service) { return false; } KRun::runService(*service, QList() << fileItem.url(), QApplication::activeWindow()); *close = true; return true; } return false; } QVariantList createAddLauncherActionList(QObject *appletInterface, const KService::Ptr &service) { QVariantList actionList; if (!service) { return actionList; } if (ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::Desktop)) { - actionList << Kicker::createActionItem(i18n("Add to Desktop"), QStringLiteral("addToDesktop")); + QVariantMap addToDesktopAction = Kicker::createActionItem(i18n("Add to Desktop"), QStringLiteral("addToDesktop")); + addToDesktopAction[QStringLiteral("icon")] = QStringLiteral("list-add"); + actionList << addToDesktopAction; } if (ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::Panel)) { - actionList << Kicker::createActionItem(i18n("Add to Panel (Widget)"), QStringLiteral("addToPanel")); + QVariantMap addToPanelAction = Kicker::createActionItem(i18n("Add to Panel (Widget)"), QStringLiteral("addToPanel")); + addToPanelAction[QStringLiteral("icon")] = QStringLiteral("list-add"); + actionList << addToPanelAction; } if (service && ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::TaskManager, Kicker::resolvedServiceEntryPath(service))) { - actionList << Kicker::createActionItem(i18n("Pin to Task Manager"), QStringLiteral("addToTaskManager")); + QVariantMap addToTaskManagerAction = Kicker::createActionItem(i18n("Pin to Task Manager"), QStringLiteral("addToTaskManager")); + addToTaskManagerAction[QStringLiteral("icon")] = QStringLiteral("pin"); + actionList << addToTaskManagerAction; } return actionList; } bool handleAddLauncherAction(const QString &actionId, QObject *appletInterface, const KService::Ptr &service) { if (!service) { return false; } if (actionId == QLatin1String("addToDesktop")) { if (ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::Desktop)) { ContainmentInterface::addLauncher(appletInterface, ContainmentInterface::Desktop, Kicker::resolvedServiceEntryPath(service)); } return true; } else if (actionId == QLatin1String("addToPanel")) { if (ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::Panel)) { ContainmentInterface::addLauncher(appletInterface, ContainmentInterface::Panel, Kicker::resolvedServiceEntryPath(service)); } return true; } else if (actionId == QLatin1String("addToTaskManager")) { if (ContainmentInterface::mayAddLauncher(appletInterface, ContainmentInterface::TaskManager, Kicker::resolvedServiceEntryPath(service))) { ContainmentInterface::addLauncher(appletInterface, ContainmentInterface::TaskManager, Kicker::resolvedServiceEntryPath(service)); } return true; } return false; } QString storageIdFromService(KService::Ptr service) { QString storageId = service->storageId(); if (storageId.endsWith(QLatin1String(".desktop"))) { storageId = storageId.left(storageId.length() - 8); } return storageId; } QVariantList jumpListActions(KService::Ptr service) { QVariantList list; if (!service) { return list; } const auto &actions = service->actions(); foreach (const KServiceAction &action, actions) { if (action.text().isEmpty() || action.exec().isEmpty()) { continue; } QVariantMap item = createActionItem(action.text(), QStringLiteral("_kicker_jumpListAction"), action.exec()); item[QStringLiteral("icon")] = action.icon(); list << item; } return list; } QVariantList recentDocumentActions(KService::Ptr service) { QVariantList list; if (!service) { return list; } const QString storageId = storageIdFromService(service); if (storageId.isEmpty()) { return list; } auto query = UsedResources | RecentlyUsedFirst | Agent(storageId) | Type::any() | Activity::current() | Url::file(); ResultSet results(query); ResultSet::const_iterator resultIt; resultIt = results.begin(); while (list.count() < 6 && resultIt != results.end()) { const QString resource = (*resultIt).resource(); ++resultIt; const QUrl url(resource); if (!url.isValid()) { continue; } const KFileItem fileItem(url); if (!fileItem.isFile()) { continue; } if (list.isEmpty()) { list << createTitleActionItem(i18n("Recent Documents")); } QVariantMap item = createActionItem(url.fileName(), QStringLiteral("_kicker_recentDocument"), resource); item[QStringLiteral("icon")] = fileItem.iconName(); list << item; } if (!list.isEmpty()) { QVariantMap forgetAction = createActionItem(i18n("Forget Recent Documents"), QStringLiteral("_kicker_forgetRecentDocuments")); forgetAction[QStringLiteral("icon")] = QStringLiteral("edit-clear-history"); list << forgetAction; } return list; } bool handleRecentDocumentAction(KService::Ptr service, const QString &actionId, const QVariant &_argument) { if (!service) { return false; } if (actionId == QLatin1String("_kicker_forgetRecentDocuments")) { const QString storageId = storageIdFromService(service); if (storageId.isEmpty()) { return false; } auto query = UsedResources | Agent(storageId) | Type::any() | Activity::current() | Url::file(); KAStats::forgetResources(query); return false; } QString argument = _argument.toString(); if (argument.isEmpty()) { return false; } return (KRun::runService(*service, QList() << QUrl(argument), QApplication::activeWindow()) != 0); } Q_GLOBAL_STATIC(MenuEntryEditor, menuEntryEditor) bool canEditApplication(const KService::Ptr &service) { return (service->isApplication() && menuEntryEditor->canEdit(service->entryPath())); } void editApplication(const QString &entryPath, const QString &menuId) { menuEntryEditor->edit(entryPath, menuId); } QVariantList editApplicationAction(const KService::Ptr &service) { QVariantList actionList; if (canEditApplication(service)) { QVariantMap editAction = Kicker::createActionItem(i18n("Edit Application..."), QStringLiteral("editApplication")); editAction[QStringLiteral("icon")] = QStringLiteral("kmenuedit"); // TODO: Using the KMenuEdit icon might be misleading. actionList << editAction; } return actionList; } bool handleEditApplicationAction(const QString &actionId, const KService::Ptr &service) { if (service && actionId ==QLatin1String("editApplication") && canEditApplication(service)) { Kicker::editApplication(service->entryPath(), service->menuId()); return true; } return false; } #ifdef HAVE_APPSTREAMQT Q_GLOBAL_STATIC(AppStream::Pool, appstreamPool) #endif QVariantList appstreamActions(const KService::Ptr &service) { QVariantList ret; #ifdef HAVE_APPSTREAMQT const KService::Ptr appStreamHandler = KMimeTypeTrader::self()->preferredService(QStringLiteral("x-scheme-handler/appstream")); // Don't show action if we can't find any app to handle appstream:// URLs. if (!appStreamHandler) { if (!KProtocolInfo::isHelperProtocol(QStringLiteral("appstream")) || KProtocolInfo::exec(QStringLiteral("appstream")).isEmpty()) { return ret; } } if (!appstreamPool.exists()) { appstreamPool->load(); } const auto components = appstreamPool->componentsById(service->desktopEntryName()+QLatin1String(".desktop")); for(const auto &component: components) { const QString componentId = component.id(); QVariantMap appstreamAction = Kicker::createActionItem(i18nc("@action opens a software center with the application", "Uninstall or Manage Add-Ons..."), "manageApplication", QVariant(QLatin1String("appstream://") + componentId)); appstreamAction[QStringLiteral("icon")] = appStreamHandler->icon(); ret << appstreamAction; } #else Q_UNUSED(service) #endif return ret; } bool handleAppstreamActions(const QString &actionId, const QVariant &argument) { if (actionId == QLatin1String("manageApplication")) { return QDesktopServices::openUrl(QUrl(argument.toString())); } return false; } QString resolvedServiceEntryPath(const KService::Ptr &service) { QString path = service->entryPath(); if (!QDir::isAbsolutePath(path)) { path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kservices5/") + path); } return path; } } diff --git a/applets/kicker/plugin/appsmodel.cpp b/applets/kicker/plugin/appsmodel.cpp index fa1ea51a0..b66641a67 100644 --- a/applets/kicker/plugin/appsmodel.cpp +++ b/applets/kicker/plugin/appsmodel.cpp @@ -1,744 +1,748 @@ /*************************************************************************** * Copyright (C) 2012 Aurélien Gâteau * * Copyright (C) 2013-2015 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 "appsmodel.h" #include "actionlist.h" #include "rootmodel.h" #include #include #include #include #include #include AppsModel::AppsModel(const QString &entryPath, bool paginate, int pageSize, bool flat, bool sorted, bool separators, QObject *parent) : AbstractModel(parent) , m_complete(false) , m_paginate(paginate) , m_pageSize(pageSize) , m_deleteEntriesOnDestruction(true) , m_separatorCount(0) , m_showSeparators(separators) , m_showTopLevelItems(false) , m_appletInterface(nullptr) , m_autoPopulate(true) , m_description(i18n("Applications")) , m_entryPath(entryPath) , m_staticEntryList(false) , m_changeTimer(nullptr) , m_flat(flat) , m_sorted(sorted) , m_appNameFormat(AppEntry::NameOnly) { if (!m_entryPath.isEmpty()) { componentComplete(); } } AppsModel::AppsModel(const QList entryList, bool deleteEntriesOnDestruction, QObject *parent) : AbstractModel(parent) , m_complete(false) , m_paginate(false) , m_pageSize(24) , m_deleteEntriesOnDestruction(deleteEntriesOnDestruction) , m_separatorCount(0) , m_showSeparators(false) , m_showTopLevelItems(false) , m_appletInterface(nullptr) , m_autoPopulate(true) , m_description(i18n("Applications")) , m_entryPath(QString()) , m_staticEntryList(true) , m_changeTimer(nullptr) , m_flat(true) , m_sorted(true) , m_appNameFormat(AppEntry::NameOnly) { foreach(AbstractEntry *suggestedEntry, entryList) { bool found = false; foreach (const AbstractEntry *entry, m_entryList) { if (entry->type() == AbstractEntry::RunnableType && static_cast(entry)->service()->storageId() == static_cast(suggestedEntry)->service()->storageId()) { found = true; break; } } if (!found) { m_entryList << suggestedEntry; } } sortEntries(); } AppsModel::~AppsModel() { if (m_deleteEntriesOnDestruction) { qDeleteAll(m_entryList); } } bool AppsModel::autoPopulate() const { return m_autoPopulate; } void AppsModel::setAutoPopulate(bool populate) { if (m_autoPopulate != populate) { m_autoPopulate = populate; emit autoPopulateChanged(); } } QString AppsModel::description() const { return m_description; } void AppsModel::setDescription(const QString &text) { if (m_description != text) { m_description = text; emit descriptionChanged(); } } QVariant AppsModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_entryList.count()) { return QVariant(); } const AbstractEntry *entry = m_entryList.at(index.row()); if (role == Qt::DisplayRole) { return entry->name(); } else if (role == Qt::DecorationRole) { return entry->icon(); } else if (role == Kicker::DescriptionRole) { return entry->description(); } else if (role == Kicker::FavoriteIdRole && entry->type() == AbstractEntry::RunnableType) { return entry->id(); } else if (role == Kicker::UrlRole && entry->type() == AbstractEntry::RunnableType) { return entry->url(); } else if (role == Kicker::IsParentRole) { return (entry->type() == AbstractEntry::GroupType); } else if (role == Kicker::IsSeparatorRole) { return (entry->type() == AbstractEntry::SeparatorType); } else if (role == Kicker::HasChildrenRole) { return entry->hasChildren(); } else if (role == Kicker::HasActionListRole) { const AppsModel *appsModel = qobject_cast(entry->childModel()); return entry->hasActions() || (appsModel && !appsModel->hiddenEntries().isEmpty()); } else if (role == Kicker::ActionListRole) { QVariantList actionList = entry->actions(); if (!m_hiddenEntries.isEmpty()) { actionList << Kicker::createSeparatorActionItem(); - actionList << Kicker::createActionItem(i18n("Unhide Applications in this Submenu"), QStringLiteral("unhideSiblingApplications")); + QVariantMap unhideSiblingApplicationsAction = Kicker::createActionItem(i18n("Unhide Applications in this Submenu"), QStringLiteral("unhideSiblingApplications")); + unhideSiblingApplicationsAction[QStringLiteral("icon")] = QStringLiteral("view-visible"); + actionList << unhideSiblingApplicationsAction; } const AppsModel *appsModel = qobject_cast(entry->childModel()); if (appsModel && !appsModel->hiddenEntries().isEmpty()) { - actionList << Kicker::createActionItem(i18n("Unhide Applications in '%1'", entry->name()), QStringLiteral("unhideChildApplications")); + QVariantMap unhideChildApplicationsAction = Kicker::createActionItem(i18n("Unhide Applications in '%1'", entry->name()), QStringLiteral("unhideChildApplications")); + unhideChildApplicationsAction[QStringLiteral("icon")] = QStringLiteral("view-visible"); + actionList << unhideChildApplicationsAction; } return actionList; } return QVariant(); } QModelIndex AppsModel::index(int row, int column, const QModelIndex &parent) const { return hasIndex(row, column, parent) ? createIndex(row, column, m_entryList.at(row)) : QModelIndex(); } int AppsModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_entryList.count(); } bool AppsModel::trigger(int row, const QString &actionId, const QVariant &argument) { if (row < 0 || row >= m_entryList.count()) { return false; } AbstractEntry *entry = m_entryList.at(row); if (actionId == QLatin1String("hideApplication") && entry->type() == AbstractEntry::RunnableType) { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = nullptr; if (appletInterface) { appletConfig = qobject_cast(appletInterface->property("configuration").value()); } if (appletConfig && appletConfig->contains(QLatin1String("hiddenApplications"))) { QStringList hiddenApps = appletConfig->value(QLatin1String("hiddenApplications")).toStringList(); KService::Ptr service = static_cast(entry)->service(); if (!hiddenApps.contains(service->menuId())) { hiddenApps << service->menuId(); appletConfig->insert(QLatin1String("hiddenApplications"), hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("hiddenApplications")), Q_ARG(QVariant, hiddenApps)); refresh(); emit hiddenEntriesChanged(); } } return false; } else if (actionId == QLatin1String("unhideSiblingApplications")) { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = nullptr; if (appletInterface) { appletConfig = qobject_cast(appletInterface->property("configuration").value()); } if (appletConfig && appletConfig->contains(QLatin1String("hiddenApplications"))) { QStringList hiddenApps = appletConfig->value(QLatin1String("hiddenApplications")).toStringList(); foreach(const QString& app, m_hiddenEntries) { hiddenApps.removeOne(app); } appletConfig->insert(QStringLiteral("hiddenApplications"), hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("hiddenApplications")), Q_ARG(QVariant, hiddenApps)); m_hiddenEntries.clear(); refresh(); emit hiddenEntriesChanged(); } return false; } else if (actionId == QLatin1String("unhideChildApplications")) { QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = nullptr; if (appletInterface) { appletConfig = qobject_cast(appletInterface->property("configuration").value()); } if (entry->type() == AbstractEntry::GroupType && appletConfig && appletConfig->contains(QLatin1String("hiddenApplications"))) { const AppsModel *appsModel = qobject_cast(entry->childModel()); if (!appsModel) { return false; } QStringList hiddenApps = appletConfig->value(QLatin1String("hiddenApplications")).toStringList(); foreach(const QString& app, appsModel->hiddenEntries()) { hiddenApps.removeOne(app); } appletConfig->insert(QStringLiteral("hiddenApplications"), hiddenApps); QMetaObject::invokeMethod(appletConfig, "valueChanged", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("hiddenApplications")), Q_ARG(QVariant, hiddenApps)); refresh(); emit hiddenEntriesChanged(); } return false; } return entry->run(actionId, argument); } AbstractModel *AppsModel::modelForRow(int row) { if (row < 0 || row >= m_entryList.count()) { return nullptr; } return m_entryList.at(row)->childModel(); } int AppsModel::rowForModel(AbstractModel *model) { for (int i = 0; i < m_entryList.count(); ++i) { if (m_entryList.at(i)->childModel() == model) { return i; } } return -1; } int AppsModel::separatorCount() const { return m_separatorCount; } bool AppsModel::paginate() const { return m_paginate; } void AppsModel::setPaginate(bool paginate) { if (m_paginate != paginate) { m_paginate = paginate; refresh(); emit paginateChanged(); } } int AppsModel::pageSize() const { return m_pageSize; } void AppsModel::setPageSize(int size) { if (m_pageSize != size) { m_pageSize = size; refresh(); emit pageSizeChanged(); } } bool AppsModel::flat() const { return m_flat; } void AppsModel::setFlat(bool flat) { if (m_flat != flat) { m_flat = flat; refresh(); emit flatChanged(); } } bool AppsModel::sorted() const { return m_sorted; } void AppsModel::setSorted(bool sorted) { if (m_sorted != sorted) { m_sorted = sorted; refresh(); emit sortedChanged(); } } bool AppsModel::showSeparators() const { return m_showSeparators; } void AppsModel::setShowSeparators(bool showSeparators) { if (m_showSeparators != showSeparators) { m_showSeparators = showSeparators; refresh(); emit showSeparatorsChanged(); } } bool AppsModel::showTopLevelItems() const { return m_showTopLevelItems; } void AppsModel::setShowTopLevelItems(bool showTopLevelItems) { if (m_showTopLevelItems != showTopLevelItems) { m_showTopLevelItems = showTopLevelItems; refresh(); emit showTopLevelItemsChanged(); } } int AppsModel::appNameFormat() const { return m_appNameFormat; } void AppsModel::setAppNameFormat(int format) { if (m_appNameFormat != (AppEntry::NameFormat)format) { m_appNameFormat = (AppEntry::NameFormat)format; refresh(); emit appNameFormatChanged(); } } QObject* AppsModel::appletInterface() const { return m_appletInterface; } void AppsModel::setAppletInterface(QObject* appletInterface) { if (m_appletInterface != appletInterface) { m_appletInterface = appletInterface; refresh(); emit appletInterfaceChanged(); } } QStringList AppsModel::hiddenEntries() const { return m_hiddenEntries; } void AppsModel::refresh() { if (!m_complete) { return; } if (m_staticEntryList) { return; } if (rootModel() == this && !m_appletInterface) { return; } beginResetModel(); refreshInternal(); endResetModel(); if (favoritesModel()) { favoritesModel()->refresh(); } emit countChanged(); emit separatorCountChanged(); } void AppsModel::refreshInternal() { if (m_staticEntryList) { return; } if (m_entryList.count()) { qDeleteAll(m_entryList); m_entryList.clear(); emit cleared(); } m_hiddenEntries.clear(); m_separatorCount = 0; if (m_entryPath.isEmpty()) { KServiceGroup::Ptr group = KServiceGroup::root(); if (!group) { return; } bool sortByGenericName = (appNameFormat() == AppEntry::GenericNameOnly || appNameFormat() == AppEntry::GenericNameAndName); KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, true /* allowSeparators */, sortByGenericName /* sortByGenericName */); for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KServiceGroup)) { KServiceGroup::Ptr subGroup(static_cast(p.data())); if (!subGroup->noDisplay() && subGroup->childCount() > 0) { AppGroupEntry *groupEntry = new AppGroupEntry(this, subGroup, m_paginate, m_pageSize, m_flat, m_sorted, m_showSeparators, m_appNameFormat); m_entryList << groupEntry; } } else if (p->isType(KST_KService) && m_showTopLevelItems) { const KService::Ptr service(static_cast(p.data())); if (service->noDisplay()) { continue; } bool found = false; foreach (const AbstractEntry *entry, m_entryList) { if (entry->type() == AbstractEntry::RunnableType && static_cast(entry)->service()->storageId() == service->storageId()) { found = true; } } if (!found) { m_entryList << new AppEntry(this, service, m_appNameFormat); } } else if (p->isType(KST_KServiceSeparator) && m_showSeparators && m_showTopLevelItems) { if (!m_entryList.count()) { continue; } if (m_entryList.last()->type() == AbstractEntry::SeparatorType) { continue; } m_entryList << new SeparatorEntry(this); ++m_separatorCount; } } if (m_entryList.count()) { while (m_entryList.last()->type() == AbstractEntry::SeparatorType) { m_entryList.removeLast(); --m_separatorCount; } } if (m_sorted) { sortEntries(); } m_changeTimer = new QTimer(this); m_changeTimer->setSingleShot(true); m_changeTimer->setInterval(100); connect(m_changeTimer, SIGNAL(timeout()), this, SLOT(refresh())); connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), SLOT(checkSycocaChanges(QStringList))); } else { KServiceGroup::Ptr group = KServiceGroup::group(m_entryPath); processServiceGroup(group); if (m_entryList.count()) { while (m_entryList.last()->type() == AbstractEntry::SeparatorType) { m_entryList.removeLast(); --m_separatorCount; } } if (m_sorted) { sortEntries(); } if (m_paginate) { QList groups; int at = 0; QList page; foreach(AbstractEntry *app, m_entryList) { page.append(app); if (at == (m_pageSize - 1)) { at = 0; AppsModel *model = new AppsModel(page, true, this); groups.append(new GroupEntry(this, QString(), QString(), model)); page.clear(); } else { ++at; } } if (page.count()) { AppsModel *model = new AppsModel(page, true, this); groups.append(new GroupEntry(this, QString(), QString(), model)); } m_entryList = groups; } } } void AppsModel::processServiceGroup(KServiceGroup::Ptr group) { if (!group || !group->isValid()) { return; } bool hasSubGroups = false; foreach(KServiceGroup::Ptr subGroup, group->groupEntries(KServiceGroup::ExcludeNoDisplay)) { if (subGroup->childCount() > 0) { hasSubGroups = true; break; } } bool sortByGenericName = (appNameFormat() == AppEntry::GenericNameOnly || appNameFormat() == AppEntry::GenericNameAndName); KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, (!m_flat || (m_flat && !hasSubGroups)) /* allowSeparators */, sortByGenericName /* sortByGenericName */); QStringList hiddenApps; QObject *appletInterface = rootModel()->property("appletInterface").value(); QQmlPropertyMap *appletConfig = nullptr; if (appletInterface) { appletConfig = qobject_cast(appletInterface->property("configuration").value()); } if (appletConfig && appletConfig->contains(QLatin1String("hiddenApplications"))) { hiddenApps = appletConfig->value(QLatin1String("hiddenApplications")).toStringList(); } for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KService)) { const KService::Ptr service(static_cast(p.data())); if (service->noDisplay()) { continue; } if (hiddenApps.contains(service->menuId())) { m_hiddenEntries << service->menuId(); continue; } bool found = false; foreach (const AbstractEntry *entry, m_entryList) { if (entry->type() == AbstractEntry::RunnableType && static_cast(entry)->service()->storageId() == service->storageId()) { found = true; break; } } if (!found) { m_entryList << new AppEntry(this, service, m_appNameFormat); } } else if (p->isType(KST_KServiceSeparator) && m_showSeparators) { if (!m_entryList.count()) { continue; } if (m_entryList.last()->type() == AbstractEntry::SeparatorType) { continue; } m_entryList << new SeparatorEntry(this); ++m_separatorCount; } else if (p->isType(KST_KServiceGroup)) { const KServiceGroup::Ptr subGroup(static_cast(p.data())); if (subGroup->childCount() == 0) { continue; } if (m_flat) { m_sorted = true; const KServiceGroup::Ptr serviceGroup(static_cast(p.data())); processServiceGroup(serviceGroup); } else { AppGroupEntry *groupEntry = new AppGroupEntry(this, subGroup, m_paginate, m_pageSize, m_flat, m_sorted, m_showSeparators, m_appNameFormat); m_entryList << groupEntry; } } } } void AppsModel::sortEntries() { QCollator c; std::sort(m_entryList.begin(), m_entryList.end(), [&c](AbstractEntry* a, AbstractEntry* b) { if (a->type() != b->type()) { return a->type() > b->type(); } else { return c.compare(a->name(), b->name()) < 0; } }); } void AppsModel::checkSycocaChanges(const QStringList &changes) { if (changes.contains(QLatin1String("services")) || changes.contains(QLatin1String("apps")) || changes.contains(QLatin1String("xdgdata-apps"))) { m_changeTimer->start(); } } void AppsModel::entryChanged(AbstractEntry *entry) { int i = m_entryList.indexOf(entry); if (i != -1) { QModelIndex idx = index(i, 0); emit dataChanged(idx, idx); } } void AppsModel::classBegin() { } void AppsModel::componentComplete() { m_complete = true; if (m_autoPopulate) { refresh(); } } diff --git a/applets/kickoff/package/contents/ui/code/tools.js b/applets/kickoff/package/contents/ui/code/tools.js index a7f6a74d4..1aa2a65eb 100644 --- a/applets/kickoff/package/contents/ui/code/tools.js +++ b/applets/kickoff/package/contents/ui/code/tools.js @@ -1,202 +1,202 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2013-2015 by Eike Hein * * Copyright (C) 2017 by Ivan Cukic * * * * 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 . * ***************************************************************************/ .pragma library function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) { // Accessing actionList can be a costly operation, so we don't // access it until we need the menu. var actions = createFavoriteActions(i18n, favoriteModel, favoriteId); if (actions) { if (actionList && actionList.length > 0) { var separator = { "type": "separator" }; actionList.push(separator); // actionList = actions.concat(actionList); // this crashes Qt O.o actionList.push.apply(actionList, actions); } else { actionList = actions; } } actionMenu.actionList = actionList; } function createFavoriteActions(i18n, favoriteModel, favoriteId) { if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) { return null; } if (favoriteModel.activities === undefined || favoriteModel.activities.runningActivities.length <= 1) { var action = {}; if (favoriteModel.isFavorite(favoriteId)) { action.text = i18n("Remove from Favorites"); action.icon = "bookmark-remove"; action.actionId = "_kicker_favorite_remove"; } else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) { action.text = i18n("Add to Favorites"); action.icon = "bookmark-new"; action.actionId = "_kicker_favorite_add"; } else { return null; } action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId }; return [action]; } else { var actions = []; var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId); var activities = favoriteModel.activities.runningActivities; // Adding the item to link/unlink to all activities var linkedToAllActivities = !(linkedActivities.indexOf(":global") === -1); actions.push({ text : i18n("On All Activities"), checkable : true, actionId : linkedToAllActivities ? "_kicker_favorite_remove_from_activity" : "_kicker_favorite_set_to_activity", checked : linkedToAllActivities, actionArgument : { favoriteModel: favoriteModel, favoriteId: favoriteId, favoriteActivity: "" } }); // Adding items for each activity separately var addActivityItem = function(activityId, activityName) { var linkedToThisActivity = !(linkedActivities.indexOf(activityId) === -1); actions.push({ text : activityName, checkable : true, checked : linkedToThisActivity && !linkedToAllActivities, actionId : // If we are on all activities, and the user clicks just one // specific activity, unlink from everything else linkedToAllActivities ? "_kicker_favorite_set_to_activity" : // If we are linked to the current activity, just unlink from // that single one linkedToThisActivity ? "_kicker_favorite_remove_from_activity" : // Otherwise, link to this activity, but do not unlink from // other ones "_kicker_favorite_add_to_activity", actionArgument : { favoriteModel : favoriteModel, favoriteId : favoriteId, favoriteActivity : activityId } }); }; // Adding the item to link/unlink to the current activity - addActivityItem(favoriteModel.activities.currentActivity, i18n("On The Current Activity")); + addActivityItem(favoriteModel.activities.currentActivity, i18n("On the Current Activity")); actions.push({ type: "separator", actionId: "_kicker_favorite_separator" }); // Adding the items for each activity activities.forEach(function(activityId) { addActivityItem(activityId, favoriteModel.activityNameForId(activityId)); }); return [{ - text : i18n("Show In Favorites"), + text : i18n("Show in Favorites"), icon : "favorite", subActions : actions }]; } } function triggerAction(model, index, actionId, actionArgument) { function startsWith(txt, needle) { return txt.substr(0, needle.length) === needle; } if (startsWith(actionId, "_kicker_favorite_")) { handleFavoriteAction(actionId, actionArgument); return; } var closeRequested = model.trigger(index, actionId, actionArgument); if (closeRequested) { return true; } return false; } function handleFavoriteAction(actionId, actionArgument) { var favoriteId = actionArgument.favoriteId; var favoriteModel = actionArgument.favoriteModel; console.log(actionId); if (favoriteModel === null || favoriteId == null) { return null; } if (actionId == "_kicker_favorite_remove") { console.log("Removing from all activities"); favoriteModel.removeFavorite(favoriteId); } else if (actionId == "_kicker_favorite_add") { console.log("Adding to global activity"); favoriteModel.addFavorite(favoriteId); } else if (actionId == "_kicker_favorite_remove_from_activity") { console.log("Removing from a specific activity"); favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity); } else if (actionId == "_kicker_favorite_add_to_activity") { console.log("Adding to another activity"); favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity); } else if (actionId == "_kicker_favorite_set_to_activity") { console.log("Removing the item from the favourites, and re-adding it just to be on a specific activity"); favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity); } }