1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

settings: mecha re-organization

This commit is contained in:
bbedward
2025-12-03 17:25:40 -05:00
parent 2c7f24a913
commit 788da62777
40 changed files with 10034 additions and 9580 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,15 +19,14 @@ FocusScope {
color: "transparent"
Loader {
id: personalizationLoader
id: wallpaperLoader
anchors.fill: parent
active: root.currentIndex === 0
visible: active
focus: active
sourceComponent: Component {
PersonalizationTab {
WallpaperTab {
parentModal: root.parentModal
}
}
@@ -41,7 +40,6 @@ FocusScope {
Loader {
id: timeWeatherLoader
anchors.fill: parent
active: root.currentIndex === 1
visible: active
@@ -58,7 +56,6 @@ FocusScope {
Loader {
id: keybindsLoader
anchors.fill: parent
active: root.currentIndex === 2
visible: active
@@ -77,7 +74,6 @@ FocusScope {
Loader {
id: topBarLoader
anchors.fill: parent
active: root.currentIndex === 3
visible: active
@@ -95,14 +91,13 @@ FocusScope {
}
Loader {
id: widgetsLoader
id: workspacesLoader
anchors.fill: parent
active: root.currentIndex === 4
visible: active
focus: active
sourceComponent: WidgetTweaksTab {}
sourceComponent: WorkspacesTab {}
onActiveChanged: {
if (active && item) {
@@ -113,7 +108,6 @@ FocusScope {
Loader {
id: dockLoader
anchors.fill: parent
active: root.currentIndex === 5
visible: active
@@ -132,7 +126,6 @@ FocusScope {
Loader {
id: displaysLoader
anchors.fill: parent
active: root.currentIndex === 6
visible: active
@@ -149,7 +142,6 @@ FocusScope {
Loader {
id: networkLoader
anchors.fill: parent
active: root.currentIndex === 7
visible: active
@@ -166,7 +158,6 @@ FocusScope {
Loader {
id: printerLoader
anchors.fill: parent
active: root.currentIndex === 8
visible: active
@@ -183,7 +174,6 @@ FocusScope {
Loader {
id: launcherLoader
anchors.fill: parent
active: root.currentIndex === 9
visible: active
@@ -200,7 +190,6 @@ FocusScope {
Loader {
id: themeColorsLoader
anchors.fill: parent
active: root.currentIndex === 10
visible: active
@@ -216,14 +205,13 @@ FocusScope {
}
Loader {
id: powerLoader
id: lockScreenLoader
anchors.fill: parent
active: root.currentIndex === 11
visible: active
focus: active
sourceComponent: PowerSettings {}
sourceComponent: LockScreenTab {}
onActiveChanged: {
if (active && item) {
@@ -234,7 +222,6 @@ FocusScope {
Loader {
id: pluginsLoader
anchors.fill: parent
active: root.currentIndex === 12
visible: active
@@ -253,7 +240,6 @@ FocusScope {
Loader {
id: aboutLoader
anchors.fill: parent
active: root.currentIndex === 13
visible: active
@@ -267,5 +253,133 @@ FocusScope {
}
}
}
Loader {
id: typographyMotionLoader
anchors.fill: parent
active: root.currentIndex === 14
visible: active
focus: active
sourceComponent: TypographyMotionTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: soundsLoader
anchors.fill: parent
active: root.currentIndex === 15
visible: active
focus: active
sourceComponent: SoundsTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: mediaPlayerLoader
anchors.fill: parent
active: root.currentIndex === 16
visible: active
focus: active
sourceComponent: MediaPlayerTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: notificationsLoader
anchors.fill: parent
active: root.currentIndex === 17
visible: active
focus: active
sourceComponent: NotificationsTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: osdLoader
anchors.fill: parent
active: root.currentIndex === 18
visible: active
focus: active
sourceComponent: OSDTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: runningAppsLoader
anchors.fill: parent
active: root.currentIndex === 19
visible: active
focus: active
sourceComponent: RunningAppsTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: systemUpdaterLoader
anchors.fill: parent
active: root.currentIndex === 20
visible: active
focus: active
sourceComponent: SystemUpdaterTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
Loader {
id: powerSleepLoader
anchors.fill: parent
active: root.currentIndex === 21
visible: active
focus: active
sourceComponent: PowerSleepTab {}
onActiveChanged: {
if (active && item) {
Qt.callLater(() => item.forceActiveFocus());
}
}
}
}
}

View File

@@ -41,7 +41,7 @@ FloatingWindow {
title: I18n.tr("Settings", "settings window title")
minimumSize: Qt.size(500, 400)
implicitWidth: 800
implicitHeight: 800
implicitHeight: 875
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
visible: false
@@ -121,29 +121,18 @@ FloatingWindow {
focus: true
Keys.onPressed: event => {
const tabCount = 13;
if (event.key === Qt.Key_Escape) {
hide();
event.accepted = true;
return;
}
if (event.key === Qt.Key_Down) {
currentTabIndex = (currentTabIndex + 1) % tabCount;
if (event.key === Qt.Key_Down || (event.key === Qt.Key_Tab && !event.modifiers)) {
sidebar.navigateNext();
event.accepted = true;
return;
}
if (event.key === Qt.Key_Up) {
currentTabIndex = (currentTabIndex - 1 + tabCount) % tabCount;
event.accepted = true;
return;
}
if (event.key === Qt.Key_Tab && !event.modifiers) {
currentTabIndex = (currentTabIndex + 1) % tabCount;
event.accepted = true;
return;
}
if (event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && event.modifiers & Qt.ShiftModifier)) {
currentTabIndex = (currentTabIndex - 1 + tabCount) % tabCount;
if (event.key === Qt.Key_Up || event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && event.modifiers & Qt.ShiftModifier)) {
sidebar.navigatePrevious();
event.accepted = true;
return;
}

View File

@@ -7,105 +7,324 @@ import qs.Services
import qs.Widgets
Rectangle {
id: sidebarContainer
id: root
property int currentIndex: 0
property var parentModal: null
readonly property var allSidebarItems: [
property var expandedCategories: ({})
property var autoExpandedCategories: ({})
readonly property var categoryStructure: [
{
"id": "personalization",
"text": I18n.tr("Personalization"),
"icon": "person",
"tabIndex": 0
},
{
"text": I18n.tr("Time & Weather"),
"icon": "schedule",
"tabIndex": 1
},
{
"text": I18n.tr("Keyboard Shortcuts"),
"icon": "keyboard",
"shortcutsOnly": true,
"tabIndex": 2
"icon": "palette",
"children": [
{
"text": I18n.tr("Wallpaper"),
"icon": "wallpaper",
"tabIndex": 0
},
{
"text": I18n.tr("Theme & Colors"),
"icon": "format_paint",
"tabIndex": 10
},
{
"text": I18n.tr("Typography & Motion"),
"icon": "text_fields",
"tabIndex": 14
},
{
"text": I18n.tr("Time & Weather"),
"icon": "schedule",
"tabIndex": 1
},
{
"text": I18n.tr("Sounds"),
"icon": "volume_up",
"tabIndex": 15,
"soundsOnly": true
}
]
},
{
"id": "dankbar",
"text": I18n.tr("Dank Bar"),
"icon": "toolbar",
"tabIndex": 3
},
{
"text": I18n.tr("Widgets"),
"icon": "widgets",
"tabIndex": 4
"id": "workspaces_widgets",
"text": I18n.tr("Workspaces & Widgets"),
"icon": "dashboard",
"collapsedByDefault": true,
"children": [
{
"text": I18n.tr("Workspaces"),
"icon": "view_module",
"tabIndex": 4
},
{
"text": I18n.tr("Media Player"),
"icon": "music_note",
"tabIndex": 16
},
{
"text": I18n.tr("Notifications"),
"icon": "notifications",
"tabIndex": 17
},
{
"text": I18n.tr("On-screen Displays"),
"icon": "tune",
"tabIndex": 18
},
{
"text": I18n.tr("Running Apps"),
"icon": "apps",
"tabIndex": 19,
"hyprlandNiriOnly": true
},
{
"text": I18n.tr("System Updater"),
"icon": "refresh",
"tabIndex": 20
}
]
},
{
"text": I18n.tr("Dock"),
"icon": "dock_to_bottom",
"tabIndex": 5
"id": "dock_launcher",
"text": I18n.tr("Dock & Launcher"),
"icon": "apps",
"collapsedByDefault": true,
"children": [
{
"text": I18n.tr("Dock"),
"icon": "dock_to_bottom",
"tabIndex": 5
},
{
"text": I18n.tr("Launcher"),
"icon": "grid_view",
"tabIndex": 9
}
]
},
{
"id": "input",
"text": I18n.tr("Keyboard Shortcuts"),
"icon": "keyboard",
"tabIndex": 2,
"shortcutsOnly": true
},
{
"id": "displays",
"text": I18n.tr("Displays"),
"icon": "monitor",
"tabIndex": 6
},
{
"id": "network",
"text": I18n.tr("Network"),
"icon": "wifi",
"dmsOnly": true,
"tabIndex": 7
"tabIndex": 7,
"dmsOnly": true
},
{
"id": "printers",
"text": I18n.tr("Printers"),
"icon": "print",
"cupsOnly": true,
"tabIndex": 8
},
{
"text": I18n.tr("Launcher"),
"icon": "apps",
"tabIndex": 9
},
{
"text": I18n.tr("Theme & Colors"),
"icon": "palette",
"tabIndex": 10
"tabIndex": 8,
"cupsOnly": true
},
{
"id": "power_security",
"text": I18n.tr("Power & Security"),
"icon": "power",
"tabIndex": 11
"icon": "security",
"collapsedByDefault": true,
"children": [
{
"text": I18n.tr("Lock Screen"),
"icon": "lock",
"tabIndex": 11
},
{
"text": I18n.tr("Power & Sleep"),
"icon": "power_settings_new",
"tabIndex": 21
}
]
},
{
"id": "plugins",
"text": I18n.tr("Plugins"),
"icon": "extension",
"tabIndex": 12
},
{
"id": "separator",
"separator": true
},
{
"id": "about",
"text": I18n.tr("About"),
"icon": "info",
"tabIndex": 13
}
]
readonly property var sidebarItems: allSidebarItems.filter(item => {
function isItemVisible(item) {
if (item.dmsOnly && NetworkService.usingLegacy)
return false;
if (item.cupsOnly && !CupsService.cupsAvailable)
return false;
if (item.shortcutsOnly && !KeybindsService.available)
return false;
if (item.soundsOnly && !AudioService.soundsAvailable)
return false;
if (item.hyprlandNiriOnly && !CompositorService.isNiri && !CompositorService.isHyprland)
return false;
return true;
})
}
function hasVisibleChildren(category) {
if (!category.children)
return false;
return category.children.some(child => isItemVisible(child));
}
function isCategoryVisible(category) {
if (category.separator)
return true;
if (!isItemVisible(category))
return false;
if (category.children && !hasVisibleChildren(category))
return false;
return true;
}
function toggleCategory(categoryId) {
var newExpanded = Object.assign({}, expandedCategories);
newExpanded[categoryId] = !isCategoryExpanded(categoryId);
expandedCategories = newExpanded;
var newAutoExpanded = Object.assign({}, autoExpandedCategories);
delete newAutoExpanded[categoryId];
autoExpandedCategories = newAutoExpanded;
}
function isCategoryExpanded(categoryId) {
if (expandedCategories[categoryId] !== undefined) {
return expandedCategories[categoryId];
}
var category = categoryStructure.find(cat => cat.id === categoryId);
if (category && category.collapsedByDefault) {
return false;
}
return true;
}
function isChildActive(category) {
if (!category.children)
return false;
return category.children.some(child => child.tabIndex === currentIndex);
}
function findParentCategory(tabIndex) {
for (var i = 0; i < categoryStructure.length; i++) {
var cat = categoryStructure[i];
if (cat.children) {
for (var j = 0; j < cat.children.length; j++) {
if (cat.children[j].tabIndex === tabIndex) {
return cat;
}
}
}
}
return null;
}
function autoExpandForTab(tabIndex) {
var parent = findParentCategory(tabIndex);
if (!parent)
return;
if (!isCategoryExpanded(parent.id)) {
var newExpanded = Object.assign({}, expandedCategories);
newExpanded[parent.id] = true;
expandedCategories = newExpanded;
var newAutoExpanded = Object.assign({}, autoExpandedCategories);
newAutoExpanded[parent.id] = true;
autoExpandedCategories = newAutoExpanded;
}
}
function autoCollapseIfNeeded(oldTabIndex, newTabIndex) {
var oldParent = findParentCategory(oldTabIndex);
var newParent = findParentCategory(newTabIndex);
if (oldParent && oldParent !== newParent && autoExpandedCategories[oldParent.id]) {
var newExpanded = Object.assign({}, expandedCategories);
newExpanded[oldParent.id] = false;
expandedCategories = newExpanded;
var newAutoExpanded = Object.assign({}, autoExpandedCategories);
delete newAutoExpanded[oldParent.id];
autoExpandedCategories = newAutoExpanded;
}
}
function navigateNext() {
const currentItemIndex = sidebarItems.findIndex(item => item.tabIndex === currentIndex);
const nextIndex = (currentItemIndex + 1) % sidebarItems.length;
currentIndex = sidebarItems[nextIndex].tabIndex;
var flatItems = getFlatNavigableItems();
var currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
var oldIndex = currentIndex;
if (currentPos === -1) {
currentIndex = flatItems[0]?.tabIndex ?? 0;
} else {
var nextPos = (currentPos + 1) % flatItems.length;
currentIndex = flatItems[nextPos].tabIndex;
}
autoCollapseIfNeeded(oldIndex, currentIndex);
autoExpandForTab(currentIndex);
}
function navigatePrevious() {
const currentItemIndex = sidebarItems.findIndex(item => item.tabIndex === currentIndex);
const prevIndex = (currentItemIndex - 1 + sidebarItems.length) % sidebarItems.length;
currentIndex = sidebarItems[prevIndex].tabIndex;
var flatItems = getFlatNavigableItems();
var currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
var oldIndex = currentIndex;
if (currentPos === -1) {
currentIndex = flatItems[0]?.tabIndex ?? 0;
} else {
var prevPos = (currentPos - 1 + flatItems.length) % flatItems.length;
currentIndex = flatItems[prevPos].tabIndex;
}
autoCollapseIfNeeded(oldIndex, currentIndex);
autoExpandForTab(currentIndex);
}
function getFlatNavigableItems() {
var items = [];
for (var i = 0; i < categoryStructure.length; i++) {
var cat = categoryStructure[i];
if (cat.separator || !isCategoryVisible(cat))
continue;
if (cat.tabIndex !== undefined && !cat.children) {
items.push(cat);
}
if (cat.children) {
for (var j = 0; j < cat.children.length; j++) {
var child = cat.children[j];
if (isItemVisible(child)) {
items.push(child);
}
}
}
}
return items;
}
width: 270
@@ -120,17 +339,16 @@ Rectangle {
Column {
id: sidebarColumn
width: parent.width
leftPadding: Theme.spacingS
rightPadding: Theme.spacingS
bottomPadding: Theme.spacingL
topPadding: Theme.spacingM + 2
spacing: Theme.spacingXS
spacing: 2
ProfileSection {
width: parent.width - parent.leftPadding - parent.rightPadding
parentModal: sidebarContainer.parentModal
parentModal: root.parentModal
}
Rectangle {
@@ -142,62 +360,194 @@ Rectangle {
Item {
width: parent.width - parent.leftPadding - parent.rightPadding
height: Theme.spacingL
height: Theme.spacingM
}
Repeater {
id: sidebarRepeater
model: root.categoryStructure
model: sidebarContainer.sidebarItems
delegate: Rectangle {
delegate: Column {
id: categoryDelegate
required property int index
required property var modelData
property bool isActive: sidebarContainer.currentIndex === modelData.tabIndex
width: parent.width - parent.leftPadding - parent.rightPadding
height: 44
radius: Theme.cornerRadius
color: isActive ? Theme.primary : tabMouseArea.containsMouse ? Theme.surfaceHover : "transparent"
visible: root.isCategoryVisible(modelData)
spacing: 2
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.15
visible: categoryDelegate.modelData.separator === true
}
DankIcon {
name: modelData.icon || ""
size: Theme.iconSize - 2
color: parent.parent.isActive ? Theme.primaryText : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
Item {
width: parent.width
height: Theme.spacingS
visible: categoryDelegate.modelData.separator === true
}
Rectangle {
id: categoryRow
width: parent.width
height: 40
radius: Theme.cornerRadius
visible: categoryDelegate.modelData.separator !== true
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
if (isActive)
return Theme.primary;
if (categoryMouseArea.containsMouse)
return Theme.surfaceHover;
return "transparent";
}
StyledText {
text: modelData.text || ""
font.pixelSize: Theme.fontSizeMedium
color: parent.parent.isActive ? Theme.primaryText : Theme.surfaceText
font.weight: parent.parent.isActive ? Font.Medium : Font.Normal
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: categoryDelegate.modelData.icon || ""
size: Theme.iconSize - 2
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: categoryDelegate.modelData.text || ""
font.pixelSize: Theme.fontSizeMedium
font.weight: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
var childActive = root.isChildActive(categoryDelegate.modelData);
return (isActive || childActive) ? Font.Medium : Font.Normal;
}
color: {
var hasTab = categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children;
var isActive = hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
width: parent.width - Theme.iconSize - Theme.spacingM - (categoryDelegate.modelData.children ? expandIcon.width + Theme.spacingS : 0)
elide: Text.ElideRight
}
DankIcon {
id: expandIcon
name: root.isCategoryExpanded(categoryDelegate.modelData.id) ? "expand_less" : "expand_more"
size: Theme.iconSize - 4
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
visible: categoryDelegate.modelData.children !== undefined && categoryDelegate.modelData.children.length > 0
}
}
MouseArea {
id: categoryMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (categoryDelegate.modelData.children) {
root.toggleCategory(categoryDelegate.modelData.id);
} else if (categoryDelegate.modelData.tabIndex !== undefined) {
root.currentIndex = categoryDelegate.modelData.tabIndex;
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
MouseArea {
id: tabMouseArea
Column {
id: childrenColumn
width: parent.width
spacing: 2
visible: categoryDelegate.modelData.children !== undefined && root.isCategoryExpanded(categoryDelegate.modelData.id)
clip: true
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
sidebarContainer.currentIndex = modelData.tabIndex;
}
}
Repeater {
model: categoryDelegate.modelData.children || []
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
delegate: Rectangle {
id: childDelegate
required property int index
required property var modelData
width: childrenColumn.width
height: 36
radius: Theme.cornerRadius
visible: root.isItemVisible(modelData)
color: {
var isActive = root.currentIndex === modelData.tabIndex;
if (isActive)
return Theme.primary;
if (childMouseArea.containsMouse)
return Theme.surfaceHover;
return "transparent";
}
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingL + Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
name: childDelegate.modelData.icon || ""
size: Theme.iconSize - 4
color: {
var isActive = root.currentIndex === childDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceVariantText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: childDelegate.modelData.text || ""
font.pixelSize: Theme.fontSizeSmall + 1
font.weight: root.currentIndex === childDelegate.modelData.tabIndex ? Font.Medium : Font.Normal
color: {
var isActive = root.currentIndex === childDelegate.modelData.tabIndex;
return isActive ? Theme.primaryText : Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: childMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.currentIndex = childDelegate.modelData.tabIndex;
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}