add readme/screenshot for 'QML Live Preview and Slime'; revisions

This commit is contained in:
pls.153 2022-02-25 15:09:02 +01:00
parent d7a999acdb
commit be2b4520d1
17 changed files with 107 additions and 32 deletions

View file

@ -69,11 +69,11 @@
given property of all items sharing the same 'objectName'. given property of all items sharing the same 'objectName'.
<b>qapropos (name &optional qt-object/name)</b> <b>qapropos (string &optional qt-object/name)</b>
Searches properties, methods, signals, slots for NAME in QObject Searches properties, methods, signals, slots for STRING in QObject (e.g.
(e.g. QQuickItem) passed as second argument. QQuickItems can also be passed QQuickItem) passed as second argument. A QQuickItem can also be passed by
by their 'objectName'. its 'objectName'.
(qapropos nil *canvas*) (qapropos nil *canvas*)
(qapropos "color") (qapropos "color")
@ -91,12 +91,20 @@
<b>qcopy-file (from to)</b> <b>qcopy-file (from to)</b>
Convenience function for e.g. copying asset files on android, which can't Convenience function for android, for e.g. copying files from 'assets:/',
be accessed directly from Lisp. which can't be accessed directly from Lisp.
(qcopy-file "assets:/lib/asdf.fas" "asdf.fas") (qcopy-file "assets:/lib/asdf.fas" "asdf.fas")
<b>qdirectory (path)</b>
Convenience function for android, which works also with 'assets:/'
paths.
(qdirectory "assets:/lib")
<b>qescape (string)</b> <b>qescape (string)</b>
Calls QString::toHtmlEscaped(). Calls QString::toHtmlEscaped().
@ -134,7 +142,7 @@
(qget *quick-view* |width|) (qget *quick-view* |width|)
<b>qjs (method-name item/name &rest arguments)</b> <b>qjs (function item/name &rest arguments)</b>
Fast and convenient way to call JS functions defined in QML. You may pass Fast and convenient way to call JS functions defined in QML. You may pass
up to 10 arguments of the following types: up to 10 arguments of the following types:

View file

@ -23,7 +23,7 @@ QMAKE_EXTRA_COMPILERS += lisp
QT += quick qml QT += quick qml
TEMPLATE = app TEMPLATE = app
CONFIG += no_keywords release CONFIG += no_keywords release
DEFINES += INI_LISP DEFINES += INI_LISP # SWANK
INCLUDEPATH = /usr/local/include INCLUDEPATH = /usr/local/include
LIBS = -L/usr/local/lib -lecl LIBS = -L/usr/local/lib -lecl
DESTDIR = . DESTDIR = .

View file

