modernize introduction somewhat

At least it no longer recommends deprecated types.
This commit is contained in:
outfoxxed 2025-06-07 17:23:18 -07:00
parent 2f2e5fedd3
commit 565cc5817d
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
2 changed files with 172 additions and 188 deletions

View file

@ -32,7 +32,7 @@ const remarkParseAtTypes: RemarkPlugin<[]> = () => {
const node = rawNode as Md.Literal; const node = rawNode as Md.Literal;
node.value = node.value.replace( node.value = node.value.replace(
/@@((?<module>([A-Z]\w*\.)*)(?<type>([A-Z]\w*))\.?)?((?<member>[a-z]\w*)((?<function>\(\))|(?<signal>\(s\)))?)?(?=[$.,;:)\s]|$)/g, /@@((?<module>([A-Z]\w*\.)*)(?<type>([A-Z]\w*))(\.(?!\s|$))?)?((?<member>[a-z]\w*)((?<function>\(\))|(?<signal>\(s\)))?)?(?=[$.,;:)\s]|$)/g,
(_full, ...args) => { (_full, ...args) => {
type Capture = { type Capture = {
module: string | undefined; module: string | undefined;

View file

@ -3,41 +3,27 @@ title: "Introduction"
index: 2 index: 2
--- ---
import Collapsible from "@components/Collapsible.astro";
# {frontmatter.title} # {frontmatter.title}
> [!NOTE]
> This guide was created a long time ago, and is somewhat outdated.
> Take a look at @@Quickshell.SystemClock after going through.
This page will walk you through the process of creating a simple bar/panel, and This page will walk you through the process of creating a simple bar/panel, and
introduce you to all the basic concepts involved. introduce you to all the basic concepts involved. You can use the
[QML Language Reference](/docs/guide/qml-language) to learn about the syntax
of the QML language.
There are many links to the [QML Overview](/docs/guide/qml-language) Note that all the <a>Green Links</a> in code blocks will take you to the documentation
and [Type Reference](/docs/types) which you should follow if you don't for their respective types.
fully understand the concepts involved.
## Shell Files ## Config Files
Quickshell searches the `quickshell` subfolder of every XDG standard config path
for configs. Usually this is `~/.config/quickshell`.
Every quickshell instance starts from a shell root file, conventionally named `shell.qml`. Each named subfolder containing a `shell.qml` file is considered to be a config.
The default path is `~/.config/quickshell/shell.qml`. If the base `quickshell` folder contains a shell.qml file, subfolders will not be
(where `~/.config` can be substituted with `$XDG_CONFIG_HOME` if present.) considered.
Each shell file starts with the shell root object. Only one may exist per configuration. A specific config can be picked using the `--config` or `-c` argument to Quickshell.
```qml Configs at other paths, including raw qml files can be run with `--path` or `-p`.
// ~/.config/quickshell/shell.qml
import Quickshell
@@Quickshell.ShellRoot {
// ...
}
```
The shell root is not a visual element but instead contains all of the visual
and non visual objects in your shell. You can have multiple different shells
with shared components and different shell roots.
## Creating Windows ## Creating Windows
@ -48,25 +34,23 @@ Quickshell has two main window types available,
We'll start with an example: We'll start with an example:
```qml ```qml
import Quickshell // for ShellRoot and PanelWindow import Quickshell // for PanelWindow
import QtQuick // for Text import QtQuick // for Text
@@Quickshell.ShellRoot { @@Quickshell.PanelWindow {
@@Quickshell.PanelWindow { anchors {
anchors { top: true
top: true left: true
left: true right: true
right: true }
}
implicitHeight: 30 implicitHeight: 30
@@QtQuick.Text { @@QtQuick.Text {
// center the bar in its parent component (the window) // center the bar in its parent component (the window)
anchors.centerIn: parent anchors.centerIn: parent
text: "hello world" text: "hello world"
}
} }
} }
``` ```
@ -74,13 +58,16 @@ import QtQuick // for Text
The above example creates a bar/panel on your currently focused monitor with The above example creates a bar/panel on your currently focused monitor with
a centered piece of [text](https://doc.qt.io/qt-6/qml-qtquick-text.html). It will also reserve space for itself on your monitor. a centered piece of [text](https://doc.qt.io/qt-6/qml-qtquick-text.html). It will also reserve space for itself on your monitor.
More information about available properties is available in the [type reference](/docs/types/quickshell/panelwindow). More information about available properties is available in the [type reference](/docs/types/Quickshell/PanelWindow).
## Running a process ## Running a process
Now that we have a piece of text, what if it did something useful? Now that we have a piece of text, what if it did something useful?
To start with lets make a clock. To get the time we'll use the `date` command. To start with lets make a clock. To get the time we'll use the `date` command.
> [!note/Note]
> Quickshell can do more than just run processes. Read until the end for more information.
We can use a [Process](/docs/types/quickshell.io/process) object to run commands We can use a [Process](/docs/types/quickshell.io/process) object to run commands
and return their results. and return their results.
@ -98,37 +85,35 @@ import Quickshell
import Quickshell.Io // for Process import Quickshell.Io // for Process
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.PanelWindow {
@@Quickshell.PanelWindow { anchors {
anchors { top: true
top: true left: true
left: true right: true
right: true }
}
implicitHeight: 30 implicitHeight: 30
@@QtQuick.Text { @@QtQuick.Text {
// give the text an ID we can refer to elsewhere in the file // give the text an ID we can refer to elsewhere in the file
id: clock id: clock
anchors.centerIn: parent anchors.centerIn: parent
// create a process management object // create a process management object
@@Quickshell.Io.Process { @@Quickshell.Io.Process {
// the command it will run, every argument is its own string // the command it will run, every argument is its own string
command: ["date"] command: ["date"]
// run the command immediately // run the command immediately
running: true running: true
// process the stdout stream using a SplitParser // process the stdout stream using a SplitParser
// which returns chunks of output after a delimiter // which returns chunks of output after a delimiter
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
// listen for the read signal, which returns the data that was read // listen for the read signal, which returns the data that was read
// from stdout, then write that data to the clock's text property // from stdout, then write that data to the clock's text property
onRead: data => clock.text = data onRead: data => clock.text = data
}
} }
} }
} }
@ -145,48 +130,46 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.PanelWindow {
@@Quickshell.PanelWindow { anchors {
anchors { top: true
top: true left: true
left: true right: true
right: true }
implicitHeight: 30
@@QtQuick.Text {
id: clock
anchors.centerIn: parent
@@Quickshell.Io.Process {
// give the process object an id so we can talk
// about it from the timer
id: dateProc
command: ["date"]
running: true
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
} }
implicitHeight: 30 // use a timer to rerun the process at an interval
@@QtQml.Timer {
// 1000 milliseconds is 1 second
interval: 1000
@@QtQuick.Text { // start the timer immediately
id: clock running: true
anchors.centerIn: parent
@@Quickshell.Io.Process { // run the timer again when it ends
// give the process object an id so we can talk repeat: true
// about it from the timer
id: dateProc
command: ["date"] // when the timer is triggered, set the running property of the
running: true // process to true, which reruns it if stopped.
onTriggered: dateProc.running = true
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
}
// use a timer to rerun the process at an interval
@@QtQml.Timer {
// 1000 milliseconds is 1 second
interval: 1000
// start the timer immediately
running: true
// run the timer again when it ends
repeat: true
// when the timer is triggered, set the running property of the
// process to true, which reruns it if stopped.
onTriggered: dateProc.running = true
}
} }
} }
} }
@ -217,47 +200,45 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.Variants {
@@Quickshell.Variants { model: Quickshell.screens;
model: Quickshell.screens;
delegate: @@QtQml.Component { delegate: @@QtQml.Component {
@@Quickshell.PanelWindow { @@Quickshell.PanelWindow {
// the screen from the screens list will be injected into this // the screen from the screens list will be injected into this
// property // property
property var modelData property var modelData
// we can then set the window's screen to the injected property // we can then set the window's screen to the injected property
screen: modelData screen: modelData
anchors { anchors {
top: true top: true
left: true left: true
right: true right: true
}
implicitHeight: 30
@@QtQuick.Text {
id: clock
anchors.centerIn: parent
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
} }
implicitHeight: 30 @@QtQml.Timer {
interval: 1000
@@QtQuick.Text { running: true
id: clock repeat: true
anchors.centerIn: parent onTriggered: dateProc.running = true
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
}
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
onTriggered: dateProc.running = true
}
} }
} }
} }
@ -276,8 +257,9 @@ due to the reactive nature of the
(See: [Reactive Bindings](/docs/configuration/qml-overview/#reactive-bindings).) (See: [Reactive Bindings](/docs/configuration/qml-overview/#reactive-bindings).)
Now there's an important problem you might have noticed: when the window Now there's an important problem you might have noticed: when the window
is created multiple times we also make a new Process and Timer. We can fix is created multiple times we also make a new Process and Timer, which makes the
this by moving the Process and Timer outside of the window. bar less efficient than it could be. We can fix this by moving the
Process and Timer outside of the window using @@Quickshell.Scope.
> [!caution/Error] > [!caution/Error]
> This code will not work correctly. > This code will not work correctly.
@ -287,7 +269,7 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.Scope {
@@Quickshell.Variants { @@Quickshell.Variants {
model: Quickshell.screens model: Quickshell.screens
@ -338,11 +320,11 @@ _What about the `clock` that the process references?_
If you run the above example you'll see something like this in the console every second: If you run the above example you'll see something like this in the console every second:
``` ```
file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined
file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined
file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined
file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined
file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined
``` ```
This is because the `clock` object, even though it has an ID, cannot be referenced This is because the `clock` object, even though it has an ID, cannot be referenced
@ -362,11 +344,11 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.Scope {
id: root id: root
// add a property in the root // add a property in the root
property string time; property string time
@@Quickshell.Variants { @@Quickshell.Variants {
model: Quickshell.screens model: Quickshell.screens
@ -389,7 +371,7 @@ import QtQuick
anchors.centerIn: parent anchors.centerIn: parent
// bind the text to the root's time property // bind the text to the root object's time property
text: root.time text: root.time
} }
} }
@ -427,9 +409,6 @@ above code, but we can make it more concise:
which means we can skip the `delegate:` part of the assignment. which means we can skip the `delegate:` part of the assignment.
We're already using the default property of @@Quickshell.ShellRoot to store our We're already using the default property of @@Quickshell.ShellRoot to store our
Variants, Process, and Timer components among other things. Variants, Process, and Timer components among other things.
3. The ShellRoot doesn't actually need an `id` property to talk about
the time property, as it is the outermost object in the file which
has [special scoping rules](/docs/configuration/qml-overview/#property-access-scopes).
This is what our shell looks like with the above (optional) cleanup: This is what our shell looks like with the above (optional) cleanup:
@ -438,8 +417,9 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.ShellRoot { @@Quickshell.Scope {
property string time; id: root
property string time
@@Quickshell.Variants { @@Quickshell.Variants {
model: Quickshell.screens model: Quickshell.screens
@ -458,9 +438,7 @@ import QtQuick
@@QtQuick.Text { @@QtQuick.Text {
anchors.centerIn: parent anchors.centerIn: parent
text: root.time
// now just time instead of root.time
text: time
} }
} }
} }
@ -471,8 +449,7 @@ import QtQuick
running: true running: true
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
// now just time instead of root.time onRead: data => root.time = data
onRead: data => time = data
} }
} }
@ -496,7 +473,7 @@ To start with, let's move the entire bar into a new file.
// shell.qml // shell.qml
import Quickshell import Quickshell
@@Quickshell.ShellRoot { @@Quickshell.Scope {
Bar {} Bar {}
} }
``` ```
@ -508,7 +485,8 @@ import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.Scope { @@Quickshell.Scope {
property string time; id: root
property string time
@@Quickshell.Variants { @@Quickshell.Variants {
model: Quickshell.screens model: Quickshell.screens
@ -527,9 +505,7 @@ import QtQuick
@@QtQuick.Text { @@QtQuick.Text {
anchors.centerIn: parent anchors.centerIn: parent
text: root.time
// now just time instead of root.time
text: time
} }
} }
} }
@ -540,8 +516,7 @@ import QtQuick
running: true running: true
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
// now just time instead of root.time onRead: data => root.time = data
onRead: data => time = data
} }
} }
@ -589,7 +564,7 @@ import QtQuick
@@Quickshell.Scope { @@Quickshell.Scope {
id: root id: root
property string time; property string time
@@Quickshell.Variants { @@Quickshell.Variants {
model: Quickshell.screens model: Quickshell.screens
@ -609,7 +584,6 @@ import QtQuick
// the ClockWidget type we just created // the ClockWidget type we just created
ClockWidget { ClockWidget {
anchors.centerIn: parent anchors.centerIn: parent
// Warning: setting `time: time` will bind time to itself which is not what we want
time: root.time time: root.time
} }
} }
@ -621,7 +595,7 @@ import QtQuick
running: true running: true
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data onRead: data => root.time = data
} }
} }
@ -646,7 +620,8 @@ import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.Scope { @@Quickshell.Scope {
property string time; id: root
property string time
@@Quickshell.Io.Process { @@Quickshell.Io.Process {
id: dateProc id: dateProc
@ -654,7 +629,7 @@ import QtQuick
running: true running: true
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data onRead: data => root.time = data
} }
} }
@ -721,6 +696,7 @@ import QtQuick
// your singletons should always have Singleton as the type // your singletons should always have Singleton as the type
@@Quickshell.Singleton { @@Quickshell.Singleton {
id: root
property string time property string time
@@Quickshell.Io.Process { @@Quickshell.Io.Process {
@ -729,7 +705,7 @@ import QtQuick
running: true running: true
stdout: @@Quickshell.Io.SplitParser { stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data onRead: data => root.time = data
} }
} }
@ -786,31 +762,39 @@ import Quickshell
} }
``` ```
## JavaScript APIs ## Quickshell Support Libraries
In addition to calling external processes, Quickshell comes with a large set of support libraries
for common OS integrations and tasks. These libraries are indexed on the left sidebar.
In addition to calling external processes, a [limited set of javascript interfaces] is available. One of these integrations is @@Quickshell.SystemClock, which exposes the system time in an easy to
We can use this to improve our clock by using the [Date API] instead of calling `date`. use way.
[limited set of javascript interfaces]: https://doc.qt.io/qt-6/qtqml-javascript-functionlist.html We can use @@Quickshell.SystemClock.date to get a Date object to display. The
[Date API]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date @@QtQml.Qt.formatDateTime() function can be used to easily format the date
as shown below.
@@Quickshell.SystemClock.precision can be set to `Minutes` to improve battery life if you don't
show seconds on your clock, as Quickshell will have less work to do.
```qml ```qml
// Time.qml // Time.qml
pragma Singleton pragma Singleton
import Quickshell import Quickshell
import Quickshell.Io
import QtQuick import QtQuick
@@Quickshell.Singleton { @@Quickshell.Singleton {
property var date: new Date() id: root
property string time: date.toLocaleString(Qt.locale()) // an expression can be broken across multiple lines using {}
readonly property string time: {
// The passed format string matches the default output of
// the `date` command.
Qt.formatDateTime(clock.date, "ddd MMM d hh:mm:ss AP t yyyy")
}
@@QtQml.Timer { @@Quickshell.SystemClock {
interval: 1000 id: clock
running: true precision: SystemClock.Seconds
repeat: true
onTriggered: date = new Date()
} }
} }
``` ```