mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-27 23:12:49 -05:00
feat: appsDock Widget Overflow & Config Options
This commit is contained in:
@@ -263,6 +263,9 @@ Singleton {
|
||||
property bool clockCompactMode: false
|
||||
property bool focusedWindowCompactMode: false
|
||||
property bool runningAppsCompactMode: true
|
||||
property int barMaxVisibleApps: 0
|
||||
property int barMaxVisibleRunningApps: 0
|
||||
property bool barShowOverflowBadge: true
|
||||
property bool keyboardLayoutNameCompactMode: false
|
||||
property bool runningAppsCurrentWorkspace: false
|
||||
property bool runningAppsGroupByApp: false
|
||||
|
||||
@@ -120,6 +120,9 @@ var SPEC = {
|
||||
clockCompactMode: { def: false },
|
||||
focusedWindowCompactMode: { def: false },
|
||||
runningAppsCompactMode: { def: true },
|
||||
barMaxVisibleApps: { def: 0 },
|
||||
barMaxVisibleRunningApps: { def: 0 },
|
||||
barShowOverflowBadge: { def: true },
|
||||
keyboardLayoutNameCompactMode: { def: false },
|
||||
runningAppsCurrentWorkspace: { def: false },
|
||||
runningAppsGroupByApp: { def: false },
|
||||
|
||||
@@ -31,6 +31,15 @@ Item {
|
||||
property bool suppressShiftAnimation: false
|
||||
property int pinnedAppCount: 0
|
||||
|
||||
property int maxVisibleApps: widgetData?.barMaxVisibleApps !== undefined ? widgetData.barMaxVisibleApps : SettingsData.barMaxVisibleApps
|
||||
property int maxVisibleRunningApps: widgetData?.barMaxVisibleRunningApps !== undefined ? widgetData.barMaxVisibleRunningApps : SettingsData.barMaxVisibleRunningApps
|
||||
property bool showOverflowBadge: widgetData?.barShowOverflowBadge !== undefined ? widgetData.barShowOverflowBadge : SettingsData.barShowOverflowBadge
|
||||
property bool overflowExpanded: false
|
||||
property int overflowItemCount: 0
|
||||
|
||||
onMaxVisibleAppsChanged: updateModel()
|
||||
onMaxVisibleRunningAppsChanged: updateModel()
|
||||
|
||||
readonly property real effectiveBarThickness: {
|
||||
if (barThickness > 0 && barSpacing > 0) {
|
||||
return barThickness + barSpacing;
|
||||
@@ -116,6 +125,12 @@ Item {
|
||||
function onRunningAppsCurrentWorkspaceChanged() {
|
||||
updateModel();
|
||||
}
|
||||
function onBarMaxVisibleAppsChanged() {
|
||||
updateModel();
|
||||
}
|
||||
function onBarMaxVisibleRunningAppsChanged() {
|
||||
updateModel();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
@@ -165,7 +180,51 @@ Item {
|
||||
return null;
|
||||
}
|
||||
|
||||
function updateModel() {
|
||||
function createSeparator(key) {
|
||||
return {
|
||||
uniqueKey: key,
|
||||
type: "separator",
|
||||
appId: "__SEPARATOR__",
|
||||
toplevel: null,
|
||||
isPinned: false,
|
||||
isRunning: false,
|
||||
isInOverflow: false
|
||||
};
|
||||
}
|
||||
|
||||
function markAsOverflow(item) {
|
||||
return {
|
||||
uniqueKey: item.uniqueKey,
|
||||
type: item.type,
|
||||
appId: item.appId,
|
||||
toplevel: item.toplevel,
|
||||
isPinned: item.isPinned,
|
||||
isRunning: item.isRunning,
|
||||
windowCount: item.windowCount,
|
||||
allWindows: item.allWindows,
|
||||
isCoreApp: item.isCoreApp,
|
||||
coreAppData: item.coreAppData,
|
||||
isInOverflow: true
|
||||
};
|
||||
}
|
||||
|
||||
function markAsVisible(item) {
|
||||
return {
|
||||
uniqueKey: item.uniqueKey,
|
||||
type: item.type,
|
||||
appId: item.appId,
|
||||
toplevel: item.toplevel,
|
||||
isPinned: item.isPinned,
|
||||
isRunning: item.isRunning,
|
||||
windowCount: item.windowCount,
|
||||
allWindows: item.allWindows,
|
||||
isCoreApp: item.isCoreApp,
|
||||
coreAppData: item.coreAppData,
|
||||
isInOverflow: false
|
||||
};
|
||||
}
|
||||
|
||||
function buildBaseItems() {
|
||||
const items = [];
|
||||
const pinnedApps = [...(SessionData.barPinnedApps || [])];
|
||||
_toplevelsUpdateTrigger;
|
||||
@@ -235,7 +294,8 @@ Item {
|
||||
windowCount: group.windows.length,
|
||||
allWindows: group.windows,
|
||||
isCoreApp: group.isCoreApp || false,
|
||||
coreAppData: group.coreAppData || null
|
||||
coreAppData: group.coreAppData || null,
|
||||
isInOverflow: false
|
||||
};
|
||||
|
||||
if (group.isPinned) {
|
||||
@@ -248,20 +308,97 @@ Item {
|
||||
pinnedGroups.forEach(item => items.push(item));
|
||||
|
||||
if (pinnedGroups.length > 0 && unpinnedGroups.length > 0) {
|
||||
items.push({
|
||||
uniqueKey: "separator_grouped",
|
||||
type: "separator",
|
||||
appId: "__SEPARATOR__",
|
||||
toplevel: null,
|
||||
isPinned: false,
|
||||
isRunning: false
|
||||
});
|
||||
items.push(createSeparator("separator_grouped"));
|
||||
}
|
||||
|
||||
unpinnedGroups.forEach(item => items.push(item));
|
||||
|
||||
root.pinnedAppCount = pinnedGroups.length;
|
||||
dockItems = items;
|
||||
return {
|
||||
items,
|
||||
pinnedCount: pinnedGroups.length,
|
||||
runningCount: unpinnedGroups.length
|
||||
};
|
||||
}
|
||||
|
||||
function applyOverflow(baseResult) {
|
||||
const { items } = baseResult;
|
||||
const maxPinned = root.maxVisibleApps;
|
||||
const maxRunning = root.maxVisibleRunningApps;
|
||||
|
||||
const pinnedItems = items.filter(i => i.type === "grouped" && i.isPinned);
|
||||
const runningItems = items.filter(i => i.type === "grouped" && i.isRunning && !i.isPinned);
|
||||
|
||||
const pinnedOverflow = maxPinned > 0 && pinnedItems.length > maxPinned;
|
||||
const runningOverflow = maxRunning > 0 && runningItems.length > maxRunning;
|
||||
|
||||
if (!pinnedOverflow && !runningOverflow) {
|
||||
root.overflowItemCount = 0;
|
||||
return items.map(i => markAsVisible(i));
|
||||
}
|
||||
|
||||
const visiblePinnedKeys = new Set(pinnedOverflow ? pinnedItems.slice(0, maxPinned).map(i => i.uniqueKey) : pinnedItems.map(i => i.uniqueKey));
|
||||
const visibleRunningKeys = new Set(runningOverflow ? runningItems.slice(0, maxRunning).map(i => i.uniqueKey) : runningItems.map(i => i.uniqueKey));
|
||||
|
||||
const overflowPinnedCount = pinnedOverflow ? pinnedItems.length - maxPinned : 0;
|
||||
const overflowRunningCount = runningOverflow ? runningItems.length - maxRunning : 0;
|
||||
const totalOverflow = overflowPinnedCount + overflowRunningCount;
|
||||
root.overflowItemCount = totalOverflow;
|
||||
|
||||
const finalItems = [];
|
||||
let addedSeparator = false;
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
switch (item.type) {
|
||||
case "separator":
|
||||
break;
|
||||
case "grouped":
|
||||
if (item.isPinned) {
|
||||
if (visiblePinnedKeys.has(item.uniqueKey)) {
|
||||
finalItems.push(markAsVisible(item));
|
||||
} else {
|
||||
finalItems.push(markAsOverflow(item));
|
||||
}
|
||||
} else if (item.isRunning) {
|
||||
if (!addedSeparator && finalItems.length > 0) {
|
||||
finalItems.push(createSeparator("separator_overflow"));
|
||||
addedSeparator = true;
|
||||
}
|
||||
if (visibleRunningKeys.has(item.uniqueKey)) {
|
||||
finalItems.push(markAsVisible(item));
|
||||
} else {
|
||||
finalItems.push(markAsOverflow(item));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
finalItems.push(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalOverflow > 0) {
|
||||
const toggleIndex = finalItems.findIndex(i => i.type === "separator");
|
||||
const insertPos = toggleIndex >= 0 ? toggleIndex : finalItems.length;
|
||||
finalItems.splice(insertPos, 0, {
|
||||
uniqueKey: "overflow_toggle",
|
||||
type: "overflow-toggle",
|
||||
appId: "__OVERFLOW_TOGGLE__",
|
||||
toplevel: null,
|
||||
isPinned: false,
|
||||
isRunning: false,
|
||||
isInOverflow: false,
|
||||
overflowCount: totalOverflow
|
||||
});
|
||||
}
|
||||
|
||||
return finalItems;
|
||||
}
|
||||
|
||||
function updateModel() {
|
||||
const baseResult = buildBaseItems();
|
||||
dockItems = applyOverflow(baseResult);
|
||||
}
|
||||
|
||||
Component.onCompleted: updateModel()
|
||||
@@ -284,6 +421,10 @@ Item {
|
||||
|
||||
for (let i = 0; i < dockItems.length; i++) {
|
||||
const item = dockItems[i];
|
||||
const isInOverflow = item.isInOverflow === true;
|
||||
if (isInOverflow && !root.overflowExpanded)
|
||||
continue;
|
||||
|
||||
let itemSize = 0;
|
||||
if (item.type === "separator") {
|
||||
itemSize = 8;
|
||||
@@ -411,13 +552,33 @@ Item {
|
||||
Item {
|
||||
id: delegateItem
|
||||
property bool isSeparator: modelData.type === "separator"
|
||||
readonly property bool isOverflowToggle: modelData.type === "overflow-toggle"
|
||||
readonly property bool isInOverflow: modelData.isInOverflow === true
|
||||
|
||||
readonly property real visualSize: isSeparator ? 8 : ((widgetData?.runningAppsCompactMode !== undefined ? widgetData.runningAppsCompactMode : SettingsData.runningAppsCompactMode) ? 24 : (24 + Theme.spacingXS + 120))
|
||||
readonly property real visualWidth: root.isVertical ? root.barThickness : visualSize
|
||||
readonly property real visualHeight: root.isVertical ? visualSize : root.barThickness
|
||||
|
||||
width: visualWidth
|
||||
height: visualHeight
|
||||
visible: !isInOverflow || root.overflowExpanded
|
||||
opacity: (isInOverflow && !root.overflowExpanded) ? 0 : 1
|
||||
scale: (isInOverflow && !root.overflowExpanded) ? 0.8 : 1
|
||||
|
||||
width: (isInOverflow && !root.overflowExpanded) ? 0 : visualWidth
|
||||
height: (isInOverflow && !root.overflowExpanded) ? 0 : visualHeight
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
z: (dragHandler.dragging) ? 100 : 0
|
||||
|
||||
@@ -471,9 +632,27 @@ Item {
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
AppsDockOverflowButton {
|
||||
visible: isOverflowToggle
|
||||
anchors.centerIn: parent
|
||||
width: delegateItem.visualWidth
|
||||
height: delegateItem.visualHeight
|
||||
iconSize: 24
|
||||
overflowCount: modelData.overflowCount || 0
|
||||
overflowExpanded: root.overflowExpanded
|
||||
isVertical: root.isVertical
|
||||
showBadge: root.showOverflowBadge
|
||||
z: 10
|
||||
onClicked: {
|
||||
console.log("Overflow button clicked! Current state:", root.overflowExpanded);
|
||||
root.overflowExpanded = !root.overflowExpanded;
|
||||
console.log("New state:", root.overflowExpanded);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: appItem
|
||||
visible: !isSeparator
|
||||
visible: !isSeparator && !isOverflowToggle
|
||||
anchors.fill: parent
|
||||
|
||||
property bool isFocused: {
|
||||
@@ -786,21 +965,22 @@ Item {
|
||||
|
||||
onEntered: {
|
||||
root.hoveredItem = delegateItem;
|
||||
if (isSeparator)
|
||||
if (isSeparator || isOverflowToggle)
|
||||
return;
|
||||
|
||||
tooltipLoader.active = true;
|
||||
if (tooltipLoader.item) {
|
||||
if (root.isVertical) {
|
||||
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2);
|
||||
const globalPos = delegateItem.mapToGlobal(0, delegateItem.height / 2);
|
||||
const screenX = root.parentScreen ? root.parentScreen.x : 0;
|
||||
const screenY = root.parentScreen ? root.parentScreen.y : 0;
|
||||
const relativeY = globalPos.y - screenY;
|
||||
const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (root.parentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS);
|
||||
const barThickness = root.effectiveBarThickness;
|
||||
const spacing = barConfig?.spacing ?? 4;
|
||||
const isLeft = root.axis?.edge === "left";
|
||||
const adjustedY = relativeY + root.minTooltipY;
|
||||
const finalX = screenX + tooltipX;
|
||||
tooltipLoader.item.show(appItem.tooltipText, finalX, adjustedY, root.parentScreen, isLeft, !isLeft);
|
||||
const tooltipOffset = barThickness + spacing + Theme.spacingM;
|
||||
const tooltipX = isLeft ? tooltipOffset : (root.parentScreen.width - tooltipOffset);
|
||||
const screenRelativeY = globalPos.y - screenY + root.barY;
|
||||
tooltipLoader.item.show(appItem.tooltipText, screenX + tooltipX, screenRelativeY, root.parentScreen, isLeft, !isLeft);
|
||||
} else {
|
||||
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height);
|
||||
const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real iconSize: 24
|
||||
property int overflowCount: 0
|
||||
property bool overflowExpanded: false
|
||||
property bool isVertical: false
|
||||
property bool showBadge: true
|
||||
|
||||
signal clicked
|
||||
|
||||
Rectangle {
|
||||
id: buttonBackground
|
||||
anchors.centerIn: parent
|
||||
width: root.iconSize
|
||||
height: root.iconSize
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, mouseArea.containsMouse ? 0.2 : 0.1)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
id: arrowIcon
|
||||
anchors.centerIn: parent
|
||||
size: root.iconSize * 0.6
|
||||
name: "expand_more"
|
||||
color: Theme.widgetIconColor
|
||||
rotation: isVertical ? (overflowExpanded ? 180 : 0) : (overflowExpanded ? 90 : -90)
|
||||
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: overflowCount > 0 && !overflowExpanded && root.showBadge
|
||||
anchors.right: buttonBackground.right
|
||||
anchors.top: buttonBackground.top
|
||||
anchors.rightMargin: -4
|
||||
anchors.topMargin: -4
|
||||
width: Math.max(18, badgeText.width + 8)
|
||||
height: 18
|
||||
radius: 9
|
||||
color: Theme.primary
|
||||
z: 10
|
||||
|
||||
StyledText {
|
||||
id: badgeText
|
||||
anchors.centerIn: parent
|
||||
text: `+${overflowCount}`
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.onPrimary
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
||||
@@ -419,7 +419,7 @@ Item {
|
||||
"id": widget.id,
|
||||
"enabled": widget.enabled
|
||||
};
|
||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon"];
|
||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (widget[keys[i]] !== undefined)
|
||||
result[keys[i]] = widget[keys[i]];
|
||||
@@ -530,6 +530,18 @@ Item {
|
||||
setWidgetsForSection(sectionId, widgets);
|
||||
}
|
||||
|
||||
function handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value) {
|
||||
var widgets = getWidgetsForSection(sectionId).slice();
|
||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
||||
setWidgetsForSection(sectionId, widgets);
|
||||
return;
|
||||
}
|
||||
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||
newWidget[settingName] = value;
|
||||
widgets[widgetIndex] = newWidget;
|
||||
setWidgetsForSection(sectionId, widgets);
|
||||
}
|
||||
|
||||
function handleCompactModeChanged(sectionId, widgetId, value) {
|
||||
var widgets = getWidgetsForSection(sectionId).slice();
|
||||
for (var i = 0; i < widgets.length; i++) {
|
||||
@@ -621,6 +633,12 @@ Item {
|
||||
item.runningAppsCompactMode = widget.runningAppsCompactMode;
|
||||
if (widget.keyboardLayoutNameCompactMode !== undefined)
|
||||
item.keyboardLayoutNameCompactMode = widget.keyboardLayoutNameCompactMode;
|
||||
if (widget.barMaxVisibleApps !== undefined)
|
||||
item.barMaxVisibleApps = widget.barMaxVisibleApps;
|
||||
if (widget.barMaxVisibleRunningApps !== undefined)
|
||||
item.barMaxVisibleRunningApps = widget.barMaxVisibleRunningApps;
|
||||
if (widget.barShowOverflowBadge !== undefined)
|
||||
item.barShowOverflowBadge = widget.barShowOverflowBadge;
|
||||
}
|
||||
widgets.push(item);
|
||||
});
|
||||
@@ -897,6 +915,9 @@ Item {
|
||||
onCompactModeChanged: (widgetId, value) => {
|
||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||
}
|
||||
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
|
||||
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,6 +973,9 @@ Item {
|
||||
onCompactModeChanged: (widgetId, value) => {
|
||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||
}
|
||||
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
|
||||
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1007,6 +1031,9 @@ Item {
|
||||
onCompactModeChanged: (widgetId, value) => {
|
||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||
}
|
||||
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
|
||||
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,14 @@ Column {
|
||||
signal privacySettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
|
||||
signal minimumWidthChanged(string sectionId, int widgetIndex, bool enabled)
|
||||
signal showSwapChanged(string sectionId, int widgetIndex, bool enabled)
|
||||
signal overflowSettingChanged(string sectionId, int widgetIndex, string settingName, var value)
|
||||
|
||||
function cloneWidgetData(widget) {
|
||||
var result = {
|
||||
"id": widget.id,
|
||||
"enabled": widget.enabled
|
||||
};
|
||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon"];
|
||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (widget[keys[i]] !== undefined)
|
||||
result[keys[i]] = widget[keys[i]];
|
||||
@@ -408,7 +409,7 @@ Column {
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "runningApps" || modelData.id === "keyboard_layout_name"
|
||||
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "runningApps" || modelData.id === "keyboard_layout_name" || modelData.id === "appsDock"
|
||||
|
||||
DankActionButton {
|
||||
id: compactModeButton
|
||||
@@ -508,6 +509,49 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: overflowMenuButton
|
||||
buttonSize: 28
|
||||
visible: modelData.id === "appsDock"
|
||||
iconName: "unfold_more"
|
||||
iconSize: 16
|
||||
iconColor: {
|
||||
const maxApps = modelData.barMaxVisibleApps !== undefined ? modelData.barMaxVisibleApps : SettingsData.barMaxVisibleApps;
|
||||
const maxRunning = modelData.barMaxVisibleRunningApps !== undefined ? modelData.barMaxVisibleRunningApps : SettingsData.barMaxVisibleRunningApps;
|
||||
return (maxApps > 0 || maxRunning > 0) ? Theme.primary : Theme.outline;
|
||||
}
|
||||
onClicked: {
|
||||
overflowContextMenu.widgetData = modelData;
|
||||
overflowContextMenu.sectionId = root.sectionId;
|
||||
overflowContextMenu.widgetIndex = index;
|
||||
|
||||
var buttonPos = overflowMenuButton.mapToItem(root, 0, 0);
|
||||
var popupWidth = overflowContextMenu.width;
|
||||
var popupHeight = overflowContextMenu.height;
|
||||
|
||||
var xPos = buttonPos.x - popupWidth - Theme.spacingS;
|
||||
if (xPos < 0)
|
||||
xPos = buttonPos.x + overflowMenuButton.width + Theme.spacingS;
|
||||
|
||||
var yPos = buttonPos.y - popupHeight / 2 + overflowMenuButton.height / 2;
|
||||
if (yPos < 0) {
|
||||
yPos = Theme.spacingS;
|
||||
} else if (yPos + popupHeight > root.height) {
|
||||
yPos = root.height - popupHeight - Theme.spacingS;
|
||||
}
|
||||
|
||||
overflowContextMenu.x = xPos;
|
||||
overflowContextMenu.y = yPos;
|
||||
overflowContextMenu.open();
|
||||
}
|
||||
onEntered: {
|
||||
sharedTooltip.show(I18n.tr("Overflow"), overflowMenuButton, 0, 0, "bottom");
|
||||
}
|
||||
onExited: {
|
||||
sharedTooltip.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: compactModeTooltip
|
||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||
@@ -1384,4 +1428,219 @@ Column {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Popup {
|
||||
id: overflowContextMenu
|
||||
|
||||
property var widgetData: null
|
||||
property string sectionId: ""
|
||||
property int widgetIndex: -1
|
||||
|
||||
// Dynamically get current widget data from the items list
|
||||
readonly property var currentWidgetData: (widgetIndex >= 0 && widgetIndex < root.items.length) ? root.items[widgetIndex] : widgetData
|
||||
|
||||
width: 280
|
||||
height: overflowMenuColumn.implicitHeight + Theme.spacingS * 2
|
||||
padding: 0
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
background: Rectangle {
|
||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
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: overflowMenuColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingS
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Overflow")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
leftPadding: Theme.spacingS
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Max Pinned Apps")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 120
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: 24
|
||||
iconName: "remove"
|
||||
iconSize: 14
|
||||
iconColor: Theme.outline
|
||||
onClicked: {
|
||||
var current = overflowContextMenu.currentWidgetData?.barMaxVisibleApps ?? SettingsData.barMaxVisibleApps;
|
||||
var newVal = Math.max(0, current - 1);
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barMaxVisibleApps", newVal);
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
var val = overflowContextMenu.currentWidgetData?.barMaxVisibleApps ?? SettingsData.barMaxVisibleApps;
|
||||
return val === 0 ? I18n.tr("All") : val;
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width: 30
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: 24
|
||||
iconName: "add"
|
||||
iconSize: 14
|
||||
iconColor: Theme.outline
|
||||
onClicked: {
|
||||
var current = overflowContextMenu.currentWidgetData?.barMaxVisibleApps ?? SettingsData.barMaxVisibleApps;
|
||||
var newVal = current + 1;
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barMaxVisibleApps", newVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Max Running Apps")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 120
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: 24
|
||||
iconName: "remove"
|
||||
iconSize: 14
|
||||
iconColor: Theme.outline
|
||||
onClicked: {
|
||||
var current = overflowContextMenu.currentWidgetData?.barMaxVisibleRunningApps ?? SettingsData.barMaxVisibleRunningApps;
|
||||
var newVal = Math.max(0, current - 1);
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barMaxVisibleRunningApps", newVal);
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
var val = overflowContextMenu.currentWidgetData?.barMaxVisibleRunningApps ?? SettingsData.barMaxVisibleRunningApps;
|
||||
return val === 0 ? I18n.tr("All") : val;
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width: 30
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
buttonSize: 24
|
||||
iconName: "add"
|
||||
iconSize: 14
|
||||
iconColor: Theme.outline
|
||||
onClicked: {
|
||||
var current = overflowContextMenu.currentWidgetData?.barMaxVisibleRunningApps ?? SettingsData.barMaxVisibleRunningApps;
|
||||
var newVal = current + 1;
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barMaxVisibleRunningApps", newVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outline
|
||||
opacity: 0.15
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: badgeToggleArea.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: "notifications"
|
||||
size: 16
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Show Badge")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Normal
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
id: badgeToggle
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 40
|
||||
height: 20
|
||||
checked: overflowContextMenu.currentWidgetData?.barShowOverflowBadge ?? SettingsData.barShowOverflowBadge
|
||||
onToggled: {
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barShowOverflowBadge", toggled);
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: badgeToggleArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
badgeToggle.checked = !badgeToggle.checked;
|
||||
root.overflowSettingChanged(overflowContextMenu.sectionId, overflowContextMenu.widgetIndex, "barShowOverflowBadge", badgeToggle.checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user