formatter

This commit is contained in:
Zacharias-Brohn
2026-02-24 23:20:11 +01:00
parent 40cd984b6d
commit d56a0260fb
202 changed files with 15037 additions and 15352 deletions
+176 -180
View File
@@ -8,211 +8,207 @@ import qs.Components
import qs.Config
CustomListView {
id: root
id: root
required property CustomTextField search
required property PersistentProperties visibilities
required property CustomTextField search
required property PersistentProperties visibilities
model: ScriptModel {
id: model
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
orientation: Qt.Vertical
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Appearance.spacing.small
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;
onValuesChanged: root.currentIndex = 0
}
return "actions";
}
return "apps";
}
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
CustomScrollBar.vertical: CustomScrollBar {
flickable: root
}
add: Transition {
enabled: !root.state
highlightFollowsCurrentItem: false
highlight: CustomRect {
radius: 8
color: DynamicColors.palette.m3onSurface
opacity: 0.08
Anim {
from: 0
properties: "opacity,scale"
to: 1
}
}
addDisplaced: Transition {
Anim {
duration: Appearance.anim.durations.small
property: "y"
}
y: root.currentItem?.y ?? 0
implicitWidth: root.width
implicitHeight: root.currentItem?.implicitHeight ?? 0
Anim {
properties: "opacity,scale"
to: 1
}
}
displaced: Transition {
Anim {
property: "y"
}
Behavior on y {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
}
Anim {
properties: "opacity,scale"
to: 1
}
}
highlight: CustomRect {
color: DynamicColors.palette.m3onSurface
implicitHeight: root.currentItem?.implicitHeight ?? 0
implicitWidth: root.width
opacity: 0.08
radius: 8
y: root.currentItem?.y ?? 0
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;
Behavior on y {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
}
model: ScriptModel {
id: model
return "actions";
}
onValuesChanged: root.currentIndex = 0
}
move: Transition {
Anim {
property: "y"
}
return "apps";
}
Anim {
properties: "opacity,scale"
to: 1
}
}
remove: Transition {
enabled: !root.state
states: [
State {
name: "apps"
Anim {
from: 1
properties: "opacity,scale"
to: 0
}
}
states: [
State {
name: "apps"
PropertyChanges {
model.values: Apps.search(search.text)
root.delegate: appItem
}
},
State {
name: "actions"
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: Actions.query(search.text)
root.delegate: actionItem
}
},
State {
name: "calc"
PropertyChanges {
model.values: [0]
root.delegate: calcItem
}
},
]
PropertyChanges {
model.values: [0]
root.delegate: calcItem
}
}
]
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
from: 1
property: "opacity"
target: root
to: 0
}
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
Anim {
target: root
property: "opacity"
from: 1
to: 0
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
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 {
Anim {
target: root
property: "opacity"
from: 0
to: 1
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
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
}
}
}
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
from: 1
property: "scale"
target: root
to: 0.9
}
}
CustomScrollBar.vertical: CustomScrollBar {
flickable: root
}
PropertyAction {
properties: "values,delegate"
targets: [model, root]
}
add: Transition {
enabled: !root.state
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
from: 0
property: "opacity"
target: root
to: 1
}
Anim {
properties: "opacity,scale"
from: 0
to: 1
}
}
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
from: 0.9
property: "scale"
target: root
to: 1
}
}
remove: Transition {
enabled: !root.state
PropertyAction {
property: "enabled"
targets: [root.add, root.remove]
value: true
}
}
}
Anim {
properties: "opacity,scale"
from: 1
to: 0
}
}
Component {
id: appItem
move: Transition {
Anim {
property: "y"
}
Anim {
properties: "opacity,scale"
to: 1
}
}
AppItem {
visibilities: root.visibilities
}
}
addDisplaced: Transition {
Anim {
property: "y"
duration: Appearance.anim.durations.small
}
Anim {
properties: "opacity,scale"
to: 1
}
}
Component {
id: actionItem
displaced: Transition {
Anim {
property: "y"
}
Anim {
properties: "opacity,scale"
to: 1
}
}
ActionItem {
list: root
}
}
Component {
id: appItem
Component {
id: calcItem
AppItem {
visibilities: root.visibilities
}
}
Component {
id: actionItem
ActionItem {
list: root
}
}
Component {
id: calcItem
CalcItem {
list: root
}
}
CalcItem {
list: root
}
}
}
+55 -48
View File
@@ -4,56 +4,63 @@ import qs.Components
import qs.Config
ShapePath {
id: root
id: root
required property Wrapper wrapper
readonly property real rounding: Config.barConfig.rounding + 5
readonly property bool flatten: wrapper.height < rounding * 2
readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
readonly property bool flatten: wrapper.height < rounding * 2
readonly property real rounding: Config.barConfig.rounding + 5
readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
required property Wrapper wrapper
strokeWidth: -1
fillColor: DynamicColors.palette.m3surface
fillColor: DynamicColors.palette.m3surface
strokeWidth: -1
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 {
CAnim {
}
}
Behavior on fillColor {
CAnim {}
}
PathArc {
direction: PathArc.Counterclockwise
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: -root.roundingY
}
PathLine {
relativeX: 0
relativeY: -(root.wrapper.height - root.roundingY * 2)
}
PathArc {
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: -root.roundingY
}
PathLine {
relativeX: root.wrapper.width - root.rounding * 2
relativeY: 0
}
PathArc {
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: root.roundingY
}
PathLine {
relativeX: 0
relativeY: root.wrapper.height - root.roundingY * 2
}
PathArc {
direction: PathArc.Counterclockwise
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: root.roundingY
}
}
+142 -156
View File
@@ -8,183 +8,169 @@ import qs.Helpers
import qs.Config
Item {
id: root
id: root
required property PersistentProperties visibilities
required property var panels
required property real maxHeight
required property real maxHeight
readonly property int padding: Appearance.padding.small
required property var panels
readonly property int rounding: Appearance.rounding.large
required property PersistentProperties visibilities
readonly property int padding: Appearance.padding.small
readonly property int rounding: Appearance.rounding.large
implicitHeight: searchWrapper.height + listWrapper.height + padding * 2
implicitWidth: listWrapper.width + padding * 2
implicitWidth: listWrapper.width + padding * 2
implicitHeight: searchWrapper.height + listWrapper.height + padding * 2
Item {
id: listWrapper
Item {
id: listWrapper
anchors.bottom: searchWrapper.top
anchors.bottomMargin: root.padding
anchors.horizontalCenter: parent.horizontalCenter
implicitHeight: list.height + root.padding
implicitWidth: list.width
implicitWidth: list.width
implicitHeight: list.height + root.padding
ContentList {
id: list
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: searchWrapper.top
anchors.bottomMargin: root.padding
content: root
maxHeight: root.maxHeight - searchWrapper.implicitHeight - root.padding * 3
padding: root.padding
panels: root.panels
rounding: root.rounding
search: search
visibilities: root.visibilities
}
}
ContentList {
id: list
CustomRect {
id: searchWrapper
content: root
visibilities: root.visibilities
panels: root.panels
maxHeight: root.maxHeight - searchWrapper.implicitHeight - root.padding * 3
search: search
padding: root.padding
rounding: root.rounding
}
}
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: root.padding
anchors.right: parent.right
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2)
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
radius: 8
CustomRect {
id: searchWrapper
MaterialIcon {
id: searchIcon
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2)
radius: 8
anchors.left: parent.left
anchors.leftMargin: root.padding + 10
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3onSurfaceVariant
text: "search"
}
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: root.padding
CustomTextField {
id: search
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
anchors.left: searchIcon.right
anchors.leftMargin: Appearance.spacing.small
anchors.right: clearIcon.left
anchors.rightMargin: Appearance.spacing.small
bottomPadding: Appearance.padding.larger
placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
topPadding: Appearance.padding.larger
MaterialIcon {
id: searchIcon
Component.onCompleted: forceActiveFocus()
Keys.onDownPressed: list.currentList?.decrementCurrentIndex()
Keys.onEscapePressed: root.visibilities.launcher = false
Keys.onPressed: event => {
if (!Config.launcher.vimKeybinds)
return;
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: root.padding + 10
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;
}
}
Keys.onUpPressed: list.currentList?.incrementCurrentIndex()
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;
}
}
}
text: "search"
color: DynamicColors.palette.m3onSurfaceVariant
}
Connections {
function onLauncherChanged(): void {
if (!root.visibilities.launcher)
search.text = "";
}
CustomTextField {
id: search
function onSessionChanged(): void {
if (!root.visibilities.session)
search.forceActiveFocus();
}
anchors.left: searchIcon.right
anchors.right: clearIcon.left
anchors.leftMargin: Appearance.spacing.small
anchors.rightMargin: Appearance.spacing.small
target: root.visibilities
}
}
topPadding: Appearance.padding.larger
bottomPadding: Appearance.padding.larger
MaterialIcon {
id: clearIcon
placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
anchors.right: parent.right
anchors.rightMargin: root.padding + 10
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3onSurfaceVariant
opacity: {
if (!search.text)
return 0;
if (mouse.pressed)
return 0.7;
if (mouse.containsMouse)
return 0.8;
return 1;
}
text: "close"
width: search.text ? implicitWidth : implicitWidth / 2
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;
}
}
}
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
Behavior on width {
Anim {
duration: Appearance.anim.durations.small
}
}
Keys.onUpPressed: list.currentList?.incrementCurrentIndex()
Keys.onDownPressed: list.currentList?.decrementCurrentIndex()
MouseArea {
id: mouse
Keys.onEscapePressed: root.visibilities.launcher = false
anchors.fill: parent
cursorShape: search.text ? Qt.PointingHandCursor : undefined
hoverEnabled: true
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 {
Anim {
duration: Appearance.anim.durations.small
}
}
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
}
}
onClicked: search.text = ""
}
}
}
}
+129 -135
View File
@@ -9,162 +9,156 @@ import qs.Helpers
import qs.Config
Item {
id: root
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
required property var content
readonly property Item currentList: showWallpapers ? wallpaperList.item : appList.item
required property real maxHeight
required property int padding
required property var panels
required property int rounding
required property CustomTextField search
readonly property bool showWallpapers: search.text.startsWith(`${Config.launcher.actionPrefix}wallpaper `)
required property PersistentProperties visibilities
readonly property bool showWallpapers: search.text.startsWith(`${Config.launcher.actionPrefix}wallpaper `)
readonly property Item currentList: showWallpapers ? wallpaperList.item : appList.item
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
clip: true
state: showWallpapers ? "wallpapers" : "apps"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
Behavior on implicitHeight {
enabled: root.visibilities.launcher
clip: true
state: showWallpapers ? "wallpapers" : "apps"
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
Behavior on implicitWidth {
enabled: root.visibilities.launcher
states: [
State {
name: "apps"
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
Behavior on state {
SequentialAnimation {
Anim {
duration: Appearance.anim.durations.small
from: 1
property: "opacity"
target: root
to: 0
}
PropertyChanges {
root.implicitWidth: Config.launcher.sizes.itemWidth
root.implicitHeight: Math.min(root.maxHeight, appList.implicitHeight > 0 ? appList.implicitHeight : empty.implicitHeight)
appList.active: true
}
PropertyAction {
}
AnchorChanges {
anchors.left: root.parent.left
anchors.right: root.parent.right
}
},
State {
name: "wallpapers"
Anim {
duration: Appearance.anim.durations.small
from: 0
property: "opacity"
target: root
to: 1
}
}
}
states: [
State {
name: "apps"
PropertyChanges {
root.implicitWidth: Math.max(Config.launcher.sizes.itemWidth * 1.2, wallpaperList.implicitWidth)
root.implicitHeight: Config.launcher.sizes.wallpaperHeight
wallpaperList.active: true
}
}
]
PropertyChanges {
appList.active: true
root.implicitHeight: Math.min(root.maxHeight, appList.implicitHeight > 0 ? appList.implicitHeight : empty.implicitHeight)
root.implicitWidth: Config.launcher.sizes.itemWidth
}
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
}
}
}
AnchorChanges {
anchors.left: root.parent.left
anchors.right: root.parent.right
}
},
State {
name: "wallpapers"
Loader {
id: appList
PropertyChanges {
root.implicitHeight: Config.launcher.sizes.wallpaperHeight
root.implicitWidth: Math.max(Config.launcher.sizes.itemWidth * 1.2, wallpaperList.implicitWidth)
wallpaperList.active: true
}
}
]
active: false
Loader {
id: appList
anchors.fill: parent
active: false
anchors.fill: parent
sourceComponent: AppList {
search: root.search
visibilities: root.visibilities
}
}
sourceComponent: AppList {
search: root.search
visibilities: root.visibilities
}
}
Loader {
id: wallpaperList
Loader {
id: wallpaperList
active: false
active: false
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: WallpaperList {
content: root.content
panels: root.panels
search: root.search
visibilities: root.visibilities
}
}
sourceComponent: WallpaperList {
search: root.search
visibilities: root.visibilities
panels: root.panels
content: root.content
}
}
Row {
id: empty
Row {
id: empty
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
opacity: root.currentList?.count === 0 ? 1 : 0
padding: Appearance.padding.large
scale: root.currentList?.count === 0 ? 1 : 0.5
spacing: Appearance.spacing.normal
opacity: root.currentList?.count === 0 ? 1 : 0
scale: root.currentList?.count === 0 ? 1 : 0.5
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
spacing: Appearance.spacing.normal
padding: Appearance.padding.large
MaterialIcon {
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.extraLarge
text: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search"
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Column {
anchors.verticalCenter: parent.verticalCenter
MaterialIcon {
text: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search"
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.extraLarge
CustomText {
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger
font.weight: 500
text: root.state === "wallpapers" ? qsTr("No wallpapers found") : qsTr("No results")
}
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
}
}
CustomText {
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
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")
}
}
}
}
+45 -50
View File
@@ -5,66 +5,61 @@ import qs.Helpers
import qs.Config
Item {
id: root
id: root
required property var modelData
required property var list
required property var list
required property var modelData
implicitHeight: Config.launcher.sizes.itemHeight
anchors.left: parent?.left
anchors.right: parent?.right
implicitHeight: Config.launcher.sizes.itemHeight
anchors.left: parent?.left
anchors.right: parent?.right
StateLayer {
function onClicked(): void {
root.modelData?.onClicked(root.list);
}
StateLayer {
radius: Appearance.rounding.normal
radius: Appearance.rounding.normal
}
function onClicked(): void {
root.modelData?.onClicked(root.list);
}
}
Item {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.larger
anchors.margins: Appearance.padding.smaller
anchors.rightMargin: Appearance.padding.larger
Item {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.larger
anchors.rightMargin: Appearance.padding.larger
anchors.margins: Appearance.padding.smaller
MaterialIcon {
id: icon
MaterialIcon {
id: icon
anchors.verticalCenter: parent.verticalCenter
font.pointSize: Appearance.font.size.extraLarge
text: root.modelData?.icon ?? ""
}
text: root.modelData?.icon ?? ""
font.pointSize: Appearance.font.size.extraLarge
Item {
anchors.left: icon.right
anchors.leftMargin: Appearance.spacing.normal
anchors.verticalCenter: icon.verticalCenter
implicitHeight: name.implicitHeight + desc.implicitHeight
implicitWidth: parent.width - icon.width
anchors.verticalCenter: parent.verticalCenter
}
CustomText {
id: name
Item {
anchors.left: icon.right
anchors.leftMargin: Appearance.spacing.normal
anchors.verticalCenter: icon.verticalCenter
font.pointSize: Appearance.font.size.normal
text: root.modelData?.name ?? ""
}
implicitWidth: parent.width - icon.width
implicitHeight: name.implicitHeight + desc.implicitHeight
CustomText {
id: desc
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
}
}
}
anchors.top: name.bottom
color: DynamicColors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
text: root.modelData?.desc ?? ""
width: root.width - icon.width - Appearance.rounding.normal * 2
}
}
}
}
+46 -51
View File
@@ -8,67 +8,62 @@ import qs.Config
import qs.Modules
Item {
id: root
id: root
required property DesktopEntry modelData
required property PersistentProperties visibilities
required property DesktopEntry modelData
required property PersistentProperties visibilities
implicitHeight: Config.launcher.sizes.itemHeight
anchors.left: parent?.left
anchors.right: parent?.right
implicitHeight: Config.launcher.sizes.itemHeight
anchors.left: parent?.left
anchors.right: parent?.right
StateLayer {
function onClicked(): void {
Apps.launch(root.modelData);
root.visibilities.launcher = false;
}
StateLayer {
radius: 8
radius: 8
}
function onClicked(): void {
Apps.launch(root.modelData);
root.visibilities.launcher = false;
}
}
Item {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.larger
anchors.margins: Appearance.padding.smaller
anchors.rightMargin: Appearance.padding.larger
Item {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.larger
anchors.rightMargin: Appearance.padding.larger
anchors.margins: Appearance.padding.smaller
IconImage {
id: icon
IconImage {
id: icon
anchors.verticalCenter: parent.verticalCenter
implicitSize: parent.height
source: Quickshell.iconPath(root.modelData?.icon, "image-missing")
}
source: Quickshell.iconPath(root.modelData?.icon, "image-missing")
implicitSize: parent.height
Item {
anchors.left: icon.right
anchors.leftMargin: Appearance.spacing.normal
anchors.verticalCenter: icon.verticalCenter
implicitHeight: name.implicitHeight + comment.implicitHeight
implicitWidth: parent.width - icon.width
anchors.verticalCenter: parent.verticalCenter
}
CustomText {
id: name
Item {
anchors.left: icon.right
anchors.leftMargin: Appearance.spacing.normal
anchors.verticalCenter: icon.verticalCenter
font.pointSize: Appearance.font.size.normal
text: root.modelData?.name ?? ""
}
implicitWidth: parent.width - icon.width
implicitHeight: name.implicitHeight + comment.implicitHeight
CustomText {
id: comment
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
}
}
}
anchors.top: name.bottom
color: DynamicColors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? ""
width: root.width - icon.width - Appearance.rounding.normal * 2
}
}
}
}
+86 -94
View File
@@ -8,117 +8,109 @@ import qs.Helpers
import qs.Config
Item {
id: root
id: root
required property var list
readonly property string math: list.search.text.slice(`${Config.launcher.actionPrefix}calc `.length)
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;
}
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
implicitHeight: Config.launcher.sizes.itemHeight
anchors.left: parent?.left
anchors.right: parent?.right
StateLayer {
function onClicked(): void {
root.onClicked();
}
StateLayer {
radius: Appearance.rounding.normal
radius: Appearance.rounding.normal
}
function onClicked(): void {
root.onClicked();
}
}
RowLayout {
anchors.left: parent.left
anchors.margins: Appearance.padding.larger
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Appearance.padding.larger
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
font.pointSize: Appearance.font.size.extraLarge
text: "function"
}
spacing: Appearance.spacing.normal
CustomText {
id: result
MaterialIcon {
text: "function"
font.pointSize: Appearance.font.size.extraLarge
Layout.alignment: Qt.AlignVCenter
}
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: {
if (text.includes("error: ") || text.includes("warning: "))
return DynamicColors.palette.m3error;
if (!root.math)
return DynamicColors.palette.m3onSurfaceVariant;
return DynamicColors.palette.m3onSurface;
}
elide: Text.ElideLeft
text: root.math.length > 0 ? Qalculator.eval(root.math) : qsTr("Type an expression to calculate")
}
CustomText {
id: result
CustomRect {
Layout.alignment: Qt.AlignVCenter
clip: true
color: DynamicColors.palette.m3tertiary
implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Appearance.padding.small * 2
implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Appearance.padding.normal * 2
radius: Appearance.rounding.normal
color: {
if (text.includes("error: ") || text.includes("warning: "))
return DynamicColors.palette.m3error;
if (!root.math)
return DynamicColors.palette.m3onSurfaceVariant;
return DynamicColors.palette.m3onSurface;
}
Behavior on implicitWidth {
Anim {
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
text: root.math.length > 0 ? Qalculator.eval(root.math) : qsTr("Type an expression to calculate")
elide: Text.ElideLeft
StateLayer {
id: stateLayer
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
function onClicked(): void {
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.terminal, "fish", "-C", `exec qalc -i '${root.math}'`]);
root.list.visibilities.launcher = false;
}
CustomRect {
color: DynamicColors.palette.m3tertiary
radius: Appearance.rounding.normal
clip: true
color: DynamicColors.palette.m3onTertiary
}
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
CustomText {
id: label
Layout.alignment: Qt.AlignVCenter
anchors.right: icon.left
anchors.rightMargin: Appearance.spacing.small
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3onTertiary
font.pointSize: Appearance.font.size.normal
opacity: stateLayer.containsMouse ? 1 : 0
text: qsTr("Open in calculator")
StateLayer {
id: stateLayer
Behavior on opacity {
Anim {
}
}
}
color: DynamicColors.palette.m3onTertiary
MaterialIcon {
id: icon
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
}
}
}
}
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3onTertiary
font.pointSize: Appearance.font.size.large
text: "open_in_new"
}
}
}
}
+71 -73
View File
@@ -7,92 +7,90 @@ import qs.Config
import qs.Modules
Item {
id: root
id: root
required property FileSystemEntry modelData
required property PersistentProperties visibilities
required property FileSystemEntry modelData
required property PersistentProperties visibilities
scale: 0.5
opacity: 0
z: PathView.z ?? 0
implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal
implicitWidth: image.width + Appearance.padding.larger * 2
opacity: 0
scale: 0.5
z: PathView.z ?? 0
Component.onCompleted: {
scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
}
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
implicitWidth: image.width + Appearance.padding.larger * 2
implicitHeight: image.height + label.height + Appearance.spacing.small / 2 + Appearance.padding.large + Appearance.padding.normal
Component.onCompleted: {
scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
}
StateLayer {
radius: Appearance.rounding.normal
function onClicked(): void {
StateLayer {
function onClicked(): void {
console.log(root.modelData.path);
Wallpapers.setWallpaper(root.modelData.path);
root.visibilities.launcher = false;
}
}
Wallpapers.setWallpaper(root.modelData.path);
root.visibilities.launcher = false;
}
Elevation {
anchors.fill: image
radius: image.radius
opacity: root.PathView.isCurrentItem ? 1 : 0
level: 4
radius: Appearance.rounding.normal
}
Behavior on opacity {
Anim {}
}
}
Elevation {
anchors.fill: image
level: 4
opacity: root.PathView.isCurrentItem ? 1 : 0
radius: image.radius
CustomClippingRect {
id: image
Behavior on opacity {
Anim {
}
}
}
anchors.horizontalCenter: parent.horizontalCenter
y: Appearance.padding.large
color: DynamicColors.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal
CustomClippingRect {
id: image
implicitWidth: Config.launcher.sizes.wallpaperWidth
implicitHeight: implicitWidth / 16 * 9
anchors.horizontalCenter: parent.horizontalCenter
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: implicitWidth / 16 * 9
implicitWidth: Config.launcher.sizes.wallpaperWidth
radius: Appearance.rounding.normal
y: Appearance.padding.large
MaterialIcon {
anchors.centerIn: parent
text: "image"
color: DynamicColors.tPalette.m3outline
font.pointSize: Appearance.font.size.extraLarge * 2
font.weight: 600
}
MaterialIcon {
anchors.centerIn: parent
color: DynamicColors.tPalette.m3outline
font.pointSize: Appearance.font.size.extraLarge * 2
font.weight: 600
text: "image"
}
CachingImage {
path: root.modelData.path
smooth: !root.PathView.view.moving
cache: true
CachingImage {
anchors.fill: parent
cache: true
path: root.modelData.path
smooth: !root.PathView.view.moving
}
}
anchors.fill: parent
}
}
CustomText {
id: label
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 {}
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: image.bottom
anchors.topMargin: Appearance.spacing.small / 2
elide: Text.ElideRight
font.pointSize: Appearance.font.size.normal
horizontalAlignment: Text.AlignHCenter
renderType: Text.QtRendering
text: root.modelData.relativePath
width: image.width - Appearance.padding.normal * 2
}
}
+34 -33
View File
@@ -7,45 +7,46 @@ import Quickshell
import QtQuick
Searcher {
id: root
id: root
function transformSearch(search: string): string {
return search.slice(Config.launcher.actionPrefix.length);
}
function transformSearch(search: string): string {
return search.slice(Config.launcher.actionPrefix.length);
}
list: variants.instances
useFuzzy: Config.launcher.useFuzzy.actions
list: variants.instances
useFuzzy: Config.launcher.useFuzzy.actions
Variants {
id: variants
Variants {
id: variants
model: Config.launcher.actions.filter(a => (a.enabled ?? true))
model: Config.launcher.actions.filter(a => (a.enabled ?? true))
Action {}
}
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
component Action: QtObject {
readonly property list<string> command: modelData.command ?? []
readonly property bool dangerous: modelData.dangerous ?? false
readonly property string desc: modelData.description ?? qsTr("No description")
readonly property bool enabled: modelData.enabled ?? true
readonly property string icon: modelData.icon ?? "help_outline"
required property var modelData
readonly property string name: modelData.name ?? qsTr("Unnamed")
function onClicked(list: AppList): void {
if (command.length === 0)
return;
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);
}
}
}
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);
}
}
}
}
+58 -58
View File
@@ -7,72 +7,72 @@ import qs.Helpers
import qs.Paths
Searcher {
id: root
id: root
function launch(entry: DesktopEntry): void {
appDb.incrementFrequency(entry.id);
function launch(entry: DesktopEntry): void {
appDb.incrementFrequency(entry.id);
if (entry.runInTerminal)
Quickshell.execDetached({
command: ["app2unit", "--", ...Config.general.apps.terminal, `${Quickshell.shellDir}/assets/wrap_term_launch.sh`, ...entry.command],
workingDirectory: entry.workingDirectory
});
else
Quickshell.execDetached({
command: ["app2unit", "--", ...entry.command],
workingDirectory: entry.workingDirectory
});
}
if (entry.runInTerminal)
Quickshell.execDetached({
command: ["app2unit", "--", ...Config.general.apps.terminal, `${Quickshell.shellDir}/assets/wrap_term_launch.sh`, ...entry.command],
workingDirectory: entry.workingDirectory
});
else
Quickshell.execDetached({
command: ["app2unit", "--", ...entry.command],
workingDirectory: entry.workingDirectory
});
}
function search(search: string): list<var> {
const prefix = Config.launcher.specialPrefix;
function search(search: string): list<var> {
const prefix = Config.launcher.specialPrefix;
if (search.startsWith(`${prefix}i `)) {
keys = ["id", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}c `)) {
keys = ["categories", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}d `)) {
keys = ["comment", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}e `)) {
keys = ["execString", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}w `)) {
keys = ["startupClass", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}g `)) {
keys = ["genericName", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}k `)) {
keys = ["keywords", "name"];
weights = [0.9, 0.1];
} else {
keys = ["name"];
weights = [1];
if (search.startsWith(`${prefix}i `)) {
keys = ["id", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}c `)) {
keys = ["categories", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}d `)) {
keys = ["comment", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}e `)) {
keys = ["execString", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}w `)) {
keys = ["startupClass", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}g `)) {
keys = ["genericName", "name"];
weights = [0.9, 0.1];
} else if (search.startsWith(`${prefix}k `)) {
keys = ["keywords", "name"];
weights = [0.9, 0.1];
} else {
keys = ["name"];
weights = [1];
if (!search.startsWith(`${prefix}t `))
return query(search).map(e => e.entry);
}
if (!search.startsWith(`${prefix}t `))
return query(search).map(e => e.entry);
}
const results = query(search.slice(prefix.length + 2)).map(e => e.entry);
if (search.startsWith(`${prefix}t `))
return results.filter(a => a.runInTerminal);
return results;
}
const results = query(search.slice(prefix.length + 2)).map(e => e.entry);
if (search.startsWith(`${prefix}t `))
return results.filter(a => a.runInTerminal);
return results;
}
function selector(item: var): string {
return keys.map(k => item[k]).join(" ");
}
function selector(item: var): string {
return keys.map(k => item[k]).join(" ");
}
list: appDb.apps
useFuzzy: Config.launcher.useFuzzy.apps
list: appDb.apps
useFuzzy: Config.launcher.useFuzzy.apps
AppDb {
id: appDb
AppDb {
id: appDb
path: `${Paths.state}/apps.sqlite`
entries: DesktopEntries.applications.values
}
entries: DesktopEntries.applications.values
path: `${Paths.state}/apps.sqlite`
}
}
+69 -71
View File
@@ -8,90 +8,88 @@ import qs.Config
import qs.Modules.Launcher.Items
PathView {
id: root
id: root
required property CustomTextField search
required property var visibilities
required property var panels
required property var content
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;
readonly property int itemWidth: Config.launcher.sizes.wallpaperWidth * 0.8 + Appearance.padding.larger * 2
// 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;
readonly property int numItems: {
const screen = QsWindow.window?.screen;
if (!screen)
return 0;
if (maxWidth <= 0)
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;
const maxItemsOnScreen = Math.floor(maxWidth / itemWidth);
const visible = Math.min(maxItemsOnScreen, Config.launcher.maxWallpapers, scriptModel.values.length);
if (maxWidth <= 0)
return 0;
if (visible === 2)
return 1;
if (visible > 1 && visible % 2 === 0)
return visible - 1;
return visible;
}
required property var panels
required property CustomTextField search
required property var visibilities
const maxItemsOnScreen = Math.floor(maxWidth / itemWidth);
const visible = Math.min(maxItemsOnScreen, Config.launcher.maxWallpapers, scriptModel.values.length);
cacheItemCount: 4
highlightRangeMode: PathView.StrictlyEnforceRange
implicitWidth: Math.min(numItems, count) * itemWidth
pathItemCount: numItems
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
snapMode: PathView.SnapToItem
if (visible === 2)
return 1;
if (visible > 1 && visible % 2 === 0)
return visible - 1;
return visible;
}
delegate: WallpaperItem {
visibilities: root.visibilities
}
model: ScriptModel {
id: scriptModel
model: ScriptModel {
id: scriptModel
readonly property string search: root.search.text.split(" ").slice(1).join(" ")
readonly property string search: root.search.text.split(" ").slice(1).join(" ")
values: Wallpapers.query(search)
values: Wallpapers.query(search)
onValuesChanged: root.currentIndex = search ? 0 : values.findIndex(w => w.path === Wallpapers.actualCurrent)
}
onValuesChanged: root.currentIndex = search ? 0 : values.findIndex(w => w.path === Wallpapers.actualCurrent)
}
path: Path {
startY: root.height / 2
Component.onCompleted: currentIndex = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent)
Component.onDestruction: Wallpapers.stopPreview()
PathAttribute {
name: "z"
value: 0
}
onCurrentItemChanged: {
if (currentItem)
Wallpapers.preview(currentItem.modelData.path);
}
PathLine {
relativeY: 0
x: root.width / 2
}
implicitWidth: Math.min(numItems, count) * itemWidth
pathItemCount: numItems
cacheItemCount: 4
PathAttribute {
name: "z"
value: 1
}
snapMode: PathView.SnapToItem
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
highlightRangeMode: PathView.StrictlyEnforceRange
PathLine {
relativeY: 0
x: root.width
}
}
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
}
}
Component.onCompleted: currentIndex = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent)
Component.onDestruction: Wallpapers.stopPreview()
onCurrentItemChanged: {
if (currentItem)
Wallpapers.preview(currentItem.modelData.path);
}
}
+99 -99
View File
@@ -6,125 +6,125 @@ import qs.Components
import qs.Config
Item {
id: root
id: root
required property ShellScreen screen
required property PersistentProperties visibilities
required property var panels
property int contentHeight
readonly property real maxHeight: {
let max = screen.height - Appearance.spacing.large;
if (visibilities.dashboard)
max -= panels.dashboard.nonAnimHeight;
return max;
}
required property var panels
required property ShellScreen screen
readonly property bool shouldBeActive: visibilities.launcher
required property PersistentProperties visibilities
readonly property bool shouldBeActive: visibilities.launcher
property int contentHeight
implicitHeight: 0
implicitWidth: content.implicitWidth
visible: height > 0
readonly property real maxHeight: {
let max = screen.height - Appearance.spacing.large;
if (visibilities.dashboard)
max -= panels.dashboard.nonAnimHeight;
return max;
}
onMaxHeightChanged: timer.start()
onShouldBeActiveChanged: {
if (shouldBeActive) {
timer.stop();
hideAnim.stop();
showAnim.start();
} else {
showAnim.stop();
hideAnim.start();
}
}
onMaxHeightChanged: timer.start()
SequentialAnimation {
id: showAnim
visible: height > 0
implicitHeight: 0
implicitWidth: content.implicitWidth
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
property: "implicitHeight"
target: root
to: root.contentHeight
}
onShouldBeActiveChanged: {
if (shouldBeActive) {
timer.stop();
hideAnim.stop();
showAnim.start();
} else {
showAnim.stop();
hideAnim.start();
}
}
ScriptAction {
script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
}
}
SequentialAnimation {
id: showAnim
SequentialAnimation {
id: hideAnim
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)
}
}
ScriptAction {
script: root.implicitHeight = root.implicitHeight
}
SequentialAnimation {
id: hideAnim
Anim {
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
property: "implicitHeight"
target: root
to: 0
}
}
ScriptAction {
script: root.implicitHeight = root.implicitHeight
}
Anim {
target: root
property: "implicitHeight"
to: 0
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
Connections {
function onEnabledChanged(): void {
timer.start();
}
Connections {
target: Config.launcher
function onMaxShownChanged(): void {
timer.start();
}
function onEnabledChanged(): void {
timer.start();
}
target: Config.launcher
}
function onMaxShownChanged(): void {
timer.start();
}
}
Connections {
function onValuesChanged(): void {
if (DesktopEntries.applications.values.length < Config.launcher.maxAppsShown)
timer.start();
}
Connections {
target: DesktopEntries.applications
target: DesktopEntries.applications
}
function onValuesChanged(): void {
if (DesktopEntries.applications.values.length < Config.launcher.maxAppsShown)
timer.start();
}
}
Timer {
id: timer
Timer {
id: timer
interval: Appearance.anim.durations.small
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();
}
}
}
}
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
Loader {
id: content
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
active: false
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
visible: false
visible: false
active: false
Component.onCompleted: timer.start()
sourceComponent: Content {
maxHeight: root.maxHeight
panels: root.panels
visibilities: root.visibilities
sourceComponent: Content {
visibilities: root.visibilities
panels: root.panels
maxHeight: root.maxHeight
Component.onCompleted: root.contentHeight = implicitHeight
}
Component.onCompleted: root.contentHeight = implicitHeight
}
}
Component.onCompleted: timer.start()
}
}