feat: init quickshell
This commit is contained in:
84
modules/desktop/quickshell/qml/Core/Corners.qml
Normal file
84
modules/desktop/quickshell/qml/Core/Corners.qml
Normal file
@@ -0,0 +1,84 @@
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
import "root:/Data" as Settings
|
||||
|
||||
// Concave corner shape component for rounded panel edges
|
||||
Shape {
|
||||
id: root
|
||||
|
||||
property string position: "topleft" // Corner position: topleft/topright/bottomleft/bottomright
|
||||
property real size: 1.0 // Scale multiplier for entire corner
|
||||
property int concaveWidth: 100 * size
|
||||
property int concaveHeight: 60 * size
|
||||
property int offsetX: -20
|
||||
property int offsetY: -20
|
||||
property color fillColor: Settings.Colors.bgColor
|
||||
property int arcRadius: 20 * size
|
||||
|
||||
// Position flags derived from position string
|
||||
property bool _isTop: position.includes("top")
|
||||
property bool _isLeft: position.includes("left")
|
||||
property bool _isRight: position.includes("right")
|
||||
property bool _isBottom: position.includes("bottom")
|
||||
|
||||
// Base coordinates for left corner shape
|
||||
property real _baseStartX: 30 * size
|
||||
property real _baseStartY: _isTop ? 20 * size : 0
|
||||
property real _baseLineX: 30 * size
|
||||
property real _baseLineY: _isTop ? 0 : 20 * size
|
||||
property real _baseArcX: 50 * size
|
||||
property real _baseArcY: _isTop ? 20 * size : 0
|
||||
|
||||
// Mirror coordinates for right corners
|
||||
property real _startX: _isRight ? (concaveWidth - _baseStartX) : _baseStartX
|
||||
property real _startY: _baseStartY
|
||||
property real _lineX: _isRight ? (concaveWidth - _baseLineX) : _baseLineX
|
||||
property real _lineY: _baseLineY
|
||||
property real _arcX: _isRight ? (concaveWidth - _baseArcX) : _baseArcX
|
||||
property real _arcY: _baseArcY
|
||||
|
||||
// Arc direction varies by corner to maintain proper concave shape
|
||||
property int _arcDirection: {
|
||||
if (_isTop && _isLeft)
|
||||
return PathArc.Counterclockwise;
|
||||
if (_isTop && _isRight)
|
||||
return PathArc.Clockwise;
|
||||
if (_isBottom && _isLeft)
|
||||
return PathArc.Clockwise;
|
||||
if (_isBottom && _isRight)
|
||||
return PathArc.Counterclockwise;
|
||||
return PathArc.Counterclockwise;
|
||||
}
|
||||
|
||||
width: concaveWidth
|
||||
height: concaveHeight
|
||||
// Position relative to parent based on corner type
|
||||
x: _isLeft ? offsetX : (parent ? parent.width - width + offsetX : 0)
|
||||
y: _isTop ? offsetY : (parent ? parent.height - height + offsetY : 0)
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
layer.enabled: true
|
||||
layer.samples: 4
|
||||
|
||||
ShapePath {
|
||||
strokeWidth: 0
|
||||
fillColor: root.fillColor
|
||||
strokeColor: root.fillColor // Use same color as fill to eliminate artifacts
|
||||
|
||||
startX: root._startX
|
||||
startY: root._startY
|
||||
|
||||
PathLine {
|
||||
x: root._lineX
|
||||
y: root._lineY
|
||||
}
|
||||
|
||||
PathArc {
|
||||
x: root._arcX
|
||||
y: root._arcY
|
||||
radiusX: root.arcRadius
|
||||
radiusY: root.arcRadius
|
||||
useLargeArc: false
|
||||
direction: root._arcDirection
|
||||
}
|
||||
}
|
||||
}
|
||||
48
modules/desktop/quickshell/qml/Core/LoaderManager.qml
Normal file
48
modules/desktop/quickshell/qml/Core/LoaderManager.qml
Normal file
@@ -0,0 +1,48 @@
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
// Keep track of loaded components
|
||||
property var activeLoaders: ({})
|
||||
|
||||
// Dynamically load a QML component
|
||||
function load(componentUrl, parent, properties) {
|
||||
if (!activeLoaders[componentUrl]) {
|
||||
var loader = Qt.createQmlObject(`
|
||||
import QtQuick
|
||||
Loader {
|
||||
active: false
|
||||
asynchronous: true
|
||||
visible: false
|
||||
}
|
||||
`, parent);
|
||||
|
||||
loader.source = componentUrl;
|
||||
loader.active = true;
|
||||
|
||||
if (properties) {
|
||||
for (var prop in properties) {
|
||||
loader[prop] = properties[prop];
|
||||
}
|
||||
}
|
||||
|
||||
activeLoaders[componentUrl] = loader;
|
||||
}
|
||||
return activeLoaders[componentUrl];
|
||||
}
|
||||
|
||||
// Destroy and remove a loaded component
|
||||
function unload(componentUrl) {
|
||||
if (activeLoaders[componentUrl]) {
|
||||
activeLoaders[componentUrl].active = false;
|
||||
activeLoaders[componentUrl].destroy();
|
||||
delete activeLoaders[componentUrl];
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a component is loaded
|
||||
function isLoaded(componentUrl) {
|
||||
return !!activeLoaders[componentUrl];
|
||||
}
|
||||
}
|
||||
189
modules/desktop/quickshell/qml/Core/ProcessManager.qml
Normal file
189
modules/desktop/quickshell/qml/Core/ProcessManager.qml
Normal file
@@ -0,0 +1,189 @@
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
import Quickshell.Io
|
||||
|
||||
// System process and resource monitoring
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
// System resource metrics
|
||||
property real cpuUsage: 0
|
||||
property real ramUsage: 0
|
||||
property real totalRam: 0
|
||||
property real usedRam: 0
|
||||
|
||||
// System control processes
|
||||
property Process shutdownProcess: Process {
|
||||
command: ["shutdown", "-h", "now"]
|
||||
}
|
||||
|
||||
property Process rebootProcess: Process {
|
||||
command: ["reboot"]
|
||||
}
|
||||
|
||||
property Process lockProcess: Process {
|
||||
command: ["hyprlock"]
|
||||
}
|
||||
|
||||
property Process logoutProcess: Process {
|
||||
command: ["loginctl", "terminate-user", "$USER"]
|
||||
}
|
||||
|
||||
property Process pavucontrolProcess: Process {
|
||||
command: ["pavucontrol"]
|
||||
}
|
||||
|
||||
// Resource monitoring processes
|
||||
property Process cpuProcess: Process {
|
||||
command: ["sh", "-c", "grep '^cpu ' /proc/stat | awk '{usage=($2+$3+$4)*100/($2+$3+$4+$5)} END {print usage}'"]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
root.cpuUsage = parseFloat(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Process ramProcess: Process {
|
||||
command: ["sh", "-c", "free -b | awk '/Mem:/ {print $2\" \"$3\" \"$3/$2*100}'"]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
var parts = data.trim().split(/\s+/);
|
||||
if (parts.length >= 3) {
|
||||
root.totalRam = parseFloat(parts[0]) / (1024 * 1024 * 1024);
|
||||
root.usedRam = parseFloat(parts[1]) / (1024 * 1024 * 1024);
|
||||
root.ramUsage = parseFloat(parts[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Monitoring timers (start manually when needed)
|
||||
property Timer cpuTimer: Timer {
|
||||
interval: 30000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
cpuProcess.running = false;
|
||||
cpuProcess.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
property Timer ramTimer: Timer {
|
||||
interval: 30000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
ramProcess.running = false;
|
||||
ramProcess.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
// System control functions
|
||||
function shutdown() {
|
||||
console.log("Executing shutdown command");
|
||||
shutdownProcess.running = true;
|
||||
}
|
||||
|
||||
function reboot() {
|
||||
console.log("Executing reboot command");
|
||||
rebootProcess.running = true;
|
||||
}
|
||||
|
||||
function lock() {
|
||||
console.log("Executing lock command");
|
||||
lockProcess.running = true;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
console.log("Executing logout command");
|
||||
logoutProcess.running = true;
|
||||
}
|
||||
|
||||
function openPavuControl() {
|
||||
console.log("Opening PavuControl");
|
||||
pavucontrolProcess.running = true;
|
||||
}
|
||||
|
||||
// Performance monitoring control
|
||||
function startMonitoring() {
|
||||
console.log("Starting system monitoring");
|
||||
cpuTimer.running = true;
|
||||
ramTimer.running = true;
|
||||
}
|
||||
|
||||
function stopMonitoring() {
|
||||
console.log("Stopping system monitoring");
|
||||
cpuTimer.running = false;
|
||||
ramTimer.running = false;
|
||||
}
|
||||
|
||||
function setMonitoringInterval(intervalMs) {
|
||||
console.log("Setting monitoring interval to", intervalMs, "ms");
|
||||
cpuTimer.interval = intervalMs;
|
||||
ramTimer.interval = intervalMs;
|
||||
}
|
||||
|
||||
function refreshSystemStats() {
|
||||
console.log("Manually refreshing system stats");
|
||||
cpuProcess.running = false;
|
||||
cpuProcess.running = true;
|
||||
ramProcess.running = false;
|
||||
ramProcess.running = true;
|
||||
}
|
||||
|
||||
// Process state queries
|
||||
function isShutdownRunning() {
|
||||
return shutdownProcess.running;
|
||||
}
|
||||
function isRebootRunning() {
|
||||
return rebootProcess.running;
|
||||
}
|
||||
function isLogoutRunning() {
|
||||
return logoutProcess.running;
|
||||
}
|
||||
function isPavuControlRunning() {
|
||||
return pavucontrolProcess.running;
|
||||
}
|
||||
function isMonitoringActive() {
|
||||
return cpuTimer.running && ramTimer.running;
|
||||
}
|
||||
|
||||
function stopPavuControl() {
|
||||
pavucontrolProcess.running = false;
|
||||
}
|
||||
|
||||
// Formatted output helpers
|
||||
function getCpuUsageFormatted() {
|
||||
return Math.round(cpuUsage) + "%";
|
||||
}
|
||||
|
||||
function getRamUsageFormatted() {
|
||||
return Math.round(ramUsage) + "% (" + usedRam.toFixed(1) + "GB/" + totalRam.toFixed(1) + "GB)";
|
||||
}
|
||||
|
||||
function getRamUsageSimple() {
|
||||
return Math.round(ramUsage) + "%";
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
// Stop all timers
|
||||
cpuTimer.running = false;
|
||||
ramTimer.running = false;
|
||||
|
||||
// Stop monitoring processes
|
||||
cpuProcess.running = false;
|
||||
ramProcess.running = false;
|
||||
|
||||
// Stop control processes if running
|
||||
if (shutdownProcess.running)
|
||||
shutdownProcess.running = false;
|
||||
if (rebootProcess.running)
|
||||
rebootProcess.running = false;
|
||||
if (lockProcess.running)
|
||||
lockProcess.running = false;
|
||||
if (logoutProcess.running)
|
||||
logoutProcess.running = false;
|
||||
if (pavucontrolProcess.running)
|
||||
pavucontrolProcess.running = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user