mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -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 focusedWindowCompactMode: false
|
||||||
property bool runningAppsCompactMode: true
|
property bool runningAppsCompactMode: true
|
||||||
property bool runningAppsCurrentWorkspace: false
|
property bool runningAppsCurrentWorkspace: false
|
||||||
|
property bool runningAppsGroupByApp: false
|
||||||
property string clockDateFormat: ""
|
property string clockDateFormat: ""
|
||||||
property string lockDateFormat: ""
|
property string lockDateFormat: ""
|
||||||
property int mediaSize: 1
|
property int mediaSize: 1
|
||||||
@@ -373,6 +374,7 @@ Singleton {
|
|||||||
focusedWindowCompactMode = settings.focusedWindowCompactMode !== undefined ? settings.focusedWindowCompactMode : false
|
focusedWindowCompactMode = settings.focusedWindowCompactMode !== undefined ? settings.focusedWindowCompactMode : false
|
||||||
runningAppsCompactMode = settings.runningAppsCompactMode !== undefined ? settings.runningAppsCompactMode : true
|
runningAppsCompactMode = settings.runningAppsCompactMode !== undefined ? settings.runningAppsCompactMode : true
|
||||||
runningAppsCurrentWorkspace = settings.runningAppsCurrentWorkspace !== undefined ? settings.runningAppsCurrentWorkspace : false
|
runningAppsCurrentWorkspace = settings.runningAppsCurrentWorkspace !== undefined ? settings.runningAppsCurrentWorkspace : false
|
||||||
|
runningAppsGroupByApp = settings.runningAppsGroupByApp !== undefined ? settings.runningAppsGroupByApp : false
|
||||||
clockDateFormat = settings.clockDateFormat !== undefined ? settings.clockDateFormat : ""
|
clockDateFormat = settings.clockDateFormat !== undefined ? settings.clockDateFormat : ""
|
||||||
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : ""
|
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : ""
|
||||||
mediaSize = settings.mediaSize !== undefined ? settings.mediaSize : (settings.mediaCompactMode !== undefined ? (settings.mediaCompactMode ? 0 : 1) : 1)
|
mediaSize = settings.mediaSize !== undefined ? settings.mediaSize : (settings.mediaCompactMode !== undefined ? (settings.mediaCompactMode ? 0 : 1) : 1)
|
||||||
@@ -576,6 +578,7 @@ Singleton {
|
|||||||
"focusedWindowCompactMode": focusedWindowCompactMode,
|
"focusedWindowCompactMode": focusedWindowCompactMode,
|
||||||
"runningAppsCompactMode": runningAppsCompactMode,
|
"runningAppsCompactMode": runningAppsCompactMode,
|
||||||
"runningAppsCurrentWorkspace": runningAppsCurrentWorkspace,
|
"runningAppsCurrentWorkspace": runningAppsCurrentWorkspace,
|
||||||
|
"runningAppsGroupByApp": runningAppsGroupByApp,
|
||||||
"clockDateFormat": clockDateFormat,
|
"clockDateFormat": clockDateFormat,
|
||||||
"lockDateFormat": lockDateFormat,
|
"lockDateFormat": lockDateFormat,
|
||||||
"mediaSize": mediaSize,
|
"mediaSize": mediaSize,
|
||||||
@@ -701,7 +704,7 @@ Singleton {
|
|||||||
"controlCenterWidgets", "showWorkspaceIndex", "workspaceScrolling", "showWorkspacePadding", "showWorkspaceApps",
|
"controlCenterWidgets", "showWorkspaceIndex", "workspaceScrolling", "showWorkspacePadding", "showWorkspaceApps",
|
||||||
"maxWorkspaceIcons", "workspacesPerMonitor", "workspaceNameIcons", "waveProgressEnabled",
|
"maxWorkspaceIcons", "workspacesPerMonitor", "workspaceNameIcons", "waveProgressEnabled",
|
||||||
"clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode",
|
"clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode",
|
||||||
"runningAppsCurrentWorkspace", "clockDateFormat", "lockDateFormat", "mediaSize",
|
"runningAppsCurrentWorkspace", "runningAppsGroupByApp", "clockDateFormat", "lockDateFormat", "mediaSize",
|
||||||
"dankBarLeftWidgets", "dankBarCenterWidgets", "dankBarRightWidgets",
|
"dankBarLeftWidgets", "dankBarCenterWidgets", "dankBarRightWidgets",
|
||||||
"appLauncherViewMode", "spotlightModalViewMode", "sortAppsAlphabetically",
|
"appLauncherViewMode", "spotlightModalViewMode", "sortAppsAlphabetically",
|
||||||
"networkPreference", "iconTheme", "launcherLogoMode", "launcherLogoCustomPath",
|
"networkPreference", "iconTheme", "launcherLogoMode", "launcherLogoCustomPath",
|
||||||
@@ -1232,6 +1235,11 @@ Singleton {
|
|||||||
saveSettings()
|
saveSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setRunningAppsGroupByApp(enabled) {
|
||||||
|
runningAppsGroupByApp = enabled
|
||||||
|
saveSettings()
|
||||||
|
}
|
||||||
|
|
||||||
function setClockDateFormat(format) {
|
function setClockDateFormat(format) {
|
||||||
clockDateFormat = format || ""
|
clockDateFormat = format || ""
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|||||||
@@ -26,7 +26,28 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
return CompositorService.sortedToplevels;
|
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: {
|
readonly property int calculatedSize: {
|
||||||
if (windowCount === 0) {
|
if (windowCount === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -158,15 +179,19 @@ Rectangle {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: windowRepeater
|
id: windowRepeater
|
||||||
model: sortedToplevels
|
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
id: delegateItem
|
||||||
|
|
||||||
property bool isFocused: modelData.activated
|
property bool isGrouped: SettingsData.runningAppsGroupByApp
|
||||||
property string appId: modelData.appId || ""
|
property var groupData: isGrouped ? modelData : null
|
||||||
property string windowTitle: modelData.title || "(Unnamed)"
|
property var toplevelData: isGrouped ? (modelData.windows.length > 0 ? modelData.windows[0].toplevel : null) : modelData
|
||||||
property var toplevelObject: 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: {
|
property string tooltipText: {
|
||||||
let appName = "Unknown";
|
let appName = "Unknown";
|
||||||
if (appId) {
|
if (appId) {
|
||||||
@@ -174,6 +199,9 @@ Rectangle {
|
|||||||
appName = desktopEntry
|
appName = desktopEntry
|
||||||
&& desktopEntry.name ? desktopEntry.name : appId;
|
&& desktopEntry.name ? desktopEntry.name : appId;
|
||||||
}
|
}
|
||||||
|
if (isGrouped && windowCount > 1) {
|
||||||
|
return appName + " (" + windowCount + " windows)";
|
||||||
|
}
|
||||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +292,27 @@ Rectangle {
|
|||||||
font.weight: Font.Medium
|
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)
|
// Window title text (only visible in expanded mode)
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.left: iconImg.right
|
anchors.left: iconImg.right
|
||||||
@@ -289,7 +338,17 @@ Rectangle {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
onClicked: (mouse) => {
|
onClicked: (mouse) => {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
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();
|
toplevelObject.activate();
|
||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
@@ -352,15 +411,19 @@ Rectangle {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: windowRepeater
|
id: windowRepeater
|
||||||
model: sortedToplevels
|
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
id: delegateItem
|
||||||
|
|
||||||
property bool isFocused: modelData.activated
|
property bool isGrouped: SettingsData.runningAppsGroupByApp
|
||||||
property string appId: modelData.appId || ""
|
property var groupData: isGrouped ? modelData : null
|
||||||
property string windowTitle: modelData.title || "(Unnamed)"
|
property var toplevelData: isGrouped ? (modelData.windows.length > 0 ? modelData.windows[0].toplevel : null) : modelData
|
||||||
property var toplevelObject: 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: {
|
property string tooltipText: {
|
||||||
let appName = "Unknown";
|
let appName = "Unknown";
|
||||||
if (appId) {
|
if (appId) {
|
||||||
@@ -368,6 +431,9 @@ Rectangle {
|
|||||||
appName = desktopEntry
|
appName = desktopEntry
|
||||||
&& desktopEntry.name ? desktopEntry.name : appId;
|
&& desktopEntry.name ? desktopEntry.name : appId;
|
||||||
}
|
}
|
||||||
|
if (isGrouped && windowCount > 1) {
|
||||||
|
return appName + " (" + windowCount + " windows)";
|
||||||
|
}
|
||||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,6 +522,27 @@ Rectangle {
|
|||||||
font.weight: Font.Medium
|
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 {
|
StyledText {
|
||||||
anchors.left: iconImg.right
|
anchors.left: iconImg.right
|
||||||
anchors.leftMargin: Theme.spacingXS
|
anchors.leftMargin: Theme.spacingXS
|
||||||
@@ -480,7 +567,17 @@ Rectangle {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
onClicked: (mouse) => {
|
onClicked: (mouse) => {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
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();
|
toplevelObject.activate();
|
||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} 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 {
|
Rectangle {
|
||||||
id: compactModeTooltip
|
id: compactModeTooltip
|
||||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||||
@@ -930,4 +956,10 @@ Column {
|
|||||||
active: false
|
active: false
|
||||||
sourceComponent: DankTooltip {}
|
sourceComponent: DankTooltip {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: groupByAppTooltipLoader
|
||||||
|
active: false
|
||||||
|
sourceComponent: DankTooltip {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user