mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-28 07:22:50 -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
|
├── Modules/ # UI components
|
||||||
│ ├── TopBar.qml
|
│ ├── TopBar.qml
|
||||||
│ ├── AppLauncher.qml
|
│ ├── AppLauncher.qml
|
||||||
│ ├── ControlCenterPopup.qml
|
│ ├── ControlCenter.qml
|
||||||
│ └── [18 total modules]
|
│ └── [18 total modules]
|
||||||
└── Widgets/ # Reusable UI controls
|
└── Widgets/ # Reusable UI controls
|
||||||
├── DankIcon.qml
|
├── DankIcon.qml
|
||||||
@@ -115,7 +115,7 @@ shell.qml # Main entry point (minimal orchestration)
|
|||||||
- Services handle system commands, state management, and hardware integration
|
- Services handle system commands, state management, and hardware integration
|
||||||
|
|
||||||
4. **Modules/** - UI components
|
4. **Modules/** - UI components
|
||||||
- **Full-screen components**: AppLauncher, ClipboardHistory, ControlCenterPopup
|
- **Full-screen components**: AppLauncher, ClipboardHistory, ControlCenter
|
||||||
- **Panel components**: TopBar, SystemTrayWidget, NotificationPopup
|
- **Panel components**: TopBar, SystemTrayWidget, NotificationPopup
|
||||||
- **Layout components**: WorkspaceSwitcher
|
- **Layout components**: WorkspaceSwitcher
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ shell.qml # Main entry point (minimal orchestration)
|
|||||||
|
|
||||||
### Important Components
|
### 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
|
- **AppLauncher**: Full-featured app grid/list with 93+ applications, search, categories
|
||||||
- **ClipboardHistory**: Complete clipboard management with cliphist integration
|
- **ClipboardHistory**: Complete clipboard management with cliphist integration
|
||||||
- **TopBar**: Per-monitor panels with workspace switching, clock, system tray
|
- **TopBar**: Per-monitor panels with workspace switching, clock, system tray
|
||||||
|
|||||||
@@ -317,7 +317,10 @@ Rectangle {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: progressGlobalMouseArea
|
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
|
enabled: progressMouseArea.isSeeking
|
||||||
visible: false
|
visible: false
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
@@ -192,7 +192,10 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: volumeGlobalMouseArea
|
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
|
enabled: volumeMouseArea.isDragging
|
||||||
visible: false
|
visible: false
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
@@ -514,7 +517,10 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: micGlobalMouseArea
|
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
|
enabled: micMouseArea.isDragging
|
||||||
visible: false
|
visible: false
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ PanelWindow {
|
|||||||
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||||
onClicked: {
|
onClicked: {
|
||||||
controlCenterVisible = false;
|
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
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
import Quickshell.Widgets
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
PanelWindow {
|
DankModal {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool networkInfoDialogVisible: false
|
property bool networkInfoDialogVisible: false
|
||||||
@@ -16,12 +15,6 @@ PanelWindow {
|
|||||||
property var networkData: null
|
property var networkData: null
|
||||||
property string networkDetails: ""
|
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) {
|
function showNetworkInfo(ssid, data) {
|
||||||
networkSSID = ssid;
|
networkSSID = ssid;
|
||||||
networkData = data;
|
networkData = data;
|
||||||
@@ -36,43 +29,24 @@ PanelWindow {
|
|||||||
networkDetails = "";
|
networkDetails = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors {
|
visible: networkInfoDialogVisible
|
||||||
top: true
|
width: 600
|
||||||
left: true
|
height: 500
|
||||||
right: true
|
enableShadow: true
|
||||||
bottom: true
|
onBackgroundClicked: {
|
||||||
|
hideDialog();
|
||||||
|
}
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
networkSSID = "";
|
||||||
|
networkData = null;
|
||||||
|
networkDetails = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
content: Component {
|
||||||
anchors.fill: parent
|
Item {
|
||||||
color: Qt.rgba(0, 0, 0, 0.5)
|
|
||||||
opacity: networkInfoDialogVisible ? 1 : 0
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
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 {
|
Column {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -101,6 +75,7 @@ PanelWindow {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
@@ -112,6 +87,7 @@ PanelWindow {
|
|||||||
root.hideDialog();
|
root.hideDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network Details
|
// Network Details
|
||||||
@@ -128,6 +104,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: detailsRect
|
id: detailsRect
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Math.max(parent.parent.height, detailsText.contentHeight + Theme.spacingM * 2)
|
height: Math.max(parent.parent.height, detailsText.contentHeight + Theme.spacingM * 2)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
@@ -137,6 +114,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: detailsText
|
id: detailsText
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
text: WifiService.networkInfoDetails.replace(/\\n/g, '\n') || "No information available"
|
text: WifiService.networkInfoDetails.replace(/\\n/g, '\n') || "No information available"
|
||||||
@@ -145,8 +123,11 @@ PanelWindow {
|
|||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
lineHeight: 1.5
|
lineHeight: 1.5
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Button
|
// Close Button
|
||||||
@@ -164,6 +145,7 @@ PanelWindow {
|
|||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: closeText
|
id: closeText
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Close"
|
text: "Close"
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
@@ -173,6 +155,7 @@ PanelWindow {
|
|||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: closeArea
|
id: closeArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
@@ -186,23 +169,15 @@ PanelWindow {
|
|||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
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.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
PanelWindow {
|
DankModal {
|
||||||
id: processListPopup
|
id: processListModal
|
||||||
|
|
||||||
property bool isVisible: false
|
|
||||||
property int currentTab: 0
|
property int currentTab: 0
|
||||||
property var tabNames: ["Processes", "Performance", "System"]
|
property var tabNames: ["Processes", "Performance", "System"]
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
processListPopup.isVisible = true;
|
processListModal.visible = true;
|
||||||
ProcessMonitorService.updateSystemInfo();
|
ProcessMonitorService.updateSystemInfo();
|
||||||
ProcessMonitorService.updateProcessList();
|
ProcessMonitorService.updateProcessList();
|
||||||
SystemMonitorService.enableDetailedMonitoring(true);
|
SystemMonitorService.enableDetailedMonitoring(true);
|
||||||
@@ -27,82 +26,38 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
processListPopup.isVisible = false;
|
processListModal.visible = false;
|
||||||
SystemMonitorService.enableDetailedMonitoring(false);
|
SystemMonitorService.enableDetailedMonitoring(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
if (processListPopup.isVisible)
|
if (processListModal.visible)
|
||||||
hide();
|
hide();
|
||||||
else
|
else
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
WlrLayershell.layer: WlrLayershell.Overlay
|
width: 900
|
||||||
WlrLayershell.exclusiveZone: -1
|
height: 680
|
||||||
WlrLayershell.keyboardFocus: isVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
visible: false
|
||||||
WlrLayershell.namespace: "quickshell-processlist"
|
keyboardFocus: "exclusive"
|
||||||
visible: isVisible
|
backgroundColor: Theme.popupBackground()
|
||||||
color: "transparent"
|
cornerRadius: Theme.cornerRadiusXLarge
|
||||||
onIsVisibleChanged: {
|
enableShadow: true
|
||||||
ProcessMonitorService.enableMonitoring(isVisible);
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
ProcessMonitorService.enableMonitoring(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors {
|
onBackgroundClicked: hide()
|
||||||
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: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
content: Component {
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
Keys.onPressed: function(event) {
|
Keys.onPressed: function(event) {
|
||||||
if (event.key === Qt.Key_Escape) {
|
if (event.key === Qt.Key_Escape) {
|
||||||
processListPopup.hide();
|
processListModal.hide();
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
} else if (event.key === Qt.Key_1) {
|
} else if (event.key === Qt.Key_1) {
|
||||||
currentTab = 0;
|
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 {
|
Component {
|
||||||
@@ -370,17 +298,17 @@ PanelWindow {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function open() {
|
function open() {
|
||||||
processListPopup.show();
|
processListModal.show();
|
||||||
return "PROCESSLIST_OPEN_SUCCESS";
|
return "PROCESSLIST_OPEN_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
processListPopup.hide();
|
processListModal.hide();
|
||||||
return "PROCESSLIST_CLOSE_SUCCESS";
|
return "PROCESSLIST_CLOSE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
processListPopup.toggle();
|
processListModal.toggle();
|
||||||
return "PROCESSLIST_TOGGLE_SUCCESS";
|
return "PROCESSLIST_TOGGLE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4,18 +4,15 @@ import qs.Common
|
|||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
DankModal {
|
DankModal {
|
||||||
id: settingsPopup
|
id: settingsModal
|
||||||
|
|
||||||
property bool settingsVisible: false
|
property bool settingsVisible: false
|
||||||
|
|
||||||
signal closingPopup()
|
signal closingModal()
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
closingPopup();
|
closingModal();
|
||||||
if (typeof globalDropdownWindow !== 'undefined') {
|
|
||||||
globalDropdownWindow.hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +65,7 @@ DankModal {
|
|||||||
iconSize: Theme.iconSize - 4
|
iconSize: Theme.iconSize - 4
|
||||||
iconColor: Theme.surfaceText
|
iconColor: Theme.surfaceText
|
||||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
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
|
// Keyboard focus and shortcuts
|
||||||
FocusScope {
|
FocusScope {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: settingsPopup.settingsVisible
|
focus: settingsModal.settingsVisible
|
||||||
Keys.onEscapePressed: settingsPopup.settingsVisible = false
|
Keys.onEscapePressed: settingsModal.settingsVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -242,24 +242,6 @@ DankModal {
|
|||||||
id: filteredModel
|
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 {
|
content: Component {
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ PanelWindow {
|
|||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
onClockClicked: {
|
onClockClicked: {
|
||||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ PanelWindow {
|
|||||||
anchors.rightMargin: Theme.spacingS
|
anchors.rightMargin: Theme.spacingS
|
||||||
visible: Prefs.showMusic && MprisController.activePlayer
|
visible: Prefs.showMusic && MprisController.activePlayer
|
||||||
onClicked: {
|
onClicked: {
|
||||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ PanelWindow {
|
|||||||
anchors.leftMargin: Theme.spacingS
|
anchors.leftMargin: Theme.spacingS
|
||||||
visible: Prefs.showWeather && WeatherService.weather.available && WeatherService.weather.temp > 0 && WeatherService.weather.tempF > 0
|
visible: Prefs.showWeather && WeatherService.weather.available && WeatherService.weather.temp > 0 && WeatherService.weather.tempF > 0
|
||||||
onClicked: {
|
onClicked: {
|
||||||
centerCommandCenter.calendarVisible = !centerCommandCenter.calendarVisible;
|
centcomCenter.calendarVisible = !centcomCenter.calendarVisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,10 +273,10 @@ PanelWindow {
|
|||||||
// Bluetooth devices are automatically updated via signals
|
// Bluetooth devices are automatically updated via signals
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
isActive: controlCenterPopup.controlCenterVisible
|
isActive: controlCenter.controlCenterVisible
|
||||||
onClicked: {
|
onClicked: {
|
||||||
controlCenterPopup.controlCenterVisible = !controlCenterPopup.controlCenterVisible;
|
controlCenter.controlCenterVisible = !controlCenter.controlCenterVisible;
|
||||||
if (controlCenterPopup.controlCenterVisible) {
|
if (controlCenter.controlCenterVisible) {
|
||||||
if (NetworkService.wifiEnabled)
|
if (NetworkService.wifiEnabled)
|
||||||
WifiService.scanWifi();
|
WifiService.scanWifi();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -84,19 +87,110 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onPressed: (mouse) => {
|
||||||
if (typeof globalDropdownWindow !== 'undefined') {
|
mouse.accepted = true;
|
||||||
// Get global position of the dropdown button
|
if (!dropdownMenu.visible) {
|
||||||
var globalPos = dropdown.mapToGlobal(0, 0);
|
dropdownMenu.updatePosition();
|
||||||
globalDropdownWindow.showAt(root, globalPos.x, globalPos.y + dropdown.height + 4, root.options, root.currentValue);
|
dropdownMenu.visible = true;
|
||||||
|
} else {
|
||||||
// Connect to value selection (with cleanup)
|
dropdownMenu.visible = false;
|
||||||
globalDropdownWindow.valueSelected.connect(function(value) {
|
|
||||||
root.currentValue = value;
|
|
||||||
root.valueChanged(value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 Quickshell
|
||||||
import qs.Modules
|
import qs.Modules
|
||||||
import qs.Modules.CenterCommandCenter
|
import qs.Modules.CentcomCenter
|
||||||
import qs.Modules.ControlCenter
|
import qs.Modules.ControlCenter
|
||||||
import qs.Modules.Settings
|
import qs.Modules.Settings
|
||||||
import qs.Modules.TopBar
|
import qs.Modules.TopBar
|
||||||
@@ -22,8 +22,8 @@ ShellRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Global popup windows
|
// Global popup windows
|
||||||
CenterCommandCenter {
|
CentcomCenter {
|
||||||
id: centerCommandCenter
|
id: centcomCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayMenuPopup {
|
TrayMenuPopup {
|
||||||
@@ -38,8 +38,8 @@ ShellRoot {
|
|||||||
id: notificationPopup
|
id: notificationPopup
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlCenterPopup {
|
ControlCenter {
|
||||||
id: controlCenterPopup
|
id: controlCenter
|
||||||
onPowerActionRequested: (action, title, message) => {
|
onPowerActionRequested: (action, title, message) => {
|
||||||
powerConfirmDialog.powerConfirmAction = action;
|
powerConfirmDialog.powerConfirmAction = action;
|
||||||
powerConfirmDialog.powerConfirmTitle = title;
|
powerConfirmDialog.powerConfirmTitle = title;
|
||||||
@@ -56,10 +56,6 @@ ShellRoot {
|
|||||||
id: networkInfoDialog
|
id: networkInfoDialog
|
||||||
}
|
}
|
||||||
|
|
||||||
InputDialog {
|
|
||||||
id: globalInputDialog
|
|
||||||
}
|
|
||||||
|
|
||||||
BatteryControlPopup {
|
BatteryControlPopup {
|
||||||
id: batteryControlPopup
|
id: batteryControlPopup
|
||||||
}
|
}
|
||||||
@@ -76,13 +72,10 @@ ShellRoot {
|
|||||||
id: processListDropdown
|
id: processListDropdown
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPopup {
|
SettingsModal {
|
||||||
id: settingsPopup
|
id: settingsModal
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalDropdown {
|
|
||||||
id: globalDropdownWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
// Application and clipboard components
|
// Application and clipboard components
|
||||||
AppLauncher {
|
AppLauncher {
|
||||||
@@ -93,8 +86,8 @@ ShellRoot {
|
|||||||
id: spotlightLauncher
|
id: spotlightLauncher
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessListPopup {
|
ProcessListModal {
|
||||||
id: processListPopup
|
id: processListModal
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipboardHistory {
|
ClipboardHistory {
|
||||||
|
|||||||
Reference in New Issue
Block a user