diff --git a/applets/taskmanager/package/contents/ui/ContextMenu.qml b/applets/taskmanager/package/contents/ui/ContextMenu.qml index fa5c72d6c..8b8798981 100644 --- a/applets/taskmanager/package/contents/ui/ContextMenu.qml +++ b/applets/taskmanager/package/contents/ui/ContextMenu.qml @@ -1,451 +1,451 @@ /*************************************************************************** * 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents PlasmaComponents.ContextMenu { id: menu placement: { if (plasmoid.location == PlasmaCore.Types.LeftEdge) { return PlasmaCore.Types.RightPosedTopAlignedPopup; } else if (plasmoid.location == PlasmaCore.Types.TopEdge) { return PlasmaCore.Types.BottomPosedLeftAlignedPopup; } else { return PlasmaCore.Types.TopPosedLeftAlignedPopup; } } minimumWidth: visualParent.width onStatusChanged: { if (visualParent && visualParent.m.LauncherUrlWithoutIcon != null && status == PlasmaComponents.DialogStatus.Open) { launcherToggleAction.checked = (tasksModel.launcherPosition(visualParent.m.LauncherUrlWithoutIcon) != -1); } else if (status == PlasmaComponents.DialogStatus.Closed) { menu.destroy(); } } function show() { loadDynamicLaunchActions(visualParent.m.LauncherUrlWithoutIcon); backend.ungrabMouse(visualParent); openRelative(); } function newMenuItem(parent) { return Qt.createQmlObject( "import org.kde.plasma.components 2.0 as PlasmaComponents;" + "PlasmaComponents.MenuItem {}", parent); } function newSeparator(parent) { return Qt.createQmlObject( "import org.kde.plasma.components 2.0 as PlasmaComponents;" + "PlasmaComponents.MenuItem { separator: true }", parent); } function loadDynamicLaunchActions(launcherUrl) { var actionList = backend.jumpListActions(launcherUrl, menu); for (var i = 0; i < actionList.length; ++i) { var item = newMenuItem(menu); item.action = actionList[i]; menu.addMenuItem(item, virtualDesktopsMenuItem); } if (actionList.length > 0) { menu.addMenuItem(newSeparator(menu), virtualDesktopsMenuItem); } var actionList = backend.recentDocumentActions(launcherUrl, menu); for (var i = 0; i < actionList.length; ++i) { var item = newMenuItem(menu); item.action = actionList[i]; menu.addMenuItem(item, virtualDesktopsMenuItem); } if (actionList.length > 0) { menu.addMenuItem(newSeparator(menu), virtualDesktopsMenuItem); } } PlasmaComponents.MenuItem { id: virtualDesktopsMenuItem visible: virtualDesktopInfo.numberOfDesktops > 1 && (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true && visualParent.m.IsVirtualDesktopChangeable === true) enabled: visible text: i18n("Move To &Desktop") Connections { target: virtualDesktopInfo onNumberOfDesktopsChanged: virtualDesktopsMenu.refresh() onDesktopNamesChanged: virtualDesktopsMenu.refresh() } PlasmaComponents.ContextMenu { id: virtualDesktopsMenu visualParent: virtualDesktopsMenuItem.action function refresh() { clearMenuItems(); if (virtualDesktopInfo.numberOfDesktops <= 1) { return; } var menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("Move &To Current Desktop"); menuItem.enabled = Qt.binding(function() { return menu.visualParent && menu.visualParent.m.VirtualDesktop != virtualDesktopInfo.currentDesktop; }); menuItem.clicked.connect(function() { tasksModel.requestVirtualDesktop(menu.visualParent.modelIndex(), 0); }); menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("&All Desktops"); menuItem.checkable = true; menuItem.checked = Qt.binding(function() { return menu.visualParent && menu.visualParent.m.IsOnAllVirtualDesktops === true; }); menuItem.clicked.connect(function() { tasksModel.requestVirtualDesktop(menu.visualParent.modelIndex(), 0); }); backend.setActionGroup(menuItem.action); menu.newSeparator(virtualDesktopsMenu); for (var i = 0; i < virtualDesktopInfo.desktopNames.length; ++i) { menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18nc("1 = number of desktop, 2 = desktop name", "&%1 Desktop %2", i + 1, virtualDesktopInfo.desktopNames[i]); menuItem.checkable = true; menuItem.checked = Qt.binding((function(i) { return function() { return menu.visualParent && menu.visualParent.m.VirtualDesktop == (i + 1) }; })(i)); menuItem.clicked.connect((function(i) { return function() { return tasksModel.requestVirtualDesktop(menu.visualParent.modelIndex(), i + 1); }; })(i)); backend.setActionGroup(menuItem.action); } menu.newSeparator(virtualDesktopsMenu); menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("&New Desktop"); menuItem.clicked.connect(function() { tasksModel.requestVirtualDesktop(menu.visualParent.modelIndex(), virtualDesktopInfo.numberOfDesktops + 1) }); } Component.onCompleted: refresh() } } PlasmaComponents.MenuItem { id: activitiesDesktopsMenuItem visible: activityInfo.numberOfRunningActivities > 1 && (visualParent && !visualParent.m.IsLauncher && !visualParent.m.IsStartup) enabled: visible text: i18n("Move To &Activity") Connections { target: activityInfo onNumberOfRunningActivitiesChanged: activitiesDesktopsMenu.refresh() } PlasmaComponents.ContextMenu { id: activitiesDesktopsMenu visualParent: activitiesDesktopsMenuItem.action function refresh() { clearMenuItems(); if (activityInfo.numberOfRunningActivities <= 1) { return; } var menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = i18n("Add To Current Activity"); menuItem.enabled = Qt.binding(function() { return menu.visualParent && menu.visualParent.m.Activities.length > 0 && menu.visualParent.m.Activities.indexOf(activityInfo.currentActivity) < 0; }); menuItem.clicked.connect(function() { tasksModel.requestActivities(menu.visualParent.modelIndex(), menu.visualParent.m.Activities.concat(activityInfo.currentActivity)); }); menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = i18n("All Activities"); menuItem.checkable = true; menuItem.checked = Qt.binding(function() { return menu.visualParent && menu.visualParent.m.Activities.length === 0; }); menuItem.clicked.connect(function() { var checked = menuItem.checked; var newActivities = undefined; // will cast to an empty QStringList i.e all activities if (!checked) { newActivities = new Array(activityInfo.currentActivity); } tasksModel.requestActivities(menu.visualParent.modelIndex(), newActivities); }); menu.newSeparator(activitiesDesktopsMenu); var runningActivities = activityInfo.runningActivities(); for (var i = 0; i < runningActivities.length; ++i) { var activityId = runningActivities[i]; menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = activityInfo.activityName(runningActivities[i]); menuItem.checkable = true; menuItem.checked = Qt.binding( (function(activityId) { return function() { return menu.visualParent && menu.visualParent.m.Activities.indexOf(activityId) >= 0; }; })(activityId)); menuItem.clicked.connect((function(activityId) { return function () { var checked = menuItem.checked; var newActivities = menu.visualParent.m.Activities; if (checked) { newActivities = newActivities.concat(activityId); } else { var index = newActivities.indexOf(activityId) if (index < 0) { return; } newActivities = newActivities.splice(index, 1); } return tasksModel.requestActivities(menu.visualParent.modelIndex(), newActivities); }; })(activityId)); } menu.newSeparator(activitiesDesktopsMenu); } Component.onCompleted: refresh() } } PlasmaComponents.MenuItem { visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) enabled: visualParent && visualParent.m.IsMinimizable === true checkable: true checked: visualParent && visualParent.m.IsMinimized === true text: i18n("Mi&nimize") onClicked: tasksModel.requestToggleMinimized(visualParent.modelIndex()) } PlasmaComponents.MenuItem { visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) enabled: visualParent && visualParent.m.IsMaximizable === true checkable: true checked: visualParent && visualParent.m.IsMaximized === true text: i18n("Ma&ximize") onClicked: tasksModel.requestToggleMaximized(visualParent.modelIndex()) } PlasmaComponents.MenuItem { visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) enabled: visualParent && visualParent.m.LauncherUrlWithoutIcon != null text: i18n("Start New Instance") icon: "system-run" onClicked: tasksModel.requestNewInstance(visualParent.modelIndex()) } PlasmaComponents.MenuItem { id: launcherToggleAction - visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) + visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable enabled: visualParent && visualParent.m.LauncherUrlWithoutIcon != null checkable: true text: i18n("&Show A Launcher When Not Running") onClicked: { if (tasksModel.launcherPosition(visualParent.m.LauncherUrlWithoutIcon) != -1) { tasksModel.requestRemoveLauncher(visualParent.m.LauncherUrlWithoutIcon); } else { tasksModel.requestAddLauncher(visualParent.m.LauncherUrl); } } } PlasmaComponents.MenuItem { - visible: (visualParent && visualParent.m.IsLauncher === true) + visible: (visualParent && visualParent.m.IsLauncher === true) && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable text: i18n("Remove Launcher") onClicked: tasksModel.requestRemoveLauncher(visualParent.m.LauncherUrlWithoutIcon); } PlasmaComponents.MenuItem { id: moreActionsMenuItem visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) enabled: visible text: i18n("More Actions") PlasmaComponents.ContextMenu { visualParent: moreActionsMenuItem.action PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.visualParent.m.IsMovable === true text: i18n("&Move") icon: "transform-move" onClicked: tasksModel.requestMove(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.visualParent.m.IsResizable === true text: i18n("Re&size") onClicked: tasksModel.requestResize(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { checkable: true checked: menu.visualParent && menu.visualParent.m.IsKeepAbove === true text: i18n("Keep &Above Others") icon: "go-up" onClicked: tasksModel.requestToggleKeepAbove(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { checkable: true checked: menu.visualParent && menu.visualParent.m.IsKeepBelow === true text: i18n("Keep &Below Others") icon: "go-down" onClicked: tasksModel.requestToggleKeepBelow(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.visualParent.m.IsFullScreenable === true checkable: true checked: menu.visualParent && menu.visualParent.m.IsFullScreen === true text: i18n("&Fullscreen") icon: "view-fullscreen" onClicked: tasksModel.requestToggleFullScreen(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.visualParent.m.IsShadeable === true checkable: true checked: menu.visualParent && menu.visualParent.m.IsShaded === true text: i18n("&Shade") onClicked: tasksModel.requestToggleShaded(menu.visualParent.modelIndex()) } PlasmaComponents.MenuItem { separator: true } PlasmaComponents.MenuItem { visible: (plasmoid.configuration.groupingStrategy != 0) && menu.visualParent.m.IsWindow === true checkable: true checked: menu.visualParent && menu.visualParent.m.IsGroupable === true text: i18n("Allow this program to be grouped") onClicked: tasksModel.requestToggleGrouping(menu.visualParent.modelIndex()) } } } PlasmaComponents.MenuItem { property QtObject configureAction: null enabled: configureAction && configureAction.enabled text: configureAction ? configureAction.text : "" icon: configureAction ? configureAction.icon : "" onClicked: configureAction.trigger() Component.onCompleted: configureAction = plasmoid.action("configure") } PlasmaComponents.MenuItem { separator: true } PlasmaComponents.MenuItem { visible: (visualParent && visualParent.m.IsLauncher !== true && visualParent.m.IsStartup !== true) enabled: visualParent && visualParent.m.IsClosable === true text: i18n("&Close") icon: "window-close" onClicked: tasksModel.requestClose(visualParent.modelIndex()) } } diff --git a/applets/taskmanager/package/contents/ui/main.qml b/applets/taskmanager/package/contents/ui/main.qml index 341a372c4..9275e4c09 100644 --- a/applets/taskmanager/package/contents/ui/main.qml +++ b/applets/taskmanager/package/contents/ui/main.qml @@ -1,348 +1,350 @@ /*************************************************************************** * 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.taskmanager 0.1 as TaskManager import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import "../code/layout.js" as LayoutManager import "../code/tools.js" as TaskTools Item { id: tasks anchors.fill: parent property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) property bool iconsOnly: (plasmoid.pluginName == "org.kde.plasma.icontasks") property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml"); Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Layout.fillWidth: true Layout.fillHeight:true Layout.minimumWidth: tasks.vertical ? 0 : LayoutManager.preferredMinWidth() Layout.minimumHeight: !tasks.vertical ? 0 : LayoutManager.preferredMinHeight() //BEGIN TODO: this is not precise enough: launchers are smaller than full tasks Layout.preferredWidth: tasks.vertical ? units.gridUnit * 10 : ((LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxWidth()) / LayoutManager.calculateStripes()); Layout.preferredHeight: tasks.vertical ? ((LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxHeight()) / LayoutManager.calculateStripes()) : units.gridUnit * 2; //END TODO property Item dragSource: null signal requestLayout signal windowsHovered(variant winIds, bool hovered) signal presentWindows(variant winIds) onWidthChanged: { taskList.width = LayoutManager.layoutWidth(); if (plasmoid.configuration.forceStripes) { taskList.height = LayoutManager.layoutHeight(); } } onHeightChanged: { if (plasmoid.configuration.forceStripes) { taskList.width = LayoutManager.layoutWidth(); } taskList.height = LayoutManager.layoutHeight(); } onDragSourceChanged: { if (dragSource == null) { tasksModel.syncLaunchers(); } } TaskManager.TasksModel { id: tasksModel virtualDesktop: virtualDesktopInfo.currentDesktop screenGeometry: plasmoid.screenGeometry activity: activityInfo.currentActivity filterByVirtualDesktop: plasmoid.configuration.showOnlyCurrentDesktop filterByScreen: plasmoid.configuration.showOnlyCurrentScreen filterByActivity: plasmoid.configuration.showOnlyCurrentActivity filterNotMinimized: plasmoid.configuration.showOnlyMinimized sortMode: iconsOnly ? TaskManager.TasksModel.SortManual : sortModeEnumValue(plasmoid.configuration.sortingStrategy) launchInPlace: iconsOnly separateLaunchers: { if (!iconsOnly && !plasmoid.configuration.separateLaunchers && plasmoid.configuration.sortingStrategy == 1) { return false; } return true; } groupMode: iconsOnly ? TaskManager.TasksModel.GroupApplication : sortModeEnumValue(plasmoid.configuration.groupingStrategy) groupInline: !plasmoid.configuration.groupPopups groupingWindowTasksThreshold: (plasmoid.configuration.onlyGroupWhenFull && !iconsOnly ? LayoutManager.optimumCapacity(width, height) + 1 : -1) onLauncherListChanged: { layoutTimer.restart(); plasmoid.configuration.launchers = launcherList; } onGroupingAppIdBlacklistChanged: { plasmoid.configuration.groupingAppIdBlacklist = groupingAppIdBlacklist; } onGroupingLauncherUrlBlacklistChanged: { plasmoid.configuration.groupingLauncherUrlBlacklist = groupingLauncherUrlBlacklist; } function sortModeEnumValue(index) { switch (index) { case 0: return TaskManager.TasksModel.SortDisabled; case 1: return TaskManager.TasksModel.SortManual; case 2: return TaskManager.TasksModel.SortAlpha; case 3: return TaskManager.TasksModel.SortVirtualDesktop; case 4: return TaskManager.TasksModel.SortActivity; default: return TaskManager.TasksModel.SortDisabled; } } function groupModeEnumValue(index) { switch (index) { case 0: return TaskManager.TasksModel.GroupDisabled; case 1: return TaskManager.TasksModel.GroupApplications; } } Component.onCompleted: { launcherList = plasmoid.configuration.launchers; groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; // Only hook up view only after the above churn is done. taskRepeater.model = tasksModel; } } TaskManager.VirtualDesktopInfo { id: virtualDesktopInfo } TaskManager.ActivityInfo { id: activityInfo } TaskManagerApplet.Backend { id: backend taskManagerItem: tasks toolTipItem: toolTipDelegate highlightWindows: plasmoid.configuration.highlightWindows onAddLauncher: { - tasksModel.requestAddLauncher(url); + tasks.addLauncher(url); } } Timer { id: iconGeometryTimer interval: 500 repeat: false onTriggered: { TaskTools.publishIconGeometries(taskList.children); } } Binding { target: plasmoid property: "status" value: (tasksModel.anyTaskDemandsAttention ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus) } Connections { target: plasmoid onLocationChanged: { // This is on a timer because the panel may not have // settled into position yet when the location prop- // erty updates. iconGeometryTimer.start(); } } Connections { target: plasmoid.configuration onLaunchersChanged: tasksModel.launcherList = plasmoid.configuration.launchers onGroupingAppIdBlacklistChanged: tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; onGroupingLauncherUrlBlacklistChanged: tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; } TaskManagerApplet.DragHelper { id: dragHelper dragIconSize: units.iconSizes.medium } PlasmaCore.FrameSvgItem { id: taskFrame visible: false; imagePath: "widgets/tasks"; prefix: "normal" } PlasmaCore.Svg { id: taskSvg imagePath: "widgets/tasks" } MouseHandler { id: mouseHandler anchors.fill: parent target: taskList onUrlsDropped: { // If all dropped URLs point to application desktop files, we'll add a launcher for each of them. var createLaunchers = urls.every(function (item) { return backend.isApplication(item) }); if (createLaunchers) { urls.forEach(function (item) { addLauncher(item); }); return; } if (!hoveredItem) { return; } // DeclarativeMimeData urls is a QJsonArray but requestOpenUrls expects a proper QList. var urlsList = backend.jsonArrayToUrlList(urls); // Otherwise we'll just start a new instance of the application with the URLs as argument, // as you probably don't expect some of your files to open in the app and others to spawn launchers. tasksModel.requestOpenUrls(hoveredItem.modelIndex(), urlsList); } } ToolTipDelegate { id: toolTipDelegate visible: false } TaskList { id: taskList anchors { left: parent.left top: parent.top } onWidthChanged: LayoutManager.layout(taskRepeater) onHeightChanged: LayoutManager.layout(taskRepeater) flow: { if (tasks.vertical) { return plasmoid.configuration.forceStripes ? Flow.LeftToRight : Flow.TopToBottom } return plasmoid.configuration.forceStripes ? Flow.TopToBottom : Flow.LeftToRight } onAnimatingChanged: { if (!animating) { TaskTools.publishIconGeometries(children); } } function layout() { taskList.width = LayoutManager.layoutWidth(); taskList.height = LayoutManager.layoutHeight(); LayoutManager.layout(taskRepeater); } Timer { id: layoutTimer interval: 0 repeat: false onTriggered: taskList.layout() } Repeater { id: taskRepeater delegate: Task {} onItemAdded: taskList.layout() onItemRemoved: taskList.layout() } } GroupDialog { id: groupDialog } function hasLauncher(url) { return tasksModel.launcherPosition(url) != -1; } function addLauncher(url) { - tasksModel.requestAddLauncher(url); + if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) { + tasksModel.requestAddLauncher(url); + } } function resetDragSource() { dragSource = null; } Component.onCompleted: { tasks.requestLayout.connect(layoutTimer.restart); tasks.requestLayout.connect(iconGeometryTimer.restart); tasks.windowsHovered.connect(backend.windowsHovered); tasks.presentWindows.connect(backend.presentWindows); dragHelper.dropped.connect(resetDragSource); } }