diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 52f1d4f..d268134 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -1,35 +1,35 @@ import QtQuick 2.2 import org.kde.plasma.configuration 2.0 ConfigModel { ConfigCategory { name: i18n("Layout") icon: "preferences-desktop-color" source: "config/ConfigLayout.qml" } ConfigCategory { name: i18n("Behaviour") icon: "preferences-desktop" source: "config/ConfigBehaviour.qml" } ConfigCategory { name: i18n("Title and Icon") - icon: "preferences-desktop-color" + icon: "preferences-system-windows" source: "config/ConfigTitleAndIcon.qml" } ConfigCategory { name: i18n("Buttons") icon: "preferences-activities" source: "config/ConfigButtons.qml" } ConfigCategory { name: i18n("Application Menu") icon: "application-menu" source: "config/ConfigAppMenu.qml" } ConfigCategory { name: i18n("Mouse Control") icon: "preferences-desktop-mouse" source: "config/ConfigMouseControl.qml" } } diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 3963f5b..99fed7c 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -1,228 +1,228 @@ icon|title|menu|buttons 5.0 0 true false 1 0 true true 0 0 true true 0 0 false false 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 + + 1.0 false false false false close|maximize|minimize|pin false 10 0.5 0 true false 1 true 1.0 true 0 0 false 0 diff --git a/package/contents/ui/WindowTitle.qml b/package/contents/ui/WindowTitle.qml index 3170b34..885b39b 100644 --- a/package/contents/ui/WindowTitle.qml +++ b/package/contents/ui/WindowTitle.qml @@ -1,76 +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 string textFontFamily: plasmoid.configuration.textFontFamily 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 || (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 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 + font.family: textFontFamily || theme.defaultFont.family 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/code/profiles.js b/package/contents/ui/code/profiles.js new file mode 100644 index 0000000..e8dbc0f --- /dev/null +++ b/package/contents/ui/code/profiles.js @@ -0,0 +1,122 @@ +var ITEMS = [ + { + "title": "Unity", + "configuration": { + "horizontalScreenWidthPercent": 0.25, + + "controlPartOrder": "icon|title|buttons|menu", + "controlPartSpacing": 5.0, + "controlPartButtonsShowOnMouseIn": true, + "controlPartButtonsShowOnMouseOut": false, + "controlPartButtonsPosition": 1, + "controlPartButtonsHorizontalAlignment": 0, + "controlPartIconShowOnMouseIn": false, + "controlPartIconShowOnMouseOut": true, + "controlPartIconPosition": 0, + "controlPartIconHorizontalAlignment": 0, + "controlPartTitleShowOnMouseIn": false, + "controlPartTitleShowOnMouseOut": true, + "controlPartTitlePosition": 0, + "controlPartTitleHorizontalAlignment": 0, + "controlPartMenuShowOnMouseIn": true, + "controlPartMenuShowOnMouseOut": false, + "controlPartMenuPosition": 1, + "controlPartMenuHorizontalAlignment": 0, + + "textFontBold": 1, + + "buttonOrder": "close|maximize|minimize|alldesktops", + "showMaximize": true, + "showMinimize": true, + "showPinToAllDesktops": false, + "showButtonOnlyWhenMaximized": false, + "controlButtonsSpacing": 0, + "buttonSize": 1, + "buttonsVerticalPosition": 1, + + "appmenuFontBold": false, + "appmenuSeparatorEnabled": false, + "appmenuVerticalPosition": 1 + } + }, + { + "title": "One Liner", + "configuration": { + "horizontalScreenWidthPercent": 0.33, + + "controlPartOrder": "buttons|icon|title|menu", + "controlPartSpacing": 5.0, + "controlPartButtonsShowOnMouseIn": true, + "controlPartButtonsShowOnMouseOut": true, + "controlPartButtonsPosition": 0, + "controlPartButtonsHorizontalAlignment": 0, + "controlPartIconShowOnMouseIn": true, + "controlPartIconShowOnMouseOut": true, + "controlPartIconPosition": 0, + "controlPartIconHorizontalAlignment": 0, + "controlPartTitleShowOnMouseIn": true, + "controlPartTitleShowOnMouseOut": true, + "controlPartTitlePosition": 0, + "controlPartTitleHorizontalAlignment": 0, + "controlPartMenuShowOnMouseIn": true, + "controlPartMenuShowOnMouseOut": true, + "controlPartMenuPosition": 0, + "controlPartMenuHorizontalAlignment": 0, + + "textFontBold": 0, + + "buttonOrder": "close|maximize|minimize|alldesktops", + "showMaximize": true, + "showMinimize": true, + "showPinToAllDesktops": false, + "showButtonOnlyWhenMaximized": false, + "controlButtonsSpacing": 0, + "buttonSize": 1, + "buttonsVerticalPosition": 1, + + "appmenuFontBold": false, + "appmenuSeparatorEnabled": true, + "appmenuVerticalPosition": 1 + } + }, + { + "title": "Thick Panel", + "configuration": { + "horizontalScreenWidthPercent": 0.20, + + "controlPartOrder": "icon|title|menu|buttons", + "controlPartSpacing": 5.0, + "controlPartButtonsShowOnMouseIn": true, + "controlPartButtonsShowOnMouseOut": false, + "controlPartButtonsPosition": 2, + "controlPartButtonsHorizontalAlignment": 0, + "controlPartIconShowOnMouseIn": false, + "controlPartIconShowOnMouseOut": true, + "controlPartIconPosition": 0, + "controlPartIconHorizontalAlignment": 0, + "controlPartTitleShowOnMouseIn": false, + "controlPartTitleShowOnMouseOut": true, + "controlPartTitlePosition": 0, + "controlPartTitleHorizontalAlignment": 0, + "controlPartMenuShowOnMouseIn": true, + "controlPartMenuShowOnMouseOut": false, + "controlPartMenuPosition": 2, + "controlPartMenuHorizontalAlignment": 0, + + "textFontBold": 0, + + "buttonOrder": "close|maximize|minimize|alldesktops", + "showMaximize": true, + "showMinimize": true, + "showPinToAllDesktops": false, + "showButtonOnlyWhenMaximized": false, + "controlButtonsSpacing": 5, + "buttonSize": 0.4, + "buttonsVerticalPosition": 0, + + "appmenuFontBold": false, + "appmenuSeparatorEnabled": false, + "appmenuVerticalPosition": 2 + } + } +] \ No newline at end of file diff --git a/package/contents/ui/config/ConfigLayout.qml b/package/contents/ui/config/ConfigLayout.qml index 98c8121..4db5232 100644 --- a/package/contents/ui/config/ConfigLayout.qml +++ b/package/contents/ui/config/ConfigLayout.qml @@ -1,433 +1,480 @@ import QtQuick 2.2 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQml.Models 2.1 +import "../code/profiles.js" as Profiles 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 + // properties from other config pages + // we need them here to be able to apply profiles from this config page + property bool cfg_textFontBold + property string cfg_buttonOrder + property bool cfg_showMaximize + property bool cfg_showMinimize + property bool cfg_showPinToAllDesktops + property bool cfg_showButtonOnlyWhenMaximized + property double cfg_controlButtonsSpacing + property double cfg_buttonSize + property int cfg_buttonsVerticalPosition + property bool cfg_appmenuFontBold + property bool cfg_appmenuSeparatorEnabled + property int cfg_appmenuVerticalPosition + 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) } + onCfg_controlPartOrderChanged: sortPartOrder() + GridLayout { columns: 3 Label { text: i18n('Plasmoid version: ') + '1.8.0-git' Layout.alignment: Qt.AlignRight Layout.columnSpan: 3 } + Label { + text: i18n('Profiles:') + Layout.alignment: Qt.AlignLeft + } + ComboBox { + id: profilesCombo + model: [] + onCurrentIndexChanged: { + if (currentIndex < 1) { + return + } + var item = Profiles.ITEMS[currentIndex - 1] + print('setting profile: ' + item.title) + var config = item.configuration + for (var key in config) { + var configPropName = 'cfg_' + key + if (configPropName in configLayout) { + configLayout[configPropName] = config[key] + } + } + } + } + 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 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('On mouse in') } Item { width: 2 height: 2 } CheckBox { id: controlPartIconShowOnMouseOut text: i18n('On mouse out') } 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('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('On mouse in') } Item { width: 2 height: 2 } CheckBox { id: controlPartButtonsShowOnMouseOut text: i18n('On mouse out') } 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('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('On mouse in') } Item { width: 2 height: 2 } CheckBox { id: controlPartTitleShowOnMouseOut text: i18n('On mouse out') } 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('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('On mouse in') } Item { width: 2 height: 2 } CheckBox { id: controlPartMenuShowOnMouseOut text: i18n('On mouse out') } 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('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() + var profileNames = ['Default'] + Profiles.ITEMS.forEach(function (item) { + print('profile: ' + item.title) + profileNames.push(item.title) + }) + profilesCombo.model = profileNames } } diff --git a/package/contents/ui/config/ConfigTitleAndIcon.qml b/package/contents/ui/config/ConfigTitleAndIcon.qml index 45b6d7f..9993351 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 + property string cfg_textFontFamily + property alias cfg_textFontSizeScale: textFontSizeScale.value /* copied from /usr/share/plasma/plasmoids/org.kde.plasma.digitalclock/contents/ui/configAppearance.qml */ - onCfg_fontFamilyChanged: { + onCfg_textFontFamilyChanged: { // HACK by the time we populate our model and/or the ComboBox is finished the value is still undefined - if (cfg_fontFamily) { + if (cfg_textFontFamily) { for (var i = 0, j = fontsModel.count; i < j; ++i) { - if (fontsModel.get(i).value == cfg_fontFamily) { - fontFamilyComboBox.currentIndex = i + if (fontsModel.get(i).value == cfg_textFontFamily) { + textFontFamilyComboBox.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(); + cfg_textFontFamilyChanged(); } } GridLayout { columns: 2 Label { 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 + id: textFontFamilyComboBox // 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 + cfg_textFontFamily = current.value //appearancePage.configurationChanged() - console.log('change: ' + cfg_fontFamily) + console.log('change: ' + cfg_textFontFamily) } } } Label { text: i18n("Font size scale:") Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } SpinBox { - id: fontSizeScale + id: textFontSizeScale 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 b3f29f1..fa2b574 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -1,619 +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 double fontPixelSize: theme.defaultFont.pixelSize * plasmoid.configuration.textFontSizeScale 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) return plasmoid.configuration['controlPart' + configName + 'Position'] } /* * Alignment can be: * 0 ... left * 1 ... right */ function getAlignment(itemName) { var configName = getConfigName(itemName) 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') { 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 (menuItem.useUpPossibleWidth) { titleItem.recommendedMaxWidth = getMaxWidth('title') menuItem.recommendedMaxWidth = getMaxWidth('menu') } else { 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) } 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)) 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 } } }