Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad23da4eda | |||
| 06ebc4ffbf | |||
| f2f9fa1302 |
+8
-1
@@ -31,6 +31,13 @@ if("shell" IN_LIST ENABLE_MODULES)
|
||||
foreach(dir assets scripts Components Config Modules Daemons Drawers Effects Helpers Paths)
|
||||
install(DIRECTORY ${dir} DESTINATION "${INSTALL_QSCONFDIR}")
|
||||
endforeach()
|
||||
install(FILES shell.qml DESTINATION "${INSTALL_QSCONFDIR}")
|
||||
|
||||
# Disable watching for changes
|
||||
file(READ shell.qml SHELL_QML)
|
||||
string(REPLACE "settings.watchFiles: true" "settings.watchFiles: false" SHELL_QML "${SHELL_QML}")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/qml/shell.qml" "${SHELL_QML}")
|
||||
install(FILES "${CMAKE_BINARY_DIR}/qml/shell.qml" DESTINATION "${INSTALL_QSCONFDIR}")
|
||||
|
||||
# Greeter
|
||||
install(DIRECTORY Greeter/ DESTINATION "${INSTALL_GREETERCONFDIR}")
|
||||
endif()
|
||||
|
||||
@@ -15,6 +15,7 @@ Text {
|
||||
color: DynamicColors.palette.m3onSurface
|
||||
font.family: Appearance.font.family.sans
|
||||
font.pointSize: Appearance.font.size.normal
|
||||
linkColor: DynamicColors.palette.m3onPrimaryFixedVariant
|
||||
renderType: Text.NativeRendering
|
||||
textFormat: Text.PlainText
|
||||
|
||||
|
||||
+12
-1
@@ -22,6 +22,7 @@ Singleton {
|
||||
property alias notifs: adapter.notifs
|
||||
property alias osd: adapter.osd
|
||||
property alias overview: adapter.overview
|
||||
property alias plugins: adapter.plugins
|
||||
property bool recentlySaved: false
|
||||
property alias screenshot: adapter.screenshot
|
||||
property alias services: adapter.services
|
||||
@@ -140,7 +141,8 @@ Singleton {
|
||||
launcher: serializeLauncher(),
|
||||
colors: serializeColors(),
|
||||
dock: serializeDock(),
|
||||
screenshot: serializeScreenshot()
|
||||
screenshot: serializeScreenshot(),
|
||||
plugins: serializePlugins()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -289,6 +291,13 @@ Singleton {
|
||||
};
|
||||
}
|
||||
|
||||
function serializePlugins(): var {
|
||||
return {
|
||||
enabled: plugins.enabled,
|
||||
entries: plugins.entries
|
||||
};
|
||||
}
|
||||
|
||||
function serializeScreenshot(): var {
|
||||
return {
|
||||
enable_pp: screenshot.enable_pp,
|
||||
@@ -458,6 +467,8 @@ Singleton {
|
||||
}
|
||||
property Overview overview: Overview {
|
||||
}
|
||||
property PluginConfig plugins: PluginConfig {
|
||||
}
|
||||
property Screenshot screenshot: Screenshot {
|
||||
}
|
||||
property Services services: Services {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import Quickshell.Io
|
||||
|
||||
JsonObject {
|
||||
property bool enabled: false
|
||||
property list<var> entries: [
|
||||
{
|
||||
id: "Plugin",
|
||||
enabled: false
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import ZShell.Models
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property alias plugins: plugins.entries
|
||||
|
||||
FileSystemModel {
|
||||
id: plugins
|
||||
|
||||
nameFilters: ["*.qml"]
|
||||
path: Quickshell.env("HOME") + "/.config/zshell"
|
||||
recursive: false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import ZShell.Models
|
||||
import qs.Config
|
||||
|
||||
Repeater {
|
||||
model: FetchPlugins.plugins
|
||||
|
||||
LazyLoader {
|
||||
required property FileSystemEntry modelData
|
||||
|
||||
activeAsync: Config.plugins.entries.some(p => {
|
||||
return p.id === modelData.baseName && p.enabled;
|
||||
})
|
||||
source: modelData.path
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import Quickshell
|
||||
import "../scripts/fzf.js" as Fzf
|
||||
import "../scripts/fuzzysort.js" as Fuzzy
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
|
||||
Singleton {
|
||||
property var extraOpts: ({})
|
||||
|
||||
@@ -136,7 +136,10 @@ CustomRect {
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
onLinkActivated: link => {
|
||||
if (Config.launcher.uwsm)
|
||||
Quickshell.execDetached(["app2unit", "-O", "--", link]);
|
||||
else
|
||||
Quickshell.execDetached(["xdg-open", link]);
|
||||
root.visibilities.sidebar = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,13 +100,15 @@ Item {
|
||||
icon: `brightness_${(Math.round(value * 6) + 1)}`
|
||||
value: root.brightness
|
||||
|
||||
onMoved: {
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
if (Config.osd.allMonBrightness) {
|
||||
root.monitor?.setBrightness(value);
|
||||
} else {
|
||||
for (const mon of Brightness.monitors) {
|
||||
mon.setBrightness(value);
|
||||
}
|
||||
} else {
|
||||
root.monitor?.setBrightness(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,12 @@ Item {
|
||||
key: "updates"
|
||||
name: "Updates"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
icon: "extension"
|
||||
key: "plugins"
|
||||
name: "Extensions"
|
||||
}
|
||||
}
|
||||
|
||||
CustomClippingRect {
|
||||
|
||||
@@ -19,8 +19,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Media update interval"
|
||||
min: 0
|
||||
name: "Media update interval"
|
||||
object: Config.dashboard
|
||||
setting: "mediaUpdateInterval"
|
||||
step: 50
|
||||
@@ -30,8 +30,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Resource update interval"
|
||||
min: 0
|
||||
name: "Resource update interval"
|
||||
object: Config.dashboard
|
||||
setting: "resourceUpdateInterval"
|
||||
step: 50
|
||||
@@ -41,8 +41,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Drag threshold"
|
||||
min: 0
|
||||
name: "Drag threshold"
|
||||
object: Config.dashboard
|
||||
setting: "dragThreshold"
|
||||
}
|
||||
@@ -107,112 +107,112 @@ SettingsPage {
|
||||
}
|
||||
}
|
||||
|
||||
SettingsSection {
|
||||
sectionId: "Layout Sizes"
|
||||
|
||||
SettingsHeader {
|
||||
name: "Layout Sizes"
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Tab indicator height"
|
||||
value: String(Config.dashboard.sizes.tabIndicatorHeight)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Tab indicator spacing"
|
||||
value: String(Config.dashboard.sizes.tabIndicatorSpacing)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Info width"
|
||||
value: String(Config.dashboard.sizes.infoWidth)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Info icon size"
|
||||
value: String(Config.dashboard.sizes.infoIconSize)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Date time width"
|
||||
value: String(Config.dashboard.sizes.dateTimeWidth)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Media width"
|
||||
value: String(Config.dashboard.sizes.mediaWidth)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Media progress sweep"
|
||||
value: String(Config.dashboard.sizes.mediaProgressSweep)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Media progress thickness"
|
||||
value: String(Config.dashboard.sizes.mediaProgressThickness)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Resource progress thickness"
|
||||
value: String(Config.dashboard.sizes.resourceProgessThickness)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Weather width"
|
||||
value: String(Config.dashboard.sizes.weatherWidth)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Media cover art size"
|
||||
value: String(Config.dashboard.sizes.mediaCoverArtSize)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Media visualiser size"
|
||||
value: String(Config.dashboard.sizes.mediaVisualiserSize)
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingReadOnly {
|
||||
name: "Resource size"
|
||||
value: String(Config.dashboard.sizes.resourceSize)
|
||||
}
|
||||
}
|
||||
// SettingsSection {
|
||||
// sectionId: "Layout Sizes"
|
||||
//
|
||||
// SettingsHeader {
|
||||
// name: "Layout Sizes"
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Tab indicator height"
|
||||
// value: String(Config.dashboard.sizes.tabIndicatorHeight)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Tab indicator spacing"
|
||||
// value: String(Config.dashboard.sizes.tabIndicatorSpacing)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Info width"
|
||||
// value: String(Config.dashboard.sizes.infoWidth)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Info icon size"
|
||||
// value: String(Config.dashboard.sizes.infoIconSize)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Date time width"
|
||||
// value: String(Config.dashboard.sizes.dateTimeWidth)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Media width"
|
||||
// value: String(Config.dashboard.sizes.mediaWidth)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Media progress sweep"
|
||||
// value: String(Config.dashboard.sizes.mediaProgressSweep)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Media progress thickness"
|
||||
// value: String(Config.dashboard.sizes.mediaProgressThickness)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Resource progress thickness"
|
||||
// value: String(Config.dashboard.sizes.resourceProgessThickness)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Weather width"
|
||||
// value: String(Config.dashboard.sizes.weatherWidth)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Media cover art size"
|
||||
// value: String(Config.dashboard.sizes.mediaCoverArtSize)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Media visualiser size"
|
||||
// value: String(Config.dashboard.sizes.mediaVisualiserSize)
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingReadOnly {
|
||||
// name: "Resource size"
|
||||
// value: String(Config.dashboard.sizes.resourceSize)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ ColumnLayout {
|
||||
|
||||
SettingList {
|
||||
Layout.fillWidth: true
|
||||
anchors.left: undefined
|
||||
anchors.right: undefined
|
||||
|
||||
onAddActiveActionRequested: {
|
||||
root.updateTimeoutEntry(index, "activeAction", "");
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import qs.Modules.Settings.Controls
|
||||
import qs.Config
|
||||
|
||||
SettingsPage {
|
||||
SettingsSection {
|
||||
sectionId: "Plugins"
|
||||
|
||||
SettingsHeader {
|
||||
name: "Plugins"
|
||||
}
|
||||
|
||||
SettingBarEntryList {
|
||||
name: "Enable or disable plugins"
|
||||
object: Config.plugins
|
||||
setting: "entries"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Max toasts"
|
||||
min: 1
|
||||
name: "Max toasts"
|
||||
object: Config.utilities
|
||||
setting: "maxToasts"
|
||||
}
|
||||
@@ -29,8 +29,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Panel width"
|
||||
min: 1
|
||||
name: "Panel width"
|
||||
object: Config.utilities.sizes
|
||||
setting: "width"
|
||||
}
|
||||
@@ -39,8 +39,8 @@ SettingsPage {
|
||||
}
|
||||
|
||||
SettingSpinBox {
|
||||
name: "Toast width"
|
||||
min: 1
|
||||
name: "Toast width"
|
||||
object: Config.utilities.sizes
|
||||
setting: "toastWidth"
|
||||
}
|
||||
@@ -77,100 +77,100 @@ SettingsPage {
|
||||
setting: "gameModeChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Do not disturb changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "dndChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Audio output changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "audioOutputChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Audio input changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "audioInputChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Caps lock changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "capsLockChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Num lock changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "numLockChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Keyboard layout changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "kbLayoutChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "VPN changed"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "vpnChanged"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Now playing"
|
||||
// object: Config.utilities.toasts
|
||||
// setting: "nowPlaying"
|
||||
// }
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Do not disturb changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "dndChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Audio output changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "audioOutputChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Audio input changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "audioInputChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Caps lock changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "capsLockChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Num lock changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "numLockChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Keyboard layout changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "kbLayoutChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "VPN changed"
|
||||
object: Config.utilities.toasts
|
||||
setting: "vpnChanged"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Now playing"
|
||||
object: Config.utilities.toasts
|
||||
setting: "nowPlaying"
|
||||
}
|
||||
}
|
||||
|
||||
SettingsSection {
|
||||
sectionId: "VPN"
|
||||
|
||||
SettingsHeader {
|
||||
name: "VPN"
|
||||
}
|
||||
|
||||
SettingSwitch {
|
||||
name: "Enable VPN integration"
|
||||
object: Config.utilities.vpn
|
||||
setting: "enabled"
|
||||
}
|
||||
|
||||
Separator {
|
||||
}
|
||||
|
||||
SettingStringList {
|
||||
name: "Provider"
|
||||
addLabel: qsTr("Add VPN provider")
|
||||
object: Config.utilities.vpn
|
||||
setting: "provider"
|
||||
}
|
||||
}
|
||||
// SettingsSection {
|
||||
// sectionId: "VPN"
|
||||
//
|
||||
// SettingsHeader {
|
||||
// name: "VPN"
|
||||
// }
|
||||
//
|
||||
// SettingSwitch {
|
||||
// name: "Enable VPN integration"
|
||||
// object: Config.utilities.vpn
|
||||
// setting: "enabled"
|
||||
// }
|
||||
//
|
||||
// Separator {
|
||||
// }
|
||||
//
|
||||
// SettingStringList {
|
||||
// name: "Provider"
|
||||
// addLabel: qsTr("Add VPN provider")
|
||||
// object: Config.utilities.vpn
|
||||
// setting: "provider"
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ Item {
|
||||
stack.push(screenshot);
|
||||
else if (currentCategory === "updates")
|
||||
stack.push(updates);
|
||||
else if (currentCategory === "plugins")
|
||||
stack.push(plugins);
|
||||
}
|
||||
|
||||
target: root
|
||||
@@ -245,4 +247,11 @@ Item {
|
||||
Cat.SystemUpdates {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: plugins
|
||||
|
||||
Cat.Plugins {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,9 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
Separator {
|
||||
Layout.fillWidth: true
|
||||
anchors.left: undefined
|
||||
anchors.right: undefined
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -207,6 +210,8 @@ ColumnLayout {
|
||||
StringListEditor {
|
||||
Layout.fillWidth: true
|
||||
addLabel: qsTr("Add command argument")
|
||||
anchors.left: undefined
|
||||
anchors.right: undefined
|
||||
values: [...(modelData.command ?? [])]
|
||||
|
||||
onListEdited: function (values) {
|
||||
@@ -215,6 +220,9 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
Separator {
|
||||
Layout.fillWidth: true
|
||||
anchors.left: undefined
|
||||
anchors.right: undefined
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -233,6 +241,9 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
Separator {
|
||||
Layout.fillWidth: true
|
||||
anchors.left: undefined
|
||||
anchors.right: undefined
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
@@ -6,7 +6,7 @@ import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
ColumnLayout {
|
||||
CustomRect {
|
||||
id: root
|
||||
|
||||
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
|
||||
@@ -43,10 +43,9 @@ ColumnLayout {
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: shouldBeActive ? implicitHeight : 0
|
||||
height: shouldBeActive ? layout.implicitHeight : 0
|
||||
opacity: shouldBeActive ? 1 : 0
|
||||
scale: shouldBeActive ? 1 : 0.8
|
||||
spacing: Appearance.spacing.smaller
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -77,6 +76,14 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Appearance.spacing.smaller
|
||||
|
||||
CustomText {
|
||||
Layout.fillWidth: true
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
@@ -121,15 +128,17 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
CustomRect {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 33
|
||||
Layout.preferredWidth: Math.max(Math.min(fromTextField.contentWidth + Appearance.padding.large * 2, 550), 50)
|
||||
color: DynamicColors.tPalette.m3surfaceContainerHigh
|
||||
radius: Appearance.rounding.full
|
||||
|
||||
CustomTextField {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Appearance.padding.normal
|
||||
anchors.rightMargin: Appearance.padding.normal
|
||||
id: fromTextField
|
||||
|
||||
anchors.centerIn: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 550)
|
||||
text: modelData.from ?? ""
|
||||
|
||||
onEditingFinished: root.updateAlias(index, "from", text)
|
||||
@@ -154,15 +163,17 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
CustomRect {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 33
|
||||
color: DynamicColors.tPalette.m3surface
|
||||
radius: Appearance.rounding.small
|
||||
Layout.preferredWidth: Math.max(Math.min(toTextField.contentWidth + Appearance.padding.large * 2, 550), 50)
|
||||
color: DynamicColors.tPalette.m3surfaceContainerHigh
|
||||
radius: Appearance.rounding.full
|
||||
|
||||
CustomTextField {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Appearance.padding.normal
|
||||
anchors.rightMargin: Appearance.padding.normal
|
||||
id: toTextField
|
||||
|
||||
anchors.centerIn: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 550)
|
||||
text: modelData.to ?? ""
|
||||
|
||||
onEditingFinished: root.updateAlias(index, "to", text)
|
||||
@@ -188,4 +199,5 @@ ColumnLayout {
|
||||
text: qsTr("Add alias")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ FileSystemEntry::FileSystemEntry(const QString& path, const QString& relativePat
|
||||
, m_path(path)
|
||||
, m_relativePath(relativePath)
|
||||
, m_isImageInitialised(false)
|
||||
, m_mimeTypeInitialised(false) {}
|
||||
, m_mimeTypeInitialised(false) {
|
||||
}
|
||||
|
||||
QString FileSystemEntry::path() const {
|
||||
return m_path;
|
||||
@@ -57,8 +58,8 @@ bool FileSystemEntry::isImage() const {
|
||||
|
||||
QString FileSystemEntry::mimeType() const {
|
||||
if (!m_mimeTypeInitialised) {
|
||||
const QMimeDatabase db;
|
||||
m_mimeType = db.mimeTypeForFile(m_path).name();
|
||||
static const QMimeDatabase s_db;
|
||||
m_mimeType = s_db.mimeTypeForFile(m_path).name();
|
||||
m_mimeTypeInitialised = true;
|
||||
}
|
||||
return m_mimeType;
|
||||
@@ -219,7 +220,7 @@ void FileSystemModel::watchDirIfRecursive(const QString& path) {
|
||||
if (m_recursive && m_watchChanges) {
|
||||
const auto currentDir = m_dir;
|
||||
const bool showHidden = m_showHidden;
|
||||
const auto future = QtConcurrent::run([showHidden, path]() {
|
||||
auto future = QtConcurrent::run([showHidden, path]() {
|
||||
QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot;
|
||||
if (showHidden) {
|
||||
filters |= QDir::Hidden;
|
||||
@@ -232,16 +233,12 @@ void FileSystemModel::watchDirIfRecursive(const QString& path) {
|
||||
}
|
||||
return dirs;
|
||||
});
|
||||
const auto watcher = new QFutureWatcher<QStringList>(this);
|
||||
connect(watcher, &QFutureWatcher<QStringList>::finished, this, [currentDir, showHidden, watcher, this]() {
|
||||
const auto paths = watcher->result();
|
||||
future.then(this, [currentDir, showHidden, this](const QStringList& paths) {
|
||||
if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) {
|
||||
// Ignore if dir or showHidden has changed
|
||||
m_watcher.addPaths(paths);
|
||||
}
|
||||
watcher->deleteLater();
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +292,7 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
|
||||
oldPaths << entry->path();
|
||||
}
|
||||
|
||||
const auto future = QtConcurrent::run([=](QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) {
|
||||
auto future = QtConcurrent::run([=](QPromise<QPair<QSet<QString>, QSet<QString> > >& promise) {
|
||||
const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags;
|
||||
|
||||
std::optional<QDirIterator> iter;
|
||||
@@ -353,7 +350,7 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
|
||||
newPaths.insert(path);
|
||||
}
|
||||
|
||||
if (promise.isCanceled() || newPaths == oldPaths) {
|
||||
if (promise.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -365,23 +362,17 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
|
||||
}
|
||||
m_futures.insert(dir, future);
|
||||
|
||||
const auto watcher = new QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>(this);
|
||||
|
||||
connect(watcher, &QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>::finished, this, [dir, watcher, this]() {
|
||||
future
|
||||
.then(this,
|
||||
[dir, this](QPair<QSet<QString>, QSet<QString> > result) {
|
||||
m_futures.remove(dir);
|
||||
|
||||
if (!watcher->future().isResultReadyAt(0)) {
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result = watcher->result();
|
||||
if (!result.first.isEmpty() || !result.second.isEmpty()) {
|
||||
applyChanges(result.first, result.second);
|
||||
|
||||
watcher->deleteLater();
|
||||
}
|
||||
})
|
||||
.onCanceled(this, [dir, this]() {
|
||||
m_futures.remove(dir);
|
||||
});
|
||||
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths) {
|
||||
|
||||
@@ -13,136 +13,136 @@
|
||||
namespace ZShell::models {
|
||||
|
||||
class FileSystemEntry : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("FileSystemEntry instances can only be retrieved from a FileSystemModel")
|
||||
|
||||
Q_PROPERTY(QString path READ path CONSTANT)
|
||||
Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString baseName READ baseName CONSTANT)
|
||||
Q_PROPERTY(QString parentDir READ parentDir CONSTANT)
|
||||
Q_PROPERTY(QString suffix READ suffix CONSTANT)
|
||||
Q_PROPERTY(qint64 size READ size CONSTANT)
|
||||
Q_PROPERTY(bool isDir READ isDir CONSTANT)
|
||||
Q_PROPERTY(bool isImage READ isImage CONSTANT)
|
||||
Q_PROPERTY(QString mimeType READ mimeType CONSTANT)
|
||||
Q_PROPERTY(QString path READ path CONSTANT)
|
||||
Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString baseName READ baseName CONSTANT)
|
||||
Q_PROPERTY(QString parentDir READ parentDir CONSTANT)
|
||||
Q_PROPERTY(QString suffix READ suffix CONSTANT)
|
||||
Q_PROPERTY(qint64 size READ size CONSTANT)
|
||||
Q_PROPERTY(bool isDir READ isDir CONSTANT)
|
||||
Q_PROPERTY(bool isImage READ isImage CONSTANT)
|
||||
Q_PROPERTY(QString mimeType READ mimeType CONSTANT)
|
||||
|
||||
public:
|
||||
explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr);
|
||||
explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QString path() const;
|
||||
[[nodiscard]] QString relativePath() const;
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] QString baseName() const;
|
||||
[[nodiscard]] QString parentDir() const;
|
||||
[[nodiscard]] QString suffix() const;
|
||||
[[nodiscard]] qint64 size() const;
|
||||
[[nodiscard]] bool isDir() const;
|
||||
[[nodiscard]] bool isImage() const;
|
||||
[[nodiscard]] QString mimeType() const;
|
||||
[[nodiscard]] QString path() const;
|
||||
[[nodiscard]] QString relativePath() const;
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] QString baseName() const;
|
||||
[[nodiscard]] QString parentDir() const;
|
||||
[[nodiscard]] QString suffix() const;
|
||||
[[nodiscard]] qint64 size() const;
|
||||
[[nodiscard]] bool isDir() const;
|
||||
[[nodiscard]] bool isImage() const;
|
||||
[[nodiscard]] QString mimeType() const;
|
||||
|
||||
void updateRelativePath(const QDir& dir);
|
||||
void updateRelativePath(const QDir& dir);
|
||||
|
||||
signals:
|
||||
void relativePathChanged();
|
||||
void relativePathChanged();
|
||||
|
||||
private:
|
||||
const QFileInfo m_fileInfo;
|
||||
const QFileInfo m_fileInfo;
|
||||
|
||||
const QString m_path;
|
||||
QString m_relativePath;
|
||||
const QString m_path;
|
||||
QString m_relativePath;
|
||||
|
||||
mutable bool m_isImage;
|
||||
mutable bool m_isImageInitialised;
|
||||
mutable bool m_isImage;
|
||||
mutable bool m_isImageInitialised;
|
||||
|
||||
mutable QString m_mimeType;
|
||||
mutable bool m_mimeTypeInitialised;
|
||||
mutable QString m_mimeType;
|
||||
mutable bool m_mimeTypeInitialised;
|
||||
};
|
||||
|
||||
class FileSystemModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
|
||||
Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged)
|
||||
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged)
|
||||
Q_PROPERTY(bool sortReverse READ sortReverse WRITE setSortReverse NOTIFY sortReverseChanged)
|
||||
Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged)
|
||||
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
|
||||
Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged)
|
||||
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged)
|
||||
Q_PROPERTY(bool sortReverse READ sortReverse WRITE setSortReverse NOTIFY sortReverseChanged)
|
||||
Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged)
|
||||
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
|
||||
|
||||
Q_PROPERTY(QQmlListProperty<ZShell::models::FileSystemEntry> entries READ entries NOTIFY entriesChanged)
|
||||
Q_PROPERTY(QQmlListProperty<ZShell::models::FileSystemEntry> entries READ entries NOTIFY entriesChanged)
|
||||
|
||||
public:
|
||||
enum Filter {
|
||||
enum Filter {
|
||||
NoFilter,
|
||||
Images,
|
||||
Files,
|
||||
Dirs
|
||||
};
|
||||
Q_ENUM(Filter)
|
||||
};
|
||||
Q_ENUM(Filter)
|
||||
|
||||
explicit FileSystemModel(QObject* parent = nullptr);
|
||||
explicit FileSystemModel(QObject* parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
[[nodiscard]] QString path() const;
|
||||
void setPath(const QString& path);
|
||||
[[nodiscard]] QString path() const;
|
||||
void setPath(const QString& path);
|
||||
|
||||
[[nodiscard]] bool recursive() const;
|
||||
void setRecursive(bool recursive);
|
||||
[[nodiscard]] bool recursive() const;
|
||||
void setRecursive(bool recursive);
|
||||
|
||||
[[nodiscard]] bool watchChanges() const;
|
||||
void setWatchChanges(bool watchChanges);
|
||||
[[nodiscard]] bool watchChanges() const;
|
||||
void setWatchChanges(bool watchChanges);
|
||||
|
||||
[[nodiscard]] bool showHidden() const;
|
||||
void setShowHidden(bool showHidden);
|
||||
[[nodiscard]] bool showHidden() const;
|
||||
void setShowHidden(bool showHidden);
|
||||
|
||||
[[nodiscard]] bool sortReverse() const;
|
||||
void setSortReverse(bool sortReverse);
|
||||
[[nodiscard]] bool sortReverse() const;
|
||||
void setSortReverse(bool sortReverse);
|
||||
|
||||
[[nodiscard]] Filter filter() const;
|
||||
void setFilter(Filter filter);
|
||||
[[nodiscard]] Filter filter() const;
|
||||
void setFilter(Filter filter);
|
||||
|
||||
[[nodiscard]] QStringList nameFilters() const;
|
||||
void setNameFilters(const QStringList& nameFilters);
|
||||
[[nodiscard]] QStringList nameFilters() const;
|
||||
void setNameFilters(const QStringList& nameFilters);
|
||||
|
||||
[[nodiscard]] QQmlListProperty<FileSystemEntry> entries();
|
||||
[[nodiscard]] QQmlListProperty<FileSystemEntry> entries();
|
||||
|
||||
signals:
|
||||
void pathChanged();
|
||||
void recursiveChanged();
|
||||
void watchChangesChanged();
|
||||
void showHiddenChanged();
|
||||
void sortReverseChanged();
|
||||
void filterChanged();
|
||||
void nameFiltersChanged();
|
||||
void entriesChanged();
|
||||
void pathChanged();
|
||||
void recursiveChanged();
|
||||
void watchChangesChanged();
|
||||
void showHiddenChanged();
|
||||
void sortReverseChanged();
|
||||
void filterChanged();
|
||||
void nameFiltersChanged();
|
||||
void entriesChanged();
|
||||
|
||||
private:
|
||||
QDir m_dir;
|
||||
QFileSystemWatcher m_watcher;
|
||||
QList<FileSystemEntry*> m_entries;
|
||||
QHash<QString, QFuture<QPair<QSet<QString>, QSet<QString>>>> m_futures;
|
||||
QDir m_dir;
|
||||
QFileSystemWatcher m_watcher;
|
||||
QList<FileSystemEntry*> m_entries;
|
||||
QHash<QString, QFuture<QPair<QSet<QString>, QSet<QString> > > > m_futures;
|
||||
|
||||
QString m_path;
|
||||
bool m_recursive;
|
||||
bool m_watchChanges;
|
||||
bool m_showHidden;
|
||||
bool m_sortReverse;
|
||||
Filter m_filter;
|
||||
QStringList m_nameFilters;
|
||||
QString m_path;
|
||||
bool m_recursive;
|
||||
bool m_watchChanges;
|
||||
bool m_showHidden;
|
||||
bool m_sortReverse = false;
|
||||
Filter m_filter;
|
||||
QStringList m_nameFilters;
|
||||
|
||||
void watchDirIfRecursive(const QString& path);
|
||||
void update();
|
||||
void updateWatcher();
|
||||
void updateEntries();
|
||||
void updateEntriesForDir(const QString& dir);
|
||||
void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths);
|
||||
[[nodiscard]] bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const;
|
||||
void watchDirIfRecursive(const QString& path);
|
||||
void update();
|
||||
void updateWatcher();
|
||||
void updateEntries();
|
||||
void updateEntriesForDir(const QString& dir);
|
||||
void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths);
|
||||
[[nodiscard]] bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const;
|
||||
};
|
||||
|
||||
} // namespace ZShell::models
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
//@ pragma UseQApplication
|
||||
//@ pragma Env QSG_RENDER_LOOP=threaded
|
||||
// @ pragma Env QSG_RHI_BACKEND=vulkan
|
||||
//@ pragma Env QSG_RHI_BACKEND=vulkan
|
||||
//@ pragma Env QSG_NO_VSYNC=1
|
||||
//@ pragma Env QS_NO_RELOAD_POPUP=1
|
||||
//@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round
|
||||
//@ pragma DropExpensiveFonts
|
||||
import Quickshell
|
||||
import qs.Extensions
|
||||
import qs.Modules
|
||||
import qs.Modules.Wallpaper
|
||||
import qs.Modules.Lock
|
||||
@@ -14,6 +15,8 @@ import qs.Helpers
|
||||
import qs.Modules.Polkit
|
||||
|
||||
ShellRoot {
|
||||
settings.watchFiles: true
|
||||
|
||||
Windows {
|
||||
}
|
||||
|
||||
@@ -36,4 +39,7 @@ ShellRoot {
|
||||
|
||||
Polkit {
|
||||
}
|
||||
|
||||
LoadExtensions {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user