├── .gitignore ├── install ├── reinstall ├── run ├── package ├── contents │ ├── config │ │ ├── config.qml │ │ └── main.xml │ ├── ui │ │ ├── libconfig │ │ │ ├── Label.qml │ │ │ ├── RadioButtonGroup.qml │ │ │ ├── Heading.qml │ │ │ ├── IconField.qml │ │ │ └── AppletIconField.qml │ │ ├── UnityThemeDetector.qml │ │ ├── lib │ │ │ ├── ExecUtil.qml │ │ │ ├── AppletIcon.qml │ │ │ ├── KPackageModel.qml │ │ │ └── DesktopEffectToggle.qml │ │ ├── Unity7Workspaces.qml │ │ ├── Main.qml │ │ └── config │ │ │ └── ConfigGeneral.qml │ └── icons │ │ ├── presentwindows-16px.svg │ │ ├── presentwindows-22px.svg │ │ ├── presentwindows-24px.svg │ │ └── unity7selectedworkspace.svg ├── metadata.desktop └── translate │ ├── build │ ├── ReadMe.md │ ├── template.pot │ ├── pl.po │ ├── nl.po │ ├── plasmoidlocaletest │ └── merge ├── ReadMe.md └── Changelog.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.plasmoid 2 | *.qmlc 3 | *.jsc 4 | *.mo 5 | -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Version 2 3 | 4 | kpackagetool5 -t Plasma/Applet -i package 5 | -------------------------------------------------------------------------------- /reinstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Version 2 3 | 4 | kpackagetool5 -t Plasma/Applet -u package 5 | killall plasmashell 6 | kstart5 plasmashell 7 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Version 5 3 | 4 | # Clear SVG cache 5 | # rm ~/.cache/plasma-svgelements-* 6 | 7 | killall plasmoidviewer 8 | QML_DISABLE_DISK_CACHE=true plasmoidviewer -a package -l topedge -f horizontal -x 0 -y 0 9 | -------------------------------------------------------------------------------- /package/contents/config/config.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import org.kde.plasma.configuration 2.0 3 | 4 | ConfigModel { 5 | ConfigCategory { 6 | name: i18n("General") 7 | icon: "configure" 8 | source: "config/ConfigGeneral.qml" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # Present Windows Button 2 | 3 | https://store.kde.org/p/1181039/ 4 | 5 | A simple button that'll trigger the "Present Windows" desktop effect. It uses the same icon as Windows 10s "Task View" icon. 6 | 7 | ## Screenshots 8 | 9 | ![](https://i.imgur.com/2lpnrr7.png) 10 | 11 | ![](https://i.imgur.com/9RCDAfa.png) 12 | -------------------------------------------------------------------------------- /package/contents/ui/libconfig/Label.qml: -------------------------------------------------------------------------------- 1 | // Version 2 2 | 3 | import QtQuick 2.0 4 | import QtQuick.Controls 2.0 as QQC2 5 | import QtQuick.Layouts 1.0 6 | import org.kde.kirigami 2.0 as Kirigami 7 | 8 | QQC2.Label { 9 | Layout.fillWidth: true 10 | wrapMode: Text.Wrap 11 | linkColor: Kirigami.Theme.highlightColor 12 | onLinkActivated: Qt.openUrlExternally(link) 13 | MouseArea { 14 | anchors.fill: parent 15 | acceptedButtons: Qt.NoButton // we don't want to eat clicks on the Text 16 | cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package/metadata.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Present Windows Button 3 | Comment=Trigger the Present Windows desktop effect's shortcut with a click. 4 | 5 | Type=Service 6 | Icon=window 7 | X-KDE-ServiceTypes=Plasma/Applet 8 | 9 | X-Plasma-API=declarativeappletscript 10 | X-Plasma-MainScript=ui/Main.qml 11 | 12 | X-KDE-PluginInfo-Author=Chris Holland 13 | X-KDE-PluginInfo-Email=zrenfire@gmail.com 14 | X-KDE-PluginInfo-Name=com.github.zren.presentwindows 15 | X-KDE-PluginInfo-Version=9 16 | X-KDE-PluginInfo-Website=https://github.com/Zren/plasma-applet-presentwindows 17 | X-KDE-PluginInfo-Category=Windows and Tasks 18 | -------------------------------------------------------------------------------- /package/contents/ui/UnityThemeDetector.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import org.kde.plasma.core 2.0 as PlasmaCore 3 | 4 | QtObject { 5 | readonly property bool shouldUseUnityTheme: { 6 | return PlasmaCore.Theme.themeName == 'UnityAmbiance' 7 | } 8 | readonly property int configState: plasmoid.configuration.useUnityTheme 9 | readonly property bool useUnityTheme: { 10 | // console.log('useUnityTheme', configState, shouldUseUnityTheme) 11 | if (configState == 0) { // Never 12 | return false 13 | } else if (configState == 1) { // DependsOnPlasmaStyle 14 | return shouldUseUnityTheme 15 | } else { // configState == 2 Always 16 | return true 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /package/contents/icons/presentwindows-16px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /package/contents/ui/lib/ExecUtil.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import org.kde.plasma.core 2.0 as PlasmaCore 3 | 4 | PlasmaCore.DataSource { 5 | id: executable 6 | engine: "executable" 7 | connectedSources: [] 8 | onNewData: { 9 | var exitCode = data["exit code"] 10 | var exitStatus = data["exit status"] 11 | var stdout = data["stdout"] 12 | var stderr = data["stderr"] 13 | exited(sourceName, exitCode, exitStatus, stdout, stderr) 14 | disconnectSource(sourceName) // cmd finished 15 | } 16 | function exec(cmd) { 17 | connectSource(cmd) 18 | } 19 | signal exited(string command, int exitCode, int exitStatus, string stdout, string stderr) 20 | 21 | function trimOutput(stdout) { 22 | return stdout.replace('\n', ' ').trim() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /package/contents/icons/presentwindows-22px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /package/contents/icons/presentwindows-24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /package/contents/config/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | ExposeAll 11 | 12 | 13 | presentwindows-24px 14 | 15 | 16 | 17 | 1 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | ## v9 - April 24 2020 2 | 3 | * Add Parachute (KWin Script) support (Issue #9) 4 | * Added Dutch translations by @Vistaus (Pull Request #3) 5 | 6 | ## v8 - September 16 2018 7 | 8 | * Show preset values for the 22px and 16px icon in the config icon dropdown menu. 9 | * Fix the Desktop Effect toggle buttons not persisting accross reboots (Issue #1). 10 | 11 | ## v7 - August 4 2018 12 | 13 | * Add a 22px icon, with pathing done by @andreyorst. 14 | * Make sure the bundled icon is always smooth, even on older versions of plasma. 15 | 16 | ## v6 - April 14 2018 17 | 18 | * Force Latte Dock v0.7.5+ to not hide this widget. 19 | 20 | ## v5 - April 11 2018 21 | 22 | * Add Unity 7 virtual desktop indicator style for use with the Unity Ambiance desktop theme (used in the United Look and Feel). 23 | 24 | ## v4 - July 8 2017 25 | 26 | * Add ability to change the panel icon. 27 | 28 | ## v3 - June 22 2017 29 | 30 | * Add option to toggle the Desktop Grid Effect. 31 | 32 | ## v2 - June 15 2017 33 | 34 | * Provide checkbox in the config to quickly enabled the "Present Windows" desktop effect. 35 | 36 | ## v1 - June 15 2017 37 | 38 | * First version uploaded to the store. 39 | * Can configure which shortcut is run on click (All/CurrentDesktop/WindowClass). 40 | * Use same icon as Windows 10's Task View toggle. 41 | -------------------------------------------------------------------------------- /package/contents/ui/lib/AppletIcon.qml: -------------------------------------------------------------------------------- 1 | // Version: 4 2 | 3 | import QtQuick 2.0 4 | import org.kde.plasma.core 2.0 as PlasmaCore 5 | 6 | Item { 7 | id: appletIcon 8 | property string source: '' 9 | property bool active: false 10 | readonly property bool usingPackageSvg: filename // plasmoid.file() returns "" if file doesn't exist. 11 | readonly property string filename: source ? plasmoid.file('', 'icons/' + source + '.svg') : '' 12 | readonly property int minSize: Math.min(width, height) 13 | property bool smooth: true 14 | 15 | PlasmaCore.IconItem { 16 | anchors.fill: parent 17 | visible: !appletIcon.usingPackageSvg 18 | source: appletIcon.usingPackageSvg ? '' : appletIcon.source 19 | active: appletIcon.active 20 | smooth: appletIcon.smooth 21 | } 22 | 23 | PlasmaCore.SvgItem { 24 | id: svgItem 25 | anchors.centerIn: parent 26 | readonly property real minSize: Math.min(naturalSize.width, naturalSize.height) 27 | readonly property real widthRatio: naturalSize.width / svgItem.minSize 28 | readonly property real heightRatio: naturalSize.height / svgItem.minSize 29 | width: appletIcon.minSize * widthRatio 30 | height: appletIcon.minSize * heightRatio 31 | 32 | smooth: appletIcon.smooth 33 | 34 | visible: appletIcon.usingPackageSvg 35 | svg: PlasmaCore.Svg { 36 | id: svg 37 | imagePath: appletIcon.filename 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /package/contents/ui/lib/KPackageModel.qml: -------------------------------------------------------------------------------- 1 | // Version 1 2 | 3 | import QtQuick 2.0 4 | 5 | ListModel { 6 | property string packageType 7 | property bool loaded: false 8 | 9 | readonly property var executable: ExecUtil { 10 | id: executable 11 | property string readStateCommand: '( kpackagetool5 --type="' + packageType + '" --list ; kpackagetool5 --g --type="' + packageType + '" --list ) | cat' 12 | 13 | function readState() { 14 | executable.exec(readStateCommand) 15 | } 16 | Component.onCompleted: { 17 | readState() 18 | } 19 | 20 | function parsePackageList(stdout) { 21 | clear() 22 | var lines = stdout.split('\n') 23 | for (var i = 0; i < lines.length; i++) { 24 | var line = lines[i] 25 | if (line.indexOf(packageType) >= 0) { 26 | // Treat line as: 27 | // Listing service types: KWin/Script in /usr/share/kwin/scripts/ 28 | continue 29 | } 30 | var pluginId = line.trim() 31 | if (pluginId) { 32 | append({ 33 | pluginId: pluginId, 34 | }) 35 | } 36 | } 37 | } 38 | 39 | onExited: { 40 | if (command == readStateCommand) { 41 | parsePackageList(stdout) 42 | loaded = true 43 | } 44 | } 45 | 46 | function startsWith(a, b) { 47 | if (b.length <= a.length) { 48 | return a.substr(0, b.length) == b 49 | } else { 50 | return false 51 | } 52 | } 53 | } 54 | 55 | function contains(pluginId) { 56 | for (var i = 0; i < count; i++) { 57 | var item = get(i) 58 | if (item.pluginId == pluginId) { 59 | return true 60 | } 61 | } 62 | return false 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /package/contents/ui/libconfig/RadioButtonGroup.qml: -------------------------------------------------------------------------------- 1 | // Version 5 2 | 3 | import QtQuick 2.0 4 | import QtQuick.Controls 2.5 as QQC2 5 | import QtQuick.Layouts 1.0 6 | import org.kde.kirigami 2.5 as Kirigami 7 | 8 | /* 9 | ** Example: 10 | ** 11 | import './libconfig' as LibConfig 12 | LibConfig.RadioButtonGroup { 13 | configKey: "priority" 14 | model: [ 15 | { value: "a", text: i18n("A") }, 16 | { value: "b", text: i18n("B") }, 17 | { value: "c", text: i18n("C") }, 18 | ] 19 | } 20 | */ 21 | ColumnLayout { 22 | id: radioButtonGroup 23 | 24 | property string configKey: '' 25 | readonly property var configValue: configKey ? plasmoid.configuration[configKey] : "" 26 | 27 | property alias group: group 28 | QQC2.ButtonGroup { 29 | id: group 30 | } 31 | 32 | property alias model: buttonRepeater.model 33 | 34 | // The main reason we put all the RadioButtons in 35 | // a ColumnLayout is to shrink the spacing between the buttons. 36 | spacing: Kirigami.Units.smallSpacing 37 | 38 | // Assign buddyFor to the first RadioButton so that the Kirigami label aligns with it. 39 | // Repeater is also a visibleChild, so avoid it. 40 | Kirigami.FormData.buddyFor: { 41 | for (var i = 0; i < visibleChildren.length; i++) { 42 | if (!(visibleChildren[i] instanceof Repeater)) { 43 | return visibleChildren[i] 44 | } 45 | } 46 | return null 47 | } 48 | 49 | Repeater { 50 | id: buttonRepeater 51 | QQC2.RadioButton { 52 | visible: typeof modelData.visible !== "undefined" ? modelData.visible : true 53 | enabled: typeof modelData.enabled !== "undefined" ? modelData.enabled : true 54 | text: modelData.text 55 | checked: modelData.value === configValue 56 | QQC2.ButtonGroup.group: radioButtonGroup.group 57 | onClicked: { 58 | focus = true 59 | if (configKey) { 60 | plasmoid.configuration[configKey] = modelData.value 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /package/translate/build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Version: 6 3 | 4 | # This script will convert the *.po files to *.mo files, rebuilding the package/contents/locale folder. 5 | # Feature discussion: https://phabricator.kde.org/D5209 6 | # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo 7 | 8 | DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` 9 | plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` 10 | website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` 11 | bugAddress="$website" 12 | packageRoot=".." # Root of translatable sources 13 | projectName="plasma_applet_${plasmoidName}" # project name 14 | 15 | #--- 16 | if [ -z "$plasmoidName" ]; then 17 | echo "[build] Error: Couldn't read plasmoidName." 18 | exit 19 | fi 20 | 21 | if [ -z "$(which msgfmt)" ]; then 22 | echo "[build] Error: msgfmt command not found. Need to install gettext" 23 | echo "[build] Running 'sudo apt install gettext'" 24 | sudo apt install gettext 25 | echo "[build] gettext installation should be finished. Going back to installing translations." 26 | fi 27 | 28 | #--- 29 | echo "[build] Compiling messages" 30 | 31 | catalogs=`find . -name '*.po' | sort` 32 | for cat in $catalogs; do 33 | echo "$cat" 34 | catLocale=`basename ${cat%.*}` 35 | msgfmt -o "${catLocale}.mo" "$cat" 36 | 37 | installPath="$DIR/../contents/locale/${catLocale}/LC_MESSAGES/${projectName}.mo" 38 | 39 | echo "[build] Install to ${installPath}" 40 | mkdir -p "$(dirname "$installPath")" 41 | mv "${catLocale}.mo" "${installPath}" 42 | done 43 | 44 | echo "[build] Done building messages" 45 | 46 | if [ "$1" = "--restartplasma" ]; then 47 | echo "[build] Restarting plasmashell" 48 | killall plasmashell 49 | kstart5 plasmashell 50 | echo "[build] Done restarting plasmashell" 51 | else 52 | echo "[build] (re)install the plasmoid and restart plasmashell to test." 53 | fi 54 | -------------------------------------------------------------------------------- /package/translate/ReadMe.md: -------------------------------------------------------------------------------- 1 | > Version 7 of Zren's i18n scripts. 2 | 3 | With KDE Frameworks v5.37 and above, translations are bundled with the `*.plasmoid` file downloaded from the store. 4 | 5 | ## Install Translations 6 | 7 | Go to `~/.local/share/plasma/plasmoids/com.github.zren.presentwindows/translate/` and run `sh ./build --restartplasma`. 8 | 9 | ## New Translations 10 | 11 | 1. Fill out [`template.pot`](template.pot) with your translations then open a [new issue](https://github.com/Zren/plasma-applet-presentwindows/issues/new), name the file `spanish.txt`, attach the txt file to the issue (drag and drop). 12 | 13 | Or if you know how to make a pull request 14 | 15 | 1. Copy the `template.pot` file and name it your locale's code (Eg: `en`/`de`/`fr`) with the extension `.po`. Then fill out all the `msgstr ""`. 16 | 17 | ## Scripts 18 | 19 | * `sh ./merge` will parse the `i18n()` calls in the `*.qml` files and write it to the `template.pot` file. Then it will merge any changes into the `*.po` language files. 20 | * `sh ./build` will convert the `*.po` files to it's binary `*.mo` version and move it to `contents/locale/...` which will bundle the translations in the `*.plasmoid` without needing the user to manually install them. 21 | * `sh ./plasmoidlocaletest` will run `./build` then `plasmoidviewer` (part of `plasma-sdk`). 22 | 23 | ## Links 24 | 25 | * https://zren.github.io/kde/docs/widget/#translations-i18n 26 | * https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems 27 | * https://api.kde.org/frameworks/ki18n/html/prg_guide.html 28 | 29 | ## Examples 30 | 31 | * https://l10n.kde.org/stats/gui/trunk-kf5/team/fr/plasma-desktop/ 32 | * https://github.com/psifidotos/nowdock-plasmoid/tree/master/po 33 | * https://github.com/kotelnik/plasma-applet-redshift-control/tree/master/translations 34 | 35 | ## Status 36 | | Locale | Lines | % Done| 37 | |----------|---------|-------| 38 | | Template | 20 | | 39 | | nl | 12/20 | 60% | 40 | | pl | 12/20 | 60% | 41 | -------------------------------------------------------------------------------- /package/contents/ui/lib/DesktopEffectToggle.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 1.0 3 | import QtQuick.Layouts 1.0 4 | 5 | QtObject { 6 | id: desktopEffectToggle 7 | property string effectId 8 | property bool loaded: false 9 | property bool effectEnabled: false 10 | 11 | 12 | function toggle() { 13 | executable.toggleState() 14 | } 15 | 16 | property ExecUtil executable: ExecUtil { 17 | id: executable 18 | property string readStateCommand: 'qdbus org.kde.KWin /Effects isEffectLoaded ' + effectId 19 | property string toggleStateCommand: 'qdbus org.kde.KWin /Effects toggleEffect ' + effectId 20 | 21 | // For some reason, the toggleEffect qdbus function does not save to kwinrc. 22 | // So we need to manually write the new state to it, so that the next time 23 | // kwin is launched (next reboot), the desktop effect is still enabled/disabled. 24 | property string saveStateCommand: 'kwriteconfig5 --file ~/.config/kwinrc --group Plugins --key ' + effectId + 'Enabled' // saveStateCommand + ' ' + value 25 | property bool saveOnRead: false 26 | 27 | function readState() { 28 | executable.exec(readStateCommand) 29 | } 30 | function toggleState() { 31 | executable.exec(toggleStateCommand) 32 | } 33 | function saveState() { 34 | var isCurrentlyEnabled = effectEnabled 35 | executable.exec(saveStateCommand + ' ' + (isCurrentlyEnabled ? 'true' : 'false')) 36 | } 37 | Component.onCompleted: { 38 | readState() 39 | } 40 | 41 | onExited: { 42 | if (command == readStateCommand) { 43 | var value = executable.trimOutput(stdout) 44 | value = value === 'true' // cast to boolean 45 | effectEnabled = value 46 | loaded = true 47 | if (saveOnRead) { 48 | saveOnRead = false 49 | saveState() 50 | } 51 | } else if (command == toggleStateCommand) { 52 | saveOnRead = true 53 | readState() 54 | } else if (startsWith(command, saveStateCommand)) { 55 | 56 | } 57 | } 58 | 59 | function startsWith(a, b) { 60 | if (b.length <= a.length) { 61 | return a.substr(0, b.length) == b 62 | } else { 63 | return false 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /package/contents/ui/libconfig/Heading.qml: -------------------------------------------------------------------------------- 1 | // Version 5 2 | 3 | import QtQuick 2.0 4 | import QtQuick.Controls 2.5 as QQC2 5 | import QtQuick.Layouts 1.0 6 | import org.kde.kirigami 2.5 as Kirigami 7 | 8 | /* 9 | ** Example: 10 | ** 11 | import './libconfig' as LibConfig 12 | LibConfig.Heading { 13 | text: i18n("SpinBox (Double)") 14 | } 15 | */ 16 | 17 | // While the following Kirigami is very simple: 18 | // Kirigami.Separator { 19 | // Kirigami.FormData.label: "Heading" 20 | // Kirigami.FormData.isSection: true 21 | // } 22 | // 23 | // I want to be able to adjust the label size and make it bold. 24 | // Kirigami's buddy Heading is level=3, which does not stand out 25 | // very well. I also want to center the heading. 26 | // Since we can't access the Heading in the buddy component, we 27 | // need to make sure the Heading has no text, and draw our own. 28 | ColumnLayout { 29 | id: heading 30 | spacing: 0 31 | 32 | property string text: "" 33 | property alias separator: separator 34 | property alias label: label 35 | property bool useThickTopMargin: true 36 | 37 | property Item __formLayout: { 38 | if (parent && typeof parent.wideMode === 'boolean') { 39 | return parent 40 | } else if (typeof formLayout !== 'undefined' && typeof formLayout.wideMode === 'boolean') { 41 | return formLayout 42 | } else if (typeof page !== 'undefined' && typeof page.wideMode === 'boolean') { 43 | return page 44 | } else { 45 | return null 46 | } 47 | } 48 | 49 | Layout.fillWidth: true 50 | // Kirigami.FormData.isSection: true 51 | Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.FormLabel 52 | 53 | Kirigami.Separator { 54 | id: separator 55 | visible: false 56 | Layout.fillWidth: true 57 | Layout.topMargin: Kirigami.Units.largeSpacing 58 | Layout.bottomMargin: Kirigami.Units.largeSpacing 59 | } 60 | 61 | Kirigami.Heading { 62 | id: label 63 | Layout.topMargin: useThickTopMargin ? Kirigami.Units.largeSpacing * 3 : Kirigami.Units.largeSpacing 64 | Layout.bottomMargin: Kirigami.Units.smallSpacing 65 | Layout.fillWidth: true 66 | text: heading.text 67 | level: 1 68 | font.weight: Font.Bold 69 | // horizontalAlignment: (!__formLayout || __formLayout.wideMode) ? Text.AlignHCenter : Text.AlignLeft 70 | verticalAlignment: (!__formLayout || __formLayout.wideMode) ? Text.AlignVCenter : Text.AlignBottom 71 | } 72 | } 73 | 74 | //--- Test Default Kirigami Heading 75 | // Kirigami.Separator { 76 | // property string text: "" 77 | // Kirigami.FormData.label: text 78 | // Kirigami.FormData.isSection: true 79 | // property alias separator: separator 80 | // Item { 81 | // id: separator 82 | // } 83 | // } 84 | -------------------------------------------------------------------------------- /package/translate/template.pot: -------------------------------------------------------------------------------- 1 | # Translation of presentwindows in LANGUAGE 2 | # Copyright (C) 2022 3 | # This file is distributed under the same license as the presentwindows package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: presentwindows\n" 10 | "Report-Msgid-Bugs-To: https://github.com/Zren/plasma-applet-presentwindows\n" 11 | "POT-Creation-Date: 2022-02-23 22:57-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Present Windows Button" 22 | msgstr "" 23 | 24 | #: ../metadata.desktop 25 | msgid "Trigger the Present Windows desktop effect's shortcut with a click." 26 | msgstr "" 27 | 28 | #: ../contents/config/config.qml 29 | msgid "General" 30 | msgstr "" 31 | 32 | #: ../contents/ui/config/ConfigGeneral.qml 33 | msgid "Behavior" 34 | msgstr "" 35 | 36 | #: ../contents/ui/config/ConfigGeneral.qml 37 | msgid "Click" 38 | msgstr "" 39 | 40 | #: ../contents/ui/config/ConfigGeneral.qml 41 | msgid "Enable Desktop Effect" 42 | msgstr "" 43 | 44 | #: ../contents/ui/config/ConfigGeneral.qml 45 | msgid "Appearance" 46 | msgstr "" 47 | 48 | #: ../contents/ui/config/ConfigGeneral.qml 49 | msgid "Icon" 50 | msgstr "" 51 | 52 | #: ../contents/ui/config/ConfigGeneral.qml 53 | msgid "Unity Pager Theme" 54 | msgstr "" 55 | 56 | #: ../contents/ui/config/ConfigGeneral.qml 57 | msgid "Use Unity 7 Theme" 58 | msgstr "" 59 | 60 | #: ../contents/ui/config/ConfigGeneral.qml 61 | msgid "Never" 62 | msgstr "" 63 | 64 | #: ../contents/ui/config/ConfigGeneral.qml 65 | msgid "When Plasma Style is Unity Ambiance" 66 | msgstr "" 67 | 68 | #: ../contents/ui/config/ConfigGeneral.qml 69 | msgid "Always" 70 | msgstr "" 71 | 72 | #: ../contents/ui/config/ConfigGeneral.qml 73 | msgid "Should we use a Virtual Desktop indicator similar to Unity 7? This feature is enabled for the Unity Ambiance Plasma Style by default." 74 | msgstr "" 75 | 76 | #: ../contents/ui/config/ConfigGeneral.qml 77 | msgid "Current Plasma Style: %1" 78 | msgstr "" 79 | 80 | #: ../contents/ui/Main.qml 81 | msgid "Show Overview" 82 | msgstr "" 83 | 84 | #: ../contents/ui/Main.qml 85 | msgid "Present Windows (All desktops)" 86 | msgstr "" 87 | 88 | #: ../contents/ui/Main.qml 89 | msgid "Present Windows (Current desktop)" 90 | msgstr "" 91 | 92 | #: ../contents/ui/Main.qml 93 | msgid "Present Windows (Window class)" 94 | msgstr "" 95 | 96 | #: ../contents/ui/Main.qml 97 | msgid "Show Desktop Grid" 98 | msgstr "" 99 | -------------------------------------------------------------------------------- /package/translate/pl.po: -------------------------------------------------------------------------------- 1 | # Translation of presentwindows in pl 2 | # Copyright (C) 2020 3 | # This file is distributed under the same license as the presentwindows package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: presentwindows\n" 9 | "Report-Msgid-Bugs-To: https://github.com/Zren/plasma-applet-presentwindows\n" 10 | "POT-Creation-Date: 2022-02-23 22:57-0500\n" 11 | "PO-Revision-Date: 2020-05-31 08:11+0200\n" 12 | "Last-Translator: Piotr Komur \n" 13 | "Language-Team: Piotr Komur \n" 14 | "Language: pl\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 2.3\n" 19 | "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 " 20 | "|| n%100>14) ? 1 : 2);\n" 21 | 22 | #: ../metadata.desktop 23 | msgid "Present Windows Button" 24 | msgstr "" 25 | 26 | #: ../metadata.desktop 27 | msgid "Trigger the Present Windows desktop effect's shortcut with a click." 28 | msgstr "" 29 | 30 | #: ../contents/config/config.qml 31 | msgid "General" 32 | msgstr "Ogólne" 33 | 34 | #: ../contents/ui/config/ConfigGeneral.qml 35 | msgid "Behavior" 36 | msgstr "" 37 | 38 | #: ../contents/ui/config/ConfigGeneral.qml 39 | msgid "Click" 40 | msgstr "Kliknięcie" 41 | 42 | #: ../contents/ui/config/ConfigGeneral.qml 43 | msgid "Enable Desktop Effect" 44 | msgstr "" 45 | 46 | #: ../contents/ui/config/ConfigGeneral.qml 47 | msgid "Appearance" 48 | msgstr "Wygląd" 49 | 50 | #: ../contents/ui/config/ConfigGeneral.qml 51 | msgid "Icon" 52 | msgstr "Ikona" 53 | 54 | #: ../contents/ui/config/ConfigGeneral.qml 55 | msgid "Unity Pager Theme" 56 | msgstr "Motyw Unity Pager" 57 | 58 | #: ../contents/ui/config/ConfigGeneral.qml 59 | msgid "Use Unity 7 Theme" 60 | msgstr "Motyw Unity 7" 61 | 62 | #: ../contents/ui/config/ConfigGeneral.qml 63 | msgid "Never" 64 | msgstr "Nigdy" 65 | 66 | #: ../contents/ui/config/ConfigGeneral.qml 67 | msgid "When Plasma Style is Unity Ambiance" 68 | msgstr "" 69 | 70 | #: ../contents/ui/config/ConfigGeneral.qml 71 | msgid "Always" 72 | msgstr "Zawsze" 73 | 74 | #: ../contents/ui/config/ConfigGeneral.qml 75 | msgid "" 76 | "Should we use a Virtual Desktop indicator similar to Unity 7? This feature " 77 | "is enabled for the Unity " 78 | "Ambiance Plasma Style by default." 79 | msgstr "" 80 | 81 | #: ../contents/ui/config/ConfigGeneral.qml 82 | msgid "Current Plasma Style: %1" 83 | msgstr "" 84 | 85 | #: ../contents/ui/Main.qml 86 | msgid "Show Overview" 87 | msgstr "" 88 | 89 | #: ../contents/ui/Main.qml 90 | msgid "Present Windows (All desktops)" 91 | msgstr "Prezentacja okien (Wszystkie pulpity)" 92 | 93 | #: ../contents/ui/Main.qml 94 | msgid "Present Windows (Current desktop)" 95 | msgstr "Prezentacja okien (Bieżący pulpit)" 96 | 97 | #: ../contents/ui/Main.qml 98 | msgid "Present Windows (Window class)" 99 | msgstr "Prezentacja okien (Klasa okna)" 100 | 101 | #: ../contents/ui/Main.qml 102 | msgid "Show Desktop Grid" 103 | msgstr "Siatka pulpitu" 104 | 105 | #~ msgid "Present Windows Effect" 106 | #~ msgstr "Efekt prezentacji okien" 107 | 108 | #~ msgid "" 109 | #~ "Button will not work when the Present Windows desktop effect is disabled." 110 | #~ msgstr "Przycisk nie działa, gdy efekt pulpitu jest nieaktywny." 111 | 112 | #~ msgid "Show Desktop Grid Effect" 113 | #~ msgstr "Efekt siatki pulpitu" 114 | 115 | #~ msgid "" 116 | #~ "Button will not work when the Desktop Grid desktop effect is disabled." 117 | #~ msgstr "Przycisk nie działa, gdy efekt pulpitu jest nieaktywny." 118 | 119 | #~ msgid "Current Desktop Theme: %1" 120 | #~ msgstr "Motyw bieżącego pulpitu: %1" 121 | 122 | #~ msgid "Version: %1" 123 | #~ msgstr "Wersja: %1" 124 | 125 | #~ msgid "Enabled" 126 | #~ msgstr "Włączone" 127 | -------------------------------------------------------------------------------- /package/contents/ui/Unity7Workspaces.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.1 3 | import org.kde.plasma.plasmoid 2.0 4 | import org.kde.plasma.core 2.0 as PlasmaCore 5 | 6 | import org.kde.plasma.private.pager 2.0 7 | 8 | import "lib" 9 | 10 | Item { 11 | id: panelItem 12 | 13 | // Heavy use of the default Pager's code. 14 | // See: /usr/share/plasma/plasmoid/org.kde.plasma.pager/contents/ui/main.qml 15 | PagerModel { 16 | id: pagerModel 17 | 18 | enabled: true 19 | showOnlyCurrentScreen: true //plasmoid.configuration.showOnlyCurrentScreen 20 | screenGeometry: plasmoid.screenGeometry 21 | pagerType: PagerModel.VirtualDesktops 22 | } 23 | 24 | PlasmaCore.FrameSvgItem { 25 | id: taskFrame 26 | anchors.fill: parent 27 | imagePath: "widgets/tasks" 28 | prefix: "normal" 29 | } 30 | 31 | Grid { 32 | id: pagerItemGrid 33 | anchors.fill: parent 34 | 35 | anchors.leftMargin: taskFrame.margins.left 36 | anchors.rightMargin: taskFrame.margins.right 37 | anchors.topMargin: taskFrame.margins.top 38 | anchors.bottomMargin: taskFrame.margins.bottom 39 | 40 | // spacing: PlasmaCore.Units.devicePixelRatio 41 | rows: effectiveRows 42 | columns: effectiveColumns 43 | 44 | readonly property int effectiveRows: { 45 | var rows = 1 46 | var columns = Math.floor(pagerModel.count / pagerModel.layoutRows) 47 | 48 | if (pagerModel.count % pagerModel.layoutRows > 0) { 49 | columns += 1 50 | } 51 | 52 | rows = Math.floor(pagerModel.count / columns) 53 | 54 | if (pagerModel.count % columns > 0) { 55 | rows += 1 56 | } 57 | 58 | return rows 59 | } 60 | 61 | readonly property int effectiveColumns: { 62 | if (!pagerModel.count) { 63 | return 1 64 | } 65 | 66 | return Math.ceil(pagerModel.count / effectiveRows) 67 | } 68 | 69 | 70 | readonly property real pagerItemSizeRatio: pagerModel.pagerItemSize.width / pagerModel.pagerItemSize.height 71 | // readonly property real widthScaleFactor: columnWidth / pagerModel.pagerItemSize.width 72 | // readonly property real heightScaleFactor: rowHeight / pagerModel.pagerItemSize.height 73 | 74 | property int rowHeight: Math.floor(height / effectiveRows) 75 | property int columnWidth: Math.floor(width / effectiveColumns) 76 | 77 | property color seperatorColor: "#44FFFFFF" 78 | property color activeDesktopFillColor: "#44442027" 79 | 80 | Repeater { 81 | id: repeater 82 | model: pagerModel 83 | 84 | Item { 85 | id: desktop 86 | property int desktopIndex: index 87 | property int desktopColumn: index % pagerItemGrid.columns 88 | property int desktopRow: Math.floor(index / pagerItemGrid.columns) 89 | property bool isActiveDesktop: (index == pagerModel.currentPage) 90 | 91 | width: pagerItemGrid.columnWidth 92 | height: pagerItemGrid.rowHeight 93 | 94 | 95 | Rectangle { 96 | anchors.fill: parent 97 | color: desktop.isActiveDesktop ? pagerItemGrid.activeDesktopFillColor : "transparent" 98 | } 99 | 100 | Rectangle { 101 | id: verticalSeperator 102 | visible: desktop.desktopColumn < pagerItemGrid.columns-1 // Don't show on last column 103 | anchors.top: parent.top 104 | anchors.right: parent.right 105 | anchors.bottom: parent.bottom 106 | width: Math.round(1 * PlasmaCore.Units.devicePixelRatio) 107 | color: pagerItemGrid.seperatorColor 108 | } 109 | Rectangle { 110 | id: horizontalSeperator 111 | visible: desktop.desktopRow < pagerItemGrid.rows-1 // Don't show on last row 112 | anchors.left: parent.left 113 | anchors.bottom: parent.bottom 114 | anchors.right: parent.right 115 | height: Math.round(1 * PlasmaCore.Units.devicePixelRatio) 116 | color: pagerItemGrid.seperatorColor 117 | } 118 | 119 | AppletIcon { 120 | anchors.fill: parent 121 | source: desktop.isActiveDesktop ? "unity7selectedworkspace" : "" 122 | } 123 | } 124 | 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /package/contents/ui/Main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.1 3 | import org.kde.plasma.plasmoid 2.0 4 | import org.kde.plasma.core 2.0 as PlasmaCore 5 | 6 | import "lib" as Lib 7 | 8 | Item { 9 | id: widget 10 | 11 | UnityThemeDetector { 12 | id: unityThemeDetector 13 | } 14 | 15 | property bool disableLatteParabolicIcon: true // Don't hide the representation in Latte (https://github.com/psifidotos/Latte-Dock/issues/983) 16 | 17 | Plasmoid.onActivated: widget.activate() 18 | 19 | Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation 20 | Plasmoid.fullRepresentation: Item { 21 | id: panelItem 22 | 23 | readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge 24 | || plasmoid.location == PlasmaCore.Types.RightEdge 25 | || plasmoid.location == PlasmaCore.Types.BottomEdge 26 | || plasmoid.location == PlasmaCore.Types.LeftEdge) 27 | 28 | Layout.minimumWidth: { 29 | switch (plasmoid.formFactor) { 30 | case PlasmaCore.Types.Vertical: 31 | return 0; 32 | case PlasmaCore.Types.Horizontal: 33 | return height; 34 | default: 35 | return PlasmaCore.Units.gridUnit * 3; 36 | } 37 | } 38 | 39 | Layout.minimumHeight: { 40 | switch (plasmoid.formFactor) { 41 | case PlasmaCore.Types.Vertical: 42 | return width; 43 | case PlasmaCore.Types.Horizontal: 44 | return 0; 45 | default: 46 | return PlasmaCore.Units.gridUnit * 3; 47 | } 48 | } 49 | 50 | Layout.maximumWidth: inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1 51 | Layout.maximumHeight: inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1 52 | 53 | Lib.AppletIcon { 54 | id: icon 55 | anchors.fill: parent 56 | visible: !unityThemeDetector.useUnityTheme 57 | 58 | source: plasmoid.configuration.icon 59 | active: mouseArea.containsMouse 60 | } 61 | Loader { 62 | anchors.fill: parent 63 | active: unityThemeDetector.useUnityTheme 64 | visible: active 65 | source: "Unity7Workspaces.qml" 66 | } 67 | 68 | MouseArea { 69 | id: mouseArea 70 | anchors.fill: parent 71 | hoverEnabled: true 72 | onClicked: widget.activate() 73 | } 74 | } 75 | 76 | PlasmaCore.DataSource { 77 | id: executable 78 | engine: "executable" 79 | connectedSources: [] 80 | onNewData: disconnectSource(sourceName) 81 | 82 | function exec(cmd) { 83 | executable.connectSource(cmd) 84 | } 85 | } 86 | 87 | function action_showOverview() { 88 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "Overview"') 89 | } 90 | 91 | function action_exposeAll() { 92 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeAll"') 93 | } 94 | 95 | function action_exposeDesktop() { 96 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "Expose"') 97 | } 98 | 99 | function action_exposeWindowClass() { 100 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeClass"') 101 | } 102 | 103 | function action_showDesktopGrid() { 104 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ShowDesktopGrid"') 105 | } 106 | 107 | function action_toggleParachute() { 108 | executable.exec('qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "Parachute"') 109 | } 110 | 111 | function activate() { 112 | if (plasmoid.configuration.clickCommand == 'Overview') { 113 | action_showOverview() 114 | } else if (plasmoid.configuration.clickCommand == 'ExposeAll') { 115 | action_exposeAll() 116 | } else if (plasmoid.configuration.clickCommand == 'Expose') { 117 | action_exposeDesktop() 118 | } else if (plasmoid.configuration.clickCommand == 'ExposeClass') { 119 | action_exposeWindowClass() 120 | } else if (plasmoid.configuration.clickCommand == 'ShowDesktopGrid') { 121 | action_showDesktopGrid() 122 | } else if (plasmoid.configuration.clickCommand == 'Parachute') { 123 | action_toggleParachute() 124 | } 125 | } 126 | 127 | Component.onCompleted: { 128 | plasmoid.setAction("showOverview", i18n("Show Overview"), "view-grid"); 129 | plasmoid.setAction("exposeAll", i18n("Present Windows (All desktops)"), "window"); 130 | plasmoid.setAction("exposeDesktop", i18n("Present Windows (Current desktop)"), "window"); 131 | plasmoid.setAction("exposeWindowClass", i18n("Present Windows (Window class)"), "window"); 132 | plasmoid.setAction("showDesktopGrid", i18n("Show Desktop Grid"), "view-grid"); 133 | 134 | // plasmoid.action('configure').trigger() // Uncomment to open the config window on load. 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /package/contents/ui/libconfig/IconField.qml: -------------------------------------------------------------------------------- 1 | // Version 9 2 | 3 | import QtQuick 2.0 4 | import QtQuick.Controls 2.0 as QQC2 5 | import QtQuick.Layouts 1.0 6 | 7 | import org.kde.kirigami 2.0 as Kirigami 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons 10 | 11 | RowLayout { 12 | id: iconField 13 | 14 | default property alias _contentChildren: content.data 15 | 16 | property string configKey: '' 17 | property alias value: textField.text 18 | readonly property string configValue: configKey ? plasmoid.configuration[configKey] : "" 19 | onConfigValueChanged: { 20 | if (!textField.focus && value != configValue) { 21 | value = configValue 22 | } 23 | } 24 | property int previewIconSize: Kirigami.Units.iconSizes.medium 25 | property string defaultValue: "" 26 | property alias placeholderValue: textField.placeholderText 27 | property var presetValues: [] 28 | 29 | // Based on org.kde.plasma.kickoff 30 | QQC2.Button { 31 | id: iconButton 32 | padding: Kirigami.Units.smallSpacing 33 | Layout.alignment: Qt.AlignTop 34 | 35 | // KDE QQC2 sets implicitSize to background.implicitSize ignoring padding/inset properties. 36 | implicitWidth: leftPadding + contentItem.implicitWidth + rightPadding 37 | implicitHeight: topPadding + contentItem.implicitHeight + bottomPadding 38 | 39 | onPressed: iconMenu.opened ? iconMenu.close() : iconMenu.open() 40 | 41 | contentItem: PlasmaCore.FrameSvgItem { 42 | id: previewFrame 43 | imagePath: plasmoid.location === PlasmaCore.Types.Vertical || plasmoid.location === PlasmaCore.Types.Horizontal 44 | ? "widgets/panel-background" : "widgets/background" 45 | implicitWidth: fixedMargins.left + previewIconSize + fixedMargins.right 46 | implicitHeight: fixedMargins.top + previewIconSize + fixedMargins.bottom 47 | 48 | PlasmaCore.IconItem { 49 | anchors.fill: parent 50 | anchors.leftMargin: previewFrame.fixedMargins.left 51 | anchors.topMargin: previewFrame.fixedMargins.top 52 | anchors.rightMargin: previewFrame.fixedMargins.right 53 | anchors.bottomMargin: previewFrame.fixedMargins.bottom 54 | source: iconField.value || iconField.placeholderValue 55 | active: iconButton.hovered 56 | } 57 | } 58 | 59 | QQC2.Menu { 60 | id: iconMenu 61 | 62 | // Appear below the button 63 | y: +parent.height 64 | 65 | QQC2.MenuItem { 66 | text: i18ndc("plasma_applet_org.kde.plasma.kickoff", "@item:inmenu Open icon chooser dialog", "Choose...") 67 | icon.name: "document-open" 68 | onClicked: dialogLoader.active = true 69 | } 70 | QQC2.MenuItem { 71 | text: i18ndc("plasma_applet_org.kde.plasma.kickoff", "@item:inmenu Reset icon to default", "Clear Icon") 72 | icon.name: "edit-clear" 73 | onClicked: iconField.value = iconField.defaultValue 74 | } 75 | } 76 | } 77 | 78 | ColumnLayout { 79 | id: content 80 | Layout.fillWidth: true 81 | 82 | RowLayout { 83 | QQC2.TextField { 84 | id: textField 85 | Layout.fillWidth: true 86 | 87 | text: iconField.configValue 88 | onTextChanged: serializeTimer.restart() 89 | 90 | rightPadding: clearButton.width + Kirigami.Units.smallSpacing 91 | 92 | QQC2.ToolButton { 93 | id: clearButton 94 | visible: iconField.configValue != iconField.defaultValue 95 | icon.name: iconField.defaultValue === "" ? "edit-clear" : "edit-undo" 96 | onClicked: iconField.value = iconField.defaultValue 97 | 98 | anchors.top: parent.top 99 | anchors.right: parent.right 100 | anchors.bottom: parent.bottom 101 | 102 | width: height 103 | } 104 | } 105 | 106 | QQC2.Button { 107 | id: browseButton 108 | icon.name: "document-open" 109 | onClicked: dialogLoader.active = true 110 | } 111 | } 112 | 113 | Flow { 114 | Layout.fillWidth: true 115 | Layout.maximumWidth: Kirigami.Units.gridUnit * 30 116 | Repeater { 117 | model: presetValues 118 | QQC2.Button { 119 | icon.name: modelData 120 | text: modelData 121 | onClicked: iconField.value = modelData 122 | } 123 | } 124 | } 125 | } 126 | 127 | Loader { 128 | id: dialogLoader 129 | active: false 130 | sourceComponent: KQuickAddons.IconDialog { 131 | id: dialog 132 | visible: true 133 | modality: Qt.WindowModal 134 | onIconNameChanged: { 135 | iconField.value = iconName 136 | } 137 | onVisibleChanged: { 138 | if (!visible) { 139 | dialogLoader.active = false 140 | } 141 | } 142 | } 143 | } 144 | 145 | Timer { // throttle 146 | id: serializeTimer 147 | interval: 300 148 | onTriggered: { 149 | if (configKey) { 150 | plasmoid.configuration[configKey] = iconField.value 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /package/contents/ui/libconfig/AppletIconField.qml: -------------------------------------------------------------------------------- 1 | // Version 9 2 | // Forked LibConfig.IconField to use Lib.AppletIcon 3 | 4 | import QtQuick 2.0 5 | import QtQuick.Controls 2.0 as QQC2 6 | import QtQuick.Layouts 1.0 7 | 8 | import org.kde.kirigami 2.0 as Kirigami 9 | import org.kde.plasma.core 2.0 as PlasmaCore 10 | import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons 11 | 12 | import "../lib" as Lib 13 | 14 | RowLayout { 15 | id: iconField 16 | 17 | default property alias _contentChildren: content.data 18 | 19 | property string configKey: '' 20 | property alias value: textField.text 21 | readonly property string configValue: configKey ? plasmoid.configuration[configKey] : "" 22 | onConfigValueChanged: { 23 | if (!textField.focus && value != configValue) { 24 | value = configValue 25 | } 26 | } 27 | property int previewIconSize: Kirigami.Units.iconSizes.medium 28 | property string defaultValue: "" 29 | property alias placeholderValue: textField.placeholderText 30 | property var presetValues: [] 31 | 32 | // Based on org.kde.plasma.kickoff 33 | QQC2.Button { 34 | id: iconButton 35 | padding: Kirigami.Units.smallSpacing 36 | Layout.alignment: Qt.AlignTop 37 | 38 | // KDE QQC2 sets implicitSize to background.implicitSize ignoring padding/inset properties. 39 | implicitWidth: leftPadding + contentItem.implicitWidth + rightPadding 40 | implicitHeight: topPadding + contentItem.implicitHeight + bottomPadding 41 | 42 | onPressed: iconMenu.opened ? iconMenu.close() : iconMenu.open() 43 | 44 | contentItem: PlasmaCore.FrameSvgItem { 45 | id: previewFrame 46 | imagePath: plasmoid.location === PlasmaCore.Types.Vertical || plasmoid.location === PlasmaCore.Types.Horizontal 47 | ? "widgets/panel-background" : "widgets/background" 48 | implicitWidth: fixedMargins.left + previewIconSize + fixedMargins.right 49 | implicitHeight: fixedMargins.top + previewIconSize + fixedMargins.bottom 50 | 51 | Lib.AppletIcon { 52 | anchors.fill: parent 53 | anchors.leftMargin: previewFrame.fixedMargins.left 54 | anchors.topMargin: previewFrame.fixedMargins.top 55 | anchors.rightMargin: previewFrame.fixedMargins.right 56 | anchors.bottomMargin: previewFrame.fixedMargins.bottom 57 | source: iconField.value || iconField.placeholderValue 58 | active: iconButton.hovered 59 | } 60 | } 61 | 62 | QQC2.Menu { 63 | id: iconMenu 64 | 65 | // Appear below the button 66 | y: +parent.height 67 | 68 | QQC2.MenuItem { 69 | text: i18ndc("plasma_applet_org.kde.plasma.kickoff", "@item:inmenu Open icon chooser dialog", "Choose...") 70 | icon.name: "document-open" 71 | onClicked: dialogLoader.active = true 72 | } 73 | QQC2.MenuItem { 74 | text: i18ndc("plasma_applet_org.kde.plasma.kickoff", "@item:inmenu Reset icon to default", "Clear Icon") 75 | icon.name: "edit-clear" 76 | onClicked: iconField.value = iconField.defaultValue 77 | } 78 | } 79 | } 80 | 81 | ColumnLayout { 82 | id: content 83 | Layout.fillWidth: true 84 | 85 | RowLayout { 86 | QQC2.TextField { 87 | id: textField 88 | Layout.fillWidth: true 89 | 90 | text: iconField.configValue 91 | onTextChanged: serializeTimer.restart() 92 | 93 | rightPadding: clearButton.width + Kirigami.Units.smallSpacing 94 | 95 | QQC2.ToolButton { 96 | id: clearButton 97 | visible: iconField.configValue != iconField.defaultValue 98 | icon.name: iconField.defaultValue === "" ? "edit-clear" : "edit-undo" 99 | onClicked: iconField.value = iconField.defaultValue 100 | 101 | anchors.top: parent.top 102 | anchors.right: parent.right 103 | anchors.bottom: parent.bottom 104 | 105 | width: height 106 | } 107 | } 108 | 109 | QQC2.Button { 110 | id: browseButton 111 | icon.name: "document-open" 112 | onClicked: dialogLoader.active = true 113 | } 114 | } 115 | 116 | Flow { 117 | Layout.fillWidth: true 118 | Layout.maximumWidth: Kirigami.Units.gridUnit * 30 119 | Repeater { 120 | model: presetValues 121 | QQC2.Button { 122 | icon.name: modelData 123 | text: modelData 124 | onClicked: iconField.value = modelData 125 | } 126 | } 127 | } 128 | } 129 | 130 | Loader { 131 | id: dialogLoader 132 | active: false 133 | sourceComponent: KQuickAddons.IconDialog { 134 | id: dialog 135 | visible: true 136 | modality: Qt.WindowModal 137 | onIconNameChanged: { 138 | iconField.value = iconName 139 | } 140 | onVisibleChanged: { 141 | if (!visible) { 142 | dialogLoader.active = false 143 | } 144 | } 145 | } 146 | } 147 | 148 | Timer { // throttle 149 | id: serializeTimer 150 | interval: 300 151 | onTriggered: { 152 | if (configKey) { 153 | plasmoid.configuration[configKey] = iconField.value 154 | } 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /package/translate/nl.po: -------------------------------------------------------------------------------- 1 | # Translation of presentwindows in nl_NL 2 | # Copyright (C) 2018 3 | # This file is distributed under the same license as the presentwindows package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: presentwindows\n" 9 | "Report-Msgid-Bugs-To: https://github.com/Zren/plasma-applet-presentwindows\n" 10 | "POT-Creation-Date: 2022-02-23 22:57-0500\n" 11 | "PO-Revision-Date: 2022-02-25 12:30+0100\n" 12 | "Last-Translator: Heimen Stoffels \n" 13 | "Language-Team: Dutch \n" 14 | "Language: nl_NL\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "X-Generator: Poedit 3.0.1\n" 20 | 21 | #: ../metadata.desktop 22 | msgid "Present Windows Button" 23 | msgstr "Vensters presenteren-knop" 24 | 25 | #: ../metadata.desktop 26 | msgid "Trigger the Present Windows desktop effect's shortcut with a click." 27 | msgstr "Toon het vensteroverzicht met één muisklik." 28 | 29 | #: ../contents/config/config.qml 30 | msgid "General" 31 | msgstr "Algemeen" 32 | 33 | #: ../contents/ui/config/ConfigGeneral.qml 34 | msgid "Behavior" 35 | msgstr "Gedrag" 36 | 37 | #: ../contents/ui/config/ConfigGeneral.qml 38 | msgid "Click" 39 | msgstr "Klik" 40 | 41 | #: ../contents/ui/config/ConfigGeneral.qml 42 | msgid "Enable Desktop Effect" 43 | msgstr "Effect inschakelen" 44 | 45 | #: ../contents/ui/config/ConfigGeneral.qml 46 | msgid "Appearance" 47 | msgstr "Vormgeving" 48 | 49 | #: ../contents/ui/config/ConfigGeneral.qml 50 | msgid "Icon" 51 | msgstr "Pictogram" 52 | 53 | #: ../contents/ui/config/ConfigGeneral.qml 54 | msgid "Unity Pager Theme" 55 | msgstr "Unity-thema" 56 | 57 | #: ../contents/ui/config/ConfigGeneral.qml 58 | msgid "Use Unity 7 Theme" 59 | msgstr "Unity 7-thema gebruiken" 60 | 61 | #: ../contents/ui/config/ConfigGeneral.qml 62 | msgid "Never" 63 | msgstr "Nooit" 64 | 65 | #: ../contents/ui/config/ConfigGeneral.qml 66 | msgid "When Plasma Style is Unity Ambiance" 67 | msgstr "Als Plasmastijl is ingesteld op Unity Ambience" 68 | 69 | #: ../contents/ui/config/ConfigGeneral.qml 70 | msgid "Always" 71 | msgstr "Altijd" 72 | 73 | #: ../contents/ui/config/ConfigGeneral.qml 74 | msgid "" 75 | "Should we use a Virtual Desktop indicator similar to Unity 7? This feature " 76 | "is enabled for the Unity " 77 | "Ambiance Plasma Style by default." 78 | msgstr "" 79 | "Moet er een virtuelebureaublad-indicator worden getoond, net zoals in Unity " 80 | "7? Deze functie is standaard ingeschakeld als je gebruikmaakt van de Unity Ambiance-plasmastijl." 82 | 83 | #: ../contents/ui/config/ConfigGeneral.qml 84 | msgid "Current Plasma Style: %1" 85 | msgstr "Huidige Plasma-stijl: %1" 86 | 87 | #: ../contents/ui/Main.qml 88 | msgid "Show Overview" 89 | msgstr "Overzicht tonen" 90 | 91 | #: ../contents/ui/Main.qml 92 | msgid "Present Windows (All desktops)" 93 | msgstr "Vensters presenteren (alle bureaubladen)" 94 | 95 | #: ../contents/ui/Main.qml 96 | msgid "Present Windows (Current desktop)" 97 | msgstr "Vensters presenteren (huidig bureaublad)" 98 | 99 | #: ../contents/ui/Main.qml 100 | msgid "Present Windows (Window class)" 101 | msgstr "Vensters presenteren (vensterklasse)" 102 | 103 | #: ../contents/ui/Main.qml 104 | msgid "Show Desktop Grid" 105 | msgstr "Bureaubladrooster tonen" 106 | 107 | #~ msgid "Present Windows Effect" 108 | #~ msgstr "Effect voor Vensters presenteren" 109 | 110 | #~ msgid "" 111 | #~ "Button will not work when the Present Windows desktop effect is disabled." 112 | #~ msgstr "" 113 | #~ "De knop werkt niet als het bureaubladeffect Vensters presenteren is " 114 | #~ "uitgeschakeld." 115 | 116 | #~ msgid "Show Desktop Grid Effect" 117 | #~ msgstr "Bureaubladraster-effect tonen" 118 | 119 | #~ msgid "" 120 | #~ "Button will not work when the Desktop Grid desktop effect is disabled." 121 | #~ msgstr "" 122 | #~ "De knop werkt niet als het bureaubladeffect Bureaubladraster is " 123 | #~ "uitgeschakeld." 124 | 125 | #~ msgid "" 126 | #~ "Should we use a Virtual Desktop indicator similar to Unity 7? This " 127 | #~ "feature is enabled for the Unity Ambiance desktop theme by default." 129 | #~ msgstr "" 130 | #~ "Moet er een virtuele bureaubladindicator in de stijl van Unity 7 worden " 131 | #~ "gebruikt? Deze functie is standaard ingeschakeld voor het bureaubladthema " 132 | #~ "Unity Ambiance." 133 | 134 | #~ msgid "Current Desktop Theme: %1" 135 | #~ msgstr "Huidig bureaubladthema: %1" 136 | 137 | #~ msgid "Version: %1" 138 | #~ msgstr "Versie: %1" 139 | 140 | #~ msgid "Enabled" 141 | #~ msgstr "Ingeschakeld" 142 | -------------------------------------------------------------------------------- /package/contents/ui/config/ConfigGeneral.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 1.0 3 | import QtQuick.Controls 2.5 as QQC2 4 | import QtQuick.Layouts 1.0 5 | 6 | import org.kde.plasma.core 2.0 as PlasmaCore 7 | import org.kde.kirigami 2.5 as Kirigami 8 | 9 | import "../lib" as Lib 10 | import "../libconfig" as LibConfig 11 | 12 | 13 | Kirigami.FormLayout { 14 | 15 | 16 | //------------------------------------------------------- 17 | LibConfig.Heading { 18 | text: i18n("Behavior") 19 | useThickTopMargin: false 20 | } 21 | Lib.DesktopEffectToggle { 22 | id: overviewToggle 23 | effectId: 'overview' 24 | } 25 | Lib.DesktopEffectToggle { 26 | id: presentWindowsToggle 27 | effectId: 'presentwindows' 28 | } 29 | Lib.DesktopEffectToggle { 30 | id: showDesktopGridToggle 31 | effectId: 'desktopgrid' 32 | } 33 | LibConfig.RadioButtonGroup { 34 | id: clickCommandGroup 35 | configKey: 'clickCommand' 36 | Kirigami.FormData.label: i18n("Click") 37 | Kirigami.FormData.buddyFor: null // Note: it attaches to the first CheckBox in the Repeater since it loads first. 38 | model: [] 39 | 40 | //--- 41 | Repeater { 42 | model: [ 43 | { value: 'Overview', text: i18nd("kwin_effects", "Toggle Overview"), effectToggle: overviewToggle }, 44 | { value: 'ExposeAll', text: i18nd("kwin_effects", "Toggle Present Windows (All desktops)"), effectToggle: presentWindowsToggle }, 45 | { value: 'Expose', text: i18nd("kwin_effects", "Toggle Present Windows (Current desktop)"), effectToggle: presentWindowsToggle }, 46 | { value: 'ExposeClass', text: i18nd("kwin_effects", "Toggle Present Windows (Window class)"), effectToggle: presentWindowsToggle }, 47 | { value: 'ShowDesktopGrid', text: i18nd("kwin_effects", "Toggle Desktop Grid"), effectToggle: showDesktopGridToggle }, 48 | ] 49 | RowLayout { 50 | QQC2.RadioButton { 51 | text: modelData.text 52 | enabled: modelData.effectToggle.loaded && modelData.effectToggle.effectEnabled 53 | QQC2.ButtonGroup.group: clickCommandGroup.group 54 | checked: modelData.value === plasmoid.configuration[clickCommandGroup.configKey] 55 | onClicked: { 56 | focus = true 57 | if (clickCommandGroup.configKey) { 58 | plasmoid.configuration[clickCommandGroup.configKey] = modelData.value 59 | } 60 | } 61 | } 62 | QQC2.Button { 63 | visible: modelData.effectToggle.loaded && !modelData.effectToggle.effectEnabled 64 | text: i18n("Enable Desktop Effect") 65 | onClicked: modelData.effectToggle.toggle() 66 | } 67 | } 68 | } 69 | 70 | //--- 71 | Lib.KPackageModel { 72 | id: kwinScriptModel 73 | packageType: 'KWin/Script' 74 | } 75 | Repeater { 76 | visible: kwinScriptModel.loaded 77 | model: [ 78 | { 79 | pluginId: 'Parachute', 80 | url: 'https://store.kde.org/p/1370195/', 81 | }, 82 | ] 83 | RowLayout { 84 | QQC2.RadioButton { 85 | text: modelData.pluginId 86 | enabled: kwinScriptModel.contains(modelData.pluginId) 87 | QQC2.ButtonGroup.group: clickCommandGroup.group 88 | checked: modelData.value === plasmoid.configuration[clickCommandGroup.configKey] 89 | onClicked: { 90 | focus = true 91 | if (clickCommandGroup.configKey) { 92 | plasmoid.configuration[clickCommandGroup.configKey] = modelData.value 93 | } 94 | } 95 | } 96 | LibConfig.Label { 97 | text: '' + modelData.url + '' 98 | } 99 | } 100 | } 101 | } 102 | 103 | //------------------------------------------------------- 104 | LibConfig.Heading { 105 | text: i18n("Appearance") 106 | } 107 | 108 | LibConfig.AppletIconField { 109 | id: iconField 110 | configKey: 'icon' 111 | Kirigami.FormData.label: i18n("Icon") 112 | defaultValue: 'presentwindows-24px' 113 | presetValues: [ 114 | 'presentwindows-24px', 115 | 'presentwindows-22px', 116 | 'presentwindows-16px', 117 | 'edit-group', 118 | 'window', 119 | 'view-app-grid-symbolic', 120 | 'homerun', 121 | ] 122 | } 123 | 124 | 125 | 126 | //------------------------------------------------------- 127 | LibConfig.Heading { 128 | text: i18n("Unity Pager Theme") 129 | } 130 | 131 | LibConfig.RadioButtonGroup { 132 | configKey: 'useUnityTheme' 133 | Kirigami.FormData.label: i18n("Use Unity 7 Theme") 134 | model: [ 135 | { value: 0, text: i18n("Never") }, 136 | { value: 1, text: i18n("When Plasma Style is Unity Ambiance") }, 137 | { value: 2, text: i18n("Always") }, 138 | ] 139 | } 140 | 141 | LibConfig.Label { 142 | text: i18n("Should we use a Virtual Desktop indicator similar to Unity 7? This feature is enabled for the Unity Ambiance Plasma Style by default.") 143 | } 144 | 145 | Label { 146 | text: i18n("Current Plasma Style: %1", PlasmaCore.Theme.themeName) 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /package/contents/icons/unity7selectedworkspace.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 33 | 34 | 42 | 46 | 47 | 48 | 67 | 69 | 70 | 72 | image/svg+xml 73 | 75 | 76 | 77 | 78 | 79 | 93 | 98 | 102 | 110 | 118 | 125 | 132 | 139 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /package/translate/plasmoidlocaletest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Version 9 3 | # Requires plasmoidviewer v5.13.0 4 | 5 | function checkIfLangInstalled { 6 | if [ -x "$(command -v dpkg)" ]; then 7 | dpkg -l ${1} >/dev/null 2>&1 || ( \ 8 | echo -e "${1} not installed.\nInstalling now before continuing.\n" \ 9 | ; sudo apt install ${1} \ 10 | ) || ( \ 11 | echo -e "\nError trying to install ${1}\nPlease run 'sudo apt install ${1}'\n" \ 12 | ; exit 1 \ 13 | ) 14 | elif [ -x "$(command -v pacman)" ]; then 15 | # TODO: run `locale -a` and check if the locale is enabled. 16 | if false; then 17 | # https://wiki.archlinux.org/index.php/Locale 18 | # Uncomment the locale in /etc/locale.gen 19 | # Then run `locale-gen` 20 | echo -e "\nPlease install this locale in System Settings first.\n" 21 | exit 1 22 | else 23 | echo "" 24 | fi 25 | else 26 | echo -e "\nPackage manager not recognized. If the widget is not translated, please install the package '${1}'\n" 27 | fi 28 | } 29 | 30 | langInput="${1}" 31 | lang="" 32 | languagePack="" 33 | 34 | if [[ "$langInput" =~ ":" ]]; then # String contains a colon so assume it's a locale code. 35 | lang="${langInput}" 36 | IFS=: read -r l1 l2 <<< "${lang}" 37 | languagePack="language-pack-${l2}" 38 | fi 39 | 40 | # https://stackoverflow.com/questions/3191664/list-of-all-locales-and-their-short-codes/28357857#28357857 41 | declare -a langArr=( 42 | "af_ZA:af:Afrikaans (South Africa)" 43 | "ak_GH:ak:Akan (Ghana)" 44 | "am_ET:am:Amharic (Ethiopia)" 45 | "ar_EG:ar:Arabic (Egypt)" 46 | "as_IN:as:Assamese (India)" 47 | "az_AZ:az:Azerbaijani (Azerbaijan)" 48 | "be_BY:be:Belarusian (Belarus)" 49 | "bem_ZM:bem:Bemba (Zambia)" 50 | "bg_BG:bg:Bulgarian (Bulgaria)" 51 | "bo_IN:bo:Tibetan (India)" 52 | "bs_BA:bs:Bosnian (Bosnia and Herzegovina)" 53 | "ca_ES:ca:Catalan (Spain)" 54 | "chr_US:ch:Cherokee (United States)" 55 | "cs_CZ:cs:Czech (Czech Republic)" 56 | "cy_GB:cy:Welsh (United Kingdom)" 57 | "da_DK:da:Danish (Denmark)" 58 | "de_DE:de:German (Germany)" 59 | "el_GR:el:Greek (Greece)" 60 | "es_MX:es:Spanish (Mexico)" 61 | "et_EE:et:Estonian (Estonia)" 62 | "eu_ES:eu:Basque (Spain)" 63 | "fa_IR:fa:Persian (Iran)" 64 | "ff_SN:ff:Fulah (Senegal)" 65 | "fi_FI:fi:Finnish (Finland)" 66 | "fo_FO:fo:Faroese (Faroe Islands)" 67 | "fr_CA:fr:French (Canada)" 68 | "ga_IE:ga:Irish (Ireland)" 69 | "gl_ES:gl:Galician (Spain)" 70 | "gu_IN:gu:Gujarati (India)" 71 | "gv_GB:gv:Manx (United Kingdom)" 72 | "ha_NG:ha:Hausa (Nigeria)" 73 | "he_IL:he:Hebrew (Israel)" 74 | "hi_IN:hi:Hindi (India)" 75 | "hr_HR:hr:Croatian (Croatia)" 76 | "hu_HU:hu:Hungarian (Hungary)" 77 | "hy_AM:hy:Armenian (Armenia)" 78 | "id_ID:id:Indonesian (Indonesia)" 79 | "ig_NG:ig:Igbo (Nigeria)" 80 | "is_IS:is:Icelandic (Iceland)" 81 | "it_IT:it:Italian (Italy)" 82 | "ja_JP:ja:Japanese (Japan)" 83 | "ka_GE:ka:Georgian (Georgia)" 84 | "kk_KZ:kk:Kazakh (Kazakhstan)" 85 | "kl_GL:kl:Kalaallisut (Greenland)" 86 | "km_KH:km:Khmer (Cambodia)" 87 | "kn_IN:kn:Kannada (India)" 88 | "ko_KR:ko:Korean (South Korea)" 89 | "ko_KR:ko:Korean (South Korea)" 90 | "lg_UG:lg:Ganda (Uganda)" 91 | "lt_LT:lt:Lithuanian (Lithuania)" 92 | "lv_LV:lv:Latvian (Latvia)" 93 | "mg_MG:mg:Malagasy (Madagascar)" 94 | "mk_MK:mk:Macedonian (Macedonia)" 95 | "ml_IN:ml:Malayalam (India)" 96 | "mr_IN:mr:Marathi (India)" 97 | "ms_MY:ms:Malay (Malaysia)" 98 | "mt_MT:mt:Maltese (Malta)" 99 | "my_MM:my:Burmese (Myanmar [Burma])" 100 | "nb_NO:nb:Norwegian Bokmål (Norway)" 101 | "ne_NP:ne:Nepali (Nepal)" 102 | "nl_NL:nl:Dutch (Netherlands)" 103 | "nn_NO:nn:Norwegian Nynorsk (Norway)" 104 | "om_ET:om:Oromo (Ethiopia)" 105 | "or_IN:or:Oriya (India)" 106 | "pa_PK:pa:Punjabi (Pakistan)" 107 | "pl_PL:pl:Polish (Poland)" 108 | "ps_AF:ps:Pashto (Afghanistan)" 109 | "pt_BR:pt:Portuguese (Brazil)" 110 | "ro_RO:ro:Romanian (Romania)" 111 | "ru_RU:ru:Russian (Russia)" 112 | "rw_RW:rw:Kinyarwanda (Rwanda)" 113 | "si_LK:si:Sinhala (Sri Lanka)" 114 | "sk_SK:sk:Slovak (Slovakia)" 115 | "sl_SI:sl:Slovenian (Slovenia)" 116 | "so_SO:so:Somali (Somalia)" 117 | "sq_AL:sq:Albanian (Albania)" 118 | "sr_RS:sr:Serbian (Serbia)" 119 | "sv_SE:sv:Swedish (Sweden)" 120 | "sw_KE:sw:Swahili (Kenya)" 121 | "ta_IN:ta:Tamil (India)" 122 | "te_IN:te:Telugu (India)" 123 | "th_TH:th:Thai (Thailand)" 124 | "ti_ER:ti:Tigrinya (Eritrea)" 125 | "to_TO:to:Tonga (Tonga)" 126 | "tr_TR:tr:Turkish (Turkey)" 127 | "uk_UA:uk:Ukrainian (Ukraine)" 128 | "ur_IN:ur:Urdu (India)" 129 | "uz_UZ:uz:Uzbek (Uzbekistan)" 130 | "vi_VN:vi:Vietnamese (Vietnam)" 131 | "yo_NG:yo:Yoruba (Nigeria)" 132 | "yo_NG:yo:Yoruba (Nigeria)" 133 | "yue_HK:yu:Cantonese (Hong Kong)" 134 | "zh_CN:zh:Chinese (China)" 135 | "zu_ZA:zu:Zulu (South Africa)" 136 | ) 137 | 138 | for i in "${langArr[@]}"; do 139 | IFS=: read -r l1 l2 l3 <<< "$i" 140 | if [ "$langInput" == "$l2" ]; then 141 | lang="${l1}:${l2}" 142 | languagePack="language-pack-${l2}" 143 | fi 144 | done 145 | 146 | if [ -z "$lang" ]; then 147 | echo "plasmoidlocaletest doesn't recognize the language '$lang'" 148 | echo "Eg:" 149 | scriptcmd='sh ./plasmoidlocaletest' 150 | for i in "${langArr[@]}"; do 151 | IFS=: read -r l1 l2 l3 <<< "$i" 152 | echo " ${scriptcmd} ${l2} | ${l3}" 153 | done 154 | echo "" 155 | echo "Or use a the full locale code:" 156 | echo " ${scriptcmd} ar_EG:ar" 157 | exit 1 158 | fi 159 | 160 | IFS=: read -r l1 l2 <<< "${lang}" 161 | l1="${l1}.UTF-8" 162 | 163 | # Check if language is installed 164 | if [ ! -z "$languagePack" ]; then 165 | if [ "$lang" == "zh_CN:zh" ]; then languagePack="language-pack-zh-hans" 166 | fi 167 | 168 | checkIfLangInstalled "$languagePack" || exit 1 169 | fi 170 | 171 | 172 | echo "LANGUAGE=\"${lang}\"" 173 | echo "LANG=\"${l1}\"" 174 | 175 | scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 176 | packageDir="${scriptDir}/.." 177 | 178 | # Build local translations for plasmoidviewer 179 | sh "${scriptDir}/build" 180 | 181 | LANGUAGE="${lang}" LANG="${l1}" LC_TIME="${l1}" QML_DISABLE_DISK_CACHE=true plasmoidviewer -a "$packageDir" -l topedge -f horizontal -x 0 -y 0 182 | -------------------------------------------------------------------------------- /package/translate/merge: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Version: 22 3 | 4 | # https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems 5 | # https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems/Outside_KDE_repositories 6 | # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh 7 | 8 | DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` 9 | plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` 10 | widgetName="${plasmoidName##*.}" # Strip namespace 11 | website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` 12 | bugAddress="$website" 13 | packageRoot=".." # Root of translatable sources 14 | projectName="plasma_applet_${plasmoidName}" # project name 15 | 16 | #--- 17 | if [ -z "$plasmoidName" ]; then 18 | echo "[merge] Error: Couldn't read plasmoidName." 19 | exit 20 | fi 21 | 22 | if [ -z "$(which xgettext)" ]; then 23 | echo "[merge] Error: xgettext command not found. Need to install gettext" 24 | echo "[merge] Running 'sudo apt install gettext'" 25 | sudo apt install gettext 26 | echo "[merge] gettext installation should be finished. Going back to merging translations." 27 | fi 28 | 29 | #--- 30 | echo "[merge] Extracting messages" 31 | potArgs="--from-code=UTF-8 --width=200 --add-location=file" 32 | 33 | # Note: xgettext v0.20.1 (Kubuntu 20.04) and below will attempt to translate Icon, 34 | # so we need to specify Name, GenericName, Comment, and Keywords. 35 | # https://github.com/Zren/plasma-applet-lib/issues/1 36 | # https://savannah.gnu.org/support/?108887 37 | find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" 38 | xgettext \ 39 | ${potArgs} \ 40 | --files-from="${DIR}/infiles.list" \ 41 | --language=Desktop \ 42 | -k -kName -kGenericName -kComment -kKeywords \ 43 | -D "${packageRoot}" \ 44 | -D "${DIR}" \ 45 | -o "template.pot.new" \ 46 | || \ 47 | { echo "[merge] error while calling xgettext. aborting."; exit 1; } 48 | 49 | sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" 50 | 51 | # See Ki18n's extract-messages.sh for a full example: 52 | # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh#L25 53 | # The -kN_ and -kaliasLocale keywords are mentioned in the Outside_KDE_repositories wiki. 54 | # We don't need -kN_ since we don't use intltool-extract but might as well keep it. 55 | # I have no idea what -kaliasLocale is used for. Googling aliasLocale found only listed kde1 code. 56 | # We don't need to parse -ki18nd since that'll extract messages from other domains. 57 | find "${packageRoot}" -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' -o -name '*.js' | sort > "${DIR}/infiles.list" 58 | xgettext \ 59 | ${potArgs} \ 60 | --files-from="${DIR}/infiles.list" \ 61 | -C -kde \ 62 | -ci18n \ 63 | -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 \ 64 | -kki18n:1 -kki18nc:1c,2 -kki18np:1,2 -kki18ncp:1c,2,3 \ 65 | -kxi18n:1 -kxi18nc:1c,2 -kxi18np:1,2 -kxi18ncp:1c,2,3 \ 66 | -kkxi18n:1 -kkxi18nc:1c,2 -kkxi18np:1,2 -kkxi18ncp:1c,2,3 \ 67 | -kI18N_NOOP:1 -kI18NC_NOOP:1c,2 \ 68 | -kI18N_NOOP2:1c,2 -kI18N_NOOP2_NOSTRIP:1c,2 \ 69 | -ktr2i18n:1 -ktr2xi18n:1 \ 70 | -kN_:1 \ 71 | -kaliasLocale \ 72 | --package-name="${widgetName}" \ 73 | --msgid-bugs-address="${bugAddress}" \ 74 | -D "${packageRoot}" \ 75 | -D "${DIR}" \ 76 | --join-existing \ 77 | -o "template.pot.new" \ 78 | || \ 79 | { echo "[merge] error while calling xgettext. aborting."; exit 1; } 80 | 81 | sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in LANGUAGE"'/' "template.pot.new" 82 | sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "template.pot.new" 83 | 84 | if [ -f "template.pot" ]; then 85 | newPotDate=`grep "POT-Creation-Date:" template.pot.new | sed 's/.\{3\}$//'` 86 | oldPotDate=`grep "POT-Creation-Date:" template.pot | sed 's/.\{3\}$//'` 87 | sed -i 's/'"${newPotDate}"'/'"${oldPotDate}"'/' "template.pot.new" 88 | changes=`diff "template.pot" "template.pot.new"` 89 | if [ ! -z "$changes" ]; then 90 | # There's been changes 91 | sed -i 's/'"${oldPotDate}"'/'"${newPotDate}"'/' "template.pot.new" 92 | mv "template.pot.new" "template.pot" 93 | 94 | addedKeys=`echo "$changes" | grep "> msgid" | cut -c 9- | sort` 95 | removedKeys=`echo "$changes" | grep "< msgid" | cut -c 9- | sort` 96 | echo "" 97 | echo "Added Keys:" 98 | echo "$addedKeys" 99 | echo "" 100 | echo "Removed Keys:" 101 | echo "$removedKeys" 102 | echo "" 103 | 104 | else 105 | # No changes 106 | rm "template.pot.new" 107 | fi 108 | else 109 | # template.pot didn't already exist 110 | mv "template.pot.new" "template.pot" 111 | fi 112 | 113 | potMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "template.pot" | grep -c 'msgstr ""')` 114 | echo "| Locale | Lines | % Done|" > "./Status.md" 115 | echo "|----------|---------|-------|" >> "./Status.md" 116 | entryFormat="| %-8s | %7s | %5s |" 117 | templateLine=`perl -e "printf(\"$entryFormat\", \"Template\", \"${potMessageCount}\", \"\")"` 118 | echo "$templateLine" >> "./Status.md" 119 | 120 | rm "${DIR}/infiles.list" 121 | echo "[merge] Done extracting messages" 122 | 123 | #--- 124 | echo "[merge] Merging messages" 125 | catalogs=`find . -name '*.po' | sort` 126 | for cat in $catalogs; do 127 | echo "[merge] $cat" 128 | catLocale=`basename ${cat%.*}` 129 | 130 | widthArg="" 131 | catUsesGenerator=`grep "X-Generator:" "$cat"` 132 | if [ -z "$catUsesGenerator" ]; then 133 | widthArg="--width=400" 134 | fi 135 | 136 | compendiumArg="" 137 | if [ ! -z "$COMPENDIUM_DIR" ]; then 138 | langCode=`basename "${cat%.*}"` 139 | compendiumPath=`realpath "$COMPENDIUM_DIR/compendium-${langCode}.po"` 140 | if [ -f "$compendiumPath" ]; then 141 | echo "compendiumPath=$compendiumPath" 142 | compendiumArg="--compendium=$compendiumPath" 143 | fi 144 | fi 145 | 146 | cp "$cat" "$cat.new" 147 | sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "$cat.new" 148 | 149 | msgmerge \ 150 | ${widthArg} \ 151 | --add-location=file \ 152 | --no-fuzzy-matching \ 153 | ${compendiumArg} \ 154 | -o "$cat.new" \ 155 | "$cat.new" "${DIR}/template.pot" 156 | 157 | sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" 158 | sed -i 's/# Translation of '"${widgetName}"' in LANGUAGE/'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" 159 | sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "$cat.new" 160 | 161 | poEmptyMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "$cat.new" | grep -c 'msgstr ""')` 162 | poMessagesDoneCount=`expr $potMessageCount - $poEmptyMessageCount` 163 | poCompletion=`perl -e "printf(\"%d\", $poMessagesDoneCount * 100 / $potMessageCount)"` 164 | poLine=`perl -e "printf(\"$entryFormat\", \"$catLocale\", \"${poMessagesDoneCount}/${potMessageCount}\", \"${poCompletion}%\")"` 165 | echo "$poLine" >> "./Status.md" 166 | 167 | # mv "$cat" "$cat.old" 168 | mv "$cat.new" "$cat" 169 | done 170 | echo "[merge] Done merging messages" 171 | 172 | #--- 173 | echo "[merge] Updating .desktop file" 174 | 175 | # Generate LINGUAS for msgfmt 176 | if [ -f "$DIR/LINGUAS" ]; then 177 | rm "$DIR/LINGUAS" 178 | fi 179 | touch "$DIR/LINGUAS" 180 | for cat in $catalogs; do 181 | catLocale=`basename ${cat%.*}` 182 | echo "${catLocale}" >> "$DIR/LINGUAS" 183 | done 184 | 185 | cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" 186 | sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" 187 | 188 | msgfmt \ 189 | --desktop \ 190 | --template="$DIR/template.desktop" \ 191 | -d "$DIR/" \ 192 | -o "$DIR/new.desktop" 193 | 194 | # Delete empty msgid messages that used the po header 195 | if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then 196 | echo "[merge] Name in metadata.desktop is empty!" 197 | sed -i '/^Name\[/ d' "$DIR/new.desktop" 198 | fi 199 | if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then 200 | echo "[merge] GenericName in metadata.desktop is empty!" 201 | sed -i '/^GenericName\[/ d' "$DIR/new.desktop" 202 | fi 203 | if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then 204 | echo "[merge] Comment in metadata.desktop is empty!" 205 | sed -i '/^Comment\[/ d' "$DIR/new.desktop" 206 | fi 207 | if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then 208 | echo "[merge] Keywords in metadata.desktop is empty!" 209 | sed -i '/^Keywords\[/ d' "$DIR/new.desktop" 210 | fi 211 | 212 | # Place translations at the bottom of the desktop file. 213 | translatedLines=`cat "$DIR/new.desktop" | grep "]="` 214 | if [ ! -z "${translatedLines}" ]; then 215 | sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" 216 | if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then 217 | # Does not end with 2 empty lines, so add an empty line. 218 | echo "" >> "$DIR/new.desktop" 219 | fi 220 | echo "${translatedLines}" >> "$DIR/new.desktop" 221 | fi 222 | 223 | # Cleanup 224 | mv "$DIR/new.desktop" "$DIR/../metadata.desktop" 225 | rm "$DIR/template.desktop" 226 | rm "$DIR/LINGUAS" 227 | 228 | #--- 229 | # Populate ReadMe.md 230 | echo "[merge] Updating translate/ReadMe.md" 231 | sed -i -E 's`share\/plasma\/plasmoids\/(.+)\/translate`share/plasma/plasmoids/'"${plasmoidName}"'/translate`' ./ReadMe.md 232 | if [[ "$website" == *"github.com"* ]]; then 233 | sed -i -E 's`\[new issue\]\(https:\/\/github\.com\/(.+)\/(.+)\/issues\/new\)`[new issue]('"${website}"'/issues/new)`' ./ReadMe.md 234 | fi 235 | sed -i '/^|/ d' ./ReadMe.md # Remove status table from ReadMe 236 | cat ./Status.md >> ./ReadMe.md 237 | rm ./Status.md 238 | 239 | echo "[merge] Done" 240 | --------------------------------------------------------------------------------