mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
mecha refactoring
This commit is contained in:
@@ -116,7 +116,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
|
||||
4. **Modules/** - UI components
|
||||
- **Full-screen components**: AppLauncher, ClipboardHistoryModal, ControlCenter
|
||||
- **Panel components**: TopBar, SystemTrayWidget, NotificationPopup
|
||||
- **Panel components**: TopBar, SystemTray, NotificationPopup
|
||||
- **Layout components**: WorkspaceSwitcher
|
||||
|
||||
5. **Widgets/** - Reusable UI controls
|
||||
|
||||
49
Common/Anims.qml
Normal file
49
Common/Anims.qml
Normal file
@@ -0,0 +1,49 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
readonly property int durShort: 160
|
||||
readonly property int durMed: 220
|
||||
readonly property int durLong: 320
|
||||
|
||||
readonly property int slidePx: 100
|
||||
|
||||
readonly property QtObject direction: QtObject {
|
||||
readonly property int fromLeft: 0
|
||||
readonly property int fromRight: 1
|
||||
readonly property int fadeOnly: 2
|
||||
}
|
||||
|
||||
readonly property Component slideInLeft: Transition {
|
||||
NumberAnimation { properties: "x"; from: -Anims.slidePx; to: 0; duration: Anims.durMed; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: Anims.durShort }
|
||||
}
|
||||
|
||||
readonly property Component slideOutLeft: Transition {
|
||||
NumberAnimation { properties: "x"; to: -Anims.slidePx; duration: Anims.durShort; easing.type: Easing.InCubic }
|
||||
NumberAnimation { properties: "opacity"; to: 0.0; duration: Anims.durShort }
|
||||
}
|
||||
|
||||
readonly property Component slideInRight: Transition {
|
||||
NumberAnimation { properties: "x"; from: Anims.slidePx; to: 0; duration: Anims.durMed; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: Anims.durShort }
|
||||
}
|
||||
|
||||
readonly property Component slideOutRight: Transition {
|
||||
NumberAnimation { properties: "x"; to: Anims.slidePx; duration: Anims.durShort; easing.type: Easing.InCubic }
|
||||
NumberAnimation { properties: "opacity"; to: 0.0; duration: Anims.durShort }
|
||||
}
|
||||
|
||||
readonly property Component fadeIn: Transition {
|
||||
NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: Anims.durShort; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
readonly property Component fadeOut: Transition {
|
||||
NumberAnimation { properties: "opacity"; to: 0.0; duration: Anims.durShort; easing.type: Easing.InCubic }
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ Singleton {
|
||||
property bool showWorkspaceIndex: false
|
||||
property bool showWorkspacePadding: false
|
||||
property string appLauncherViewMode: "list"
|
||||
property string spotlightLauncherViewMode: "list"
|
||||
property string spotlightModalViewMode: "list"
|
||||
property string networkPreference: "auto"
|
||||
property string iconTheme: "System Default"
|
||||
property var availableIconThemes: ["System Default"]
|
||||
@@ -70,7 +70,7 @@ Singleton {
|
||||
showWorkspaceIndex = settings.showWorkspaceIndex !== undefined ? settings.showWorkspaceIndex : false;
|
||||
showWorkspacePadding = settings.showWorkspacePadding !== undefined ? settings.showWorkspacePadding : false;
|
||||
appLauncherViewMode = settings.appLauncherViewMode !== undefined ? settings.appLauncherViewMode : "list";
|
||||
spotlightLauncherViewMode = settings.spotlightLauncherViewMode !== undefined ? settings.spotlightLauncherViewMode : "list";
|
||||
spotlightModalViewMode = settings.spotlightModalViewMode !== undefined ? settings.spotlightModalViewMode : "list";
|
||||
networkPreference = settings.networkPreference !== undefined ? settings.networkPreference : "auto";
|
||||
iconTheme = settings.iconTheme !== undefined ? settings.iconTheme : "System Default";
|
||||
useOSLogo = settings.useOSLogo !== undefined ? settings.useOSLogo : false;
|
||||
@@ -112,7 +112,7 @@ Singleton {
|
||||
"showWorkspaceIndex": showWorkspaceIndex,
|
||||
"showWorkspacePadding": showWorkspacePadding,
|
||||
"appLauncherViewMode": appLauncherViewMode,
|
||||
"spotlightLauncherViewMode": spotlightLauncherViewMode,
|
||||
"spotlightModalViewMode": spotlightModalViewMode,
|
||||
"networkPreference": networkPreference,
|
||||
"iconTheme": iconTheme,
|
||||
"useOSLogo": useOSLogo,
|
||||
@@ -277,8 +277,8 @@ Singleton {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setSpotlightLauncherViewMode(mode) {
|
||||
spotlightLauncherViewMode = mode;
|
||||
function setSpotlightModalViewMode(mode) {
|
||||
spotlightModalViewMode = mode;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
|
||||
46
Common/SlideFadeBehavior.qml
Normal file
46
Common/SlideFadeBehavior.qml
Normal file
@@ -0,0 +1,46 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
|
||||
Item {
|
||||
id: root
|
||||
// attach to target
|
||||
required property Item target
|
||||
property int direction: Anims.direction.fadeOnly
|
||||
|
||||
// call these
|
||||
function show() { _apply(true) }
|
||||
function hide() { _apply(false) }
|
||||
|
||||
function _apply(showing) {
|
||||
const off = Anims.slidePx
|
||||
let fromX = 0
|
||||
let toX = 0
|
||||
switch(direction) {
|
||||
case Anims.direction.fromLeft: fromX = -off; toX = 0; break
|
||||
case Anims.direction.fromRight: fromX = off; toX = 0; break
|
||||
default: fromX = 0; toX = 0;
|
||||
}
|
||||
|
||||
if (showing) {
|
||||
target.x = fromX
|
||||
target.opacity = 0
|
||||
target.visible = true
|
||||
animX.from = fromX; animX.to = toX
|
||||
animO.from = 0; animO.to = 1
|
||||
} else {
|
||||
animX.from = target.x; animX.to = (direction === Anims.direction.fromLeft ? -off :
|
||||
direction === Anims.direction.fromRight ? off : 0)
|
||||
animO.from = target.opacity; animO.to = 0
|
||||
}
|
||||
seq.restart()
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: seq
|
||||
ParallelAnimation {
|
||||
NumberAnimation { id: animX; target: root.target; property: "x"; duration: Anims.durMed; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { id: animO; target: root.target; property: "opacity"; duration: Anims.durShort }
|
||||
}
|
||||
ScriptAction { script: if (root.target.opacity === 0) root.target.visible = false }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
@@ -10,7 +10,7 @@ import qs.Widgets
|
||||
DankModal {
|
||||
id: root
|
||||
|
||||
property bool networkInfoDialogVisible: false
|
||||
property bool networkInfoModalVisible: false
|
||||
property string networkSSID: ""
|
||||
property var networkData: null
|
||||
property string networkDetails: ""
|
||||
@@ -18,18 +18,18 @@ DankModal {
|
||||
function showNetworkInfo(ssid, data) {
|
||||
networkSSID = ssid;
|
||||
networkData = data;
|
||||
networkInfoDialogVisible = true;
|
||||
networkInfoModalVisible = true;
|
||||
WifiService.fetchNetworkInfo(ssid);
|
||||
}
|
||||
|
||||
function hideDialog() {
|
||||
networkInfoDialogVisible = false;
|
||||
networkInfoModalVisible = false;
|
||||
networkSSID = "";
|
||||
networkData = null;
|
||||
networkDetails = "";
|
||||
}
|
||||
|
||||
visible: networkInfoDialogVisible
|
||||
visible: networkInfoModalVisible
|
||||
width: 600
|
||||
height: 500
|
||||
enableShadow: true
|
||||
@@ -9,6 +9,7 @@ import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.ProcessList
|
||||
|
||||
DankModal {
|
||||
id: processListModal
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
import qs.Modules.Settings
|
||||
|
||||
DankModal {
|
||||
id: settingsModal
|
||||
@@ -8,7 +8,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: spotlightLauncher
|
||||
id: spotlightModal
|
||||
|
||||
property bool spotlightOpen: false
|
||||
property var filteredApps: []
|
||||
@@ -25,13 +25,13 @@ DankModal {
|
||||
}));
|
||||
}
|
||||
property string selectedCategory: "All"
|
||||
property string viewMode: Prefs.spotlightLauncherViewMode // "list" or "grid"
|
||||
property string viewMode: Prefs.spotlightModalViewMode // "list" or "grid"
|
||||
property int gridColumns: 4
|
||||
|
||||
function show() {
|
||||
console.log("SpotlightLauncher: show() called");
|
||||
console.log("SpotlightModal: show() called");
|
||||
spotlightOpen = true;
|
||||
console.log("SpotlightLauncher: spotlightOpen set to", spotlightOpen);
|
||||
console.log("SpotlightModal: spotlightOpen set to", spotlightOpen);
|
||||
searchDebounceTimer.stop(); // Stop any pending search
|
||||
updateFilteredApps(); // Immediate update when showing
|
||||
}
|
||||
@@ -208,7 +208,7 @@ DankModal {
|
||||
enableShadow: true
|
||||
|
||||
onVisibleChanged: {
|
||||
console.log("SpotlightLauncher visibility changed to:", visible);
|
||||
console.log("SpotlightModal visibility changed to:", visible);
|
||||
if (visible && !spotlightOpen) {
|
||||
show();
|
||||
}
|
||||
@@ -219,7 +219,7 @@ DankModal {
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("SpotlightLauncher: Component.onCompleted called - component loaded successfully!");
|
||||
console.log("SpotlightModal: Component.onCompleted called - component loaded successfully!");
|
||||
var allCategories = AppSearchService.getAllCategories().filter((cat) => {
|
||||
return cat !== "Education" && cat !== "Science";
|
||||
});
|
||||
@@ -405,7 +405,7 @@ DankModal {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: spotlightLauncher
|
||||
target: spotlightModal
|
||||
function onOpened() {
|
||||
searchField.forceActiveFocus();
|
||||
}
|
||||
@@ -464,7 +464,7 @@ DankModal {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
viewMode = "list";
|
||||
Prefs.setSpotlightLauncherViewMode("list");
|
||||
Prefs.setSpotlightModalViewMode("list");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,7 +493,7 @@ DankModal {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
viewMode = "grid";
|
||||
Prefs.setSpotlightLauncherViewMode("grid");
|
||||
Prefs.setSpotlightModalViewMode("grid");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -557,20 +557,20 @@ DankModal {
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
console.log("SpotlightLauncher: IPC open() called");
|
||||
spotlightLauncher.show();
|
||||
console.log("SpotlightModal: IPC open() called");
|
||||
spotlightModal.show();
|
||||
return "SPOTLIGHT_OPEN_SUCCESS";
|
||||
}
|
||||
|
||||
function close() {
|
||||
console.log("SpotlightLauncher: IPC close() called");
|
||||
spotlightLauncher.hide();
|
||||
console.log("SpotlightModal: IPC close() called");
|
||||
spotlightModal.hide();
|
||||
return "SPOTLIGHT_CLOSE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
console.log("SpotlightLauncher: IPC toggle() called");
|
||||
spotlightLauncher.toggle();
|
||||
console.log("SpotlightModal: IPC toggle() called");
|
||||
spotlightModal.toggle();
|
||||
return "SPOTLIGHT_TOGGLE_SUCCESS";
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import qs.Widgets
|
||||
DankModal {
|
||||
id: root
|
||||
|
||||
property bool wifiPasswordDialogVisible: false
|
||||
property bool wifiPasswordModalVisible: false
|
||||
property string wifiPasswordSSID: ""
|
||||
property string wifiPasswordInput: ""
|
||||
|
||||
visible: wifiPasswordDialogVisible
|
||||
visible: wifiPasswordModalVisible
|
||||
width: 420
|
||||
height: 230
|
||||
keyboardFocus: "ondemand"
|
||||
@@ -21,7 +21,7 @@ DankModal {
|
||||
|
||||
}
|
||||
onBackgroundClicked: {
|
||||
wifiPasswordDialogVisible = false;
|
||||
wifiPasswordModalVisible = false;
|
||||
wifiPasswordInput = "";
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ DankModal {
|
||||
if (WifiService.passwordDialogShouldReopen && WifiService.connectingSSID !== "") {
|
||||
wifiPasswordSSID = WifiService.connectingSSID;
|
||||
wifiPasswordInput = "";
|
||||
wifiPasswordDialogVisible = true;
|
||||
wifiPasswordModalVisible = true;
|
||||
WifiService.passwordDialogShouldReopen = false;
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ DankModal {
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||
onClicked: {
|
||||
wifiPasswordDialogVisible = false;
|
||||
wifiPasswordModalVisible = false;
|
||||
wifiPasswordInput = "";
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ DankModal {
|
||||
}
|
||||
onAccepted: {
|
||||
WifiService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text);
|
||||
wifiPasswordDialogVisible = false;
|
||||
wifiPasswordModalVisible = false;
|
||||
wifiPasswordInput = "";
|
||||
passwordInput.text = "";
|
||||
}
|
||||
@@ -212,7 +212,7 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
wifiPasswordDialogVisible = false;
|
||||
wifiPasswordModalVisible = false;
|
||||
wifiPasswordInput = "";
|
||||
}
|
||||
}
|
||||
@@ -246,7 +246,7 @@ DankModal {
|
||||
enabled: parent.enabled
|
||||
onClicked: {
|
||||
WifiService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text);
|
||||
wifiPasswordDialogVisible = false;
|
||||
wifiPasswordModalVisible = false;
|
||||
wifiPasswordInput = "";
|
||||
passwordInput.text = "";
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Column {
|
||||
id: calendarWidget
|
||||
id: calendarGrid
|
||||
|
||||
property date displayDate: new Date()
|
||||
property date selectedDate: new Date()
|
||||
@@ -7,7 +7,7 @@ import qs.Widgets
|
||||
|
||||
// Events widget for selected date - Material Design 3 style
|
||||
Rectangle {
|
||||
id: eventsWidget
|
||||
id: events
|
||||
|
||||
property date selectedDate: new Date()
|
||||
property var selectedDateEvents: []
|
||||
@@ -17,7 +17,7 @@ Rectangle {
|
||||
function updateSelectedDateEvents() {
|
||||
if (CalendarService && CalendarService.khalAvailable) {
|
||||
let events = CalendarService.getEventsForDate(selectedDate);
|
||||
console.log("EventsWidget: Updating events for", Qt.formatDate(selectedDate, "yyyy-MM-dd"), "found", events.length, "events");
|
||||
console.log("Events: Updating events for", Qt.formatDate(selectedDate, "yyyy-MM-dd"), "found", events.length, "events");
|
||||
selectedDateEvents = events;
|
||||
} else {
|
||||
selectedDateEvents = [];
|
||||
@@ -25,7 +25,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
onSelectedDateEventsChanged: {
|
||||
console.log("EventsWidget: selectedDateEvents changed, count:", selectedDateEvents.length);
|
||||
console.log("Events: selectedDateEvents changed, count:", selectedDateEvents.length);
|
||||
eventsList.model = selectedDateEvents;
|
||||
}
|
||||
width: parent.width
|
||||
@@ -8,7 +8,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: mediaPlayerWidget
|
||||
id: mediaPlayer
|
||||
|
||||
property MprisPlayer activePlayer: MprisController.activePlayer
|
||||
property string lastValidTitle: ""
|
||||
@@ -6,7 +6,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: weatherWidget
|
||||
id: weather
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
@@ -13,8 +13,8 @@ Rectangle {
|
||||
property var networkData: null
|
||||
property bool menuVisible: false
|
||||
property var parentItem
|
||||
property var wifiPasswordDialogRef
|
||||
property var networkInfoDialogRef
|
||||
property var wifiPasswordModalRef
|
||||
property var networkInfoModalRef
|
||||
|
||||
function show(x, y) {
|
||||
const menuWidth = 160;
|
||||
@@ -123,10 +123,10 @@ Rectangle {
|
||||
if (wifiContextMenuWindow.networkData.saved) {
|
||||
WifiService.connectToWifi(wifiContextMenuWindow.networkData.ssid);
|
||||
} else if (wifiContextMenuWindow.networkData.secured) {
|
||||
if (wifiPasswordDialogRef) {
|
||||
wifiPasswordDialogRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid;
|
||||
wifiPasswordDialogRef.wifiPasswordInput = "";
|
||||
wifiPasswordDialogRef.wifiPasswordDialogVisible = true;
|
||||
if (wifiPasswordModalRef) {
|
||||
wifiPasswordModalRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid;
|
||||
wifiPasswordModalRef.wifiPasswordInput = "";
|
||||
wifiPasswordModalRef.wifiPasswordModalVisible = true;
|
||||
}
|
||||
} else {
|
||||
WifiService.connectToWifi(wifiContextMenuWindow.networkData.ssid);
|
||||
@@ -248,8 +248,8 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (wifiContextMenuWindow.networkData && networkInfoDialogRef) {
|
||||
networkInfoDialogRef.showNetworkInfo(wifiContextMenuWindow.networkData.ssid, wifiContextMenuWindow.networkData);
|
||||
if (wifiContextMenuWindow.networkData && networkInfoModalRef) {
|
||||
networkInfoModalRef.showNetworkInfo(wifiContextMenuWindow.networkData.ssid, wifiContextMenuWindow.networkData);
|
||||
}
|
||||
wifiContextMenuWindow.hide();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ Column {
|
||||
|
||||
property var wifiContextMenuWindow
|
||||
property var sortedWifiNetworks
|
||||
property var wifiPasswordDialogRef
|
||||
property var wifiPasswordModalRef
|
||||
|
||||
function getWiFiSignalIcon(signalStrength) {
|
||||
switch (signalStrength) {
|
||||
@@ -255,10 +255,10 @@ Column {
|
||||
if (modelData.saved) {
|
||||
WifiService.connectToWifi(modelData.ssid);
|
||||
} else if (modelData.secured) {
|
||||
if (wifiPasswordDialogRef) {
|
||||
wifiPasswordDialogRef.wifiPasswordSSID = modelData.ssid;
|
||||
wifiPasswordDialogRef.wifiPasswordInput = "";
|
||||
wifiPasswordDialogRef.wifiPasswordDialogVisible = true;
|
||||
if (wifiPasswordModalRef) {
|
||||
wifiPasswordModalRef.wifiPasswordSSID = modelData.ssid;
|
||||
wifiPasswordModalRef.wifiPasswordInput = "";
|
||||
wifiPasswordModalRef.wifiPasswordModalVisible = true;
|
||||
}
|
||||
} else {
|
||||
WifiService.connectToWifi(modelData.ssid);
|
||||
|
||||
@@ -11,8 +11,8 @@ import qs.Modules.ControlCenter.Network
|
||||
Item {
|
||||
id: networkTab
|
||||
|
||||
property var wifiPasswordDialogRef: wifiPasswordDialog
|
||||
property var networkInfoDialogRef: networkInfoDialog
|
||||
property var wifiPasswordModalRef: wifiPasswordModal
|
||||
property var networkInfoModalRef: networkInfoModal
|
||||
|
||||
// Properly sorted WiFi networks with connected networks first
|
||||
property var sortedWifiNetworks: {
|
||||
@@ -188,7 +188,7 @@ Item {
|
||||
WiFiNetworksList {
|
||||
wifiContextMenuWindow: wifiContextMenuWindow
|
||||
sortedWifiNetworks: networkTab.sortedWifiNetworks
|
||||
wifiPasswordDialogRef: networkTab.wifiPasswordDialogRef
|
||||
wifiPasswordModalRef: networkTab.wifiPasswordModalRef
|
||||
}
|
||||
|
||||
// Timer for refreshing network status after WiFi toggle
|
||||
@@ -312,8 +312,8 @@ Item {
|
||||
WiFiContextMenu {
|
||||
id: wifiContextMenuWindow
|
||||
parentItem: networkTab
|
||||
wifiPasswordDialogRef: networkTab.wifiPasswordDialogRef
|
||||
networkInfoDialogRef: networkTab.networkInfoDialogRef
|
||||
wifiPasswordModalRef: networkTab.wifiPasswordModalRef
|
||||
networkInfoModalRef: networkTab.networkInfoModalRef
|
||||
}
|
||||
|
||||
// Background MouseArea to close the context menu
|
||||
|
||||
@@ -12,7 +12,7 @@ import qs.Widgets
|
||||
PanelWindow {
|
||||
// For recents, use the recent apps from Prefs and filter out non-existent ones
|
||||
|
||||
id: launcher
|
||||
id: appDrawerPopout
|
||||
|
||||
property bool isVisible: false
|
||||
// App management
|
||||
@@ -125,9 +125,9 @@ PanelWindow {
|
||||
Prefs.addRecentApp(selectedApp.desktopEntry);
|
||||
selectedApp.desktopEntry.execute();
|
||||
} else {
|
||||
launcher.launchApp(selectedApp.exec);
|
||||
appDrawerPopout.launchApp(selectedApp.exec);
|
||||
}
|
||||
launcher.hide();
|
||||
appDrawerPopout.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ PanelWindow {
|
||||
}
|
||||
|
||||
function show() {
|
||||
launcher.isVisible = true;
|
||||
appDrawerPopout.isVisible = true;
|
||||
searchField.enabled = true;
|
||||
searchDebounceTimer.stop(); // Stop any pending search
|
||||
updateFilteredModel();
|
||||
@@ -153,14 +153,14 @@ PanelWindow {
|
||||
|
||||
function hide() {
|
||||
searchField.enabled = false; // Disable before hiding to prevent Wayland warnings
|
||||
launcher.isVisible = false;
|
||||
appDrawerPopout.isVisible = false;
|
||||
searchDebounceTimer.stop(); // Stop any pending search
|
||||
searchField.text = "";
|
||||
showCategories = false;
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (launcher.isVisible)
|
||||
if (appDrawerPopout.isVisible)
|
||||
hide();
|
||||
else
|
||||
show();
|
||||
@@ -207,13 +207,13 @@ PanelWindow {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.3)
|
||||
opacity: launcher.isVisible ? 1 : 0
|
||||
visible: launcher.isVisible
|
||||
opacity: appDrawerPopout.isVisible ? 1 : 0
|
||||
visible: appDrawerPopout.isVisible
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: launcher.isVisible
|
||||
onClicked: launcher.hide()
|
||||
enabled: appDrawerPopout.isVisible
|
||||
onClicked: appDrawerPopout.hide()
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -273,66 +273,15 @@ PanelWindow {
|
||||
height: 600
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusXLarge
|
||||
opacity: launcher.isVisible ? 1 : 0
|
||||
// Animated entrance with spring effect
|
||||
transform: [
|
||||
Scale {
|
||||
id: scaleTransform
|
||||
|
||||
origin.x: 0
|
||||
origin.y: 0
|
||||
xScale: launcher.isVisible ? 1 : 0.92
|
||||
yScale: launcher.isVisible ? 1 : 0.92
|
||||
|
||||
Behavior on xScale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Easing.OutBack
|
||||
easing.overshoot: 1.2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on yScale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Easing.OutBack
|
||||
easing.overshoot: 1.2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
Translate {
|
||||
id: translateTransform
|
||||
|
||||
x: launcher.isVisible ? 0 : -30
|
||||
y: launcher.isVisible ? 0 : -15
|
||||
opacity: appDrawerPopout.isVisible ? 1 : 0
|
||||
x: appDrawerPopout.isVisible ? Theme.spacingL : Theme.spacingL - Anims.slidePx
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
topMargin: Theme.barHeight + Theme.spacingXS
|
||||
leftMargin: Theme.spacingL
|
||||
}
|
||||
|
||||
// Material 3 elevation with multiple layers
|
||||
@@ -370,14 +319,14 @@ PanelWindow {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
if (launcher.isVisible)
|
||||
if (appDrawerPopout.isVisible)
|
||||
forceActiveFocus();
|
||||
|
||||
}
|
||||
// Handle keyboard shortcuts
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
launcher.hide();
|
||||
appDrawerPopout.hide();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Down) {
|
||||
selectNext();
|
||||
@@ -452,7 +401,7 @@ PanelWindow {
|
||||
leftIconFocusedColor: Theme.primary
|
||||
showClearButton: true
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
enabled: launcher.isVisible
|
||||
enabled: appDrawerPopout.isVisible
|
||||
placeholderText: "Search applications..."
|
||||
onTextEdited: {
|
||||
searchDebounceTimer.restart();
|
||||
@@ -465,9 +414,9 @@ PanelWindow {
|
||||
Prefs.addRecentApp(firstApp.desktopEntry);
|
||||
firstApp.desktopEntry.execute();
|
||||
} else {
|
||||
launcher.launchApp(firstApp.exec);
|
||||
appDrawerPopout.launchApp(firstApp.exec);
|
||||
}
|
||||
launcher.hide();
|
||||
appDrawerPopout.hide();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || (event.key === Qt.Key_Left && viewMode === "grid") || (event.key === Qt.Key_Right && viewMode === "grid") || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
||||
// Pass navigation keys and enter (when not searching) to main handler
|
||||
@@ -477,13 +426,13 @@ PanelWindow {
|
||||
|
||||
Connections {
|
||||
function onVisibleChanged() {
|
||||
if (launcher.visible)
|
||||
if (appDrawerPopout.visible)
|
||||
searchField.forceActiveFocus();
|
||||
else
|
||||
searchField.clearFocus();
|
||||
}
|
||||
|
||||
target: launcher
|
||||
target: appDrawerPopout
|
||||
}
|
||||
|
||||
}
|
||||
@@ -621,9 +570,9 @@ PanelWindow {
|
||||
Prefs.addRecentApp(modelData.desktopEntry);
|
||||
modelData.desktopEntry.execute();
|
||||
} else {
|
||||
launcher.launchApp(modelData.exec);
|
||||
appDrawerPopout.launchApp(modelData.exec);
|
||||
}
|
||||
launcher.hide();
|
||||
appDrawerPopout.hide();
|
||||
}
|
||||
onItemHovered: function(index) {
|
||||
selectedIndex = index;
|
||||
@@ -646,9 +595,9 @@ PanelWindow {
|
||||
Prefs.addRecentApp(modelData.desktopEntry);
|
||||
modelData.desktopEntry.execute();
|
||||
} else {
|
||||
launcher.launchApp(modelData.exec);
|
||||
appDrawerPopout.launchApp(modelData.exec);
|
||||
}
|
||||
launcher.hide();
|
||||
appDrawerPopout.hide();
|
||||
}
|
||||
onItemHovered: function(index) {
|
||||
selectedIndex = index;
|
||||
@@ -768,10 +717,9 @@ PanelWindow {
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,16 +54,18 @@ PanelWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: Math.min(380, parent.width - Theme.spacingL * 2)
|
||||
height: Math.min(450, parent.height - Theme.barHeight - Theme.spacingS * 2)
|
||||
x: Math.max(Theme.spacingL, parent.width - width - Theme.spacingL)
|
||||
readonly property real targetWidth: Math.min(380, Screen.width - Theme.spacingL * 2)
|
||||
readonly property real targetHeight: Math.min(450, Screen.height - Theme.barHeight - Theme.spacingS * 2)
|
||||
width: targetWidth
|
||||
height: targetHeight
|
||||
property real normalX: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
x: batteryPopupVisible ? normalX : normalX + Anims.slidePx
|
||||
y: Theme.barHeight + Theme.spacingS
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
opacity: batteryPopupVisible ? 1 : 0
|
||||
scale: batteryPopupVisible ? 1 : 0.85
|
||||
|
||||
// Prevent click-through to background
|
||||
MouseArea {
|
||||
@@ -352,8 +354,8 @@ PanelWindow {
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: profileArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (batteryControlPopup.isActiveProfile(modelData) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
|
||||
border.color: batteryControlPopup.isActiveProfile(modelData) ? Theme.primary : "transparent"
|
||||
color: profileArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (batteryPopout.isActiveProfile(modelData) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
|
||||
border.color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : "transparent"
|
||||
border.width: 2
|
||||
|
||||
Row {
|
||||
@@ -365,7 +367,7 @@ PanelWindow {
|
||||
DankIcon {
|
||||
name: Theme.getPowerProfileIcon(modelData)
|
||||
size: Theme.iconSize
|
||||
color: batteryControlPopup.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
@@ -376,8 +378,8 @@ PanelWindow {
|
||||
Text {
|
||||
text: Theme.getPowerProfileLabel(modelData)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: batteryControlPopup.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||
font.weight: batteryControlPopup.isActiveProfile(modelData) ? Font.Medium : Font.Normal
|
||||
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||
font.weight: batteryPopout.isActiveProfile(modelData) ? Font.Medium : Font.Normal
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -397,7 +399,7 @@ PanelWindow {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
batteryControlPopup.setProfile(modelData);
|
||||
batteryPopout.setProfile(modelData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,18 +463,16 @@ PanelWindow {
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,19 +7,33 @@ import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Modules.CentcomCenter
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
|
||||
readonly property bool hasActiveMedia: MprisController.activePlayer !== null
|
||||
property bool calendarVisible: false
|
||||
property bool internalVisible: false
|
||||
|
||||
visible: calendarVisible
|
||||
visible: internalVisible
|
||||
|
||||
onCalendarVisibleChanged: {
|
||||
if (calendarVisible) {
|
||||
internalVisible = true
|
||||
Qt.callLater(() => {
|
||||
// This ensures opacity changes after window is visible
|
||||
internalVisible = true // Force re-trigger if needed
|
||||
})
|
||||
} else {
|
||||
internalVisible = false
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible && CalendarService)
|
||||
CalendarService.loadCurrentMonth();
|
||||
|
||||
}
|
||||
|
||||
implicitWidth: 480
|
||||
implicitHeight: 600
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
@@ -57,24 +71,31 @@ PanelWindow {
|
||||
contentHeight += mainRowHeight + Theme.spacingM;
|
||||
// Add events widget height - use calculated height instead of actual
|
||||
if (CalendarService && CalendarService.khalAvailable) {
|
||||
let hasEvents = eventsWidget.selectedDateEvents && eventsWidget.selectedDateEvents.length > 0;
|
||||
let eventsHeight = hasEvents ? Math.min(300, 80 + eventsWidget.selectedDateEvents.length * 60) : 120;
|
||||
let hasEvents = events.selectedDateEvents && events.selectedDateEvents.length > 0;
|
||||
let eventsHeight = hasEvents ? Math.min(300, 80 + events.selectedDateEvents.length * 60) : 120;
|
||||
contentHeight += eventsHeight;
|
||||
}
|
||||
return Math.min(contentHeight, parent.height * 0.9);
|
||||
}
|
||||
|
||||
width: calculateWidth()
|
||||
readonly property real targetWidth: Math.min(Screen.width * 0.9, 600)
|
||||
width: targetWidth
|
||||
height: calculateHeight()
|
||||
x: (parent.width - width) / 2
|
||||
y: Theme.barHeight + 4
|
||||
color: Theme.surfaceContainer
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
layer.enabled: true
|
||||
opacity: calendarVisible ? 1 : 0
|
||||
scale: calendarVisible ? 1 : 0.92
|
||||
x: (Screen.width - targetWidth) / 2
|
||||
y: Theme.barHeight + 4
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
@@ -101,7 +122,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
// Update height when calendar service events change
|
||||
Connections {
|
||||
function onEventsByDateChanged() {
|
||||
mainContainer.height = mainContainer.calculateHeight();
|
||||
@@ -115,16 +135,16 @@ PanelWindow {
|
||||
enabled: CalendarService !== null
|
||||
}
|
||||
|
||||
// Update height when events widget's selectedDateEvents changes
|
||||
Connections {
|
||||
function onSelectedDateEventsChanged() {
|
||||
mainContainer.height = mainContainer.calculateHeight();
|
||||
}
|
||||
|
||||
target: eventsWidget
|
||||
enabled: eventsWidget !== null
|
||||
target: events
|
||||
enabled: events !== null
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
@@ -153,13 +173,13 @@ PanelWindow {
|
||||
visible: hasAnyWidgets
|
||||
anchors.top: parent.top
|
||||
|
||||
MediaPlayerWidget {
|
||||
MediaPlayer {
|
||||
visible: true // Always visible - shows placeholder when no media
|
||||
width: parent.width
|
||||
height: 160
|
||||
}
|
||||
|
||||
WeatherWidget {
|
||||
Weather {
|
||||
visible: true // Always visible - shows placeholder when no weather
|
||||
width: parent.width
|
||||
height: 140
|
||||
@@ -168,8 +188,8 @@ PanelWindow {
|
||||
}
|
||||
|
||||
// Right section for calendar
|
||||
CalendarWidget {
|
||||
id: calendarWidget
|
||||
CalendarGrid {
|
||||
id: calendarGrid
|
||||
|
||||
width: leftWidgets.hasAnyWidgets ? parent.width * 0.55 - Theme.spacingL : parent.width
|
||||
height: parent.height
|
||||
@@ -178,11 +198,11 @@ PanelWindow {
|
||||
}
|
||||
|
||||
// Full-width events widget below
|
||||
EventsWidget {
|
||||
id: eventsWidget
|
||||
Events {
|
||||
id: events
|
||||
|
||||
width: parent.width
|
||||
selectedDate: calendarWidget.selectedDate
|
||||
selectedDate: calendarGrid.selectedDate
|
||||
}
|
||||
|
||||
}
|
||||
@@ -196,35 +216,14 @@ PanelWindow {
|
||||
shadowOpacity: 0.15
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.longDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.longDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
enabled: calendarVisible
|
||||
onClicked: {
|
||||
calendarVisible = false;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../../Widgets"
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
@@ -10,6 +9,7 @@ import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.ControlCenter
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
@@ -48,87 +48,25 @@ PanelWindow {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: Math.min(600, Screen.width - Theme.spacingL * 2)
|
||||
readonly property real targetWidth: Math.min(600, Screen.width - Theme.spacingL * 2)
|
||||
width: targetWidth
|
||||
height: root.powerOptionsExpanded ? 570 : 500
|
||||
x: Math.max(Theme.spacingL, Screen.width - width - Theme.spacingL)
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
opacity: controlCenterVisible ? 1 : 0
|
||||
// TopBar dropdown animation - optimized for performance
|
||||
transform: [
|
||||
Scale {
|
||||
id: scaleTransform
|
||||
property real normalX: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
x: controlCenterVisible ? normalX : normalX + Anims.slidePx
|
||||
|
||||
origin.x: 600 // Use fixed width since popup is max 600px wide
|
||||
origin.y: 0
|
||||
xScale: controlCenterVisible ? 1 : 0.95
|
||||
yScale: controlCenterVisible ? 1 : 0.8
|
||||
},
|
||||
Translate {
|
||||
id: translateTransform
|
||||
|
||||
x: controlCenterVisible ? 0 : 15 // Slide slightly left when hidden
|
||||
y: controlCenterVisible ? 0 : -30
|
||||
}
|
||||
]
|
||||
// Single coordinated animation for better performance
|
||||
states: [
|
||||
State {
|
||||
name: "visible"
|
||||
when: controlCenterVisible
|
||||
|
||||
PropertyChanges {
|
||||
target: scaleTransform
|
||||
xScale: 1
|
||||
yScale: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: translateTransform
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
|
||||
},
|
||||
State {
|
||||
name: "hidden"
|
||||
when: !controlCenterVisible
|
||||
|
||||
PropertyChanges {
|
||||
target: scaleTransform
|
||||
xScale: 0.95
|
||||
yScale: 0.8
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: translateTransform
|
||||
x: 15
|
||||
y: -30
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "*"
|
||||
to: "*"
|
||||
|
||||
ParallelAnimation {
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
targets: [scaleTransform, translateTransform]
|
||||
properties: "xScale,yScale,x,y"
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
@@ -720,10 +658,9 @@ PanelWindow {
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,9 +9,10 @@ import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.ProcessList
|
||||
|
||||
PanelWindow {
|
||||
id: processListDropdown
|
||||
id: processListPopout
|
||||
|
||||
property bool isVisible: false
|
||||
property var parentWidget: null
|
||||
@@ -53,74 +54,34 @@ PanelWindow {
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: processListDropdown.hide()
|
||||
onClicked: processListPopout.hide()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: dropdownContent
|
||||
|
||||
width: Math.min(600, Screen.width - Theme.spacingL * 2)
|
||||
height: Math.min(600, Screen.height - Theme.barHeight - Theme.spacingS * 2)
|
||||
x: Math.max(Theme.spacingL, Screen.width - width - Theme.spacingL)
|
||||
readonly property real targetWidth: Math.min(600, Screen.width - Theme.spacingL * 2)
|
||||
readonly property real targetHeight: Math.min(600, Screen.height - Theme.barHeight - Theme.spacingS * 2)
|
||||
width: targetWidth
|
||||
height: targetHeight
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Theme.popupBackground()
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
clip: true
|
||||
opacity: processListDropdown.isVisible ? 1 : 0
|
||||
opacity: processListPopout.isVisible ? 1 : 0
|
||||
layer.enabled: true
|
||||
transform: [
|
||||
Scale {
|
||||
id: scaleTransform
|
||||
|
||||
origin.x: dropdownContent.width * 0.85
|
||||
origin.y: 0
|
||||
xScale: processListDropdown.isVisible ? 1 : 0.95
|
||||
yScale: processListDropdown.isVisible ? 1 : 0.8
|
||||
|
||||
Behavior on xScale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on yScale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
Translate {
|
||||
id: translateTransform
|
||||
|
||||
x: processListDropdown.isVisible ? 0 : 20
|
||||
y: processListDropdown.isVisible ? 0 : -30
|
||||
property real normalX: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||
x: processListPopout.isVisible ? normalX : normalX + Anims.slidePx
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
MouseArea {
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -157,15 +118,14 @@ PanelWindow {
|
||||
shadowVerticalOffset: 8
|
||||
shadowBlur: 1
|
||||
shadowColor: Qt.rgba(0, 0, 0, 0.15)
|
||||
shadowOpacity: processListDropdown.isVisible ? 0.15 : 0
|
||||
shadowOpacity: processListPopout.isVisible ? 0.15 : 0
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,13 +16,16 @@ ScrollView {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 200
|
||||
height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
id: systemInfoColumn
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
@@ -95,7 +98,8 @@ ScrollView {
|
||||
Text {
|
||||
text: SystemMonitorService.motherboard
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
@@ -118,7 +122,8 @@ ScrollView {
|
||||
Text {
|
||||
text: "BIOS " + SystemMonitorService.biosVersion
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
@@ -134,13 +139,16 @@ ScrollView {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: Math.max(180, diskMountRepeater.count * 28 + 100)
|
||||
height: storageColumn.implicitHeight + 2 * Theme.spacingL
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
id: storageColumn
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
|
||||
@@ -173,13 +181,6 @@ ScrollView {
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
width: parent.width
|
||||
height: Math.max(120, diskMountRepeater.count * 28 + 50)
|
||||
clip: true
|
||||
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 2
|
||||
@@ -344,6 +345,4 @@ ScrollView {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: batteryWidget
|
||||
id: battery
|
||||
|
||||
property bool batteryPopupVisible: false
|
||||
|
||||
@@ -6,7 +6,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: cpuWidget
|
||||
id: cpuMonitor
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
@@ -24,7 +24,7 @@ Rectangle {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
ProcessMonitorService.setSortBy("cpu");
|
||||
processListDropdown.toggle();
|
||||
processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: ramWidget
|
||||
id: ramMonitor
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
@@ -24,7 +24,7 @@ Rectangle {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
ProcessMonitorService.setSortBy("memory");
|
||||
processListDropdown.toggle();
|
||||
processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,9 +133,9 @@ PanelWindow {
|
||||
|
||||
LauncherButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
isActive: appLauncher.isVisible
|
||||
isActive: appDrawerPopout.isVisible
|
||||
onClicked: {
|
||||
appLauncher.toggle();
|
||||
appDrawerPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,41 +144,41 @@ PanelWindow {
|
||||
screenName: root.screenName
|
||||
}
|
||||
|
||||
FocusedAppWidget {
|
||||
FocusedApp {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: Prefs.showFocusedWindow
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ClockWidget {
|
||||
id: clockWidget
|
||||
Clock {
|
||||
id: clock
|
||||
|
||||
anchors.centerIn: parent
|
||||
onClockClicked: {
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
MediaWidget {
|
||||
Media {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: clockWidget.left
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
visible: Prefs.showMusic && MprisController.activePlayer
|
||||
onClicked: {
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
WeatherWidget {
|
||||
id: weatherWidget
|
||||
Weather {
|
||||
id: weather
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: clockWidget.right
|
||||
anchors.left: clock.right
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
visible: Prefs.showWeather && WeatherService.weather.available && WeatherService.weather.temp > 0 && WeatherService.weather.tempF > 0
|
||||
onClicked: {
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ PanelWindow {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
SystemTrayWidget {
|
||||
SystemTrayBar {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: Prefs.showSystemTray
|
||||
onMenuRequested: (menu, item, x, y) => {
|
||||
@@ -240,12 +240,12 @@ PanelWindow {
|
||||
}
|
||||
|
||||
// System Monitor Widgets
|
||||
CpuMonitorWidget {
|
||||
CpuMonitor {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: Prefs.showSystemResources
|
||||
}
|
||||
|
||||
RamMonitorWidget {
|
||||
RamMonitor {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: Prefs.showSystemResources
|
||||
}
|
||||
@@ -260,11 +260,11 @@ PanelWindow {
|
||||
}
|
||||
|
||||
// Battery Widget
|
||||
BatteryWidget {
|
||||
Battery {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
batteryPopupVisible: batteryControlPopup.batteryPopupVisible
|
||||
batteryPopupVisible: batteryPopout.batteryPopupVisible
|
||||
onToggleBatteryPopup: {
|
||||
batteryControlPopup.batteryPopupVisible = !batteryControlPopup.batteryPopupVisible;
|
||||
batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,10 +272,10 @@ PanelWindow {
|
||||
// Bluetooth devices are automatically updated via signals
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
isActive: controlCenter.controlCenterVisible
|
||||
isActive: controlCenterPopout.controlCenterVisible
|
||||
onClicked: {
|
||||
controlCenter.controlCenterVisible = !controlCenter.controlCenterVisible;
|
||||
if (controlCenter.controlCenterVisible) {
|
||||
controlCenterPopout.controlCenterVisible = !controlCenterPopout.controlCenterVisible;
|
||||
if (controlCenterPopout.controlCenterVisible) {
|
||||
if (NetworkService.wifiEnabled)
|
||||
WifiService.scanWifi();
|
||||
|
||||
|
||||
38
Widgets/DankSystemLogo.qml
Normal file
38
Widgets/DankSystemLogo.qml
Normal file
@@ -0,0 +1,38 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
|
||||
IconImage {
|
||||
id: root
|
||||
|
||||
property string colorOverride: ""
|
||||
property real brightnessOverride: 0.5
|
||||
property real contrastOverride: 1
|
||||
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
layer.enabled: colorOverride !== ""
|
||||
|
||||
Process {
|
||||
running: true
|
||||
command: ["sh", "-c", ". /etc/os-release && echo $LOGO"]
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: () => {
|
||||
root.source = Quickshell.iconPath(this.text.trim());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
colorization: 1
|
||||
colorizationColor: colorOverride
|
||||
brightness: brightnessOverride
|
||||
contrast: contrastOverride
|
||||
}
|
||||
|
||||
}
|
||||
56
Widgets/SlideFadeBehavior.qml
Normal file
56
Widgets/SlideFadeBehavior.qml
Normal file
@@ -0,0 +1,56 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property Item target
|
||||
property int direction: Anims.direction.fadeOnly
|
||||
|
||||
function show() { _apply(true) }
|
||||
function hide() { _apply(false) }
|
||||
|
||||
function _apply(showing) {
|
||||
const off = Anims.slidePx
|
||||
let fromX = 0
|
||||
let toX = 0
|
||||
switch(direction) {
|
||||
case Anims.direction.fromLeft: fromX = -off; toX = 0; break
|
||||
case Anims.direction.fromRight: fromX = off; toX = 0; break
|
||||
default: fromX = 0; toX = 0;
|
||||
}
|
||||
|
||||
if (showing) {
|
||||
target.x = fromX
|
||||
target.opacity = 0
|
||||
target.visible = true
|
||||
animX.from = fromX; animX.to = toX
|
||||
animO.from = 0; animO.to = 1
|
||||
} else {
|
||||
animX.from = target.x; animX.to = (direction === Anims.direction.fromLeft ? -off :
|
||||
direction === Anims.direction.fromRight ? off : 0)
|
||||
animO.from = target.opacity; animO.to = 0
|
||||
}
|
||||
seq.restart()
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: seq
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
id: animX
|
||||
target: root.target
|
||||
property: "x"
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
id: animO
|
||||
target: root.target
|
||||
property: "opacity"
|
||||
duration: Anims.durShort
|
||||
}
|
||||
}
|
||||
ScriptAction { script: if (root.target.opacity === 0) root.target.visible = false }
|
||||
}
|
||||
}
|
||||
46
shell.qml
46
shell.qml
@@ -8,6 +8,8 @@ import qs.Modules.Settings
|
||||
import qs.Modules.TopBar
|
||||
import qs.Modules.ProcessList
|
||||
import qs.Modules.ControlCenter.Network
|
||||
import qs.Modules.Popouts
|
||||
import qs.Modals
|
||||
|
||||
ShellRoot {
|
||||
id: root
|
||||
@@ -23,8 +25,8 @@ ShellRoot {
|
||||
}
|
||||
|
||||
// Global popup windows
|
||||
CentcomCenter {
|
||||
id: centcomCenter
|
||||
CentcomPopout {
|
||||
id: centcomPopout
|
||||
}
|
||||
|
||||
TrayMenuPopup {
|
||||
@@ -39,38 +41,38 @@ ShellRoot {
|
||||
id: notificationPopup
|
||||
}
|
||||
|
||||
ControlCenter {
|
||||
id: controlCenter
|
||||
ControlCenterPopout {
|
||||
id: controlCenterPopout
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
powerConfirmDialog.powerConfirmAction = action;
|
||||
powerConfirmDialog.powerConfirmTitle = title;
|
||||
powerConfirmDialog.powerConfirmMessage = message;
|
||||
powerConfirmDialog.powerConfirmVisible = true;
|
||||
powerConfirmModal.powerConfirmAction = action;
|
||||
powerConfirmModal.powerConfirmTitle = title;
|
||||
powerConfirmModal.powerConfirmMessage = message;
|
||||
powerConfirmModal.powerConfirmVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
WifiPasswordDialog {
|
||||
id: wifiPasswordDialog
|
||||
WifiPasswordModal {
|
||||
id: wifiPasswordModal
|
||||
}
|
||||
|
||||
NetworkInfoDialog {
|
||||
id: networkInfoDialog
|
||||
NetworkInfoModal {
|
||||
id: networkInfoModal
|
||||
}
|
||||
|
||||
BatteryControlPopup {
|
||||
id: batteryControlPopup
|
||||
BatteryPopout {
|
||||
id: batteryPopout
|
||||
}
|
||||
|
||||
PowerMenuPopup {
|
||||
id: powerMenuPopup
|
||||
}
|
||||
|
||||
PowerConfirmDialog {
|
||||
id: powerConfirmDialog
|
||||
PowerConfirmModal {
|
||||
id: powerConfirmModal
|
||||
}
|
||||
|
||||
ProcessListDropdown {
|
||||
id: processListDropdown
|
||||
ProcessListPopout {
|
||||
id: processListPopout
|
||||
}
|
||||
|
||||
SettingsModal {
|
||||
@@ -79,12 +81,12 @@ ShellRoot {
|
||||
|
||||
|
||||
// Application and clipboard components
|
||||
AppLauncher {
|
||||
id: appLauncher
|
||||
AppDrawerPopout {
|
||||
id: appDrawerPopout
|
||||
}
|
||||
|
||||
SpotlightLauncher {
|
||||
id: spotlightLauncher
|
||||
SpotlightModal {
|
||||
id: spotlightModal
|
||||
}
|
||||
|
||||
ProcessListModal {
|
||||
|
||||
Reference in New Issue
Block a user