mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
refactors: more DankModals, remove GlobalDropdown and InputDialog
This commit is contained in:
@@ -84,7 +84,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
├── Modules/ # UI components
|
||||
│ ├── TopBar.qml
|
||||
│ ├── AppLauncher.qml
|
||||
│ ├── ControlCenterPopup.qml
|
||||
│ ├── ControlCenter.qml
|
||||
│ └── [18 total modules]
|
||||
└── Widgets/ # Reusable UI controls
|
||||
├── DankIcon.qml
|
||||
@@ -115,7 +115,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
- Services handle system commands, state management, and hardware integration
|
||||
|
||||
4. **Modules/** - UI components
|
||||
- **Full-screen components**: AppLauncher, ClipboardHistory, ControlCenterPopup
|
||||
- **Full-screen components**: AppLauncher, ClipboardHistory, ControlCenter
|
||||
- **Panel components**: TopBar, SystemTrayWidget, NotificationPopup
|
||||
- **Layout components**: WorkspaceSwitcher
|
||||
|
||||
@@ -158,7 +158,7 @@ shell.qml # Main entry point (minimal orchestration)
|
||||
|
||||
### Important Components
|
||||
|
||||
- **ControlCenterPopup**: System controls (WiFi, Bluetooth, brightness, volume, night mode)
|
||||
- **ControlCenter**: System controls (WiFi, Bluetooth, brightness, volume, night mode)
|
||||
- **AppLauncher**: Full-featured app grid/list with 93+ applications, search, categories
|
||||
- **ClipboardHistory**: Complete clipboard management with cliphist integration
|
||||
- **TopBar**: Per-monitor panels with workspace switching, clock, system tray
|
||||
|
||||
@@ -317,7 +317,10 @@ Rectangle {
|
||||
MouseArea {
|
||||
id: progressGlobalMouseArea
|
||||
|
||||
anchors.fill: parent.parent.parent // Fill the entire media player widget
|
||||
x: 0
|
||||
y: 0
|
||||
width: mediaPlayerWidget.width
|
||||
height: mediaPlayerWidget.height
|
||||
enabled: progressMouseArea.isSeeking
|
||||
visible: false
|
||||
preventStealing: true
|
||||
@@ -192,7 +192,10 @@ Item {
|
||||
MouseArea {
|
||||
id: volumeGlobalMouseArea
|
||||
|
||||
anchors.fill: parent.parent.parent.parent.parent // Fill the entire control center
|
||||
x: 0
|
||||
y: 0
|
||||
width: audioTab.width
|
||||
height: audioTab.height
|
||||
enabled: volumeMouseArea.isDragging
|
||||
visible: false
|
||||
preventStealing: true
|
||||
@@ -514,7 +517,10 @@ Item {
|
||||
MouseArea {
|
||||
id: micGlobalMouseArea
|
||||
|
||||
anchors.fill: parent.parent.parent.parent.parent // Fill the entire control center
|
||||
x: 0
|
||||
y: 0
|
||||
width: audioTab.width
|
||||
height: audioTab.height
|
||||
enabled: micMouseArea.isDragging
|
||||
visible: false
|
||||
preventStealing: true
|
||||
|
||||
@@ -364,7 +364,7 @@ PanelWindow {
|
||||
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||
onClicked: {
|
||||
controlCenterVisible = false;
|
||||
settingsPopup.settingsVisible = true;
|
||||
settingsModal.settingsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
id: globalDropdownWindow
|
||||
|
||||
property var sourceComponent: null
|
||||
property var options: []
|
||||
property string currentValue: ""
|
||||
property int targetX: 0
|
||||
property int targetY: 0
|
||||
signal valueSelected(string value)
|
||||
|
||||
visible: sourceComponent !== null
|
||||
implicitWidth: 180
|
||||
implicitHeight: Math.min(200, options.length * 36 + 16)
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
WlrLayershell.margins {
|
||||
top: targetY
|
||||
left: targetX
|
||||
}
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
}
|
||||
color: "transparent"
|
||||
|
||||
function showAt(component, globalX, globalY, opts, current) {
|
||||
sourceComponent = component;
|
||||
options = opts;
|
||||
currentValue = current;
|
||||
|
||||
// Set the target position using margins
|
||||
targetX = globalX;
|
||||
targetY = globalY;
|
||||
|
||||
visible = true;
|
||||
}
|
||||
|
||||
function hide() {
|
||||
sourceComponent = null;
|
||||
visible = false;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1.0)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||
border.width: 1
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingS
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
model: globalDropdownWindow.options
|
||||
spacing: 2
|
||||
|
||||
delegate: Rectangle {
|
||||
width: ListView.view.width
|
||||
height: 32
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: optionArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: modelData
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: globalDropdownWindow.currentValue === modelData ? Theme.primary : Theme.surfaceText
|
||||
font.weight: globalDropdownWindow.currentValue === modelData ? Font.Medium : Font.Normal
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: optionArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
globalDropdownWindow.valueSelected(modelData);
|
||||
globalDropdownWindow.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close on click outside
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
onClicked: globalDropdownWindow.hide()
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: inputDialog
|
||||
|
||||
property bool dialogVisible: false
|
||||
property string dialogTitle: "Input Required"
|
||||
property string dialogSubtitle: "Please enter the required information"
|
||||
property string inputPlaceholder: "Enter text"
|
||||
property string inputValue: ""
|
||||
property bool isPassword: false
|
||||
property string confirmButtonText: "Confirm"
|
||||
property string cancelButtonText: "Cancel"
|
||||
|
||||
signal confirmed(string value)
|
||||
signal cancelled()
|
||||
|
||||
function showDialog(title, subtitle, placeholder, isPass, confirmText, cancelText) {
|
||||
dialogTitle = title || "Input Required";
|
||||
dialogSubtitle = subtitle || "Please enter the required information";
|
||||
inputPlaceholder = placeholder || "Enter text";
|
||||
isPassword = isPass || false;
|
||||
confirmButtonText = confirmText || "Confirm";
|
||||
cancelButtonText = cancelText || "Cancel";
|
||||
inputValue = "";
|
||||
dialogVisible = true;
|
||||
}
|
||||
|
||||
function hideDialog() {
|
||||
textInput.enabled = false; // Disable before hiding to prevent Wayland warnings
|
||||
dialogVisible = false;
|
||||
inputValue = "";
|
||||
}
|
||||
|
||||
visible: dialogVisible
|
||||
width: 380
|
||||
height: 190
|
||||
keyboardFocus: "ondemand"
|
||||
|
||||
onOpened: {
|
||||
textInput.forceActiveFocus()
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
textInput.enabled = true;
|
||||
} else {
|
||||
textInput.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
onBackgroundClicked: {
|
||||
hideDialog();
|
||||
cancelled();
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Text {
|
||||
text: dialogTitle
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: dialogSubtitle
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: textInput
|
||||
width: parent.width
|
||||
placeholderText: inputPlaceholder
|
||||
text: inputValue
|
||||
echoMode: isPassword ? TextInput.Password : TextInput.Normal
|
||||
onTextChanged: inputValue = text
|
||||
onAccepted: {
|
||||
hideDialog();
|
||||
confirmed(text);
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: cancelButton.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
|
||||
Text {
|
||||
text: cancelButtonText
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelButton
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
hideDialog();
|
||||
cancelled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: confirmButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.9) : Theme.primary
|
||||
|
||||
Text {
|
||||
text: confirmButtonText
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.primaryText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: confirmButton
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
hideDialog();
|
||||
confirmed(textInput.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
DankModal {
|
||||
id: root
|
||||
|
||||
property bool networkInfoDialogVisible: false
|
||||
@@ -16,12 +15,6 @@ PanelWindow {
|
||||
property var networkData: null
|
||||
property string networkDetails: ""
|
||||
|
||||
visible: networkInfoDialogVisible
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: networkInfoDialogVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
color: "transparent"
|
||||
|
||||
function showNetworkInfo(ssid, data) {
|
||||
networkSSID = ssid;
|
||||
networkData = data;
|
||||
@@ -36,43 +29,24 @@ PanelWindow {
|
||||
networkDetails = "";
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
visible: networkInfoDialogVisible
|
||||
width: 600
|
||||
height: 500
|
||||
enableShadow: true
|
||||
onBackgroundClicked: {
|
||||
hideDialog();
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
networkSSID = "";
|
||||
networkData = null;
|
||||
networkDetails = "";
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.5)
|
||||
opacity: networkInfoDialogVisible ? 1 : 0
|
||||
|
||||
MouseArea {
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.hideDialog();
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: Math.min(600, parent.width - Theme.spacingL * 2)
|
||||
height: Math.min(500, parent.height - Theme.spacingL * 2)
|
||||
anchors.centerIn: parent
|
||||
color: Theme.surfaceContainer
|
||||
radius: Theme.cornerRadiusLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
border.width: 1
|
||||
opacity: networkInfoDialogVisible ? 1 : 0
|
||||
scale: networkInfoDialogVisible ? 1 : 0.9
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
@@ -101,6 +75,7 @@ PanelWindow {
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
@@ -112,6 +87,7 @@ PanelWindow {
|
||||
root.hideDialog();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Network Details
|
||||
@@ -128,6 +104,7 @@ PanelWindow {
|
||||
|
||||
Rectangle {
|
||||
id: detailsRect
|
||||
|
||||
width: parent.width
|
||||
height: Math.max(parent.parent.height, detailsText.contentHeight + Theme.spacingM * 2)
|
||||
radius: Theme.cornerRadius
|
||||
@@ -137,6 +114,7 @@ PanelWindow {
|
||||
|
||||
Text {
|
||||
id: detailsText
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
text: WifiService.networkInfoDetails.replace(/\\n/g, '\n') || "No information available"
|
||||
@@ -145,8 +123,11 @@ PanelWindow {
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 1.5
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Close Button
|
||||
@@ -164,6 +145,7 @@ PanelWindow {
|
||||
|
||||
Text {
|
||||
id: closeText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Close"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -173,6 +155,7 @@ PanelWindow {
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -186,23 +169,15 @@ PanelWindow {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,15 +10,14 @@ import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
id: processListPopup
|
||||
DankModal {
|
||||
id: processListModal
|
||||
|
||||
property bool isVisible: false
|
||||
property int currentTab: 0
|
||||
property var tabNames: ["Processes", "Performance", "System"]
|
||||
|
||||
function show() {
|
||||
processListPopup.isVisible = true;
|
||||
processListModal.visible = true;
|
||||
ProcessMonitorService.updateSystemInfo();
|
||||
ProcessMonitorService.updateProcessList();
|
||||
SystemMonitorService.enableDetailedMonitoring(true);
|
||||
@@ -27,82 +26,38 @@ PanelWindow {
|
||||
}
|
||||
|
||||
function hide() {
|
||||
processListPopup.isVisible = false;
|
||||
processListModal.visible = false;
|
||||
SystemMonitorService.enableDetailedMonitoring(false);
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (processListPopup.isVisible)
|
||||
if (processListModal.visible)
|
||||
hide();
|
||||
else
|
||||
show();
|
||||
}
|
||||
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: isVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
WlrLayershell.namespace: "quickshell-processlist"
|
||||
visible: isVisible
|
||||
color: "transparent"
|
||||
onIsVisibleChanged: {
|
||||
ProcessMonitorService.enableMonitoring(isVisible);
|
||||
width: 900
|
||||
height: 680
|
||||
visible: false
|
||||
keyboardFocus: "exclusive"
|
||||
backgroundColor: Theme.popupBackground()
|
||||
cornerRadius: Theme.cornerRadiusXLarge
|
||||
enableShadow: true
|
||||
|
||||
onVisibleChanged: {
|
||||
ProcessMonitorService.enableMonitoring(visible);
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.4)
|
||||
opacity: processListPopup.isVisible ? 1 : 0
|
||||
visible: processListPopup.isVisible
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: processListPopup.isVisible
|
||||
onClicked: processListPopup.hide()
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: mainContainer
|
||||
|
||||
width: 900
|
||||
height: 680
|
||||
anchors.centerIn: parent
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusXLarge
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
layer.enabled: true
|
||||
opacity: processListPopup.isVisible ? 1 : 0
|
||||
scale: processListPopup.isVisible ? 1 : 0.96
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
onBackgroundClicked: hide()
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
processListPopup.hide();
|
||||
processListModal.hide();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_1) {
|
||||
currentTab = 0;
|
||||
@@ -315,34 +270,7 @@ PanelWindow {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 8
|
||||
shadowBlur: 1
|
||||
shadowColor: Qt.rgba(0, 0, 0, 0.3)
|
||||
shadowOpacity: 0.3
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
@@ -370,17 +298,17 @@ PanelWindow {
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
processListPopup.show();
|
||||
processListModal.show();
|
||||
return "PROCESSLIST_OPEN_SUCCESS";
|
||||
}
|
||||
|
||||
function close() {
|
||||
processListPopup.hide();
|
||||
processListModal.hide();
|
||||
return "PROCESSLIST_CLOSE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
processListPopup.toggle();
|
||||
processListModal.toggle();
|
||||
return "PROCESSLIST_TOGGLE_SUCCESS";
|
||||
}
|
||||
|
||||
@@ -4,18 +4,15 @@ import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: settingsPopup
|
||||
id: settingsModal
|
||||
|
||||
property bool settingsVisible: false
|
||||
|
||||
signal closingPopup()
|
||||
signal closingModal()
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
closingPopup();
|
||||
if (typeof globalDropdownWindow !== 'undefined') {
|
||||
globalDropdownWindow.hide();
|
||||
}
|
||||
closingModal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +65,7 @@ DankModal {
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||
onClicked: settingsPopup.settingsVisible = false
|
||||
onClicked: settingsModal.settingsVisible = false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -140,8 +137,8 @@ DankModal {
|
||||
// Keyboard focus and shortcuts
|
||||
FocusScope {
|
||||
anchors.fill: parent
|
||||
focus: settingsPopup.settingsVisible
|
||||
Keys.onEscapePressed: settingsPopup.settingsVisible = false
|
||||
focus: settingsModal.settingsVisible
|
||||
Keys.onEscapePressed: settingsModal.settingsVisible = false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -242,24 +242,6 @@ DankModal {
|
||||
id: filteredModel
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onReadyChanged() {
|
||||
if (AppSearchService.ready) {
|
||||
var allCategories = AppSearchService.getAllCategories().filter((cat) => {
|
||||
return cat !== "Education" && cat !== "Science";
|
||||
});
|
||||
// Insert "Recents" after "All"
|
||||
var result = ["All", "Recents"];
|
||||
categories = result.concat(allCategories.filter((cat) => {
|
||||
return cat !== "All";
|
||||
}));
|
||||
if (spotlightOpen)
|
||||
updateFilteredApps();
|
||||
}
|
||||
}
|
||||
target: AppSearchService
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -157,7 +157,7 @@ PanelWindow {
|
||||
|
||||
anchors.centerIn: parent
|
||||
onClockClicked: {
|
||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ PanelWindow {
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
visible: Prefs.showMusic && MprisController.activePlayer
|
||||
onClicked: {
|
||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ PanelWindow {
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
visible: Prefs.showWeather && WeatherService.weather.available && WeatherService.weather.temp > 0 && WeatherService.weather.tempF > 0
|
||||
onClicked: {
|
||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
||||
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,10 +273,10 @@ PanelWindow {
|
||||
// Bluetooth devices are automatically updated via signals
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
isActive: controlCenterPopup.controlCenterVisible
|
||||
isActive: controlCenter.controlCenterVisible
|
||||
onClicked: {
|
||||
controlCenterPopup.controlCenterVisible = !controlCenterPopup.controlCenterVisible;
|
||||
if (controlCenterPopup.controlCenterVisible) {
|
||||
controlCenter.controlCenterVisible = !controlCenter.controlCenterVisible;
|
||||
if (controlCenter.controlCenterVisible) {
|
||||
if (NetworkService.wifiEnabled)
|
||||
WifiService.scanWifi();
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
@@ -84,19 +87,110 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (typeof globalDropdownWindow !== 'undefined') {
|
||||
// Get global position of the dropdown button
|
||||
var globalPos = dropdown.mapToGlobal(0, 0);
|
||||
globalDropdownWindow.showAt(root, globalPos.x, globalPos.y + dropdown.height + 4, root.options, root.currentValue);
|
||||
|
||||
// Connect to value selection (with cleanup)
|
||||
globalDropdownWindow.valueSelected.connect(function(value) {
|
||||
root.currentValue = value;
|
||||
root.valueChanged(value);
|
||||
});
|
||||
onPressed: (mouse) => {
|
||||
mouse.accepted = true;
|
||||
if (!dropdownMenu.visible) {
|
||||
dropdownMenu.updatePosition();
|
||||
dropdownMenu.visible = true;
|
||||
} else {
|
||||
dropdownMenu.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Integrated dropdown menu with full-screen overlay
|
||||
PanelWindow {
|
||||
id: dropdownMenu
|
||||
|
||||
property int targetX: 0
|
||||
property int targetY: 0
|
||||
|
||||
visible: false
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
color: "transparent"
|
||||
|
||||
function updatePosition() {
|
||||
var globalPos = dropdown.mapToGlobal(0, 0);
|
||||
targetX = globalPos.x;
|
||||
targetY = globalPos.y + dropdown.height + 4;
|
||||
}
|
||||
|
||||
// Background click interceptor (invisible)
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
onPressed: {
|
||||
dropdownMenu.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Dropdown menu content
|
||||
Rectangle {
|
||||
x: dropdownMenu.targetX
|
||||
y: dropdownMenu.targetY
|
||||
width: 180
|
||||
height: Math.min(200, root.options.length * 36 + 16)
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1.0)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
|
||||
border.width: 1
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingS
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
model: root.options
|
||||
spacing: 2
|
||||
|
||||
delegate: Rectangle {
|
||||
width: ListView.view.width
|
||||
height: 32
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: optionArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: modelData
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: root.currentValue === modelData ? Theme.primary : Theme.surfaceText
|
||||
font.weight: root.currentValue === modelData ? Font.Medium : Font.Normal
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: optionArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
root.currentValue = modelData;
|
||||
root.valueChanged(modelData);
|
||||
dropdownMenu.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Global keyboard handler for escape key
|
||||
Keys.onEscapePressed: {
|
||||
if (dropdownMenu.visible) {
|
||||
dropdownMenu.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
shell.qml
25
shell.qml
@@ -2,7 +2,7 @@
|
||||
|
||||
import Quickshell
|
||||
import qs.Modules
|
||||
import qs.Modules.CenterCommandCenter
|
||||
import qs.Modules.CentcomCenter
|
||||
import qs.Modules.ControlCenter
|
||||
import qs.Modules.Settings
|
||||
import qs.Modules.TopBar
|
||||
@@ -22,8 +22,8 @@ ShellRoot {
|
||||
}
|
||||
|
||||
// Global popup windows
|
||||
CenterCommandCenter {
|
||||
id: centerCommandCenter
|
||||
CentcomCenter {
|
||||
id: centcomCenter
|
||||
}
|
||||
|
||||
TrayMenuPopup {
|
||||
@@ -38,8 +38,8 @@ ShellRoot {
|
||||
id: notificationPopup
|
||||
}
|
||||
|
||||
ControlCenterPopup {
|
||||
id: controlCenterPopup
|
||||
ControlCenter {
|
||||
id: controlCenter
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
powerConfirmDialog.powerConfirmAction = action;
|
||||
powerConfirmDialog.powerConfirmTitle = title;
|
||||
@@ -56,10 +56,6 @@ ShellRoot {
|
||||
id: networkInfoDialog
|
||||
}
|
||||
|
||||
InputDialog {
|
||||
id: globalInputDialog
|
||||
}
|
||||
|
||||
BatteryControlPopup {
|
||||
id: batteryControlPopup
|
||||
}
|
||||
@@ -76,13 +72,10 @@ ShellRoot {
|
||||
id: processListDropdown
|
||||
}
|
||||
|
||||
SettingsPopup {
|
||||
id: settingsPopup
|
||||
SettingsModal {
|
||||
id: settingsModal
|
||||
}
|
||||
|
||||
GlobalDropdown {
|
||||
id: globalDropdownWindow
|
||||
}
|
||||
|
||||
// Application and clipboard components
|
||||
AppLauncher {
|
||||
@@ -93,8 +86,8 @@ ShellRoot {
|
||||
id: spotlightLauncher
|
||||
}
|
||||
|
||||
ProcessListPopup {
|
||||
id: processListPopup
|
||||
ProcessListModal {
|
||||
id: processListModal
|
||||
}
|
||||
|
||||
ClipboardHistory {
|
||||
|
||||
Reference in New Issue
Block a user