launcher overhaul
This commit is contained in:
@@ -4,6 +4,7 @@ import QtQuick
|
|||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules
|
import qs.Modules
|
||||||
import qs.Modules.Bar
|
import qs.Modules.Bar
|
||||||
@@ -25,7 +26,7 @@ Variants {
|
|||||||
|
|
||||||
WlrLayershell.namespace: "ZShell-Bar"
|
WlrLayershell.namespace: "ZShell-Bar"
|
||||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||||
|
WlrLayershell.keyboardFocus: visibilities.launcher ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: exclusionZone
|
id: exclusionZone
|
||||||
WlrLayershell.namespace: "ZShell-Bar-Exclusion"
|
WlrLayershell.namespace: "ZShell-Bar-Exclusion"
|
||||||
@@ -78,6 +79,19 @@ Variants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab {
|
||||||
|
id: focusGrab
|
||||||
|
|
||||||
|
active: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.osd
|
||||||
|
windows: [bar]
|
||||||
|
onCleared: {
|
||||||
|
visibilities.launcher = false;
|
||||||
|
visibilities.sidebar = false;
|
||||||
|
visibilities.dashboard = false;
|
||||||
|
visibilities.osd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CustomShortcut {
|
CustomShortcut {
|
||||||
name: "toggle-nc"
|
name: "toggle-nc"
|
||||||
|
|
||||||
@@ -93,6 +107,7 @@ Variants {
|
|||||||
property bool dashboard
|
property bool dashboard
|
||||||
property bool bar
|
property bool bar
|
||||||
property bool osd
|
property bool osd
|
||||||
|
property bool launcher
|
||||||
|
|
||||||
Component.onCompleted: Visibilities.load(scope.modelData, this)
|
Component.onCompleted: Visibilities.load(scope.modelData, this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
placeholderTextColor: DynamicColors.palette.m3outline
|
||||||
|
font.family: Appearance.font.family.sans
|
||||||
|
font.pointSize: Appearance.font.size.smaller
|
||||||
|
renderType: echoMode === TextField.Password ? TextField.QtRendering : TextField.NativeRendering
|
||||||
|
cursorVisible: !readOnly
|
||||||
|
|
||||||
|
background: null
|
||||||
|
|
||||||
|
cursorDelegate: CustomRect {
|
||||||
|
id: cursor
|
||||||
|
|
||||||
|
property bool disableBlink
|
||||||
|
|
||||||
|
implicitWidth: 2
|
||||||
|
color: DynamicColors.palette.m3primary
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
|
||||||
|
function onCursorPositionChanged(): void {
|
||||||
|
if (root.activeFocus && root.cursorVisible) {
|
||||||
|
cursor.opacity = 1;
|
||||||
|
cursor.disableBlink = true;
|
||||||
|
enableBlink.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: enableBlink
|
||||||
|
|
||||||
|
interval: 100
|
||||||
|
onTriggered: cursor.disableBlink = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
running: root.activeFocus && root.cursorVisible && !cursor.disableBlink
|
||||||
|
repeat: true
|
||||||
|
triggeredOnStart: true
|
||||||
|
interval: 500
|
||||||
|
onTriggered: parent.opacity = parent.opacity === 1 ? 0 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
when: !root.activeFocus || !root.cursorVisible
|
||||||
|
cursor.opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on placeholderTextColor {
|
||||||
|
CAnim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import Quickshell.Io
|
|||||||
|
|
||||||
JsonObject {
|
JsonObject {
|
||||||
property bool autoHide: false
|
property bool autoHide: false
|
||||||
|
property int rounding: 8
|
||||||
property Popouts popouts: Popouts {}
|
property Popouts popouts: Popouts {}
|
||||||
|
|
||||||
property list<var> entries: [
|
property list<var> entries: [
|
||||||
|
|||||||
+23
-1
@@ -101,6 +101,7 @@ Singleton {
|
|||||||
function serializeBar(): var {
|
function serializeBar(): var {
|
||||||
return {
|
return {
|
||||||
autoHide: barConfig.autoHide,
|
autoHide: barConfig.autoHide,
|
||||||
|
rounding: barConfig.rounding,
|
||||||
popouts: {
|
popouts: {
|
||||||
tray: barConfig.popouts.tray,
|
tray: barConfig.popouts.tray,
|
||||||
audio: barConfig.popouts.audio,
|
audio: barConfig.popouts.audio,
|
||||||
@@ -132,6 +133,12 @@ Singleton {
|
|||||||
logo: general.logo,
|
logo: general.logo,
|
||||||
wallpaperPath: general.wallpaperPath,
|
wallpaperPath: general.wallpaperPath,
|
||||||
wallust: general.wallust,
|
wallust: general.wallust,
|
||||||
|
apps: {
|
||||||
|
terminal: general.apps.terminal,
|
||||||
|
audio: general.apps.audio,
|
||||||
|
playback: general.apps.playback,
|
||||||
|
explorer: general.apps.explorer,
|
||||||
|
},
|
||||||
idle: {
|
idle: {
|
||||||
timouts: general.idle.timeouts
|
timouts: general.idle.timeouts
|
||||||
}
|
}
|
||||||
@@ -245,7 +252,22 @@ Singleton {
|
|||||||
return {
|
return {
|
||||||
maxAppsShown: launcher.maxAppsShown,
|
maxAppsShown: launcher.maxAppsShown,
|
||||||
maxWallpapers: launcher.maxWallpapers,
|
maxWallpapers: launcher.maxWallpapers,
|
||||||
wallpaperPrefix: launcher.wallpaperPrefix
|
actionPrefix: launcher.actionPrefix,
|
||||||
|
specialPrefix: launcher.specialPrefix,
|
||||||
|
useFuzzy: {
|
||||||
|
apps: launcher.useFuzzy.apps,
|
||||||
|
actions: launcher.useFuzzy.actions,
|
||||||
|
schemes: launcher.useFuzzy.schemes,
|
||||||
|
variants: launcher.useFuzzy.variants,
|
||||||
|
wallpapers: launcher.useFuzzy.wallpapers
|
||||||
|
},
|
||||||
|
sizes: {
|
||||||
|
itemWidth: launcher.sizes.itemWidth,
|
||||||
|
itemHeight: launcher.sizes.itemHeight,
|
||||||
|
wallpaperWidth: launcher.sizes.wallpaperWidth,
|
||||||
|
wallpaperHeight: launcher.sizes.wallpaperHeight
|
||||||
|
},
|
||||||
|
actions: launcher.actions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,16 @@ JsonObject {
|
|||||||
property string logo: ""
|
property string logo: ""
|
||||||
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
|
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
|
||||||
property bool wallust: false
|
property bool wallust: false
|
||||||
|
property Apps apps: Apps {}
|
||||||
property Idle idle: Idle {}
|
property Idle idle: Idle {}
|
||||||
|
|
||||||
|
component Apps: JsonObject {
|
||||||
|
property list<string> terminal: ["foot"]
|
||||||
|
property list<string> audio: ["pavucontrol"]
|
||||||
|
property list<string> playback: ["mpv"]
|
||||||
|
property list<string> explorer: ["thunar"]
|
||||||
|
}
|
||||||
|
|
||||||
component Idle: JsonObject {
|
component Idle: JsonObject {
|
||||||
property list<var> timeouts: [
|
property list<var> timeouts: [
|
||||||
{
|
{
|
||||||
|
|||||||
+78
-1
@@ -3,5 +3,82 @@ import Quickshell.Io
|
|||||||
JsonObject {
|
JsonObject {
|
||||||
property int maxAppsShown: 10
|
property int maxAppsShown: 10
|
||||||
property int maxWallpapers: 7
|
property int maxWallpapers: 7
|
||||||
property string wallpaperPrefix: ">"
|
property string actionPrefix: ">"
|
||||||
|
property string specialPrefix: "@"
|
||||||
|
property Sizes sizes: Sizes {}
|
||||||
|
property UseFuzzy useFuzzy: UseFuzzy {}
|
||||||
|
|
||||||
|
component UseFuzzy: JsonObject {
|
||||||
|
property bool apps: false
|
||||||
|
property bool actions: false
|
||||||
|
property bool schemes: false
|
||||||
|
property bool variants: false
|
||||||
|
property bool wallpapers: false
|
||||||
|
}
|
||||||
|
|
||||||
|
component Sizes: JsonObject {
|
||||||
|
property int itemWidth: 600
|
||||||
|
property int itemHeight: 50
|
||||||
|
property int wallpaperWidth: 280
|
||||||
|
property int wallpaperHeight: 200
|
||||||
|
}
|
||||||
|
|
||||||
|
property list<var> actions: [
|
||||||
|
{
|
||||||
|
name: "Calculator",
|
||||||
|
icon: "calculate",
|
||||||
|
description: "Do simple math equations (powered by Qalc)",
|
||||||
|
command: ["autocomplete", "calc"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wallpaper",
|
||||||
|
icon: "image",
|
||||||
|
description: "Change the current wallpaper",
|
||||||
|
command: ["autocomplete", "wallpaper"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Shutdown",
|
||||||
|
icon: "power_settings_new",
|
||||||
|
description: "Shutdown the system",
|
||||||
|
command: ["systemctl", "poweroff"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Reboot",
|
||||||
|
icon: "cached",
|
||||||
|
description: "Reboot the system",
|
||||||
|
command: ["systemctl", "reboot"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Logout",
|
||||||
|
icon: "exit_to_app",
|
||||||
|
description: "Log out of the current session",
|
||||||
|
command: ["loginctl", "terminate-user", ""],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Lock",
|
||||||
|
icon: "lock",
|
||||||
|
description: "Lock the current session",
|
||||||
|
command: ["loginctl", "lock-session"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sleep",
|
||||||
|
icon: "bedtime",
|
||||||
|
description: "Suspend then hibernate",
|
||||||
|
command: ["systemctl", "suspend-then-hibernate"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: false
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import qs.Modules.Notifications.Sidebar as Sidebar
|
|||||||
import qs.Modules.Notifications.Sidebar.Utils as Utils
|
import qs.Modules.Notifications.Sidebar.Utils as Utils
|
||||||
import qs.Modules.Dashboard as Dashboard
|
import qs.Modules.Dashboard as Dashboard
|
||||||
import qs.Modules.Osd as Osd
|
import qs.Modules.Osd as Osd
|
||||||
|
import qs.Modules.Launcher as Launcher
|
||||||
|
|
||||||
Shape {
|
Shape {
|
||||||
id: root
|
id: root
|
||||||
@@ -45,6 +46,13 @@ Shape {
|
|||||||
startY: 0
|
startY: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Launcher.Background {
|
||||||
|
wrapper: root.panels.launcher
|
||||||
|
|
||||||
|
startX: ( root.width - wrapper.width ) / 2 - rounding
|
||||||
|
startY: root.height
|
||||||
|
}
|
||||||
|
|
||||||
Dashboard.Background {
|
Dashboard.Background {
|
||||||
wrapper: root.panels.dashboard
|
wrapper: root.panels.dashboard
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import qs.Modules.Notifications.Sidebar.Utils as Utils
|
|||||||
import qs.Modules.Dashboard as Dashboard
|
import qs.Modules.Dashboard as Dashboard
|
||||||
import qs.Modules.Osd as Osd
|
import qs.Modules.Osd as Osd
|
||||||
import qs.Components.Toast as Toasts
|
import qs.Components.Toast as Toasts
|
||||||
|
import qs.Modules.Launcher as Launcher
|
||||||
import qs.Config
|
import qs.Config
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -24,6 +25,7 @@ Item {
|
|||||||
readonly property alias dashboard: dashboard
|
readonly property alias dashboard: dashboard
|
||||||
readonly property alias osd: osd
|
readonly property alias osd: osd
|
||||||
readonly property alias toasts: toasts
|
readonly property alias toasts: toasts
|
||||||
|
readonly property alias launcher: launcher
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
// anchors.margins: 8
|
// anchors.margins: 8
|
||||||
@@ -75,6 +77,17 @@ Item {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Launcher.Wrapper {
|
||||||
|
id: launcher
|
||||||
|
|
||||||
|
screen: root.screen
|
||||||
|
visibilities: root.visibilities
|
||||||
|
panels: root
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
Utils.Wrapper {
|
Utils.Wrapper {
|
||||||
id: utilities
|
id: utilities
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import ZShell.Models
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Paths
|
||||||
|
|
||||||
|
Searcher {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool showPreview: false
|
||||||
|
readonly property string current: showPreview ? previewPath : actualCurrent
|
||||||
|
property string previewPath
|
||||||
|
property string actualCurrent: WallpaperPath.currentWallpaperPath
|
||||||
|
|
||||||
|
function setWallpaper(path: string): void {
|
||||||
|
actualCurrent = path;
|
||||||
|
WallpaperPath.currentWallpaperPath = path;
|
||||||
|
Quickshell.execDetached(["sh", "-c", `python3 ${Quickshell.shellPath("scripts/LockScreenBg.py")} --input_image=${root.actualCurrent} --output_path=${Paths.state}/lockscreen_bg.png`]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function preview(path: string): void {
|
||||||
|
previewPath = path;
|
||||||
|
showPreview = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopPreview(): void {
|
||||||
|
showPreview = false;
|
||||||
|
Quickshell.execDetached(["sh", "-c", `python3 ${Quickshell.shellPath("scripts/SchemeColorGen.py")} --path=${root.actualCurrent} --thumbnail=${Paths.cache}/imagecache/thumbnail.jpg --output=${Paths.state}/scheme.json --scheme=${Config.colors.schemeType}`]);
|
||||||
|
}
|
||||||
|
|
||||||
|
list: wallpapers.entries
|
||||||
|
key: "relativePath"
|
||||||
|
useFuzzy: true
|
||||||
|
extraOpts: useFuzzy ? ({}) : ({
|
||||||
|
forward: false
|
||||||
|
})
|
||||||
|
|
||||||
|
FileSystemModel {
|
||||||
|
id: wallpapers
|
||||||
|
|
||||||
|
recursive: true
|
||||||
|
path: Config.general.wallpaperPath
|
||||||
|
filter: FileSystemModel.Images
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import QtQuick
|
|
||||||
import qs
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property DesktopEntry modelData
|
|
||||||
|
|
||||||
implicitHeight: 48
|
|
||||||
|
|
||||||
anchors.left: parent?.left
|
|
||||||
anchors.right: parent?.right
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: event => onClicked(event)
|
|
||||||
function onClicked(): void {
|
|
||||||
Search.launch(root.modelData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 8
|
|
||||||
anchors.rightMargin: 8
|
|
||||||
anchors.margins: 4
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: icon
|
|
||||||
|
|
||||||
source: Quickshell.iconPath( root.modelData?.icon, "image-missing" )
|
|
||||||
implicitSize: parent.height * 0.8
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.left: icon.right
|
|
||||||
anchors.leftMargin: 8
|
|
||||||
anchors.verticalCenter: icon.verticalCenter
|
|
||||||
|
|
||||||
implicitWidth: parent.width - icon.width
|
|
||||||
implicitHeight: name.implicitHeight + comment.implicitHeight
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: name
|
|
||||||
|
|
||||||
text: root.modelData?.name || qsTr("Unknown Application")
|
|
||||||
font.pointSize: 12
|
|
||||||
color: mouseArea.containsMouse ? "#ffffff" : "#cccccc"
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: comment
|
|
||||||
|
|
||||||
text: ( root.modelData?.comment || root.modelData?.genericName || root.modelData?.name ) ?? ""
|
|
||||||
font.pointSize: 10
|
|
||||||
color: mouseArea.containsMouse ? "#dddddd" : "#888888"
|
|
||||||
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: root.width - icon.width - 4 * 2
|
|
||||||
|
|
||||||
anchors.top: name.bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import qs.Config
|
|
||||||
import qs.Daemons
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: ScriptModel {
|
|
||||||
values: {
|
|
||||||
const map = new Map();
|
|
||||||
for ( const n of NotifServer.notClosed )
|
|
||||||
map.set( n.appName, null );
|
|
||||||
for ( const n of NotifServer.list )
|
|
||||||
map.set( n.appName, null );
|
|
||||||
return [ ...map.keys() ];
|
|
||||||
}
|
|
||||||
onValuesChanged: {
|
|
||||||
root.flagChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: groupColumn
|
|
||||||
required property string modelData
|
|
||||||
property list<var> notifications: NotifServer.list.filter( n => n.appName === modelData )
|
|
||||||
width: parent.width
|
|
||||||
spacing: 10
|
|
||||||
|
|
||||||
property bool shouldShow: false
|
|
||||||
property bool isExpanded: false
|
|
||||||
property bool collapseAnimRunning: false
|
|
||||||
property color textColor: DynamicColors.palette.m3onSurface
|
|
||||||
|
|
||||||
function closeAll(): void {
|
|
||||||
for ( const n of NotifServer.notClosed.filter( n => n.appName === modelData ))
|
|
||||||
n.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on height {
|
|
||||||
Anim {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on y {
|
|
||||||
Anim {
|
|
||||||
duration: MaterialEasing.expressiveEffectsTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add: Transition {
|
|
||||||
id: addTrans
|
|
||||||
SequentialAnimation {
|
|
||||||
PauseAnimation {
|
|
||||||
duration: ( addTrans.ViewTransition.index - addTrans.ViewTransition.targetIndexes[ 0 ]) * 30
|
|
||||||
}
|
|
||||||
ParallelAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
properties: "y";
|
|
||||||
from: addTrans.ViewTransition.destination.y - (height / 2);
|
|
||||||
to: addTrans.ViewTransition.destination.y;
|
|
||||||
duration: 100;
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
NumberAnimation {
|
|
||||||
properties: "opacity";
|
|
||||||
from: 0;
|
|
||||||
to: 1;
|
|
||||||
duration: 100;
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
NumberAnimation {
|
|
||||||
properties: "scale";
|
|
||||||
from: 0.7;
|
|
||||||
to: 1.0;
|
|
||||||
duration: 100
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
interval: addTrans.ViewTransition.targetIndexes.length * 30 + 100
|
|
||||||
running: groupColumn.isExpanded
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
groupColumn.shouldShow = true;
|
|
||||||
console.log("ran timer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
move: Transition {
|
|
||||||
id: moveTrans
|
|
||||||
NumberAnimation {
|
|
||||||
properties: "y";
|
|
||||||
duration: 100;
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
properties: "opacity, scale";
|
|
||||||
to: 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
width: parent.width
|
|
||||||
height: 30
|
|
||||||
|
|
||||||
Text {
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
|
||||||
Layout.leftMargin: 5
|
|
||||||
text: groupColumn.modelData
|
|
||||||
color: groupColumn.textColor
|
|
||||||
font.pointSize: 14
|
|
||||||
font.bold: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: collapseRect
|
|
||||||
|
|
||||||
property color notifyBgColor: DynamicColors.palette.m3primary
|
|
||||||
property color notifyColor: DynamicColors.palette.m3onPrimary
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: 30
|
|
||||||
color: !groupColumn.isExpanded ? collapseRect.notifyBgColor : ( collapseArea.containsMouse ? "#15FFFFFF" : "transparent" )
|
|
||||||
radius: groupColumn.isExpanded ? 4 : height / 2
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: groupColumn.isExpanded ? "\ue944" : groupColumn.notifications.length
|
|
||||||
font.family: groupColumn.isExpanded ? "Material Symbols Rounded" : "Rubik"
|
|
||||||
font.pointSize: 18
|
|
||||||
color: groupColumn.isExpanded ? groupColumn.textColor : collapseRect.notifyColor
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: collapseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: {
|
|
||||||
groupColumn.collapseAnimRunning = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NotifGroupRepeater { id: groupRepeater }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,538 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Components
|
|
||||||
import qs.Config
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Effects
|
|
||||||
import qs.Paths
|
|
||||||
|
|
||||||
Scope {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
PanelWindow {
|
|
||||||
id: launcherWindow
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
left: true
|
|
||||||
right: true
|
|
||||||
bottom: true
|
|
||||||
}
|
|
||||||
color: "transparent"
|
|
||||||
visible: false
|
|
||||||
|
|
||||||
WlrLayershell.namespace: "ZShell-Launcher"
|
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if ( !visible ) {
|
|
||||||
searchInput.text = "";
|
|
||||||
appListLoader.item.currentIndex = 0;
|
|
||||||
appListLoader.item.positionViewAtBeginning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomShortcut {
|
|
||||||
name: "toggle-launcher"
|
|
||||||
onPressed: {
|
|
||||||
if ( !launcherWindow.visible ) {
|
|
||||||
if ( !openAnim.running ) {
|
|
||||||
openAnim.start();
|
|
||||||
}
|
|
||||||
} else if ( launcherWindow.visible ) {
|
|
||||||
if ( !closeAnim.running ) {
|
|
||||||
closeAnim.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
searchInput.forceActiveFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShadowRect {
|
|
||||||
id: effects
|
|
||||||
anchors {
|
|
||||||
top: appListRect.top
|
|
||||||
bottom: backgroundRect.bottom
|
|
||||||
left: appListRect.left
|
|
||||||
right: appListRect.right
|
|
||||||
}
|
|
||||||
radius: 8
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: backgroundRect
|
|
||||||
|
|
||||||
property color backgroundColor: DynamicColors.tPalette.m3surface
|
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 0
|
|
||||||
implicitHeight: mainLayout.childrenRect.height + 20
|
|
||||||
implicitWidth: appListRect.implicitWidth
|
|
||||||
x: Math.round(( parent.width - width ) / 2 )
|
|
||||||
color: backgroundColor
|
|
||||||
opacity: 1
|
|
||||||
|
|
||||||
ParallelAnimation {
|
|
||||||
id: openAnim
|
|
||||||
Anim {
|
|
||||||
target: appListRect
|
|
||||||
duration: MaterialEasing.expressiveDefaultSpatialTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
|
||||||
property: "implicitHeight"
|
|
||||||
from: 40
|
|
||||||
to: appListContainer.implicitHeight + 20
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: appListRect
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: backgroundRect
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: effects
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
onStarted: {
|
|
||||||
launcherWindow.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParallelAnimation {
|
|
||||||
id: closeAnim
|
|
||||||
Anim {
|
|
||||||
target: appListRect
|
|
||||||
duration: MaterialEasing.expressiveDefaultSpatialTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
|
||||||
property: "implicitHeight"
|
|
||||||
from: appListContainer.implicitHeight
|
|
||||||
to: 0
|
|
||||||
}
|
|
||||||
SequentialAnimation {
|
|
||||||
PauseAnimation { duration: 120 }
|
|
||||||
|
|
||||||
ParallelAnimation {
|
|
||||||
Anim {
|
|
||||||
target: backgroundRect
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: appListRect
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: effects
|
|
||||||
duration: 50
|
|
||||||
property: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onStopped: {
|
|
||||||
launcherWindow.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: mainLayout
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 10
|
|
||||||
spacing: 5
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
CustomTextField {
|
|
||||||
id: searchInput
|
|
||||||
implicitHeight: 30
|
|
||||||
implicitWidth: parent.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: appListRect
|
|
||||||
x: Math.round(( parent.width - width ) / 2 )
|
|
||||||
implicitWidth: appListContainer.implicitWidth + 20
|
|
||||||
implicitHeight: appListContainer.implicitHeight + 20
|
|
||||||
anchors.bottom: backgroundRect.top
|
|
||||||
color: backgroundRect.color
|
|
||||||
topRightRadius: 8
|
|
||||||
topLeftRadius: 8
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
|
||||||
Anim {
|
|
||||||
duration: MaterialEasing.expressiveFastSpatialTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
Anim {
|
|
||||||
duration: MaterialEasing.expressiveFastSpatialTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
id: appListContainer
|
|
||||||
visible: true
|
|
||||||
clip: true
|
|
||||||
property var showWallpapers: searchInput.text.startsWith(">")
|
|
||||||
state: showWallpapers ? "wallpaperpicker" : "apps"
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "apps"
|
|
||||||
PropertyChanges {
|
|
||||||
appListLoader.active: true
|
|
||||||
appListContainer.implicitHeight: appListLoader.implicitHeight
|
|
||||||
appListContainer.implicitWidth: 600
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "wallpaperpicker"
|
|
||||||
PropertyChanges {
|
|
||||||
wallpaperPickerLoader.active: true
|
|
||||||
appListContainer.implicitHeight: wallpaperPickerLoader.implicitHeight
|
|
||||||
appListContainer.implicitWidth: wallpaperPickerLoader.implicitWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Loader {
|
|
||||||
id: wallpaperPickerLoader
|
|
||||||
active: false
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: PathView {
|
|
||||||
id: wallpaperPickerView
|
|
||||||
anchors.fill: parent
|
|
||||||
model: ScriptModel {
|
|
||||||
id: wallpaperModel
|
|
||||||
readonly property string search: searchInput.text.split(" ").slice(1).join(" ")
|
|
||||||
|
|
||||||
values: SearchWallpapers.query( search )
|
|
||||||
onValuesChanged: wallpaperPickerView.currentIndex = SearchWallpapers.list.findIndex( w => w.path === WallpaperPath.currentWallpaperPath )
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property int itemWidth: 288 + 10
|
|
||||||
readonly property int numItems: {
|
|
||||||
const screen = QsWindow.window?.screen;
|
|
||||||
if (!screen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Screen width - 4x outer rounding - 2x max side thickness (cause centered)
|
|
||||||
const margins = 10;
|
|
||||||
const maxWidth = screen.width - margins * 2;
|
|
||||||
|
|
||||||
if ( maxWidth <= 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
const maxItemsOnScreen = Math.floor( maxWidth / itemWidth );
|
|
||||||
const visible = Math.min( maxItemsOnScreen, Config.launcher.maxWallpapers, wallpaperModel.values.length );
|
|
||||||
|
|
||||||
if ( visible === 2 )
|
|
||||||
return 1;
|
|
||||||
if ( visible > 1 && visible % 2 === 0 )
|
|
||||||
return visible - 1;
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: currentIndex = SearchWallpapers.list.findIndex( w => w.path === WallpaperPath.currentWallpaperPath )
|
|
||||||
Component.onDestruction: SearchWallpapers.stopPreview()
|
|
||||||
|
|
||||||
onCurrentItemChanged: {
|
|
||||||
if ( currentItem )
|
|
||||||
SearchWallpapers.preview( currentItem.modelData.path );
|
|
||||||
Quickshell.execDetached(["python3", Quickshell.shellPath("scripts/SchemeColorGen.py"), `--path=${currentItem.modelData.path}`, `--thumbnail=${Paths.cache}/imagecache/thumbnail.jpg`, `--output=${Paths.state}/scheme.json`, `--scheme=${Config.colors.schemeType}`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheItemCount: 5
|
|
||||||
snapMode: PathView.SnapToItem
|
|
||||||
preferredHighlightBegin: 0.5
|
|
||||||
preferredHighlightEnd: 0.5
|
|
||||||
highlightRangeMode: PathView.StrictlyEnforceRange
|
|
||||||
|
|
||||||
pathItemCount: numItems
|
|
||||||
implicitHeight: 212
|
|
||||||
implicitWidth: Math.min( numItems, count ) * itemWidth
|
|
||||||
|
|
||||||
path: Path {
|
|
||||||
startY: wallpaperPickerView.height / 2
|
|
||||||
|
|
||||||
PathAttribute {
|
|
||||||
name: "z"
|
|
||||||
value: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: wallpaperPickerView.width / 2
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
PathAttribute {
|
|
||||||
name: "z"
|
|
||||||
value: 1
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: wallpaperPickerView.width
|
|
||||||
relativeY: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
focus: true
|
|
||||||
|
|
||||||
delegate: WallpaperItem { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loader {
|
|
||||||
id: appListLoader
|
|
||||||
active: false
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: ListView {
|
|
||||||
id: appListView
|
|
||||||
|
|
||||||
property color highlightColor: DynamicColors.tPalette.m3onSurface
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
model: ScriptModel {
|
|
||||||
id: appModel
|
|
||||||
|
|
||||||
onValuesChanged: {
|
|
||||||
appListView.currentIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalLayoutDirection: ListView.BottomToTop
|
|
||||||
implicitHeight: Math.min( count, Config.launcher.maxAppsShown ) * 48
|
|
||||||
|
|
||||||
preferredHighlightBegin: 0
|
|
||||||
preferredHighlightEnd: appListView.height
|
|
||||||
highlightFollowsCurrentItem: false
|
|
||||||
highlightRangeMode: ListView.ApplyRange
|
|
||||||
focus: true
|
|
||||||
highlight: Rectangle {
|
|
||||||
radius: 4
|
|
||||||
color: appListView.highlightColor
|
|
||||||
opacity: 0.20
|
|
||||||
|
|
||||||
y: appListView.currentItem?.y
|
|
||||||
implicitWidth: appListView.width
|
|
||||||
implicitHeight: appListView.currentItem?.implicitHeight ?? 0
|
|
||||||
|
|
||||||
Behavior on y {
|
|
||||||
Anim {
|
|
||||||
duration: MaterialEasing.expressiveEffectsTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property list<var> search: Search.search( searchInput.text )
|
|
||||||
|
|
||||||
state: {
|
|
||||||
const text = searchInput.text
|
|
||||||
if ( search.length === 0 ) {
|
|
||||||
return "noresults"
|
|
||||||
} else {
|
|
||||||
return "apps"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "apps"
|
|
||||||
PropertyChanges {
|
|
||||||
appModel.values: Search.search(searchInput.text)
|
|
||||||
appListView.delegate: appItem
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "noresults"
|
|
||||||
PropertyChanges {
|
|
||||||
appModel.values: [1]
|
|
||||||
appListView.delegate: noResultsItem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: appItem
|
|
||||||
AppItem {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: noResultsItem
|
|
||||||
Item {
|
|
||||||
width: appListView.width
|
|
||||||
height: 48
|
|
||||||
Text {
|
|
||||||
id: icon
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
property real fill: 0
|
|
||||||
text: "\ue000"
|
|
||||||
color: "#cccccc"
|
|
||||||
renderType: Text.NativeRendering
|
|
||||||
font.pointSize: 28
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.variableAxes: ({
|
|
||||||
FILL: fill.toFixed(1),
|
|
||||||
GRAD: -25,
|
|
||||||
opsz: fontInfo.pixelSize,
|
|
||||||
wght: fontInfo.weight
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.left: icon.right
|
|
||||||
anchors.leftMargin: 10
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: "No results found"
|
|
||||||
color: "#cccccc"
|
|
||||||
renderType: Text.NativeRendering
|
|
||||||
|
|
||||||
font.pointSize: 12
|
|
||||||
font.family: "Rubik"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: wallpaperItem
|
|
||||||
WallpaperItem { }
|
|
||||||
}
|
|
||||||
|
|
||||||
transitions: Transition {
|
|
||||||
SequentialAnimation {
|
|
||||||
ParallelAnimation {
|
|
||||||
Anim {
|
|
||||||
target: appListView
|
|
||||||
property: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
duration: 200
|
|
||||||
easing.bezierCurve: MaterialEasing.standardAccel
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: appListView
|
|
||||||
property: "scale"
|
|
||||||
from: 1
|
|
||||||
to: 0.9
|
|
||||||
duration: 200
|
|
||||||
easing.bezierCurve: MaterialEasing.standardAccel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PropertyAction {
|
|
||||||
targets: [model, appListView]
|
|
||||||
properties: "values,delegate"
|
|
||||||
}
|
|
||||||
ParallelAnimation {
|
|
||||||
Anim {
|
|
||||||
target: appListView
|
|
||||||
property: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
duration: 200
|
|
||||||
easing.bezierCurve: MaterialEasing.standardDecel
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
target: appListView
|
|
||||||
property: "scale"
|
|
||||||
from: 0.9
|
|
||||||
to: 1
|
|
||||||
duration: 200
|
|
||||||
easing.bezierCurve: MaterialEasing.standardDecel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PropertyAction {
|
|
||||||
targets: [appListView.add, appListView.remove]
|
|
||||||
property: "enabled"
|
|
||||||
value: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add: Transition {
|
|
||||||
enabled: !appListView.state
|
|
||||||
Anim {
|
|
||||||
properties: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
properties: "scale"
|
|
||||||
from: 0.95
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove: Transition {
|
|
||||||
enabled: !appListView.state
|
|
||||||
Anim {
|
|
||||||
properties: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
properties: "scale"
|
|
||||||
from: 1
|
|
||||||
to: 0.95
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
move: Transition {
|
|
||||||
Anim {
|
|
||||||
property: "y"
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
properties: "opacity,scale"
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDisplaced: Transition {
|
|
||||||
Anim {
|
|
||||||
property: "y"
|
|
||||||
duration: 200
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
properties: "opacity,scale"
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
displaced: Transition {
|
|
||||||
Anim {
|
|
||||||
property: "y"
|
|
||||||
}
|
|
||||||
Anim {
|
|
||||||
properties: "opacity,scale"
|
|
||||||
to: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Modules.Launcher.Services
|
||||||
|
import qs.Modules.Launcher.Items
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules as Modules
|
||||||
|
|
||||||
|
CustomListView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property CustomTextField search
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
model: ScriptModel {
|
||||||
|
id: model
|
||||||
|
|
||||||
|
onValuesChanged: root.currentIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
|
spacing: Appearance.spacing.small
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
|
||||||
|
|
||||||
|
preferredHighlightBegin: 0
|
||||||
|
preferredHighlightEnd: height
|
||||||
|
highlightRangeMode: ListView.ApplyRange
|
||||||
|
|
||||||
|
highlightFollowsCurrentItem: false
|
||||||
|
highlight: CustomRect {
|
||||||
|
radius: 8
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
opacity: 0.08
|
||||||
|
|
||||||
|
y: root.currentItem?.y ?? 0
|
||||||
|
implicitWidth: root.width
|
||||||
|
implicitHeight: root.currentItem?.implicitHeight ?? 0
|
||||||
|
|
||||||
|
Behavior on y {
|
||||||
|
Modules.Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state: {
|
||||||
|
const text = search.text;
|
||||||
|
const prefix = Config.launcher.actionPrefix;
|
||||||
|
if (text.startsWith(prefix)) {
|
||||||
|
for (const action of ["calc", "scheme", "variant"])
|
||||||
|
if (text.startsWith(`${prefix}${action} `))
|
||||||
|
return action;
|
||||||
|
|
||||||
|
return "actions";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "apps";
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "apps"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
model.values: Apps.search(search.text)
|
||||||
|
root.delegate: appItem
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "actions"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
model.values: Actions.query(search.text)
|
||||||
|
root.delegate: actionItem
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "calc"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
model.values: [0]
|
||||||
|
root.delegate: calcItem
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: Transition {
|
||||||
|
SequentialAnimation {
|
||||||
|
ParallelAnimation {
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "scale"
|
||||||
|
from: 1
|
||||||
|
to: 0.9
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
targets: [model, root]
|
||||||
|
properties: "values,delegate"
|
||||||
|
}
|
||||||
|
ParallelAnimation {
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "scale"
|
||||||
|
from: 0.9
|
||||||
|
to: 1
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
targets: [root.add, root.remove]
|
||||||
|
property: "enabled"
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomScrollBar.vertical: CustomScrollBar {
|
||||||
|
flickable: root
|
||||||
|
}
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
enabled: !root.state
|
||||||
|
|
||||||
|
Modules.Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove: Transition {
|
||||||
|
enabled: !root.state
|
||||||
|
|
||||||
|
Modules.Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
move: Transition {
|
||||||
|
Modules.Anim {
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDisplaced: Transition {
|
||||||
|
Modules.Anim {
|
||||||
|
property: "y"
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displaced: Transition {
|
||||||
|
Modules.Anim {
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: appItem
|
||||||
|
|
||||||
|
AppItem {
|
||||||
|
visibilities: root.visibilities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: actionItem
|
||||||
|
|
||||||
|
ActionItem {
|
||||||
|
list: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: calcItem
|
||||||
|
|
||||||
|
CalcItem {
|
||||||
|
list: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Shapes
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules as Modules
|
||||||
|
|
||||||
|
ShapePath {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property Wrapper wrapper
|
||||||
|
readonly property real rounding: Config.barConfig.rounding
|
||||||
|
readonly property bool flatten: wrapper.height < rounding * 2
|
||||||
|
readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
|
||||||
|
|
||||||
|
strokeWidth: -1
|
||||||
|
fillColor: DynamicColors.palette.m3surface
|
||||||
|
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.rounding
|
||||||
|
relativeY: -root.roundingY
|
||||||
|
radiusX: root.rounding
|
||||||
|
radiusY: Math.min(root.rounding, root.wrapper.height)
|
||||||
|
direction: PathArc.Counterclockwise
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
relativeX: 0
|
||||||
|
relativeY: -(root.wrapper.height - root.roundingY * 2)
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.rounding
|
||||||
|
relativeY: -root.roundingY
|
||||||
|
radiusX: root.rounding
|
||||||
|
radiusY: Math.min(root.rounding, root.wrapper.height)
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
relativeX: root.wrapper.width - root.rounding * 2
|
||||||
|
relativeY: 0
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.rounding
|
||||||
|
relativeY: root.roundingY
|
||||||
|
radiusX: root.rounding
|
||||||
|
radiusY: Math.min(root.rounding, root.wrapper.height)
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
relativeX: 0
|
||||||
|
relativeY: root.wrapper.height - root.roundingY * 2
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.rounding
|
||||||
|
relativeY: root.roundingY
|
||||||
|
radiusX: root.rounding
|
||||||
|
radiusY: Math.min(root.rounding, root.wrapper.height)
|
||||||
|
direction: PathArc.Counterclockwise
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on fillColor {
|
||||||
|
Modules.CAnim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Modules.Launcher.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules as Modules
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
required property var panels
|
||||||
|
required property real maxHeight
|
||||||
|
|
||||||
|
readonly property int padding: Appearance.padding.small
|
||||||
|
readonly property int rounding: Appearance.rounding.large
|
||||||
|
|
||||||
|
implicitWidth: listWrapper.width + padding * 2
|
||||||
|
implicitHeight: searchWrapper.height + listWrapper.height + padding * 2
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: listWrapper
|
||||||
|
|
||||||
|
implicitWidth: list.width
|
||||||
|
implicitHeight: list.height + root.padding
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottom: searchWrapper.top
|
||||||
|
anchors.bottomMargin: root.padding
|
||||||
|
|
||||||
|
ContentList {
|
||||||
|
id: list
|
||||||
|
|
||||||
|
content: root
|
||||||
|
visibilities: root.visibilities
|
||||||
|
panels: root.panels
|
||||||
|
maxHeight: root.maxHeight - searchWrapper.implicitHeight - root.padding * 3
|
||||||
|
search: search
|
||||||
|
padding: root.padding
|
||||||
|
rounding: root.rounding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: searchWrapper
|
||||||
|
|
||||||
|
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2)
|
||||||
|
radius: 8
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.margins: root.padding
|
||||||
|
|
||||||
|
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: searchIcon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: root.padding + 10
|
||||||
|
|
||||||
|
text: "search"
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomTextField {
|
||||||
|
id: search
|
||||||
|
|
||||||
|
anchors.left: searchIcon.right
|
||||||
|
anchors.right: clearIcon.left
|
||||||
|
anchors.leftMargin: Appearance.spacing.small
|
||||||
|
anchors.rightMargin: Appearance.spacing.small
|
||||||
|
|
||||||
|
topPadding: Appearance.padding.larger
|
||||||
|
bottomPadding: Appearance.padding.larger
|
||||||
|
|
||||||
|
placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
const currentItem = list.currentList?.currentItem;
|
||||||
|
if (currentItem) {
|
||||||
|
if (list.showWallpapers) {
|
||||||
|
if (DynamicColors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent)
|
||||||
|
Wallpapers.previewColourLock = true;
|
||||||
|
Wallpapers.setWallpaper(currentItem.modelData.path);
|
||||||
|
root.visibilities.launcher = false;
|
||||||
|
} else if (text.startsWith(Config.launcher.actionPrefix)) {
|
||||||
|
if (text.startsWith(`${Config.launcher.actionPrefix}calc `))
|
||||||
|
currentItem.onClicked();
|
||||||
|
else
|
||||||
|
currentItem.modelData.onClicked(list.currentList);
|
||||||
|
} else {
|
||||||
|
Apps.launch(currentItem.modelData);
|
||||||
|
root.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onUpPressed: list.currentList?.incrementCurrentIndex()
|
||||||
|
Keys.onDownPressed: list.currentList?.decrementCurrentIndex()
|
||||||
|
|
||||||
|
Keys.onEscapePressed: root.visibilities.launcher = false
|
||||||
|
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
if (!Config.launcher.vimKeybinds)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.modifiers & Qt.ControlModifier) {
|
||||||
|
if (event.key === Qt.Key_J) {
|
||||||
|
list.currentList?.incrementCurrentIndex();
|
||||||
|
event.accepted = true;
|
||||||
|
} else if (event.key === Qt.Key_K) {
|
||||||
|
list.currentList?.decrementCurrentIndex();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_Tab) {
|
||||||
|
list.currentList?.incrementCurrentIndex();
|
||||||
|
event.accepted = true;
|
||||||
|
} else if (event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier))) {
|
||||||
|
list.currentList?.decrementCurrentIndex();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: forceActiveFocus()
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.visibilities
|
||||||
|
|
||||||
|
function onLauncherChanged(): void {
|
||||||
|
if (!root.visibilities.launcher)
|
||||||
|
search.text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSessionChanged(): void {
|
||||||
|
if (!root.visibilities.session)
|
||||||
|
search.forceActiveFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: clearIcon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: root.padding + 10
|
||||||
|
|
||||||
|
width: search.text ? implicitWidth : implicitWidth / 2
|
||||||
|
opacity: {
|
||||||
|
if (!search.text)
|
||||||
|
return 0;
|
||||||
|
if (mouse.pressed)
|
||||||
|
return 0.7;
|
||||||
|
if (mouse.containsMouse)
|
||||||
|
return 0.8;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
text: "close"
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouse
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: search.text ? Qt.PointingHandCursor : undefined
|
||||||
|
|
||||||
|
onClicked: search.text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on width {
|
||||||
|
Modules.Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Modules.Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Paths
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var content
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
required property var panels
|
||||||
|
required property real maxHeight
|
||||||
|
required property CustomTextField search
|
||||||
|
required property int padding
|
||||||
|
required property int rounding
|
||||||
|
|
||||||
|
readonly property bool showWallpapers: search.text.startsWith(`${Config.launcher.actionPrefix}wallpaper `)
|
||||||
|
readonly property Item currentList: showWallpapers ? wallpaperList.item : appList.item
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
state: showWallpapers ? "wallpapers" : "apps"
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "apps"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitWidth: Config.launcher.sizes.itemWidth
|
||||||
|
root.implicitHeight: Math.min(root.maxHeight, appList.implicitHeight > 0 ? appList.implicitHeight : empty.implicitHeight)
|
||||||
|
appList.active: true
|
||||||
|
}
|
||||||
|
|
||||||
|
AnchorChanges {
|
||||||
|
anchors.left: root.parent.left
|
||||||
|
anchors.right: root.parent.right
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "wallpapers"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitWidth: Math.max(Config.launcher.sizes.itemWidth * 1.2, wallpaperList.implicitWidth)
|
||||||
|
root.implicitHeight: Config.launcher.sizes.wallpaperHeight
|
||||||
|
wallpaperList.active: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Behavior on state {
|
||||||
|
SequentialAnimation {
|
||||||
|
Anim {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
from: 1
|
||||||
|
to: 0
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
PropertyAction {}
|
||||||
|
Anim {
|
||||||
|
target: root
|
||||||
|
property: "opacity"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: appList
|
||||||
|
|
||||||
|
active: false
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
sourceComponent: AppList {
|
||||||
|
search: root.search
|
||||||
|
visibilities: root.visibilities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: wallpaperList
|
||||||
|
|
||||||
|
active: false
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
sourceComponent: WallpaperList {
|
||||||
|
search: root.search
|
||||||
|
visibilities: root.visibilities
|
||||||
|
panels: root.panels
|
||||||
|
content: root.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: empty
|
||||||
|
|
||||||
|
opacity: root.currentList?.count === 0 ? 1 : 0
|
||||||
|
scale: root.currentList?.count === 0 ? 1 : 0.5
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
padding: Appearance.padding.large
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
text: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search"
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: root.state === "wallpapers" ? qsTr("No wallpapers found") : qsTr("No results")
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Appearance.font.size.larger
|
||||||
|
font.weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: root.state === "wallpapers" && Wallpapers.list.length === 0 ? qsTr("Try putting some wallpapers in %1").arg(Paths.shortenHome(Paths.wallsdir)) : qsTr("Try searching for something else")
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on scale {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
enabled: root.visibilities.launcher
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitHeight {
|
||||||
|
enabled: root.visibilities.launcher
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Modules.Launcher.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var modelData
|
||||||
|
required property var list
|
||||||
|
|
||||||
|
implicitHeight: Config.launcher.sizes.itemHeight
|
||||||
|
|
||||||
|
anchors.left: parent?.left
|
||||||
|
anchors.right: parent?.right
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.modelData?.onClicked(root.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Appearance.padding.larger
|
||||||
|
anchors.rightMargin: Appearance.padding.larger
|
||||||
|
anchors.margins: Appearance.padding.smaller
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
text: root.modelData?.icon ?? ""
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.left: icon.right
|
||||||
|
anchors.leftMargin: Appearance.spacing.normal
|
||||||
|
anchors.verticalCenter: icon.verticalCenter
|
||||||
|
|
||||||
|
implicitWidth: parent.width - icon.width
|
||||||
|
implicitHeight: name.implicitHeight + desc.implicitHeight
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: name
|
||||||
|
|
||||||
|
text: root.modelData?.name ?? ""
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: desc
|
||||||
|
|
||||||
|
text: root.modelData?.desc ?? ""
|
||||||
|
font.pointSize: Appearance.font.size.small
|
||||||
|
color: DynamicColors.palette.m3outline
|
||||||
|
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: root.width - icon.width - Appearance.rounding.normal * 2
|
||||||
|
|
||||||
|
anchors.top: name.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import QtQuick
|
||||||
|
import qs.Modules.Launcher.Services
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property DesktopEntry modelData
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
implicitHeight: Config.launcher.sizes.itemHeight
|
||||||
|
|
||||||
|
anchors.left: parent?.left
|
||||||
|
anchors.right: parent?.right
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
Apps.launch(root.modelData);
|
||||||
|
root.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Appearance.padding.larger
|
||||||
|
anchors.rightMargin: Appearance.padding.larger
|
||||||
|
anchors.margins: Appearance.padding.smaller
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
source: Quickshell.iconPath(root.modelData?.icon, "image-missing")
|
||||||
|
implicitSize: parent.height * 0.8
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.left: icon.right
|
||||||
|
anchors.leftMargin: Appearance.spacing.normal
|
||||||
|
anchors.verticalCenter: icon.verticalCenter
|
||||||
|
|
||||||
|
implicitWidth: parent.width - icon.width
|
||||||
|
implicitHeight: name.implicitHeight + comment.implicitHeight
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: name
|
||||||
|
|
||||||
|
text: root.modelData?.name ?? ""
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: comment
|
||||||
|
|
||||||
|
text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? ""
|
||||||
|
font.pointSize: Appearance.font.size.small
|
||||||
|
color: DynamicColors.palette.m3outline
|
||||||
|
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: root.width - icon.width - Appearance.rounding.normal * 2
|
||||||
|
|
||||||
|
anchors.top: name.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import ZShell
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var list
|
||||||
|
readonly property string math: list.search.text.slice(`${Config.launcher.actionPrefix}calc `.length)
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
Quickshell.execDetached(["wl-copy", Qalculator.eval(math, false)]);
|
||||||
|
root.list.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitHeight: Config.launcher.sizes.itemHeight
|
||||||
|
|
||||||
|
anchors.left: parent?.left
|
||||||
|
anchors.right: parent?.right
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.onClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: Appearance.padding.larger
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
text: "function"
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: result
|
||||||
|
|
||||||
|
color: {
|
||||||
|
if (text.includes("error: ") || text.includes("warning: "))
|
||||||
|
return DynamicColors.palette.m3error;
|
||||||
|
if (!root.math)
|
||||||
|
return DynamicColors.palette.m3onSurfaceVariant;
|
||||||
|
return DynamicColors.palette.m3onSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
text: root.math.length > 0 ? Qalculator.eval(root.math) : qsTr("Type an expression to calculate")
|
||||||
|
elide: Text.ElideLeft
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
color: DynamicColors.palette.m3tertiary
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Appearance.padding.normal * 2
|
||||||
|
implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Appearance.padding.small * 2
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: stateLayer
|
||||||
|
|
||||||
|
color: DynamicColors.palette.m3onTertiary
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.terminal, "fish", "-C", `exec qalc -i '${root.math}'`]);
|
||||||
|
root.list.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: icon.left
|
||||||
|
anchors.rightMargin: Appearance.spacing.small
|
||||||
|
|
||||||
|
text: qsTr("Open in calculator")
|
||||||
|
color: DynamicColors.palette.m3onTertiary
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
|
||||||
|
opacity: stateLayer.containsMouse ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Appearance.padding.normal
|
||||||
|
|
||||||
|
text: "open_in_new"
|
||||||
|
color: DynamicColors.palette.m3onTertiary
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import ZShell.Models
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property FileSystemEntry modelData
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
scale: 0.5
|
||||||
|
opacity: 0
|
||||||
|
z: PathView.z ?? 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
|
||||||
|
opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: image.width + Appearance.padding.larger * 2
|
||||||
|
implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
Wallpapers.setWallpaper(root.modelData.path);
|
||||||
|
root.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Elevation {
|
||||||
|
anchors.fill: image
|
||||||
|
radius: image.radius
|
||||||
|
opacity: root.PathView.isCurrentItem ? 1 : 0
|
||||||
|
level: 4
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: image
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
y: Appearance.padding.large
|
||||||
|
color: DynamicColors.tPalette.m3surfaceContainer
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
implicitWidth: Config.launcher.sizes.wallpaperWidth
|
||||||
|
implicitHeight: implicitWidth / 16 * 9
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "image"
|
||||||
|
color: DynamicColors.tPalette.m3outline
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge * 2
|
||||||
|
font.weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
CachingImage {
|
||||||
|
path: root.modelData.path
|
||||||
|
smooth: !root.PathView.view.moving
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.top: image.bottom
|
||||||
|
anchors.topMargin: Appearance.spacing.small / 2
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
width: image.width - Appearance.padding.normal * 2
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
renderType: Text.QtRendering
|
||||||
|
text: root.modelData.relativePath
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on scale {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import qs.Modules.Launcher
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Searcher {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
function transformSearch(search: string): string {
|
||||||
|
return search.slice(Config.launcher.actionPrefix.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
list: variants.instances
|
||||||
|
useFuzzy: Config.launcher.useFuzzy.actions
|
||||||
|
|
||||||
|
Variants {
|
||||||
|
id: variants
|
||||||
|
|
||||||
|
model: Config.launcher.actions.filter(a => (a.enabled ?? true))
|
||||||
|
|
||||||
|
Action {}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Action: QtObject {
|
||||||
|
required property var modelData
|
||||||
|
readonly property string name: modelData.name ?? qsTr("Unnamed")
|
||||||
|
readonly property string desc: modelData.description ?? qsTr("No description")
|
||||||
|
readonly property string icon: modelData.icon ?? "help_outline"
|
||||||
|
readonly property list<string> command: modelData.command ?? []
|
||||||
|
readonly property bool enabled: modelData.enabled ?? true
|
||||||
|
readonly property bool dangerous: modelData.dangerous ?? false
|
||||||
|
|
||||||
|
function onClicked(list: AppList): void {
|
||||||
|
if (command.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (command[0] === "autocomplete" && command.length > 1) {
|
||||||
|
list.search.text = `${Config.launcher.actionPrefix}${command[1]} `;
|
||||||
|
} else if (command[0] === "setMode" && command.length > 1) {
|
||||||
|
list.visibilities.launcher = false;
|
||||||
|
Colours.setMode(command[1]);
|
||||||
|
} else {
|
||||||
|
list.visibilities.launcher = false;
|
||||||
|
Quickshell.execDetached(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,26 +2,31 @@ pragma Singleton
|
|||||||
|
|
||||||
import ZShell
|
import ZShell
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Paths
|
||||||
|
|
||||||
Searcher {
|
Searcher {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property string home: Quickshell.env("HOME")
|
|
||||||
|
|
||||||
function launch(entry: DesktopEntry): void {
|
function launch(entry: DesktopEntry): void {
|
||||||
appDb.incrementFrequency(entry.id);
|
appDb.incrementFrequency(entry.id);
|
||||||
|
|
||||||
console.log( "Search command:", entry.command );
|
if (entry.runInTerminal)
|
||||||
|
Quickshell.execDetached({
|
||||||
Quickshell.execDetached({
|
command: ["app2unit", "--", ...Config.general.apps.terminal, `${Quickshell.shellDir}/assets/wrap_term_launch.sh`, ...entry.command],
|
||||||
command: ["app2unit", "--", ...entry.command],
|
workingDirectory: entry.workingDirectory
|
||||||
workingDirectory: entry.workingDirectory || Quickshell.env("HOME")
|
});
|
||||||
});
|
else
|
||||||
|
Quickshell.execDetached({
|
||||||
|
command: ["app2unit", "--", ...entry.command],
|
||||||
|
workingDirectory: entry.workingDirectory
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(search: string): list<var> {
|
function search(search: string): list<var> {
|
||||||
const prefix = ">";
|
const prefix = Config.launcher.specialPrefix;
|
||||||
|
|
||||||
if (search.startsWith(`${prefix}i `)) {
|
if (search.startsWith(`${prefix}i `)) {
|
||||||
keys = ["id", "name"];
|
keys = ["id", "name"];
|
||||||
weights = [0.9, 0.1];
|
weights = [0.9, 0.1];
|
||||||
@@ -62,12 +67,12 @@ Searcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
list: appDb.apps
|
list: appDb.apps
|
||||||
useFuzzy: true
|
useFuzzy: Config.launcher.useFuzzy.apps
|
||||||
|
|
||||||
AppDb {
|
AppDb {
|
||||||
id: appDb
|
id: appDb
|
||||||
|
|
||||||
path: `${root.home}/.local/share/z-cast-qt/apps.sqlite`
|
path: `${Paths.state}/apps.sqlite`
|
||||||
entries: DesktopEntries.applications.values
|
entries: DesktopEntries.applications.values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules.Launcher.Items
|
||||||
|
|
||||||
|
PathView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property CustomTextField search
|
||||||
|
required property var visibilities
|
||||||
|
required property var panels
|
||||||
|
required property var content
|
||||||
|
|
||||||
|
readonly property int itemWidth: Config.launcher.sizes.wallpaperWidth * 0.8 + Appearance.padding.larger * 2
|
||||||
|
|
||||||
|
readonly property int numItems: {
|
||||||
|
const screen = QsWindow.window?.screen;
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Screen width - 4x outer rounding - 2x max side thickness (cause centered)
|
||||||
|
const barMargins = panels.bar.implicitWidth;
|
||||||
|
let outerMargins = 0;
|
||||||
|
if (panels.popouts.hasCurrent && panels.popouts.currentCenter + panels.popouts.nonAnimHeight / 2 > screen.height - content.implicitHeight)
|
||||||
|
outerMargins = panels.popouts.nonAnimWidth;
|
||||||
|
if ((visibilities.utilities || visibilities.sidebar) && panels.utilities.implicitWidth > outerMargins)
|
||||||
|
outerMargins = panels.utilities.implicitWidth;
|
||||||
|
const maxWidth = screen.width - Config.barConfig.rounding * 4 - (barMargins + outerMargins) * 2;
|
||||||
|
|
||||||
|
if (maxWidth <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const maxItemsOnScreen = Math.floor(maxWidth / itemWidth);
|
||||||
|
const visible = Math.min(maxItemsOnScreen, Config.launcher.maxWallpapers, scriptModel.values.length);
|
||||||
|
|
||||||
|
if (visible === 2)
|
||||||
|
return 1;
|
||||||
|
if (visible > 1 && visible % 2 === 0)
|
||||||
|
return visible - 1;
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
model: ScriptModel {
|
||||||
|
id: scriptModel
|
||||||
|
|
||||||
|
readonly property string search: root.search.text.split(" ").slice(1).join(" ")
|
||||||
|
|
||||||
|
values: Wallpapers.query(search)
|
||||||
|
onValuesChanged: root.currentIndex = search ? 0 : values.findIndex(w => w.path === Wallpapers.actualCurrent)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: currentIndex = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent)
|
||||||
|
Component.onDestruction: Wallpapers.stopPreview()
|
||||||
|
|
||||||
|
onCurrentItemChanged: {
|
||||||
|
if (currentItem)
|
||||||
|
Wallpapers.preview(currentItem.modelData.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: Math.min(numItems, count) * itemWidth
|
||||||
|
pathItemCount: numItems
|
||||||
|
cacheItemCount: 4
|
||||||
|
|
||||||
|
snapMode: PathView.SnapToItem
|
||||||
|
preferredHighlightBegin: 0.5
|
||||||
|
preferredHighlightEnd: 0.5
|
||||||
|
highlightRangeMode: PathView.StrictlyEnforceRange
|
||||||
|
|
||||||
|
delegate: WallpaperItem {
|
||||||
|
visibilities: root.visibilities
|
||||||
|
}
|
||||||
|
|
||||||
|
path: Path {
|
||||||
|
startY: root.height / 2
|
||||||
|
|
||||||
|
PathAttribute {
|
||||||
|
name: "z"
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: root.width / 2
|
||||||
|
relativeY: 0
|
||||||
|
}
|
||||||
|
PathAttribute {
|
||||||
|
name: "z"
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: root.width
|
||||||
|
relativeY: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Modules as Modules
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property ShellScreen screen
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
required property var panels
|
||||||
|
|
||||||
|
readonly property bool shouldBeActive: visibilities.launcher
|
||||||
|
property int contentHeight
|
||||||
|
|
||||||
|
readonly property real maxHeight: {
|
||||||
|
let max = screen.height - Appearance.spacing.large;
|
||||||
|
if (visibilities.dashboard)
|
||||||
|
max -= panels.dashboard.nonAnimHeight;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMaxHeightChanged: timer.start()
|
||||||
|
|
||||||
|
visible: height > 0
|
||||||
|
implicitHeight: 0
|
||||||
|
implicitWidth: content.implicitWidth
|
||||||
|
|
||||||
|
onShouldBeActiveChanged: {
|
||||||
|
if (shouldBeActive) {
|
||||||
|
timer.stop();
|
||||||
|
hideAnim.stop();
|
||||||
|
showAnim.start();
|
||||||
|
} else {
|
||||||
|
showAnim.stop();
|
||||||
|
hideAnim.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: showAnim
|
||||||
|
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "implicitHeight"
|
||||||
|
to: root.contentHeight
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
ScriptAction {
|
||||||
|
script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: hideAnim
|
||||||
|
|
||||||
|
ScriptAction {
|
||||||
|
script: root.implicitHeight = root.implicitHeight
|
||||||
|
}
|
||||||
|
Modules.Anim {
|
||||||
|
target: root
|
||||||
|
property: "implicitHeight"
|
||||||
|
to: 0
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Config.launcher
|
||||||
|
|
||||||
|
function onEnabledChanged(): void {
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMaxShownChanged(): void {
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: DesktopEntries.applications
|
||||||
|
|
||||||
|
function onValuesChanged(): void {
|
||||||
|
if (DesktopEntries.applications.values.length < Config.launcher.maxAppsShown)
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
|
||||||
|
interval: Appearance.anim.durations.small
|
||||||
|
onRunningChanged: {
|
||||||
|
if (running && !root.shouldBeActive) {
|
||||||
|
content.visible = false;
|
||||||
|
content.active = true;
|
||||||
|
} else {
|
||||||
|
root.contentHeight = Math.min(root.maxHeight, content.implicitHeight);
|
||||||
|
content.active = Qt.binding(() => root.shouldBeActive || root.visible);
|
||||||
|
content.visible = true;
|
||||||
|
if (showAnim.running) {
|
||||||
|
showAnim.stop();
|
||||||
|
showAnim.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
active: false
|
||||||
|
Component.onCompleted: timer.start()
|
||||||
|
|
||||||
|
sourceComponent: Content {
|
||||||
|
visibilities: root.visibilities
|
||||||
|
panels: root.panels
|
||||||
|
maxHeight: root.maxHeight
|
||||||
|
|
||||||
|
Component.onCompleted: root.contentHeight = implicitHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import ZShell
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool launcherInterrupted
|
||||||
|
readonly property bool hasFullscreen: Hypr.focusedWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) ?? false
|
||||||
|
|
||||||
|
CustomShortcut {
|
||||||
|
name: "toggle-launcher"
|
||||||
|
description: "Toggle launcher"
|
||||||
|
onPressed: root.launcherInterrupted = false
|
||||||
|
onReleased: {
|
||||||
|
if (!root.launcherInterrupted && !root.hasFullscreen) {
|
||||||
|
const visibilities = Visibilities.getForActive();
|
||||||
|
visibilities.launcher = !visibilities.launcher;
|
||||||
|
}
|
||||||
|
root.launcherInterrupted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.Wayland
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick
|
|
||||||
import qs.Components
|
|
||||||
import qs.Config
|
|
||||||
import qs.Daemons
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Effects
|
|
||||||
|
|
||||||
PanelWindow {
|
|
||||||
id: root
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
top: true
|
|
||||||
right: true
|
|
||||||
left: true
|
|
||||||
bottom: true
|
|
||||||
}
|
|
||||||
|
|
||||||
WlrLayershell.namespace: "ZShell-Notifs"
|
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
|
||||||
|
|
||||||
mask: Region { regions: root.notifRegions }
|
|
||||||
exclusionMode: ExclusionMode.Ignore
|
|
||||||
property list<Region> notifRegions: []
|
|
||||||
required property bool centerShown
|
|
||||||
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3onSurface : "white"
|
|
||||||
property color backgroundColor: Config.useDynamicColors ? DynamicColors.tPalette.m3surface : Config.baseBgColor
|
|
||||||
// visible: Hyprland.monitorFor(screen).focused
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: notifListView
|
|
||||||
model: ScriptModel {
|
|
||||||
values: NotifServer.list.filter( n => n.popup )
|
|
||||||
onValuesChanged: {
|
|
||||||
if ( values.length === 0 )
|
|
||||||
root.notifRegions = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
x: root.centerShown ? root.screen.width - width - 420 : root.screen.width - width - 20
|
|
||||||
z: 0
|
|
||||||
anchors.topMargin: 54
|
|
||||||
width: 400
|
|
||||||
spacing: 10
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: MaterialEasing.expressiveEffectsTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
displaced: Transition {
|
|
||||||
NumberAnimation {
|
|
||||||
property: "y"
|
|
||||||
duration: 100
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove: Transition {
|
|
||||||
id: hideTransition
|
|
||||||
ParallelAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
property: "opacity"
|
|
||||||
from: 1
|
|
||||||
to: 0
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
property: "x"
|
|
||||||
to: hideTransition.ViewTransition.destination.x + 200
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add: Transition {
|
|
||||||
id: showTransition
|
|
||||||
ParallelAnimation {
|
|
||||||
NumberAnimation {
|
|
||||||
property: "opacity"
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
property: "x"
|
|
||||||
from: showTransition.ViewTransition.destination.x + 200
|
|
||||||
to: showTransition.ViewTransition.destination.x
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component NotifRegion: Region { }
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: notifRegion
|
|
||||||
NotifRegion {}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
id: rootItem
|
|
||||||
implicitWidth: 400
|
|
||||||
implicitHeight: contentLayout.childrenRect.height + 16
|
|
||||||
required property NotifServer.Notif modelData
|
|
||||||
|
|
||||||
ShadowRect {
|
|
||||||
anchors.fill: backgroundRect
|
|
||||||
radius: backgroundRect.radius
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomClippingRect {
|
|
||||||
id: backgroundRect
|
|
||||||
implicitWidth: 400
|
|
||||||
implicitHeight: contentLayout.childrenRect.height + 16
|
|
||||||
color: root.backgroundColor
|
|
||||||
border.width: Config.useDynamicColors ? 0 : 1
|
|
||||||
border.color: "#555555"
|
|
||||||
radius: 8
|
|
||||||
|
|
||||||
CustomRect {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
color: DynamicColors.palette.m3primary
|
|
||||||
|
|
||||||
implicitHeight: 4
|
|
||||||
implicitWidth: ( rootItem.modelData.timer.remainingTime / rootItem.modelData.timer.totalTime ) * parent.width
|
|
||||||
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
Anim {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
root.notifRegions.push( notifRegion.createObject(root, { item: backgroundRect }));
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: contentLayout
|
|
||||||
z: 0
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.margins: 10
|
|
||||||
spacing: 8
|
|
||||||
RowLayout {
|
|
||||||
spacing: 12
|
|
||||||
IconImage {
|
|
||||||
source: rootItem.modelData.image === "" ? Qt.resolvedUrl(rootItem.modelData.appIcon) : Qt.resolvedUrl(rootItem.modelData.image)
|
|
||||||
Layout.preferredWidth: 48
|
|
||||||
Layout.preferredHeight: 48
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignLeft
|
|
||||||
// visible: rootItem.modelData.image !== ""
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.leftMargin: 0
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: rootItem.modelData.appName
|
|
||||||
color: root.textColor
|
|
||||||
font.bold: true
|
|
||||||
font.pointSize: 14
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: rootItem.modelData.summary
|
|
||||||
color: root.textColor
|
|
||||||
font.pointSize: 12
|
|
||||||
font.bold: true
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: rootItem.modelData.body
|
|
||||||
color: root.textColor
|
|
||||||
font.pointSize: 14
|
|
||||||
textFormat: Text.MarkdownText
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
maximumLineCount: 4
|
|
||||||
width: parent.width
|
|
||||||
linkColor: Config.accentColor.accents.primaryAlt
|
|
||||||
|
|
||||||
onLinkActivated: link => {
|
|
||||||
Quickshell.execDetached(["app2unit", "-O", "--", link]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.rightMargin: 6
|
|
||||||
anchors.topMargin: 6
|
|
||||||
width: 18
|
|
||||||
height: 18
|
|
||||||
color: closeArea.containsMouse ? "#FF6077" : "transparent"
|
|
||||||
radius: 9
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "✕"
|
|
||||||
color: closeArea.containsMouse ? "white" : "#888888"
|
|
||||||
font.pointSize: 12
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: closeArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: {
|
|
||||||
rootItem.modelData.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElapsedTimer {
|
|
||||||
id: timer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ import qs.Config
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string source: SearchWallpapers.current
|
property string source: Wallpapers.current
|
||||||
property Image current: one
|
property Image current: one
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -50,7 +50,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
opacity: 0
|
opacity: 0
|
||||||
scale: SearchWallpapers.showPreview ? 1 : 0.8
|
scale: Wallpapers.showPreview ? 1 : 0.8
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
if (status === Image.Ready) {
|
if (status === Image.Ready) {
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import QtQuick
|
|
||||||
import ZShell.Models
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
required property FileSystemEntry modelData
|
|
||||||
implicitWidth: 288
|
|
||||||
implicitHeight: 162
|
|
||||||
|
|
||||||
scale: 0.5
|
|
||||||
opacity: 0
|
|
||||||
z: PathView.z ?? 0
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
|
|
||||||
opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: 8
|
|
||||||
color: "#10FFFFFF"
|
|
||||||
Image {
|
|
||||||
id: thumbnailImage
|
|
||||||
|
|
||||||
asynchronous: true
|
|
||||||
anchors.fill: parent
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
source: root.modelData.path
|
|
||||||
sourceSize.width: 960
|
|
||||||
sourceSize.height: 540
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
Anim {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Config
|
|
||||||
import qs.Components
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
property string currentTitle: Hypr.activeName
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: Math.max( titleText1.implicitWidth, titleText2.implicitWidth ) + 10
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
property bool showFirst: true
|
|
||||||
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "white"
|
|
||||||
|
|
||||||
// Component.onCompleted: {
|
|
||||||
// Hyprland.rawEvent.connect(( event ) => {
|
|
||||||
// if (event.name === "activewindow") {
|
|
||||||
// InitialTitle.getInitialTitle( function( initialTitle ) {
|
|
||||||
// root.currentTitle = initialTitle
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
onCurrentTitleChanged: {
|
|
||||||
if (showFirst) {
|
|
||||||
titleText2.text = currentTitle
|
|
||||||
showFirst = false
|
|
||||||
} else {
|
|
||||||
titleText1.text = currentTitle
|
|
||||||
showFirst = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: titleText1
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 5
|
|
||||||
text: root.currentTitle
|
|
||||||
color: root.textColor
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pixelSize: 16
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
opacity: root.showFirst ? 1 : 0
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: titleText2
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 5
|
|
||||||
color: root.textColor
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pixelSize: 16
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
opacity: root.showFirst ? 0 : 1
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,19 +10,15 @@ import qs.Modules.Polkit
|
|||||||
ShellRoot {
|
ShellRoot {
|
||||||
Bar {}
|
Bar {}
|
||||||
Wallpaper {}
|
Wallpaper {}
|
||||||
Launcher {}
|
|
||||||
AreaPicker {}
|
AreaPicker {}
|
||||||
Lock.Lock {
|
Lock.Lock {
|
||||||
id: lock
|
id: lock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shortcuts {}
|
||||||
Lock.IdleInhibitor {
|
Lock.IdleInhibitor {
|
||||||
lock: lock
|
lock: lock
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotificationCenter {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
Polkit {}
|
Polkit {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user