added markdown parser for @@ types used in typegen

This commit is contained in:
outfoxxed 2024-10-16 04:22:33 -07:00
parent 77e2d05d6f
commit 00feaca3d5
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 226 additions and 206 deletions

View file

@ -104,12 +104,12 @@ export function getQMLTypeLinkObject(unparsed: string) {
: linkSplit[0];
const linkObj: QMLTypeLinkObject = {
type: "qt",
module: linkModule,
module: linkModule.replace("_", "-"),
name: linkSplit[1].slice(1),
};
if (linkSplit.length > 2) {
linkObj.mname = linkSplit[3];
linkObj.mtype = linkSplit[4];
linkObj.mname = linkSplit[2].slice(1);
linkObj.mtype = linkSplit[3].slice(1);
}
return linkObj;
},

View file

@ -1,10 +1,12 @@
import type { Parent, Node } from "unist";
import { visit, CONTINUE, SKIP } from "unist-util-visit";
import { fromHtml } from "hast-util-from-html";
import type { Root } from "hast";
import type * as Unist from "unist";
import type * as Html from "hast";
import type * as Md from "mdast";
import type {
AstroMarkdownOptions,
MarkdownProcessor,
RemarkPlugin,
RehypePlugin,
} from "@astrojs/markdown-remark";
import { createMarkdownProcessor } from "@astrojs/markdown-remark";
@ -18,19 +20,52 @@ import {
getIconForLink,
} from "./helpers.ts";
// couldn't find the actual type to use
interface HtmlNode extends Node {
value: string;
type: string;
tagName: string;
}
const remarkParseAtTypes: RemarkPlugin<[]> = () => {
return (root: Md.Root): Md.Root => {
visit(
root as Unist.Parent,
(rawNode: Unist.Node) => {
if (rawNode.type === "text" || (rawNode.type === "code" && (rawNode as Md.Code).lang === "qml")) {
const node = rawNode as Md.Literal;
node.value = node.value.replace(
/@@((?<module>([A-Z]\w*\.)*)(?<type>([A-Z]\w*))\.?)?((?<member>[a-z]\w*)((?<function>\(\))|(?<signal>\(s\)))?)?(?=[$.,;:\s]|$)/g,
(_full, ...args) => {
type Capture = {
module: string | undefined;
type: string | undefined;
member: string | undefined;
function: string | undefined;
signal: string | undefined;
}
const groups = args.pop() as Capture;
if (groups.module) {
groups.module = groups.module.substring(0, groups.module.length - 1);
const isQs = groups.module.startsWith("Quickshell");
groups.module = `99M${isQs ? "QS" : "QT_qml"}_${groups.module.replace(".", "_")}`;
} else groups.module = ""; // WARNING: rehype parser can't currently handle intra-module links
groups.type = groups.type ? `99N${groups.type}` : "";
groups.member = groups.member ? `99V${groups.member}` : "";
const type = groups.member ? `99T${groups.function ? "func" : groups.signal ? "signal" : "prop"}` : "";
return `TYPE${groups.module}${groups.type}${groups.member}${type}99TYPE`;
}
);
}
}
);
return root;
};
};
const rehypeRewriteTypelinks: RehypePlugin<[]> = () => {
return (root: Node): Root => {
return (root: Html.Root): Html.Root => {
visit(
root,
root as Unist.Parent,
"text",
(node: HtmlNode, index: number, parent: Parent) => {
(node: Html.Text, index: number, parent: Html.Parent) => {
let changed = false;
node.value = node.value.replace(
@ -65,7 +100,7 @@ const rehypeRewriteTypelinks: RehypePlugin<[]> = () => {
}
);
return root as Root;
return root;
};
};
@ -93,7 +128,7 @@ export const markdownConfig: AstroMarkdownOptions = {
wrap: true,
transformers: [shikiRewriteTypelinks],
},
remarkPlugins: [[remarkAlert, { legacyTitle: true }]],
remarkPlugins: [remarkParseAtTypes, [remarkAlert, { legacyTitle: true }]],
rehypePlugins: [
// FIXME: incompatible types between unified/Plugin and Astro/RehypePlugin
[sectionize as RehypePlugin, { idPropertyName: "id" }],

View file

@ -26,7 +26,7 @@ Each shell file starts with the shell root object. Only one may exist per config
```qml {filename="~/.config/quickshell/shell.qml"}
import Quickshell
QS_Quickshell_ShellRoot {
@@Quickshell.ShellRoot {
// ...
}
```
@ -82,8 +82,8 @@ We'll start with an example:
import Quickshell // for ShellRoot and PanelWindow
import QtQuick // for Text
QS_Quickshell_ShellRoot {
QS_Quickshell_PanelWindow {
@@Quickshell.ShellRoot {
@@Quickshell.PanelWindow {
anchors {
top: true
left: true
@ -92,7 +92,7 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
// center the bar in its parent component (the window)
anchors.centerIn: parent
@ -115,9 +115,8 @@ To start with lets make a clock. To get the time we'll use the `date` command.
We can use a [Process](/docs/types/quickshell.io/process) object to run commands
and return their results.
We'll listen to the [DataStreamParser.read](/docs/types/quickshell.io/datastreamparser/#signal.read)
[signal](/docs/configuration/qml-overview/#signals) emitted by
[SplitParser](/docs/types/quickshell.io/splitparser/) using a
We'll listen to the @@Quickshell.Io.DataStreamParser.read(s) emitted by
@@Quickshell.Io.SplitParser using a
[signal handler](/docs/configuration/qml-overview/#signal-handlers)
to update the text on the clock.
@ -130,8 +129,8 @@ import Quickshell
import Quickshell.Io // for Process
import QtQuick
QS_Quickshell_ShellRoot {
QS_Quickshell_PanelWindow {
@@Quickshell.ShellRoot {
@@Quickshell.PanelWindow {
anchors {
top: true
left: true
@ -140,14 +139,14 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
// give the text an ID we can refer to elsewhere in the file
id: clock
anchors.centerIn: parent
// create a process management object
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
// the command it will run, every argument is its own string
command: ["date"]
@ -156,7 +155,7 @@ QS_Quickshell_ShellRoot {
// process the stdout stream using a SplitParser
// which returns chunks of output after a delimiter
stdout: QS_Quickshell00Io_SplitParser {
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
@ -170,15 +169,15 @@ QS_Quickshell_ShellRoot {
## <MD_Title titleVar={2}> Running code at an interval </MD_Title>
With the above example, your bar should now display the time, but it isn't updating!
Let's use a [Timer](https://doc.qt.io/qt-6/qml-qtqml-timer.html) fix that.
Let's use a @@QtQml.Timer to fix that.
```qml
import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_ShellRoot {
QS_Quickshell_PanelWindow {
@@Quickshell.ShellRoot {
@@Quickshell.PanelWindow {
anchors {
top: true
left: true
@ -187,11 +186,11 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
id: clock
anchors.centerIn: parent
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
// give the process object an id so we can talk
// about it from the timer
id: dateProc
@ -199,13 +198,13 @@ QS_Quickshell_ShellRoot {
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
}
// use a timer to rerun the process at an interval
QT_qtqml_Timer {
@@QtQml.Timer {
// 1000 milliseconds is 1 second
interval: 1000
@ -230,34 +229,31 @@ If you have multiple monitors you might have noticed that your bar
is only on one of them. If not, you'll still want to **follow this section
to make sure your bar doesn't disappear if your monitor disconnects**.
We can use a [Variants](/docs/types/quickshell/variants)
object to create instances of _non widget items_.
(See [Repeater](https://doc.qt.io/qt-6/qml-qtquick-repeater.html) for doing
We can use a @@Quickshell.Variants object to create instances of _non widget items_.
(See @@QtQuick.Repeater for doing
something similar with visual items.)
The `Variants` type creates instances of a
[Component](https://doc.qt.io/qt-6/qml-qtqml-component.html) based on a data model
you supply. (A component is a re-usable tree of objects.)
The @@Quickshell.Variants type creates instances of a @@QtQml.Component based on
a data model you supply. (A component is a re-usable tree of objects.)
The most common use of `Variants` in a shell is to create instances of
The most common use of @@Quickshell.Variants in a shell is to create instances of
a window (your bar) based on your monitor list (the data model).
Variants will inject the values in the data model into each new
@@Quickshell.Variants will inject the values in the data model into each new
component's `modelData` property, which means we can easily pass each screen
to its own component.
(See [Window.screen](/docs/types/quickshell/qswindow/#prop.screen).)
to its own component. (See @@Quickshell.QsWindow.screen.)
```qml
import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_ShellRoot {
QS_Quickshell_Variants {
@@Quickshell.ShellRoot {
@@Quickshell.Variants {
model: Quickshell.screens;
delegate: QT_qtqml_Component {
QS_Quickshell_PanelWindow {
delegate: @@QtQml.Component {
@@Quickshell.PanelWindow {
// the screen from the screens list will be injected into this
// property
property var modelData
@ -273,21 +269,21 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
id: clock
anchors.centerIn: parent
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -301,16 +297,13 @@ QS_Quickshell_ShellRoot {
```
<span class="small">
See also: [Property
Bindings](/docs/configuration/qml-overview/#property-bindings),
[Variants.component](/docs/types/quickshell/variants/#prop.component),
[Quickshell.screens](/docs/types/quickshell/quickshell/#prop.screens),
See also: [Property Bindings](/docs/configuration/qml-overview/#property-bindings),
[Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
</span>
With this example, bars will be created and destroyed as you plug and unplug them,
due to the reactive nature of the
[Quickshell.screens](/docs/types/quickshell/quickshell/#prop.screens) property.
@@Quickshell.Quickshell.screens property.
(See: [Reactive Bindings](/docs/configuration/qml-overview/#reactive-bindings).)
Now there's an important problem you might have noticed: when the window
@ -325,12 +318,12 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_ShellRoot {
QS_Quickshell_Variants {
@@Quickshell.ShellRoot {
@@Quickshell.Variants {
model: Quickshell.screens
delegate: QT_qtqml_Component {
QS_Quickshell_PanelWindow {
delegate: @@QtQml.Component {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -342,7 +335,7 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
id: clock
anchors.centerIn: parent
}
@ -350,17 +343,17 @@ QS_Quickshell_ShellRoot {
}
}
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => clock.text = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -400,17 +393,17 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_ShellRoot {
@@Quickshell.ShellRoot {
id: root
// add a property in the root
property string time;
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
delegate: QT_qtqml_Component {
QS_Quickshell_PanelWindow {
delegate: @@QtQml.Component {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -422,7 +415,7 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
// remove the id as we don't need it anymore
anchors.centerIn: parent
@ -434,18 +427,18 @@ QS_Quickshell_ShellRoot {
}
}
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
// update the property instead of the clock directly
onRead: data => root.time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -460,12 +453,11 @@ above code, but we can make it more concise:
1. `Component`s can be defined implicitly, meaning we can remove the
component wrapping the window and place the window directly into the
`delegate` property.
2. The [Variants.delegate](/docs/types/quickshell/variants/#prop.delegate)
property is a [Default Property](/docs/configuration/qml-overview/#the-default-property),
2. The @@Quickshell.Variants.delegate property is a
[Default Property](/docs/configuration/qml-overview/#the-default-property),
which means we can skip the `delegate:` part of the assignment.
We're already using [ShellRoot](/docs/types/quickshell/shellroot/)'s
default property to store our Variants, Process, and Timer components
among other things.
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).
@ -477,13 +469,13 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_ShellRoot {
@@Quickshell.ShellRoot {
property string time;
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
QS_Quickshell_PanelWindow {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -495,7 +487,7 @@ QS_Quickshell_ShellRoot {
height: 30
QT__Text {
@@QtQuick.Text {
anchors.centerIn: parent
// now just time instead of root.time
@ -504,18 +496,18 @@ QS_Quickshell_ShellRoot {
}
}
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
// now just time instead of root.time
onRead: data => time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -534,7 +526,7 @@ To start with, let's move the entire bar into a new file.
```qml {filename="shell.qml"}
import Quickshell
QS_Quickshell_ShellRoot {
@@Quickshell.ShellRoot {
Bar {}
}
```
@ -544,13 +536,13 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_Scope {
@@Quickshell.Scope {
property string time;
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
QS_Quickshell_PanelWindow {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -562,7 +554,7 @@ QS_Quickshell_Scope {
height: 30
QT__Text {
@@QtQuick.Text {
anchors.centerIn: parent
// now just time instead of root.time
@ -571,18 +563,18 @@ QS_Quickshell_Scope {
}
}
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
// now just time instead of root.time
onRead: data => time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -602,12 +594,12 @@ the clock component in the bar, as well as the process and timer that
make up the actual clock, need to be dealt with.
To start with, we can move the clock widget to a new file. For now it's just a
single `Text` object but the same concepts apply regardless of complexity.
single @@QtQuick.Text object but the same concepts apply regardless of complexity.
```qml {filename="ClockWidget.qml"}
import QtQuick
QT__Text {
@@QtQuick.Text {
// A property the creator of this type is required to set.
// Note that we could just set `text` instead, but don't because your
// clock probably will not be this simple.
@ -622,14 +614,14 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_Scope {
@@Quickshell.Scope {
id: root
property string time;
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
QS_Quickshell_PanelWindow {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -650,17 +642,17 @@ QS_Quickshell_Scope {
}
}
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -679,20 +671,20 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_Scope {
@@Quickshell.Scope {
property string time;
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -704,14 +696,14 @@ QS_Quickshell_Scope {
```qml {filename="Bar.qml"}
import Quickshell
QS_Quickshell_Scope {
@@Quickshell.Scope {
// the Time type we just created
Time { id: timeSource }
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
QS_Quickshell_PanelWindow {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -751,20 +743,20 @@ import Quickshell.Io
import QtQuick
// your singletons should always have Singleton as the type
QS_Quickshell_Singleton {
@@Quickshell.Singleton {
property string time
QS_Quickshell00Io_Process {
@@Quickshell.Io.Process {
id: dateProc
command: ["date"]
running: true
stdout: QS_Quickshell00Io_SplitParser {
stdout: @@Quickshell.Io.SplitParser {
onRead: data => time = data
}
}
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true
@ -776,7 +768,7 @@ QS_Quickshell_Singleton {
```qml {filename="ClockWidget.qml"}
import QtQuick
QT__Text {
@@QtQuick.Text {
// we no longer need time as an input
// directly access the time property from the Time singleton
@ -787,13 +779,13 @@ QT__Text {
```qml {filename="Bar.qml"}
import Quickshell
QS_Quickshell_Scope {
@@Quickshell.Scope {
// no more time object
QS_Quickshell_Variants {
@@Quickshell.Variants {
model: Quickshell.screens
QS_Quickshell_PanelWindow {
@@Quickshell.PanelWindow {
property var modelData
screen: modelData
@ -830,11 +822,11 @@ import Quickshell
import Quickshell.Io
import QtQuick
QS_Quickshell_Singleton {
@@Quickshell.Singleton {
property var date: new Date()
property string time: date.toLocaleString(Qt.locale())
QT_qtqml_Timer {
@@QtQml.Timer {
interval: 1000
running: true
repeat: true

View file

@ -32,19 +32,19 @@ page has good documentation of the basic layout types and how to use them.
## <MD_Title titleVar={2}> Manual Positioning </MD_Title>
If layouts and anchors can't easily fulfill your usecase, you can also manually position and size
components by setting their `x`, `y`, `width` and `height` properties, which are relative to
the parent component.
components by setting their @@QtQuick.Item.x, @@QtQuick.Item.y, @@QtQuick.Item.width and @@QtQuick.Item.height
properties, which are relative to the parent component.
This example puts a 100x100px blue rectangle at x=20,y=40 in the parent item. Ensure the size
of the parent is large enough for its content or positioning based on them will break.
```qml
QT__Item {
@@QtQuick.Item {
// make sure the component is large enough to fit its children
implicitWidth: childrenRect.width
implicitHeight: childrenRect.height
QT__Rectangle {
@@QtQuick.Rectangle {
color: "blue"
x: 20
y: 40
@ -58,27 +58,22 @@ QT__Item {
### <MD_Title titleVar={3}> Component Size </MD_Title>
The [Item.implicitHeight] and [Item.implicitWidth] properties control the _base size_ of a
component, before layouts are applied. These properties are _not_ the same as
[Item.height] and [Item.width] which are the final size of the component.
The @@QtQuick.Item.implicitHeight and @@QtQuick.Item.implicitWidth properties control the
_base size_ of a component, before layouts are applied. These properties are _not_ the same as
@@QtQuick.Item.height and @@QtQuick.Item.width which are the final size of the component.
You should nearly always use the implicit size properties when creating a component,
however using the normal width and height properties is fine if you know an
item will never go in a layout.
[Item.height]: https://doc.qt.io/qt-6/qml-qtquick-item.html#height-prop
[Item.width]: https://doc.qt.io/qt-6/qml-qtquick-item.html#width-prop
[Item.implicitHeight]: https://doc.qt.io/qt-6/qml-qtquick-item.html#implicitHeight-prop
[Item.implicitWidth]: https://doc.qt.io/qt-6/qml-qtquick-item.html#implicitWidth-prop
This example component puts a colored rectangle behind some text, and will act the same
way in a layout as the text by itself.
```qml {filename="TextWithBkgColor.qml"}
QT__Rectangle {
@@QtQuick.Rectangle {
implicitWidth: text.implicitWidth
implicitHeight: text.implicitHeight
QT__Text {
@@QtQuick.Text {
id: text
text: "hello!"
}
@ -88,18 +83,18 @@ QT__Rectangle {
If you want to size your component based on multiple others or use any other math you can.
```qml {filename="PaddedTexts.qml"}
QT__Item {
@@QtQuick.Item {
// width of both texts plus 5
implicitWidth: text1.implicitWidth + text2.implicitWidth + 5
// max height of both texts plus 5
implicitHeight: Math.min(text1.implicitHeight, text2.implicitHeight) + 5
QT__Text {
@@QtQuick.Text {
id: text1
text: "text1"
}
QT__Text {
@@QtQuick.Text {
id: text2
anchors.left: text1.left
text: "text2"
@ -110,7 +105,7 @@ QT__Item {
### <MD_Title titleVar={3}> Coordinate space </MD_Title>
You should always position or size components relative to the closest possible
parent. Often this is just the `parent` property.
parent. Often this is just the @@QtQuick.Item.parent property.
Refrain from using things like the size of your screen to size a component,
as this will break as soon as anything up the component hierarchy changes, such

View file

@ -35,7 +35,7 @@ import QtQuick 6.0
import "myjs.js" as MyJs
// Root Object
QT__Item {
@@QtQuick.Item {
// Id assignment
id: root
@ -202,7 +202,7 @@ Expressions are snippets of javascript code assigned to a property. The last (or
can be the return value, or an explicit return statement (multiline expressions only) can be used.
```qml
QT__Item {
@@QtQuick.Item {
// simple expression
property: 5
@ -252,7 +252,7 @@ Properties can be defined inside of objects with the following syntax:
- `binding` is the property binding. See [Property bindings](#property-bindings) for details.
```qml
QT__Item {
@@QtQuick.Item {
// normal property
property int foo: 3
@ -274,12 +274,12 @@ Types can have a _default property_ which must accept either an object or a list
The default property will allow you to assign a value to it without using the name of the property:
```qml
QT__Item {
@@QtQuick.Item {
// normal property
foo: 3
// this item is assigned to the outer object's default property
QT__Item {
@@QtQuick.Item {
}
}
```
@ -288,16 +288,16 @@ If the default property is a list, you can put multiple objects into it the same
would put a single object in:
```qml
QT__Item {
@@QtQuick.Item {
// normal property
foo: 3
// this item is assigned to the outer object's default property
QT__Item {
@@QtQuick.Item {
}
// this one is too
QT__Item {
@@QtQuick.Item {
}
}
```
@ -308,13 +308,13 @@ 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.
```qml
QT_qtquick11layouts_ColumnLayout {
QT__Text {
@@QtQuick.Layouts.ColumnLayout {
@@QtQuick.Text {
id: text
text: "Hello World!"
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: "Make the text red";
onClicked: text.color = "red";
}
@ -344,14 +344,14 @@ The `parent` property is also defined for all objects, but may not always point
looks like it should. Use the `id` property if `parent` does not do what you want.
```qml
QT__Item {
@@QtQuick.Item {
property string rootDefinition
QT__Item {
@@QtQuick.Item {
id: mid
property string midDefinition
QT__Text {
@@QtQuick.Text {
property string innerDefinition
// legal - innerDefinition is defined on the current object
@ -402,19 +402,19 @@ functions, meaning if one of the properties a function depends on is re-evaluate
every expression depending on the function is also re-evaluated.
```qml
QT_qtquick11layouts_ColumnLayout {
@@QtQuick.Layouts.ColumnLayout {
property int clicks: 0
function makeClicksLabel(): string {
return "the button has been clicked " + clicks + " times!";
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: "click me"
onClicked: clicks += 1
}
QT__Text {
@@QtQuick.Text {
text: makeClicksLabel()
}
}
@ -450,7 +450,7 @@ Lambda syntax:
Assigning functions to properties:
```qml
QT__Item {
@@QtQuick.Item {
// using functions
function dub(number: int): int { return number * 2; }
property var operation: dub
@ -463,7 +463,7 @@ QT__Item {
An overcomplicated click counter using a lambda callback:
```qml
QT_qtquick11layouts_ColumnLayout {
@@QtQuick.Layouts.ColumnLayout {
property int clicks: 0
function incrementAndCall(callback) {
@ -471,14 +471,14 @@ QT_qtquick11layouts_ColumnLayout {
callback(clicks);
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: "click me"
onClicked: incrementAndCall(clicks => {
label.text = `the button was clicked ${clicks} time(s)!`;
})
}
QT__Text {
@@QtQuick.Text {
id: label
text: "the button has not been clicked"
}
@ -510,7 +510,7 @@ Signals all have a `connect(<function>)` method which invokes the given function
or signal when the signal is emitted.
```qml
QT_qtquick11layouts_ColumnLayout {
@@QtQuick.Layouts.ColumnLayout {
property int clicks: 0
function updateText() {
@ -518,12 +518,12 @@ QT_qtquick11layouts_ColumnLayout {
label.text = `the button has been clicked ${clicks} times!`;
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
id: button
text: "click me"
}
QT__Text {
@@QtQuick.Text {
id: label
text: "the button has not been clicked"
}
@ -540,9 +540,9 @@ QT_qtquick11layouts_ColumnLayout {
immediately once the object is fully initialized.
</span>
When the button is clicked, the button emits the `clicked` signal which we connected to
`updateText`. The signal then invokes `updateText` which updates the counter and the
text on the label.
When the button is clicked, the button emits the @@QtQuick.Controls.Button.clicked(s)
signal which we connected to `updateText`. The signal then invokes `updateText`
which updates the counter and the text on the label.
##### <MD_Title titleVar={5}> Signal handlers </MD_Title>
@ -553,10 +553,10 @@ property implicitly defined which can be set to a function. (Note that the first
signal's name it capitalized.)
Below is the same example as in [Making Connections](#making-connections),
this time using the implicit signal handler property to handle `button.clicked`.
this time using the implicit signal handler property to handle @@QtQuick.Controls.Button.clicked(s).
```qml
QT_qtquick11layouts_ColumnLayout {
@@QtQuick.Layouts.ColumnLayout {
property int clicks: 0
function updateText() {
@ -564,12 +564,12 @@ QT_qtquick11layouts_ColumnLayout {
label.text = `the button has been clicked ${clicks} times!`;
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: "click me"
onClicked: updateText()
}
QT__Text {
@@QtQuick.Text {
id: label
text: "the button has not been clicked"
}
@ -579,18 +579,18 @@ QT_qtquick11layouts_ColumnLayout {
##### <MD_Title titleVar={5}> Indirect signal handlers </MD_Title>
When it is not possible or not convenient to directly define a signal handler, before resorting
to `.connect`ing the properties, a [Connections] object can be used to access them.
to `.connect`ing the properties, a @@QtQml.Connections object can be used to access them.
This is especially useful to connect to signals of singletons.
```qml
QT__Item {
QT_qtquick11controls_Button {
@@QtQuick.Item {
@@QtQuick.Controls.Button {
id: myButton
text "click me"
}
QT_qtqml_Connections {
@@QtQml.Connections {
target: myButton
function onClicked() {
@ -609,8 +609,8 @@ Whenever the property is re-evaluated, its change signal is emitted. This is use
to update dependent properties, but can be directly used, usually with a signal handler.
```qml
QT_qtquick11layouts_ColumnLayout {
CheckBox {
@@QtQuick.Layouts.ColumnLayout {
@@QtQuick.Controls.CheckBox {
text: "check me"
onCheckStateChanged: {
@ -618,7 +618,7 @@ QT_qtquick11layouts_ColumnLayout {
}
}
QT__Text {
@@QtQuick.Text {
id: label
text: labelText(false)
}
@ -629,19 +629,19 @@ QT_qtquick11layouts_ColumnLayout {
}
```
In this example we listen for the `checkState` property of the CheckBox changing
In this example we listen for changes to the @@QtQuick.Controls.CheckBox.checkState property of the CheckBox
using its change signal, `checkStateChanged` with the signal handler `onCheckStateChanged`.
Since text is also a property we can do the same thing more concisely:
```qml
QT_qtquick11layouts_ColumnLayout {
CheckBox {
@@QtQuick.Layouts.ColumnLayout {
@@QtQuick.Controls.CheckBox {
id: checkbox
text: "check me"
}
QT__Text {
@@QtQuick.Text {
id: label
text: labelText(checkbox.checkState == Qt.Checked)
}
@ -655,13 +655,13 @@ QT_qtquick11layouts_ColumnLayout {
And the function can also be inlined to an expression:
```qml
QT_qtquick11layouts_ColumnLayout {
CheckBox {
@@QtQuick.Layouts.ColumnLayout {
@@QtQuick.Controls.CheckBox {
id: checkbox
text: "check me"
}
QT__Text {
@@QtQuick.Text {
id: label
text: {
const checked = checkbox.checkState == Qt.Checked;
@ -682,11 +682,11 @@ tell you if it can be used as an attached object and how.
Attached objects are accessed in the form `<Typename>.<member>` and can have
properties, functions and signals.
A good example is the [Component](https://doc.qt.io/qt-6/qml-qtqml-component.html) type,
A good example is the @@QtQml.Component type,
which is attached to every object and often used to run code when an object initializes.
```qml
QT__Text {
@@QtQuick.Text {
Component.onCompleted: {
text = "hello!"
}
@ -706,14 +706,14 @@ are not visible outside the file.
```qml
// MyText.qml
QT__Rectangle {
@@QtQuick.Rectangle {
required property string text
color: "red"
implicitWidth: textObj.implicitWidth
implicitHeight: textObj.implicitHeight
QT__Text {
@@QtQuick.Text {
id: textObj
anchors.fill: parent
text: parent.text
@ -721,7 +721,7 @@ QT__Rectangle {
}
// AnotherComponent.qml
QT__Item {
@@QtQuick.Item {
MyText {
// The `text` property of `MyText` is required, so we must set it.
text: "Hello World!"
@ -748,13 +748,13 @@ of the type.
To make a type a singleton, put `pragma Singleton` at the top of the file.
To ensure it behaves correctly with quickshell you should also make
[Singleton](/docs/types/quickshell/singleton) the root item of your type.
@@Quickshell.Singleton the root item of your type.
```qml
pragma Singleton
import ...
QS_Quickshell_Singleton {
@@Quickshell.Singleton {
...
}
```
@ -785,18 +785,18 @@ A reactive binding occurs automatically when you use one or more properties in t
of another property. .
```qml
QT__Item {
@@QtQuick.Item {
property int clicks: 0
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: `clicks: ${clicks}`
onClicked: clicks += 1
}
}
```
In this example, the button's `text` property is re-evaluated every time the button is clicked, because
the `clicks` property has changed.
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.
###### <MD_Title titleVar={6}> Avoiding creation </MD_Title>
@ -806,10 +806,10 @@ You can use the `Component.onCompleted` signal to set a value using a property w
as assignments to properties do not create binding.
```qml
QT__Item {
@@QtQuick.Item {
property string theProperty: "initial value"
QT__Text {
@@QtQuick.Text {
// text: "Right now, theProperty is: " + theProperty
Component.onCompleted: text = "At creation time, theProperty is: " + theProperty
}
@ -826,13 +826,13 @@ The `Qt.binding` function takes another function as an argument, and when assign
the property will use that function as its binding expression.
```qml
QT__Item {
QT__Text {
@@QtQuick.Item {
@@QtQuick.Text {
id: boundText
text: "not bound to anything"
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
text: "bind the above text"
onClicked: {
if (boundText.text == "not bound to anything") {
@ -853,13 +853,13 @@ be updated.
To remove a binding, just assign a new value to the property without using `Qt.binding`.
```qml
QT__Item {
QT__Text {
@@QtQuick.Item {
@@QtQuick.Text {
id: boundText
text: `button is pressed: ${theButton.pressed}`
}
QT_qtquick11controls_Button {
@@QtQuick.Controls.Button {
id: theButton
text: "break the binding"
onClicked: boundText.text = `button was pressed at the time the binding was broken: ${pressed}`
@ -876,13 +876,11 @@ it will not be updated further by the binding.
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.
For parts of the interface you don't need to be immediately visible, load them
asynchronously using a [LazyLoader](/docs/types/quickshell/lazyloader).
asynchronously using a @@Quickshell.LazyLoader.
See its documentation for more information.
#### <MD_Title titleVar={4}> Components </MD_Title>
Another delayed loading mechanism is the [Component](https://doc.qt.io/qt-6/qml-qtqml-component.html) type.
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
as [Repeater](https://doc.qt.io/qt-6/qml-qtquick-repeater.html)
and [Quickshell.Variants](/docs/types/quickshell/variants)
to create instances of a component at runtime.
as @@QtQuick.Repeater and @@Quickshell.Variants to create instances of a component at runtime.