@ -1 +1,2 @@
adb install -r android-build/*.apk adb install -r android-build/*.apk
adb shell am start -n org.qtproject.example.app/org.qtproject.qt5.android.bindings.QtActivity # Qt5

View file

@ -3,7 +3,7 @@ Prepare
------- -------
If you use Qt versions prior to 5.15, you need to adapt the QML module version If you use Qt versions prior to 5.15, you need to adapt the QML module version
to your minor Qt version in file `qml/main.qml`. to your minor Qt version in all files under `qml/`.
Example: Qt5.**12** => import QtQuick 2.**12**. Example: Qt5.**12** => import QtQuick 2.**12**.

View file

@ -14,6 +14,6 @@
;;; for Slime after copying 'lqml-start-swank.lisp' from LQML sources ;;; for Slime after copying 'lqml-start-swank.lisp' from LQML sources
;;; to your Slime directory, which is assumed to be '~/slime/' ;;; to your Slime directory, which is assumed to be '~/slime/'
(when (find "-slime" (ext:command-args) :test 'string=) (when (find "-slime" (ext:command-args) :test 'search)
(load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs (load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs

View file

@ -1,3 +1,3 @@
The Sun, also known by the Latin name Sol and the Greek name Helios, is a yellow dwarf star of spectral type G2V. The eight planets, including Earth, orbit the sun, as do countless other objects. The Sun, also known by the Latin name Sol and the Greek name Helios, is a yellow dwarf star of spectral type G2V. The eight planets, including Earth, orbit the sun, as do countless other objects.
The sun a classified as spectral class G2V. The "G" means it is a moderately warm yellow star. The "2" means it is in the third hottest group of stars within type "G" (the scale runs from 0 to 9). The "V" is a Roman numeral for 5 and indicates the Sun's size. A size V star is a dwarf, main sequence star. The sun is in the 95th percentile in its class by size and mass of other stars in its immediate region. The sun is classified as spectral class G2V. The "G" means it is a moderately warm yellow star. The "2" means it is in the third hottest group of stars within type "G" (the scale runs from 0 to 9). The "V" is a Roman numeral for 5 and indicates the Sun's size. A size V star is a dwarf, main sequence star. The sun is in the 95th percentile in its class by size and mass of other stars in its immediate region.

View file

@ -7,7 +7,7 @@
;;; *** (1) byte-compile ASDF system *** ;;; *** (1) byte-compile ASDF system ***
(si:install-bytecodes-compiler) (ext:install-bytecodes-compiler)
(when *ql-libs* (when *ql-libs*
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" (let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
@ -34,7 +34,7 @@
;;; load and prepare cross-compiler ;;; load and prepare cross-compiler
(si:install-c-compiler) (ext:install-c-compiler)
(defun cc (&rest args) (defun cc (&rest args)
(apply 'concatenate 'string args)) (apply 'concatenate 'string args))

View file

@ -10,8 +10,9 @@ Important note
of any Lisp code next time you do a build. of any Lisp code next time you do a build.
* **LQML**: any time you upgrade LQML, please purge the build directories in * **LQML**: any time you upgrade LQML, please purge the build directories in
`src/` (see also `src/mkdirs.sh`) and rebuild the whole library for every `src/`, including `.qmake.stash` in case you use a different Qt version
single platform. (see also `src/mkdirs.sh`) and rebuild the whole library for every single
platform.

View file

@ -0,0 +1,33 @@
QML Preview and Slime
---------------------
(LQML >= 22.2.2, see `lqml -v`)
If you want to be impressed (I certainly was when I first tried it), do the
following:
* edit `lisp/main.lisp` of an example, and add this line at the end:
```
(load "~/slime/lqml-start-swank.lisp")
```
* edit `app.pro` and change `DEFINES` to:
```
DEFINES += INI_LISP SWANK
```
* open `app.pro` in **Qt Creator**, and in 'Build Settings' choose `build/`
from the example as 'Build directory'
* in the 'Edit' view of Qt Creator choose 'Build / QML Preview' (after a
'Build / Clean')
Now the example should compile and start. You may now select any QML file from
the tree view on the left, and any change to QML will be shown immediately in
the running app, while you are typing!
Additionally you may now also run `M-x slime-connect` from Emacs (the Swank
server should already run, see 'Application Ouput' at the bottom of Qt
Creator).
[Screenshot](screenshots/qml-live-preview-and-slime.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View file

@ -8,6 +8,7 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QThread> #include <QThread>
#include <QFile> #include <QFile>
#include <QDir>
#include <QQuickItem> #include <QQuickItem>
#include <QQuickView> #include <QQuickView>
#include <QQmlEngine> #include <QQmlEngine>
@ -32,6 +33,7 @@ void iniCLFunctions() {
DEFUN ("%qapropos", qapropos2, 3) DEFUN ("%qapropos", qapropos2, 3)
DEFUN ("qchildren", qchildren, 1) DEFUN ("qchildren", qchildren, 1)
DEFUN ("qcopy-file", qcopy_file, 2) DEFUN ("qcopy-file", qcopy_file, 2)
DEFUN ("qdirectory", qdirectory, 1)
DEFUN ("qescape", qescape, 1) DEFUN ("qescape", qescape, 1)
DEFUN ("%qexec", qexec2, 1) DEFUN ("%qexec", qexec2, 1)
DEFUN ("qexit", qexit, 0) DEFUN ("qexit", qexit, 0)
@ -330,7 +332,6 @@ cl_object qexec2(cl_object l_milliseconds) {
LQML::eventLoop->exec(); LQML::eventLoop->exec();
return l_milliseconds; return l_milliseconds;
} }
QCoreApplication::exit(); // prevent "the event loop is already running"
QCoreApplication::exec(); QCoreApplication::exec();
return ECL_T; return ECL_T;
} }
@ -556,13 +557,32 @@ cl_object reload2() {
cl_object qcopy_file(cl_object l_from, cl_object l_to) { cl_object qcopy_file(cl_object l_from, cl_object l_to) {
/// args: (from to) /// args: (from to)
/// Convenience function for e.g. copying asset files on android, which can't /// Convenience function for android, for e.g. copying files from 'assets:/',
/// be accessed directly from Lisp. /// which can't be accessed directly from Lisp.
/// (qcopy-file "assets:/lib/asdf.fas" "asdf.fas") /// (qcopy-file "assets:/lib/asdf.fas" "asdf.fas")
bool ok = QFile::copy(toQString(l_from), toQString(l_to)); bool ok = QFile::copy(toQString(l_from), toQString(l_to));
ecl_return1(ecl_process_env(), ok ? ECL_T : ECL_NIL); ecl_return1(ecl_process_env(), ok ? ECL_T : ECL_NIL);
} }
cl_object qdirectory(cl_object l_dir) {
/// args: (path)
/// Convenience function for android, which works also with 'assets:/'
/// paths.
/// (qdirectory "assets:/lib")
QDir dir(toQString(l_dir));
QFileInfoList infos(dir.entryInfoList());
cl_object l_files = ECL_NIL;
for (QFileInfo info : qAsConst(infos)) {
QString path(info.absoluteFilePath());
if (info.isDir()) {
path.append("/");
}
l_files = CONS(from_qstring(path), l_files);
}
l_files = cl_nreverse(l_files);
ecl_return1(ecl_process_env(), l_files);
}
cl_object ensure_permissions2(cl_object l_permissions) { cl_object ensure_permissions2(cl_object l_permissions) {
/// args: (&rest permissions) /// args: (&rest permissions)
/// Android only; requests the passed permissions. Returns the list of /// Android only; requests the passed permissions. Returns the list of

View file

@ -57,6 +57,7 @@ cl_object pixel_ratio ();
cl_object qapropos2 (cl_object, cl_object, cl_object); cl_object qapropos2 (cl_object, cl_object, cl_object);
cl_object qchildren (cl_object); cl_object qchildren (cl_object);
cl_object qcopy_file (cl_object, cl_object); cl_object qcopy_file (cl_object, cl_object);
cl_object qdirectory (cl_object);
cl_object qescape (cl_object); cl_object qescape (cl_object);
cl_object qexec2 (cl_object); cl_object qexec2 (cl_object);
cl_object qexit (); cl_object qexit ();

View file

@ -7,7 +7,7 @@
#include <QStringList> #include <QStringList>
#include <QDebug> #include <QDebug>
const char LQML::version[] = "22.2.1"; // Feb 2022 const char LQML::version[] = "22.2.2"; // Feb 2022
extern "C" void ini_LQML(cl_object); extern "C" void ini_LQML(cl_object);

View file

@ -77,7 +77,14 @@ int main(int argc, char* argv[]) {
arguments.removeAll("-norc"); arguments.removeAll("-norc");
} }
else { else {
LQML::eval("(x:when-it (probe-file \"~/.eclrc\") (load x:it))"); #if (defined Q_OS_ANDROID) || (defined Q_OS_IOS)
// mobile: don't hang on startup
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (ignore-errors (load x:it)))");
#else
LQML::eval("(x:when-it (probe-file \"~/.eclrc\")"
" (load x:it))");
#endif
} }
#ifdef INI_LISP #ifdef INI_LISP
@ -99,6 +106,10 @@ int main(int argc, char* argv[]) {
} }
} }
#ifdef SWANK
slime = true;
#endif
if (slime) { if (slime) {
// fallback restart for conditions while processing the Qt event loop // fallback restart for conditions while processing the Qt event loop
LQML::eval("(loop (with-simple-restart (restart-qt-events \"Restart Qt event processing.\")" LQML::eval("(loop (with-simple-restart (restart-qt-events \"Restart Qt event processing.\")"

View file

@ -260,7 +260,6 @@ cl_object from_qstring(const QString& s) {
cl_object from_qstringlist(const QStringList& l) { cl_object from_qstringlist(const QStringList& l) {
cl_object l_list = ECL_NIL; cl_object l_list = ECL_NIL;
for (QString s : qAsConst(l)) { for (QString s : qAsConst(l)) {
l_list = CONS(from_qstring(s), l_list); l_list = CONS(from_qstring(s), l_list);
} }

View file

@ -13,6 +13,7 @@
#:qapropos* #:qapropos*
#:qchildren #:qchildren
#:qcopy-file #:qcopy-file
#:qdirectory
#:qfind-child #:qfind-child
#:qml-call #:qml-call
#:qml-get #:qml-get

View file

@ -160,8 +160,8 @@
;;; JS calls ;;; JS calls
(defmacro qjs (method-name item/name &rest arguments) (defmacro qjs (function item/name &rest arguments)
"args: (method-name item/name &rest arguments) "args: (function item/name &rest arguments)
Fast and convenient way to call JS functions defined in QML. You may pass Fast and convenient way to call JS functions defined in QML. You may pass
up to 10 arguments of the following types: up to 10 arguments of the following types:
T, NIL, INTEGER, FLOAT, STRING, VECTOR of octets, and (nested) lists of T, NIL, INTEGER, FLOAT, STRING, VECTOR of octets, and (nested) lists of
@ -172,9 +172,9 @@
(qjs |drawLine| *canvas* x1 y1 x2 y2)) (qjs |drawLine| *canvas* x1 y1 x2 y2))
(qjs |addPlanet| *planets* (list :name \"Jupiter\" :src \"img/jupiter.png\"))" (qjs |addPlanet| *planets* (list :name \"Jupiter\" :src \"img/jupiter.png\"))"
`(qrun* (qfun (quick-item ,item/name) `(qrun* (qfun (quick-item ,item/name)
,(if (symbolp method-name) ,(if (symbolp function)
(symbol-name method-name) (symbol-name function)
method-name) function)
,@arguments))) ,@arguments)))
;;; apropos ;;; apropos
@ -184,14 +184,14 @@
x x
(quick-item x))) (quick-item x)))
(defun qapropos (name &optional qt-object/name offset) (defun qapropos (string &optional qt-object/name offset)
"args: (name &optional qt-object/name) "args: (string &optional qt-object/name)
Searches properties, methods, signals, slots for NAME in QObject Searches properties, methods, signals, slots for STRING in QObject (e.g.
(e.g. QQuickItem) passed as second argument. QQuickItems can also be passed QQuickItem) passed as second argument. A QQuickItem can also be passed by
by their 'objectName'. its 'objectName'.
(qapropos nil *canvas*) (qapropos nil *canvas*)
(qapropos \"color\")" (qapropos \"color\")"
(dolist (sub1 (%qapropos (%string-or-nil name) (%to-qt-object qt-object/name) offset)) (dolist (sub1 (%qapropos (%string-or-nil string) (%to-qt-object qt-object/name) offset))
(format t "~%~%~A~%" (first sub1)) (format t "~%~%~A~%" (first sub1))
(dolist (sub2 (rest sub1)) (dolist (sub2 (rest sub1))
(format t "~% ~A~%~%" (first sub2)) (format t "~% ~A~%~%" (first sub2))