mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-14 15:24:00 -04:00
settings: fix greeter FAB button desktop: change styling of edit menu fixes #3767
259 lines
8.7 KiB
QML
259 lines
8.7 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import Qt.labs.folderlistmodel
|
|
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.DCommon.Widgets
|
|
import qs.Widgets
|
|
import "../DCommon/Common/MaterialWallpaper.js" as Art
|
|
|
|
DContextMenu {
|
|
id: root
|
|
|
|
property bool settingsExpanded: false
|
|
property var stripItems: []
|
|
|
|
readonly property int stripCount: 4
|
|
readonly property real stripUnit: Theme.listItemHeight
|
|
readonly property string currentWallpaper: {
|
|
if (SessionData.perMonitorWallpaper && targetScreen)
|
|
return SessionData.getMonitorWallpaper(targetScreen.name) || "";
|
|
return SessionData.wallpaperPath || "";
|
|
}
|
|
readonly property string wallpaperDir: currentWallpaper.startsWith("/") ? currentWallpaper.substring(0, currentWallpaper.lastIndexOf("/")) : ""
|
|
readonly property bool materialWallpaper: currentWallpaper === ""
|
|
readonly property var materialTarget: SessionData.materialWallpaperTarget(targetScreen?.name ?? "")
|
|
readonly property var materialEntry: SessionData.materialWallpaperEntry(materialTarget)
|
|
readonly property string currentKey: materialWallpaper ? Art.resolvePreset(materialEntry.preset, SessionData.materialWallpaperProfiles) : currentWallpaper
|
|
|
|
layerNamespace: "dms:desktop-context-menu"
|
|
keyboardNavigable: true
|
|
itemHeight: Theme.listItemHeight
|
|
itemFontSize: Theme.fontSizeMedium
|
|
minMenuWidth: stripUnit * (stripCount + 1) + Theme.spacingS * (stripCount + 1)
|
|
|
|
menuItems: {
|
|
const items = [
|
|
{
|
|
type: "item",
|
|
icon: "edit",
|
|
text: I18n.tr("Edit widgets"),
|
|
action: () => DesktopWidgetRegistry.startEditing(root.targetScreen, false)
|
|
},
|
|
{
|
|
type: "item",
|
|
icon: "extension",
|
|
text: I18n.tr("Plugins"),
|
|
action: () => PopoutService.openSettingsWithTab("plugins")
|
|
},
|
|
{
|
|
type: "item",
|
|
icon: "palette",
|
|
text: I18n.tr("Wallpaper & colors"),
|
|
action: () => PopoutService.openSettingsWithTab("personalization")
|
|
}
|
|
];
|
|
if (wallpaperDir || materialWallpaper)
|
|
items.push({
|
|
type: "component",
|
|
component: wallpaperStrip,
|
|
height: stripUnit * 2 + Theme.spacingS
|
|
});
|
|
return items.concat([settingsEntry, allSettingsEntry, desktopWidgetsEntry, displaysEntry]);
|
|
}
|
|
|
|
component MenuEntry: QtObject {
|
|
property string type: "item"
|
|
property string icon
|
|
property string text
|
|
property string trailingIcon
|
|
property bool keepOpen
|
|
property bool hidden
|
|
property var action
|
|
}
|
|
|
|
MenuEntry {
|
|
id: settingsEntry
|
|
icon: "settings"
|
|
text: I18n.tr("Settings")
|
|
trailingIcon: root.settingsExpanded ? "expand_less" : "expand_more"
|
|
keepOpen: true
|
|
action: () => root.settingsExpanded = !root.settingsExpanded
|
|
}
|
|
|
|
MenuEntry {
|
|
id: allSettingsEntry
|
|
icon: "tune"
|
|
text: I18n.tr("All settings")
|
|
hidden: !root.settingsExpanded
|
|
action: () => PopoutService.openSettings()
|
|
}
|
|
|
|
MenuEntry {
|
|
id: desktopWidgetsEntry
|
|
icon: "widgets"
|
|
text: I18n.tr("Desktop widgets")
|
|
hidden: !root.settingsExpanded
|
|
action: () => PopoutService.openSettingsWithTab("desktop_widgets")
|
|
}
|
|
|
|
MenuEntry {
|
|
id: displaysEntry
|
|
icon: "monitor"
|
|
text: I18n.tr("Displays")
|
|
hidden: !root.settingsExpanded
|
|
action: () => PopoutService.openSettingsWithTab("displays")
|
|
}
|
|
|
|
onBackdropRightClicked: (x, y) => open(targetScreen, x, y, false)
|
|
onRenderActiveChanged: {
|
|
settingsExpanded = false;
|
|
stripItems = renderActive && materialWallpaper ? leadWithCurrent(presetItems()) : [];
|
|
}
|
|
onWallpaperDirChanged: stripItems = []
|
|
|
|
function pick(item) {
|
|
if (item.path) {
|
|
setWallpaper(item.path);
|
|
return;
|
|
}
|
|
SessionData.setMaterialWallpaperPreset(materialTarget, item.key);
|
|
}
|
|
|
|
function setWallpaper(path) {
|
|
if (SessionData.perMonitorWallpaper && targetScreen) {
|
|
SessionData.setMonitorWallpaper(targetScreen.name, path);
|
|
SessionData.setMonitorCyclingFolderPath(targetScreen.name, "");
|
|
return;
|
|
}
|
|
SessionData.setWallpaper(path);
|
|
SessionData.wallpaperCyclingFolderPath = "";
|
|
SessionData.saveSettings();
|
|
}
|
|
|
|
// Order is fixed per open so a pick moves the check, not the list.
|
|
function leadWithCurrent(items) {
|
|
const start = Math.max(0, items.findIndex(item => item.key === currentKey));
|
|
return items.slice(start).concat(items.slice(0, start));
|
|
}
|
|
|
|
function presetItems() {
|
|
const profiles = SessionData.materialWallpaperProfiles;
|
|
return Art.profiles(profiles).map(profile => ({
|
|
key: profile.id,
|
|
path: "",
|
|
composition: Art.composition({
|
|
preset: profile.id,
|
|
seed: materialEntry.seed
|
|
}, profiles)
|
|
}));
|
|
}
|
|
|
|
function loadStrip(model) {
|
|
const items = [];
|
|
for (let i = 0; i < model.count; i++) {
|
|
const path = model.get(i, "filePath");
|
|
items.push({
|
|
key: path,
|
|
path
|
|
});
|
|
}
|
|
stripItems = leadWithCurrent(items);
|
|
}
|
|
|
|
Loader {
|
|
active: root.renderActive && root.wallpaperDir !== ""
|
|
|
|
sourceComponent: Item {
|
|
FolderListModel {
|
|
id: folderModel
|
|
showDirs: false
|
|
showDotAndDotDot: false
|
|
caseSensitive: false
|
|
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp", "*.jxl", "*.avif", "*.heif", "*.exr", "*.svg"]
|
|
folder: "file://" + root.wallpaperDir.split("/").map(s => encodeURIComponent(s)).join("/")
|
|
onStatusChanged: {
|
|
if (folderModel.status === FolderListModel.Ready)
|
|
root.loadStrip(folderModel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: wallpaperStrip
|
|
|
|
Item {
|
|
DCarousel {
|
|
y: Theme.spacingXS
|
|
width: parent.width
|
|
height: root.stripUnit * 2
|
|
preferredItemWidth: width / 2
|
|
itemRadius: Theme.cornerRadiusM
|
|
model: root.stripItems
|
|
|
|
delegate: DCarouselItem {
|
|
id: thumb
|
|
|
|
required property var modelData
|
|
readonly property bool current: thumb.modelData.key === root.currentKey
|
|
|
|
onClicked: {
|
|
if (!thumb.current)
|
|
root.pick(thumb.modelData);
|
|
}
|
|
|
|
Loader {
|
|
anchors.fill: parent
|
|
sourceComponent: thumb.modelData.path ? imageThumb : materialThumb
|
|
|
|
Component {
|
|
id: imageThumb
|
|
|
|
CachingImage {
|
|
imagePath: thumb.modelData.path
|
|
maxCacheSize: 256
|
|
animate: false
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: materialThumb
|
|
|
|
MaterialWallpaper {
|
|
composition: thumb.modelData.composition
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.centerIn: parent
|
|
width: Theme.iconSizeLarge
|
|
height: width
|
|
radius: width / 2
|
|
color: Theme.primaryContainer
|
|
scale: thumb.current ? 1 : 0
|
|
visible: scale > 0
|
|
|
|
Behavior on scale {
|
|
NumberAnimation {
|
|
duration: SettingsData.reduceMotion ? 0 : Theme.expressiveDurations.expressiveFastSpatial
|
|
easing.type: Easing.BezierSpline
|
|
easing.bezierCurve: Theme.expressiveCurves.expressiveFastSpatial
|
|
}
|
|
}
|
|
|
|
DIcon {
|
|
anchors.centerIn: parent
|
|
name: "check"
|
|
size: Theme.iconSizeMedium
|
|
color: Theme.onPrimaryContainer
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|