mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-15 00:32:47 -04:00
be4ea71756
* feat(settings): Added Default Apps page to settings Added a new page to settings. This page relies on xdg-mime and gio, so their existence is checked to show the page. This logic and the mime type stuff was added to DesktopService.qml. Slightly reordered the settings sidebar to include an Applications category * fix(settings): read xdg-terminals.list directly read the file directly instead of using xdg-terminal-exec which might not be installed
1050 lines
39 KiB
QML
1050 lines
39 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import qs.Common
|
|
import qs.Modals.Settings
|
|
import qs.Services
|
|
import qs.Widgets
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
LayoutMirroring.enabled: I18n.isRtl
|
|
LayoutMirroring.childrenInherit: true
|
|
|
|
property int currentIndex: 0
|
|
property var parentModal: null
|
|
|
|
signal tabChangeRequested(int tabIndex)
|
|
property string _expandedIds: ","
|
|
property string _collapsedIds: ","
|
|
property string _autoExpandedIds: ","
|
|
property bool searchActive: searchField.text.length > 0
|
|
property int searchSelectedIndex: 0
|
|
property int keyboardHighlightIndex: -1
|
|
|
|
function focusSearch() {
|
|
searchField.forceActiveFocus();
|
|
}
|
|
|
|
function highlightNext() {
|
|
var flatItems = getFlatNavigableItems();
|
|
if (flatItems.length === 0)
|
|
return;
|
|
var currentPos = flatItems.findIndex(item => item.tabIndex === keyboardHighlightIndex);
|
|
if (currentPos === -1) {
|
|
currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
|
|
}
|
|
var nextPos = (currentPos + 1) % flatItems.length;
|
|
keyboardHighlightIndex = flatItems[nextPos].tabIndex;
|
|
autoExpandForTab(keyboardHighlightIndex);
|
|
}
|
|
|
|
function highlightPrevious() {
|
|
var flatItems = getFlatNavigableItems();
|
|
if (flatItems.length === 0)
|
|
return;
|
|
var currentPos = flatItems.findIndex(item => item.tabIndex === keyboardHighlightIndex);
|
|
if (currentPos === -1) {
|
|
currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
|
|
}
|
|
var prevPos = (currentPos - 1 + flatItems.length) % flatItems.length;
|
|
keyboardHighlightIndex = flatItems[prevPos].tabIndex;
|
|
autoExpandForTab(keyboardHighlightIndex);
|
|
}
|
|
|
|
function selectHighlighted() {
|
|
if (keyboardHighlightIndex < 0)
|
|
return;
|
|
var oldIndex = currentIndex;
|
|
var newIndex = keyboardHighlightIndex;
|
|
tabChangeRequested(newIndex);
|
|
autoCollapseIfNeeded(oldIndex, newIndex);
|
|
keyboardHighlightIndex = -1;
|
|
Qt.callLater(searchField.forceActiveFocus);
|
|
}
|
|
|
|
readonly property var categoryStructure: [
|
|
{
|
|
"id": "personalization",
|
|
"text": I18n.tr("Personalization"),
|
|
"icon": "palette",
|
|
"children": [
|
|
{
|
|
"id": "wallpaper",
|
|
"text": I18n.tr("Wallpaper"),
|
|
"icon": "wallpaper",
|
|
"tabIndex": 0
|
|
},
|
|
{
|
|
"id": "theme",
|
|
"text": I18n.tr("Theme & Colors"),
|
|
"icon": "format_paint",
|
|
"tabIndex": 10
|
|
},
|
|
{
|
|
"id": "typography",
|
|
"text": I18n.tr("Typography & Motion"),
|
|
"icon": "text_fields",
|
|
"tabIndex": 14
|
|
},
|
|
{
|
|
"id": "time_weather",
|
|
"text": I18n.tr("Time & Weather"),
|
|
"icon": "schedule",
|
|
"tabIndex": 1
|
|
},
|
|
{
|
|
"id": "sounds",
|
|
"text": I18n.tr("Sounds"),
|
|
"icon": "volume_up",
|
|
"tabIndex": 15,
|
|
"soundsOnly": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "dankbar",
|
|
"text": I18n.tr("Dank Bar"),
|
|
"icon": "toolbar",
|
|
"children": [
|
|
{
|
|
"id": "dankbar_settings",
|
|
"text": I18n.tr("Settings"),
|
|
"icon": "tune",
|
|
"tabIndex": 3
|
|
},
|
|
{
|
|
"id": "dankbar_widgets",
|
|
"text": I18n.tr("Widgets"),
|
|
"icon": "widgets",
|
|
"tabIndex": 22
|
|
},
|
|
{
|
|
"id": "frame",
|
|
"text": I18n.tr("Frame"),
|
|
"icon": "frame_source",
|
|
"tabIndex": 33
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "workspaces_widgets",
|
|
"text": I18n.tr("Workspaces & Widgets"),
|
|
"icon": "dashboard",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "workspaces",
|
|
"text": I18n.tr("Workspaces"),
|
|
"icon": "view_module",
|
|
"tabIndex": 4
|
|
},
|
|
{
|
|
"id": "media_player",
|
|
"text": I18n.tr("Media Player"),
|
|
"icon": "music_note",
|
|
"tabIndex": 16
|
|
},
|
|
{
|
|
"id": "notifications",
|
|
"text": I18n.tr("Notifications"),
|
|
"icon": "notifications",
|
|
"tabIndex": 17
|
|
},
|
|
{
|
|
"id": "osd",
|
|
"text": I18n.tr("On-screen Displays"),
|
|
"icon": "tune",
|
|
"tabIndex": 18
|
|
},
|
|
{
|
|
"id": "updater",
|
|
"text": I18n.tr("System Updater"),
|
|
"icon": "refresh",
|
|
"tabIndex": 20,
|
|
"updaterOnly": true
|
|
},
|
|
{
|
|
"id": "desktop_widgets",
|
|
"text": I18n.tr("Desktop Widgets"),
|
|
"icon": "widgets",
|
|
"tabIndex": 27
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "dock_launcher",
|
|
"text": I18n.tr("Dock & Launcher"),
|
|
"icon": "shelf_auto_hide",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "dock",
|
|
"text": I18n.tr("Dock"),
|
|
"icon": "dock_to_bottom",
|
|
"tabIndex": 5
|
|
},
|
|
{
|
|
"id": "launcher",
|
|
"text": I18n.tr("Launcher"),
|
|
"icon": "grid_view",
|
|
"tabIndex": 9
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "keybinds",
|
|
"text": I18n.tr("Keyboard Shortcuts"),
|
|
"icon": "keyboard",
|
|
"tabIndex": 2,
|
|
"shortcutsOnly": true
|
|
},
|
|
{
|
|
"id": "displays",
|
|
"text": I18n.tr("Displays"),
|
|
"icon": "monitor",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "display_config",
|
|
"text": I18n.tr("Configuration"),
|
|
"icon": "display_settings",
|
|
"tabIndex": 24
|
|
},
|
|
{
|
|
"id": "display_gamma",
|
|
"text": I18n.tr("Gamma Control"),
|
|
"icon": "brightness_6",
|
|
"tabIndex": 25
|
|
},
|
|
{
|
|
"id": "display_widgets",
|
|
"text": I18n.tr("Widgets", "settings_displays"),
|
|
"icon": "widgets",
|
|
"tabIndex": 26
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "network",
|
|
"text": I18n.tr("Network"),
|
|
"icon": "wifi",
|
|
"tabIndex": 7,
|
|
"dmsOnly": true
|
|
},
|
|
{
|
|
"id": "applications",
|
|
"text": I18n.tr("Applications"),
|
|
"icon": "apps",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "default_apps",
|
|
"text": I18n.tr("Default Apps"),
|
|
"icon": "star",
|
|
"tabIndex": 34,
|
|
"gioOnly": true
|
|
},
|
|
{
|
|
"id": "running_apps",
|
|
"text": I18n.tr("Running Apps"),
|
|
"icon": "app_registration",
|
|
"tabIndex": 19,
|
|
"hyprlandNiriOnly": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "system",
|
|
"text": I18n.tr("System"),
|
|
"icon": "memory",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "audio",
|
|
"text": I18n.tr("Audio"),
|
|
"icon": "headphones",
|
|
"tabIndex": 29
|
|
},
|
|
{
|
|
"id": "locale",
|
|
"text": I18n.tr("Locale"),
|
|
"icon": "language",
|
|
"tabIndex": 30
|
|
},
|
|
{
|
|
"id": "clipboard",
|
|
"text": I18n.tr("Clipboard"),
|
|
"icon": "content_paste",
|
|
"tabIndex": 23,
|
|
"clipboardOnly": true
|
|
},
|
|
{
|
|
"id": "printers",
|
|
"text": I18n.tr("Printers"),
|
|
"icon": "print",
|
|
"tabIndex": 8,
|
|
"cupsOnly": true
|
|
},
|
|
{
|
|
"id": "multiplexers",
|
|
"text": I18n.tr("Multiplexers"),
|
|
"icon": "terminal",
|
|
"tabIndex": 32
|
|
},
|
|
{
|
|
"id": "window_rules",
|
|
"text": I18n.tr("Window Rules"),
|
|
"icon": "select_window",
|
|
"tabIndex": 28,
|
|
"niriOnly": true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "power_security",
|
|
"text": I18n.tr("Power & Security"),
|
|
"icon": "security",
|
|
"collapsedByDefault": true,
|
|
"children": [
|
|
{
|
|
"id": "lock_screen",
|
|
"text": I18n.tr("Lock Screen"),
|
|
"icon": "lock",
|
|
"tabIndex": 11
|
|
},
|
|
{
|
|
"id": "greeter",
|
|
"text": I18n.tr("Greeter"),
|
|
"icon": "login",
|
|
"tabIndex": 31
|
|
},
|
|
{
|
|
"id": "power_sleep",
|
|
"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
|
|
}
|
|
]
|
|
|
|
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;
|
|
if (item.niriOnly && !CompositorService.isNiri)
|
|
return false;
|
|
if (item.clipboardOnly && (!DMSService.isConnected || DMSService.apiVersion < 23))
|
|
return false;
|
|
if (item.updaterOnly && !SystemUpdateService.sysupdateAvailable)
|
|
return false;
|
|
if (item.gioOnly && !DesktopService.gioAvailable)
|
|
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 _setExpanded(id, expanded) {
|
|
var marker = "," + id + ",";
|
|
if (expanded) {
|
|
if (_expandedIds.indexOf(marker) < 0)
|
|
_expandedIds = _expandedIds + id + ",";
|
|
_collapsedIds = _collapsedIds.replace(marker, ",");
|
|
} else {
|
|
_expandedIds = _expandedIds.replace(marker, ",");
|
|
if (_collapsedIds.indexOf(marker) < 0)
|
|
_collapsedIds = _collapsedIds + id + ",";
|
|
}
|
|
SessionData.setSettingsSidebarState(_expandedIds, _collapsedIds);
|
|
}
|
|
|
|
function _setAutoExpanded(id, value) {
|
|
var marker = "," + id + ",";
|
|
if (value) {
|
|
if (_autoExpandedIds.indexOf(marker) < 0)
|
|
_autoExpandedIds = _autoExpandedIds + id + ",";
|
|
} else {
|
|
_autoExpandedIds = _autoExpandedIds.replace(marker, ",");
|
|
}
|
|
}
|
|
|
|
function _isAutoExpanded(id) {
|
|
return _autoExpandedIds.indexOf("," + id + ",") >= 0;
|
|
}
|
|
|
|
function toggleCategory(categoryId) {
|
|
_setExpanded(categoryId, !isCategoryExpanded(categoryId));
|
|
_setAutoExpanded(categoryId, false);
|
|
}
|
|
|
|
function isCategoryExpanded(categoryId) {
|
|
if (_collapsedIds.indexOf("," + categoryId + ",") >= 0)
|
|
return false;
|
|
if (_expandedIds.indexOf("," + categoryId + ",") >= 0)
|
|
return true;
|
|
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)) {
|
|
_setExpanded(parent.id, true);
|
|
_setAutoExpanded(parent.id, true);
|
|
}
|
|
}
|
|
|
|
function autoCollapseIfNeeded(oldTabIndex, newTabIndex) {
|
|
var oldParent = findParentCategory(oldTabIndex);
|
|
var newParent = findParentCategory(newTabIndex);
|
|
|
|
if (oldParent && oldParent !== newParent && _isAutoExpanded(oldParent.id)) {
|
|
_setExpanded(oldParent.id, false);
|
|
_setAutoExpanded(oldParent.id, false);
|
|
}
|
|
}
|
|
|
|
function navigateNext() {
|
|
var flatItems = getFlatNavigableItems();
|
|
var currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
|
|
var oldIndex = currentIndex;
|
|
var newIndex;
|
|
if (currentPos === -1) {
|
|
newIndex = flatItems[0]?.tabIndex ?? 0;
|
|
} else {
|
|
var nextPos = (currentPos + 1) % flatItems.length;
|
|
newIndex = flatItems[nextPos].tabIndex;
|
|
}
|
|
tabChangeRequested(newIndex);
|
|
autoCollapseIfNeeded(oldIndex, newIndex);
|
|
autoExpandForTab(newIndex);
|
|
}
|
|
|
|
function navigatePrevious() {
|
|
var flatItems = getFlatNavigableItems();
|
|
var currentPos = flatItems.findIndex(item => item.tabIndex === currentIndex);
|
|
var oldIndex = currentIndex;
|
|
var newIndex;
|
|
if (currentPos === -1) {
|
|
newIndex = flatItems[0]?.tabIndex ?? 0;
|
|
} else {
|
|
var prevPos = (currentPos - 1 + flatItems.length) % flatItems.length;
|
|
newIndex = flatItems[prevPos].tabIndex;
|
|
}
|
|
tabChangeRequested(newIndex);
|
|
autoCollapseIfNeeded(oldIndex, newIndex);
|
|
autoExpandForTab(newIndex);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
function resolveTabIndex(name: string): int {
|
|
if (!name)
|
|
return -1;
|
|
|
|
var normalized = name.toLowerCase().replace(/[_\-\s]/g, "");
|
|
|
|
for (var i = 0; i < categoryStructure.length; i++) {
|
|
var cat = categoryStructure[i];
|
|
if (cat.separator)
|
|
continue;
|
|
|
|
var catId = (cat.id || "").toLowerCase().replace(/[_\-\s]/g, "");
|
|
if (catId === normalized) {
|
|
if (cat.tabIndex !== undefined)
|
|
return cat.tabIndex;
|
|
if (cat.children && cat.children.length > 0)
|
|
return cat.children[0].tabIndex;
|
|
}
|
|
|
|
if (cat.children) {
|
|
for (var j = 0; j < cat.children.length; j++) {
|
|
var child = cat.children[j];
|
|
var childId = (child.id || "").toLowerCase().replace(/[_\-\s]/g, "");
|
|
if (childId === normalized)
|
|
return child.tabIndex;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
property real __maxTextWidth: Math.max(__m1.advanceWidth, __m2.advanceWidth, __m3.advanceWidth, __m4.advanceWidth, __m5.advanceWidth, __m6.advanceWidth)
|
|
property real __calculatedWidth: Math.max(270, __maxTextWidth + Theme.iconSize * 2 + Theme.spacingM * 4 + Theme.spacingS * 2)
|
|
|
|
implicitWidth: __calculatedWidth
|
|
width: __calculatedWidth
|
|
height: parent.height
|
|
color: Theme.surfaceContainer
|
|
radius: Theme.cornerRadius
|
|
|
|
Component.onCompleted: {
|
|
root._expandedIds = SessionData.settingsSidebarExpandedIds;
|
|
root._collapsedIds = SessionData.settingsSidebarCollapsedIds;
|
|
}
|
|
|
|
StyledTextMetrics {
|
|
id: __m1
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Workspaces & Widgets")
|
|
}
|
|
StyledTextMetrics {
|
|
id: __m2
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Typography & Motion")
|
|
}
|
|
StyledTextMetrics {
|
|
id: __m3
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Keyboard Shortcuts")
|
|
}
|
|
StyledTextMetrics {
|
|
id: __m4
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Power & Security")
|
|
}
|
|
StyledTextMetrics {
|
|
id: __m5
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Dock & Launcher")
|
|
}
|
|
StyledTextMetrics {
|
|
id: __m6
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
text: I18n.tr("Personalization")
|
|
}
|
|
|
|
function selectSearchResult(result) {
|
|
if (!result)
|
|
return;
|
|
if (result.section) {
|
|
SettingsSearchService.navigateToSection(result.section);
|
|
}
|
|
var oldIndex = root.currentIndex;
|
|
tabChangeRequested(result.tabIndex);
|
|
autoCollapseIfNeeded(oldIndex, result.tabIndex);
|
|
autoExpandForTab(result.tabIndex);
|
|
searchField.text = "";
|
|
SettingsSearchService.clear();
|
|
searchSelectedIndex = 0;
|
|
keyboardHighlightIndex = -1;
|
|
Qt.callLater(searchField.forceActiveFocus);
|
|
}
|
|
|
|
function navigateSearchResults(delta) {
|
|
if (SettingsSearchService.results.length === 0)
|
|
return;
|
|
searchSelectedIndex = Math.max(0, Math.min(searchSelectedIndex + delta, SettingsSearchService.results.length - 1));
|
|
}
|
|
|
|
DankFlickable {
|
|
anchors.fill: parent
|
|
clip: true
|
|
contentHeight: sidebarColumn.height
|
|
|
|
Column {
|
|
id: sidebarColumn
|
|
width: parent.width
|
|
leftPadding: Theme.spacingS
|
|
rightPadding: Theme.spacingS
|
|
bottomPadding: Theme.spacingL
|
|
topPadding: Theme.spacingM + 2
|
|
spacing: 2
|
|
|
|
ProfileSection {
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
parentModal: root.parentModal
|
|
}
|
|
|
|
Rectangle {
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
height: 1
|
|
color: Theme.outline
|
|
opacity: 0.2
|
|
}
|
|
|
|
Item {
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
height: Theme.spacingXS
|
|
}
|
|
|
|
DankTextField {
|
|
id: searchField
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
placeholderText: I18n.tr("Search...")
|
|
normalBorderColor: Theme.outlineMedium
|
|
focusedBorderColor: Theme.primary
|
|
leftIconName: "search"
|
|
leftIconSize: Theme.iconSize - 4
|
|
showClearButton: text.length > 0
|
|
usePopupTransparency: false
|
|
onTextChanged: {
|
|
SettingsSearchService.search(text);
|
|
root.searchSelectedIndex = 0;
|
|
}
|
|
keyForwardTargets: [keyHandler]
|
|
|
|
Item {
|
|
id: keyHandler
|
|
function navNext() {
|
|
if (root.searchActive) {
|
|
root.navigateSearchResults(1);
|
|
} else {
|
|
root.highlightNext();
|
|
}
|
|
}
|
|
function navPrev() {
|
|
if (root.searchActive) {
|
|
root.navigateSearchResults(-1);
|
|
} else {
|
|
root.highlightPrevious();
|
|
}
|
|
}
|
|
function navSelect() {
|
|
if (root.searchActive && SettingsSearchService.results.length > 0) {
|
|
root.selectSearchResult(SettingsSearchService.results[root.searchSelectedIndex]);
|
|
} else if (root.keyboardHighlightIndex >= 0) {
|
|
root.selectHighlighted();
|
|
}
|
|
}
|
|
Keys.onDownPressed: event => {
|
|
navNext();
|
|
event.accepted = true;
|
|
}
|
|
Keys.onUpPressed: event => {
|
|
navPrev();
|
|
event.accepted = true;
|
|
}
|
|
Keys.onTabPressed: event => {
|
|
navNext();
|
|
event.accepted = true;
|
|
}
|
|
Keys.onBacktabPressed: event => {
|
|
navPrev();
|
|
event.accepted = true;
|
|
}
|
|
Keys.onReturnPressed: event => {
|
|
navSelect();
|
|
event.accepted = true;
|
|
}
|
|
Keys.onEscapePressed: event => {
|
|
if (root.searchActive) {
|
|
searchField.text = "";
|
|
SettingsSearchService.clear();
|
|
} else {
|
|
root.keyboardHighlightIndex = -1;
|
|
}
|
|
event.accepted = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: searchResultsColumn
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
spacing: 2
|
|
visible: root.searchActive
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: Theme.spacingS
|
|
}
|
|
|
|
Repeater {
|
|
model: ScriptModel {
|
|
values: SettingsSearchService.results
|
|
}
|
|
|
|
Rectangle {
|
|
id: resultDelegate
|
|
required property int index
|
|
required property var modelData
|
|
|
|
width: searchResultsColumn.width
|
|
height: resultContent.height + Theme.spacingM * 2
|
|
radius: Theme.cornerRadius
|
|
color: {
|
|
if (root.searchSelectedIndex === index)
|
|
return Theme.buttonBg;
|
|
if (resultMouseArea.containsMouse)
|
|
return Theme.surfaceHover;
|
|
return "transparent";
|
|
}
|
|
|
|
DankRipple {
|
|
id: resultRipple
|
|
rippleColor: root.searchSelectedIndex === resultDelegate.index ? Theme.buttonText : Theme.surfaceText
|
|
cornerRadius: resultDelegate.radius
|
|
}
|
|
|
|
Row {
|
|
id: resultContent
|
|
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: resultDelegate.modelData.icon || "settings"
|
|
size: Theme.iconSize - 2
|
|
color: root.searchSelectedIndex === resultDelegate.index ? Theme.buttonText : Theme.surfaceText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
|
|
Column {
|
|
width: parent.width - Theme.iconSize - Theme.spacingM
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 2
|
|
|
|
StyledText {
|
|
text: resultDelegate.modelData.label
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Font.Medium
|
|
color: root.searchSelectedIndex === resultDelegate.index ? Theme.buttonText : Theme.surfaceText
|
|
width: parent.width
|
|
wrapMode: Text.Wrap
|
|
horizontalAlignment: Text.AlignLeft
|
|
}
|
|
|
|
StyledText {
|
|
text: resultDelegate.modelData.category
|
|
font.pixelSize: Theme.fontSizeSmall - 1
|
|
color: root.searchSelectedIndex === resultDelegate.index ? Theme.withAlpha(Theme.buttonText, 0.7) : Theme.surfaceVariantText
|
|
width: parent.width
|
|
wrapMode: Text.Wrap
|
|
horizontalAlignment: Text.AlignLeft
|
|
}
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: resultMouseArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onPressed: mouse => resultRipple.trigger(mouse.x, mouse.y)
|
|
onClicked: root.selectSearchResult(resultDelegate.modelData)
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: I18n.tr("No matches")
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: Theme.surfaceVariantText
|
|
horizontalAlignment: Text.AlignHCenter
|
|
visible: searchField.text.length > 0 && SettingsSearchService.results.length === 0
|
|
topPadding: Theme.spacingM
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
height: Theme.spacingXS
|
|
visible: !root.searchActive
|
|
}
|
|
|
|
Repeater {
|
|
model: root.categoryStructure
|
|
|
|
delegate: Column {
|
|
id: categoryDelegate
|
|
required property int index
|
|
required property var modelData
|
|
|
|
width: parent.width - parent.leftPadding - parent.rightPadding
|
|
visible: !root.searchActive && root.isCategoryVisible(modelData)
|
|
spacing: 2
|
|
|
|
Rectangle {
|
|
width: parent.width
|
|
height: 1
|
|
color: Theme.outline
|
|
opacity: 0.15
|
|
visible: categoryDelegate.modelData.separator === true
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: Theme.spacingS
|
|
visible: categoryDelegate.modelData.separator === true
|
|
}
|
|
|
|
Rectangle {
|
|
id: categoryRow
|
|
width: parent.width
|
|
height: Math.max(Theme.iconSize, Theme.fontSizeMedium) + Theme.spacingS * 2
|
|
radius: Theme.cornerRadius
|
|
visible: categoryDelegate.modelData.separator !== true
|
|
|
|
readonly property bool hasTab: categoryDelegate.modelData.tabIndex !== undefined && !categoryDelegate.modelData.children
|
|
readonly property bool isActive: hasTab && root.currentIndex === categoryDelegate.modelData.tabIndex
|
|
readonly property bool isHighlighted: hasTab && root.keyboardHighlightIndex === categoryDelegate.modelData.tabIndex
|
|
|
|
color: {
|
|
if (isActive)
|
|
return Theme.buttonBg;
|
|
if (isHighlighted)
|
|
return Theme.buttonHover;
|
|
if (categoryMouseArea.containsMouse)
|
|
return Theme.surfaceHover;
|
|
return "transparent";
|
|
}
|
|
|
|
DankRipple {
|
|
id: categoryRipple
|
|
rippleColor: categoryRow.isActive ? Theme.buttonText : Theme.surfaceText
|
|
cornerRadius: categoryRow.radius
|
|
}
|
|
|
|
Row {
|
|
id: categoryRowContent
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: Theme.spacingM
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Theme.spacingM
|
|
|
|
DankIcon {
|
|
name: categoryDelegate.modelData.icon || ""
|
|
size: Theme.iconSize - 2
|
|
color: categoryRow.isActive ? Theme.buttonText : Theme.surfaceText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
|
|
StyledText {
|
|
text: categoryDelegate.modelData.text || ""
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: (categoryRow.isActive || root.isChildActive(categoryDelegate.modelData)) ? Font.Medium : Font.Normal
|
|
color: categoryRow.isActive ? Theme.buttonText : Theme.surfaceText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
}
|
|
|
|
DankIcon {
|
|
id: expandIcon
|
|
name: root.isCategoryExpanded(categoryDelegate.modelData.id) ? "expand_less" : "expand_more"
|
|
size: Theme.iconSize - 4
|
|
color: Theme.surfaceVariantText
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: Theme.spacingM
|
|
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
|
|
onPressed: mouse => categoryRipple.trigger(mouse.x, mouse.y)
|
|
onClicked: {
|
|
root.keyboardHighlightIndex = -1;
|
|
if (categoryDelegate.modelData.children) {
|
|
root.toggleCategory(categoryDelegate.modelData.id);
|
|
} else if (categoryDelegate.modelData.tabIndex !== undefined) {
|
|
root.tabChangeRequested(categoryDelegate.modelData.tabIndex);
|
|
}
|
|
Qt.callLater(searchField.forceActiveFocus);
|
|
}
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: childrenColumn
|
|
width: parent.width
|
|
spacing: 2
|
|
visible: categoryDelegate.modelData.children !== undefined && root.isCategoryExpanded(categoryDelegate.modelData.id)
|
|
clip: true
|
|
|
|
Repeater {
|
|
model: categoryDelegate.modelData.children || []
|
|
|
|
delegate: Rectangle {
|
|
id: childDelegate
|
|
required property int index
|
|
required property var modelData
|
|
|
|
readonly property bool isActive: root.currentIndex === modelData.tabIndex
|
|
readonly property bool isHighlighted: root.keyboardHighlightIndex === modelData.tabIndex
|
|
|
|
width: childrenColumn.width
|
|
height: Math.max(Theme.iconSize - 4, Theme.fontSizeSmall + 1) + Theme.spacingS * 2
|
|
radius: Theme.cornerRadius
|
|
visible: root.isItemVisible(modelData)
|
|
color: {
|
|
if (isActive)
|
|
return Theme.buttonBg;
|
|
if (isHighlighted)
|
|
return Theme.buttonHover;
|
|
if (childMouseArea.containsMouse)
|
|
return Theme.surfaceHover;
|
|
return "transparent";
|
|
}
|
|
|
|
DankRipple {
|
|
id: childRipple
|
|
rippleColor: childDelegate.isActive ? Theme.buttonText : Theme.surfaceText
|
|
cornerRadius: childDelegate.radius
|
|
}
|
|
|
|
Row {
|
|
id: childRowContent
|
|
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: childDelegate.isActive ? Theme.buttonText : Theme.surfaceVariantText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
|
|
StyledText {
|
|
text: childDelegate.modelData.text || ""
|
|
font.pixelSize: Theme.fontSizeSmall + 1
|
|
font.weight: childDelegate.isActive ? Font.Medium : Font.Normal
|
|
color: childDelegate.isActive ? Theme.buttonText : Theme.surfaceText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: childMouseArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onPressed: mouse => childRipple.trigger(mouse.x, mouse.y)
|
|
onClicked: {
|
|
root.keyboardHighlightIndex = -1;
|
|
root.tabChangeRequested(childDelegate.modelData.tabIndex);
|
|
Qt.callLater(searchField.forceActiveFocus);
|
|
}
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|