From 2f2e5fedd3f7c329b85c7ae0c9524cb678f47cc0 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 7 Jun 2025 05:23:45 -0700 Subject: [PATCH 1/6] set up caddy redirects --- default.nix | 6 +++++- redirects.caddyfile | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 redirects.caddyfile diff --git a/default.nix b/default.nix index 2d6ae88..abe0fa5 100644 --- a/default.nix +++ b/default.nix @@ -75,5 +75,9 @@ in { HOME=$(pwd)/garbage-tooling yarn build ''; - installPhase = "mv dist $out"; + installPhase = '' + mkdir -p $out + mv redirects.caddyfile $out + mv dist $out/site + ''; }) diff --git a/redirects.caddyfile b/redirects.caddyfile new file mode 100644 index 0000000..3c4e286 --- /dev/null +++ b/redirects.caddyfile @@ -0,0 +1,5 @@ +redir /docs/configuration/getting-started* /docs/guide/install-setup permanent +redir /docs/configuration/intro* /docs/guide/introduction permanent +redir /docs/configuration/positioning* /docs/guide/size-position permanent +redir /docs/configuration/qml-overview* /docs/guide/qml-language permanent +redir /docs/configuration* /docs/guide permanent From 565cc5817ddb68afcc3d4f17563c07f77ba1967d Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 7 Jun 2025 17:23:18 -0700 Subject: [PATCH 2/6] modernize introduction somewhat At least it no longer recommends deprecated types. --- src/config/io/markdown.ts | 2 +- src/guide/introduction.mdx | 358 ++++++++++++++++++------------------- 2 files changed, 172 insertions(+), 188 deletions(-) diff --git a/src/config/io/markdown.ts b/src/config/io/markdown.ts index 225c1fe..c32d13a 100644 --- a/src/config/io/markdown.ts +++ b/src/config/io/markdown.ts @@ -32,7 +32,7 @@ const remarkParseAtTypes: RemarkPlugin<[]> = () => { const node = rawNode as Md.Literal; node.value = node.value.replace( - /@@((?([A-Z]\w*\.)*)(?([A-Z]\w*))\.?)?((?[a-z]\w*)((?\(\))|(?\(s\)))?)?(?=[$.,;:)\s]|$)/g, + /@@((?([A-Z]\w*\.)*)(?([A-Z]\w*))(\.(?!\s|$))?)?((?[a-z]\w*)((?\(\))|(?\(s\)))?)?(?=[$.,;:)\s]|$)/g, (_full, ...args) => { type Capture = { module: string | undefined; diff --git a/src/guide/introduction.mdx b/src/guide/introduction.mdx index 8a1b5cf..b7bc674 100644 --- a/src/guide/introduction.mdx +++ b/src/guide/introduction.mdx @@ -3,41 +3,27 @@ title: "Introduction" index: 2 --- -import Collapsible from "@components/Collapsible.astro"; - # {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 -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) -and [Type Reference](/docs/types) which you should follow if you don't -fully understand the concepts involved. +Note that all the Green Links in code blocks will take you to the documentation +for their respective types. -## 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`. -The default path is `~/.config/quickshell/shell.qml`. -(where `~/.config` can be substituted with `$XDG_CONFIG_HOME` if present.) +Each named subfolder containing a `shell.qml` file is considered to be a config. +If the base `quickshell` folder contains a shell.qml file, subfolders will not be +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 -// ~/.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. +Configs at other paths, including raw qml files can be run with `--path` or `-p`. ## Creating Windows @@ -48,25 +34,23 @@ Quickshell has two main window types available, We'll start with an example: ```qml -import Quickshell // for ShellRoot and PanelWindow +import Quickshell // for PanelWindow import QtQuick // for Text -@@Quickshell.ShellRoot { - @@Quickshell.PanelWindow { - anchors { - top: true - left: true - right: true - } +@@Quickshell.PanelWindow { + anchors { + top: true + left: true + right: true + } - implicitHeight: 30 + implicitHeight: 30 - @@QtQuick.Text { - // center the bar in its parent component (the window) - anchors.centerIn: parent + @@QtQuick.Text { + // center the bar in its parent component (the window) + 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 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 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. +> [!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 and return their results. @@ -98,37 +85,35 @@ import Quickshell import Quickshell.Io // for Process import QtQuick -@@Quickshell.ShellRoot { - @@Quickshell.PanelWindow { - anchors { - top: true - left: true - right: true - } +@@Quickshell.PanelWindow { + anchors { + top: true + left: true + right: true + } - implicitHeight: 30 + implicitHeight: 30 - @@QtQuick.Text { - // give the text an ID we can refer to elsewhere in the file - id: clock + @@QtQuick.Text { + // give the text an ID we can refer to elsewhere in the file + id: clock - anchors.centerIn: parent + anchors.centerIn: parent - // create a process management object - @@Quickshell.Io.Process { - // the command it will run, every argument is its own string - command: ["date"] + // create a process management object + @@Quickshell.Io.Process { + // the command it will run, every argument is its own string + command: ["date"] - // run the command immediately - running: true + // run the command immediately + running: true - // process the stdout stream using a SplitParser - // which returns chunks of output after a delimiter - stdout: @@Quickshell.Io.SplitParser { - // listen for the read signal, which returns the data that was read - // from stdout, then write that data to the clock's text property - onRead: data => clock.text = data - } + // process the stdout stream using a SplitParser + // which returns chunks of output after a delimiter + stdout: @@Quickshell.Io.SplitParser { + // listen for the read signal, which returns the data that was read + // from stdout, then write that data to the clock's text property + onRead: data => clock.text = data } } } @@ -145,48 +130,46 @@ import Quickshell import Quickshell.Io import QtQuick -@@Quickshell.ShellRoot { - @@Quickshell.PanelWindow { - anchors { - top: true - left: true - right: true +@@Quickshell.PanelWindow { + anchors { + top: true + left: 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 { - id: clock - anchors.centerIn: parent + // start the timer immediately + running: true - @@Quickshell.Io.Process { - // give the process object an id so we can talk - // about it from the timer - id: dateProc + // run the timer again when it ends + repeat: true - command: ["date"] - 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 - } + // 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 QtQuick -@@Quickshell.ShellRoot { - @@Quickshell.Variants { - model: Quickshell.screens; +@@Quickshell.Variants { + model: Quickshell.screens; - delegate: @@QtQml.Component { - @@Quickshell.PanelWindow { - // the screen from the screens list will be injected into this - // property - property var modelData + delegate: @@QtQml.Component { + @@Quickshell.PanelWindow { + // the screen from the screens list will be injected into this + // property + property var modelData - // we can then set the window's screen to the injected property - screen: modelData + // we can then set the window's screen to the injected property + screen: modelData - anchors { - top: true - left: true - right: true + anchors { + top: true + left: 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 - - @@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 - } - } - - @@QtQml.Timer { - interval: 1000 - running: true - repeat: true - onTriggered: dateProc.running = true - } + @@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).) 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 -this by moving the Process and Timer outside of the window. +is created multiple times we also make a new Process and Timer, which makes the +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] > This code will not work correctly. @@ -287,7 +269,7 @@ import Quickshell import Quickshell.Io import QtQuick -@@Quickshell.ShellRoot { +@@Quickshell.Scope { @@Quickshell.Variants { 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: ``` -file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined -file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined -file:///home/name/.config/quickshell/shell.qml:33: ReferenceError: clock is not defined -file:///home/name/.config/quickshell/shell.qml:33: 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 +WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined +WARN scene: **/shell.qml[36:-1]: ReferenceError: clock is not defined +WARN scene: **/shell.qml[36:-1]: 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 @@ -362,11 +344,11 @@ import Quickshell import Quickshell.Io import QtQuick -@@Quickshell.ShellRoot { +@@Quickshell.Scope { id: root // add a property in the root - property string time; + property string time @@Quickshell.Variants { model: Quickshell.screens @@ -389,7 +371,7 @@ import QtQuick 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 } } @@ -427,9 +409,6 @@ above code, but we can make it more concise: which means we can skip the `delegate:` part of the assignment. We're already using the default property of @@Quickshell.ShellRoot to store our 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: @@ -438,8 +417,9 @@ import Quickshell import Quickshell.Io import QtQuick -@@Quickshell.ShellRoot { - property string time; +@@Quickshell.Scope { + id: root + property string time @@Quickshell.Variants { model: Quickshell.screens @@ -458,9 +438,7 @@ import QtQuick @@QtQuick.Text { anchors.centerIn: parent - - // now just time instead of root.time - text: time + text: root.time } } } @@ -471,8 +449,7 @@ import QtQuick running: true stdout: @@Quickshell.Io.SplitParser { - // now just time instead of root.time - onRead: data => time = data + onRead: data => root.time = data } } @@ -496,7 +473,7 @@ To start with, let's move the entire bar into a new file. // shell.qml import Quickshell -@@Quickshell.ShellRoot { +@@Quickshell.Scope { Bar {} } ``` @@ -508,7 +485,8 @@ import Quickshell.Io import QtQuick @@Quickshell.Scope { - property string time; + id: root + property string time @@Quickshell.Variants { model: Quickshell.screens @@ -527,9 +505,7 @@ import QtQuick @@QtQuick.Text { anchors.centerIn: parent - - // now just time instead of root.time - text: time + text: root.time } } } @@ -540,8 +516,7 @@ import QtQuick running: true stdout: @@Quickshell.Io.SplitParser { - // now just time instead of root.time - onRead: data => time = data + onRead: data => root.time = data } } @@ -589,7 +564,7 @@ import QtQuick @@Quickshell.Scope { id: root - property string time; + property string time @@Quickshell.Variants { model: Quickshell.screens @@ -609,7 +584,6 @@ import QtQuick // the ClockWidget type we just created ClockWidget { anchors.centerIn: parent - // Warning: setting `time: time` will bind time to itself which is not what we want time: root.time } } @@ -621,7 +595,7 @@ import QtQuick running: true stdout: @@Quickshell.Io.SplitParser { - onRead: data => time = data + onRead: data => root.time = data } } @@ -646,7 +620,8 @@ import Quickshell.Io import QtQuick @@Quickshell.Scope { - property string time; + id: root + property string time @@Quickshell.Io.Process { id: dateProc @@ -654,7 +629,7 @@ import QtQuick running: true 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 @@Quickshell.Singleton { + id: root property string time @@Quickshell.Io.Process { @@ -729,7 +705,7 @@ import QtQuick running: true 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. -We can use this to improve our clock by using the [Date API] instead of calling `date`. +One of these integrations is @@Quickshell.SystemClock, which exposes the system time in an easy to +use way. -[limited set of javascript interfaces]: https://doc.qt.io/qt-6/qtqml-javascript-functionlist.html -[Date API]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date +We can use @@Quickshell.SystemClock.date to get a Date object to display. The +@@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 // Time.qml pragma Singleton import Quickshell -import Quickshell.Io import QtQuick @@Quickshell.Singleton { - property var date: new Date() - property string time: date.toLocaleString(Qt.locale()) + id: root + // 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 { - interval: 1000 - running: true - repeat: true - onTriggered: date = new Date() + @@Quickshell.SystemClock { + id: clock + precision: SystemClock.Seconds } } ``` From c55d54e6a5c1b152d0d83bab7e8fbed131915dd0 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 7 Jun 2025 20:56:56 -0700 Subject: [PATCH 3/6] add faq entries --- src/guide/faq.mdx | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/guide/faq.mdx b/src/guide/faq.mdx index d87de4a..3ed493f 100644 --- a/src/guide/faq.mdx +++ b/src/guide/faq.mdx @@ -12,6 +12,28 @@ Make sure to also read the [Item Size and Position](/docs/guide/size-position) a ## How do I +### Reduce memory usage +The main thing you can do to reduce the memory usage of a given configuration +is to use loaders. Loaders can be used to create objects only when needed, +and destroy them when not needed. + +- Use @@QtQuick.Loader when the component being loaded inherits from @@QtQuick.Item. +- Use @@Quickshell.LazyLoader in other cases. + +### Show widgets conditionally +The @@QtQuick.Item.visible property can be used to change the visibility of an +Item conditionally, as well as Loaders. + +Note that you can change out a loader's component conditionally: +```qml +@@QtQuick.Loader { + readonly property Component thing1: ... + readonly property Component thing2: ... + + sourceComponent: condition ? thing1 : thing2 +} +``` + ### Make a rounded window Rounded windows are simply transparent square ones with a rounded rectangle inside of them. @@ -29,3 +51,22 @@ inside of them. } } ``` + +## Something is broken + +### There is a hole in my window +If you set a Rectangle's color to `"transparent"` and touch its `border` property, +you'll hit [QTBUG-137166](https://bugreports.qt.io/browse/QTBUG-137166), which +causes everything under the transparent rectangle to become invisible. + +Adding a definition like `border.width: 0` seems to work around it, especially +if the only border property you wanted to set was radius. + +### My window should not be opaque +If a window is created with an opaque background color, Quickshell will use +a window surface format that is opaque, which reduces the amount of processing +the gpu must do to draw it. If you change the background color of your window +between opaque and transparent colors, this may affect you. + +To tell Quickshell to always create a window capable of showing transparency, +use @@Quickshell.QsWindow.surfaceFormat to set `opaque` to false. From 444958eb8f24ad59199027119f4b722efaa23bf9 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 7 Jun 2025 21:12:20 -0700 Subject: [PATCH 4/6] document inline components Also remove MD_Title elements --- src/guide/qml-language.mdx | 99 ++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 32 deletions(-) diff --git a/src/guide/qml-language.mdx b/src/guide/qml-language.mdx index b9e0543..8bec9fb 100644 --- a/src/guide/qml-language.mdx +++ b/src/guide/qml-language.mdx @@ -2,7 +2,6 @@ title: "QML Language" index: 10 --- -import MD_Title from "@components/MD_Title.tsx" import Collapsible from "@components/Collapsible.astro"; # {frontmatter.title} @@ -15,7 +14,7 @@ This page explains what you need to know about QML to start using quickshell. Tutorial](https://doc.qt.io/qt-6/qml-tutorial.html) -## Structure +## Structure Below is a QML document showing most of the syntax. Keep it in mind as you read the detailed descriptions below. @@ -87,12 +86,17 @@ import "myjs.js" as MyJs function dub(x: int): int { return x * 2 } + + // Inline component + component MyComponent: Object { + // ... + } } ``` -### Imports +### Imports -#### Manual imports +#### Manual imports Every QML File begins with a list of imports. Import statements tell the QML engine where @@ -130,7 +134,7 @@ import "" as Note: All _Module_ and _Namespace_ names must start with an uppercase letter. Attempting to use a lowercase namespace is an error. -##### Examples +##### Examples ```qml import QtQuick @@ -158,7 +162,7 @@ specifying a version at least when importing quickshell modules. syntax](https://doc.qt.io/qt-6/qtqml-syntax-imports.html) -#### Implicit imports +#### Implicit imports The QML engine will automatically import any [types](#creating-types) in neighboring files with names that start with an uppercase letter. @@ -172,7 +176,7 @@ root In this example, `MyButton` will automatically be imported as a type usable from shell.qml or any other neighboring files. -### Objects +### Objects Objects are instances of a type from an imported module. The name of an object must start with an uppercase letter. @@ -191,12 +195,12 @@ Every object can contain [properties](#properties), [functions](#functions), and [signals](#signals). You can find out what properties are available for a type by looking it up in the [Type Reference](/docs/types/). -#### Properties +#### Properties Every object may have any number of property assignments (only one per specific property). Each assignment binds the named property to the given expression. -##### Property bindings +##### Property bindings Expressions are snippets of javascript code assigned to a property. The last (or only) line can be the return value, or an explicit return statement (multiline expressions only) can be used. @@ -235,7 +239,7 @@ on is updated, the expression is re-evaluated and the property is updated. Note that it is an error to try to assign to a property that does not exist. (See: [property definitions](#property-definitions)) -##### Property definitions +##### Property definitions Properties can be defined inside of objects with the following syntax: @@ -267,7 +271,7 @@ Properties can be defined inside of objects with the following syntax: Defining a property with the same name as one provided by the current object will override the property of the type it is derived from in the current context. -##### The default property +##### The default property Types can have a _default property_ which must accept either an object or a list of objects. @@ -302,7 +306,7 @@ would put a single object in: } ``` -##### The `id` property +##### The `id` property Every object has a special property called `id` that can be assigned to give the object a name it can be referred to throughout the current file. The id must be lowercase. @@ -330,7 +334,7 @@ definition rules. The name `id` is always reserved for the id property. -##### Property access scopes +##### Property access scopes Properties are "in scope" and usable in two cases. @@ -343,6 +347,9 @@ or make sure the property you are accessing is from the current object using `th The `parent` property is also defined for all objects, but may not always point to what it looks like it should. Use the `id` property if `parent` does not do what you want. +In general, you should only access properties of the *current* object without an id. For +all other objects, you should refer to them by id when accessing properties. + ```qml @@QtQuick.Item { property string rootDefinition @@ -384,7 +391,7 @@ looks like it should. Use the `id` property if `parent` does not do what you wan Resolution](https://doc.qt.io/qt-6/qtqml-documents-scope.html) -#### Functions +#### Functions Functions in QML can be declared everywhere [properties](#properties) can, and follow the same [scoping rules](#property-access-scopes). @@ -424,7 +431,7 @@ In this example, every time the button is clicked, the label's count increases by one, as `clicks` is changed, which triggers a re-evaluation of `text` through `makeClicksLabel`. -##### Lambdas +##### Lambdas Functions can also be values, and you can assign them to properties or pass them to other functions (callbacks). There is a shorter way to write these functions, known @@ -485,7 +492,7 @@ An overcomplicated click counter using a lambda callback: } ``` -#### Signals +#### Signals A signal is basically an event emitter you can connect to and receive updates from. They can be declared everywhere [properties](#properties) and [functions](#functions) @@ -496,7 +503,7 @@ can, and follow the same [scoping rules](#property-access-scopes). System](https://doc.qt.io/qt-6/qtqml-syntax-signals.html) -##### Signal definitions +##### Signal definitions A signal can be explicitly defined with the following syntax: @@ -504,7 +511,7 @@ A signal can be explicitly defined with the following syntax: signal (: [, ...]) ``` -##### Making connections +##### Making connections Signals all have a `connect()` method which invokes the given function or signal when the signal is emitted. @@ -544,7 +551,7 @@ When the button is clicked, the button emits the @@QtQuick.Controls.Button.click signal which we connected to `updateText`. The signal then invokes `updateText` which updates the counter and the text on the label. -##### Signal handlers +##### Signal handlers Signal handlers are a more concise way to make a connections, and prior examples have used them. @@ -576,7 +583,7 @@ this time using the implicit signal handler property to handle @@QtQuick.Control } ``` -##### Indirect signal handlers +##### Indirect signal handlers When it is not possible or not convenient to directly define a signal handler, before resorting to `.connect`ing the properties, a @@QtQml.Connections object can be used to access them. @@ -600,7 +607,7 @@ This is especially useful to connect to signals of singletons. } ``` -##### Property change signals +##### Property change signals Every property has an associated signal, which powers QML's [reactive bindings](#reactive-bindings). The signal is named `Changed` and works exactly the same as any other signal. @@ -673,7 +680,7 @@ And the function can also be inlined to an expression: You can also remove the return statement if you wish. -##### Attached objects +##### Attached objects Attached objects are additional objects that can be associated with an object as decided by internal library code. The documentation for a type will @@ -695,7 +702,7 @@ which is attached to every object and often used to run code when an object init In this example, the text property is set inside the `Component.onCompleted` attached signal handler. -#### Creating types +#### Creating types Every QML file with an uppercase name is implicitly a type, and can be used from neighboring files or imported (See [Imports](#imports).) @@ -741,7 +748,35 @@ are not visible outside the file. } ``` -##### Singletons +##### Inline Components + +Inline components work the same as any other type, but are created inside +another QML file. These components only work within the file, and can reference +IDs inside the file. + +While inline components can be created anywhere inside a QML file, they are +scoped to the file itself and cannot be nested. + +Example of an inline component: +```qml +@@QtQuick.Layouts.ColumnLayout { + id: layout + property real textPointSize: 10 + + MyText { text: "Thing 1" } + MyText { text: "Thing 2" } + MyText { text: "Thing 3" } + + component MyText: @@QtQuick.Text { + // applied to all MyText instances + color: "red" + // references an id outside of the component + font.pointSize: layout.textPointSize + } +} +``` + +##### Singletons QML Types can be easily made into a singleton, meaning there is only one instance of the type. @@ -762,9 +797,9 @@ import ... once a type is a singleton, its members can be accessed by name from neighboring files. -## Concepts +## Concepts -### Reactive bindings +### Reactive bindings This section assumes knowledge of: [Properties](#properties), @@ -779,7 +814,7 @@ are then re-evaluated and so forth. Bindings can be created in two different ways: -##### Automatic bindings +##### Automatic bindings A reactive binding occurs automatically when you use one or more properties in the definition of another property. . @@ -798,7 +833,7 @@ of another property. . In this example, the button's @@QtQuick.Controls.Button.text property is re-evaluated every time the button is clicked, because the `clicks` property has changed. -###### Avoiding creation +###### Avoiding creation To avoid creating a binding, do not use any other properties in the definition of a property. @@ -816,7 +851,7 @@ as assignments to properties do not create binding. } ``` -##### Manual bindings +##### Manual bindings Sometimes (not often) you need to create a binding inside of a function, signal, or expression. If you need to change or attach a binding at runtime, the `Qt.binding` function can be used to @@ -848,7 +883,7 @@ In this example, `boundText`'s `text` property is bound to the button's pressed when the button is first clicked. When you press or unpress the button the text will be updated. -##### Removing bindings +##### Removing bindings To remove a binding, just assign a new value to the property without using `Qt.binding`. @@ -871,7 +906,7 @@ When the button is first pressed, the text will be updated, but once `onClicked` the text will be unbound, and even though it contains a reference to the `pressed` property, it will not be updated further by the binding. -### Lazy loading +### Lazy loading Often not all of your interface needs to load immediately. By default the QML engine initializes every object in the scene before showing anything onscreen. @@ -879,7 +914,7 @@ For parts of the interface you don't need to be immediately visible, load them asynchronously using a @@Quickshell.LazyLoader. See its documentation for more information. -#### Components +#### Components Another delayed loading mechanism is the @@QtQml.Component type. This type can be used to create multiple instances of objects or lazily load them. It's used by types such From 9c669b4afac6af133ce68b247527e38b0160075d Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 7 Jun 2025 21:30:37 -0700 Subject: [PATCH 5/6] faq: add icon fallback --- src/guide/faq.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/guide/faq.mdx b/src/guide/faq.mdx index 3ed493f..58f88f9 100644 --- a/src/guide/faq.mdx +++ b/src/guide/faq.mdx @@ -52,6 +52,14 @@ inside of them. } ``` +### Get rid of the purple/black icons +The @@Quickshell.Quickshell.iconPath() function has three variants: +- One draws a purple/black square if the icon is missing. +- One allows you to specify a fallback icon if the desired one is missing. +- One returns an empty string if the icon is missing. + +Either of the last two variants can be used to avoid the purple/black square. + ## Something is broken ### There is a hole in my window From 068e2062267e1b58818f60404f7a28d7bf239bf1 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 8 Jun 2025 01:53:24 -0700 Subject: [PATCH 6/6] add about page --- .../navigation/sidebars/nav/RootNav.astro | 15 ++++++---- src/layouts/GuideLayout.astro | 25 ++++++++++++++++ src/layouts/GuideMdLayout.astro | 17 +++++++++++ src/pages/docs/about.mdx | 30 +++++++++++++++++++ src/pages/docs/guide/[...id].astro | 18 +++-------- 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 src/layouts/GuideLayout.astro create mode 100644 src/layouts/GuideMdLayout.astro create mode 100644 src/pages/docs/about.mdx diff --git a/src/components/navigation/sidebars/nav/RootNav.astro b/src/components/navigation/sidebars/nav/RootNav.astro index 95330d8..6e9f22e 100644 --- a/src/components/navigation/sidebars/nav/RootNav.astro +++ b/src/components/navigation/sidebars/nav/RootNav.astro @@ -1,8 +1,8 @@ --- export interface Props { - currentRoute: string; - currentModule: string; - currentClass: string; + currentRoute?: string; + currentModule?: string; + currentClass?: string; } const { currentRoute, currentModule, currentClass } = Astro.props; @@ -36,14 +36,14 @@ function genGuideNav(base: string): TreeEntry[] | undefined { const guide = { title: "Usage Guide", link: "/docs/guide", - current: currentRoute.startsWith("guide"), + current: currentRoute?.startsWith("guide") ?? false, entries: genGuideNav(""), } const types = { title: "Quickshell Types", link: "/docs/types", - current: currentRoute.startsWith("types"), + current: currentRoute?.startsWith("types") ?? false, entries: Object.entries(groupedRoutes.types).map( ([module, items]) => ({ title: module, @@ -59,6 +59,11 @@ const types = { }; ---