mirror of
https://gitlab.com/eql/EQL5.git
synced 2026-01-06 01:02:06 -08:00
"quick": add example "painted-item"; small revisions;
This commit is contained in:
parent
fcbf75464c
commit
0ff3dee53c
20 changed files with 350 additions and 15 deletions
|
|
@ -1,9 +1,10 @@
|
|||
If you are new to QML/EQL5, you probably want to go through the examples
|
||||
in this order:
|
||||
(and READMEs) in this order:
|
||||
|
||||
1) qml-lisp
|
||||
2) Tic-Tac-Toe
|
||||
3) item-model
|
||||
* qml-lisp
|
||||
* Tic-Tac-Toe
|
||||
* item-model
|
||||
* painted-item
|
||||
|
||||
The trivial "quickwidget" example just demonstrates that you can integrate
|
||||
a QML widget in any Qt application, combining both traditional Qt and QML.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ static QObject* lisp_provider(QQmlEngine*, QJSEngine*) { return lisp; }
|
|||
QObject* ini() {
|
||||
if(!lisp) {
|
||||
lisp = new Lisp;
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider); }
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider);
|
||||
qmlRegisterType<PaintedItem>("EQL5", 1, 0, "PaintedItem"); }
|
||||
return lisp; }
|
||||
|
||||
QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantList& arguments) {
|
||||
|
|
@ -19,4 +20,9 @@ QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantLis
|
|||
Q_ARG(QString, function),
|
||||
Q_ARG(QVariantList, arguments)); }
|
||||
|
||||
void PaintedItem::paint(QPainter* painter) {
|
||||
eql_fun("qml:paint",
|
||||
Q_ARG(QQuickPaintedItem*, this),
|
||||
Q_ARG(QPainter*, painter)); }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define LIB_H
|
||||
|
||||
#include <QtQml>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
|
|
@ -20,6 +21,17 @@ public:
|
|||
Q_INVOKABLE QVariant apply(QObject*, const QString&, const QVariantList& = QVariantList());
|
||||
};
|
||||
|
||||
class PaintedItem : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PaintedItem(QQuickItem* parent = 0) : QQuickPaintedItem(parent) {}
|
||||
|
||||
void paint(QPainter*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
QT += qml
|
||||
QT += qml quick
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin release
|
||||
INCLUDEPATH += ../../../../../src
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@
|
|||
(or data *empty-variant*))))
|
||||
(qoverride *animal-model* "roleNames()"
|
||||
(lambda ()
|
||||
(list (cons +kind-role+ "kind")
|
||||
(cons +size-role+ "size")))))
|
||||
(list (cons +kind-role+ "kind") ; see 'kind' in QML
|
||||
(cons +size-role+ "size"))))) ; see 'size' in QML
|
||||
|
||||
(defun run ()
|
||||
;; data
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
(add-animal "mouse" "small")
|
||||
;; view
|
||||
(setf qml:*quick-view* (qnew "QQuickView"))
|
||||
(|setContextProperty| (|rootContext| qml:*quick-view*) "myModel" *animal-model*)
|
||||
(|setContextProperty| (|rootContext| qml:*quick-view*) "myModel" *animal-model*) ; see 'myModel' in QML
|
||||
(|setSource| qml:*quick-view* (|fromLocalFile.QUrl| "qml/abstract-model.qml"))
|
||||
(|setResizeMode| qml:*quick-view* |QQuickView.SizeRootObjectToView|)
|
||||
(|resize| qml:*quick-view* '(200 250))
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ static QObject* lisp_provider(QQmlEngine*, QJSEngine*) { return lisp; }
|
|||
QObject* ini() {
|
||||
if(!lisp) {
|
||||
lisp = new Lisp;
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider); }
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider);
|
||||
qmlRegisterType<PaintedItem>("EQL5", 1, 0, "PaintedItem"); }
|
||||
return lisp; }
|
||||
|
||||
QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantList& arguments) {
|
||||
|
|
@ -19,4 +20,9 @@ QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantLis
|
|||
Q_ARG(QString, function),
|
||||
Q_ARG(QVariantList, arguments)); }
|
||||
|
||||
void PaintedItem::paint(QPainter* painter) {
|
||||
eql_fun("qml:paint",
|
||||
Q_ARG(QQuickPaintedItem*, this),
|
||||
Q_ARG(QPainter*, painter)); }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define LIB_H
|
||||
|
||||
#include <QtQml>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
|
|
@ -20,6 +21,17 @@ public:
|
|||
Q_INVOKABLE QVariant apply(QObject*, const QString&, const QVariantList& = QVariantList());
|
||||
};
|
||||
|
||||
class PaintedItem : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PaintedItem(QQuickItem* parent = 0) : QQuickPaintedItem(parent) {}
|
||||
|
||||
void paint(QPainter*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
QT += qml
|
||||
QT += qml quick
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin release
|
||||
INCLUDEPATH += ../../../../../src
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
(defun set-my-model ()
|
||||
;; this function needs to be called after every change to *items*
|
||||
(qlet ((data (qvariant-from-value *items* "QStringList")))
|
||||
(|setContextProperty| (|rootContext| qml:*quick-view*) "myModel" data)))
|
||||
(|setContextProperty| (|rootContext| qml:*quick-view*) "myModel" data))) ; see 'myModel' in QML
|
||||
|
||||
(defun change-items (items)
|
||||
(setf *items* items)
|
||||
|
|
|
|||
11
examples/M-modules/quick/painted-item/README.txt
Normal file
11
examples/M-modules/quick/painted-item/README.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
INFO
|
||||
====
|
||||
|
||||
This is an alternative to 'Canvas' in QML, using a QQuickPaintedItem,
|
||||
which means using QPainter from Lisp (instead of JS in QML).
|
||||
|
||||
|
||||
RUN
|
||||
===
|
||||
|
||||
Please run it from this directory.
|
||||
28
examples/M-modules/quick/painted-item/lib/qml_lisp.cpp
Normal file
28
examples/M-modules/quick/painted-item/lib/qml_lisp.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "qml_lisp.h"
|
||||
#include <eql_fun.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static Lisp* lisp = 0;
|
||||
|
||||
static QObject* lisp_provider(QQmlEngine*, QJSEngine*) { return lisp; }
|
||||
|
||||
QObject* ini() {
|
||||
if(!lisp) {
|
||||
lisp = new Lisp;
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider);
|
||||
qmlRegisterType<PaintedItem>("EQL5", 1, 0, "PaintedItem"); }
|
||||
return lisp; }
|
||||
|
||||
QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantList& arguments) {
|
||||
return eql_fun("qml:qml-apply", QVariant::String,
|
||||
Q_ARG(QObject*, caller),
|
||||
Q_ARG(QString, function),
|
||||
Q_ARG(QVariantList, arguments)); }
|
||||
|
||||
void PaintedItem::paint(QPainter* painter) {
|
||||
eql_fun("qml:paint",
|
||||
Q_ARG(QQuickPaintedItem*, this),
|
||||
Q_ARG(QPainter*, painter)); }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
37
examples/M-modules/quick/painted-item/lib/qml_lisp.h
Normal file
37
examples/M-modules/quick/painted-item/lib/qml_lisp.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef LIB_H
|
||||
#define LIB_H
|
||||
|
||||
#include <QtQml>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIB_EXPORT
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
extern "C" { LIB_EXPORT QObject* ini(); }
|
||||
|
||||
class Lisp : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QVariant apply(QObject*, const QString&, const QVariantList& = QVariantList());
|
||||
};
|
||||
|
||||
class PaintedItem : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PaintedItem(QQuickItem* parent = 0) : QQuickPaintedItem(parent) {}
|
||||
|
||||
void paint(QPainter*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
15
examples/M-modules/quick/painted-item/lib/qml_lisp.pro
Normal file
15
examples/M-modules/quick/painted-item/lib/qml_lisp.pro
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
QT += qml quick
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin release
|
||||
INCLUDEPATH += ../../../../../src
|
||||
LIBS += -L../../../../.. -leql5
|
||||
DESTDIR = ./
|
||||
TARGET = qml_lisp
|
||||
OBJECTS_DIR = ./tmp/
|
||||
MOC_DIR = ./tmp/
|
||||
|
||||
include(../../../../../src/windows.pri)
|
||||
|
||||
HEADERS += qml_lisp.h
|
||||
SOURCES += qml_lisp.cpp
|
||||
|
||||
27
examples/M-modules/quick/painted-item/painted-item.lisp
Normal file
27
examples/M-modules/quick/painted-item/painted-item.lisp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
;;; QQuickView loading Lisp enabled QML
|
||||
|
||||
#-qt-wrapper-functions ; see README-OPTIONAL.txt
|
||||
(load (in-home "src/lisp/all-wrappers"))
|
||||
|
||||
(qrequire :quick)
|
||||
|
||||
(require :qml-lisp "qml-lisp")
|
||||
|
||||
(use-package :qml)
|
||||
|
||||
;; paint
|
||||
|
||||
(defun qml:paint (item painter)
|
||||
"This function is called on every 'paint' request of QML type 'PaintedItem'."
|
||||
(|fillRect| painter (|contentsBoundingRect| item)
|
||||
(qml-get item "fillColor"))) ; QML property
|
||||
|
||||
(defun run ()
|
||||
;; *quick-view* can be either a QQuickView or a QQuickWidget
|
||||
(setf qml:*quick-view* (qnew "QQuickView(QUrl)"
|
||||
(|fromLocalFile.QUrl| "qml/painted-item.qml")))
|
||||
(|setResizeMode| qml:*quick-view* |QQuickView.SizeRootObjectToView|)
|
||||
(|resize| qml:*quick-view* '(350 350))
|
||||
(|show| qml:*quick-view*))
|
||||
|
||||
(run)
|
||||
140
examples/M-modules/quick/painted-item/qml-lisp.lisp
Normal file
140
examples/M-modules/quick/painted-item/qml-lisp.lisp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
;;;
|
||||
;;; * enables QML to call Lisp functions
|
||||
;;; * allows to get/set any QML property from Lisp (needs 'objectName' to be set)
|
||||
;;; * allows to evaluate JS code from Lisp (needs 'objectName' to be set)
|
||||
;;;
|
||||
;;; (requires a C++ plugin, see "lib/")
|
||||
|
||||
(defpackage :qml-lisp
|
||||
(:use :common-lisp :eql)
|
||||
(:nicknames :qml)
|
||||
(:export
|
||||
#:*quick-view*
|
||||
#:*caller*
|
||||
#:children
|
||||
#:find-quick-item
|
||||
#:js
|
||||
#:paint
|
||||
#:qml-get
|
||||
#:qml-set
|
||||
#:reload
|
||||
#:root-item))
|
||||
|
||||
(provide :qml-lisp)
|
||||
|
||||
(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)))
|
||||
(if p
|
||||
(find-symbol (subseq upper (1+ (position #\: name :from-end t)))
|
||||
(subseq upper 0 p))
|
||||
(find-symbol upper))))
|
||||
|
||||
;;; function calls from QML
|
||||
|
||||
(defun print-js-readably (object)
|
||||
"Prints (nested) lists, vectors, T, NIL, floats in JS notation, which will be passed to JS 'eval()'."
|
||||
(if (and (not (stringp object))
|
||||
(vectorp object))
|
||||
(print-js-readably (coerce object 'list))
|
||||
(typecase object
|
||||
(cons
|
||||
(write-char #\[)
|
||||
(do ((list object (rest list)))
|
||||
((null list) (write-char #\]))
|
||||
(print-js-readably (first list))
|
||||
(when (rest list)
|
||||
(write-char #\,))))
|
||||
(float
|
||||
;; cut off Lisp specific notations
|
||||
(princ (string-right-trim "dl0" (princ-to-string object))))
|
||||
(t
|
||||
(cond ((eql 't object)
|
||||
(princ "true"))
|
||||
((eql 'nil object)
|
||||
(princ "false"))
|
||||
(t
|
||||
(prin1 object)))))))
|
||||
|
||||
(defun print-to-js-string (object)
|
||||
(with-output-to-string (*standard-output*)
|
||||
(princ "#<>") ; mark for passing to JS "eval()"
|
||||
(print-js-readably object)))
|
||||
|
||||
(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) *caller* (qt-object-? caller)))
|
||||
(object (apply (string-to-symbol function)
|
||||
arguments)))
|
||||
(if (stringp object)
|
||||
object
|
||||
(print-to-js-string object))))
|
||||
|
||||
;;; utils
|
||||
|
||||
(defun root-item ()
|
||||
(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)
|
||||
(qt-object-? (qfind-child (root-item) object-name))))
|
||||
|
||||
(defun quick-item (item/name)
|
||||
(cond ((stringp item/name)
|
||||
(find-quick-item item/name))
|
||||
((qt-object-p item/name)
|
||||
item/name)
|
||||
((not item/name)
|
||||
(root-item))))
|
||||
|
||||
(defun children (item/name)
|
||||
(|childItems| (quick-item item/name)))
|
||||
|
||||
(defun reload ()
|
||||
"Force reloading of QML file after changes made to it."
|
||||
(|clearComponentCache| (|engine| *quick-view*))
|
||||
(|setSource| *quick-view* (|source| *quick-view*)))
|
||||
|
||||
;;; get/set QQmlProperty
|
||||
|
||||
(defun qml-get (item/name property-name)
|
||||
"Gets QQmlProperty of either ITEM or first object matching NAME."
|
||||
(qlet ((property "QQmlProperty(QObject*,QString)"
|
||||
(quick-item item/name)
|
||||
property-name))
|
||||
(if (|isValid| property)
|
||||
(qlet ((variant (|read| property)))
|
||||
(values (qvariant-value variant)
|
||||
t))
|
||||
(eql::%error-msg "QML-GET" (list item/name property-name)))))
|
||||
|
||||
(defun qml-set (item/name property-name value)
|
||||
"Sets QQmlProperty of either ITEM, or first object matching NAME. Returns T on success."
|
||||
(qlet ((property "QQmlProperty(QObject*,QString)"
|
||||
(quick-item item/name)
|
||||
property-name))
|
||||
(if (|isValid| property)
|
||||
(qlet ((variant (qvariant-from-value value (|propertyTypeName| property))))
|
||||
(|write| property variant))
|
||||
(eql::%error-msg "QML-SET" (list item/name property-name value)))))
|
||||
|
||||
;;; 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. Arguments are passed through FORMAT."
|
||||
(qlet ((qml-exp "QQmlExpression(QQmlContext*,QObject*,QString)"
|
||||
(|rootContext| *quick-view*)
|
||||
(quick-item item/name)
|
||||
(apply 'format nil js-format-string arguments))
|
||||
(variant (|evaluate| qml-exp)))
|
||||
(qvariant-value variant)))
|
||||
|
||||
22
examples/M-modules/quick/painted-item/qml/painted-item.qml
Normal file
22
examples/M-modules/quick/painted-item/qml/painted-item.qml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
import EQL5 1.0
|
||||
import "qrc:eql5.js" as Lisp
|
||||
|
||||
Rectangle {
|
||||
color: "gray"
|
||||
|
||||
PaintedItem {
|
||||
// see QML:PAINT in Lisp
|
||||
|
||||
property string fillColor: "red"
|
||||
x: 10; y: 10; width: 100; height: 100
|
||||
}
|
||||
|
||||
PaintedItem {
|
||||
// see QML:PAINT in Lisp
|
||||
|
||||
property string fillColor: "blue"
|
||||
x: 120; y: 10; width: 100; height: 100
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@ static QObject* lisp_provider(QQmlEngine*, QJSEngine*) { return lisp; }
|
|||
QObject* ini() {
|
||||
if(!lisp) {
|
||||
lisp = new Lisp;
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider); }
|
||||
qmlRegisterSingletonType<Lisp>("EQL5", 1, 0, "EQL5", lisp_provider);
|
||||
qmlRegisterType<PaintedItem>("EQL5", 1, 0, "PaintedItem"); }
|
||||
return lisp; }
|
||||
|
||||
QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantList& arguments) {
|
||||
|
|
@ -19,4 +20,9 @@ QVariant Lisp::apply(QObject* caller, const QString& function, const QVariantLis
|
|||
Q_ARG(QString, function),
|
||||
Q_ARG(QVariantList, arguments)); }
|
||||
|
||||
void PaintedItem::paint(QPainter* painter) {
|
||||
eql_fun("qml:paint",
|
||||
Q_ARG(QQuickPaintedItem*, this),
|
||||
Q_ARG(QPainter*, painter)); }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define LIB_H
|
||||
|
||||
#include <QtQml>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
|
|
@ -20,6 +21,17 @@ public:
|
|||
Q_INVOKABLE QVariant apply(QObject*, const QString&, const QVariantList& = QVariantList());
|
||||
};
|
||||
|
||||
class PaintedItem : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PaintedItem(QQuickItem* parent = 0) : QQuickPaintedItem(parent) {}
|
||||
|
||||
void paint(QPainter*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
QT += qml
|
||||
QT += qml quick
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin release
|
||||
INCLUDEPATH += ../../../../../src
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Item {
|
|||
// (5) pass 'this' as first argument (can be accessed in Lisp via qml:*caller*)
|
||||
Lisp.call(this, "eql-user:show-properties-dialog")
|
||||
|
||||
// (6) i18n
|
||||
// (6) i........18........n
|
||||
console.log(Lisp.tr("internationalization"))
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue