diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 8b38b91..3963f5b 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -1,234 +1,228 @@ - buttons|icon|title|menu + icon|title|menu|buttons 5.0 0 true - true + false - 0 + 1 0 true true 0 0 true true 0 0 - true + false - true + false - 0 + 1 0 false false 0.2 0.0 true 0 0 0 false ^(.*)\s*[—–\-:]\s*(Mozilla )?([^—–\-:]+)$ $3 — $1 Plasma Desktop :: %activity% false 1000 0 1 false false false false close|maximize|minimize|pin false 10 0.5 0 true false - - false - 1 true - - 0.1 - 1.0 true 0 0 false 0 diff --git a/package/contents/ui/AppMenu.qml b/package/contents/ui/AppMenu.qml index 5a64640..6c0075f 100644 --- a/package/contents/ui/AppMenu.qml +++ b/package/contents/ui/AppMenu.qml @@ -1,159 +1,194 @@ 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 MouseArea { id: appmenu property bool mouseInWidget: appmenuOpened || appmenu.containsMouse property bool appmenuEnabled: plasmoid.configuration.controlPartMenuShowOnMouseIn || plasmoid.configuration.controlPartMenuShowOnMouseOut property bool appmenuFillHeight: plasmoid.configuration.appmenuFillHeight property bool appmenuFontBold: plasmoid.configuration.appmenuFontBold property bool appmenuEnabledAndNonEmpty: appmenuEnabled && appMenuModel !== null && appMenuModel.menuAvailable property bool appmenuOpened: appmenuEnabled && plasmoid.nativeInterface.currentIndex > -1 property var appMenuModel: null - - visible: appmenuEnabledAndNonEmpty && !main.noWindowActive + property int appmenuVerticalPosition: plasmoid.configuration.appmenuVerticalPosition; property bool showItem property double recommendedMaxWidth + property bool useUpPossibleWidth: main.useUpWidthItem === 1 + property bool doNotRestrictWidth: useUpPossibleWidth && autoFillWidth + property double innerItemWidth: buttonGrid.implicitWidth + visible: appmenuEnabledAndNonEmpty && !main.noWindowActive opacity: showItem ? 1 : 0 width: recommendedMaxWidth + signal contentChanged() + + Timer { + id: contentChangedTimer + interval: 100 + onTriggered: contentChanged() + } + + onInnerItemWidthChanged: { + contentChangedTimer.restart() + } + + onRecommendedMaxWidthChanged: { + width = undefined + if (useUpPossibleWidth || (innerItemWidth > recommendedMaxWidth)) { + width = recommendedMaxWidth + } + print('menu: width set to ' + width) + } + + onUseUpPossibleWidthChanged: recommendedMaxWidthChanged() + + onDoNotRestrictWidthChanged: { + if (doNotRestrictWidth) { + width = undefined + } else { + recommendedMaxWidthChanged() + } + } + + y: appmenuVerticalPosition === 0 ? 0 : main.height - buttonGrid.implicitHeight + hoverEnabled: true GridLayout { id: buttonGrid Layout.minimumWidth: implicitWidth Layout.minimumHeight: implicitHeight flow: GridLayout.LeftToRight rowSpacing: 0 columnSpacing: 0 anchors.top: parent.top anchors.left: parent.left 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.top: appmenuButtonBackground.top anchors.bottom: appmenuButtonBackground.bottom verticalAlignment: Text.AlignVCenter anchors.horizontalCenter: appmenuButtonBackground.horizontalCenter font.pixelSize: main.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' } } } } 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/WindowIcon.qml b/package/contents/ui/WindowIcon.qml index 7d5d994..5aff040 100644 --- a/package/contents/ui/WindowIcon.qml +++ b/package/contents/ui/WindowIcon.qml @@ -1,16 +1,14 @@ import QtQuick 2.2 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.IconItem { id: iconItem width: parent.height height: parent.height source: plasmoid.configuration.noWindowIcon - - opacity: menuItem.showItem ? plasmoid.configuration.appmenuIconAndTextOpacity : 1 } diff --git a/package/contents/ui/WindowTitle.qml b/package/contents/ui/WindowTitle.qml index 9a051ac..3170b34 100644 --- a/package/contents/ui/WindowTitle.qml +++ b/package/contents/ui/WindowTitle.qml @@ -1,75 +1,76 @@ import QtQuick 2.2 import QtGraphicalEffects 1.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.plasma.components 2.0 as PlasmaComponents PlasmaComponents.Label { id: titleItem property double properHeight: parent.height property int fontBold: plasmoid.configuration.textFontBold property string fontFamily: plasmoid.configuration.fontFamily property int fitText: plasmoid.configuration.fitText property bool noElide: fitText === 2 || (fitText === 1 && mainMouseArea.containsMouse) property int allowFontSizeChange: 3 property int minimumPixelSize: 8 property bool limitTextWidth: plasmoid.configuration.limitTextWidth property int textWidthLimit: plasmoid.configuration.textWidthLimit property double recommendedMaxWidth property bool useUpPossibleWidth: main.useUpWidthItem === 0 property bool doNotRestrictWidth: useUpPossibleWidth && autoFillWidth + signal contentChanged() + onRecommendedMaxWidthChanged: { var maxWidth = limitTextWidth ? Math.min(textWidthLimit, recommendedMaxWidth) : recommendedMaxWidth width = undefined - if (useUpPossibleWidth || (limitTextWidth && implicitWidth > maxWidth)) { + if (useUpPossibleWidth || (implicitWidth > maxWidth)) { width = maxWidth } + print('title: width set to ' + width) } onUseUpPossibleWidthChanged: recommendedMaxWidthChanged() onDoNotRestrictWidthChanged: { if (doNotRestrictWidth) { width = undefined } else { recommendedMaxWidthChanged() } } verticalAlignment: Text.AlignVCenter horizontalAlignment: plasmoid.configuration.controlPartTitleHorizontalAlignment === 0 ? Text.AlignLeft : Text.AlignRight text: plasmoid.configuration.noWindowText wrapMode: Text.Wrap - //width: recommendedMaxWidth height: properHeight elide: noElide ? Text.ElideNone : Text.ElideRight font.pixelSize: fontPixelSize font.pointSize: -1 font.weight: fontBold === 1 || (fontBold === 2 && menuItem.showItem) ? Font.Bold : theme.defaultFont.weight font.family: fontFamily || theme.defaultFont.family - opacity: menuItem.showItem ? plasmoid.configuration.appmenuIconAndTextOpacity : 1 - onTextChanged: { font.pixelSize = fontPixelSize allowFontSizeChange = 3 recommendedMaxWidthChanged() + contentChanged() } 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-- } } \ No newline at end of file diff --git a/package/contents/ui/config/ConfigAppMenu.qml b/package/contents/ui/config/ConfigAppMenu.qml index 6b77f71..eb42b22 100644 --- a/package/contents/ui/config/ConfigAppMenu.qml +++ b/package/contents/ui/config/ConfigAppMenu.qml @@ -1,76 +1,102 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 Item { property alias cfg_appmenuFontBold: appmenuFontBold.checked - property alias cfg_appmenuFillHeight: appmenuFillHeight.checked - property alias cfg_appmenuVerticalPosition: appmenuVerticalPosition.currentIndex + property int cfg_appmenuVerticalPosition property alias cfg_appmenuSeparatorEnabled: appmenuSeparatorEnabled.checked - property alias cfg_appmenuIconAndTextOpacity: appmenuIconAndTextOpacity.value property alias cfg_appmenuButtonTextSizeScale: appmenuButtonTextSizeScale.value + onCfg_appmenuVerticalPositionChanged: { + switch (cfg_appmenuVerticalPosition) { + case 0: + appmenuVertialPositionGroup.current = topRadio; + break; + case 1: + appmenuVertialPositionGroup.current = fillHeightRadio; + break; + case 2: + appmenuVertialPositionGroup.current = bottomRadio; + break; + default: + appmenuVertialPositionGroup.current = topRadio; + } + } + + Component.onCompleted: { + cfg_appmenuVerticalPositionChanged() + } + + ExclusiveGroup { + id: appmenuVertialPositionGroup + } + GridLayout { columns: 2 Item { width: 2 - height: 10 + height: units.largeSpacing Layout.columnSpan: 2 } + Item { + width: 2 + height: 2 + Layout.rowSpan: 2 + } + CheckBox { id: appmenuFontBold text: i18n("Bold font") - Layout.columnSpan: 2 } CheckBox { - id: appmenuFillHeight - text: i18n("Fill height") - Layout.columnSpan: 2 + id: appmenuSeparatorEnabled + text: i18n("Show separator") } Label { text: i18n('Vertical position:') Layout.alignment: Qt.AlignRight } - ComboBox { - id: appmenuVerticalPosition - model: [i18n('Top'), i18n('Bottom')] - enabled: !appmenuFillHeight.checked + RadioButton { + id: topRadio + exclusiveGroup: appmenuVertialPositionGroup + text: i18n("Top") + onCheckedChanged: if (checked) cfg_appmenuVerticalPosition = 0; } - - CheckBox { - id: appmenuSeparatorEnabled - text: i18n("Show separator") - Layout.columnSpan: 2 + Item { + width: 2 + height: 2 + Layout.rowSpan: 2 } - - Label { - text: i18n('Icon and text opacity:') - Layout.alignment: Qt.AlignRight + RadioButton { + id: fillHeightRadio + exclusiveGroup: appmenuVertialPositionGroup + text: i18n("Fill height") + onCheckedChanged: if (checked) cfg_appmenuVerticalPosition = 1; } - SpinBox { - id: appmenuIconAndTextOpacity - decimals: 2 - stepSize: 0.1 - minimumValue: 0 - maximumValue: 1 + RadioButton { + id: bottomRadio + exclusiveGroup: appmenuVertialPositionGroup + text: i18n("Bottom") + onCheckedChanged: if (checked) cfg_appmenuVerticalPosition = 2; } 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/config/ConfigButtons.qml b/package/contents/ui/config/ConfigButtons.qml index b48e3c9..92e962b 100644 --- a/package/contents/ui/config/ConfigButtons.qml +++ b/package/contents/ui/config/ConfigButtons.qml @@ -1,250 +1,250 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQml.Models 2.1 Item { property string cfg_buttonOrder property alias cfg_showMinimize: showMinimize.checked property alias cfg_showMaximize: showMaximize.checked property alias cfg_showPinToAllDesktops: showPinToAllDesktops.checked property alias cfg_showButtonOnlyWhenMaximized: showButtonOnlyWhenMaximized.checked property alias cfg_buttonSize: buttonSize.value property int cfg_buttonsVerticalPosition property alias cfg_controlButtonsSpacing: controlButtonsSpacing.value property alias cfg_automaticButtonThemeEnabled: automaticButtonThemeEnabled.checked property alias cfg_customAuroraeThemePath: customAuroraeThemePath.text onCfg_buttonsVerticalPositionChanged: { switch (cfg_buttonsVerticalPosition) { case 0: buttonsVertialPositionGroup.current = topRadio; break; case 1: buttonsVertialPositionGroup.current = middleRadio; break; case 2: buttonsVertialPositionGroup.current = bottomRadio; break; default: buttonsVertialPositionGroup.current = topRadio; } } Component.onCompleted: { cfg_buttonsVerticalPositionChanged() print('intially calling sortButtonOrder()') sortButtonOrder() } ListModel { id: buttonsToSpend ListElement { name: 'close' iconName: 'close' } ListElement { name: 'minimize' iconName: 'minimize' } ListElement { name: 'maximize' iconName: 'maximize' } ListElement { name: 'alldesktops' iconName: 'alldesktops' } } function sortButtonOrder() { cfg_buttonOrder.split('|').forEach(function (itemId, index) { if (itemId === 'close') { print('adding ' + itemId); buttonOrder.model.insert(index, buttonsToSpend.get(0)); } else if (itemId === 'minimize') { buttonOrder.model.insert(index, buttonsToSpend.get(1)); print('adding ' + itemId); } else if (itemId === 'maximize') { buttonOrder.model.insert(index, buttonsToSpend.get(2)); print('adding ' + itemId); } else if (itemId === 'pin' || itemId === 'alldesktops') { buttonOrder.model.insert(index, buttonsToSpend.get(3)); print('adding ' + itemId); } }); } ExclusiveGroup { id: buttonsVertialPositionGroup } GridLayout { columns: 2 Label { text: i18n("Button order:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } OrderableListView { id: buttonOrder height: units.gridUnit * 2 width: height * 4 model: ListModel { // will be filled initially by sortButtonOrder() method } orientation: ListView.Horizontal itemWidth: width / 4 itemHeight: itemWidth onModelOrderChanged: { var orderStr = ''; for (var i = 0; i < model.count; i++) { var item = model.get(i) if (orderStr.length > 0) { orderStr += '|'; } orderStr += item.name; } cfg_buttonOrder = orderStr; print('written: ' + cfg_buttonOrder); } } Item { width: 2 height: 10 Layout.columnSpan: 2 } Label { text: i18n("Show:") Layout.alignment: Qt.AlignRight } CheckBox { id: showMinimize text: i18n("Minimize button") } Item { width: 2 height: 2 Layout.rowSpan: 2 } CheckBox { id: showMaximize text: i18n("Maximize button") } CheckBox { id: showPinToAllDesktops text: i18n("Pin to all desktops") } Item { width: 2 height: 10 Layout.columnSpan: 2 } Label { text: i18n("Behaviour:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } CheckBox { id: showButtonOnlyWhenMaximized text: i18n("Show only when maximized") } Item { width: 2 height: 10 Layout.columnSpan: 2 } Label { text: i18n("Buttons spacing:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } Slider { id: controlButtonsSpacing stepSize: 1 minimumValue: 0 maximumValue: 20 tickmarksEnabled: true width: parent.width } Label { text: i18n("Button size:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } Slider { id: buttonSize stepSize: 0.1 minimumValue: 0.1 tickmarksEnabled: true width: parent.width } Label { - text: i18n("Position:") + text: i18n("Vertical position:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } RadioButton { id: topRadio exclusiveGroup: buttonsVertialPositionGroup text: i18n("Top") onCheckedChanged: if (checked) cfg_buttonsVerticalPosition = 0; enabled: buttonSize.value < 1 } Item { width: 2 height: 2 Layout.rowSpan: 4 } RadioButton { id: middleRadio exclusiveGroup: buttonsVertialPositionGroup text: i18n("Middle") onCheckedChanged: if (checked) cfg_buttonsVerticalPosition = 1; enabled: buttonSize.value < 1 } RadioButton { id: bottomRadio exclusiveGroup: buttonsVertialPositionGroup text: i18n("Bottom") onCheckedChanged: if (checked) cfg_buttonsVerticalPosition = 2; enabled: buttonSize.value < 1 } Item { width: 2 height: 10 Layout.columnSpan: 2 } Label { text: i18n("Theme") Layout.columnSpan: parent.columns font.bold: true } CheckBox { id: automaticButtonThemeEnabled text: i18n("Automatic") } TextField { id: customAuroraeThemePath placeholderText: i18n("Absolute path to aurorae button theme folder") Layout.preferredWidth: 350 onTextChanged: cfg_customAuroraeThemePath = text enabled: !automaticButtonThemeEnabled.checked } } } diff --git a/package/contents/ui/config/ConfigLayout.qml b/package/contents/ui/config/ConfigLayout.qml index a0fddee..98c8121 100644 --- a/package/contents/ui/config/ConfigLayout.qml +++ b/package/contents/ui/config/ConfigLayout.qml @@ -1,421 +1,433 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQml.Models 2.1 Item { id: configLayout property string cfg_controlPartOrder property alias cfg_controlPartSpacing: controlPartSpacing.value property alias cfg_useUpWidthItem: useUpWidthItem.currentIndex // GENERATED config (start) property alias cfg_controlPartIconShowOnMouseIn: controlPartIconShowOnMouseIn.checked property alias cfg_controlPartIconShowOnMouseOut: controlPartIconShowOnMouseOut.checked property alias cfg_controlPartIconPosition: controlPartIconPosition.currentIndex property alias cfg_controlPartIconHorizontalAlignment: controlPartIconHorizontalAlignment.currentIndex property alias cfg_controlPartTitleShowOnMouseIn: controlPartTitleShowOnMouseIn.checked property alias cfg_controlPartTitleShowOnMouseOut: controlPartTitleShowOnMouseOut.checked property alias cfg_controlPartTitlePosition: controlPartTitlePosition.currentIndex property alias cfg_controlPartTitleHorizontalAlignment: controlPartTitleHorizontalAlignment.currentIndex property alias cfg_controlPartButtonsShowOnMouseIn: controlPartButtonsShowOnMouseIn.checked property alias cfg_controlPartButtonsShowOnMouseOut: controlPartButtonsShowOnMouseOut.checked property alias cfg_controlPartButtonsPosition: controlPartButtonsPosition.currentIndex property alias cfg_controlPartButtonsHorizontalAlignment: controlPartButtonsHorizontalAlignment.currentIndex property alias cfg_controlPartMenuShowOnMouseIn: controlPartMenuShowOnMouseIn.checked property alias cfg_controlPartMenuShowOnMouseOut: controlPartMenuShowOnMouseOut.checked property alias cfg_controlPartMenuPosition: controlPartMenuPosition.currentIndex property alias cfg_controlPartMenuHorizontalAlignment: controlPartMenuHorizontalAlignment.currentIndex // GENERATED config (end) property alias cfg_controlPartMouseAreaRestrictedToWidget: controlPartMouseAreaRestrictedToWidget.checked property alias cfg_autoFillWidth: autoFillWidth.checked property alias cfg_horizontalScreenWidthPercent: horizontalScreenWidthPercent.value property alias cfg_widthFineTuning: widthFineTuning.value ListModel { id: partsToSpend ListElement { name: 'icon' text: 'Icon' } ListElement { name: 'title' text: 'Title' } ListElement { name: 'buttons' text: 'Buttons' } ListElement { name: 'menu' text: 'Menu' } } function sortPartOrder() { buttonOrder.model.clear() cfg_controlPartOrder.split('|').forEach(function (itemId, index) { var partIndex = -1 print('adding ' + itemId); if (itemId === 'icon') { partIndex = 0 } else if (itemId === 'title') { partIndex = 1 } else if (itemId === 'buttons') { partIndex = 2 } else if (itemId === 'menu') { partIndex = 3 } if (partIndex >= 0) { buttonOrder.model.append(partsToSpend.get(partIndex)); } }); print('model count: ' + buttonOrder.model.count) } GridLayout { columns: 3 Label { text: i18n('Plasmoid version: ') + '1.8.0-git' Layout.alignment: Qt.AlignRight Layout.columnSpan: 3 } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 3 } Label { text: i18n("Item order:") } OrderableListView { id: buttonOrder Layout.columnSpan: 2 itemHeight: units.gridUnit * 2 itemWidth: units.gridUnit * 4 height: itemHeight width: itemWidth * 4 model: ListModel { // will be filled initially by sortButtonOrder() method } orientation: ListView.Horizontal onModelOrderChanged: { var orderStr = ''; for (var i = 0; i < model.count; i++) { var item = model.get(i) if (orderStr.length > 0) { orderStr += '|'; } orderStr += item.name; } cfg_controlPartOrder = orderStr; print('written: ' + cfg_controlPartOrder); } } Label { text: i18n("Item spacing:") } SpinBox { id: controlPartSpacing decimals: 1 stepSize: 0.5 minimumValue: 0.5 maximumValue: 300 Layout.columnSpan: 2 } Label { - text: i18n('Item to use up all possible width:') + text: i18n('Item to use up remaining width:') } ComboBox { id: useUpWidthItem model: [i18n('Title'), i18n('Menu'), i18n('None')] Layout.columnSpan: 2 } // GENERATED controls (start) GridLayout { columns: 2 Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Icon') font.bold: true Layout.columnSpan: 2 } + Label { + text: i18n('Show:') + Layout.alignment: Qt.AlignRight + } CheckBox { id: controlPartIconShowOnMouseIn - text: i18n('Show on mouse in') - Layout.columnSpan: 2 + text: i18n('On mouse in') + } + Item { + width: 2 + height: 2 } - CheckBox { id: controlPartIconShowOnMouseOut - text: i18n('Show on mouse out') - Layout.columnSpan: 2 + text: i18n('On mouse out') } - GridLayout { - columns: 2 - Layout.columnSpan: 2 + Label { + text: i18n('Position:') + Layout.alignment: Qt.AlignRight + enabled: controlPartIconPosition.enabled + } + ComboBox { + id: controlPartIconPosition + model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] enabled: controlPartIconShowOnMouseIn.checked || controlPartIconShowOnMouseOut.checked + } - Label { - text: i18n('Position:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartIconPosition - model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] - } - - Label { - text: i18n('Align:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartIconHorizontalAlignment - model: [i18n('Left'), i18n('Right')] - } + Label { + text: i18n('Align:') + Layout.alignment: Qt.AlignRight + enabled: controlPartIconPosition.enabled + } + ComboBox { + id: controlPartIconHorizontalAlignment + model: [i18n('Left'), i18n('Right')] + enabled: controlPartIconPosition.enabled } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Buttons') font.bold: true Layout.columnSpan: 2 } + Label { + text: i18n('Show:') + Layout.alignment: Qt.AlignRight + } CheckBox { id: controlPartButtonsShowOnMouseIn - text: i18n('Show on mouse in') - Layout.columnSpan: 2 + text: i18n('On mouse in') + } + Item { + width: 2 + height: 2 } - CheckBox { id: controlPartButtonsShowOnMouseOut - text: i18n('Show on mouse out') - Layout.columnSpan: 2 + text: i18n('On mouse out') } - GridLayout { - columns: 2 - Layout.columnSpan: 2 + Label { + text: i18n('Position:') + Layout.alignment: Qt.AlignRight + enabled: controlPartButtonsPosition.enabled + } + ComboBox { + id: controlPartButtonsPosition + model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] enabled: controlPartButtonsShowOnMouseIn.checked || controlPartButtonsShowOnMouseOut.checked + } - Label { - text: i18n('Position:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartButtonsPosition - model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] - } - - Label { - text: i18n('Align:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartButtonsHorizontalAlignment - model: [i18n('Left'), i18n('Right')] - } + Label { + text: i18n('Align:') + Layout.alignment: Qt.AlignRight + enabled: controlPartButtonsPosition.enabled + } + ComboBox { + id: controlPartButtonsHorizontalAlignment + model: [i18n('Left'), i18n('Right')] + enabled: controlPartButtonsPosition.enabled } } Item { width: units.largeSpacing height: units.largeSpacing } GridLayout { columns: 2 Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Title') font.bold: true Layout.columnSpan: 2 } + Label { + text: i18n('Show:') + Layout.alignment: Qt.AlignRight + } CheckBox { id: controlPartTitleShowOnMouseIn - text: i18n('Show on mouse in') - Layout.columnSpan: 2 + text: i18n('On mouse in') + } + Item { + width: 2 + height: 2 } - CheckBox { id: controlPartTitleShowOnMouseOut - text: i18n('Show on mouse out') - Layout.columnSpan: 2 + text: i18n('On mouse out') } - GridLayout { - columns: 2 - Layout.columnSpan: 2 + Label { + text: i18n('Position:') + Layout.alignment: Qt.AlignRight + enabled: controlPartTitlePosition.enabled + } + ComboBox { + id: controlPartTitlePosition + model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] enabled: controlPartTitleShowOnMouseIn.checked || controlPartTitleShowOnMouseOut.checked + } - Label { - text: i18n('Position:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartTitlePosition - model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] - } - - Label { - text: i18n('Align:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartTitleHorizontalAlignment - model: [i18n('Left'), i18n('Right')] - } + Label { + text: i18n('Align:') + Layout.alignment: Qt.AlignRight + enabled: controlPartTitlePosition.enabled + } + ComboBox { + id: controlPartTitleHorizontalAlignment + model: [i18n('Left'), i18n('Right')] + enabled: controlPartTitlePosition.enabled } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Menu') font.bold: true Layout.columnSpan: 2 } + Label { + text: i18n('Show:') + Layout.alignment: Qt.AlignRight + } CheckBox { id: controlPartMenuShowOnMouseIn - text: i18n('Show on mouse in') - Layout.columnSpan: 2 + text: i18n('On mouse in') + } + Item { + width: 2 + height: 2 } - CheckBox { id: controlPartMenuShowOnMouseOut - text: i18n('Show on mouse out') - Layout.columnSpan: 2 + text: i18n('On mouse out') } - GridLayout { - columns: 2 - Layout.columnSpan: 2 + Label { + text: i18n('Position:') + Layout.alignment: Qt.AlignRight + enabled: controlPartMenuPosition.enabled + } + ComboBox { + id: controlPartMenuPosition + model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] enabled: controlPartMenuShowOnMouseIn.checked || controlPartMenuShowOnMouseOut.checked + } - Label { - text: i18n('Position:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartMenuPosition - model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')] - } - - Label { - text: i18n('Align:') - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - } - ComboBox { - id: controlPartMenuHorizontalAlignment - model: [i18n('Left'), i18n('Right')] - } + Label { + text: i18n('Align:') + Layout.alignment: Qt.AlignRight + enabled: controlPartMenuPosition.enabled + } + ComboBox { + id: controlPartMenuHorizontalAlignment + model: [i18n('Left'), i18n('Right')] + enabled: controlPartMenuPosition.enabled } } // GENERATED controls (end) Item { width: units.largeSpacing height: units.largeSpacing Layout.columnSpan: 3 } CheckBox { id: controlPartMouseAreaRestrictedToWidget text: i18n('Restrict mouse area to widget') Layout.columnSpan: 3 } Item { width: units.largeSpacing height: units.largeSpacing Layout.columnSpan: 3 } Label { text: i18n("Width in horizontal panel:") font.bold: true Layout.alignment: Qt.AlignLeft Layout.columnSpan: 3 } CheckBox { id: autoFillWidth text: i18n("Fill width") Layout.columnSpan: 3 } GridLayout { columns: 2 Layout.columnSpan: 3 enabled: !autoFillWidth.checked Slider { id: horizontalScreenWidthPercent stepSize: 0.001 minimumValue: 0.001 maximumValue: 1 Layout.preferredWidth: configLayout.width Layout.columnSpan: 2 } Label { text: i18n("Fine tuning:") Layout.alignment: Qt.AlignRight } SpinBox { id: widthFineTuning decimals: 1 stepSize: 0.5 minimumValue: -100 maximumValue: 100 } } } Component.onCompleted: { sortPartOrder() } } diff --git a/package/contents/ui/config/ConfigTitleAndIcon.qml b/package/contents/ui/config/ConfigTitleAndIcon.qml index a932631..45b6d7f 100644 --- a/package/contents/ui/config/ConfigTitleAndIcon.qml +++ b/package/contents/ui/config/ConfigTitleAndIcon.qml @@ -1,233 +1,233 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore Item { property alias cfg_textType: textTypeCombo.currentIndex property alias cfg_fitText: fitTextCombo.currentIndex property alias cfg_tooltipTextType: tooltipTextTypeCombo.currentIndex property alias cfg_useWindowTitleReplace: useWindowTitleReplace.checked property alias cfg_replaceTextRegex: replaceTextRegex.text property alias cfg_replaceTextReplacement: replaceTextReplacement.text property alias cfg_noWindowText: noWindowText.text property string cfg_noWindowIcon: plasmoid.configuration.noWindowIcon property alias cfg_limitTextWidth: limitTextWidth.checked property alias cfg_textWidthLimit: textWidthLimit.value property alias cfg_textFontBold: textFontBoldCombo.currentIndex property string cfg_fontFamily property alias cfg_fontSizeScale: fontSizeScale.value /* copied from /usr/share/plasma/plasmoids/org.kde.plasma.digitalclock/contents/ui/configAppearance.qml */ onCfg_fontFamilyChanged: { // HACK by the time we populate our model and/or the ComboBox is finished the value is still undefined if (cfg_fontFamily) { for (var i = 0, j = fontsModel.count; i < j; ++i) { if (fontsModel.get(i).value == cfg_fontFamily) { fontFamilyComboBox.currentIndex = i break } } } } ListModel { id: fontsModel Component.onCompleted: { var arr = [ {text: i18nc("Use default font", "Default"), value: ""} ] Qt.fontFamilies().forEach(function (font) { arr.push({text: font, value: font}) }) append(arr) cfg_fontFamilyChanged(); } } GridLayout { columns: 2 Label { - text: i18n('Text') + text: i18n('Title') Layout.alignment: Qt.AlignLeft font.bold: true Layout.columnSpan: 2 } Label { text: i18n('Text type:') Layout.alignment: Qt.AlignRight } ComboBox { id: textTypeCombo model: [i18n('Window title'), i18n('Application name')] } Label { text: i18n('Fit text:') Layout.alignment: Qt.AlignRight } ComboBox { id: fitTextCombo model: [i18n('Just elide'), i18n('Fit on hover'), i18n('Always fit')] } Label { text: i18n('Tooltip text:') Layout.alignment: Qt.AlignRight } ComboBox { id: tooltipTextTypeCombo model: [i18n('No tooltip'), i18n('Window title'), i18n('Application name')] } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Bold text:') Layout.alignment: Qt.AlignRight } ComboBox { id: textFontBoldCombo // ComboBox's sizing is just utterly broken Layout.minimumWidth: units.gridUnit * 10 model: [i18n('Never'), i18n('Always'), i18n('When appmenu is displayed')] } Label { text: i18n('Text font:') Layout.alignment: Qt.AlignRight } ComboBox { id: fontFamilyComboBox // ComboBox's sizing is just utterly broken Layout.minimumWidth: units.gridUnit * 10 model: fontsModel // doesn't autodeduce from model because we manually populate it textRole: "text" onCurrentIndexChanged: { var current = model.get(currentIndex) if (current) { cfg_fontFamily = current.value //appearancePage.configurationChanged() console.log('change: ' + cfg_fontFamily) } } } Label { text: i18n("Font size scale:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } SpinBox { id: fontSizeScale decimals: 2 stepSize: 0.05 minimumValue: 0 maximumValue: 3 } CheckBox { id: limitTextWidth text: i18n('Limit text width') Layout.alignment: Qt.AlignRight } SpinBox { id: textWidthLimit decimals: 0 stepSize: 10 minimumValue: 0 maximumValue: 10000 enabled: limitTextWidth.checked suffix: i18nc('Abbreviation for pixels', 'px') } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } CheckBox { id: useWindowTitleReplace text: '"' + i18n('Window title') + '".replace(/' Layout.alignment: Qt.AlignRight } GridLayout { columns: 4 TextField { id: replaceTextRegex placeholderText: '^(.*)\\s+[—–\\-:]\\s+([^—–\\-:]+)$' Layout.preferredWidth: 270 onTextChanged: cfg_replaceTextRegex = text enabled: useWindowTitleReplace.checked } Label { text: '/, "' } TextField { id: replaceTextReplacement placeholderText: '$2 — $1' Layout.preferredWidth: 100 onTextChanged: cfg_replaceTextReplacement = text enabled: useWindowTitleReplace.checked } Label { text: '");' } } Label { text: i18n('No window text:') Layout.alignment: Qt.AlignRight } GridLayout { columns: 2 TextField { id: noWindowText placeholderText: 'Plasma Desktop :: %activity%' onTextChanged: cfg_noWindowText = text Layout.preferredWidth: 270 } Label { text: i18n('Use %activity% placeholder to show current activity name.') Layout.preferredWidth: 150 wrapMode: Text.Wrap } } Item { width: 2 height: units.largeSpacing Layout.columnSpan: 2 } Label { text: i18n('Icon') Layout.alignment: Qt.AlignLeft font.bold: true Layout.columnSpan: 2 } Label { text: i18n("No window icon:") Layout.alignment: Qt.AlignRight } IconPicker { currentIcon: cfg_noWindowIcon defaultIcon: '' onIconChanged: cfg_noWindowIcon = iconName } } } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 700a99e..b3f29f1 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -1,600 +1,619 @@ /* * 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 bool autoFillWidth: plasmoid.configuration.autoFillWidth property double widthForHorizontalPanel: (Screen.width * horizontalScreenWidthPercent + plasmoid.configuration.widthFineTuning) property int useUpWidthItem: plasmoid.configuration.useUpWidthItem property int textType: plasmoid.configuration.textType property int tooltipTextType: plasmoid.configuration.tooltipTextType property string tooltipText: '' property double fontPixelSize: theme.defaultFont.pixelSize * plasmoid.configuration.fontSizeScale property bool noWindowActive: true property bool currentWindowMaximized: false 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 textColorLight: ((theme.textColor.r + theme.textColor.g + theme.textColor.b) / 3) > 0.5 property bool isActiveWindowPinned: false property bool isActiveWindowMaximized: false property bool controlPartMouseAreaRestrictedToWidget: plasmoid.configuration.controlPartMouseAreaRestrictedToWidget property var activeTaskLocal: null property int activityActionCount: 0 property var itemPartOrder: [] property bool mouseInWidget: mainMouseArea.containsMouse || buttonsItem.mouseInWidget || menuItem.mouseInWidget anchors.fill: parent Layout.fillWidth: 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 Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.status: { if (menuItem.appmenuOpened) { return PlasmaCore.Types.NeedsAttentionStatus; } else if (!menuItem.appmenuOpened && menuItem.appmenuEnabledAndNonEmpty){ return PlasmaCore.Types.ActiveStatus; } else { return PlasmaCore.Types.PassiveStatus; } } // // 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 } function updateTooltip() { if (tooltipTextType === 1) { tooltipText = replaceTitle(activeTask().display || '') } else if (tooltipTextType === 2) { tooltipText = activeTask().AppName || '' } else { tooltipText = '' } } onTooltipTextTypeChanged: updateTooltip() 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 activeTaskLocal = {} if (tasksModel.data(activeTaskIndex, isActive)) { 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) { titleItem.text = composeNoWindowText() iconItem.source = plasmoid.configuration.noWindowIcon } else { titleItem.text = (textType === 1 ? actTask.AppName : null) || 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() } } function getConfigName(itemName) { return itemName.substring(0, 1).toUpperCase() + itemName.substring(1) } /* * Position can be: * 0 ... occupy * 1 ... floating layer (second occupy) * 2 ... absolute */ function getPosition(itemName) { var configName = getConfigName(itemName) - print('getPosition: ' + configName) - print('POS: ' + plasmoid.configuration['controlPart' + configName + 'Position']) return plasmoid.configuration['controlPart' + configName + 'Position'] } /* * Alignment can be: * 0 ... left * 1 ... right */ function getAlignment(itemName) { var configName = getConfigName(itemName) - print('getAlignment: ' + configName) - print('ALI: ' + plasmoid.configuration['controlPart' + configName + 'HorizontalAlignment']) return plasmoid.configuration['controlPart' + configName + 'HorizontalAlignment'] } function isRelevant(itemName) { var configName = getConfigName(itemName) var mouseInConfigName = 'controlPart' + configName + 'ShowOnMouseIn' var mouseOutConfigName = 'controlPart' + configName + 'ShowOnMouseOut' return plasmoid.configuration[mouseInConfigName] || plasmoid.configuration[mouseOutConfigName] } function getItem(itemName) { if (itemName === 'icon') { return iconItem } if (itemName === 'title') { return titleItem } if (itemName === 'menu') { return menuItem } if (itemName === 'buttons') { return buttonsItem } return null } function getItemWidth(itemName) { - if (itemName === 'title' && !titleItem.useUpPossibleWidth) { - return getItem(itemName).implicitWidth + if (itemName === 'title') { + return Math.min(titleItem.implicitWidth, titleItem.recommendedMaxWidth) + } + if (itemName === 'menu') { + return Math.min(menuItem.innerItemWidth, menuItem.recommendedMaxWidth) + } + if (itemName === 'icon' && noWindowActive && !iconItem.source) { + return 0 } return getItem(itemName).width } function getLeftMargin(itemName) { var itemPosition = getPosition(itemName) var itemAlignment = getAlignment(itemName) print('position of ' + itemName + ' is ' + itemPosition) if (itemPosition === 2) { return 0 } var anchorSize = 0 var itemPartOrderArray = itemAlignment === 0 ? itemPartOrder : itemPartOrder.slice().reverse() itemPartOrderArray.some(function (iName, index) { print('iterating: ' + iName) if (iName === itemName) { return true } if (getPosition(iName) === itemPosition && getAlignment(iName) === itemAlignment && isRelevant(iName)) { var currentItemWidth = getItemWidth(iName) print('width of ' + iName + ' is ' + currentItemWidth) anchorSize += currentItemWidth anchorSize += plasmoid.configuration.controlPartSpacing } }); if (itemAlignment === 1) { var computedWidth = autoFillWidth ? main.width : widthForHorizontalPanel anchorSize = computedWidth - anchorSize - getItemWidth(itemName) } print('leftMargin of ' + itemName + ' is ' + anchorSize) return anchorSize } function getMaxWidth(itemName) { var itemPosition = getPosition(itemName) print('getMaxWidth(): position of ' + itemName + ' is ' + itemPosition) if (itemPosition === 2) { return 0 } var computedWidth = autoFillWidth ? main.width : widthForHorizontalPanel + print('available width is ' + computedWidth) + var minWidth = main.height itemPartOrder.forEach(function (iName, index) { print('iterating: ' + iName) if (iName === itemName) { return; } if (getPosition(iName) === itemPosition && isRelevant(iName)) { var currentItemWidth = getItemWidth(iName) print('width of ' + iName + ' is ' + currentItemWidth) computedWidth -= currentItemWidth computedWidth -= plasmoid.configuration.controlPartSpacing } }); print('computedWidth of ' + itemName + ' is ' + computedWidth) + if (computedWidth < minWidth) { + print('computedWidth changed to minWidth: ' + minWidth) + return minWidth + } return computedWidth } function refreshItemPosition() { - if (titleItem.useUpPossibleWidth) { + if (menuItem.useUpPossibleWidth) { titleItem.recommendedMaxWidth = getMaxWidth('title') menuItem.recommendedMaxWidth = getMaxWidth('menu') } else { - titleItem.recommendedMaxWidth = getMaxWidth('title') menuItem.recommendedMaxWidth = getMaxWidth('menu') + titleItem.recommendedMaxWidth = getMaxWidth('title') } iconItem.x = getLeftMargin('icon') titleItem.x = getLeftMargin('title') menuItem.x = getLeftMargin('menu') buttonsItem.x = getLeftMargin('buttons') - textSeparator.x = getLeftMargin('menu') - (plasmoid.configuration.controlPartSpacing / 2) + textSeparator.x = getLeftMargin('menu')// - (plasmoid.configuration.controlPartSpacing / 2) } function replaceTitle(title) { if (!plasmoid.configuration.useWindowTitleReplace) { return title } return title.replace(new RegExp(plasmoid.configuration.replaceTextRegex), plasmoid.configuration.replaceTextReplacement); } onWidthChanged: { if (autoFillWidth) { refreshItemPosition(); } } onWidthForHorizontalPanelChanged: refreshItemPosition() MouseArea { id: mainMouseArea anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.MiddleButton 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) buttonsItem.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 } } } } ListModel { id: controlButtonsModel } WindowIcon { id: iconItem visible: ((mouseInWidget && plasmoid.configuration.controlPartIconShowOnMouseIn) || (!mouseInWidget && plasmoid.configuration.controlPartIconShowOnMouseOut)) onWidthChanged: refreshItemPosition() + onSourceChanged: { + if (!source) { + refreshItemPosition() + } + } } WindowTitle { id: titleItem visible: ((mouseInWidget && plasmoid.configuration.controlPartTitleShowOnMouseIn) || (!mouseInWidget && plasmoid.configuration.controlPartTitleShowOnMouseOut)) - onImplicitWidthChanged: { - if (!titleItem.useUpPossibleWidth) { - refreshItemPosition() - } + onContentChanged: { + print('onContentChanged - TITLE') + refreshItemPosition() } onUseUpPossibleWidthChanged: refreshItemPosition() } AppMenu { id: menuItem property bool mouseIn: controlPartMouseAreaRestrictedToWidget ? menuItem.mouseInWidget : main.mouseInWidget height: main.height showItem: !noWindowActive && ((mouseIn && plasmoid.configuration.controlPartMenuShowOnMouseIn) || (!mouseIn && plasmoid.configuration.controlPartMenuShowOnMouseOut)) + + onContentChanged: { + print('onContentChanged - MENU') + refreshItemPosition() + } + + onUseUpPossibleWidthChanged: refreshItemPosition() } ControlButtons { id: buttonsItem property bool mouseIn: controlPartMouseAreaRestrictedToWidget ? buttonsItem.mouseInWidget : main.mouseInWidget showItem: !noWindowActive && ((mouseIn && plasmoid.configuration.controlPartButtonsShowOnMouseIn) || (!mouseIn && plasmoid.configuration.controlPartButtonsShowOnMouseOut)) onWidthChanged: refreshItemPosition() } Rectangle { id: textSeparator x: 0 anchors.verticalCenter: main.verticalCenter height: 0.8 * parent.height width: 1 visible: plasmoid.configuration.appmenuSeparatorEnabled && menuItem.showItem color: theme.textColor opacity: 0.4 } 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") } property string controlPartOrder: plasmoid.configuration.controlPartOrder onControlPartOrderChanged: refreshControlPartOrder() onUseUpWidthItemChanged: refreshControlPartOrder() function refreshControlPartOrder() { itemPartOrder.length = 0 plasmoid.configuration.controlPartOrder.split('|').forEach(function (itemName, index) { print('itemOrder: ' + itemName) itemPartOrder.push(itemName) print('itemZ: ' + index) getItem(itemName).z = index }); print('itemPartOrder initialized: ' + itemPartOrder) refreshItemPosition() } Component.onCompleted: { refreshControlPartOrder() refreshItemPosition() updateActiveWindowInfo() // actions 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() } 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 } } }