diff --git a/modules/nexus/PageCompRegistry.qml b/modules/nexus/PageCompRegistry.qml index 8fcdfca3..2e04a2bf 100644 --- a/modules/nexus/PageCompRegistry.qml +++ b/modules/nexus/PageCompRegistry.qml @@ -3,6 +3,7 @@ pragma Singleton import QtQuick import qs.modules.nexus.common import qs.modules.nexus.pages +import qs.modules.nexus.pages.wallandstyle QtObject { id: root @@ -14,6 +15,9 @@ QtObject { Component { WallpaperAndStyle {} } + Component { + WallpaperSelect {} + } } } ] diff --git a/modules/nexus/pages/WallpaperAndStyle.qml b/modules/nexus/pages/WallpaperAndStyle.qml index 5eb8b574..57a9f850 100644 --- a/modules/nexus/pages/WallpaperAndStyle.qml +++ b/modules/nexus/pages/WallpaperAndStyle.qml @@ -153,7 +153,8 @@ PageBase { type: IconTextButton.Tonal horizontalPadding: Tokens.padding.extraLarge verticalPadding: Tokens.padding.medium - onClicked: ; // TODO + disabled: !Config.background.wallpaperEnabled + onClicked: root.nState.openSubPage(1) // Wallpaper page } IconTextButton { diff --git a/modules/nexus/pages/wallandstyle/WallpaperSelect.qml b/modules/nexus/pages/wallandstyle/WallpaperSelect.qml new file mode 100644 index 00000000..9f60ab29 --- /dev/null +++ b/modules/nexus/pages/wallandstyle/WallpaperSelect.qml @@ -0,0 +1,139 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Layouts +import Quickshell +import Caelestia.Config +import Caelestia.Models +import qs.components +import qs.components.controls +import qs.services +import qs.modules.nexus.common + +PageBase { + id: root + + title: qsTr("Wallpaper") + isSubPage: true + + ColumnLayout { + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + width: root.cappedWidth + spacing: Tokens.spacing.small + + Wallpaper { + Layout.fillWidth: true + implicitHeight: Math.round(width * 0.3) + radius: Tokens.rounding.extraLarge + source: Wallpapers.current + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Featured wallpaper") + font: Tokens.font.label.medium + } + + StyledText { + Layout.topMargin: Tokens.spacing.large + text: qsTr("Local wallpapers") + font: Tokens.font.title.small + } + + GridLayout { + Layout.fillWidth: true + + columns: Config.nexus.wallpapersPerRow + rowSpacing: Tokens.spacing.large + columnSpacing: Tokens.spacing.large + + Repeater { + model: Wallpapers.list + + ColumnLayout { + id: wallDelegate + + required property FileSystemEntry modelData + + Layout.fillWidth: true + Layout.preferredWidth: 0 // Force uniform size + spacing: Tokens.spacing.small + + Wallpaper { + Layout.fillWidth: true + implicitHeight: width + radius: Tokens.rounding.largeIncreased + source: wallDelegate.modelData.path + } + + StyledText { + Layout.fillWidth: true + text: wallDelegate.modelData.name + color: Colours.palette.m3onSurfaceVariant + font: Tokens.font.label.builders.small.weight(Font.Medium).build() + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + } + } + } + } + } + + component Wallpaper: StyledClippingRect { + id: wallpaper + + property alias source: img.source + + color: Colours.tPalette.m3surfaceContainer + + Loader { + anchors.centerIn: parent + + opacity: img.status === Image.Ready ? 0 : 1 + active: opacity > 0 + + sourceComponent: StyledRect { + implicitWidth: loadingIndicator.implicitSize + Tokens.padding.large * 2 + implicitHeight: loadingIndicator.implicitSize + Tokens.padding.large * 2 + + color: Colours.palette.m3primaryContainer + radius: Tokens.rounding.full + + LoadingIndicator { + id: loadingIndicator + + anchors.centerIn: parent + containsIcon: true + implicitSize: Math.min(wallpaper.width, wallpaper.height) * 0.3 + } + } + + Behavior on opacity { + Anim { + type: Anim.DefaultEffects + } + } + } + + Image { + id: img + + anchors.fill: parent + asynchronous: true + fillMode: Image.PreserveAspectCrop + sourceSize: { + const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1; + return Qt.size(width * dpr, height * dpr); + } + retainWhileLoading: true + opacity: status === Image.Ready ? 1 : 0 + + Behavior on opacity { + Anim { + type: Anim.SlowEffects + } + } + } + } +} diff --git a/plugin/src/Caelestia/Config/CMakeLists.txt b/plugin/src/Caelestia/Config/CMakeLists.txt index b6f4ef08..75593177 100644 --- a/plugin/src/Caelestia/Config/CMakeLists.txt +++ b/plugin/src/Caelestia/Config/CMakeLists.txt @@ -20,6 +20,7 @@ qml_module(caelestia-config generalconfig.hpp launcherconfig.hpp lockconfig.hpp + nexusconfig.hpp notifsconfig.hpp osdconfig.hpp serviceconfig.hpp diff --git a/plugin/src/Caelestia/Config/config.cpp b/plugin/src/Caelestia/Config/config.cpp index ecd63bb5..6e15f1d2 100644 --- a/plugin/src/Caelestia/Config/config.cpp +++ b/plugin/src/Caelestia/Config/config.cpp @@ -9,6 +9,7 @@ #include "launcherconfig.hpp" #include "lockconfig.hpp" #include "monitorconfigmanager.hpp" +#include "nexusconfig.hpp" #include "notifsconfig.hpp" #include "osdconfig.hpp" #include "serviceconfig.hpp" @@ -42,14 +43,15 @@ GlobalConfig::GlobalConfig(QObject* parent) , m_dashboard(new DashboardConfig(this)) , m_controlCenter(new ControlCenterConfig(this)) , m_launcher(new LauncherConfig(this)) + , m_lock(new LockConfig(this)) + , m_nexus(new NexusConfig(this)) , m_notifs(new NotifsConfig(this)) , m_osd(new OsdConfig(this)) - , m_session(new SessionConfig(this)) - , m_winfo(new WInfoConfig(this)) - , m_lock(new LockConfig(this)) - , m_utilities(new UtilitiesConfig(this)) - , m_sidebar(new SidebarConfig(this)) , m_services(new ServiceConfig(this)) + , m_session(new SessionConfig(this)) + , m_sidebar(new SidebarConfig(this)) + , m_utilities(new UtilitiesConfig(this)) + , m_winfo(new WInfoConfig(this)) , m_paths(new UserPaths(this)) { setupFileBackend(configDir() + QStringLiteral("shell.json")); } @@ -64,14 +66,15 @@ GlobalConfig::GlobalConfig(GlobalConfig* fallback, const QString& filePath, cons , m_dashboard(new DashboardConfig(this)) , m_controlCenter(new ControlCenterConfig(this)) , m_launcher(new LauncherConfig(this)) + , m_lock(new LockConfig(this)) + , m_nexus(new NexusConfig(this)) , m_notifs(new NotifsConfig(this)) , m_osd(new OsdConfig(this)) - , m_session(new SessionConfig(this)) - , m_winfo(new WInfoConfig(this)) - , m_lock(new LockConfig(this)) - , m_utilities(new UtilitiesConfig(this)) - , m_sidebar(new SidebarConfig(this)) , m_services(new ServiceConfig(this)) + , m_session(new SessionConfig(this)) + , m_sidebar(new SidebarConfig(this)) + , m_utilities(new UtilitiesConfig(this)) + , m_winfo(new WInfoConfig(this)) , m_paths(new UserPaths(this)) { if (!filePath.isEmpty()) setupFileBackend(filePath, screen); diff --git a/plugin/src/Caelestia/Config/config.hpp b/plugin/src/Caelestia/Config/config.hpp index 248a3f22..5b5cd9a0 100644 --- a/plugin/src/Caelestia/Config/config.hpp +++ b/plugin/src/Caelestia/Config/config.hpp @@ -15,6 +15,7 @@ class DashboardConfig; class GeneralConfig; class LauncherConfig; class LockConfig; +class NexusConfig; class NotifsConfig; class OsdConfig; class ServiceConfig; @@ -37,6 +38,7 @@ class GlobalConfig : public RootConfig { Q_MOC_INCLUDE("generalconfig.hpp") Q_MOC_INCLUDE("launcherconfig.hpp") Q_MOC_INCLUDE("lockconfig.hpp") + Q_MOC_INCLUDE("nexusconfig.hpp") Q_MOC_INCLUDE("notifsconfig.hpp") Q_MOC_INCLUDE("osdconfig.hpp") Q_MOC_INCLUDE("serviceconfig.hpp") @@ -55,14 +57,15 @@ class GlobalConfig : public RootConfig { CONFIG_SUBOBJECT(DashboardConfig, dashboard) CONFIG_SUBOBJECT(ControlCenterConfig, controlCenter) CONFIG_SUBOBJECT(LauncherConfig, launcher) + CONFIG_SUBOBJECT(LockConfig, lock) + CONFIG_SUBOBJECT(NexusConfig, nexus) CONFIG_SUBOBJECT(NotifsConfig, notifs) CONFIG_SUBOBJECT(OsdConfig, osd) - CONFIG_SUBOBJECT(SessionConfig, session) - CONFIG_SUBOBJECT(WInfoConfig, winfo) - CONFIG_SUBOBJECT(LockConfig, lock) - CONFIG_SUBOBJECT(UtilitiesConfig, utilities) - CONFIG_SUBOBJECT(SidebarConfig, sidebar) CONFIG_SUBOBJECT(ServiceConfig, services) + CONFIG_SUBOBJECT(SessionConfig, session) + CONFIG_SUBOBJECT(SidebarConfig, sidebar) + CONFIG_SUBOBJECT(UtilitiesConfig, utilities) + CONFIG_SUBOBJECT(WInfoConfig, winfo) CONFIG_SUBOBJECT(UserPaths, paths) public: diff --git a/plugin/src/Caelestia/Config/configattached.cpp b/plugin/src/Caelestia/Config/configattached.cpp index 8d229049..b5420b69 100644 --- a/plugin/src/Caelestia/Config/configattached.cpp +++ b/plugin/src/Caelestia/Config/configattached.cpp @@ -73,14 +73,15 @@ CONFIG_ATTACHED_GETTER(BorderConfig, border) CONFIG_ATTACHED_GETTER(DashboardConfig, dashboard) CONFIG_ATTACHED_GETTER(ControlCenterConfig, controlCenter) CONFIG_ATTACHED_GETTER(LauncherConfig, launcher) +CONFIG_ATTACHED_GETTER(LockConfig, lock) +CONFIG_ATTACHED_GETTER(NexusConfig, nexus) CONFIG_ATTACHED_GETTER(NotifsConfig, notifs) CONFIG_ATTACHED_GETTER(OsdConfig, osd) -CONFIG_ATTACHED_GETTER(SessionConfig, session) -CONFIG_ATTACHED_GETTER(WInfoConfig, winfo) -CONFIG_ATTACHED_GETTER(LockConfig, lock) -CONFIG_ATTACHED_GETTER(UtilitiesConfig, utilities) -CONFIG_ATTACHED_GETTER(SidebarConfig, sidebar) CONFIG_ATTACHED_GETTER(ServiceConfig, services) +CONFIG_ATTACHED_GETTER(SessionConfig, session) +CONFIG_ATTACHED_GETTER(SidebarConfig, sidebar) +CONFIG_ATTACHED_GETTER(UtilitiesConfig, utilities) +CONFIG_ATTACHED_GETTER(WInfoConfig, winfo) CONFIG_ATTACHED_GETTER(UserPaths, paths) #undef CONFIG_ATTACHED_GETTER diff --git a/plugin/src/Caelestia/Config/configattached.hpp b/plugin/src/Caelestia/Config/configattached.hpp index 815b1080..19054bde 100644 --- a/plugin/src/Caelestia/Config/configattached.hpp +++ b/plugin/src/Caelestia/Config/configattached.hpp @@ -21,6 +21,7 @@ class Config : public QQuickAttachedPropertyPropagator, public QQmlParserStatus Q_MOC_INCLUDE("generalconfig.hpp") Q_MOC_INCLUDE("launcherconfig.hpp") Q_MOC_INCLUDE("lockconfig.hpp") + Q_MOC_INCLUDE("nexusconfig.hpp") Q_MOC_INCLUDE("notifsconfig.hpp") Q_MOC_INCLUDE("osdconfig.hpp") Q_MOC_INCLUDE("serviceconfig.hpp") @@ -39,14 +40,15 @@ class Config : public QQuickAttachedPropertyPropagator, public QQmlParserStatus Q_PROPERTY(const caelestia::config::DashboardConfig* dashboard READ dashboard NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::ControlCenterConfig* controlCenter READ controlCenter NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::LauncherConfig* launcher READ launcher NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::LockConfig* lock READ lock NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::NexusConfig* nexus READ nexus NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::NotifsConfig* notifs READ notifs NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::OsdConfig* osd READ osd NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::SessionConfig* session READ session NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::WInfoConfig* winfo READ winfo NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::LockConfig* lock READ lock NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::UtilitiesConfig* utilities READ utilities NOTIFY sourceChanged) - Q_PROPERTY(const caelestia::config::SidebarConfig* sidebar READ sidebar NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::ServiceConfig* services READ services NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::SessionConfig* session READ session NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::SidebarConfig* sidebar READ sidebar NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::UtilitiesConfig* utilities READ utilities NOTIFY sourceChanged) + Q_PROPERTY(const caelestia::config::WInfoConfig* winfo READ winfo NOTIFY sourceChanged) Q_PROPERTY(const caelestia::config::UserPaths* paths READ paths NOTIFY sourceChanged) public: @@ -63,14 +65,15 @@ public: [[nodiscard]] const DashboardConfig* dashboard() const; [[nodiscard]] const ControlCenterConfig* controlCenter() const; [[nodiscard]] const LauncherConfig* launcher() const; + [[nodiscard]] const LockConfig* lock() const; + [[nodiscard]] const NexusConfig* nexus() const; [[nodiscard]] const NotifsConfig* notifs() const; [[nodiscard]] const OsdConfig* osd() const; - [[nodiscard]] const SessionConfig* session() const; - [[nodiscard]] const WInfoConfig* winfo() const; - [[nodiscard]] const LockConfig* lock() const; - [[nodiscard]] const UtilitiesConfig* utilities() const; - [[nodiscard]] const SidebarConfig* sidebar() const; [[nodiscard]] const ServiceConfig* services() const; + [[nodiscard]] const SessionConfig* session() const; + [[nodiscard]] const SidebarConfig* sidebar() const; + [[nodiscard]] const UtilitiesConfig* utilities() const; + [[nodiscard]] const WInfoConfig* winfo() const; [[nodiscard]] const UserPaths* paths() const; [[nodiscard]] Q_INVOKABLE static GlobalConfig* forScreen(const QString& screen); diff --git a/plugin/src/Caelestia/Config/nexusconfig.hpp b/plugin/src/Caelestia/Config/nexusconfig.hpp new file mode 100644 index 00000000..7d43220f --- /dev/null +++ b/plugin/src/Caelestia/Config/nexusconfig.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "configobject.hpp" + +namespace caelestia::config { + +class NexusConfig : public ConfigObject { + Q_OBJECT + QML_ANONYMOUS + + CONFIG_PROPERTY(int, wallpapersPerRow, 4) + +public: + explicit NexusConfig(QObject* parent = nullptr) + : ConfigObject(parent) {} +}; + +} // namespace caelestia::config