Added System Tray modification, updated SevenStart

This commit is contained in:
wackyideas 2021-08-13 15:38:28 +02:00
parent 0f883e1bf1
commit 4e6953ba81
24 changed files with 2555 additions and 32 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -511,6 +511,10 @@ PlasmaCore.Dialog {
return shortcuts.home
else if (val === 5)
return shortcuts.movies
else if (val === 6)
return "~/Downloads"
else if (val === 7)
return "/"
}
}
@ -643,36 +647,7 @@ PlasmaCore.Dialog {
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(2))
}
ListDelegate {
text: "Music"
Image {
property bool hovered: false
source: "../pics/menu_select.png"
smooth: true
opacity: hovered ? 1.0 : 0.0
width: parent.width
height: parent.height
MouseArea {
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
parent.hovered = true
}
onExited: {
parent.hovered = false
}
onClicked: {
root.visible = false;
executable.exec("dolphin --new-window "+folderDialog.getPath(3))
}
hoverEnabled: true
anchors.fill: parent
}
}
icon: "folder-music"
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(3))
}
ListDelegate {
text: "Pictures"
Image {
@ -703,6 +678,36 @@ PlasmaCore.Dialog {
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(1))
}
ListDelegate {
text: "Music"
Image {
property bool hovered: false
source: "../pics/menu_select.png"
smooth: true
opacity: hovered ? 1.0 : 0.0
width: parent.width
height: parent.height
MouseArea {
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
parent.hovered = true
}
onExited: {
parent.hovered = false
}
onClicked: {
root.visible = false;
executable.exec("dolphin --new-window "+folderDialog.getPath(3))
}
hoverEnabled: true
anchors.fill: parent
}
}
icon: "folder-music"
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(3))
}
ListDelegate {
text: "Videos"
Image {
@ -733,6 +738,66 @@ PlasmaCore.Dialog {
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(5))
}
ListDelegate {
text: "Downloads"
Image {
property bool hovered: false
source: "../pics/menu_select.png"
smooth: true
opacity: hovered ? 1.0 : 0.0
width: parent.width
height: parent.height
MouseArea {
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
parent.hovered = true
}
onExited: {
parent.hovered = false
}
onClicked: {
root.visible = false;
executable.exec("dolphin --new-window "+folderDialog.getPath(6))
}
hoverEnabled: true
anchors.fill: parent
}
}
icon: "folder-music"
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(5))
}
ListDelegate {
text: "Computer"
Image {
property bool hovered: false
source: "../pics/menu_select.png"
smooth: true
opacity: hovered ? 1.0 : 0.0
width: parent.width
height: parent.height
MouseArea {
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
parent.hovered = true
}
onExited: {
parent.hovered = false
}
onClicked: {
root.visible = false;
executable.exec("dolphin --new-window "+folderDialog.getPath(7))
}
hoverEnabled: true
anchors.fill: parent
}
}
icon: "folder-music"
size: iconSizeSide
//onClicked: executable.exec("dolphin --new-window "+folderDialog.getPath(5))
}
ListDelegate {
text: "System Settings"
@ -754,7 +819,37 @@ PlasmaCore.Dialog {
}
onClicked: {
root.visible = false;
logic.openUrl("file:///usr/share/applications/systemsettings.desktop")
executable.exec("systemsettings5")
}
hoverEnabled: true
anchors.fill: parent
}
}
icon: "configure"
size: iconSizeSide
//onClicked: logic.openUrl("file:///usr/share/applications/systemsettings.desktop")
}
ListDelegate {
text: "Default Programs"
Image {
property bool hovered: false
source: "../pics/menu_select.png"
smooth: true
opacity: hovered ? 1.0 : 0.0
width: parent.width
height: parent.height
MouseArea {
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
parent.hovered = true
}
onExited: {
parent.hovered = false
}
onClicked: {
root.visible = false;
executable.exec("systemsettings5 componentchooser")
}
hoverEnabled: true
anchors.fill: parent

View file

@ -44,10 +44,32 @@ Item {
property QtObject globalFavorites: rootModel.favoritesModel
property QtObject systemFavorites: rootModel.systemFavoritesModel
PlasmaCore.DataSource {
id: menu_executable
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(sourceName, exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
if (cmd) {
connectSource(cmd)
}
}
signal exited(string cmd, int exitCode, int exitStatus, string stdout, string stderr)
}
function action_menuedit() {
processRunner.runMenuEditor();
}
function action_taskman() {
menu_executable.exec("ksysguard");
}
Component {
id: compactRepresentation
@ -197,6 +219,7 @@ Item {
Component.onCompleted: {
plasmoid.setAction("menuedit", i18n("Edit Applications..."));
plasmoid.setAction("taskman", i18n("Task Manager"));
rootModel.refreshed.connect(reset);

View file

@ -0,0 +1,83 @@
/*
* Copyright 2011 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
PlasmaCore.ToolTipArea {
id: appletRoot
objectName: "org.kde.desktop-CompactApplet"
anchors.fill: parent
mainText: plasmoid.toolTipMainText
subText: plasmoid.toolTipSubText
location: if (plasmoid.parent && plasmoid.parent.inHiddenLayout && plasmoid.location !== PlasmaCore.Types.LeftEdge) {
return PlasmaCore.Types.RightEdge;
} else {
return plasmoid.location;
}
active: !plasmoid.expanded
textFormat: plasmoid.toolTipTextFormat
mainItem: plasmoid.toolTipItem ? plasmoid.toolTipItem : null
property Item fullRepresentation
property Item compactRepresentation
Connections {
target: plasmoid
function onContextualActionsAboutToShow() {
appletRoot.hideToolTip()
}
}
Layout.minimumWidth: {
switch (plasmoid.formFactor) {
case PlasmaCore.Types.Vertical:
return 0;
case PlasmaCore.Types.Horizontal:
return height;
default:
return PlasmaCore.Units.gridUnit * 3;
}
}
Layout.minimumHeight: {
switch (plasmoid.formFactor) {
case PlasmaCore.Types.Vertical:
return width;
case PlasmaCore.Types.Horizontal:
return 0;
default:
return PlasmaCore.Units.gridUnit * 3;
}
}
onCompactRepresentationChanged: {
if (compactRepresentation) {
compactRepresentation.parent = appletRoot;
compactRepresentation.anchors.fill = appletRoot;
compactRepresentation.visible = true;
}
appletRoot.visible = true;
}
}

View file

@ -0,0 +1,35 @@
/***************************************************************************
* Copyright 2013 by Sebastian Kügler <sebas@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "plasma"
source: "ConfigGeneral.qml"
}
ConfigCategory {
name: i18n("Entries")
icon: "preferences-desktop-notification"
source: "ConfigEntries.qml"
}
}

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="extraItems" type="StringList">
<label>All plasmoid items that are explicitly enabled in the systray. It's a comma-separated string list of plasmoid plugin ids.</label>
<default></default>
</entry>
<entry name="hiddenItems" type="StringList">
<label>All items that are hidden, forced always in the popup. It's a comma-separated string list of unique identifiers that are either plasmoid plugin ids or StatusNotifier ids.</label>
<default></default>
</entry>
<entry name="shownItems" type="StringList">
<label>All items that are shown. It's a comma-separated string list of unique identifiers that are either plasmoid plugin ids or StatusNotifier ids.</label>
<default></default>
</entry>
<entry name="showAllItems" type="bool">
<label>If true, all systray entries will be always in the main area, outside the popup.</label>
<default>false</default>
</entry>
<entry name="knownItems" type="StringList" hidden="true">
<default></default>
</entry>
<entry name="scaleIconsToFit" type="bool">
<label>Whether to automatically scale System Tray icons to fix the available thickness of the panel. If false, tray icons will be capped at the smallMedium size (22px) and become a two-row/column layout when the panel is thick.</label>
<default>false</default>
</entry>
<entry name="pin" type="Bool">
<label>Whether the popup should remain open when another window is activated</label>
<default>false</default>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,296 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2014 Marco Martin <mart@kde.org>
* Copyright 2019 Konrad Materka <materka@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.5
import QtQuick.Controls 2.5 as QQC2
import QtQuick.Layouts 1.3
import org.kde.kquickcontrols 2.0 as KQC
import org.kde.kirigami 2.10 as Kirigami
ColumnLayout {
id: iconsPage
signal configurationChanged
property var cfg_shownItems: []
property var cfg_hiddenItems: []
property var cfg_extraItems: []
property alias cfg_showAllItems: showAllCheckBox.checked
QQC2.CheckBox {
id: showAllCheckBox
text: i18n("Always show all entries")
}
function categoryName(category) {
switch (category) {
case "ApplicationStatus":
return i18n("Application Status")
case "Communications":
return i18n("Communications")
case "SystemServices":
return i18n("System Services")
case "Hardware":
return i18n("Hardware Control")
case "UnknownCategory":
default:
return i18n("Miscellaneous")
}
}
QQC2.ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
contentHeight: itemsList.implicitHeight
Component.onCompleted: scrollView.background.visible = true
property bool scrollBarVisible: QQC2.ScrollBar.vertical && QQC2.ScrollBar.vertical.visible
property var scrollBarWidth: scrollBarVisible ? QQC2.ScrollBar.vertical.width : 0
ListView {
id: itemsList
property var visibilityColumnWidth: Kirigami.Units.gridUnit
property var keySequenceColumnWidth: Kirigami.Units.gridUnit
clip: true
model: plasmoid.nativeInterface.configSystemTrayModel
header: Kirigami.AbstractListItem {
hoverEnabled: false
RowLayout {
Kirigami.Heading {
text: i18nc("Name of the system tray entry", "Entry")
level: 2
Layout.fillWidth: true
}
Kirigami.Heading {
text: i18n("Visibility")
level: 2
Layout.preferredWidth: itemsList.visibilityColumnWidth
Component.onCompleted: itemsList.visibilityColumnWidth = Math.max(implicitWidth, itemsList.visibilityColumnWidth)
}
Kirigami.Heading {
text: i18n("Keyboard Shortcut")
level: 2
Layout.preferredWidth: itemsList.keySequenceColumnWidth
Component.onCompleted: itemsList.keySequenceColumnWidth = Math.max(implicitWidth, itemsList.keySequenceColumnWidth)
}
QQC2.Button { // Configure button column
icon.name: "configure"
enabled: false
opacity: 0
}
}
}
section {
property: "category"
delegate: Kirigami.ListSectionHeader {
label: categoryName(section)
}
}
delegate: Kirigami.AbstractListItem {
highlighted: false
hoverEnabled: false
property bool isPlasmoid: model.itemType === "Plasmoid"
contentItem: RowLayout {
RowLayout {
Layout.fillWidth: true
Kirigami.Icon {
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: model.decoration
}
QQC2.Label {
Layout.fillWidth: true
text: model.display
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
QQC2.ComboBox {
id: visibilityComboBox
property var contentWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitWidth: Math.max(contentWidth, itemsList.visibilityColumnWidth)
Component.onCompleted: itemsList.visibilityColumnWidth = Math.max(implicitWidth, itemsList.visibilityColumnWidth)
enabled: (!showAllCheckBox.checked || isPlasmoid) && itemId
textRole: "text"
model: comboBoxModel()
currentIndex: {
var value
if (cfg_shownItems.indexOf(itemId) !== -1) {
value = "shown"
} else if (cfg_hiddenItems.indexOf(itemId) !== -1) {
value = "hidden"
} else if (isPlasmoid && cfg_extraItems.indexOf(itemId) === -1) {
value = "disabled"
} else {
value = "auto"
}
for (var i = 0; i < model.length; i++) {
if (model[i].value === value) {
return i
}
}
return 0
}
property var myCurrentValue: model[currentIndex].value
onActivated: {
var shownIndex = cfg_shownItems.indexOf(itemId)
var hiddenIndex = cfg_hiddenItems.indexOf(itemId)
var extraIndex = cfg_extraItems.indexOf(itemId)
switch (myCurrentValue) {
case "auto":
if (shownIndex > -1) {
cfg_shownItems.splice(shownIndex, 1)
}
if (hiddenIndex > -1) {
cfg_hiddenItems.splice(hiddenIndex, 1)
}
if (extraIndex === -1) {
cfg_extraItems.push(itemId)
}
break
case "shown":
if (shownIndex === -1) {
cfg_shownItems.push(itemId)
}
if (hiddenIndex > -1) {
cfg_hiddenItems.splice(hiddenIndex, 1)
}
if (extraIndex === -1) {
cfg_extraItems.push(itemId)
}
break
case "hidden":
if (shownIndex > -1) {
cfg_shownItems.splice(shownIndex, 1)
}
if (hiddenIndex === -1) {
cfg_hiddenItems.push(itemId)
}
if (extraIndex === -1) {
cfg_extraItems.push(itemId)
}
break
case "disabled":
if (shownIndex > -1) {
cfg_shownItems.splice(shownIndex, 1)
}
if (hiddenIndex > -1) {
cfg_hiddenItems.splice(hiddenIndex, 1)
}
if (extraIndex > -1) {
cfg_extraItems.splice(extraIndex, 1)
}
break
}
iconsPage.configurationChanged()
}
function comboBoxModel() {
var autoElement = {"value": "auto", "text": i18n("Shown when relevant")}
var shownElement = {"value": "shown", "text": i18n("Always shown")}
var hiddenElement = {"value": "hidden", "text": i18n("Always hidden")}
var disabledElement = {"value": "disabled", "text": i18n("Disabled")}
if (showAllCheckBox.checked) {
if (isPlasmoid) {
return [autoElement, disabledElement]
} else {
return [shownElement]
}
} else {
if (isPlasmoid) {
return [autoElement, shownElement, hiddenElement, disabledElement]
} else {
return [autoElement, shownElement, hiddenElement]
}
}
}
}
KQC.KeySequenceItem {
id: keySequenceItem
Layout.minimumWidth: itemsList.keySequenceColumnWidth
Layout.preferredWidth: itemsList.keySequenceColumnWidth
Component.onCompleted: itemsList.keySequenceColumnWidth = Math.max(implicitWidth, itemsList.keySequenceColumnWidth)
visible: isPlasmoid
enabled: visibilityComboBox.myCurrentValue !== "disabled"
keySequence: model.applet ? model.applet.globalShortcut : ""
onKeySequenceChanged: {
if (model.applet && keySequence !== model.applet.globalShortcut) {
model.applet.globalShortcut = keySequence
itemsList.keySequenceColumnWidth = Math.max(implicitWidth, itemsList.keySequenceColumnWidth)
}
}
}
// Placeholder for when KeySequenceItem is not visible
Item {
Layout.minimumWidth: itemsList.keySequenceColumnWidth
Layout.maximumWidth: itemsList.keySequenceColumnWidth
visible: !keySequenceItem.visible
}
QQC2.Button {
readonly property QtObject configureAction: (model.applet && model.applet.action("configure")) || null
Accessible.name: configureAction ? configureAction.text : ""
icon.name: "configure"
enabled: configureAction && configureAction.visible && configureAction.enabled
// Still reserve layout space, so not setting visible to false
opacity: enabled ? 1 : 0
onClicked: configureAction.trigger()
QQC2.ToolTip {
// Strip out ampersands right before non-whitespace characters, i.e.
// those used to determine the alt key shortcut
text: parent.Accessible.name.replace(/&(?=\S)/g, "")
}
}
}
}
}
}
}

View file

@ -0,0 +1,49 @@
/***************************************************************************
* Copyright (C) 2020 Konrad Materka <materka@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.14
import QtQuick.Controls 2.14 as QQC2
import QtQuick.Layouts 1.13
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.kirigami 2.13 as Kirigami
ColumnLayout {
property bool cfg_scaleIconsToFit
Kirigami.FormLayout {
Layout.fillHeight: true
QQC2.RadioButton {
Kirigami.FormData.label: i18nc("The arrangement of system tray icons in the Panel", "Panel icon size:")
text: i18n("Small")
checked: cfg_scaleIconsToFit == false
onToggled: cfg_scaleIconsToFit = !checked
}
QQC2.RadioButton {
id: automaticRadioButton
text: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? i18n("Scale with Panel height")
: i18n("Scale with Panel width")
checked: cfg_scaleIconsToFit == true
onToggled: cfg_scaleIconsToFit = checked
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright 2011 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.12
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.FrameSvgItem {
id: currentItemHighLight
property int location
property bool animationEnabled: true
property var highlightedItem: null
z: -1 // always draw behind icons
opacity: systemTrayState.expanded ? 0.8 : 0
MouseArea
{
id: trayItemHighlight
anchors.fill: parent
hoverEnabled: true
property int highlightOpacity: 0
onEntered: highlightOpacity = 1
onExited: highlightOpacity = 0
}
imagePath: "widgets/tabbar"
prefix: {
var prefix = ""
switch (location) {
case PlasmaCore.Types.LeftEdge:
prefix = "west-active-tab";
break;
case PlasmaCore.Types.TopEdge:
prefix = "north-active-tab";
break;
case PlasmaCore.Types.RightEdge:
prefix = "east-active-tab";
break;
default:
prefix = "south-active-tab";
}
if (!hasElementPrefix(prefix)) {
prefix = "active-tab";
}
return prefix;
}
// update when System Tray is expanded - applet activated or hidden icons shown
Connections {
target: systemTrayState
function onActiveAppletChanged() {
Qt.callLater(updateHighlightedItem);
}
function onExpandedChanged() {
Qt.callLater(updateHighlightedItem);
}
}
// update when applet changes parent (e.g. moves from active to hidden icons)
Connections {
target: systemTrayState.activeApplet
function onParentChanged() {
Qt.callLater(updateHighlightedItem);
}
}
// update when System Tray size changes
Connections {
target: parent
function onWidthChanged() {
Qt.callLater(updateHighlightedItem);
}
function onHeightChanged() {
Qt.callLater(updateHighlightedItem);
}
}
// update when scale of newly added tray item changes (check 'add' animation in GridView in main.qml)
Connections {
target: !!highlightedItem && highlightedItem.parent ? highlightedItem.parent : null
function onScaleChanged() {
Qt.callLater(updateHighlightedItem);
}
}
function updateHighlightedItem() {
if (systemTrayState.expanded) {
if (systemTrayState.activeApplet && systemTrayState.activeApplet.parent && systemTrayState.activeApplet.parent.inVisibleLayout) {
changeHighlightedItem(systemTrayState.activeApplet.parent.container);
} else { // 'Show hiden items' popup
changeHighlightedItem(parent);
}
} else {
highlightedItem = null;
}
}
function changeHighlightedItem(nextItem) {
// do not animate the first appearance
// or when the property value of a highlighted item changes
if (!highlightedItem || (highlightedItem === nextItem)) {
animationEnabled = false;
}
highlightedItem = nextItem;
const p = parent.mapFromItem(highlightedItem, 0, 0)
x = p.x;
y = p.y;
width = highlightedItem.width
height = highlightedItem.height
animationEnabled = true;
}
Behavior on opacity {
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: systemTrayState.expanded ? Easing.OutCubic : Easing.InCubic
}
}
Behavior on x {
id: xAnim
enabled: animationEnabled
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutCubic
}
}
Behavior on y {
id: yAnim
enabled: animationEnabled
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutCubic
}
}
Behavior on width {
id: widthAnim
enabled: animationEnabled
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutCubic
}
}
Behavior on height {
id: heightAnim
enabled: animationEnabled
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutCubic
}
}
}

View file

@ -0,0 +1,231 @@
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.12
import QtQuick.Layouts 1.12
import org.kde.plasma.core 2.0 as PlasmaCore
// We still need PC2 here for that version of Menu, as PC2 Menu is still very problematic with QActions
// Not being a proper popup window, makes it a showstopper to be used in Plasma
import org.kde.plasma.components 2.0 as PC2
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: popup
//set width/height to avoid useless Dialog resize
readonly property int defaultWidth: PlasmaCore.Units.gridUnit * 24
readonly property int defaultHeight: PlasmaCore.Units.gridUnit * 24
width: defaultWidth
Layout.minimumWidth: defaultWidth
Layout.preferredWidth: defaultWidth
Layout.maximumWidth: defaultWidth
height: defaultHeight
Layout.minimumHeight: defaultHeight
Layout.preferredHeight: defaultHeight
Layout.maximumHeight: defaultHeight
property alias hiddenLayout: hiddenItemsView.layout
// Header
PlasmaExtras.PlasmoidHeading {
id: plasmoidHeading
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: trayHeading.height + bottomPadding + container.headingHeight
Behavior on height {
NumberAnimation { duration: PlasmaCore.Units.shortDuration/2; easing.type: Easing.InOutQuad }
}
}
// Main content layout
ColumnLayout {
id: expandedRepresentation
anchors.fill: parent
// TODO: remove this so the scrollview fully touches the header;
// add top padding internally
spacing: plasmoidHeading.bottomPadding
// Header content layout
RowLayout {
id: trayHeading
PlasmaComponents.ToolButton {
id: backButton
visible: systemTrayState.activeApplet && systemTrayState.activeApplet.expanded && (hiddenLayout.itemCount > 0)
icon.name: LayoutMirroring.enabled ? "go-previous-symbolic-rtl" : "go-previous-symbolic"
onClicked: systemTrayState.setActiveApplet(null)
}
PlasmaExtras.Heading {
Layout.fillWidth: true
leftPadding: systemTrayState.activeApplet ? 0 : PlasmaCore.Units.smallSpacing * 2
level: 1
text: systemTrayState.activeApplet ? systemTrayState.activeApplet.title : i18n("Status and Notifications")
}
PlasmaComponents.ToolButton {
id: actionsButton
visible: visibleActions > 0
checked: visibleActions > 1 ? configMenu.status !== PC2.DialogStatus.Closed : singleAction && singleAction.checked
property QtObject applet: systemTrayState.activeApplet || plasmoid
onAppletChanged: {
configMenu.clearMenuItems();
updateVisibleActions();
}
property int visibleActions: 0
property QtObject singleAction
function updateVisibleActions() {
let newSingleAction = null;
let newVisibleActions = 0;
for (let i in applet.contextualActions) {
let action = applet.contextualActions[i];
if (action.visible && action !== actionsButton.applet.action("configure")) {
newVisibleActions++;
newSingleAction = action;
action.changed.connect(() => {updateVisibleActions()});
}
}
if (newVisibleActions > 1) {
newSingleAction = null;
}
visibleActions = newVisibleActions;
singleAction = newSingleAction;
}
Connections {
target: actionsButton.applet
function onContextualActionsChanged() {
Qt.callLater(actionsButton.updateVisibleActions);
}
}
icon.name: "application-menu"
checkable: visibleActions > 1 || (singleAction && singleAction.checkable)
contentItem.opacity: visibleActions > 1
// NOTE: it needs an IconItem because QtQuickControls2 buttons cannot load QIcons as their icon
PlasmaCore.IconItem {
parent: actionsButton
anchors.centerIn: parent
active: actionsButton.hovered
implicitWidth: PlasmaCore.Units.iconSizes.smallMedium
implicitHeight: implicitWidth
source: actionsButton.singleAction !== null ? actionsButton.singleAction.icon : ""
visible: actionsButton.singleAction
}
onToggled: {
if (visibleActions > 1) {
if (checked) {
configMenu.openRelative();
} else {
configMenu.close();
}
}
}
onClicked: {
if (singleAction) {
singleAction.trigger();
}
}
PlasmaComponents.ToolTip {
text: actionsButton.singleAction ? actionsButton.singleAction.text : i18n("More actions")
}
PC2.Menu {
id: configMenu
visualParent: actionsButton
placement: PlasmaCore.Types.BottomPosedLeftAlignedPopup
}
Instantiator {
model: actionsButton.applet.contextualActions
delegate: PC2.MenuItem {
id: menuItem
action: modelData
}
onObjectAdded: {
if (object.action !== actionsButton.applet.action("configure")) {
configMenu.addMenuItem(object);
}
}
}
}
PlasmaComponents.ToolButton {
icon.name: "configure"
visible: actionsButton.applet && actionsButton.applet.action("configure")
PlasmaComponents.ToolTip {
text: parent.visible ? actionsButton.applet.action("configure").text : ""
}
onClicked: actionsButton.applet.action("configure").trigger();
}
PlasmaComponents.ToolButton {
id: pinButton
checkable: true
checked: plasmoid.configuration.pin
onToggled: plasmoid.configuration.pin = checked
icon.name: "window-pin"
PlasmaComponents.ToolTip {
text: i18n("Keep Open")
}
}
}
// Grid view of all available items
HiddenItemsView {
id: hiddenItemsView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: PlasmaCore.Units.smallSpacing
visible: !systemTrayState.activeApplet
}
// Container for currently visible item
PlasmoidPopupsContainer {
id: container
Layout.fillWidth: true
Layout.fillHeight: true
visible: systemTrayState.activeApplet
// We need to add margin on the top so it matches the dialog's own margin
Layout.topMargin: mergeHeadings ? 0 : dialog.margins.top
}
}
// Footer
PlasmaExtras.PlasmoidHeading {
id: plasmoidFooter
location: PlasmaExtras.PlasmoidHeading.Location.Footer
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
visible: container.appletHasFooter
height: container.footerHeight
// So that it doesn't appear over the content view, which results in
// the footer controls being inaccessible
z: -9999
}
}

View file

@ -0,0 +1,112 @@
/***************************************************************************
* Copyright 2013 Sebastian Kügler <sebas@kde.org> *
* Copyright 2015 Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.ToolTipArea {
id: tooltip
property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical
implicitWidth: PlasmaCore.Units.iconSizes.smallMedium
implicitHeight: implicitWidth
subText: systemTrayState.expanded ? i18n("Close popup") : i18n("Show hidden icons")
MouseArea {
id: arrowMouseArea
anchors.fill: parent
onClicked: systemTrayState.expanded = !systemTrayState.expanded
readonly property int arrowAnimationDuration: PlasmaCore.Units.shortDuration
PlasmaCore.Svg {
id: arrowSvg
imagePath: "widgets/arrows"
}
PlasmaCore.SvgItem {
id: arrow
anchors.centerIn: parent
width: Math.min(parent.width, parent.height)
height: width
rotation: systemTrayState.expanded ? 180 : 0
Behavior on rotation {
RotationAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
opacity: systemTrayState.expanded ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
svg: arrowSvg
elementId: {
if (plasmoid.location === PlasmaCore.Types.TopEdge) {
return "down-arrow";
} else if (plasmoid.location === PlasmaCore.Types.LeftEdge) {
return "right-arrow";
} else if (plasmoid.location === PlasmaCore.Types.RightEdge) {
return "left-arrow";
} else {
return "up-arrow";
}
}
}
PlasmaCore.SvgItem {
anchors.centerIn: parent
width: arrow.width
height: arrow.height
rotation: systemTrayState.expanded ? 0 : -180
Behavior on rotation {
RotationAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
opacity: systemTrayState.expanded ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: arrowMouseArea.arrowAnimationDuration
}
}
svg: arrowSvg
elementId: {
if (plasmoid.location === PlasmaCore.Types.TopEdge) {
return "up-arrow";
} else if (plasmoid.location === PlasmaCore.Types.LeftEdge) {
return "left-arrow";
} else if (plasmoid.location === PlasmaCore.Types.RightEdge) {
return "right-arrow";
} else {
return "down-arrow";
}
}
}
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Konrad Materka <materka@gmail.com>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents // For Highlight
import org.kde.plasma.extras 2.0 as PlasmaExtras
import "items"
MouseArea {
id: hiddenTasksView
property alias layout: hiddenTasks
hoverEnabled: true
onExited: hiddenTasks.currentIndex = -1
PlasmaExtras.ScrollArea {
width: parent.width
height: parent.height
frameVisible: false
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: systemTrayState.activeApplet ? Qt.ScrollBarAlwaysOff : Qt.ScrollBarAsNeeded
GridView {
id: hiddenTasks
readonly property int rows: 4
readonly property int columns: 4
cellWidth: hiddenTasks.width / hiddenTasks.columns
cellHeight: hiddenTasks.height / hiddenTasks.rows
currentIndex: -1
highlight: PlasmaComponents.Highlight {}
highlightMoveDuration: 0
readonly property int itemCount: model.count
model: PlasmaCore.SortFilterModel {
sourceModel: plasmoid.nativeInterface.systemTrayModel
filterRole: "effectiveStatus"
filterCallback: function(source_row, value) {
return value === PlasmaCore.Types.PassiveStatus
}
}
delegate: ItemLoader {}
}
}
}

View file

@ -0,0 +1,157 @@
/*
* Copyright 2015 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.4
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
//needed for units
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
StackView {
id: mainStack
focus: true
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 12
Layout.minimumHeight: PlasmaCore.Units.gridUnit * 12
readonly property Item activeApplet: systemTrayState.activeApplet
/* Heading */
property bool appletHasHeading: false
property bool mergeHeadings: appletHasHeading && activeApplet.fullRepresentationItem.header.visible
property int headingHeight: mergeHeadings ? activeApplet.fullRepresentationItem.header.height : 0
/* Footer */
property bool appletHasFooter: false
property bool mergeFooters: appletHasFooter && activeApplet.fullRepresentationItem.footer.visible
property int footerHeight: mergeFooters ? activeApplet.fullRepresentationItem.footer.height : 0
onActiveAppletChanged: {
mainStack.appletHasHeading = false
mainStack.appletHasFooter = false
if (activeApplet != null) {
//reset any potential anchor
activeApplet.fullRepresentationItem.anchors.left = undefined;
activeApplet.fullRepresentationItem.anchors.top = undefined;
activeApplet.fullRepresentationItem.anchors.right = undefined;
activeApplet.fullRepresentationItem.anchors.bottom = undefined;
activeApplet.fullRepresentationItem.anchors.centerIn = undefined;
activeApplet.fullRepresentationItem.anchors.fill = undefined;
if (activeApplet.fullRepresentationItem instanceof PlasmaComponents3.Page) {
if (activeApplet.fullRepresentationItem.header && activeApplet.fullRepresentationItem.header instanceof PlasmaExtras.PlasmoidHeading) {
mainStack.appletHasHeading = true
activeApplet.fullRepresentationItem.header.background.visible = false
}
if (activeApplet.fullRepresentationItem.footer && activeApplet.fullRepresentationItem.footer instanceof PlasmaExtras.PlasmoidHeading) {
mainStack.appletHasFooter = true
activeApplet.fullRepresentationItem.footer.background.visible = false
}
}
mainStack.replace({item: activeApplet.fullRepresentationItem, immediate: !systemTrayState.expanded, properties: {focus: true}});
} else {
mainStack.replace(emptyPage);
}
}
onCurrentItemChanged: {
if (currentItem !== null && plasmoid.expanded) {
currentItem.forceActiveFocus();
}
}
Connections {
target: plasmoid
function onAppletRemoved(applet) {
if (applet === systemTrayState.activeApplet) {
mainStack.clear()
}
}
}
//used to animate away to nothing
Item {
id: emptyPage
}
delegate: StackViewDelegate {
id: transitioner
function transitionFinished(properties) {
properties.exitItem.opacity = 1
}
property bool goingLeft: {
const unFlipped = systemTrayState.oldVisualIndex < systemTrayState.newVisualIndex
if (Qt.application.layoutDirection == Qt.LeftToRight) {
return unFlipped
} else {
return !unFlipped
}
}
replaceTransition: StackViewTransition {
ParallelAnimation {
PropertyAnimation {
target: enterItem
property: "x"
from: root.vertical ? 0 : (transitioner.goingLeft ? enterItem.width : -enterItem.width)
to: 0
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.shortDuration
}
SequentialAnimation {
PropertyAction {
target: enterItem
property: "opacity"
value: 0
}
PauseAnimation {
duration: root.vertical ? (PlasmaCore.Units.shortDuration/2) : 0
}
PropertyAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
easing.type: Easing.InOutQuad
duration: (PlasmaCore.Units.shortDuration/2)
}
}
}
ParallelAnimation {
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: root.vertical ? 0 : (transitioner.goingLeft ? -exitItem.width : exitItem.width)
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.shortDuration
}
PropertyAnimation {
target: exitItem
property: "opacity"
from: 1
to: 0
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.shortDuration/2
}
}
}
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2020 Konrad Materka <materka@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.12
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
//This object contains state of the SystemTray, mainly related to the 'expanded' state
QtObject {
//true if System Tray is 'expanded'. It may be when:
// - there is an active applet or
// - 'Status and Notification' with hidden items is shown
property bool expanded: false
//set when there is an applet selected
property Item activeApplet
//allow expanded change only when activated at least once
//this is to suppress expanded state change during Plasma startup
property bool acceptExpandedChange: false
// These properties allow us to keep track of where the expanded applet
// was and is on the panel, allowing PlasmoidPopupContainer.qml to animate
// depending on their locations.
property int oldVisualIndex: -1
property int newVisualIndex: -1
function setActiveApplet(applet, visualIndex) {
if (visualIndex === undefined) {
oldVisualIndex = -1
newVisualIndex = -1
} else {
oldVisualIndex = newVisualIndex
newVisualIndex = visualIndex
}
const oldApplet = activeApplet
activeApplet = applet
if (oldApplet && oldApplet !== applet) {
oldApplet.expanded = false
}
expanded = true
}
onExpandedChanged: {
if (expanded) {
plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus
} else {
plasmoid.status = PlasmaCore.Types.PassiveStatus;
if (activeApplet) {
// if not expanded we don't have an active applet anymore
activeApplet.expanded = false
activeApplet = null
}
}
acceptExpandedChange = false
plasmoid.expanded = expanded
}
//listen on SystemTray AppletInterface signals
property Connections plasmoidConnections: Connections {
target: plasmoid
//emitted when activation is requested, for example by using a global keyboard shortcut
function onActivated() {
acceptExpandedChange = true
}
//emitted when the configuration dialog is opened
function onUserConfiguringChanged() {
if (plasmoid.userConfiguring) {
systemTrayState.expanded = false
}
}
function onExpandedChanged() {
if (acceptExpandedChange) {
expanded = plasmoid.expanded
} else {
plasmoid.expanded = expanded
}
}
}
property Connections activeAppletConnections: Connections {
target: activeApplet
function onExpandedChanged() {
if (!activeApplet.expanded) {
expanded = false
}
}
}
}

View file

@ -0,0 +1,216 @@
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Konrad Materka <materka@gmail.com>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaCore.ToolTipArea {
id: abstractItem
height: inVisibleLayout ? visibleLayout.cellHeight : hiddenTasks.cellHeight
width: inVisibleLayout ? visibleLayout.cellWidth : hiddenTasks.cellWidth
property var model: itemModel
property string itemId
property alias text: label.text
property alias iconContainer: iconContainer
property int /*PlasmaCore.Types.ItemStatus*/ status: model.status || PlasmaCore.Types.UnknownStatus
property int /*PlasmaCore.Types.ItemStatus*/ effectiveStatus: model.effectiveStatus || PlasmaCore.Types.UnknownStatus
readonly property bool inHiddenLayout: effectiveStatus === PlasmaCore.Types.PassiveStatus
readonly property bool inVisibleLayout: effectiveStatus === PlasmaCore.Types.ActiveStatus
signal clicked(var mouse)
signal pressed(var mouse)
signal wheel(var wheel)
signal contextMenu(var mouse)
/* subclasses need to assign to this tooltip properties
mainText:
subText:
*/
location: {
if (inHiddenLayout) {
if (LayoutMirroring.enabled && plasmoid.location !== PlasmaCore.Types.RightEdge) {
return PlasmaCore.Types.LeftEdge;
} else if (plasmoid.location !== PlasmaCore.Types.LeftEdge) {
return PlasmaCore.Types.RightEdge;
}
}
return plasmoid.location;
}
//BEGIN CONNECTIONS
onContainsMouseChanged: {
if (inHiddenLayout && containsMouse) {
root.hiddenLayout.currentIndex = index
}
else if(!inHiddenLayout) {
itemHighLight.opacity = containsMouse ? 1 : 0
}
}
//END CONNECTIONS
PlasmaCore.FrameSvgItem {
id: itemHighLight
anchors.fill: parent
property int location
property bool animationEnabled: true
property var highlightedItem: null
z: -1 // always draw behind icons
opacity: 0
imagePath: "widgets/tabbar"
prefix: {
var prefix = ""
switch (location) {
case PlasmaCore.Types.LeftEdge:
prefix = "west-active-tab";
break;
case PlasmaCore.Types.TopEdge:
prefix = "north-active-tab";
break;
case PlasmaCore.Types.RightEdge:
prefix = "east-active-tab";
break;
default:
prefix = "south-active-tab";
}
if (!hasElementPrefix(prefix)) {
prefix = "active-tab";
}
return prefix;
}
Behavior on opacity {
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
//easing.type: systemTrayState.expanded ? Easing.OutCubic : Easing.InCubic
}
}
}
PulseAnimation {
targetItem: iconContainer
running: (abstractItem.status === PlasmaCore.Types.NeedsAttentionStatus ||
abstractItem.status === PlasmaCore.Types.RequiresAttentionStatus ) &&
PlasmaCore.Units.longDuration > 0
}
function activated() {
//activatedAnimation.start()
}
SequentialAnimation {
id: activatedAnimation
loops: 1
ScaleAnimator {
target: iconContainer
from: 1
to: 0.5
duration: PlasmaCore.Units.shortDuration
easing.type: Easing.InQuad
}
ScaleAnimator {
target: iconContainer
from: 0.5
to: 1
duration: PlasmaCore.Units.shortDuration
easing.type: Easing.OutQuad
}
}
MouseArea {
anchors.fill: abstractItem
hoverEnabled: true
drag.filterChildren: true
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onClicked: abstractItem.clicked(mouse)
onPressed: {
abstractItem.hideToolTip()
abstractItem.pressed(mouse)
}
onPressAndHold: {
abstractItem.contextMenu(mouse)
}
onWheel: {
abstractItem.wheel(wheel);
//Don't accept the event in order to make the scrolling by mouse wheel working
//for the parent scrollview this icon is in.
wheel.accepted = false;
}
}
ColumnLayout {
anchors.fill: abstractItem
spacing: 0
Item {
id: iconContainer
property alias container: abstractItem
property alias inVisibleLayout: abstractItem.inVisibleLayout
readonly property int size: abstractItem.inVisibleLayout ? root.itemSize : PlasmaCore.Units.iconSizes.medium
Layout.alignment: Qt.Bottom | Qt.AlignHCenter
Layout.fillHeight: abstractItem.inHiddenLayout ? true : false
implicitWidth: root.vertical && abstractItem.inVisibleLayout ? abstractItem.width : size
implicitHeight: !root.vertical && abstractItem.inVisibleLayout ? abstractItem.height : size
Layout.topMargin: abstractItem.inHiddenLayout ? Math.round(PlasmaCore.Units.smallSpacing * 1.5): 0
}
PlasmaComponents3.Label {
id: label
Layout.fillWidth: true
Layout.fillHeight: abstractItem.inHiddenLayout ? true : false
Layout.leftMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
Layout.rightMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
Layout.bottomMargin: abstractItem.inHiddenLayout ? PlasmaCore.Units.smallSpacing : 0
visible: abstractItem.inHiddenLayout
verticalAlignment: Text.AlignTop
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 3
opacity: visible ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2020 Konrad Materka <materka@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.0
Loader {
id: itemLoader
property var itemModel: model
source: {
if (model.itemType === "Plasmoid" && model.hasApplet) {
return "PlasmoidItem.qml"
} else if (model.itemType === "StatusNotifier") {
return "StatusNotifierItem.qml"
}
console.warn("SystemTray ItemLoader: Invalid state, cannot determine source!")
return ""
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright 2015 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQml 2.15
import org.kde.plasma.core 2.0 as PlasmaCore
AbstractItem {
id: plasmoidContainer
property Item applet: model.applet || null
text: applet ? applet.title : ""
itemId: applet ? applet.pluginName : ""
mainText: applet ? applet.toolTipMainText : ""
subText: applet ? applet.toolTipSubText : ""
mainItem: applet && applet.toolTipItem ? applet.toolTipItem : null
textFormat: applet ? applet.toolTipTextFormat : ""
active: systemTrayState.activeApplet !== applet
onClicked: {
if (!applet) {
return
}
//forward click event to the applet
if (mouse.button === Qt.LeftButton || mouse.button === Qt.MidButton) {
const mouseArea = findMouseArea(applet.compactRepresentationItem)
if (mouseArea) {
mouseArea.clicked(mouse)
} else if (mouse.button === Qt.LeftButton) {//falback
applet.expanded = true
}
}
}
onPressed: {
if (mouse.button === Qt.RightButton) {
plasmoidContainer.contextMenu(mouse);
}
}
onContextMenu: {
if (applet) {
plasmoid.nativeInterface.showPlasmoidMenu(applet, 0, plasmoidContainer.inHiddenLayout ? applet.height : 0);
}
}
onWheel: {
if (!applet) {
return
}
//forward wheel event to the applet
const mouseArea = findMouseArea(applet.compactRepresentationItem)
if (mouseArea) {
mouseArea.wheel(wheel)
}
}
//some heuristics to find MouseArea
function findMouseArea(item) {
if (!item) {
return null
}
if (item instanceof MouseArea) {
return item
}
for (var i = 0; i < item.children.length; i++) {
const child = item.children[i]
if (child instanceof MouseArea && child.enabled) {
//check if MouseArea covers the entire item
if (child.anchors.fill === item || (child.x === 0 && child.y === 0 && child.height === item.height && child.width === item.width)) {
return child
}
}
}
return null
}
//This is to make preloading effective, minimizes the scene changes
function preloadFullRepresentationItem(fullRepresentationItem) {
if (fullRepresentationItem && fullRepresentationItem.parent === null) {
fullRepresentationItem.width = expandedRepresentation.width
fullRepresentationItem.width = expandedRepresentation.height
fullRepresentationItem.parent = preloadedStorage;
}
}
onAppletChanged: {
if (applet) {
applet.parent = plasmoidContainer.iconContainer
applet.anchors.fill = applet.parent
applet.visible = true
preloadFullRepresentationItem(applet.fullRepresentationItem)
}
}
Connections {
target: applet
//activation using global keyboard shortcut
function onActivated() {
plasmoidContainer.activated()
}
function onExpandedChanged(expanded) {
if (expanded) {
systemTrayState.setActiveApplet(applet, model.row)
plasmoidContainer.activated()
}
}
function onFullRepresentationItemChanged(fullRepresentationItem) {
preloadFullRepresentationItem(fullRepresentationItem)
}
}
Binding {
property: "hideOnWindowDeactivate"
value: !plasmoid.configuration.pin
target: plasmoidContainer.applet
when: null !== plasmoidContainer.applet
restoreMode: Binding.RestoreBinding
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2015 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
SequentialAnimation {
id: pulseAnimation
objectName: "pulseAnimation"
property Item targetItem
readonly property int duration: PlasmaCore.Units.veryLongDuration * 5
loops: Animation.Infinite
alwaysRunToEnd: true
ScaleAnimator {
target: targetItem
from: 1
to: 1.2
duration: pulseAnimation.duration * 0.15
easing.type: Easing.InQuad
}
ScaleAnimator {
target: targetItem
from: 1.2
to: 1
duration: pulseAnimation.duration * 0.15
easing.type: Easing.InQuad
}
PauseAnimation {
duration: pulseAnimation.duration * 0.7
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright 2016 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import org.kde.plasma.core 2.0 as PlasmaCore
AbstractItem {
id: taskIcon
itemId: model.Id
text: model.Title || model.ToolTipTitle
mainText: model.ToolTipTitle !== "" ? model.ToolTipTitle : model.Title
subText: model.ToolTipSubTitle
textFormat: Text.AutoText
PlasmaCore.IconItem {
id: iconItem
parent: taskIcon.iconContainer
anchors.fill: iconItem.parent
source: {
if (model.status === PlasmaCore.Types.NeedsAttentionStatus) {
if (model.AttentionIcon) {
return model.AttentionIcon
}
if (model.AttentionIconName) {
return model.AttentionIconName
}
}
return model.Icon ? model.Icon : model.IconName
}
active: taskIcon.containsMouse
}
onContextMenu: {
openContextMenu(plasmoid.nativeInterface.popupPosition(taskIcon, mouse.x, mouse.y))
}
onClicked: {
var pos = plasmoid.nativeInterface.popupPosition(taskIcon, mouse.x, mouse.y);
var service = model.Service;
switch (mouse.button) {
case Qt.LeftButton:
var operation = service.operationDescription("Activate");
operation.x = pos.x;
operation.y = pos.y;
var job = service.startOperationCall(operation);
job.finished.connect(function () {
if (!job.result) {
// On error try to invoke the context menu.
// Workaround primarily for apps using libappindicator.
openContextMenu(pos);
}
});
taskIcon.activated()
break;
case Qt.RightButton:
openContextMenu(pos);
break;
case Qt.MiddleButton:
var operation = service.operationDescription("SecondaryActivate");
operation.x = pos.x;
operation.y = pos.y;
service.startOperationCall(operation);
taskIcon.activated()
break;
}
}
function openContextMenu(pos) {
var service = model.Service;
var operation = service.operationDescription("ContextMenu");
operation.x = pos.x;
operation.y = pos.y;
var job = service.startOperationCall(operation);
job.finished.connect(function () {
plasmoid.nativeInterface.showStatusNotifierContextMenu(job, taskIcon);
});
}
onWheel: {
//don't send activateVertScroll with a delta of 0, some clients seem to break (kmix)
if (wheel.angleDelta.y !== 0) {
var service = model.Service;
var operation = service.operationDescription("Scroll");
operation.delta =wheel.angleDelta.y;
operation.direction = "Vertical";
service.startOperationCall(operation);
}
if (wheel.angleDelta.x !== 0) {
var service = model.Service;
var operation = service.operationDescription("Scroll");
operation.delta =wheel.angleDelta.x;
operation.direction = "Horizontal";
service.startOperationCall(operation);
}
}
}

View file

@ -0,0 +1,238 @@
/*
* Copyright 2011 Marco Martin <mart@kde.org>
* Copyright 2020 Konrad Materka <materka@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.draganddrop 2.0 as DnD
import org.kde.kirigami 2.5 as Kirigami
import "items"
MouseArea {
id: root
readonly property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical
Layout.minimumWidth: vertical ? PlasmaCore.Units.iconSizes.small : mainLayout.implicitWidth + PlasmaCore.Units.smallSpacing
Layout.minimumHeight: vertical ? mainLayout.implicitHeight + PlasmaCore.Units.smallSpacing : PlasmaCore.Units.iconSizes.small
LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
readonly property alias systemTrayState: systemTrayState
readonly property alias itemSize: tasksGrid.itemSize
readonly property alias visibleLayout: tasksGrid
readonly property alias hiddenLayout: expandedRepresentation.hiddenLayout
onWheel: {
// Don't propagate unhandled wheel events
wheel.accepted = true;
}
SystemTrayState {
id: systemTrayState
}
//being there forces the items to fully load, and they will be reparented in the popup one by one, this item is *never* visible
Item {
id: preloadedStorage
visible: false
}
CurrentItemHighLight {
location: plasmoid.location
parent: root
}
DnD.DropArea {
anchors.fill: parent
preventStealing: true;
/** Extracts the name of the system tray applet in the drag data if present
* otherwise returns null*/
function systemTrayAppletName(event) {
if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") < 0) {
return null;
}
var plasmoidId = event.mimeData.getDataAsByteArray("text/x-plasmoidservicename");
if (!plasmoid.nativeInterface.isSystemTrayApplet(plasmoidId)) {
return null;
}
return plasmoidId;
}
onDragEnter: {
if (!systemTrayAppletName(event)) {
event.ignore();
}
}
onDrop: {
var plasmoidId = systemTrayAppletName(event);
if (!plasmoidId) {
event.ignore();
return;
}
if (plasmoid.configuration.extraItems.indexOf(plasmoidId) < 0) {
var extraItems = plasmoid.configuration.extraItems;
extraItems.push(plasmoidId);
plasmoid.configuration.extraItems = extraItems;
}
}
}
//Main Layout
GridLayout {
id: mainLayout
rowSpacing: 0
columnSpacing: 0
anchors.fill: parent
flow: vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
GridView {
id: tasksGrid
Layout.alignment: Qt.AlignCenter
interactive: false //disable features we don't need
flow: vertical ? GridView.LeftToRight : GridView.TopToBottom
// The icon size to display when not using the auto-scaling setting
readonly property int smallIconSize: PlasmaCore.Units.iconSizes.smallMedium
readonly property bool autoSize: plasmoid.configuration.scaleIconsToFit
readonly property int gridThickness: root.vertical ? root.width : root.height
// Should change to 2 rows/columns on a 56px panel (in standard DPI)
readonly property int rowsOrColumns: autoSize ? 1 : Math.max(1, Math.min(count, Math.floor(gridThickness / (smallIconSize + PlasmaCore.Units.smallSpacing))))
// Add margins only if the panel is larger than a small icon (to avoid large gaps between tiny icons)
readonly property int smallSizeCellLength: gridThickness < smallIconSize ? smallIconSize : smallIconSize + PlasmaCore.Units.smallSpacing * 2
cellHeight: {
if (root.vertical) {
return autoSize ? root.width + PlasmaCore.Units.smallSpacing : smallSizeCellLength
} else {
return autoSize ? root.height : Math.floor(root.height / rowsOrColumns)
}
}
cellWidth: {
if (root.vertical) {
return autoSize ? root.width : Math.floor(root.width / rowsOrColumns)
} else {
return autoSize ? root.height + PlasmaCore.Units.smallSpacing : smallSizeCellLength
}
}
//depending on the form factor, we are calculating only one dimention, second is always the same as root/parent
implicitHeight: root.vertical ? cellHeight * Math.ceil(count / rowsOrColumns) : root.height
implicitWidth: !root.vertical ? cellWidth * Math.ceil(count / rowsOrColumns) : root.width
// Used only by AbstractItem, but it's easiest to keep it here since it
// uses dimensions from this item to calculate the final value
readonly property int itemSize: {
if (autoSize) {
const size = Math.min(implicitWidth / rowsOrColumns, implicitHeight / rowsOrColumns)
return PlasmaCore.Units.roundToIconSize(Math.min(size, PlasmaCore.Units.iconSizes.enormous))
} else {
return smallIconSize
}
}
model: PlasmaCore.SortFilterModel {
sourceModel: plasmoid.nativeInterface.systemTrayModel
filterRole: "effectiveStatus"
filterCallback: function(source_row, value) {
return value === PlasmaCore.Types.ActiveStatus
}
}
delegate: ItemLoader {}
add: Transition {
enabled: itemSize > 0
NumberAnimation {
property: "scale"
from: 0
to: 1
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.longDuration
}
}
displaced: Transition {
//ensure scale value returns to 1.0
//https://doc.qt.io/qt-5/qml-qtquick-viewtransition.html#handling-interrupted-animations
NumberAnimation {
property: "scale"
to: 1
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.longDuration
}
}
move: Transition {
NumberAnimation {
properties: "x,y"
easing.type: Easing.InOutQuad
duration: PlasmaCore.Units.longDuration
}
}
}
ExpanderArrow {
id: expander
Layout.fillWidth: vertical
Layout.fillHeight: !vertical
Layout.alignment: vertical ? Qt.AlignVCenter : Qt.AlignHCenter
visible: root.hiddenLayout.itemCount > 0
}
}
//Main popup
PlasmaCore.Dialog {
id: dialog
visualParent: root
flags: Qt.WindowStaysOnTopHint
location: plasmoid.location
hideOnWindowDeactivate: !plasmoid.configuration.pin
visible: systemTrayState.expanded
onVisibleChanged: {
systemTrayState.expanded = visible
}
mainItem: ExpandedRepresentation {
id: expandedRepresentation
Keys.onEscapePressed: {
systemTrayState.expanded = false
}
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
}
}
}

View file

@ -0,0 +1,108 @@
[Desktop Entry]
Name=System Tray
Name[af]=Stelsellaai
Name[ar]=صينية النظام
Name[ast]=Bandexa del sistema
Name[az]=Sistem Çəkməcəsi
Name[be]=Сістэмны трэй
Name[be@latin]=Systemny trej
Name[bg]=Системен панел
Name[bn]=ি
Name[bn_IN]=ি
Name[br]=Barlenn ar reizhiad
Name[bs]=Sistemska kaseta
Name[ca]=Safata del sistema
Name[ca@valencia]=Safata del sistema
Name[cs]=Systémová část panelu
Name[csb]=Systemòwi zabiérnik
Name[cy]=Bar Tasgau
Name[da]=Statusområde
Name[de]=Systemabschnitt der Kontrollleiste
Name[el]=Πλαίσιο συστήματος
Name[en_GB]=System Tray
Name[eo]=Sistempleto
Name[es]=Bandeja del sistema
Name[et]=Süsteemne dokk
Name[eu]=Sistema-erretilua
Name[fa]=سینی سیستم
Name[fi]=Ilmoitusalue
Name[fr]=Boîte à miniatures
Name[fy]=Systeemfak
Name[ga]=Tráidire an Chórais
Name[gl]=Bandexa do sistema
Name[gu]=િ
Name[he]=מגש המערכת
Name[hi]=
Name[hne]=
Name[hr]=Sistemski blok
Name[hsb]=Systemowa wotkładka
Name[hu]=Paneltálca
Name[ia]=Tabuliero de systema
Name[id]=System Tray
Name[is]=Kerfisbakki
Name[it]=Vassoio di sistema
Name[ja]=
Name[ka]=
Name[kk]=Жүйелік сөре
Name[km]=
Name[kn]= ()
Name[ko]=
Name[lt]=Sistemos dėklas
Name[lv]=Sistēmas ikonu josla
Name[mai]=
Name[mk]=Системска лента
Name[ml]=ി
Name[mr]=
Name[ms]=Dulang Sistem
Name[nb]=Systemkurv
Name[nds]=Paneel-Systeemafsnitt
Name[ne]=
Name[nl]=Systeemvak
Name[nn]=Systemtrau
Name[or]=
Name[pa]=ਿ
Name[pl]=Tacka systemowa
Name[pt]=Bandeja do Sistema
Name[pt_BR]=Área de notificação
Name[ro]=Tavă de sistem
Name[ru]=Системный лоток
Name[se]=Vuogádatgárcu
Name[si]=
Name[sk]=Systémová lišta
Name[sl]=Sistemska vrstica
Name[sr]=системска касета
Name[sr@ijekavian]=системска касета
Name[sr@ijekavianlatin]=sistemska kaseta
Name[sr@latin]=sistemska kaseta
Name[sv]=Systembricka
Name[ta]=
Name[te]=
Name[tg]=Лавҳачаи низомӣ
Name[th]=
Name[tr]=Sistem Çekmecesi
Name[ug]=سىستېما قوندىقى
Name[uk]=Системний лоток
Name[vi]=Khay h thng
Name[wa]=Boesse ås imådjetes sistinme
Name[xh]=Itreyi Yendlela yokusebenza
Name[x-test]=xxSystem Trayxx
Name[zh_CN]=
Name[zh_TW]=
Icon=preferences-desktop-notification
Type=Service
X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-KDE-PluginInfo-Author=Marco Martin
X-KDE-PluginInfo-Email=mart@kde.org
X-KDE-PluginInfo-Name=org.kde.plasma.private.systemtray
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=https://www.kde.org/plasma-desktop
X-KDE-PluginInfo-Category=Windows and Tasks
X-KDE-PluginInfo-License=GPL-2.0+
X-KDE-PluginInfo-EnabledByDefault=true
X-Plasma-ContainmentType=Panel
#this is the internal implementation: can't be loaded directly
NoDisplay=true
X-KDE-FormFactors=desktop

View file

@ -0,0 +1,117 @@
{
"KPlugin": {
"Authors": [
{
"Email": "mart@kde.org",
"Name": "Marco Martin"
}
],
"Category": "Windows and Tasks",
"EnabledByDefault": true,
"FormFactors": [
"desktop"
],
"Icon": "preferences-desktop-notification",
"Id": "org.kde.plasma.private.systemtray",
"License": "GPL-2.0+",
"Name": "System Tray",
"Name[af]": "Stelsellaai",
"Name[ar]": "صينية النظام",
"Name[ast]": "Bandexa del sistema",
"Name[az]": "Sistem Çəkməcəsi",
"Name[be@latin]": "Systemny trej",
"Name[be]": "Сістэмны трэй",
"Name[bg]": "Системен панел",
"Name[bn]": "সিস্টেম ট্রে",
"Name[bn_IN]": "সিস্টেম ট্রে",
"Name[br]": "Barlenn ar reizhiad",
"Name[bs]": "Sistemska kaseta",
"Name[ca@valencia]": "Safata del sistema",
"Name[ca]": "Safata del sistema",
"Name[cs]": "Systémová část panelu",
"Name[csb]": "Systemòwi zabiérnik",
"Name[cy]": "Bar Tasgau",
"Name[da]": "Statusområde",
"Name[de]": "Systemabschnitt der Kontrollleiste",
"Name[el]": "Πλαίσιο συστήματος",
"Name[en_GB]": "System Tray",
"Name[eo]": "Sistempleto",
"Name[es]": "Bandeja del sistema",
"Name[et]": "Süsteemne dokk",
"Name[eu]": "Sistema-erretilua",
"Name[fa]": "سینی سیستم",
"Name[fi]": "Ilmoitusalue",
"Name[fr]": "Boîte à miniatures",
"Name[fy]": "Systeemfak",
"Name[ga]": "Tráidire an Chórais",
"Name[gl]": "Bandexa do sistema",
"Name[gu]": "સિસ્ટમ ટ્રે",
"Name[he]": "מגש המערכת",
"Name[hi]": "तंत्र तश्तरी",
"Name[hne]": "तंत्र तस्तरी",
"Name[hr]": "Sistemski blok",
"Name[hsb]": "Systemowa wotkładka",
"Name[hu]": "Paneltálca",
"Name[ia]": "Tabuliero de systema",
"Name[id]": "System Tray",
"Name[is]": "Kerfisbakki",
"Name[it]": "Vassoio di sistema",
"Name[ja]": "システムトレイ",
"Name[ka]": "სისტემური პანელი",
"Name[kk]": "Жүйелік сөре",
"Name[km]": "ថាស​ប្រព័ន្ធ",
"Name[kn]": "ವ್ಯವಸ್ಥಾ ಖಾನೆ (ಟ್ರೇ)",
"Name[ko]": "시스템 트레이",
"Name[lt]": "Sistemos dėklas",
"Name[lv]": "Sistēmas ikonu josla",
"Name[mai]": "तंत्र तश्तरी",
"Name[mk]": "Системска лента",
"Name[ml]": "സിസ്റ്റം ട്രേ",
"Name[mr]": "प्रणाली ट्रे",
"Name[ms]": "Dulang Sistem",
"Name[nb]": "Systemkurv",
"Name[nds]": "Paneel-Systeemafsnitt",
"Name[ne]": "प्रणाली ट्रे",
"Name[nl]": "Systeemvak",
"Name[nn]": "Systemtrau",
"Name[or]": "ତନ୍ତ୍ର ଧାରକ",
"Name[pa]": "ਸਿਸਟਮ ਟਰੇ",
"Name[pl]": "Tacka systemowa",
"Name[pt]": "Bandeja do Sistema",
"Name[pt_BR]": "Área de notificação",
"Name[ro]": "Tavă de sistem",
"Name[ru]": "Системный лоток",
"Name[se]": "Vuogádatgárcu",
"Name[si]": "පද්ධතිය තැටිය",
"Name[sk]": "Systémová lišta",
"Name[sl]": "Sistemska vrstica",
"Name[sr@ijekavian]": "системска касета",
"Name[sr@ijekavianlatin]": "sistemska kaseta",
"Name[sr@latin]": "sistemska kaseta",
"Name[sr]": "системска касета",
"Name[sv]": "Systembricka",
"Name[ta]": "சாதனத் தட்டு",
"Name[te]": "వ్యవస్థ ట్రె",
"Name[tg]": "Лавҳачаи низомӣ",
"Name[th]": "ถาดระบบ",
"Name[tr]": "Sistem Çekmecesi",
"Name[ug]": "سىستېما قوندىقى",
"Name[uk]": "Системний лоток",
"Name[vi]": "Khay hệ thống",
"Name[wa]": "Boesse ås imådjetes sistinme",
"Name[x-test]": "xxSystem Trayxx",
"Name[xh]": "Itreyi Yendlela yokusebenza",
"Name[zh_CN]": "系统托盘",
"Name[zh_TW]": "系統匣",
"ServiceTypes": [
"Plasma/Applet",
"Plasma/Containment"
],
"Version": "1.0",
"Website": "https://www.kde.org/plasma-desktop"
},
"NoDisplay": true,
"X-Plasma-API": "declarativeappletscript",
"X-Plasma-ContainmentType": "Panel",
"X-Plasma-MainScript": "ui/main.qml"
}

View file

@ -91,6 +91,10 @@ there are any improvements to be made here, any and all effort would be greatly
<img src="Screenshots/Taskbar.png">
### System Tray
<img src="Screenshots/System_Tray.png">
### Plasma Style
<img src="Screenshots/Notification.png">
@ -272,6 +276,16 @@ or inconsistencies, for now post them in the next desktop threads.
Make sure that your panel's width is set to 40. Also make sure that you're using the ```Icons-only Task Manager``` widget to make it look closer to Windows 7.
#### Modified System Tray
This modification will add hover animations to the default system tray plasmoid, as well as remove the annoying popup animation which happens upon clicking on an item.
Since the system tray is a complex plasmoid, its files have to be replaced with a modified version provided in this theme. To do this, copy the ```org.kde.plasma.private.systemtray``` found in the ```Plasma Widgets``` folder to the following directory:
```/usr/share/plasma/plasmoids/```
This will override the default System Tray plasmoid. It is not recommended to edit this particular plasmoid, so proceed with caution. Make sure to back up the original plasmoid somewhere safe.
#### Digital Clock Lite
Install the widget ```Digital Clock Lite``` (https://www.kde-look.org/p/1225135/) and replace the ugly large clock widget with
@ -282,6 +296,8 @@ it. By default it should already look a lot like Windows 7's clock, but if it do
You can tweak the other settings to your liking.
#### Show Desktop (Win7)
Lastly, install the ```Show Desktop (Win7)``` widget (https://www.kde-look.org/p/1100895/) and configure it to these settings:
In Look:

BIN
Screenshots/System_Tray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB