add Qt6 version of some examples (see below); revisions

'9999', 'advanced-qml-auto-reload', 'planets', 'sokoban'
This commit is contained in:
pls.153 2024-10-22 13:27:56 +02:00
parent ca79dec909
commit dc29ac9084
87 changed files with 963 additions and 74 deletions

View file

@ -0,0 +1,69 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Window
Rectangle {
id: main
width: 200
height: 300 + input.height
color: "lavender"
TextField {
id: input
objectName: "input"
width: parent.width
horizontalAlignment: Qt.AlignHCenter
text: "0000"
inputMask: "9999"
inputMethodHints: Qt.ImhDigitsOnly
focus: true
onTextChanged: Lisp.call("app:draw-number", Number(text))
}
Canvas {
id: canvas
objectName: "canvas"
y: input.height
width: parent.width
height: {
var h = Qt.inputMethod.keyboardRectangle.y
var f = (Qt.platform.os === "android") ? Screen.devicePixelRatio : 1
h = (h === 0) ? main.height : h / f
return (h - input.height)
}
property var ctx
// functions to be called from Lisp
function begin(color, width) {
ctx.beginPath()
ctx.strokeStyle = color
ctx.lineWidth = width
ctx.lineCap = "round"
}
function end() {
ctx.stroke()
}
function drawLine(x1, y1, x2, y2) {
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
}
onPaint: {
ctx = getContext("2d")
ctx.reset()
ctx.translate(canvas.width / 2, canvas.height / 2)
var s = height / 340
ctx.scale(s, s)
Lisp.call("app:paint")
ctx.stroke()
}
}
}

View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -0,0 +1,22 @@
(in-package :cl-user)
(defparameter *dir* *load-truename*)
(defvar *template* (with-open-file (s (merge-pathnames ".template.qml" *dir*))
(let ((str (make-string (file-length s))))
(read-sequence str s)
str)))
(defun create-qml-loaders ()
(dolist (file (directory (merge-pathnames "ext/**/*.qml" *dir*)))
(let* ((name (namestring file))
(p (1+ (search "/ext/" name)))
(loader (concatenate 'string (subseq name 0 p) "." (subseq name p))))
(unless (probe-file loader)
(ensure-directories-exist loader)
(with-open-file (s loader :direction :output)
(let ((new (subseq name p)))
(format t "~&creating .~A~%" new)
(format s *template* (subseq name p))))))))
(create-qml-loaders)

View file

@ -0,0 +1,15 @@
import QtQuick
Loader {
objectName: "ext/Page1.qml"
source: objectName
Component.onCompleted: if (width === 0) { anchors.fill = parent }
function reload() {
var src = source
source = ""
Engine.clearCache()
source = src
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
Loader {
objectName: "ext/Page2.qml"
source: objectName
Component.onCompleted: if (width === 0) { anchors.fill = parent }
function reload() {
var src = source
source = ""
Engine.clearCache()
source = src
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
Loader {
objectName: "ext/Page3.qml"
source: objectName
Component.onCompleted: if (width === 0) { anchors.fill = parent }
function reload() {
var src = source
source = ""
Engine.clearCache()
source = src
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
Loader {
objectName: "ext/Repl.qml"
source: objectName
Component.onCompleted: if (width === 0) { anchors.fill = parent }
function reload() {
var src = source
source = ""
Engine.clearCache()
source = src
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
Loader {
objectName: "~A"
source: objectName
Component.onCompleted: if (width === 0) { anchors.fill = parent }
function reload() {
var src = source
source = ""
Engine.clearCache()
source = src
}
}

View file

@ -0,0 +1,15 @@
import QtQuick
Item {
Rectangle {
anchors.fill: parent
color: Qt.lighter("red", 1.5)
border.width: 10
border.color: "red"
Text {
anchors.centerIn: parent
text: "<h2>page 1</h2>"
}
}
}

View file

@ -0,0 +1,16 @@
import QtQuick
Item {
Rectangle {
anchors.fill: parent
radius: 100
color: Qt.lighter("green", 3.0)
border.width: 10
border.color: "green"
Text {
anchors.centerIn: parent
text: "<h2>page 2</h2>"
}
}
}

View file

@ -0,0 +1,18 @@
import QtQuick
Item {
Rectangle {
anchors.centerIn: parent
width: Math.min(parent.width, parent.height)
height: width
radius: width
color: Qt.lighter("blue", 1.7)
border.width: 10
border.color: "blue"
Text {
anchors.centerIn: parent
text: "<h2>page 3</h2>"
}
}
}

View file

@ -0,0 +1,160 @@
import QtQuick
import QtQuick.Controls
Item {
id: repl
z: 1
anchors.fill: parent
Row {
anchors.right: parent.right
z: 1
Text {
text: "REPL"
anchors.verticalCenter: show.verticalCenter
visible: !show.checked
}
Switch {
id: show
onCheckedChanged: container.enabled = checked
}
}
Column {
id: container
opacity: 0
Rectangle {
width: repl.parent.width
height: repl.parent.height / 4
color: "#101010"
ListView {
id: replOutput
objectName: "repl_output"
anchors.fill: parent
contentWidth: parent.width * 4
clip: true
model: replModel
flickableDirection: Flickable.HorizontalAndVerticalFlick
delegate: Column {
Rectangle {
width: replOutput.contentWidth
height: 1
color: "#707070"
visible: mLine
}
Text {
x: 2
padding: 2
textFormat: Text.PlainText
font.family: fontHack.name
font.bold: mBold
text: mText
color: mColor
}
}
}
ListModel {
id: replModel
objectName: "repl_model"
function appendText(data) {
append(data)
replOutput.contentX = 0
replOutput.positionViewAtEnd()
}
}
}
Row {
width: repl.parent.width
TextField {
id: input
objectName: "repl_input"
width: repl.parent.width - 2 * back.width
font.family: fontHack.name
font.bold: true
color: "#c0c0c0"
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
focus: show.checked
palette {
highlight: "#e0e0e0"
highlightedText: "#101010"
}
background: Rectangle {
color: "#101010"
border.width: 2
border.color: "gray"
}
onAccepted: Lisp.call("eval:eval-in-thread", text)
}
Button {
id: back
objectName: "history_back"
width: 40
height: input.height
focusPolicy: Qt.NoFocus
font.family: fontIcons.name
font.pixelSize: 26
text: "\uf100"
onClicked: Lisp.call("eval:history-move", "back")
}
Rectangle {
width: 1
height: input.height
color: "#101010"
}
Button {
id: forward
objectName: "history_forward"
width: back.width
height: input.height
focusPolicy: Qt.NoFocus
font.family: fontIcons.name
font.pixelSize: 26
text: "\uf101"
onClicked: Lisp.call("eval:history-move", "forward")
}
}
Rectangle {
width: repl.parent.width
height: 1
color: "#101010"
}
}
ProgressBar {
objectName: "progress"
anchors.top: container.bottom
width: repl.width
z: 1
indeterminate: true
enabled: visible
visible: false
}
states: [
State { when: show.checked; PropertyChanges { target: container; opacity: 0.9; y: 0 }},
State { when: !show.checked; PropertyChanges { target: container; opacity: 0.0; y: -height }}
]
transitions: [
Transition { NumberAnimation { properties: "opacity,y"; duration: 250; easing.type: Easing.InCubic }}
]
}

View file

@ -0,0 +1,49 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import ".ext/" as Ext // for single file auto reload (development)
//import "ext/" as Ext // release version
Rectangle {
id: main
width: 300
height: 500
objectName: "main"
color: "black"
SwipeView {
id: view
objectName: "view"
anchors.fill: parent
Rectangle {
color: "white"
Ext.Repl {}
Text {
anchors.centerIn: parent
text: "swipe for next page"
}
}
// N.B. don't use Loader inside a Repeater here, won't work with single
// file auto reload (which already uses a Loader)
Ext.Page1 {}
Ext.Page2 {}
Ext.Page3 {}
}
PageIndicator {
anchors.bottom: view.bottom
anchors.bottomMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
count: view.count
currentIndex: view.currentIndex
}
FontLoader { id: fontIcons; source: "fonts/fontawesome-webfont.ttf" }
FontLoader { id: fontHack; source: "fonts/Hack-Regular.ttf" }
FontLoader { id: fontHackBold; source: "fonts/Hack-Bold.ttf" }
}

2
examples/Qt6/meshtastic/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

2
examples/Qt6/planets/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -0,0 +1,193 @@
import QtQuick
Item {
id: main
objectName: "main"
width: 300
height: 500
Rectangle {
anchors.fill: parent
color: "#101010"
}
ListView {
id: view
objectName: "view"
anchors.fill: parent
delegate: planetInfo
model: planets
}
ListModel {
id: planets
objectName: "planets"
// example of inline item
//ListElement { name: "Earth"; shape: "img/earth.png"; map: "img/earth-map.jpg"; info: "..." }
function addPlanet(planet) { append(planet) }
}
property int itemHeight: 44
Component {
id: planetInfo
Item {
id: wrapper
width: view.width
height: itemHeight
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: itemHeight
color: "#303060"
border.color: Qt.lighter(color, 1.2)
Text {
x: 15
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 4
font.pixelSize: parent.height - 22
color: "#f0f0f0"
text: model.name // see Lisp keyword name
}
}
Rectangle {
id: image
width: itemHeight - 4
height: width
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
color: "#101010"
Column {
id: imageColumn
anchors.fill: parent
Image {
id: shapeImage
height: parent.height - mapImage.height
width: parent.width
fillMode: Image.PreserveAspectFit
source: model.shape // see Lisp keyword name
}
Image {
id: mapImage
width: parent.width
height: 0
fillMode: Image.PreserveAspectFit
source: model.map // see Lisp keyword name
}
}
}
MouseArea {
anchors.fill: parent
onClicked: parent.state = "expanded"
}
Item {
id: infoView
anchors.top: image.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
opacity: 0
Rectangle {
anchors.fill: parent
color: "#303060"
border.color: "#101010"
border.width: 1
Flickable {
id: flick
anchors.fill: parent
anchors.margins: 4
contentWidth: edit.paintedWidth
contentHeight: edit.paintedHeight
clip: true
function ensureVisible(r) {
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x + r.width)
contentX = r.x + r.width-width;
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y + r.height)
contentY = r.y + r.height-height;
}
TextEdit {
id: edit
width: flick.width
color: "#f0f0f0"
font.pixelSize: 16
readOnly: true
focus: true
wrapMode: TextEdit.Wrap
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
text: model.info // see Lisp keyword name
}
}
}
}
Rectangle {
id: closeButton
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
width: itemHeight - 4
height: width
color: "transparent"
border.color: "#f0f0f0"
opacity: 0
Text {
anchors.centerIn: parent
color: "#f0f0f0"
font.bold: true
text: "X"
}
MouseArea {
anchors.fill: parent
onClicked: wrapper.state = ""
}
}
states: [
State {
name: "expanded"
PropertyChanges { target: wrapper; height: view.height }
PropertyChanges { target: image; width: view.width; height: view.height * 2/3; anchors.rightMargin: 0; anchors.topMargin: itemHeight }
PropertyChanges { target: mapImage; height: view.height * 1/3 }
PropertyChanges { target: infoView; opacity: 1 }
PropertyChanges { target: closeButton; opacity: 1 }
PropertyChanges { target: wrapper.ListView.view; contentY: wrapper.y; interactive: false }
}
]
transitions: [
Transition {
NumberAnimation {
duration: 250
properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"
}
}
]
}
}
}

2
examples/Qt6/sokoban/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -0,0 +1,16 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
Button {
width: main.small ? 37 : 50
height: width
flat: true
focusPolicy: Qt.NoFocus
font.family: fontAwesome.name
font.pixelSize: 1.2 * width
opacity: 0.2
scale: 1.2
onPressed: Lisp.call(this, "qsoko:button-pressed")
}

View file

@ -0,0 +1,13 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
Button {
width: main.small ? 32 : 50
height: width
font.family: fontAwesome.name
font.pixelSize: width - 6
opacity: 0.8
onPressed: Lisp.call(this, "qsoko:button-pressed")
}

View file

@ -0,0 +1,21 @@
import QtQuick
Item {
objectName: "dynamic"
property Component box: Qt.createComponent("dynamic/Box.qml")
property Component box2: Qt.createComponent("dynamic/Box2.qml")
property Component player: Qt.createComponent("dynamic/Player.qml")
property Component fixed: Qt.createComponent("dynamic/Fixed.qml")
function createItem(name) {
switch (name) {
case "object": return box.createObject()
case "object2": return box2.createObject()
case "player":
case "player2": return player.createObject()
case "wall":
case "goal": return fixed.createObject()
}
}
}

View file

@ -0,0 +1,6 @@
import QtQuick
NumberAnimation {
onRunningChanged: Lisp.call("qsoko:animation-change", running)
}

View file

@ -0,0 +1,6 @@
import QtQuick
RotationAnimation {
onRunningChanged: Lisp.call("qsoko:animation-change", running)
}

View file

@ -0,0 +1,5 @@
import QtQuick
ScaleAnimator {
onRunningChanged: Lisp.call("qsoko:animation-change", running)
}

View file

@ -0,0 +1,6 @@
import QtQuick
SequentialAnimation {
onRunningChanged: Lisp.call("qsoko:animation-change", running)
}

View file

@ -0,0 +1,18 @@
import QtQuick
import "../" as Ext
Image {
Behavior on x {
Ext.NumberAnimation {
duration: 150
easing.type: Easing.InQuart
}
}
Behavior on y {
Ext.NumberAnimation {
duration: 150
easing.type: Easing.InQuart
}
}
}

View file

@ -0,0 +1,48 @@
import QtQuick
import "../" as Ext
Image {
id: box2
Behavior on x {
Ext.NumberAnimation {
duration: 150
easing.type: Easing.InQuart
}
}
Behavior on y {
Ext.NumberAnimation {
duration: 150
easing.type: Easing.InQuart
}
}
// final animation
Ext.SequentialAnimation {
objectName: "wiggle_box"
loops: 3
RotationAnimation {
target: box2
property: "rotation"
from: 0; to: 30
duration: 150
}
RotationAnimation {
target: box2
property: "rotation"
from: 30; to: -30
duration: 300
}
RotationAnimation {
target: box2
property: "rotation"
from: -30; to: 0
duration: 150
}
}
}

View file

@ -0,0 +1,4 @@
import QtQuick
Image {
}

View file

@ -0,0 +1,30 @@
import QtQuick
import "../" as Ext
Image {
id: player
Behavior on x {
Ext.NumberAnimation {
duration: 120
easing.type: Easing.InOutSine
}
}
Behavior on y {
Ext.NumberAnimation {
duration: 120
easing.type: Easing.InOutSine
}
}
// final animation
Ext.RotationAnimation {
objectName: "rotate_player"
target: player
property: "rotation"
from: 0; to: 360
duration: 600
}
}

View file

@ -0,0 +1,157 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Window
import "ext/" as Ext
Rectangle {
id: main
width: Screen.desktopAvailableWidth
height: Screen.desktopAvailableHeight
color: Qt.darker("lightsteelblue", 1.25)
property bool small: (Math.max(width, height) < 1000)
function isLandscape() { return (Screen.primaryOrientation === Qt.LandscapeOrientation) }
Ext.Dynamic {}
Row {
anchors.centerIn: parent
// adapt 'level' and 'board' scale to screen size
scale: isLandscape()
? ((Screen.desktopAvailableHeight - 10) / board.height)
: ((Screen.desktopAvailableWidth - 10) / (board.width + 2 * level.width))
Slider {
id: level
objectName: "level"
height: board.height
orientation: Qt.Vertical
stepSize: 1.0
onValueChanged: Lisp.call("qsoko:set-maze")
}
Rectangle {
id: board
objectName: "board"
width: 512; height: 512
color: "lightsteelblue"
}
// dummy to have it exactly centered
Item {
width: level.width
height: level.height
}
}
Row {
id: buttons1
objectName: "buttons1"
spacing: main.small ? 10 : 15
padding: 10
anchors.bottom: parent.bottom
Ext.Button {
objectName: "previous"
text: "\uf100"
}
Ext.Button {
objectName: "next"
text: "\uf101"
}
}
Row {
id: buttons2
objectName: "buttons2"
spacing: main.small ? 10 : 15
padding: 10
anchors.right: parent.right
anchors.bottom: parent.bottom
Ext.Button {
objectName: "undo"
text: "\uf112"
}
Ext.Button {
objectName: "restart"
text: "\uf0e2"
}
Ext.Button {
objectName: "solve"
text: "\uf17b"
}
}
// container for arrow buttons
Item {
id: arrows
y: buttons1.y - height - (main.small ? 25 : 50)
width: up.width * 3
height: up.height * 3
anchors.margins: 10
anchors.horizontalCenter: buttons2.horizontalCenter
Ext.ArrowButton {
id: up
objectName: "up"
text: "\uf139"
anchors.horizontalCenter: parent.horizontalCenter
}
Ext.ArrowButton {
objectName: "left"
text: "\uf137"
anchors.verticalCenter: parent.verticalCenter
}
Ext.ArrowButton {
objectName: "right"
text: "\uf138"
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
}
Ext.ArrowButton {
objectName: "down"
text: "\uf13a"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
}
}
// level change animations
Ext.ScaleAnimator {
objectName: "zoom_board_out"
target: board
from: 1.0
to: 0.0
duration: 250
}
Ext.ScaleAnimator {
objectName: "zoom_board_in"
target: board
from: 0.0
to: 1.0
duration: 250
}
// etc
Keys.onPressed: {
if (event.key === Qt.Key_Back) {
event.accepted = true
Lisp.call("qml:qquit")
}
}
FontLoader {
id: fontAwesome
source: "fonts/fontawesome-webfont.ttf"
}
}

View file

@ -30,7 +30,7 @@ win32: PRE_TARGETDEPS = tmp/app.lib
QT += quick qml quickcontrols2
TEMPLATE = app
CONFIG += c++17 no_keywords release
DEFINES += DESKTOP_APP INI_LISP INI_ASDF INI_ECL_CONTRIB QT_EXTENSION
DEFINES += DESKTOP_APP INI_LISP INI_ASDF INI_ECL_CONTRIB QT_EXTENSION # NO_USB
INCLUDEPATH = /usr/local/include
ECL_VERSION = $$lower($$system(ecl -v))
ECL_VERSION = $$replace(ECL_VERSION, " ", "-")

View file

@ -1,3 +1,5 @@
*This example is outdated and not really useful anymore, sorry.*
Try it
------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -1,10 +0,0 @@
{
"UrlTemplate": "https://tile.openstreetmap.org/%z/%x/%y.png",
"ImageFormat": "png",
"QImageFormat": "Indexed8",
"ID": "cl-meshtastic",
"MaximumZoomLevel": 19,
"MapCopyRight": "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>",
"DataCopyRight": ""
}

View file

@ -105,7 +105,7 @@
<h2>Simple Standalone Device</h2>
<img src="img/chatter.jpg" width=280>
<p>
Support for Meshtastic is increasing continuously. These are <i>CircuitMess Chatter 2.0</i> devices (they come in pairs). Currently only available on ebay.
Support for Meshtastic is increasing continuously. These are <i>CircuitMess Chatter 2.0</i> devices (they come in pairs). I found them on US amazon, also available on ebay.
</p>
<p>
They have some limitations: they only support <i>MediumSlow</i> instead of <i>LongFast</i>, and have a lousy antenna, but work great if those limitations are acceptable for one's use case.

2
examples/palindrome/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -38,8 +38,8 @@ LQML is **BSD** 0 clause.
Tested
------
The examples are only tested with **Qt5.15**. The binding also works with
**Qt6**, but would need some adaption of QML in most examples. It's recommended
The examples are tested with both **Qt5.15** and **Qt6**. For differences
in Qt6 (mostly in QML) see [examples/Qt6/](examples/Qt6/). It's recommended
to use the new Qt online installer (see [readme-qt](readme-qt.md)), where
you can choose to install different Qt versions side by side, sharing the same
Qt Creator.