diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 43ea736..ec4bd13 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -1,198 +1,201 @@ true false false false close|maximize|minimize|pin false false false false false false 0 false 0.5 10 false 0.2 0.0 true 0 0 0 false ^(.*)\s*[—–\-:]\s*(Mozilla )?([^—–\-:]+)$ $3 — $1 Plasma Desktop :: %activity% false 1000 true false false 5 1 false false false false false + + false + false false true false 0 0.1 1.0 true 0 0 false 0 diff --git a/package/contents/icons/default/restore.svg b/package/contents/icons/default/restore.svg new file mode 100644 index 0000000..f5be162 --- /dev/null +++ b/package/contents/icons/default/restore.svg @@ -0,0 +1,462 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package/contents/ui/AppMenu.qml b/package/contents/ui/AppMenu.qml index d91c457..960ce37 100644 --- a/package/contents/ui/AppMenu.qml +++ b/package/contents/ui/AppMenu.qml @@ -1,172 +1,173 @@ import QtQuick 2.2 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents Item { id: appmenu anchors.fill: parent property bool appmenuEnabled: plasmoid.configuration.appmenuEnabled property bool appmenuNextToButtons: plasmoid.configuration.appmenuNextToButtons property bool appmenuFillHeight: plasmoid.configuration.appmenuFillHeight property bool appmenuFontBold: plasmoid.configuration.appmenuFontBold + property bool appmenuDoNotHide: plasmoid.configuration.appmenuDoNotHide property bool appmenuEnabledAndNonEmpty: appmenuEnabled && appMenuModel !== null && appMenuModel.menuAvailable property bool appmenuOpened: appmenuEnabled && plasmoid.nativeInterface.currentIndex > -1 property var appMenuModel: null property bool appmenuButtonsOffsetEnabled: !buttonsStandalone && appmenuNextToButtons && childrenRect.width > 0 property double appmenuOffsetWidth: visible && appmenuNextToIconAndText && !appmenuSwitchSidesWithIconAndText ? appmenu.childrenRect.width + (appmenuButtonsOffsetEnabled ? controlButtonsArea.width : 0) + appmenuSideMargin*2 : 0 - visible: appmenuEnabledAndNonEmpty && !noWindowActive && (appmenuNextToIconAndText || mouseHover || appmenuOpened) + visible: appmenuEnabledAndNonEmpty && !noWindowActive && (appmenuDoNotHide || mouseHover || appmenuOpened) GridLayout { id: buttonGrid Layout.minimumWidth: implicitWidth Layout.minimumHeight: implicitHeight flow: GridLayout.LeftToRight rowSpacing: 0 columnSpacing: 0 anchors.top: parent.top anchors.left: parent.left property double placementOffsetButtons: appmenuNextToButtons && controlButtonsArea.visible ? controlButtonsArea.width + appmenuSideMargin : 0 property double placementOffset: appmenuNextToIconAndText && appmenuSwitchSidesWithIconAndText ? activeWindowListView.anchors.leftMargin + windowTitleText.anchors.leftMargin + windowTitleText.contentWidth + appmenuSideMargin : placementOffsetButtons anchors.leftMargin: (bp === 1 || bp === 3) ? parent.width - width - placementOffset : placementOffset anchors.topMargin: (bp === 2 || bp === 3) ? 0 : parent.height - height Component.onCompleted: { plasmoid.nativeInterface.buttonGrid = buttonGrid plasmoid.nativeInterface.enabled = appmenuEnabled } Connections { target: plasmoid.nativeInterface onRequestActivateIndex: { var idx = Math.max(0, Math.min(buttonRepeater.count - 1, index)) var button = buttonRepeater.itemAt(index) if (button) { button.clicked(null) } } } Repeater { id: buttonRepeater model: null MouseArea { id: appmenuButton hoverEnabled: true readonly property int buttonIndex: index property bool menuOpened: plasmoid.nativeInterface.currentIndex === index Layout.preferredWidth: appmenuButtonBackground.width Layout.preferredHeight: appmenuButtonBackground.height Rectangle { id: appmenuButtonBackground border.color: 'transparent' width: appmenuButtonTitle.implicitWidth + units.smallSpacing * 3 height: appmenuFillHeight ? appmenu.height : appmenuButtonTitle.implicitHeight + units.smallSpacing color: menuOpened ? theme.highlightColor : 'transparent' radius: units.smallSpacing / 2 } PlasmaComponents.Label { id: appmenuButtonTitle anchors.centerIn: appmenuButtonBackground font.pixelSize: fontPixelSize * plasmoid.configuration.appmenuButtonTextSizeScale text: activeMenu.replace('&', '') font.weight: appmenuFontBold ? Font.Bold : theme.defaultFont.weight } onClicked: { plasmoid.nativeInterface.trigger(this, index) } onEntered: { appmenuButtonBackground.border.color = theme.highlightColor } onExited: { appmenuButtonBackground.border.color = 'transparent' } } } } Rectangle { id: separator anchors.left: buttonGrid.left anchors.leftMargin: appmenuSwitchSidesWithIconAndText ? - appmenuSideMargin * 0.5 : buttonGrid.width + appmenuSideMargin * 0.5 anchors.verticalCenter: buttonGrid.verticalCenter height: 0.8 * parent.height width: 1 visible: appmenuNextToIconAndText && plasmoid.configuration.appmenuSeparatorEnabled color: theme.textColor opacity: 0.4 } function initializeAppModel() { if (appMenuModel !== null) { return } print('initializing appMenuModel...') try { appMenuModel = Qt.createQmlObject( 'import QtQuick 2.2;\ import org.kde.plasma.plasmoid 2.0;\ import org.kde.private.activeWindowControl 1.0 as ActiveWindowControlPrivate;\ ActiveWindowControlPrivate.AppMenuModel {\ id: appMenuModel;\ Component.onCompleted: {\ plasmoid.nativeInterface.model = appMenuModel\ }\ }', main) } catch (e) { print('appMenuModel failed to initialize: ' + e) } print('initializing appmenu...DONE ' + appMenuModel) if (appMenuModel !== null) { resetAppmenuModel() } } function resetAppmenuModel() { if (appmenuEnabled) { initializeAppModel() if (appMenuModel === null) { return } print('setting model in QML: ' + appMenuModel) for (var key in appMenuModel) { print(' ' + key + ' -> ' + appMenuModel[key]) } plasmoid.nativeInterface.model = appMenuModel buttonRepeater.model = appMenuModel } else { plasmoid.nativeInterface.model = null buttonRepeater.model = null } } onAppmenuEnabledChanged: { appmenu.resetAppmenuModel() if (appMenuModel !== null) { plasmoid.nativeInterface.enabled = appmenuEnabled } } } \ No newline at end of file diff --git a/package/contents/ui/config/ConfigAppMenu.qml b/package/contents/ui/config/ConfigAppMenu.qml index 9acea2f..ebdd6b7 100644 --- a/package/contents/ui/config/ConfigAppMenu.qml +++ b/package/contents/ui/config/ConfigAppMenu.qml @@ -1,118 +1,124 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 Item { id: main property alias cfg_appmenuEnabled: appmenuEnabled.checked property alias cfg_appmenuNextToButtons: appmenuNextToButtons.checked property alias cfg_appmenuFillHeight: appmenuFillHeight.checked property alias cfg_appmenuFontBold: appmenuFontBold.checked + property alias cfg_appmenuDoNotHide: appmenuDoNotHide.checked property alias cfg_appmenuNextToIconAndText: appmenuNextToIconAndText.checked property alias cfg_appmenuSwitchSidesWithIconAndText: appmenuSwitchSidesWithIconAndText.checked property alias cfg_appmenuSeparatorEnabled: appmenuSeparatorEnabled.checked property alias cfg_appmenuBoldTitleWhenMenuDisplayed: appmenuBoldTitleWhenMenuDisplayed.checked property alias cfg_appmenuOuterSideMargin: appmenuOuterSideMargin.value property alias cfg_appmenuIconAndTextOpacity: appmenuIconAndTextOpacity.value property alias cfg_appmenuButtonTextSizeScale: appmenuButtonTextSizeScale.value GroupBox { id: appmenuEnabled title: i18n("Enable application menu") checkable: true flat: true GridLayout { columns: 2 Item { width: 2 height: 10 Layout.columnSpan: 2 } CheckBox { id: appmenuFillHeight text: i18n("Fill height") Layout.columnSpan: 2 } CheckBox { id: appmenuFontBold text: i18n("Bold font") Layout.columnSpan: 2 } + CheckBox { + id: appmenuDoNotHide + text: i18n("Do not hide on mouse out") + } + CheckBox { id: appmenuNextToButtons text: i18n("Show next to buttons") Layout.columnSpan: 2 } CheckBox { id: appmenuNextToIconAndText text: i18n("Show next to icon and text") Layout.columnSpan: 2 } CheckBox { id: appmenuSwitchSidesWithIconAndText text: i18n("Switch sides with icon and text") Layout.columnSpan: 2 enabled: appmenuNextToIconAndText.checked } CheckBox { id: appmenuSeparatorEnabled text: i18n("Show separator") Layout.columnSpan: 2 enabled: appmenuNextToIconAndText.checked } CheckBox { id: appmenuBoldTitleWhenMenuDisplayed text: i18n("Make window title bold when menu is displayed") Layout.columnSpan: 2 } Label { text: i18n('Side margin:') Layout.alignment: Qt.AlignRight } SpinBox { id: appmenuOuterSideMargin decimals: 0 stepSize: 1 minimumValue: 0 maximumValue: 100 suffix: i18nc('Abbreviation for pixels', 'px') } Label { text: i18n('Icon and text opacity:') Layout.alignment: Qt.AlignRight } SpinBox { id: appmenuIconAndTextOpacity decimals: 2 stepSize: 0.1 minimumValue: 0 maximumValue: 1 } Label { text: i18n('Menu button text size scale:') Layout.alignment: Qt.AlignRight } SpinBox { id: appmenuButtonTextSizeScale decimals: 2 stepSize: 0.1 minimumValue: 0.5 maximumValue: 5 } } } } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 57125b0..9631e85 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -1,611 +1,611 @@ /* * Copyright 2015 Martin Kotelnik * * 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, see . */ import QtQuick 2.2 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 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 import org.kde.taskmanager 0.1 as TaskManager import org.kde.activities 0.1 as Activities Item { id: main property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) property double horizontalScreenWidthPercent: plasmoid.configuration.horizontalScreenWidthPercent property double buttonSize: plasmoid.configuration.buttonSize property bool autoFillWidth: plasmoid.configuration.autoFillWidth property double widthForHorizontalPanel: (Screen.width * horizontalScreenWidthPercent + plasmoid.configuration.widthFineTuning) - ((!controlButtonsArea.visible && buttonsStandalone && plasmoid.configuration.buttonsDynamicWidth) ? controlButtonsArea.width : 0) anchors.fill: parent Layout.fillWidth: plasmoid.configuration.autoFillWidth Layout.preferredWidth: autoFillWidth ? -1 : (vertical ? parent.width : (widthForHorizontalPanel > 0 ? widthForHorizontalPanel : 0.0001)) Layout.minimumWidth: Layout.preferredWidth Layout.maximumWidth: Layout.preferredWidth Layout.preferredHeight: parent === null ? 0 : vertical ? Math.min(theme.defaultFont.pointSize * 4, parent.width) : parent.height Layout.minimumHeight: Layout.preferredHeight Layout.maximumHeight: Layout.preferredHeight property int textType: plasmoid.configuration.textType property int fitText: plasmoid.configuration.fitText property int tooltipTextType: plasmoid.configuration.tooltipTextType property string tooltipText: '' property bool windowIconOnTheRight: plasmoid.configuration.windowIconOnTheRight property double iconAndTextSpacing: plasmoid.configuration.iconAndTextSpacing property bool slidingIconAndText: plasmoid.configuration.slidingIconAndText property double fontPixelSize: theme.defaultFont.pixelSize * plasmoid.configuration.fontSizeScale property bool fontBold: plasmoid.configuration.boldFontWeight property string fontFamily: plasmoid.configuration.fontFamily property bool noWindowActive: true property bool currentWindowMaximized: false property bool canShowButtonsAccordingMaximized: showButtonOnlyWhenMaximized ? currentWindowMaximized : true property int controlButtonsSpacing: plasmoid.configuration.controlButtonsSpacing property int bp: plasmoid.configuration.buttonsPosition; property bool buttonsVerticalCenter: plasmoid.configuration.buttonsVerticalCenter property bool showControlButtons: plasmoid.configuration.showControlButtons property bool showButtonOnlyWhenMaximized: plasmoid.configuration.showButtonOnlyWhenMaximized property bool showMinimize: showControlButtons && plasmoid.configuration.showMinimize property bool showMaximize: showControlButtons && plasmoid.configuration.showMaximize property bool showPinToAllDesktops: showControlButtons && plasmoid.configuration.showPinToAllDesktops property string buttonOrder: plasmoid.configuration.buttonOrder property bool doubleClickMaximizes: plasmoid.configuration.doubleClickMaximizes property int leftClickAction: plasmoid.configuration.leftClickAction property string chosenLeftClickSource: leftClickAction === 1 ? shortcutDS.presentWindows : leftClickAction === 2 ? shortcutDS.presentWindowsAll : leftClickAction === 3 ? shortcutDS.presentWindowsClass : '' property bool middleClickClose: plasmoid.configuration.middleClickAction === 1 property bool middleClickFullscreen: plasmoid.configuration.middleClickAction === 2 property bool wheelUpMaximizes: plasmoid.configuration.wheelUpMaximizes property bool wheelDownMinimizes: plasmoid.configuration.wheelDownAction === 1 property bool wheelDownUnmaximizes: plasmoid.configuration.wheelDownAction === 2 property bool buttonsStandalone: showControlButtons && plasmoid.configuration.buttonsStandalone property bool buttonsBetweenIconAndText: buttonsStandalone && plasmoid.configuration.buttonsBetweenIconAndText property bool doNotHideControlButtons: showControlButtons && plasmoid.configuration.doNotHideControlButtons property bool textColorLight: ((theme.textColor.r + theme.textColor.g + theme.textColor.b) / 3) > 0.5 property bool mouseHover: false property bool isActiveWindowPinned: false property bool isActiveWindowMaximized: false property bool appmenuNextToIconAndText: plasmoid.configuration.appmenuNextToIconAndText property double appmenuSideMargin: plasmoid.configuration.appmenuOuterSideMargin property bool appmenuSwitchSidesWithIconAndText: plasmoid.configuration.appmenuSwitchSidesWithIconAndText property bool appmenuBoldTitleWhenMenuDisplayed: plasmoid.configuration.appmenuBoldTitleWhenMenuDisplayed property var activeTaskLocal: null property int activityActionCount: 0 Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation // // MODEL // TaskManager.TasksModel { id: tasksModel sortMode: TaskManager.TasksModel.SortVirtualDesktop groupMode: TaskManager.TasksModel.GroupDisabled screenGeometry: plasmoid.screenGeometry filterByScreen: plasmoid.configuration.showForCurrentScreenOnly onActiveTaskChanged: { updateActiveWindowInfo() } onDataChanged: { updateActiveWindowInfo() } onCountChanged: { updateActiveWindowInfo() } } TaskManager.ActivityInfo { id: activityInfo onCurrentActivityChanged: { if (noWindowActive) { updateActiveWindowInfo(); } reAddActivityActions() } onNumberOfRunningActivitiesChanged: { reAddActivityActions() } } Activities.ActivityModel { id: activityModel } function activeTask() { return activeTaskLocal } function activeTaskExists() { return activeTaskLocal.display !== undefined } onTooltipTextTypeChanged: updateTooltip() function updateTooltip() { if (tooltipTextType === 1) { tooltipText = replaceTitle(activeTask().display || '') } else if (tooltipTextType === 2) { tooltipText = activeTask().AppName || '' } else { tooltipText = '' } } function composeNoWindowText() { return plasmoid.configuration.noWindowText.replace('%activity%', activityInfo.activityName(activityInfo.currentActivity)) } function updateActiveWindowInfo() { var activeTaskIndex = tasksModel.activeTask // fallback for Plasma 5.8 var abstractTasksModel = TaskManager.AbstractTasksModel || {} var isActive = abstractTasksModel.IsActive || 271 var appName = abstractTasksModel.AppName || 258 var isMaximized = abstractTasksModel.IsMaximized || 276 var virtualDesktop = abstractTasksModel.VirtualDesktop || 286 if (!tasksModel.data(activeTaskIndex, isActive)) { activeTaskLocal = {} } else { activeTaskLocal = { display: tasksModel.data(activeTaskIndex, Qt.DisplayRole), decoration: tasksModel.data(activeTaskIndex, Qt.DecorationRole), AppName: tasksModel.data(activeTaskIndex, appName), IsMaximized: tasksModel.data(activeTaskIndex, isMaximized), VirtualDesktop: tasksModel.data(activeTaskIndex, virtualDesktop) } } var actTask = activeTask() noWindowActive = !activeTaskExists() currentWindowMaximized = !noWindowActive && actTask.IsMaximized === true isActiveWindowPinned = actTask.VirtualDesktop === -1; if (noWindowActive) { windowTitleText.text = composeNoWindowText() iconItem.source = plasmoid.configuration.noWindowIcon } else { windowTitleText.text = textType === 1 ? actTask.AppName : replaceTitle(actTask.display) iconItem.source = actTask.decoration } updateTooltip() } function toggleMaximized() { tasksModel.requestToggleMaximized(tasksModel.activeTask); } function toggleMinimized() { tasksModel.requestToggleMinimized(tasksModel.activeTask); } function toggleClose() { tasksModel.requestClose(tasksModel.activeTask); } function toggleFullscreen() { tasksModel.requestToggleFullScreen(tasksModel.activeTask); } function togglePinToAllDesktops() { tasksModel.requestVirtualDesktop(tasksModel.activeTask, 0); } function setMaximized(maximized) { if ((maximized && !activeTask().IsMaximized) || (!maximized && activeTask().IsMaximized)) { print('toggle maximized') toggleMaximized() } } function setMinimized() { if (!activeTask().IsMinimized) { toggleMinimized() } } // // ACTIVE WINDOW INFO // Item { id: activeWindowListView anchors.top: parent.top anchors.bottom: parent.bottom property double appmenuOffsetLeft: (bp === 0 || bp === 2) ? appmenu.appmenuOffsetWidth : 0 property double appmenuOffsetRight: (bp === 1 || bp === 3) ? appmenu.appmenuOffsetWidth : 0 property double controlButtonsAreaWidth: noWindowActive ? 0 : controlButtonsArea.width property bool buttonsVisible: buttonsStandalone && (!slidingIconAndText || controlButtonsArea.mouseInWidget || doNotHideControlButtons) && (canShowButtonsAccordingMaximized || !slidingIconAndText) property double buttonsBetweenAddition: buttonsVisible && buttonsBetweenIconAndText ? controlButtonsAreaWidth + iconAndTextSpacing : 0 anchors.left: parent.left anchors.leftMargin: buttonsVisible && (bp === 0 || bp === 2) && !buttonsBetweenIconAndText ? controlButtonsAreaWidth + iconAndTextSpacing + appmenuOffsetLeft : 0 + appmenuOffsetLeft anchors.right: parent.right anchors.rightMargin: buttonsVisible && (bp === 1 || bp === 3) && !buttonsBetweenIconAndText ? controlButtonsAreaWidth + iconAndTextSpacing + appmenuOffsetRight : 0 + appmenuOffsetRight Behavior on anchors.leftMargin { NumberAnimation { duration: 150 easing.type: Easing.Linear } } Behavior on anchors.rightMargin { NumberAnimation { duration: 150 easing.type: Easing.Linear } } width: parent.width - anchors.leftMargin - anchors.rightMargin opacity: appmenu.visible && !appmenuNextToIconAndText ? plasmoid.configuration.appmenuIconAndTextOpacity : 1 Item { width: parent.width height: main.height // window icon PlasmaCore.IconItem { id: iconItem anchors.left: parent.left anchors.leftMargin: windowIconOnTheRight ? parent.width - iconItem.width : 0 width: parent.height height: parent.height source: plasmoid.configuration.noWindowIcon visible: plasmoid.configuration.showWindowIcon } // window title PlasmaComponents.Label { id: windowTitleText property double iconMargin: (plasmoid.configuration.showWindowIcon ? iconItem.width : 0) property double properWidth: parent.width - iconMargin - iconAndTextSpacing property double properHeight: parent.height property bool noElide: fitText === 2 || (fitText === 1 && mouseHover) property int allowFontSizeChange: 3 property int minimumPixelSize: 8 property double iconMarginForAnchor: noWindowActive && plasmoid.configuration.noWindowIcon === '' ? 0 : iconMargin property bool limitTextWidth: plasmoid.configuration.limitTextWidth property int textWidthLimit: plasmoid.configuration.textWidthLimit property double computedWidth: (limitTextWidth ? (implicitWidth > textWidthLimit ? textWidthLimit : implicitWidth) : properWidth) - activeWindowListView.buttonsBetweenAddition anchors.left: parent.left anchors.leftMargin: windowIconOnTheRight ? 0 : iconMarginForAnchor + iconAndTextSpacing + activeWindowListView.buttonsBetweenAddition anchors.top: parent.top anchors.bottom: parent.bottom verticalAlignment: Text.AlignVCenter text: plasmoid.configuration.noWindowText wrapMode: Text.Wrap width: computedWidth elide: noElide ? Text.ElideNone : Text.ElideRight visible: plasmoid.configuration.showWindowTitle font.pixelSize: fontPixelSize font.pointSize: -1 font.weight: fontBold || (appmenuBoldTitleWhenMenuDisplayed && appmenu.visible) ? Font.Bold : theme.defaultFont.weight font.family: fontFamily || theme.defaultFont.family onTextChanged: { font.pixelSize = fontPixelSize allowFontSizeChange = 3 } onNoElideChanged: { font.pixelSize = fontPixelSize allowFontSizeChange = 3 } onPaintedHeightChanged: { if (allowFontSizeChange > 0 && noElide && paintedHeight > properHeight) { var newPixelSize = (properHeight / paintedHeight) * fontPixelSize font.pixelSize = newPixelSize < minimumPixelSize ? minimumPixelSize : newPixelSize } allowFontSizeChange-- } } } } function replaceTitle(title) { if (!plasmoid.configuration.useWindowTitleReplace) { return title } return title.replace(new RegExp(plasmoid.configuration.replaceTextRegex), plasmoid.configuration.replaceTextReplacement); } MouseArea { anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.MiddleButton onEntered: { mouseHover = true controlButtonsArea.mouseInWidget = showControlButtons && !noWindowActive } onExited: { mouseHover = false controlButtonsArea.mouseInWidget = false } onWheel: { if (wheel.angleDelta.y > 0) { if (wheelUpMaximizes) { setMaximized(true) } } else { if (wheelDownMinimizes) { setMinimized() } else if (wheelDownUnmaximizes) { setMaximized(false) } } } onDoubleClicked: { if (doubleClickMaximizes && mouse.button == Qt.LeftButton) { toggleMaximized() } } onClicked: { if (chosenLeftClickSource !== '' && !doubleClickMaximizes && mouse.button == Qt.LeftButton) { shortcutDS.connectedSources.push(chosenLeftClickSource) controlButtonsArea.mouseInWidget = false return } if (mouse.button == Qt.MiddleButton) { if (middleClickFullscreen) { toggleFullscreen() } else if (middleClickClose) { toggleClose() } } } PlasmaCore.ToolTipArea { anchors.fill: parent active: tooltipTextType > 0 && tooltipText !== '' interactive: true location: plasmoid.location mainItem: Row { spacing: 0 Layout.minimumWidth: fullText.width + units.largeSpacing Layout.minimumHeight: childrenRect.height Layout.maximumWidth: Layout.minimumWidth Layout.maximumHeight: Layout.minimumHeight Item { width: units.largeSpacing / 2 height: 2 } PlasmaComponents.Label { id: fullText text: tooltipText } } } AppMenu { id: appmenu } ListView { id: controlButtonsArea property bool mouseInWidget: false property double controlButtonsHeight: parent.height * buttonSize property double buttonsBetweenMargin: buttonsBetweenIconAndText ? activeWindowListView.appmenuOffsetLeft + activeWindowListView.appmenuOffsetRight + iconItem.width + iconAndTextSpacing : 0 orientation: ListView.Horizontal - visible: showControlButtons && (doNotHideControlButtons || mouseInWidget) && (currentWindowMaximized || !showButtonOnlyWhenMaximized) && !noWindowActive + visible: showControlButtons && (doNotHideControlButtons || mouseInWidget || appmenu.appmenuOpened) && (currentWindowMaximized || !showButtonOnlyWhenMaximized) && !noWindowActive spacing: controlButtonsSpacing height: buttonsVerticalCenter ? parent.height : controlButtonsHeight width: controlButtonsHeight + ((controlButtonsModel.count - 1) * (controlButtonsHeight + controlButtonsSpacing)) anchors.top: parent.top anchors.left: parent.left anchors.leftMargin: buttonsBetweenIconAndText ? (windowIconOnTheRight ? parent.width - width - buttonsBetweenMargin : buttonsBetweenMargin) : ((bp === 1 || bp === 3) ? parent.width - width : 0) anchors.topMargin: (bp === 2 || bp === 3) ? parent.height - height : 0 model: controlButtonsModel delegate: ControlButton { } } } ListModel { id: controlButtonsModel } function addButton(preparedArray, buttonName) { if (buttonName === 'close') { preparedArray.push({ iconName: 'close', windowOperation: 'close' }); } else if (buttonName === 'maximize' && showMaximize) { preparedArray.push({ iconName: 'maximize', windowOperation: 'toggleMaximized' }); } else if (buttonName === 'minimize' && showMinimize) { preparedArray.push({ iconName: 'minimize', windowOperation: 'toggleMinimized' }); } else if ((buttonName === 'pin' || buttonName === 'alldesktops') && showPinToAllDesktops) { preparedArray.push({ iconName: 'alldesktops', windowOperation: 'togglePinToAllDesktops' }); } } function initializeControlButtonsModel() { var preparedArray = [] buttonOrder.split('|').forEach(function (buttonName) { addButton(preparedArray, buttonName); }); controlButtonsModel.clear() if (bp === 1 || bp === 3) { for (var i = preparedArray.length - 1; i >= 0; i--) { controlButtonsModel.append(preparedArray[i]) } } else { for (var i = 0; i < preparedArray.length; i++) { controlButtonsModel.append(preparedArray[i]) } } } function performActiveWindowAction(windowOperation) { if (bp === 4 || !controlButtonsArea.visible) { return; } if (windowOperation === 'close') { toggleClose() } else if (windowOperation === 'toggleMaximized') { toggleMaximized() } else if (windowOperation === 'toggleMinimized') { toggleMinimized() } else if (windowOperation === 'togglePinToAllDesktops') { togglePinToAllDesktops() } } function action_close() { toggleClose() } function action_maximise() { toggleMaximized() } function action_minimise() { toggleMinimized() } function action_pinToAllDesktops() { togglePinToAllDesktops() } function action_reloadTheme() { plasmoid.nativeInterface.refreshAuroraeTheme(); } function actionTriggered(actionName) { if (actionName.indexOf("switchToActivity_") == 0) { var activityIndex = actionName.replace("switchToActivity_", "") var activityId = activityInfo.runningActivities()[activityIndex] activityModel.setCurrentActivity(activityId, function() {}); } } function reAddActivityActions() { plasmoid.removeAction("separator1") for (var i = 0; i < activityActionCount; i++) { plasmoid.removeAction('switchToActivity_' + i) } plasmoid.removeAction("separator2") var runningActivities = activityInfo.runningActivities() activityActionCount = runningActivities.length if (activityActionCount === 0) { return } plasmoid.setActionSeparator("separator1") activityInfo.runningActivities().forEach(function (activityId, index) { if (activityId === activityInfo.currentActivity) { return; } var activityName = activityInfo.activityName(activityId) plasmoid.setAction('switchToActivity_' + index, i18n('Switch to activity: %1', activityName), 'preferences-activities') }) plasmoid.setActionSeparator("separator2") } Component.onCompleted: { initializeControlButtonsModel() updateActiveWindowInfo() plasmoid.setAction('close', i18n('Close'), 'window-close'); plasmoid.setAction('maximise', i18n('Toggle Maximise'), 'arrow-up-double'); plasmoid.setAction('minimise', i18n('Minimise'), 'draw-arrow-down'); plasmoid.setAction('pinToAllDesktops', i18n('Toggle Pin To All Desktops'), 'window-pin'); plasmoid.setActionSeparator("separator0") plasmoid.setAction('reloadTheme', i18n('Reload Theme'), 'system-reboot'); reAddActivityActions() } onShowMaximizeChanged: initializeControlButtonsModel() onShowMinimizeChanged: initializeControlButtonsModel() onShowPinToAllDesktopsChanged: initializeControlButtonsModel() onBpChanged: initializeControlButtonsModel() onButtonOrderChanged: initializeControlButtonsModel() PlasmaCore.DataSource { id: shortcutDS engine: 'executable' property string presentWindows: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "Expose"' property string presentWindowsAll: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeAll"' property string presentWindowsClass: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeClass"' connectedSources: [] onNewData: { connectedSources.length = 0 } } }