mirror of
https://gitgud.io/wackyideas/aerothemeplasma.git
synced 2024-08-15 00:43:43 +00:00
Very early KDE 6 release.
This commit is contained in:
parent
7cc4ccabbc
commit
686046d4f7
6272 changed files with 140920 additions and 529657 deletions
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
PlasmaCore.ToolTipArea {
|
||||
id: appletRoot
|
||||
objectName: "org.kde.desktop-CompactApplet"
|
||||
anchors.fill: parent
|
||||
|
||||
mainText: plasmoidItem ? plasmoidItem.toolTipMainText : ""
|
||||
subText: plasmoidItem ? plasmoidItem.toolTipSubText : ""
|
||||
location: if (plasmoidItem && plasmoidItem.parent && plasmoidItem.parent.inHiddenLayout && Plasmoid.location !== PlasmaCore.Types.LeftEdge) {
|
||||
return PlasmaCore.Types.RightEdge;
|
||||
} else {
|
||||
return Plasmoid.location;
|
||||
}
|
||||
active: plasmoidItem ? !plasmoidItem.expanded : 0
|
||||
textFormat: plasmoidItem ? plasmoidItem.toolTipTextFormat : 0
|
||||
mainItem: plasmoidItem && plasmoidItem.toolTipItem ? plasmoidItem.toolTipItem : null
|
||||
|
||||
property Item fullRepresentation
|
||||
property Item compactRepresentation
|
||||
property PlasmoidItem plasmoidItem
|
||||
|
||||
Connections {
|
||||
target: Plasmoid
|
||||
function onContextualActionsAboutToShow() {
|
||||
appletRoot.hideImmediately()
|
||||
}
|
||||
}
|
||||
|
||||
Layout.minimumWidth: {
|
||||
switch (Plasmoid.formFactor) {
|
||||
case PlasmaCore.Types.Vertical:
|
||||
return 0;
|
||||
case PlasmaCore.Types.Horizontal:
|
||||
return height;
|
||||
default:
|
||||
return Kirigami.Units.gridUnit * 3;
|
||||
}
|
||||
}
|
||||
|
||||
Layout.minimumHeight: {
|
||||
switch (Plasmoid.formFactor) {
|
||||
case PlasmaCore.Types.Vertical:
|
||||
return width;
|
||||
case PlasmaCore.Types.Horizontal:
|
||||
return 0;
|
||||
default:
|
||||
return Kirigami.Units.gridUnit * 3;
|
||||
}
|
||||
}
|
||||
|
||||
onCompactRepresentationChanged: {
|
||||
if (compactRepresentation) {
|
||||
compactRepresentation.parent = appletRoot;
|
||||
compactRepresentation.anchors.fill = appletRoot;
|
||||
compactRepresentation.visible = true;
|
||||
}
|
||||
appletRoot.visible = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
import org.kde.plasma.configuration 2.0
|
||||
|
||||
ConfigModel {
|
||||
ConfigCategory {
|
||||
name: i18n("General")
|
||||
icon: "preferences-desktop-plasma"
|
||||
source: "ConfigGeneral.qml"
|
||||
}
|
||||
ConfigCategory {
|
||||
name: i18n("Entries")
|
||||
icon: "preferences-desktop-notification"
|
||||
source: "ConfigEntries.qml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?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="iconSpacing" type="int">
|
||||
<label>spacing between icons, determined by this number multiplied by Kirigami.Units.smallSpacing</label>
|
||||
<default>2</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>
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
SPDX-FileCopyrightText: 2014 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2019 Konrad Materka <materka@gmail.com>
|
||||
SPDX-FileCopyrightText: 2022 ivan (@ratijas) tkachenko <me@ratijas.tk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.kquickcontrols 2.0 as KQC
|
||||
import org.kde.kirigami 2.10 as Kirigami
|
||||
import org.kde.kitemmodels 1.0
|
||||
import org.kde.kcmutils as KCM
|
||||
|
||||
KCM.ScrollViewKCM {
|
||||
id: iconsPage
|
||||
|
||||
signal configurationChanged
|
||||
|
||||
property var cfg_shownItems: []
|
||||
property var cfg_hiddenItems: []
|
||||
property var cfg_extraItems: []
|
||||
property alias cfg_showAllItems: showAllCheckBox.checked
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
header: Kirigami.SearchField {
|
||||
id: filterField
|
||||
}
|
||||
|
||||
view: ListView {
|
||||
id: itemsList
|
||||
|
||||
property real visibilityColumnWidth: Kirigami.Units.iconSizes.small
|
||||
property real keySequenceColumnWidth: Kirigami.Units.iconSizes.small
|
||||
readonly property int iconSize: Kirigami.Units.iconSizes.smallMedium
|
||||
|
||||
clip: true
|
||||
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: Plasmoid.configSystemTrayModel
|
||||
filterString: filterField.text
|
||||
filterCaseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
reuseItems: true
|
||||
|
||||
header: RowLayout {
|
||||
width: itemsList.width
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Item {
|
||||
implicitWidth: itemsList.iconSize + 2 * Kirigami.Units.smallSpacing
|
||||
}
|
||||
Kirigami.Heading {
|
||||
text: i18nc("Name of the system tray entry", "Entry")
|
||||
level: 2
|
||||
elide: Text.ElideRight
|
||||
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
|
||||
Layout.rightMargin: 2 * Kirigami.Units.smallSpacing
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
property: "category"
|
||||
delegate: Kirigami.ListSectionHeader {
|
||||
label: categoryName(section)
|
||||
width: itemsList.width
|
||||
}
|
||||
}
|
||||
|
||||
delegate: QQC2.ItemDelegate {
|
||||
id: listItem
|
||||
|
||||
width: itemsList.width
|
||||
|
||||
// Don't need highlight, hover, or pressed effects
|
||||
highlighted: false
|
||||
hoverEnabled: false
|
||||
down: false
|
||||
|
||||
readonly property bool isPlasmoid: model.itemType === "Plasmoid"
|
||||
|
||||
contentItem: FocusScope {
|
||||
implicitHeight: childrenRect.height
|
||||
|
||||
onActiveFocusChanged: if (activeFocus) {
|
||||
listItem.ListView.view.positionViewAtIndex(index, ListView.Contain);
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Kirigami.Icon {
|
||||
implicitWidth: itemsList.iconSize
|
||||
implicitHeight: itemsList.iconSize
|
||||
source: model.decoration
|
||||
animated: false
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.display
|
||||
elide: Text.ElideRight
|
||||
|
||||
QQC2.ToolTip {
|
||||
visible: listItem.hovered && parent.truncated
|
||||
text: parent.text
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ComboBox {
|
||||
id: visibilityComboBox
|
||||
|
||||
property real 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"
|
||||
valueRole: "value"
|
||||
model: comboBoxModel()
|
||||
|
||||
currentIndex: {
|
||||
let 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 (let i = 0; i < model.length; i++) {
|
||||
if (model[i].value === value) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
const shownIndex = cfg_shownItems.indexOf(itemId)
|
||||
const hiddenIndex = cfg_hiddenItems.indexOf(itemId)
|
||||
const extraIndex = cfg_extraItems.indexOf(itemId)
|
||||
|
||||
switch (currentValue) {
|
||||
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() {
|
||||
const autoElement = {"value": "auto", "text": i18n("Shown when relevant")}
|
||||
const shownElement = {"value": "shown", "text": i18n("Always shown")}
|
||||
const hiddenElement = {"value": "hidden", "text": i18n("Always hidden")}
|
||||
const 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.currentValue !== "disabled"
|
||||
keySequence: model.applet ? model.applet.plasmoid.globalShortcut : ""
|
||||
onCaptureFinished: {
|
||||
if (model.applet && keySequence !== model.applet.plasmoid.globalShortcut) {
|
||||
model.applet.plasmoid.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.plasmoid.internalAction("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, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: QQC2.CheckBox {
|
||||
id: showAllCheckBox
|
||||
text: i18n("Always show all entries")
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14 as QQC2
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
|
||||
import org.kde.kirigami 2.13 as Kirigami
|
||||
import org.kde.kcmutils as KCM
|
||||
|
||||
KCM.SimpleKCM {
|
||||
property bool cfg_scaleIconsToFit
|
||||
property int cfg_iconSpacing
|
||||
|
||||
Kirigami.FormLayout {
|
||||
Layout.fillHeight: true
|
||||
|
||||
QQC2.RadioButton {
|
||||
Kirigami.FormData.label: i18nc("The arrangement of system tray icons in the Panel", "Panel icon size:")
|
||||
enabled: !Kirigami.Settings.tabletMode
|
||||
text: i18n("Small")
|
||||
checked: cfg_scaleIconsToFit == false && !Kirigami.Settings.tabletMode
|
||||
onToggled: cfg_scaleIconsToFit = !checked
|
||||
}
|
||||
QQC2.RadioButton {
|
||||
id: automaticRadioButton
|
||||
enabled: !Kirigami.Settings.tabletMode
|
||||
text: Plasmoid.formFactor === PlasmaCore.Types.Horizontal ? i18n("Scale with Panel height")
|
||||
: i18n("Scale with Panel width")
|
||||
checked: cfg_scaleIconsToFit == true || Kirigami.Settings.tabletMode
|
||||
onToggled: cfg_scaleIconsToFit = checked
|
||||
}
|
||||
QQC2.Label {
|
||||
visible: Kirigami.Settings.tabletMode
|
||||
text: i18n("Automatically enabled when in Touch Mode")
|
||||
font: Kirigami.Theme.smallFont
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
}
|
||||
|
||||
QQC2.ComboBox {
|
||||
Kirigami.FormData.label: i18nc("@label:listbox The spacing between system tray icons in the Panel", "Panel icon spacing:")
|
||||
model: [
|
||||
{
|
||||
"label": i18nc("@item:inlistbox Icon spacing", "Small"),
|
||||
"spacing": 1
|
||||
},
|
||||
{
|
||||
"label": i18nc("@item:inlistbox Icon spacing", "Normal"),
|
||||
"spacing": 2
|
||||
},
|
||||
{
|
||||
"label": i18nc("@item:inlistbox Icon spacing", "Large"),
|
||||
"spacing": 6
|
||||
}
|
||||
]
|
||||
textRole: "label"
|
||||
enabled: !Kirigami.Settings.tabletMode
|
||||
|
||||
currentIndex: {
|
||||
if (Kirigami.Settings.tabletMode) {
|
||||
return 2; // Large
|
||||
}
|
||||
|
||||
switch (cfg_iconSpacing) {
|
||||
case 1: return 0; // Small
|
||||
case 2: return 1; // Normal
|
||||
case 6: return 2; // Large
|
||||
}
|
||||
}
|
||||
|
||||
onActivated: cfg_iconSpacing = model[currentIndex]["spacing"];
|
||||
}
|
||||
QQC2.Label {
|
||||
visible: Kirigami.Settings.tabletMode
|
||||
text: i18nc("@info:usagetip under a combobox when Touch Mode is on", "Automatically set to Large when in Touch Mode")
|
||||
font: Kirigami.Theme.smallFont
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.ksvg 1.0 as KSvg
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
|
||||
KSvg.FrameSvgItem {
|
||||
id: currentItemHighLight
|
||||
|
||||
property int location
|
||||
|
||||
property bool animationEnabled: true
|
||||
property var highlightedItem: null
|
||||
|
||||
property var containerMargins: {
|
||||
return 0;
|
||||
let item = currentItemHighLight;
|
||||
while (item.parent) {
|
||||
item = item.parent;
|
||||
if (item.isAppletContainer) {
|
||||
return item.getMargins;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
z: -1 // always draw behind icons
|
||||
opacity: systemTrayState.expanded ? 0.8 : 0
|
||||
|
||||
imagePath: Qt.resolvedUrl("svgs/tabbar.svgz")
|
||||
prefix: {
|
||||
let 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, /*forceEdgeHighlight*/false);
|
||||
} else { // 'Show hidden items' popup
|
||||
changeHighlightedItem(parent, /*forceEdgeHighlight*/true);
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
} else {
|
||||
highlightedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
function changeHighlightedItem(nextItem, forceEdgeHighlight) {
|
||||
// do not animate the first appearance
|
||||
// or when the property value of a highlighted item changes
|
||||
if (!highlightedItem || (highlightedItem === nextItem)) {
|
||||
animationEnabled = false;
|
||||
}
|
||||
|
||||
const p = parent.mapFromItem(nextItem, 0, 0);
|
||||
if (containerMargins && (parent.oneRowOrColumn || forceEdgeHighlight)) {
|
||||
x = p.x - containerMargins('left', /*returnAllMargins*/true);
|
||||
y = p.y - containerMargins('top', /*returnAllMargins*/true);
|
||||
width = nextItem.width + containerMargins('left', /*returnAllMargins*/true) + containerMargins('right', /*returnAllMargins*/true);
|
||||
height = nextItem.height + containerMargins('bottom', /*returnAllMargins*/true) + containerMargins('top', /*returnAllMargins*/true);
|
||||
} else {
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
width = nextItem.width
|
||||
height = nextItem.height
|
||||
}
|
||||
|
||||
highlightedItem = nextItem;
|
||||
animationEnabled = true;
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
}
|
||||
/*Behavior on x {
|
||||
id: xAnim
|
||||
enabled: animationEnabled
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
id: yAnim
|
||||
enabled: animationEnabled
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
Behavior on width {
|
||||
id: widthAnim
|
||||
enabled: animationEnabled
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
Behavior on height {
|
||||
id: heightAnim
|
||||
enabled: animationEnabled
|
||||
NumberAnimation {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 Nate Graham <nate@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Window 2.15
|
||||
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
Item {
|
||||
id: popup
|
||||
|
||||
property int flyoutWidth: hiddenItemsView.visible ? hiddenItemsView.width + Kirigami.Units.smallSpacing*2 : (intendedWidth != -1 ? intendedWidth : Kirigami.Units.iconSizes.small * 19)
|
||||
property int flyoutHeight: hiddenItemsView.visible ?
|
||||
hiddenItemsView.implicitHeight + trayHeading.height + Kirigami.Units.largeSpacing :
|
||||
(container.flyoutImplicitHeight > (Kirigami.Units.iconSizes.small * 19 - trayHeading.height - Kirigami.Units.largeSpacing) ? container.flyoutImplicitHeight + container.headingHeight + container.footerHeight + trayHeading.height + Kirigami.Units.largeSpacing*4 : Kirigami.Units.iconSizes.small*19)
|
||||
//: Kirigami.Units.iconSizes.small * 19
|
||||
Layout.minimumWidth: flyoutWidth
|
||||
Layout.minimumHeight: flyoutHeight
|
||||
|
||||
Layout.maximumWidth: flyoutWidth
|
||||
Layout.maximumHeight: flyoutHeight
|
||||
|
||||
function updateHeight() {
|
||||
//console.log(container.flyoutImplicitHeight + " " + (Kirigami.Units.iconSizes.small * 19 - trayHeading.height - Kirigami.Units.largeSpacing));
|
||||
//console.log(container.flyoutImplicitHeight + container.headingHeight + container.footerHeight + trayHeading.height + Kirigami.Units.largeSpacing*4 + " new height")
|
||||
flyoutHeight = Qt.binding(() => hiddenItemsView.visible ?
|
||||
hiddenItemsView.implicitHeight + trayHeading.height + Kirigami.Units.largeSpacing :
|
||||
(container.flyoutImplicitHeight > (Kirigami.Units.iconSizes.small * 19 - trayHeading.height - Kirigami.Units.largeSpacing) ? container.flyoutImplicitHeight + container.headingHeight + container.footerHeight + trayHeading.height + Kirigami.Units.largeSpacing*4 : Kirigami.Units.iconSizes.small*19))
|
||||
popup.Layout.minimumHeight = Qt.binding(() => flyoutHeight);
|
||||
popup.Layout.maximumHeight = Qt.binding(() => flyoutHeight);
|
||||
}
|
||||
|
||||
property bool shownDialog: dialog.visible
|
||||
//property bool changedItems: false
|
||||
property int intendedWidth: container.activeApplet ? (typeof container.activeApplet.fullRepresentationItem.flyoutIntendedWidth !== "undefined" ? container.activeApplet.fullRepresentationItem.flyoutIntendedWidth : -1) : -1
|
||||
|
||||
onShownDialogChanged: {
|
||||
//changedItems = false;
|
||||
updateHeight();
|
||||
}
|
||||
|
||||
property alias hiddenLayout: hiddenItemsView.layout
|
||||
property alias plasmoidContainer: container
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
// Header
|
||||
ToolButton {
|
||||
id: pinButton
|
||||
visible: !hiddenItemsView.visible
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: Kirigami.Units.largeSpacing
|
||||
anchors.rightMargin: Kirigami.Units.largeSpacing
|
||||
width: Kirigami.Units.iconSizes.small+1;
|
||||
height: Kirigami.Units.iconSizes.small;
|
||||
checkable: true
|
||||
checked: Plasmoid.configuration.pin
|
||||
|
||||
onClicked: (mouse) => {
|
||||
Plasmoid.configuration.pin = !Plasmoid.configuration.pin;
|
||||
}
|
||||
buttonIcon: "pin"
|
||||
|
||||
z: 9999
|
||||
|
||||
//KeyNavigation.down: backButton.KeyNavigation.down
|
||||
//KeyNavigation.left: configureButton.visible ? configureButton : configureButton.KeyNavigation.left
|
||||
|
||||
/*PlasmaComponents.ToolTip {
|
||||
* text: parent.text
|
||||
}*/
|
||||
}
|
||||
|
||||
// Main content layout
|
||||
ColumnLayout {
|
||||
id: expandedRepresentation
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: trayHeading.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottomMargin: 0
|
||||
}
|
||||
//anchors.top: parent.top
|
||||
|
||||
|
||||
anchors.margins: Kirigami.Units.smallSpacing
|
||||
// TODO: remove this so the scrollview fully touches the header;
|
||||
// add top padding internally
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
// Grid view of all available items
|
||||
HiddenItemsView {
|
||||
id: hiddenItemsView
|
||||
Layout.preferredWidth: hiddenItemsView.width
|
||||
//Layout.minimumHeight: hiddenItemsView.flyoutHeight
|
||||
//Layout.maximumHeight: hiddenItemsView.flyoutHeight
|
||||
|
||||
visible: !systemTrayState.activeApplet
|
||||
/*property int previousItemCount: 0
|
||||
onHiddenItemsCountChanged: {
|
||||
if(shownDialog) {
|
||||
var itemCount = hiddenItemsView.hiddenItemsCount
|
||||
if(itemCount > previousItemCount) {
|
||||
if(itemCount % 3 == 1) {
|
||||
console.log("big change " + hiddenItemsView.flyoutHeight + " " + hiddenItemsView.implicitHeight)
|
||||
changedItems = true;
|
||||
}
|
||||
} else if(itemCount < previousItemCount) {
|
||||
if(itemCount % 3 == 0) {
|
||||
changedItems = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousItemCount = hiddenItemsView.hiddenItemsCount;
|
||||
}*/
|
||||
onVisibleChanged: {
|
||||
|
||||
if (visible) {
|
||||
layout.forceActiveFocus();
|
||||
systemTrayState.oldVisualIndex = systemTrayState.newVisualIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Container for currently visible item
|
||||
PlasmoidPopupsContainer {
|
||||
id: container
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
//Layout.topMargin: -dummyItem.height
|
||||
visible: systemTrayState.activeApplet
|
||||
// We need to add margin on the top so it matches the dialog's own margin
|
||||
Layout.margins: Kirigami.Units.smallSpacing //mergeHeadings ? 0 : dialog.topPadding
|
||||
Layout.bottomMargin: Kirigami.Units.mediumSpacing
|
||||
|
||||
//clip: true
|
||||
KeyNavigation.up: pinButton
|
||||
KeyNavigation.backtab: pinButton
|
||||
/*Rectangle {
|
||||
id: rectxd
|
||||
color: "red"
|
||||
anchors.fill: parent
|
||||
}*/
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Header content layout
|
||||
|
||||
RowLayout {
|
||||
id: trayHeading
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
/*leftMargin: dialogSvg.margins.left
|
||||
rightMargin: dialogSvg.margins.right
|
||||
bottomMargin: dialogSvg.margins.bottom*/
|
||||
|
||||
}
|
||||
property QtObject applet: systemTrayState.activeApplet || root
|
||||
visible: trayHeading.applet && trayHeading.applet.plasmoid.internalAction("configure")
|
||||
height: 40
|
||||
|
||||
Item {
|
||||
id: paddingLeft
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
id: headingLabel
|
||||
color: "#0066cc"
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
text: (systemTrayState.activeApplet ? systemTrayState.activeApplet.plasmoid.title : i18n("Customize..."))
|
||||
elide: Text.ElideRight
|
||||
font.underline: ma.containsMouse
|
||||
Item { // I don't know why the f*ck this works but it works
|
||||
id: rect
|
||||
anchors.fill: parent
|
||||
MouseArea {
|
||||
id: ma
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
//enabled: parent.hoveredLink
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
trayHeading.applet.plasmoid.internalAction("configure").trigger();
|
||||
}
|
||||
//z: 9999
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: paddingRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
Rectangle {
|
||||
id: plasmoidFooter
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
/*leftMargin: dialogSvg.margins.left
|
||||
rightMargin: dialogSvg.margins.right
|
||||
bottomMargin: dialogSvg.margins.bottom*/
|
||||
|
||||
}
|
||||
|
||||
visible: trayHeading.visible
|
||||
//visible: container.appletHasFooter
|
||||
height: trayHeading.height + Kirigami.Units.smallSpacing / 2 //+ container.footerHeight + Kirigami.Units.smallSpacing
|
||||
//height: trayHeading.height + container.headingHeight + (container.headingHeight === 0 ? 0 : Kirigami.Units.smallSpacing/2)
|
||||
color: "#f1f5fb"
|
||||
Rectangle {
|
||||
id: plasmoidFooterBorder
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: "#ccd9ea" }
|
||||
GradientStop { position: 1.0; color: "#f1f5fb" }
|
||||
}
|
||||
height: Kirigami.Units.smallSpacing
|
||||
}
|
||||
z: -9999
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.ksvg as KSvg
|
||||
|
||||
PlasmaCore.ToolTipArea {
|
||||
id: tooltip
|
||||
|
||||
readonly property int arrowAnimationDuration: Kirigami.Units.shortDuration
|
||||
property bool vertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical
|
||||
property int iconSize: Kirigami.Units.smallMedium
|
||||
property int expanderSize: Kirigami.Units.iconSizes.smallMedium - Kirigami.Units.smallSpacing / 2
|
||||
implicitWidth: expanderSize+1
|
||||
implicitHeight: expanderSize
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.name: subText
|
||||
Accessible.description: i18n("Show all the items in the system tray in a popup")
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.onPressAction: systemTrayState.expanded = !systemTrayState.expanded
|
||||
|
||||
Keys.onPressed: event => {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Space:
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Select:
|
||||
systemTrayState.expanded = !systemTrayState.expanded;
|
||||
}
|
||||
}
|
||||
|
||||
subText: systemTrayState.expanded ? i18n("Close popup") : i18n("Show hidden icons")
|
||||
|
||||
property bool wasExpanded
|
||||
|
||||
property bool flyoutExpanded: systemTrayState.expanded
|
||||
onFlyoutExpandedChanged: {
|
||||
if(flyoutExpanded) {
|
||||
tooltip.hideImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onPressedChanged: {
|
||||
if (pressed) {
|
||||
tooltip.wasExpanded = systemTrayState.expanded;
|
||||
}
|
||||
}
|
||||
onTapped: {
|
||||
systemTrayState.expanded = !tooltip.wasExpanded;
|
||||
expandedRepresentation.hiddenLayout.currentIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
KSvg.SvgItem {
|
||||
id: arrow
|
||||
z: -1
|
||||
anchors.centerIn: parent
|
||||
width: expanderSize +1
|
||||
height: expanderSize
|
||||
//width: Math.min(parent.width, parent.height)+1
|
||||
//height: width-1
|
||||
|
||||
// This is the Aero styled button texture used for the system tray expander.
|
||||
KSvg.FrameSvgItem {
|
||||
id: hoverButton
|
||||
z: -1 // To prevent layout issues with the MouseArea.
|
||||
anchors.fill: parent
|
||||
imagePath: Qt.resolvedUrl("svgs/systray.svg")
|
||||
prefix: {
|
||||
if(tooltip.containsPress || (systemTrayState.expanded && expandedRepresentation.hiddenLayout.visible)) return "pressed";
|
||||
if(tooltip.containsMouse) return "hover";
|
||||
return "normal"; // The normal state actually just makes the button invisible.
|
||||
}
|
||||
}
|
||||
imagePath: "widgets/arrows"
|
||||
//svg: arrowSvg
|
||||
elementId: {
|
||||
// Depending on the taskbar orientation, choose different arrow orientation from the SVG.
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Kirigami.Icon {
|
||||
anchors.fill: parent
|
||||
|
||||
rotation: systemTrayState.expanded ? 180 : 0
|
||||
Behavior on rotation {
|
||||
RotationAnimation {
|
||||
duration: tooltip.arrowAnimationDuration
|
||||
}
|
||||
}
|
||||
opacity: systemTrayState.expanded ? 0 : 1
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: tooltip.arrowAnimationDuration
|
||||
}
|
||||
}
|
||||
|
||||
source: {
|
||||
if (Plasmoid.location === PlasmaCore.Types.TopEdge) {
|
||||
return "arrow-down";
|
||||
} else if (Plasmoid.location === PlasmaCore.Types.LeftEdge) {
|
||||
return "arrow-right";
|
||||
} else if (Plasmoid.location === PlasmaCore.Types.RightEdge) {
|
||||
return "arrow-left";
|
||||
} else {
|
||||
return "arrow-up";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.fill: parent
|
||||
|
||||
rotation: systemTrayState.expanded ? 0 : -180
|
||||
Behavior on rotation {
|
||||
RotationAnimation {
|
||||
duration: tooltip.arrowAnimationDuration
|
||||
}
|
||||
}
|
||||
opacity: systemTrayState.expanded ? 1 : 0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: tooltip.arrowAnimationDuration
|
||||
}
|
||||
}
|
||||
|
||||
source: {
|
||||
if (Plasmoid.location === PlasmaCore.Types.TopEdge) {
|
||||
return "arrow-up";
|
||||
} else if (Plasmoid.location === PlasmaCore.Types.LeftEdge) {
|
||||
return "arrow-left";
|
||||
} else if (Plasmoid.location === PlasmaCore.Types.RightEdge) {
|
||||
return "arrow-right";
|
||||
} else {
|
||||
return "arrow-down";
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
SPDX-FileCopyrightText: 2020 Nate Graham <nate@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.kitemmodels 1.0 as KItemModels
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import "items"
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
|
||||
ScrollView {
|
||||
id: hiddenTasksView
|
||||
|
||||
property alias hiddenItemsCount: hiddenTasks.count
|
||||
property alias cellWidth: hiddenTasks.cellWidth
|
||||
property alias cellHeight: hiddenTasks.cellHeight
|
||||
//property int hiddenTasksWidth: 3 * hiddenTasks.cellWidth + Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing / 2 - 1 + hiddenTasksView.padding*2
|
||||
//property int hiddenTasksHeight: Math.ceil(hiddenTasks.count / 3) * (hiddenTasks.cellHeight + Kirigami.Units.smallSpacing) + 40 + Kirigami.Units.largeSpacing*2 + hiddenTasksView.padding*2
|
||||
property alias layout: hiddenTasks
|
||||
|
||||
property int flyoutHeight: Math.ceil(hiddenTasks.count / 3) * (hiddenTasks.cellHeight + Kirigami.Units.smallSpacing) + Kirigami.Units.smallSpacing*2
|
||||
|
||||
width: (hiddenTasks.cellWidth+Kirigami.Units.smallSpacing) * 3 - Kirigami.Units.smallSpacing/2 - 1
|
||||
|
||||
//topPadding: 0
|
||||
padding: Kirigami.Units.mediumSpacing
|
||||
leftPadding: Kirigami.Units.smallSpacing
|
||||
bottomPadding: Kirigami.Units.mediumSpacing + Kirigami.Units.smallSpacing
|
||||
rightPadding: 0
|
||||
hoverEnabled: true
|
||||
onHoveredChanged: if (!hovered) {
|
||||
|
||||
hiddenTasks.currentIndex = -1;
|
||||
}
|
||||
background: null
|
||||
|
||||
GridView {
|
||||
id: hiddenTasks
|
||||
|
||||
readonly property int maximumColumns: 3
|
||||
readonly property int minimumRows: 4
|
||||
readonly property int minimumColumns: 4
|
||||
|
||||
cellWidth: Kirigami.Units.iconSizes.medium //Math.floor(Math.min(hiddenTasksView.availableWidth, popup.Layout.minimumWidth) / minimumRows)
|
||||
cellHeight: Kirigami.Units.iconSizes.medium //Math.floor(popup.Layout.minimumHeight / minimumColumns)
|
||||
|
||||
currentIndex: -1
|
||||
//highlight: PlasmaExtras.Highlight {}
|
||||
highlightMoveDuration: 0
|
||||
|
||||
pixelAligned: true
|
||||
|
||||
readonly property int itemCount: model.count
|
||||
|
||||
//! This is used in order to identify the minimum required label height in order for all
|
||||
//! labels to be aligned properly at all items. At the same time this approach does not
|
||||
//! enforce labels with 3 lines at all cases so translations that require only one or two
|
||||
//! lines will always look consistent with no too much padding
|
||||
readonly property int minLabelHeight: {
|
||||
var minHeight = 0;
|
||||
|
||||
for(let i in contentItem.children){
|
||||
var gridItem = contentItem.children[i];
|
||||
if (!gridItem || !gridItem.hasOwnProperty("item") || !gridItem.item.hasOwnProperty("labelHeight")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gridItem.item.labelHeight > minHeight) {
|
||||
minHeight = gridItem.item.labelHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return minHeight;
|
||||
}
|
||||
|
||||
model: KItemModels.KSortFilterProxyModel {
|
||||
sourceModel: Plasmoid.systemTrayModel
|
||||
filterRoleName: "effectiveStatus"
|
||||
filterRowCallback: (sourceRow, sourceParent) => {
|
||||
let value = sourceModel.data(sourceModel.index(sourceRow, 0, sourceParent), filterRole);
|
||||
return value === PlasmaCore.Types.PassiveStatus
|
||||
}
|
||||
}
|
||||
delegate: ItemLoader {
|
||||
id: itemloader
|
||||
GridView.onRemove: SequentialAnimation {
|
||||
PropertyAction { target: itemloader; property: "GridView.delayRemove"; value: true }
|
||||
NumberAnimation { target: itemloader; property: "opacity"; to: 0; duration: 25; easing.type: Easing.InOutQuad }
|
||||
PropertyAction { target: itemloader; property: "GridView.delayRemove"; value: false }
|
||||
}
|
||||
//GridView.delayRemove: true
|
||||
width: hiddenTasks.cellWidth
|
||||
height: hiddenTasks.cellHeight
|
||||
minLabelHeight: 0//hiddenTasks.minLabelHeight
|
||||
}
|
||||
|
||||
keyNavigationEnabled: true
|
||||
activeFocusOnTab: true
|
||||
|
||||
KeyNavigation.up: hiddenTasksView.KeyNavigation.up
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus && currentIndex === -1) {
|
||||
currentIndex = 0
|
||||
} else if (!activeFocus && currentIndex >= 0) {
|
||||
currentIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
|
||||
StackView {
|
||||
id: mainStack
|
||||
focus: true
|
||||
|
||||
/*Layout.minimumWidth: Kirigami.Units.iconSizes.small * 12
|
||||
Layout.minimumHeight: Kirigami.Units.iconSizes.small * 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
|
||||
|
||||
readonly property int flyoutImplicitHeight: activeApplet ? activeApplet.fullRepresentationItem.implicitHeight : 0
|
||||
onFlyoutImplicitHeightChanged: {
|
||||
popup.updateHeight();
|
||||
}
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
Kirigami.Theme.inherit: false
|
||||
onActiveAppletChanged: {
|
||||
mainStack.appletHasHeading = false
|
||||
mainStack.appletHasFooter = false
|
||||
|
||||
if (activeApplet != null && activeApplet.fullRepresentationItem && !activeApplet.preferredRepresentation) {
|
||||
//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 ||
|
||||
activeApplet.fullRepresentationItem instanceof PlasmaExtras.Representation) {
|
||||
if (activeApplet.fullRepresentationItem.header && activeApplet.fullRepresentationItem.header instanceof PlasmaExtras.PlasmoidHeading) {
|
||||
mainStack.appletHasHeading = true;
|
||||
activeApplet.fullRepresentationItem.header.background.visible = false;
|
||||
activeApplet.fullRepresentationItem.header.Kirigami.Theme.colorSet = Kirigami.Theme.View;
|
||||
activeApplet.fullRepresentationItem.header.Kirigami.Theme.inherit = false;
|
||||
}
|
||||
if (activeApplet.fullRepresentationItem.footer && activeApplet.fullRepresentationItem.footer instanceof PlasmaExtras.PlasmoidHeading) {
|
||||
mainStack.appletHasFooter = true;
|
||||
activeApplet.fullRepresentationItem.footer.background.visible = false;
|
||||
activeApplet.fullRepresentationItem.footer.Kirigami.Theme.colorSet = Kirigami.Theme.View;
|
||||
activeApplet.fullRepresentationItem.footer.Kirigami.Theme.inherit = false;
|
||||
}
|
||||
}
|
||||
|
||||
let unFlipped = systemTrayState.oldVisualIndex < systemTrayState.newVisualIndex;
|
||||
if (Qt.application.layoutDirection !== Qt.LeftToRight) {
|
||||
unFlipped = !unFlipped;
|
||||
}
|
||||
const isTransitionEnabled = false; //systemTrayState.expanded;
|
||||
(mainStack.empty ? mainStack.push : mainStack.replace)(activeApplet.fullRepresentationItem, {
|
||||
"Kirigami.Theme.colorSet": Kirigami.Theme.View,
|
||||
"Kirigami.Theme.inherit": false,
|
||||
"width": Qt.binding(() => mainStack.width),
|
||||
"height": Qt.binding(() => mainStack.height),
|
||||
"x": 0,
|
||||
"focus": Qt.binding(() => !mainStack.busy), // QTBUG-44043: retrigger binding after StackView is ready to restore focus
|
||||
"opacity": 1,
|
||||
"KeyNavigation.up": mainStack.KeyNavigation.up,
|
||||
"KeyNavigation.backtab": mainStack.KeyNavigation.backtab,
|
||||
}, isTransitionEnabled ? (unFlipped ? StackView.PushTransition : StackView.PopTransition) : StackView.Immediate);
|
||||
|
||||
} else {
|
||||
mainStack.clear();
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentItemChanged: {
|
||||
if (currentItem !== null && root.expanded) {
|
||||
currentItem.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Plasmoid
|
||||
function onAppletRemoved(applet) {
|
||||
if (applet === systemTrayState.activeApplet) {
|
||||
mainStack.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017 The Qt Company Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-3.0-only OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Templates as T
|
||||
import QtQml
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.plasma.components as PlasmaComponents3
|
||||
|
||||
T.ScrollView {
|
||||
id: controlRoot
|
||||
|
||||
clip: true
|
||||
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
contentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
contentHeight + topPadding + bottomPadding)
|
||||
|
||||
leftPadding: mirrored && T.ScrollBar.vertical.visible && !Kirigami.Settings.isMobile ? T.ScrollBar.vertical.width : 0
|
||||
rightPadding: !mirrored && T.ScrollBar.vertical.visible && !Kirigami.Settings.isMobile ? T.ScrollBar.vertical.width : 0
|
||||
bottomPadding: T.ScrollBar.horizontal.visible && !Kirigami.Settings.isMobile ? T.ScrollBar.horizontal.height : 0
|
||||
|
||||
data: [
|
||||
Kirigami.WheelHandler {
|
||||
target: controlRoot.contentItem
|
||||
// `Qt.styleHints.wheelScrollLines * 20` is the default scroll speed.
|
||||
horizontalStepSize: Qt.styleHints.wheelScrollLines * 20
|
||||
verticalStepSize: Qt.styleHints.wheelScrollLines * 20
|
||||
},
|
||||
Binding { // TODO KF6: remove, Qt6 has this behavior by default
|
||||
target: controlRoot.contentItem // always instanceof Flickable
|
||||
property: 'clip'
|
||||
value: true
|
||||
restoreMode: Binding.RestoreBindingOrValue
|
||||
}
|
||||
]
|
||||
|
||||
/*T.ScrollBar.vertical: PlasmaComponents3.ScrollBar {
|
||||
parent: controlRoot
|
||||
x: controlRoot.mirrored ? 0 : controlRoot.width - width
|
||||
y: controlRoot.topPadding
|
||||
height: controlRoot.availableHeight
|
||||
active: controlRoot.T.ScrollBar.horizontal.active
|
||||
}
|
||||
|
||||
T.ScrollBar.horizontal: PlasmaComponents3.ScrollBar {
|
||||
parent: controlRoot
|
||||
x: controlRoot.leftPadding
|
||||
y: controlRoot.height - height
|
||||
width: controlRoot.availableWidth
|
||||
active: controlRoot.T.ScrollBar.vertical.active
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import org.kde.plasma.core 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 = (activeApplet && activeApplet.status === PlasmaCore.Types.PassiveStatus) ? 9999 : newVisualIndex
|
||||
newVisualIndex = visualIndex
|
||||
}
|
||||
|
||||
const oldApplet = activeApplet
|
||||
if (applet && !applet.preferredRepresentation) {
|
||||
applet.expanded = true;
|
||||
}
|
||||
if (!applet || !applet.preferredRepresentation) {
|
||||
activeApplet = applet;
|
||||
}
|
||||
|
||||
if (oldApplet && oldApplet !== applet) {
|
||||
oldApplet.expanded = false
|
||||
}
|
||||
|
||||
if (applet && !applet.preferredRepresentation) {
|
||||
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
|
||||
root.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
|
||||
}
|
||||
}
|
||||
|
||||
property Connections rootConnections: Connections {
|
||||
function onExpandedChanged() {
|
||||
if (acceptExpandedChange) {
|
||||
expanded = root.expanded
|
||||
} else {
|
||||
root.expanded = expanded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Connections activeAppletConnections: Connections {
|
||||
target: activeApplet && activeApplet
|
||||
|
||||
function onExpandedChanged() {
|
||||
if (activeApplet && !activeApplet.expanded) {
|
||||
expanded = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQml.Models 2.2
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
// for Highlight
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
|
||||
*/
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.15
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.ksvg 1.0 as KSvg
|
||||
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
|
||||
|
||||
MouseArea {
|
||||
id: toolButton
|
||||
|
||||
Layout.maximumWidth: Kirigami.Units.iconSizes.small+1;
|
||||
Layout.maximumHeight: Kirigami.Units.iconSizes.small;
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.small+1;
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.small;
|
||||
|
||||
//signal clicked
|
||||
property string buttonIcon: ""
|
||||
property bool checkable: false
|
||||
property bool checked: false
|
||||
|
||||
hoverEnabled: true
|
||||
KSvg.FrameSvgItem {
|
||||
id: normalButton
|
||||
imagePath: Qt.resolvedUrl("svgs/button.svgz")
|
||||
anchors.fill: parent
|
||||
prefix: {
|
||||
if(parent.containsPress || (checkable && checked)) return "toolbutton-pressed";
|
||||
else return "toolbutton-hover";
|
||||
}
|
||||
visible: parent.containsMouse || (checkable && checked)
|
||||
}
|
||||
|
||||
KSvg.SvgItem {
|
||||
id: buttonIconSvg
|
||||
svg: buttonIcons
|
||||
elementId: buttonIcon
|
||||
width: 10;
|
||||
height: 10;
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
SPDX-FileCopyrightText: 2020 Nate Graham <nate@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.ksvg 1.0 as KSvg
|
||||
|
||||
PlasmaCore.ToolTipArea {
|
||||
id: abstractItem
|
||||
|
||||
property var model: itemModel
|
||||
|
||||
property string itemId
|
||||
property alias text: label.text
|
||||
property alias labelHeight: label.implicitHeight
|
||||
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
|
||||
property bool effectivePressed: false
|
||||
property real minLabelHeight: 0
|
||||
readonly property bool inHiddenLayout: effectiveStatus === PlasmaCore.Types.PassiveStatus
|
||||
readonly property bool inVisibleLayout: effectiveStatus === PlasmaCore.Types.ActiveStatus
|
||||
|
||||
// input agnostic way to trigger the main action
|
||||
signal activated(var pos)
|
||||
|
||||
// proxy signals for MouseArea
|
||||
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;
|
||||
}
|
||||
|
||||
/*PulseAnimation {
|
||||
targetItem: iconContainer
|
||||
running: (abstractItem.status === PlasmaCore.Types.NeedsAttentionStatus
|
||||
|| abstractItem.status === PlasmaCore.Types.RequiresAttentionStatus)
|
||||
&& Kirigami.Units.longDuration > 0
|
||||
}*/
|
||||
|
||||
KSvg.FrameSvgItem {
|
||||
id: itemHighLight
|
||||
anchors.fill: parent
|
||||
//property int location
|
||||
|
||||
property bool animationEnabled: true
|
||||
property var highlightedItem: null
|
||||
|
||||
z: -1 // always draw behind icons
|
||||
opacity: mouseArea.containsMouse ? 1 : 0
|
||||
|
||||
imagePath: Qt.resolvedUrl("../svgs/tabbar.svgz")
|
||||
//imagePath: "widgets/tabbar"
|
||||
prefix: {
|
||||
var prefix = ""
|
||||
switch (Plasmoid.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: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: pressRect
|
||||
property alias activatedPress: pressRect.opacity
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Kirigami.Units.smallSpacing / 2; // We don't want the rectangle to draw over the highlight texture itself.
|
||||
anchors.rightMargin: Kirigami.Units.smallSpacing / 2;
|
||||
gradient: Gradient {
|
||||
// The first and last gradient stops are offset by +/-0.1 to avoid a sudden gradient "cutoff".
|
||||
GradientStop { position: 0.1; color: "transparent"; }
|
||||
GradientStop { position: 0.5; color: "#66000000"; }
|
||||
GradientStop { position: 0.9; color: "transparent"; }
|
||||
}
|
||||
opacity: mouseArea.containsPress ? 1 : 0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 150;
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
propagateComposedEvents: true
|
||||
// This needs to be above applets when it's in the grid hidden area
|
||||
// so that it can receive hover events while the mouse is over an applet,
|
||||
// but below them on regular systray, so collapsing works
|
||||
//z: inHiddenLayout ? 1 : 0
|
||||
z: 1
|
||||
anchors.fill: abstractItem
|
||||
hoverEnabled: true
|
||||
drag.filterChildren: true
|
||||
// Necessary to make the whole delegate area forward all mouse events
|
||||
acceptedButtons: Qt.AllButtons
|
||||
// Using onPositionChanged instead of onEntered because changing the
|
||||
// index in a scrollable view also changes the view position.
|
||||
// onEntered will change the index while the items are scrolling,
|
||||
// making it harder to scroll.
|
||||
|
||||
onContainsMouseChanged: {
|
||||
if(inHiddenLayout && !mouseArea.containsMouse) {
|
||||
root.hiddenLayout.currentIndex = -1;
|
||||
}
|
||||
}
|
||||
onPositionChanged: if (inHiddenLayout) {
|
||||
root.hiddenLayout.currentIndex = index
|
||||
}
|
||||
onClicked: mouse => { abstractItem.clicked(mouse) }
|
||||
onPressed: mouse => {
|
||||
if (inHiddenLayout) {
|
||||
root.hiddenLayout.currentIndex = index
|
||||
}
|
||||
abstractItem.hideImmediately()
|
||||
abstractItem.pressed(mouse)
|
||||
}
|
||||
onPressAndHold: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
abstractItem.contextMenu(mouse)
|
||||
}
|
||||
}
|
||||
onWheel: wheel => {
|
||||
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
|
||||
|
||||
FocusScope {
|
||||
id: iconContainer
|
||||
//scale: (abstractItem.effectivePressed || mouseArea.containsPress) ? 0.8 : 1
|
||||
|
||||
Kirigami.Theme.colorSet: abstractItem.inHiddenLayout ? Kirigami.Theme.Tooltip : Kirigami.Theme.Window
|
||||
Kirigami.Theme.inherit: false
|
||||
activeFocusOnTab: true
|
||||
focus: true // Required in HiddenItemsView so keyboard events can be forwarded to this item
|
||||
Accessible.name: abstractItem.text
|
||||
Accessible.description: abstractItem.subText
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.onPressAction: abstractItem.activated(Plasmoid.popupPosition(iconContainer, iconContainer.width/2, iconContainer.height/2));
|
||||
|
||||
/*Behavior on scale {
|
||||
ScaleAnimator {
|
||||
duration: Kirigami.Units.longDuration
|
||||
easing.type: (effectivePressed || mouseArea.containsPress) ? Easing.OutCubic : Easing.InCubic
|
||||
}
|
||||
}*/
|
||||
|
||||
Keys.onPressed: event => {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Space:
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Select:
|
||||
abstractItem.activated(Qt.point(width/2, height/2));
|
||||
break;
|
||||
case Qt.Key_Menu:
|
||||
abstractItem.contextMenu(null);
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
property alias container: abstractItem
|
||||
property alias inVisibleLayout: abstractItem.inVisibleLayout
|
||||
readonly property int size: abstractItem.inVisibleLayout ? root.itemSize : Kirigami.Units.iconSizes.small
|
||||
|
||||
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 ? Kirigami.Units.mediumSpacing : 0
|
||||
}
|
||||
PlasmaComponents3.Label {
|
||||
id: label
|
||||
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: abstractItem.inHiddenLayout ? true : false
|
||||
//! Minimum required height for all labels is used in order for all
|
||||
//! labels to be aligned properly at all items. At the same time this approach does not
|
||||
//! enforce labels with 3 lines at all cases so translations that require only one or two
|
||||
//! lines will always look consistent with no too much padding
|
||||
Layout.minimumHeight: abstractItem.inHiddenLayout ? abstractItem.minLabelHeight : 0
|
||||
Layout.leftMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0
|
||||
Layout.rightMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0
|
||||
Layout.bottomMargin: abstractItem.inHiddenLayout ? Kirigami.Units.smallSpacing : 0
|
||||
|
||||
visible: false //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: Kirigami.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
Loader {
|
||||
id: itemLoader
|
||||
|
||||
property real minLabelHeight: 0
|
||||
|
||||
z: x+1 // always be above what it's on top of, even for x==0
|
||||
property var itemModel: model
|
||||
|
||||
Binding {
|
||||
target: item
|
||||
property: "minLabelHeight"
|
||||
value: itemLoader.minLabelHeight
|
||||
}
|
||||
source: {
|
||||
if (model.itemType === "Plasmoid" && model.hasApplet) {
|
||||
return Qt.resolvedUrl("PlasmoidItem.qml")
|
||||
} else if (model.itemType === "StatusNotifier") {
|
||||
return Qt.resolvedUrl("StatusNotifierItem.qml")
|
||||
}
|
||||
console.warn("SystemTray ItemLoader: Invalid state, cannot determine source!")
|
||||
return ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQml 2.15
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
|
||||
AbstractItem {
|
||||
id: plasmoidContainer
|
||||
|
||||
property Item applet: model.applet || null
|
||||
text: applet ? applet.plasmoid.title : ""
|
||||
|
||||
itemId: applet ? applet.plasmoid.pluginName : ""
|
||||
mainText: applet ? applet.toolTipMainText : ""
|
||||
subText: applet ? applet.toolTipSubText : ""
|
||||
mainItem: applet && applet.toolTipItem ? applet.toolTipItem : null
|
||||
textFormat: applet ? applet.toolTipTextFormat : 0 /* Text.AutoText, the default value */
|
||||
active: systemTrayState.activeApplet !== applet
|
||||
|
||||
// FIXME: Use an input type agnostic way to activate whatever the primary
|
||||
// action of a plasmoid is supposed to be, even if it's just expanding the
|
||||
// Plasmoid. Not all plasmoids are supposed to expand and not all plasmoids
|
||||
// do anything with onActivated.
|
||||
onActivated: {
|
||||
if (applet) {
|
||||
applet.plasmoid.activated()
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
if (!applet) {
|
||||
return
|
||||
}
|
||||
//forward click event to the applet
|
||||
var appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
|
||||
const mouseArea = findMouseArea(appletItem)
|
||||
|
||||
if (mouseArea && mouse.button !== Qt.RightButton) {
|
||||
var temp = applet.expanded;
|
||||
mouseArea.clicked(mouse);
|
||||
|
||||
if(mouse.button === Qt.LeftButton && inVisibleLayout && applet.expanded && temp) {
|
||||
applet.expanded = false;
|
||||
}
|
||||
} else if (mouse.button === Qt.LeftButton) {//fallback
|
||||
activated(null)
|
||||
}
|
||||
}
|
||||
onPressed: mouse => {
|
||||
// Only Plasmoids can show context menu on the mouse pressed event.
|
||||
// SNI has few problems, for example legacy applications that still use XEmbed require mouse to be released.
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
contextMenu(mouse);
|
||||
} /*else {
|
||||
const appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
|
||||
const mouseArea = findMouseArea(appletItem)
|
||||
|
||||
}*/
|
||||
}
|
||||
onContextMenu: if (applet) {
|
||||
effectivePressed = false;
|
||||
Plasmoid.showPlasmoidMenu(applet, 0, inHiddenLayout ? applet.height : 0);
|
||||
}
|
||||
onWheel: (wheel) => {
|
||||
if (!applet) {
|
||||
return
|
||||
}
|
||||
//forward wheel event to the applet
|
||||
var appletItem = applet.compactRepresentationItem ?? applet.fullRepresentationItem
|
||||
const mouseArea = findMouseArea(appletItem)
|
||||
if (mouseArea) {
|
||||
mouseArea.wheel(wheel)
|
||||
}
|
||||
}
|
||||
|
||||
//some heuristics to find MouseArea
|
||||
function findMouseArea(item: Item): MouseArea {
|
||||
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.height = expandedRepresentation.height
|
||||
fullRepresentationItem.parent = preloadedStorage;
|
||||
}
|
||||
}
|
||||
|
||||
onAppletChanged: {
|
||||
if (applet) {
|
||||
applet.parent = iconContainer
|
||||
applet.anchors.fill = applet.parent
|
||||
applet.visible = true
|
||||
|
||||
preloadFullRepresentationItem(applet.fullRepresentationItem)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
enabled: plasmoidContainer.applet !== null
|
||||
target: findMouseArea(
|
||||
plasmoidContainer.applet?.compactRepresentationItem ??
|
||||
plasmoidContainer.applet?.fullRepresentationItem ??
|
||||
plasmoidContainer.applet
|
||||
)
|
||||
|
||||
function onContainsPressChanged() {
|
||||
plasmoidContainer.effectivePressed = target.containsPress;
|
||||
}
|
||||
|
||||
// TODO For touch/stylus only, since the feature is not desired for mouse users
|
||||
function onPressAndHold(mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
plasmoidContainer.contextMenu(mouse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: plasmoidContainer.applet?.plasmoid ?? null
|
||||
|
||||
//activation using global keyboard shortcut
|
||||
function onActivated() {
|
||||
plasmoidContainer.effectivePressed = true;
|
||||
Qt.callLater(() => {
|
||||
plasmoidContainer.effectivePressed = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: plasmoidContainer.applet
|
||||
|
||||
function onFullRepresentationItemChanged(fullRepresentationItem) {
|
||||
preloadFullRepresentationItem(fullRepresentationItem)
|
||||
}
|
||||
|
||||
function onExpandedChanged(expanded) {
|
||||
if (expanded) {
|
||||
systemTrayState.setActiveApplet(plasmoidContainer.applet, model.row)
|
||||
effectivePressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*PlasmaComponents3.BusyIndicator {
|
||||
anchors.fill: parent
|
||||
z: 999
|
||||
running: plasmoidContainer.applet?.plasmoid.busy ?? false
|
||||
}*/
|
||||
|
||||
Binding {
|
||||
property: "hideOnWindowDeactivate"
|
||||
value: !Plasmoid.configuration.pin
|
||||
target: plasmoidContainer.applet
|
||||
when: plasmoidContainer.applet !== null
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
|
||||
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
SequentialAnimation {
|
||||
id: pulseAnimation
|
||||
objectName: "pulseAnimation"
|
||||
|
||||
property Item targetItem
|
||||
readonly property int duration: Kirigami.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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.1
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
AbstractItem {
|
||||
id: taskIcon
|
||||
|
||||
itemId: model.Id
|
||||
text: model.Title || model.ToolTipTitle
|
||||
mainText: model.ToolTipTitle !== "" ? model.ToolTipTitle : model.Title
|
||||
subText: model.ToolTipSubTitle
|
||||
textFormat: Text.AutoText
|
||||
|
||||
Kirigami.Icon {
|
||||
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.IconName
|
||||
}
|
||||
active: taskIcon.containsMouse
|
||||
}
|
||||
|
||||
onActivated: pos => {
|
||||
const service = model.Service;
|
||||
const operation = service.operationDescription("Activate");
|
||||
operation.x = pos.x; //mouseX
|
||||
operation.y = pos.y; //mouseY
|
||||
const job = service.startOperationCall(operation);
|
||||
job.finished.connect(() => {
|
||||
if (!job.result) {
|
||||
// On error try to invoke the context menu.
|
||||
// Workaround primarily for apps using libappindicator.
|
||||
openContextMenu(pos);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onContextMenu: mouse => {
|
||||
if (mouse === null) {
|
||||
openContextMenu(Plasmoid.popupPosition(taskIcon, taskIcon.width / 2, taskIcon.height / 2));
|
||||
} else {
|
||||
openContextMenu(Plasmoid.popupPosition(taskIcon, mouse.x, mouse.y));
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
var pos = Plasmoid.popupPosition(taskIcon, mouse.x, mouse.y);
|
||||
|
||||
switch (mouse.button) {
|
||||
case Qt.LeftButton:
|
||||
taskIcon.activated(pos)
|
||||
break;
|
||||
case Qt.RightButton:
|
||||
openContextMenu(pos);
|
||||
break;
|
||||
case Qt.MiddleButton:
|
||||
const service = model.Service;
|
||||
const operation = service.operationDescription("SecondaryActivate");
|
||||
operation.x = pos.x;
|
||||
operation.y = pos.y;
|
||||
service.startOperationCall(operation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function openContextMenu(pos = Qt.point(width/2, height/2)) {
|
||||
const service = model.Service;
|
||||
const operation = service.operationDescription("ContextMenu");
|
||||
operation.x = pos.x;
|
||||
operation.y = pos.y;
|
||||
|
||||
const job = service.startOperationCall(operation);
|
||||
job.finished.connect(() => {
|
||||
Plasmoid.showStatusNotifierContextMenu(job, taskIcon);
|
||||
});
|
||||
}
|
||||
|
||||
onWheel: wheel => {
|
||||
//don't send activateVertScroll with a delta of 0, some clients seem to break (kmix)
|
||||
if (wheel.angleDelta.y !== 0) {
|
||||
const service = model.Service;
|
||||
const operation = service.operationDescription("Scroll");
|
||||
operation.delta = wheel.angleDelta.y;
|
||||
operation.direction = "Vertical";
|
||||
service.startOperationCall(operation);
|
||||
}
|
||||
if (wheel.angleDelta.x !== 0) {
|
||||
const service = model.Service;
|
||||
const operation = service.operationDescription("Scroll");
|
||||
operation.delta = wheel.angleDelta.x;
|
||||
operation.direction = "Horizontal";
|
||||
service.startOperationCall(operation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.15
|
||||
import org.kde.plasma.core as PlasmaCore
|
||||
import org.kde.ksvg 1.0 as KSvg
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.draganddrop 2.0 as DnD
|
||||
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
|
||||
import org.kde.kitemmodels 1.0 as KItemModels
|
||||
|
||||
import "items"
|
||||
|
||||
ContainmentItem {
|
||||
id: root
|
||||
|
||||
readonly property bool vertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical
|
||||
|
||||
Layout.minimumWidth: vertical ? Kirigami.Units.iconSizes.small : mainLayout.implicitWidth + Kirigami.Units.smallSpacing
|
||||
Layout.minimumHeight: vertical ? mainLayout.implicitHeight + Kirigami.Units.smallSpacing : Kirigami.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
|
||||
readonly property bool oneRowOrColumn: tasksGrid.rowsOrColumns === 1
|
||||
|
||||
KSvg.Svg {
|
||||
id: buttonIcons
|
||||
imagePath: Qt.resolvedUrl("svgs/icons.svg");
|
||||
}
|
||||
KSvg.FrameSvgItem {
|
||||
id : dialogSvg
|
||||
visible: false
|
||||
imagePath: "solid/dialogs/background"
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
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 {
|
||||
id: currentHighlight
|
||||
location: Plasmoid.location
|
||||
parent: root
|
||||
|
||||
onHighlightedItemChanged: {
|
||||
if(dialog.visible) dialog.setDialogPosition();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const plasmoidId = event.mimeData.getDataAsByteArray("text/x-plasmoidservicename");
|
||||
|
||||
if (!Plasmoid.isSystemTrayApplet(plasmoidId)) {
|
||||
return null;
|
||||
}
|
||||
return plasmoidId;
|
||||
}
|
||||
|
||||
onDragEnter: {
|
||||
if (!systemTrayAppletName(event)) {
|
||||
event.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
onDrop: {
|
||||
const plasmoidId = systemTrayAppletName(event);
|
||||
if (!plasmoidId) {
|
||||
event.ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Plasmoid.configuration.extraItems.indexOf(plasmoidId) < 0) {
|
||||
const 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
|
||||
ExpanderArrow {
|
||||
id: expander
|
||||
Layout.fillWidth: vertical
|
||||
Layout.fillHeight: !vertical
|
||||
Layout.alignment: vertical ? Qt.AlignVCenter : Qt.AlignHCenter
|
||||
iconSize: tasksGrid.itemSize
|
||||
visible: root.hiddenLayout.itemCount > 0
|
||||
}
|
||||
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: Kirigami.Units.iconSizes.small
|
||||
|
||||
// Automatically use autoSize setting when in tablet mode, if it's
|
||||
// not already being used
|
||||
readonly property bool autoSize: Plasmoid.configuration.scaleIconsToFit || Kirigami.Settings.tabletMode
|
||||
|
||||
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 + Kirigami.Units.smallSpacing))))
|
||||
|
||||
// Add margins only if the panel is larger than a small icon (to avoid large gaps between tiny icons)
|
||||
readonly property int cellSpacing: Kirigami.Units.smallSpacing * (Kirigami.Settings.tabletMode ? 6 : Plasmoid.configuration.iconSpacing)
|
||||
readonly property int smallSizeCellLength: gridThickness < smallIconSize ? smallIconSize : smallIconSize + cellSpacing
|
||||
|
||||
cellHeight: {
|
||||
if (root.vertical) {
|
||||
return autoSize ? itemSize + (gridThickness < itemSize ? 0 : cellSpacing) : 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 ? itemSize + (gridThickness < itemSize ? 0 : cellSpacing) : smallSizeCellLength
|
||||
}
|
||||
}
|
||||
|
||||
//depending on the form factor, we are calculating only one dimension, 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
|
||||
|
||||
readonly property int itemSize: {
|
||||
if (autoSize) {
|
||||
return Kirigami.Units.iconSizes.roundedIconSize(Math.min(Math.min(root.width, root.height) / rowsOrColumns, Kirigami.Units.iconSizes.enormous))
|
||||
} else {
|
||||
return smallIconSize
|
||||
}
|
||||
}
|
||||
|
||||
model: KItemModels.KSortFilterProxyModel {
|
||||
sourceModel: Plasmoid.systemTrayModel
|
||||
filterRoleName: "effectiveStatus"
|
||||
filterRowCallback: (sourceRow, sourceParent) => {
|
||||
let value = sourceModel.data(sourceModel.index(sourceRow, 0, sourceParent), filterRole);
|
||||
return value === PlasmaCore.Types.ActiveStatus;
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ItemLoader {
|
||||
id: delegate
|
||||
|
||||
width: tasksGrid.cellWidth
|
||||
height: tasksGrid.cellHeight
|
||||
minLabelHeight: 0
|
||||
|
||||
// We need to recalculate the stacking order of the z values due to how keyboard navigation works
|
||||
// the tab order depends exclusively from this, so we redo it as the position in the list
|
||||
// ensuring tab navigation focuses the expected items
|
||||
Component.onCompleted: {
|
||||
let item = tasksGrid.itemAtIndex(index - 1);
|
||||
if (item) {
|
||||
Plasmoid.stackItemBefore(delegate, item)
|
||||
} else {
|
||||
item = tasksGrid.itemAtIndex(index + 1);
|
||||
}
|
||||
if (item) {
|
||||
Plasmoid.stackItemAfter(delegate, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
enabled: itemSize > 0 && Component.status == Component.Ready
|
||||
|
||||
NumberAnimation {
|
||||
property: "scale"
|
||||
from: 0
|
||||
to: 1
|
||||
easing.type: Easing.InOutQuad
|
||||
duration: Kirigami.Units.longDuration
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
//ensure scale value returns to 1.0
|
||||
//https://doc.qt.io/qt-5/qml-qtquick-viewtransition.html#handling-interrupted-animations
|
||||
enabled: Component.status == Component.Ready
|
||||
NumberAnimation {
|
||||
property: "scale"
|
||||
to: 1
|
||||
easing.type: Easing.InOutQuad
|
||||
duration: Kirigami.Units.longDuration
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x,y"
|
||||
easing.type: Easing.InOutQuad
|
||||
duration: Kirigami.Units.longDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: expandedSync
|
||||
interval: 100
|
||||
onTriggered: systemTrayState.expanded = dialog.visible;
|
||||
}
|
||||
|
||||
//Main popup
|
||||
PlasmaCore.Dialog {
|
||||
id: dialog
|
||||
objectName: "popupWindow"
|
||||
//visualParent: root
|
||||
flags: Qt.WindowStaysOnTopHint
|
||||
/*popupDirection: switch (Plasmoid.location) {
|
||||
case PlasmaCore.Types.TopEdge:
|
||||
return Qt.BottomEdge
|
||||
case PlasmaCore.Types.LeftEdge:
|
||||
return Qt.RightEdge
|
||||
case PlasmaCore.Types.RightEdge:
|
||||
return Qt.LeftEdge
|
||||
default:
|
||||
return Qt.TopEdge
|
||||
}
|
||||
//margin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing/2 //(Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersFloatingApplets) ? Kirigami.Units.largeSpacing :
|
||||
animated: false*/
|
||||
//floating: true //Plasmoid.location == PlasmaCore.Desktop
|
||||
//location: PlasmaCore.Dialog.Floating
|
||||
location: "Floating"//Plasmoid.location
|
||||
x: 0
|
||||
y: 0
|
||||
//floating: 1
|
||||
property int flyoutMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing/2
|
||||
property bool firstTimePopup: false
|
||||
|
||||
/*removeBorderStrategy: PlasmaCore.AppletPopup.Never */ /*Plasmoid.location === PlasmaCore.Types.Floating
|
||||
? PlasmaCore.AppletPopup.AtScreenEdges
|
||||
: PlasmaCore.AppletPopup.AtScreenEdges | PlasmaCore.AppletPopup.AtPanelEdges*/
|
||||
|
||||
/*minimumWidth: expandedRepresentation.flyoutWidth
|
||||
maximumWidth: minimumWidth*/
|
||||
/*minimumHeight: expandedRepresentation.flyoutHeight
|
||||
maximumHeight: expandedRepresentation.flyoutHeight*/
|
||||
hideOnWindowDeactivate: !Plasmoid.configuration.pin
|
||||
visible: systemTrayState.expanded
|
||||
appletInterface: root
|
||||
|
||||
//flags: Qt.Dialog | Qt.FramelessWindowHint
|
||||
|
||||
backgroundHints: PlasmaCore.Dialog.SolidBackground //(Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersOpaqueBackground) ? PlasmaCore.AppletPopup.SolidBackground : PlasmaCore.AppletPopup.StandardBackground
|
||||
|
||||
onWidthChanged: setDialogPosition();
|
||||
onHeightChanged: setDialogPosition();
|
||||
function setDialogPosition() {
|
||||
var pos = root.mapToGlobal(root.x, root.y);
|
||||
pos = root.mapToGlobal(currentHighlight.x, currentHighlight.y);
|
||||
var availScreen = Plasmoid.containment.availableScreenRect;
|
||||
|
||||
x = pos.x - width / 2 + (expandedRepresentation.hiddenLayout.visible ? flyoutMargin + Kirigami.Units.smallSpacing/2 : currentHighlight.width / 2);
|
||||
y = pos.y - height;
|
||||
|
||||
if(x <= 0) x += flyoutMargin;
|
||||
if(x + dialog.width >= availScreen.width) {
|
||||
x = availScreen.width - dialog.width - flyoutMargin;
|
||||
|
||||
}
|
||||
if(y <= 0) y += flyoutMargin;
|
||||
if(y + dialog.height >= availScreen.height) {
|
||||
y = availScreen.height - dialog.height - flyoutMargin;
|
||||
}
|
||||
/*if(root.vertical) {
|
||||
if(pos.x > dialog.x) dialog.x -= flyoutMargin;
|
||||
else dialog.x += flyoutMargin;
|
||||
} else {
|
||||
if(pos.y > dialog.y) dialog.y -= flyoutMargin;
|
||||
else dialog.y += flyoutMargin;
|
||||
}*/
|
||||
}
|
||||
onYChanged: {
|
||||
if(!firstTimePopup) { setDialogPosition(); }
|
||||
firstTimePopup = true;
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if(visible) {
|
||||
setDialogPosition();
|
||||
}
|
||||
if (!visible) {
|
||||
expandedSync.restart();
|
||||
} else {
|
||||
if (expandedRepresentation.plasmoidContainer.visible) {
|
||||
expandedRepresentation.plasmoidContainer.forceActiveFocus();
|
||||
} else if (expandedRepresentation.hiddenLayout.visible) {
|
||||
expandedRepresentation.hiddenLayout.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
mainItem: ExpandedRepresentation {
|
||||
id: expandedRepresentation
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
systemTrayState.expanded = false
|
||||
}
|
||||
|
||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||
LayoutMirroring.childrenInherit: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/button.svgz
Executable file
BIN
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/button.svgz
Executable file
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 27 KiB |
2867
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/systray.svg
Executable file
2867
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/systray.svg
Executable file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 150 KiB |
BIN
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/tabbar.svgz
Executable file
BIN
plasma/plasmoids/org.kde.plasma.private.systemtray/contents/ui/svgs/tabbar.svgz
Executable file
Binary file not shown.
162
plasma/plasmoids/org.kde.plasma.private.systemtray/metadata.json
Normal file
162
plasma/plasmoids/org.kde.plasma.private.systemtray/metadata.json
Normal file
|
@ -0,0 +1,162 @@
|
|||
{
|
||||
"KPackageStructure": "Plasma/Applet",
|
||||
"KPlugin": {
|
||||
"Authors": [
|
||||
{
|
||||
"Email": "mart@kde.org",
|
||||
"Name": "Marco Martin",
|
||||
"Name[ar]": "Marco Martin",
|
||||
"Name[ast]": "Marco Martin",
|
||||
"Name[az]": "Marco Martin",
|
||||
"Name[be]": "Marco Martin",
|
||||
"Name[bg]": "Марко Мартин",
|
||||
"Name[ca@valencia]": "Marco Martin",
|
||||
"Name[ca]": "Marco Martin",
|
||||
"Name[cs]": "Marco Martin",
|
||||
"Name[da]": "Marco Martin",
|
||||
"Name[de]": "Marco Martin",
|
||||
"Name[en_GB]": "Marco Martin",
|
||||
"Name[eo]": "Marco Martin",
|
||||
"Name[es]": "Marco Martin",
|
||||
"Name[et]": "Marco Martin",
|
||||
"Name[eu]": "Marco Martin",
|
||||
"Name[fi]": "Marco Martin",
|
||||
"Name[fr]": "Marco Martin",
|
||||
"Name[gl]": "Marco Martin",
|
||||
"Name[he]": "מרקו מרטין",
|
||||
"Name[hi]": "मार्को मार्टिन",
|
||||
"Name[hu]": "Marco Martin",
|
||||
"Name[ia]": "Marco Martin",
|
||||
"Name[id]": "Marco Martin",
|
||||
"Name[is]": "Marco Martin",
|
||||
"Name[it]": "Marco Martin",
|
||||
"Name[ja]": "Marco Martin",
|
||||
"Name[ka]": "მაკრო მარტინი",
|
||||
"Name[ko]": "Marco Martin",
|
||||
"Name[lt]": "Marco Martin",
|
||||
"Name[nl]": "Marco Martin",
|
||||
"Name[nn]": "Marco Martin",
|
||||
"Name[pa]": "ਮਾਰਕੋ ਮਾਰਟਿਨ",
|
||||
"Name[pl]": "Marco Martin",
|
||||
"Name[pt]": "Marco Martin",
|
||||
"Name[pt_BR]": "Marco Martin",
|
||||
"Name[ro]": "Marco Martin",
|
||||
"Name[ru]": "Marco Martin",
|
||||
"Name[sa]": "मार्को मार्टिन्",
|
||||
"Name[sk]": "Marco Martin",
|
||||
"Name[sl]": "Marco Martin",
|
||||
"Name[sv]": "Marco Martin",
|
||||
"Name[ta]": "மார்க்கோ மார்ட்டின்",
|
||||
"Name[tr]": "Marco Martin",
|
||||
"Name[uk]": "Marco Martin",
|
||||
"Name[vi]": "Marco Martin",
|
||||
"Name[x-test]": "xxMarco Martinxx",
|
||||
"Name[zh_CN]": "Marco Martin",
|
||||
"Name[zh_TW]": "Marco Martin"
|
||||
}
|
||||
],
|
||||
"BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Tray",
|
||||
"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]": "Área de notificación",
|
||||
"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[sa]": "प्रणाली पात्र",
|
||||
"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 Tepsisi",
|
||||
"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]": "系統匣",
|
||||
"Website": "https://www.kde.org/plasma-desktop"
|
||||
},
|
||||
"NoDisplay": true,
|
||||
"X-Plasma-API-Minimum-Version": "6.0",
|
||||
"X-Plasma-ContainmentType": "CustomEmbedded"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue