mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
feat: Group by App on Running Apps
This commit is contained in:
@@ -109,6 +109,7 @@ Singleton {
|
||||
property bool focusedWindowCompactMode: false
|
||||
property bool runningAppsCompactMode: true
|
||||
property bool runningAppsCurrentWorkspace: false
|
||||
property bool runningAppsGroupByApp: false
|
||||
property string clockDateFormat: ""
|
||||
property string lockDateFormat: ""
|
||||
property int mediaSize: 1
|
||||
@@ -373,6 +374,7 @@ Singleton {
|
||||
focusedWindowCompactMode = settings.focusedWindowCompactMode !== undefined ? settings.focusedWindowCompactMode : false
|
||||
runningAppsCompactMode = settings.runningAppsCompactMode !== undefined ? settings.runningAppsCompactMode : true
|
||||
runningAppsCurrentWorkspace = settings.runningAppsCurrentWorkspace !== undefined ? settings.runningAppsCurrentWorkspace : false
|
||||
runningAppsGroupByApp = settings.runningAppsGroupByApp !== undefined ? settings.runningAppsGroupByApp : false
|
||||
clockDateFormat = settings.clockDateFormat !== undefined ? settings.clockDateFormat : ""
|
||||
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : ""
|
||||
mediaSize = settings.mediaSize !== undefined ? settings.mediaSize : (settings.mediaCompactMode !== undefined ? (settings.mediaCompactMode ? 0 : 1) : 1)
|
||||
@@ -576,6 +578,7 @@ Singleton {
|
||||
"focusedWindowCompactMode": focusedWindowCompactMode,
|
||||
"runningAppsCompactMode": runningAppsCompactMode,
|
||||
"runningAppsCurrentWorkspace": runningAppsCurrentWorkspace,
|
||||
"runningAppsGroupByApp": runningAppsGroupByApp,
|
||||
"clockDateFormat": clockDateFormat,
|
||||
"lockDateFormat": lockDateFormat,
|
||||
"mediaSize": mediaSize,
|
||||
@@ -701,7 +704,7 @@ Singleton {
|
||||
"controlCenterWidgets", "showWorkspaceIndex", "workspaceScrolling", "showWorkspacePadding", "showWorkspaceApps",
|
||||
"maxWorkspaceIcons", "workspacesPerMonitor", "workspaceNameIcons", "waveProgressEnabled",
|
||||
"clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode",
|
||||
"runningAppsCurrentWorkspace", "clockDateFormat", "lockDateFormat", "mediaSize",
|
||||
"runningAppsCurrentWorkspace", "runningAppsGroupByApp", "clockDateFormat", "lockDateFormat", "mediaSize",
|
||||
"dankBarLeftWidgets", "dankBarCenterWidgets", "dankBarRightWidgets",
|
||||
"appLauncherViewMode", "spotlightModalViewMode", "sortAppsAlphabetically",
|
||||
"networkPreference", "iconTheme", "launcherLogoMode", "launcherLogoCustomPath",
|
||||
@@ -1232,6 +1235,11 @@ Singleton {
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setRunningAppsGroupByApp(enabled) {
|
||||
runningAppsGroupByApp = enabled
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setClockDateFormat(format) {
|
||||
clockDateFormat = format || ""
|
||||
saveSettings()
|
||||
|
||||
@@ -26,7 +26,28 @@ Rectangle {
|
||||
}
|
||||
return CompositorService.sortedToplevels;
|
||||
}
|
||||
readonly property int windowCount: sortedToplevels.length
|
||||
readonly property var groupedWindows: {
|
||||
if (!SettingsData.runningAppsGroupByApp) {
|
||||
return [];
|
||||
}
|
||||
const appGroups = new Map();
|
||||
sortedToplevels.forEach((toplevel, index) => {
|
||||
const appId = toplevel.appId || "unknown";
|
||||
if (!appGroups.has(appId)) {
|
||||
appGroups.set(appId, {
|
||||
appId: appId,
|
||||
windows: []
|
||||
});
|
||||
}
|
||||
appGroups.get(appId).windows.push({
|
||||
toplevel: toplevel,
|
||||
windowId: index,
|
||||
windowTitle: toplevel.title || "(Unnamed)"
|
||||
});
|
||||
});
|
||||
return Array.from(appGroups.values());
|
||||
}
|
||||
readonly property int windowCount: SettingsData.runningAppsGroupByApp ? groupedWindows.length : sortedToplevels.length
|
||||
readonly property int calculatedSize: {
|
||||
if (windowCount === 0) {
|
||||
return 0;
|
||||
@@ -158,15 +179,19 @@ Rectangle {
|
||||
|
||||
Repeater {
|
||||
id: windowRepeater
|
||||
model: sortedToplevels
|
||||
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
|
||||
|
||||
delegate: Item {
|
||||
id: delegateItem
|
||||
|
||||
property bool isFocused: modelData.activated
|
||||
property string appId: modelData.appId || ""
|
||||
property string windowTitle: modelData.title || "(Unnamed)"
|
||||
property var toplevelObject: modelData
|
||||
property bool isGrouped: SettingsData.runningAppsGroupByApp
|
||||
property var groupData: isGrouped ? modelData : null
|
||||
property var toplevelData: isGrouped ? (modelData.windows.length > 0 ? modelData.windows[0].toplevel : null) : modelData
|
||||
property bool isFocused: toplevelData ? toplevelData.activated : false
|
||||
property string appId: isGrouped ? modelData.appId : (modelData.appId || "")
|
||||
property string windowTitle: toplevelData ? (toplevelData.title || "(Unnamed)") : "(Unnamed)"
|
||||
property var toplevelObject: toplevelData
|
||||
property int windowCount: isGrouped ? modelData.windows.length : 1
|
||||
property string tooltipText: {
|
||||
let appName = "Unknown";
|
||||
if (appId) {
|
||||
@@ -174,6 +199,9 @@ Rectangle {
|
||||
appName = desktopEntry
|
||||
&& desktopEntry.name ? desktopEntry.name : appId;
|
||||
}
|
||||
if (isGrouped && windowCount > 1) {
|
||||
return appName + " (" + windowCount + " windows)";
|
||||
}
|
||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||
}
|
||||
|
||||
@@ -264,6 +292,27 @@ Rectangle {
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: SettingsData.runningAppsCompactMode ? -2 : 2
|
||||
anchors.bottomMargin: -2
|
||||
width: 14
|
||||
height: 14
|
||||
radius: 7
|
||||
color: Theme.primary
|
||||
visible: isGrouped && windowCount > 1
|
||||
z: 10
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: windowCount > 9 ? "9+" : windowCount
|
||||
font.pixelSize: 9
|
||||
color: Theme.surface
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
// Window title text (only visible in expanded mode)
|
||||
StyledText {
|
||||
anchors.left: iconImg.right
|
||||
@@ -289,7 +338,17 @@ Rectangle {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (toplevelObject) {
|
||||
if (isGrouped && windowCount > 1) {
|
||||
let currentIndex = -1;
|
||||
for (let i = 0; i < groupData.windows.length; i++) {
|
||||
if (groupData.windows[i].toplevel.activated) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nextIndex = (currentIndex + 1) % groupData.windows.length;
|
||||
groupData.windows[nextIndex].toplevel.activate();
|
||||
} else if (toplevelObject) {
|
||||
toplevelObject.activate();
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
@@ -352,15 +411,19 @@ Rectangle {
|
||||
|
||||
Repeater {
|
||||
id: windowRepeater
|
||||
model: sortedToplevels
|
||||
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
|
||||
|
||||
delegate: Item {
|
||||
id: delegateItem
|
||||
|
||||
property bool isFocused: modelData.activated
|
||||
property string appId: modelData.appId || ""
|
||||
property string windowTitle: modelData.title || "(Unnamed)"
|
||||
property var toplevelObject: modelData
|
||||
property bool isGrouped: SettingsData.runningAppsGroupByApp
|
||||
property var groupData: isGrouped ? modelData : null
|
||||
property var toplevelData: isGrouped ? (modelData.windows.length > 0 ? modelData.windows[0].toplevel : null) : modelData
|
||||
property bool isFocused: toplevelData ? toplevelData.activated : false
|
||||
property string appId: isGrouped ? modelData.appId : (modelData.appId || "")
|
||||
property string windowTitle: toplevelData ? (toplevelData.title || "(Unnamed)") : "(Unnamed)"
|
||||
property var toplevelObject: toplevelData
|
||||
property int windowCount: isGrouped ? modelData.windows.length : 1
|
||||
property string tooltipText: {
|
||||
let appName = "Unknown";
|
||||
if (appId) {
|
||||
@@ -368,6 +431,9 @@ Rectangle {
|
||||
appName = desktopEntry
|
||||
&& desktopEntry.name ? desktopEntry.name : appId;
|
||||
}
|
||||
if (isGrouped && windowCount > 1) {
|
||||
return appName + " (" + windowCount + " windows)";
|
||||
}
|
||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||
}
|
||||
|
||||
@@ -456,6 +522,27 @@ Rectangle {
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: SettingsData.runningAppsCompactMode ? -2 : 2
|
||||
anchors.bottomMargin: -2
|
||||
width: 14
|
||||
height: 14
|
||||
radius: 7
|
||||
color: Theme.primary
|
||||
visible: isGrouped && windowCount > 1
|
||||
z: 10
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: windowCount > 9 ? "9+" : windowCount
|
||||
font.pixelSize: 9
|
||||
color: Theme.surface
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.left: iconImg.right
|
||||
anchors.leftMargin: Theme.spacingXS
|
||||
@@ -480,7 +567,17 @@ Rectangle {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (toplevelObject) {
|
||||
if (isGrouped && windowCount > 1) {
|
||||
let currentIndex = -1;
|
||||
for (let i = 0; i < groupData.windows.length; i++) {
|
||||
if (groupData.windows[i].toplevel.activated) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nextIndex = (currentIndex + 1) % groupData.windows.length;
|
||||
groupData.windows[nextIndex].toplevel.activate();
|
||||
} else if (toplevelObject) {
|
||||
toplevelObject.activate();
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
|
||||
@@ -463,6 +463,32 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: groupByAppButton
|
||||
buttonSize: 28
|
||||
visible: modelData.id === "runningApps"
|
||||
iconName: "apps"
|
||||
iconSize: 16
|
||||
iconColor: SettingsData.runningAppsGroupByApp ? Theme.primary : Theme.outline
|
||||
onClicked: {
|
||||
SettingsData.setRunningAppsGroupByApp(!SettingsData.runningAppsGroupByApp)
|
||||
}
|
||||
onEntered: {
|
||||
groupByAppTooltipLoader.active = true
|
||||
if (groupByAppTooltipLoader.item) {
|
||||
const tooltipText = SettingsData.runningAppsGroupByApp ? "Ungroup" : "Group by App"
|
||||
const p = groupByAppButton.mapToItem(null, groupByAppButton.width / 2, 0)
|
||||
groupByAppTooltipLoader.item.show(tooltipText, p.x, p.y - 40, null)
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
if (groupByAppTooltipLoader.item) {
|
||||
groupByAppTooltipLoader.item.hide()
|
||||
}
|
||||
groupByAppTooltipLoader.active = false
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: compactModeTooltip
|
||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||
@@ -930,4 +956,10 @@ Column {
|
||||
active: false
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: groupByAppTooltipLoader
|
||||
active: false
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user