mirror of
https://gitlab.com/eql/EQL5.git
synced 2025-12-08 19:40:35 -08:00
"quick": rename "Lisp.fun()" to "Lisp.call()"; allow optionally passing JS "this" (a QQuickItem) as first argument;
This commit is contained in:
parent
9e09c38766
commit
2aee9968c6
14 changed files with 117 additions and 44 deletions
|
|
@ -46,7 +46,7 @@ Please see also the documentation in "qml/example.qml".
|
|||
TIP
|
||||
===
|
||||
|
||||
In order to have uniform access to QML objects from both JS and Lisp
|
||||
In order to have uniform access to QQuickItems from both QML and Lisp
|
||||
functions, it is convenient to set both 'id:' and 'objectName:' to the
|
||||
same name.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,21 @@
|
|||
|
||||
(require :qml-lisp "qml-lisp")
|
||||
|
||||
(use-package :qml)
|
||||
|
||||
;; for example (5) in "qml/example.qml"
|
||||
|
||||
(defun show-properties-dialog ()
|
||||
(unless (find-package :properties)
|
||||
(load (in-home "gui/properties")))
|
||||
(funcall (find-symbol "SHOW" :properties) qml:*caller*))
|
||||
|
||||
(defun run ()
|
||||
;; *quick-view* can be either a QQuickView or a QQuickWidget
|
||||
(setf qml:*quick-view* (qnew "QQuickView(QUrl)"
|
||||
(|fromLocalFile.QUrl| "qml/example.qml")))
|
||||
(|setResizeMode| qml:*quick-view* |QQuickView.SizeRootObjectToView|)
|
||||
(|resize| qml:*quick-view* '(300 200))
|
||||
(|resize| qml:*quick-view* '(350 350))
|
||||
(|show| qml:*quick-view*))
|
||||
|
||||
(run)
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ QObject* ini() {
|
|||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider); }
|
||||
return lisp; }
|
||||
|
||||
QVariant Lisp::apply(const QString& function, const QVariantList& arguments) {
|
||||
QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantList& arguments) {
|
||||
QVariant ret =
|
||||
eql_fun("qml:qml-apply", QVariant::String,
|
||||
Q_ARG(QObject*, caller),
|
||||
Q_ARG(QString, function),
|
||||
Q_ARG(QVariantList, arguments));
|
||||
return ret; }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class Lisp : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QVariant apply(const QString&, const QVariantList& = QVariantList());
|
||||
Q_INVOKABLE QVariant apply(QObject*, const QString&, const QVariantList& = QVariantList());
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@
|
|||
(:nicknames :qml)
|
||||
(:export
|
||||
#:*quick-view*
|
||||
#:*caller*
|
||||
#:children
|
||||
#:find-quick-item
|
||||
#:js
|
||||
#:qml-get
|
||||
#:qml-set
|
||||
#:properties
|
||||
#:root-item))
|
||||
|
||||
(provide :qml-lisp)
|
||||
|
|
@ -22,11 +24,12 @@
|
|||
(in-package :qml-lisp)
|
||||
|
||||
(defvar *qml-lisp* (qload-c++ "lib/qml_lisp"))
|
||||
(defvar *caller* nil)
|
||||
(defvar *quick-view* nil)
|
||||
|
||||
(defun string-to-symbol (name)
|
||||
(let* ((upper (string-upcase name))
|
||||
(p (position #\: name)))
|
||||
(let ((upper (string-upcase name))
|
||||
(p (position #\: name)))
|
||||
(if p
|
||||
(intern (subseq upper (1+ (position #\: name :from-end t)))
|
||||
(subseq upper 0 p))
|
||||
|
|
@ -63,10 +66,11 @@
|
|||
(princ "#<>") ; mark for passing to JS "eval()"
|
||||
(print-js-readably object)))
|
||||
|
||||
(defun qml-apply (function arguments)
|
||||
"Every 'Lisp.fun()' or 'Lisp.apply()' function call in QML will call this function."
|
||||
(let ((object (apply (string-to-symbol function)
|
||||
arguments)))
|
||||
(defun qml-apply (caller function arguments)
|
||||
"Every 'Lisp.call()' or 'Lisp.apply()' function call in QML will call this function. The variable *CALLER* will be bound to the calling QQuickItem, if passed with 'this' as first argument to 'Lisp.call' / 'Lisp.apply()'."
|
||||
(let* ((*caller* (if (qnull caller) nil (qt-object-? caller)))
|
||||
(object (apply (string-to-symbol function)
|
||||
arguments)))
|
||||
(if (stringp object)
|
||||
object
|
||||
(print-to-js-string object))))
|
||||
|
|
@ -74,13 +78,14 @@
|
|||
;;; utils
|
||||
|
||||
(defun root-item ()
|
||||
(|rootObject| *quick-view*))
|
||||
(when *quick-view*
|
||||
(|rootObject| *quick-view*)))
|
||||
|
||||
(defun find-quick-item (object-name)
|
||||
"Finds the first QQuickItem matching OBJECT-NAME."
|
||||
(if (string= (|objectName| (root-item)) object-name)
|
||||
(root-item)
|
||||
(qfind-child (root-item) object-name)))
|
||||
(qt-object-? (qfind-child (root-item) object-name))))
|
||||
|
||||
(defun quick-item (item/name)
|
||||
(if (stringp item/name)
|
||||
|
|
@ -116,7 +121,7 @@
|
|||
;;; JS
|
||||
|
||||
(defun js (item/name js-format-string &rest arguments)
|
||||
"Evaluates a JS string, with 'this' bound to either ITEM, or first object matching NAME."
|
||||
"Evaluates a JS string, with 'this' bound to either ITEM, or first object matching NAME. Arguments are passed through FORMAT."
|
||||
(qlet ((qml-exp "QQmlExpression(QQmlContext*,QObject*,QString)"
|
||||
(|rootContext| *quick-view*)
|
||||
(quick-item item/name)
|
||||
|
|
|
|||
|
|
@ -11,32 +11,48 @@ Item {
|
|||
|
||||
// Please note:
|
||||
//
|
||||
// * to call lisp functions, use either Lisp.fun() or Lisp.apply();
|
||||
// * to call lisp functions, use either Lisp.call() or Lisp.apply();
|
||||
// use JS arrays for lists (can be nested);
|
||||
//
|
||||
// * return values can be nested Lisp lists or vectors, which will be converted to
|
||||
// nested JS arrays: they will be prepared in Lisp and passed to JS eval;
|
||||
//
|
||||
// * optionally pass 'this' (or any other item) as first argument to either
|
||||
// Lisp.call() or Lisp.apply(); it can then be accessed in Lisp via qml:*caller*;
|
||||
|
||||
// (1) call CL function
|
||||
console.log(Lisp.fun("format", false, "~R", 123))
|
||||
console.log(Lisp.call("format", false, "~R", 123))
|
||||
|
||||
// (2) call EQL function
|
||||
Lisp.fun("qmsg", "hello from QML")
|
||||
Lisp.call("qmsg", "hello from QML")
|
||||
|
||||
// (3) pass list argument
|
||||
console.log(Lisp.fun("x:join", ["11", "55"], ":"))
|
||||
console.log(Lisp.call("x:join", ["11", "55"], ":"))
|
||||
|
||||
// (4) nested list arguments
|
||||
// N.B: don't get fooled by the printed representation of the return value:
|
||||
// it's a nested JS array internally
|
||||
console.log(Lisp.fun("list", [[1, 2, 3], ["a", "b", "c"], 4, 5], 6, [[7, 8], 9]))
|
||||
console.log(Lisp.call("list", [[1, 2, 3], ["a", "b", "c"], 4, 5], 6, [[7, 8], 9]))
|
||||
|
||||
// (5) pass 'this' as first argument (can be accessed in Lisp via qml:*caller*)
|
||||
Lisp.call(this, "eql-user:show-properties-dialog")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
objectName: "label"
|
||||
|
||||
anchors.centerIn: parent
|
||||
color: "blue"
|
||||
text: "Lisp enabled QML"
|
||||
font.bold: true
|
||||
font.pixelSize: 32
|
||||
|
||||
NumberAnimation on rotation {
|
||||
from: 0; to: 360;
|
||||
easing.type: Easing.InOutElastic;
|
||||
duration: 3000;
|
||||
loops: Animation.Infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue