mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-14 01:32:29 -04:00
Make the system tray overflow popup optional and have the widget expand inline as an alternative. (#2171)
This commit is contained in:
@@ -969,6 +969,7 @@ Item {
|
|||||||
axis: barWindow.axis
|
axis: barWindow.axis
|
||||||
barSpacing: barConfig?.spacing ?? 4
|
barSpacing: barConfig?.spacing ?? 4
|
||||||
barConfig: topBarContent.barConfig
|
barConfig: topBarContent.barConfig
|
||||||
|
widgetData: parent.widgetData
|
||||||
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
|
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
|
||||||
isAtBottom: barWindow.axis?.edge === "bottom"
|
isAtBottom: barWindow.axis?.edge === "bottom"
|
||||||
visible: SettingsData.getFilteredScreens("systemTray").includes(barWindow.screen) && SystemTray.items.values.length > 0
|
visible: SettingsData.getFilteredScreens("systemTray").includes(barWindow.screen) && SystemTray.items.values.length > 0
|
||||||
|
|||||||
@@ -16,8 +16,11 @@ BasePill {
|
|||||||
enableCursor: false
|
enableCursor: false
|
||||||
|
|
||||||
property var parentWindow: null
|
property var parentWindow: null
|
||||||
|
property var widgetData: null
|
||||||
|
property string section: "right"
|
||||||
property bool isAtBottom: false
|
property bool isAtBottom: false
|
||||||
property bool isAutoHideBar: false
|
property bool isAutoHideBar: false
|
||||||
|
property bool useOverflowPopup: !widgetData?.trayUseInlineExpansion
|
||||||
readonly property var hiddenTrayIds: {
|
readonly property var hiddenTrayIds: {
|
||||||
const envValue = Quickshell.env("DMS_HIDE_TRAYIDS") || "";
|
const envValue = Quickshell.env("DMS_HIDE_TRAYIDS") || "";
|
||||||
return envValue ? envValue.split(",").map(id => id.trim().toLowerCase()) : [];
|
return envValue ? envValue.split(",").map(id => id.trim().toLowerCase()) : [];
|
||||||
@@ -40,6 +43,76 @@ BasePill {
|
|||||||
return `${id}::${tooltipTitle}`;
|
return `${id}::${tooltipTitle}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function trayIconSourceFor(trayItem) {
|
||||||
|
let icon = trayItem && trayItem.icon;
|
||||||
|
if (typeof icon === 'string' || icon instanceof String) {
|
||||||
|
if (icon === "")
|
||||||
|
return "";
|
||||||
|
if (icon.includes("?path=")) {
|
||||||
|
const split = icon.split("?path=");
|
||||||
|
if (split.length !== 2)
|
||||||
|
return icon;
|
||||||
|
const name = split[0];
|
||||||
|
const path = split[1];
|
||||||
|
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
||||||
|
if (fileName.startsWith("dropboxstatus")) {
|
||||||
|
fileName = `hicolor/16x16/status/${fileName}`;
|
||||||
|
}
|
||||||
|
return `file://${path}/${fileName}`;
|
||||||
|
}
|
||||||
|
if (icon.startsWith("/") && !icon.startsWith("file://"))
|
||||||
|
return `file://${icon}`;
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function activateInlineTrayItem(trayItem, anchorItem) {
|
||||||
|
if (!trayItem)
|
||||||
|
return;
|
||||||
|
if (!trayItem.onlyMenu) {
|
||||||
|
trayItem.activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!trayItem.hasMenu)
|
||||||
|
return;
|
||||||
|
root.showForTrayItem(trayItem, anchorItem, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInlineTrayContextMenu(trayItem, areaItem, mouse, anchorItem) {
|
||||||
|
if (!trayItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!trayItem.hasMenu) {
|
||||||
|
const gp = areaItem.mapToGlobal(mouse.x, mouse.y);
|
||||||
|
root.callContextMenuFallback(trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
root.showForTrayItem(trayItem, anchorItem, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleIconName() {
|
||||||
|
const edge = root.axis?.edge;
|
||||||
|
if (root.useOverflowPopup) {
|
||||||
|
switch (edge) {
|
||||||
|
case "left":
|
||||||
|
return root.menuOpen ? "keyboard_arrow_left" : "keyboard_arrow_right";
|
||||||
|
case "right":
|
||||||
|
return root.menuOpen ? "keyboard_arrow_right" : "keyboard_arrow_left";
|
||||||
|
case "bottom":
|
||||||
|
return root.menuOpen ? "keyboard_arrow_down" : "keyboard_arrow_up";
|
||||||
|
case "top":
|
||||||
|
return root.menuOpen ? "keyboard_arrow_up" : "keyboard_arrow_down";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge === "left" || edge === "right") {
|
||||||
|
return root.menuOpen == (root.section !== "right") ? "keyboard_arrow_up" : "keyboard_arrow_down";
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.menuOpen != (root.section === "right") ? "keyboard_arrow_left" : "keyboard_arrow_right";
|
||||||
|
}
|
||||||
|
|
||||||
// ! TODO - replace with either native dbus client (like plugins use) or just a DMS cli or something
|
// ! TODO - replace with either native dbus client (like plugins use) or just a DMS cli or something
|
||||||
function callContextMenuFallback(trayItemId, globalX, globalY) {
|
function callContextMenuFallback(trayItemId, globalX, globalY) {
|
||||||
const script = ['ITEMS=$(dbus-send --session --print-reply --dest=org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierWatcher string:RegisteredStatusNotifierItems 2>/dev/null)', 'while IFS= read -r line; do', ' line="${line#*\\\"}"', ' line="${line%\\\"*}"', ' [ -z "$line" ] && continue', ' BUS="${line%%/*}"', ' OBJ="/${line#*/}"', ' ID=$(dbus-send --session --print-reply --dest="$BUS" "$OBJ" org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierItem string:Id 2>/dev/null | grep -oP "(?<=\\\")(.*?)(?=\\\")" | tail -1)', ' if [ "$ID" = "$1" ]; then', ' dbus-send --session --type=method_call --dest="$BUS" "$OBJ" org.kde.StatusNotifierItem.ContextMenu int32:"$2" int32:"$3"', ' exit 0', ' fi', 'done <<< "$ITEMS"',].join("\n");
|
const script = ['ITEMS=$(dbus-send --session --print-reply --dest=org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierWatcher string:RegisteredStatusNotifierItems 2>/dev/null)', 'while IFS= read -r line; do', ' line="${line#*\\\"}"', ' line="${line%\\\"*}"', ' [ -z "$line" ] && continue', ' BUS="${line%%/*}"', ' OBJ="/${line#*/}"', ' ID=$(dbus-send --session --print-reply --dest="$BUS" "$OBJ" org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierItem string:Id 2>/dev/null | grep -oP "(?<=\\\")(.*?)(?=\\\")" | tail -1)', ' if [ "$ID" = "$1" ]; then', ' dbus-send --session --type=method_call --dest="$BUS" "$OBJ" org.kde.StatusNotifierItem.ContextMenu int32:"$2" int32:"$3"', ' exit 0', ' fi', 'done <<< "$ITEMS"',].join("\n");
|
||||||
@@ -78,6 +151,13 @@ BasePill {
|
|||||||
item: item
|
item: item
|
||||||
}))
|
}))
|
||||||
readonly property var hiddenBarItems: allSortedTrayItems.filter(item => SessionData.isHiddenTrayId(root.getTrayItemKey(item)))
|
readonly property var hiddenBarItems: allSortedTrayItems.filter(item => SessionData.isHiddenTrayId(root.getTrayItemKey(item)))
|
||||||
|
readonly property bool reverseInlineHorizontal: !useOverflowPopup && !isVerticalOrientation && section === "right"
|
||||||
|
readonly property bool reverseInlineVertical: !useOverflowPopup && isVerticalOrientation && section === "right"
|
||||||
|
readonly property var displayedMainBarItems: reverseInlineHorizontal ? [...mainBarItems].reverse() : mainBarItems
|
||||||
|
readonly property var displayedInlineExpandedItems: (reverseInlineHorizontal ? [...hiddenBarItems].reverse() : hiddenBarItems).map(item => ({
|
||||||
|
key: getTrayItemKey(item),
|
||||||
|
item: item
|
||||||
|
}))
|
||||||
|
|
||||||
function moveTrayItemInFullOrder(visibleFromIndex, visibleToIndex) {
|
function moveTrayItemInFullOrder(visibleFromIndex, visibleToIndex) {
|
||||||
if (visibleFromIndex === visibleToIndex || visibleFromIndex < 0 || visibleToIndex < 0)
|
if (visibleFromIndex === visibleToIndex || visibleFromIndex < 0 || visibleToIndex < 0)
|
||||||
@@ -103,6 +183,7 @@ BasePill {
|
|||||||
property int dropTargetIndex: -1
|
property int dropTargetIndex: -1
|
||||||
property bool suppressShiftAnimation: false
|
property bool suppressShiftAnimation: false
|
||||||
readonly property bool hasHiddenItems: allTrayItems.length > mainBarItems.length
|
readonly property bool hasHiddenItems: allTrayItems.length > mainBarItems.length
|
||||||
|
readonly property bool inlineExpanded: hasHiddenItems && !useOverflowPopup && menuOpen
|
||||||
visible: allTrayItems.length > 0
|
visible: allTrayItems.length > 0
|
||||||
opacity: allTrayItems.length > 0 ? 1 : 0
|
opacity: allTrayItems.length > 0 ? 1 : 0
|
||||||
|
|
||||||
@@ -198,10 +279,11 @@ BasePill {
|
|||||||
id: rowComp
|
id: rowComp
|
||||||
Row {
|
Row {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
layoutDirection: root.reverseInlineHorizontal ? Qt.RightToLeft : Qt.LeftToRight
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: root.mainBarItems
|
values: root.displayedMainBarItems
|
||||||
objectProp: "key"
|
objectProp: "key"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,29 +291,7 @@ BasePill {
|
|||||||
id: delegateRoot
|
id: delegateRoot
|
||||||
property var trayItem: modelData.item
|
property var trayItem: modelData.item
|
||||||
property string itemKey: modelData.key
|
property string itemKey: modelData.key
|
||||||
property string iconSource: {
|
property string iconSource: root.trayIconSourceFor(trayItem)
|
||||||
let icon = trayItem && trayItem.icon;
|
|
||||||
if (typeof icon === 'string' || icon instanceof String) {
|
|
||||||
if (icon === "")
|
|
||||||
return "";
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const split = icon.split("?path=");
|
|
||||||
if (split.length !== 2)
|
|
||||||
return icon;
|
|
||||||
const name = split[0];
|
|
||||||
const path = split[1];
|
|
||||||
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
|
||||||
if (fileName.startsWith("dropboxstatus")) {
|
|
||||||
fileName = `hicolor/16x16/status/${fileName}`;
|
|
||||||
}
|
|
||||||
return `file://${path}/${fileName}`;
|
|
||||||
}
|
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://"))
|
|
||||||
return `file://${icon}`;
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
width: root.trayItemSize
|
width: root.trayItemSize
|
||||||
height: root.barThickness
|
height: root.barThickness
|
||||||
@@ -371,7 +431,8 @@ BasePill {
|
|||||||
}
|
}
|
||||||
if (!delegateRoot.trayItem.hasMenu)
|
if (!delegateRoot.trayItem.hasMenu)
|
||||||
return;
|
return;
|
||||||
root.menuOpen = false;
|
if (root.useOverflowPopup)
|
||||||
|
root.menuOpen = false;
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,8 +441,8 @@ BasePill {
|
|||||||
const distance = Math.abs(mouse.x - dragHandler.dragStartPos.x);
|
const distance = Math.abs(mouse.x - dragHandler.dragStartPos.x);
|
||||||
if (distance > 5) {
|
if (distance > 5) {
|
||||||
dragHandler.dragging = true;
|
dragHandler.dragging = true;
|
||||||
root.draggedIndex = index;
|
root.draggedIndex = root.reverseInlineHorizontal ? (root.mainBarItems.length - 1 - index) : index;
|
||||||
root.dropTargetIndex = index;
|
root.dropTargetIndex = root.draggedIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dragHandler.dragging)
|
if (!dragHandler.dragging)
|
||||||
@@ -391,7 +452,8 @@ BasePill {
|
|||||||
dragHandler.dragAxisOffset = axisOffset;
|
dragHandler.dragAxisOffset = axisOffset;
|
||||||
const itemSize = root.trayItemSize;
|
const itemSize = root.trayItemSize;
|
||||||
const slotOffset = Math.round(axisOffset / itemSize);
|
const slotOffset = Math.round(axisOffset / itemSize);
|
||||||
const newTargetIndex = Math.max(0, Math.min(root.mainBarItems.length - 1, index + slotOffset));
|
const visualTargetIndex = Math.max(0, Math.min(root.mainBarItems.length - 1, index + slotOffset));
|
||||||
|
const newTargetIndex = root.reverseInlineHorizontal ? (root.mainBarItems.length - 1 - visualTargetIndex) : visualTargetIndex;
|
||||||
if (newTargetIndex !== root.dropTargetIndex) {
|
if (newTargetIndex !== root.dropTargetIndex) {
|
||||||
root.dropTargetIndex = newTargetIndex;
|
root.dropTargetIndex = newTargetIndex;
|
||||||
}
|
}
|
||||||
@@ -407,7 +469,8 @@ BasePill {
|
|||||||
root.callContextMenuFallback(delegateRoot.trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
root.callContextMenuFallback(delegateRoot.trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
root.menuOpen = false;
|
if (root.useOverflowPopup)
|
||||||
|
root.menuOpen = false;
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,7 +492,7 @@ BasePill {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: root.menuOpen ? "expand_less" : "expand_more"
|
name: root.toggleIconName()
|
||||||
size: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
size: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
color: Theme.widgetTextColor
|
color: Theme.widgetTextColor
|
||||||
}
|
}
|
||||||
@@ -451,6 +514,301 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: root.displayedInlineExpandedItems
|
||||||
|
objectProp: "key"
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: inlineExpandedTrayItemDelegate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: inlineExpandedTrayItemDelegate
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property var trayItem: modelData.item
|
||||||
|
property string itemKey: modelData.key
|
||||||
|
property string iconSource: root.trayIconSourceFor(trayItem)
|
||||||
|
|
||||||
|
width: root.isVerticalOrientation ? root.barThickness : (root.inlineExpanded ? root.trayItemSize : 0)
|
||||||
|
height: root.isVerticalOrientation ? (root.inlineExpanded ? root.trayItemSize : 0) : root.barThickness
|
||||||
|
visible: width > 0 || height > 0
|
||||||
|
|
||||||
|
Behavior on width {
|
||||||
|
enabled: !root.isVerticalOrientation
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on height {
|
||||||
|
enabled: root.isVerticalOrientation
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: inlineVisualContent
|
||||||
|
width: root.trayItemSize
|
||||||
|
height: root.trayItemSize
|
||||||
|
x: root.isVerticalOrientation ? Math.round((parent.width - width) / 2) : (root.reverseInlineHorizontal ? parent.width - width : 0)
|
||||||
|
y: root.isVerticalOrientation ? (root.reverseInlineVertical ? parent.height - height : 0) : Math.round((parent.height - height) / 2)
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: inlineTrayItemArea.containsMouse ? BlurService.hoverColor(Theme.widgetBaseHoverColor) : "transparent"
|
||||||
|
opacity: root.inlineExpanded ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
id: inlineIconImg
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
|
height: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
|
source: iconSource
|
||||||
|
asynchronous: true
|
||||||
|
smooth: true
|
||||||
|
mipmap: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: !inlineIconImg.visible
|
||||||
|
text: {
|
||||||
|
const itemId = trayItem?.id || "";
|
||||||
|
if (!itemId)
|
||||||
|
return "?";
|
||||||
|
return itemId.charAt(0).toUpperCase();
|
||||||
|
}
|
||||||
|
font.pixelSize: 10
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
}
|
||||||
|
|
||||||
|
DankRipple {
|
||||||
|
id: inlineItemRipple
|
||||||
|
cornerRadius: Theme.cornerRadius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: inlineTrayItemArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
enabled: root.inlineExpanded
|
||||||
|
|
||||||
|
onPressed: mouse => {
|
||||||
|
const pos = mapToItem(inlineVisualContent, mouse.x, mouse.y);
|
||||||
|
inlineItemRipple.trigger(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
root.activateInlineTrayItem(trayItem, inlineVisualContent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mouse.button !== Qt.RightButton)
|
||||||
|
return;
|
||||||
|
root.openInlineTrayContextMenu(trayItem, inlineTrayItemArea, mouse, inlineVisualContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: verticalMainTrayItemDelegate
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property var trayItem: modelData.item
|
||||||
|
property string itemKey: modelData.key
|
||||||
|
property string iconSource: root.trayIconSourceFor(trayItem)
|
||||||
|
|
||||||
|
width: root.barThickness
|
||||||
|
height: root.trayItemSize
|
||||||
|
z: dragHandler.dragging ? 100 : 0
|
||||||
|
|
||||||
|
property real shiftOffset: {
|
||||||
|
if (root.draggedIndex < 0)
|
||||||
|
return 0;
|
||||||
|
if (index === root.draggedIndex)
|
||||||
|
return 0;
|
||||||
|
const dragIdx = root.draggedIndex;
|
||||||
|
const dropIdx = root.dropTargetIndex;
|
||||||
|
const shiftAmount = root.trayItemSize;
|
||||||
|
if (dropIdx < 0)
|
||||||
|
return 0;
|
||||||
|
if (dragIdx < dropIdx && index > dragIdx && index <= dropIdx)
|
||||||
|
return -shiftAmount;
|
||||||
|
if (dragIdx > dropIdx && index >= dropIdx && index < dragIdx)
|
||||||
|
return shiftAmount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform: Translate {
|
||||||
|
y: shiftOffset
|
||||||
|
Behavior on y {
|
||||||
|
enabled: !root.suppressShiftAnimation
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 150
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: dragHandler
|
||||||
|
anchors.fill: parent
|
||||||
|
property bool dragging: false
|
||||||
|
property point dragStartPos: Qt.point(0, 0)
|
||||||
|
property real dragAxisOffset: 0
|
||||||
|
property bool longPressing: false
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: longPressTimer
|
||||||
|
interval: 400
|
||||||
|
repeat: false
|
||||||
|
onTriggered: dragHandler.longPressing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: visualContent
|
||||||
|
width: root.trayItemSize
|
||||||
|
height: root.trayItemSize
|
||||||
|
anchors.centerIn: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: trayItemArea.containsMouse ? BlurService.hoverColor(Theme.widgetBaseHoverColor) : "transparent"
|
||||||
|
border.width: dragHandler.dragging ? 2 : 0
|
||||||
|
border.color: Theme.primary
|
||||||
|
opacity: dragHandler.dragging ? 0.8 : 1.0
|
||||||
|
|
||||||
|
transform: Translate {
|
||||||
|
y: dragHandler.dragging ? dragHandler.dragAxisOffset : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
id: iconImg
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
|
height: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
|
source: iconSource
|
||||||
|
asynchronous: true
|
||||||
|
smooth: true
|
||||||
|
mipmap: true
|
||||||
|
visible: status === Image.Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: !iconImg.visible
|
||||||
|
text: {
|
||||||
|
const itemId = trayItem?.id || "";
|
||||||
|
if (!itemId)
|
||||||
|
return "?";
|
||||||
|
return itemId.charAt(0).toUpperCase();
|
||||||
|
}
|
||||||
|
font.pixelSize: 10
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
}
|
||||||
|
|
||||||
|
DankRipple {
|
||||||
|
id: itemRipple
|
||||||
|
cornerRadius: Theme.cornerRadius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: trayItemArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
cursorShape: dragHandler.longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
|
||||||
|
|
||||||
|
onPressed: mouse => {
|
||||||
|
const pos = mapToItem(visualContent, mouse.x, mouse.y);
|
||||||
|
itemRipple.trigger(pos.x, pos.y);
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
dragHandler.dragStartPos = Qt.point(mouse.x, mouse.y);
|
||||||
|
longPressTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onReleased: mouse => {
|
||||||
|
longPressTimer.stop();
|
||||||
|
const wasDragging = dragHandler.dragging;
|
||||||
|
const didReorder = wasDragging && root.dropTargetIndex >= 0 && root.dropTargetIndex !== root.draggedIndex;
|
||||||
|
|
||||||
|
if (didReorder) {
|
||||||
|
root.suppressShiftAnimation = true;
|
||||||
|
root.moveTrayItemInFullOrder(root.draggedIndex, root.dropTargetIndex);
|
||||||
|
Qt.callLater(() => root.suppressShiftAnimation = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
dragHandler.longPressing = false;
|
||||||
|
dragHandler.dragging = false;
|
||||||
|
dragHandler.dragAxisOffset = 0;
|
||||||
|
root.draggedIndex = -1;
|
||||||
|
root.dropTargetIndex = -1;
|
||||||
|
|
||||||
|
if (wasDragging || mouse.button !== Qt.LeftButton)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!trayItem)
|
||||||
|
return;
|
||||||
|
if (!trayItem.onlyMenu) {
|
||||||
|
trayItem.activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!trayItem.hasMenu)
|
||||||
|
return;
|
||||||
|
if (root.useOverflowPopup)
|
||||||
|
root.menuOpen = false;
|
||||||
|
root.showForTrayItem(trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
if (dragHandler.longPressing && !dragHandler.dragging) {
|
||||||
|
const distance = Math.abs(mouse.y - dragHandler.dragStartPos.y);
|
||||||
|
if (distance > 5) {
|
||||||
|
dragHandler.dragging = true;
|
||||||
|
root.draggedIndex = index;
|
||||||
|
root.dropTargetIndex = root.draggedIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dragHandler.dragging)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const axisOffset = mouse.y - dragHandler.dragStartPos.y;
|
||||||
|
dragHandler.dragAxisOffset = axisOffset;
|
||||||
|
const itemSize = root.trayItemSize;
|
||||||
|
const slotOffset = Math.round(axisOffset / itemSize);
|
||||||
|
const newTargetIndex = Math.max(0, Math.min(root.mainBarItems.length - 1, index + slotOffset));
|
||||||
|
if (newTargetIndex !== root.dropTargetIndex) {
|
||||||
|
root.dropTargetIndex = newTargetIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (dragHandler.dragging)
|
||||||
|
return;
|
||||||
|
if (mouse.button !== Qt.RightButton)
|
||||||
|
return;
|
||||||
|
root.openInlineTrayContextMenu(trayItem, trayItemArea, mouse, visualContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,219 +817,23 @@ BasePill {
|
|||||||
Column {
|
Column {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
// Column lacks layoutDirection, so we use four repeaters with mutually exclusive models to control whether main items or expanded items appear above/ below the toggle button.
|
||||||
|
// When reverseInlineVertical is true the first and third repeaters are empty and the second and fourth are active, and vice-versa.
|
||||||
|
// Because items are swapped between repeaters rather than reversed within a single list, vertical drag-and-drop indices don't need remapping (unlike the horizontal RightToLeft case).
|
||||||
Repeater {
|
Repeater {
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: root.mainBarItems
|
values: root.reverseInlineVertical ? [] : root.displayedMainBarItems
|
||||||
objectProp: "key"
|
objectProp: "key"
|
||||||
}
|
}
|
||||||
|
delegate: verticalMainTrayItemDelegate
|
||||||
|
}
|
||||||
|
|
||||||
delegate: Item {
|
Repeater {
|
||||||
id: delegateRoot
|
model: ScriptModel {
|
||||||
property var trayItem: modelData.item
|
values: root.reverseInlineVertical ? root.displayedInlineExpandedItems : []
|
||||||
property string itemKey: modelData.key
|
objectProp: "key"
|
||||||
property string iconSource: {
|
|
||||||
let icon = trayItem && trayItem.icon;
|
|
||||||
if (typeof icon === 'string' || icon instanceof String) {
|
|
||||||
if (icon === "")
|
|
||||||
return "";
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const split = icon.split("?path=");
|
|
||||||
if (split.length !== 2)
|
|
||||||
return icon;
|
|
||||||
const name = split[0];
|
|
||||||
const path = split[1];
|
|
||||||
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
|
||||||
if (fileName.startsWith("dropboxstatus")) {
|
|
||||||
fileName = `hicolor/16x16/status/${fileName}`;
|
|
||||||
}
|
|
||||||
return `file://${path}/${fileName}`;
|
|
||||||
}
|
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://"))
|
|
||||||
return `file://${icon}`;
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
width: root.barThickness
|
|
||||||
height: root.trayItemSize
|
|
||||||
z: dragHandler.dragging ? 100 : 0
|
|
||||||
|
|
||||||
property real shiftOffset: {
|
|
||||||
if (root.draggedIndex < 0)
|
|
||||||
return 0;
|
|
||||||
if (index === root.draggedIndex)
|
|
||||||
return 0;
|
|
||||||
const dragIdx = root.draggedIndex;
|
|
||||||
const dropIdx = root.dropTargetIndex;
|
|
||||||
const shiftAmount = root.trayItemSize;
|
|
||||||
if (dropIdx < 0)
|
|
||||||
return 0;
|
|
||||||
if (dragIdx < dropIdx && index > dragIdx && index <= dropIdx)
|
|
||||||
return -shiftAmount;
|
|
||||||
if (dragIdx > dropIdx && index >= dropIdx && index < dragIdx)
|
|
||||||
return shiftAmount;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
transform: Translate {
|
|
||||||
y: delegateRoot.shiftOffset
|
|
||||||
Behavior on y {
|
|
||||||
enabled: !root.suppressShiftAnimation
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 150
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: dragHandler
|
|
||||||
anchors.fill: parent
|
|
||||||
property bool dragging: false
|
|
||||||
property point dragStartPos: Qt.point(0, 0)
|
|
||||||
property real dragAxisOffset: 0
|
|
||||||
property bool longPressing: false
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: longPressTimer
|
|
||||||
interval: 400
|
|
||||||
repeat: false
|
|
||||||
onTriggered: dragHandler.longPressing = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: visualContent
|
|
||||||
width: root.trayItemSize
|
|
||||||
height: root.trayItemSize
|
|
||||||
anchors.centerIn: parent
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: trayItemArea.containsMouse ? BlurService.hoverColor(Theme.widgetBaseHoverColor) : "transparent"
|
|
||||||
border.width: dragHandler.dragging ? 2 : 0
|
|
||||||
border.color: Theme.primary
|
|
||||||
opacity: dragHandler.dragging ? 0.8 : 1.0
|
|
||||||
|
|
||||||
transform: Translate {
|
|
||||||
y: dragHandler.dragging ? dragHandler.dragAxisOffset : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: iconImg
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
|
||||||
height: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
|
||||||
source: delegateRoot.iconSource
|
|
||||||
asynchronous: true
|
|
||||||
smooth: true
|
|
||||||
mipmap: true
|
|
||||||
visible: status === Image.Ready
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: !iconImg.visible
|
|
||||||
text: {
|
|
||||||
const itemId = trayItem?.id || "";
|
|
||||||
if (!itemId)
|
|
||||||
return "?";
|
|
||||||
return itemId.charAt(0).toUpperCase();
|
|
||||||
}
|
|
||||||
font.pixelSize: 10
|
|
||||||
color: Theme.widgetTextColor
|
|
||||||
}
|
|
||||||
|
|
||||||
DankRipple {
|
|
||||||
id: itemRipple
|
|
||||||
cornerRadius: Theme.cornerRadius
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: trayItemArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
cursorShape: dragHandler.longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
|
|
||||||
|
|
||||||
onPressed: mouse => {
|
|
||||||
const pos = mapToItem(visualContent, mouse.x, mouse.y);
|
|
||||||
itemRipple.trigger(pos.x, pos.y);
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
dragHandler.dragStartPos = Qt.point(mouse.x, mouse.y);
|
|
||||||
longPressTimer.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onReleased: mouse => {
|
|
||||||
longPressTimer.stop();
|
|
||||||
const wasDragging = dragHandler.dragging;
|
|
||||||
const didReorder = wasDragging && root.dropTargetIndex >= 0 && root.dropTargetIndex !== root.draggedIndex;
|
|
||||||
|
|
||||||
if (didReorder) {
|
|
||||||
root.suppressShiftAnimation = true;
|
|
||||||
root.moveTrayItemInFullOrder(root.draggedIndex, root.dropTargetIndex);
|
|
||||||
Qt.callLater(() => root.suppressShiftAnimation = false);
|
|
||||||
}
|
|
||||||
|
|
||||||
dragHandler.longPressing = false;
|
|
||||||
dragHandler.dragging = false;
|
|
||||||
dragHandler.dragAxisOffset = 0;
|
|
||||||
root.draggedIndex = -1;
|
|
||||||
root.dropTargetIndex = -1;
|
|
||||||
|
|
||||||
if (wasDragging || mouse.button !== Qt.LeftButton)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!delegateRoot.trayItem)
|
|
||||||
return;
|
|
||||||
if (!delegateRoot.trayItem.onlyMenu) {
|
|
||||||
delegateRoot.trayItem.activate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!delegateRoot.trayItem.hasMenu)
|
|
||||||
return;
|
|
||||||
root.menuOpen = false;
|
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
onPositionChanged: mouse => {
|
|
||||||
if (dragHandler.longPressing && !dragHandler.dragging) {
|
|
||||||
const distance = Math.abs(mouse.y - dragHandler.dragStartPos.y);
|
|
||||||
if (distance > 5) {
|
|
||||||
dragHandler.dragging = true;
|
|
||||||
root.draggedIndex = index;
|
|
||||||
root.dropTargetIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dragHandler.dragging)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const axisOffset = mouse.y - dragHandler.dragStartPos.y;
|
|
||||||
dragHandler.dragAxisOffset = axisOffset;
|
|
||||||
const itemSize = root.trayItemSize;
|
|
||||||
const slotOffset = Math.round(axisOffset / itemSize);
|
|
||||||
const newTargetIndex = Math.max(0, Math.min(root.mainBarItems.length - 1, index + slotOffset));
|
|
||||||
if (newTargetIndex !== root.dropTargetIndex) {
|
|
||||||
root.dropTargetIndex = newTargetIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: mouse => {
|
|
||||||
if (dragHandler.dragging)
|
|
||||||
return;
|
|
||||||
if (mouse.button !== Qt.RightButton)
|
|
||||||
return;
|
|
||||||
if (!delegateRoot.trayItem?.hasMenu) {
|
|
||||||
const gp = trayItemArea.mapToGlobal(mouse.x, mouse.y);
|
|
||||||
root.callContextMenuFallback(delegateRoot.trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
root.menuOpen = false;
|
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
delegate: inlineExpandedTrayItemDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -689,14 +851,7 @@ BasePill {
|
|||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
name: {
|
name: root.toggleIconName()
|
||||||
const edge = root.axis?.edge;
|
|
||||||
if (edge === "left") {
|
|
||||||
return root.menuOpen ? "chevron_left" : "chevron_right";
|
|
||||||
} else {
|
|
||||||
return root.menuOpen ? "chevron_right" : "chevron_left";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
size: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
|
||||||
color: Theme.widgetTextColor
|
color: Theme.widgetTextColor
|
||||||
}
|
}
|
||||||
@@ -718,6 +873,22 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: root.reverseInlineVertical ? [] : root.displayedInlineExpandedItems
|
||||||
|
objectProp: "key"
|
||||||
|
}
|
||||||
|
delegate: inlineExpandedTrayItemDelegate
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: root.reverseInlineVertical ? root.displayedMainBarItems : []
|
||||||
|
objectProp: "key"
|
||||||
|
}
|
||||||
|
delegate: verticalMainTrayItemDelegate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,7 +904,7 @@ BasePill {
|
|||||||
blurRadius: Theme.cornerRadius
|
blurRadius: Theme.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: root.menuOpen
|
visible: root.useOverflowPopup && root.menuOpen
|
||||||
screen: root.parentScreen
|
screen: root.parentScreen
|
||||||
WlrLayershell.layer: WlrLayershell.Top
|
WlrLayershell.layer: WlrLayershell.Top
|
||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
@@ -749,13 +920,14 @@ BasePill {
|
|||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
windows: [overflowMenu]
|
windows: [overflowMenu]
|
||||||
active: CompositorService.useHyprlandFocusGrab && root.menuOpen
|
active: CompositorService.useHyprlandFocusGrab && root.useOverflowPopup && root.menuOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: PopoutManager
|
target: PopoutManager
|
||||||
function onPopoutOpening() {
|
function onPopoutOpening() {
|
||||||
root.menuOpen = false;
|
if (root.useOverflowPopup)
|
||||||
|
root.menuOpen = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,30 +1193,7 @@ BasePill {
|
|||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
property var trayItem: modelData
|
property var trayItem: modelData
|
||||||
property string iconSource: {
|
property string iconSource: root.trayIconSourceFor(trayItem)
|
||||||
let icon = trayItem?.icon;
|
|
||||||
if (typeof icon === 'string' || icon instanceof String) {
|
|
||||||
if (icon === "")
|
|
||||||
return "";
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const split = icon.split("?path=");
|
|
||||||
if (split.length !== 2)
|
|
||||||
return icon;
|
|
||||||
const name = split[0];
|
|
||||||
const path = split[1];
|
|
||||||
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
|
||||||
if (fileName.startsWith("dropboxstatus")) {
|
|
||||||
fileName = `hicolor/16x16/status/${fileName}`;
|
|
||||||
}
|
|
||||||
return `file://${path}/${fileName}`;
|
|
||||||
}
|
|
||||||
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
|
||||||
return `file://${icon}`;
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
width: root.trayItemSize + 4
|
width: root.trayItemSize + 4
|
||||||
height: root.trayItemSize + 4
|
height: root.trayItemSize + 4
|
||||||
@@ -1313,7 +1462,8 @@ BasePill {
|
|||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
updatePosition();
|
updatePosition();
|
||||||
root.menuOpen = false;
|
if (root.useOverflowPopup)
|
||||||
|
root.menuOpen = false;
|
||||||
PopoutManager.closeAllPopouts();
|
PopoutManager.closeAllPopouts();
|
||||||
ModalManager.closeAllModalsExcept(null);
|
ModalManager.closeAllModalsExcept(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ Item {
|
|||||||
"id": widget.id,
|
"id": widget.id,
|
||||||
"enabled": widget.enabled
|
"enabled": widget.enabled
|
||||||
};
|
};
|
||||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion"];
|
||||||
for (var i = 0; i < keys.length; i++) {
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (widget[keys[i]] !== undefined)
|
if (widget[keys[i]] !== undefined)
|
||||||
result[keys[i]] = widget[keys[i]];
|
result[keys[i]] = widget[keys[i]];
|
||||||
@@ -712,6 +712,8 @@ Item {
|
|||||||
item.barMaxVisibleRunningApps = widget.barMaxVisibleRunningApps;
|
item.barMaxVisibleRunningApps = widget.barMaxVisibleRunningApps;
|
||||||
if (widget.barShowOverflowBadge !== undefined)
|
if (widget.barShowOverflowBadge !== undefined)
|
||||||
item.barShowOverflowBadge = widget.barShowOverflowBadge;
|
item.barShowOverflowBadge = widget.barShowOverflowBadge;
|
||||||
|
if (widget.trayUseInlineExpansion !== undefined)
|
||||||
|
item.trayUseInlineExpansion = widget.trayUseInlineExpansion;
|
||||||
}
|
}
|
||||||
widgets.push(item);
|
widgets.push(item);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ Column {
|
|||||||
"id": widget.id,
|
"id": widget.id,
|
||||||
"enabled": widget.enabled
|
"enabled": widget.enabled
|
||||||
};
|
};
|
||||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion"];
|
||||||
for (var i = 0; i < keys.length; i++) {
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (widget[keys[i]] !== undefined)
|
if (widget[keys[i]] !== undefined)
|
||||||
result[keys[i]] = widget[keys[i]];
|
result[keys[i]] = widget[keys[i]];
|
||||||
@@ -437,7 +437,7 @@ Column {
|
|||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "keyboard_layout_name" || modelData.id === "appsDock"
|
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "keyboard_layout_name" || modelData.id === "appsDock" || modelData.id === "systemTray"
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
id: compactModeButton
|
id: compactModeButton
|
||||||
@@ -543,6 +543,39 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: trayMenuButton
|
||||||
|
buttonSize: 32
|
||||||
|
visible: modelData.id === "systemTray"
|
||||||
|
iconName: "more_vert"
|
||||||
|
iconSize: 18
|
||||||
|
iconColor: Theme.outline
|
||||||
|
onClicked: {
|
||||||
|
trayContextMenu.widgetData = modelData;
|
||||||
|
trayContextMenu.sectionId = root.sectionId;
|
||||||
|
trayContextMenu.widgetIndex = index;
|
||||||
|
|
||||||
|
var buttonPos = trayMenuButton.mapToItem(root, 0, 0);
|
||||||
|
var popupWidth = trayContextMenu.width;
|
||||||
|
var popupHeight = trayContextMenu.height;
|
||||||
|
|
||||||
|
var xPos = buttonPos.x - popupWidth - Theme.spacingS;
|
||||||
|
if (xPos < 0)
|
||||||
|
xPos = buttonPos.x + trayMenuButton.width + Theme.spacingS;
|
||||||
|
|
||||||
|
var yPos = buttonPos.y - popupHeight / 2 + trayMenuButton.height / 2;
|
||||||
|
if (yPos < 0) {
|
||||||
|
yPos = Theme.spacingS;
|
||||||
|
} else if (yPos + popupHeight > root.height) {
|
||||||
|
yPos = root.height - popupHeight - Theme.spacingS;
|
||||||
|
}
|
||||||
|
|
||||||
|
trayContextMenu.x = xPos;
|
||||||
|
trayContextMenu.y = yPos;
|
||||||
|
trayContextMenu.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: compactModeTooltip
|
id: compactModeTooltip
|
||||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||||
@@ -931,6 +964,88 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Popup {
|
||||||
|
id: trayContextMenu
|
||||||
|
|
||||||
|
property var widgetData: null
|
||||||
|
property string sectionId: ""
|
||||||
|
property int widgetIndex: -1
|
||||||
|
readonly property var currentWidgetData: (widgetIndex >= 0 && widgetIndex < root.items.length) ? root.items[widgetIndex] : widgetData
|
||||||
|
|
||||||
|
width: 220
|
||||||
|
height: contentColumn.implicitHeight + Theme.spacingS * 2
|
||||||
|
padding: 0
|
||||||
|
modal: true
|
||||||
|
focus: true
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
|
border.width: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item {
|
||||||
|
Column {
|
||||||
|
id: contentColumn
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingS
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: trayOverflowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "arrow_selector_tool"
|
||||||
|
size: 16
|
||||||
|
color: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Use Inline Expansion")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankToggle {
|
||||||
|
id: trayOverflowToggle
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 40
|
||||||
|
height: 20
|
||||||
|
checked: trayContextMenu.currentWidgetData?.trayUseInlineExpansion ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: trayOverflowArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
const newValue = !(trayContextMenu.currentWidgetData?.trayUseInlineExpansion ?? false);
|
||||||
|
root.overflowSettingChanged(trayContextMenu.sectionId, trayContextMenu.widgetIndex, "trayUseInlineExpansion", newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Popup {
|
Popup {
|
||||||
id: diskUsageContextMenu
|
id: diskUsageContextMenu
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user