diff --git a/doc/help.htm b/doc/help.htm
index cfb2efe..5114db6 100644
--- a/doc/help.htm
+++ b/doc/help.htm
@@ -188,6 +188,15 @@
(qlog "x ~A y ~A" x y)
+qnull (qt-object)
+
+ Only useful if used with UNLESS, in order to check for a valid pointer.
+ Returns T if the argument is not of type QT-OBJECT.
+
+ (unless (qnull ui:*item*)
+ ...)
+
+
qobject-name (qt-object)
Returns the QObject::objectName() of passed QT-OBJECT.
diff --git a/examples/clog-demo/clog-assets/htm/js/boot.js b/examples/clog-demo/clog-assets/htm/js/boot.js
index df5c0a8..8a10340 100644
--- a/examples/clog-demo/clog-assets/htm/js/boot.js
+++ b/examples/clog-demo/clog-assets/htm/js/boot.js
@@ -14,7 +14,7 @@ const ws = {
if (ios) {
_ws.send(message);
} else {
- // hack, seel QML 'onTitleChanged()'
+ // hack, see QML 'onTitleChanged()'
document.title = message;
document.title = "-"; // non empty
}
diff --git a/src/cpp/ecl_ext.cpp b/src/cpp/ecl_ext.cpp
index 5d9a904..1f39b11 100644
--- a/src/cpp/ecl_ext.cpp
+++ b/src/cpp/ecl_ext.cpp
@@ -43,6 +43,7 @@ void iniCLFunctions() {
DEFUN ("%qinvoke-method", qinvoke_method2, 3)
DEFUN ("%qload-c++", qload_cpp, 2)
DEFUN ("%qlog", qlog2, 1)
+ DEFUN ("qnull", qnull, 1)
DEFUN ("%qml-get", qml_get2, 2)
DEFUN ("%qml-set", qml_set2, 3)
DEFUN ("qobject-name", qobject_name, 1)
@@ -130,6 +131,30 @@ cl_object qset2(cl_object l_obj, cl_object l_args) {
/// (qset *quick-view* |x| 100 |y| 100)
QObject* qobject = toQObjectPointer(l_obj);
if (qobject != nullptr) {
+ QQuickItem* item = qobject_cast(qobject);
+ if (item != nullptr) {
+ QByteArray name(toCString(cl_first(l_args)));
+ cl_object l_val = cl_second(l_args);
+ // special case for QQuickItem to:
+ // * not trigger animations while positioning
+ // * provide 'setParent()' for dynamic items, needed for 'objectName'
+ if (QByteArray("x y parent").indexOf(name) != -1) {
+ if (name == "x") {
+ item->setX(toReal(l_val));
+ } else if (name == "y") {
+ item->setY(toReal(l_val));
+ } else {
+ QObject* o = toQObjectPointer(l_val);
+ QQuickItem* parent = qobject_cast(o);
+ if (parent != nullptr) {
+ // need to set both here
+ item->setParent(parent);
+ item->setParentItem(parent);
+ }
+ }
+ ecl_return2(ecl_process_env(), l_args, ECL_T);
+ }
+ }
const QMetaObject* mo = qobject->metaObject();
for (cl_object l_do = l_args; l_do != ECL_NIL; l_do = cl_cddr(l_do)) {
cl_object l_name = cl_first(l_do);
@@ -406,6 +431,16 @@ cl_object qlog2(cl_object l_msg) {
ecl_return1(ecl_process_env(), ECL_NIL);
}
+cl_object qnull(cl_object l_arg) {
+ /// args: (qt-object)
+ /// Only useful if used with UNLESS, in order to check for a valid pointer.
+ /// Returns T if the argument is not of type QT-OBJECT.
+ /// (unless (qnull ui:*item*)
+ /// ...)
+ QObject* qobject = toQObjectPointer(l_arg);
+ ecl_return1(ecl_process_env(), (qobject == nullptr) ? ECL_T : ECL_NIL);
+}
+
cl_object qinvoke_method2(cl_object l_obj, cl_object l_name, cl_object l_args) {
// for internal use: this is used to call user defined JS functions, and to
// call user defined Qt/C++ plugin functions.
diff --git a/src/cpp/ecl_ext.h b/src/cpp/ecl_ext.h
index c43d236..8a91152 100644
--- a/src/cpp/ecl_ext.h
+++ b/src/cpp/ecl_ext.h
@@ -66,6 +66,7 @@ cl_object qfrom_utf8 (cl_object);
cl_object qinvoke_method2 (cl_object, cl_object, cl_object);
cl_object qload_cpp (cl_object, cl_object);
cl_object qlog2 (cl_object);
+cl_object qnull (cl_object);
cl_object qml_get2 (cl_object, cl_object);
cl_object qml_set2 (cl_object, cl_object, cl_object);
cl_object qobject_name (cl_object);
diff --git a/src/cpp/ecl_fun_plugin.h b/src/cpp/ecl_fun_plugin.h
index 7e5c2dc..f0983c4 100644
--- a/src/cpp/ecl_fun_plugin.h
+++ b/src/cpp/ecl_fun_plugin.h
@@ -49,30 +49,30 @@ QT_BEGIN_NAMESPACE
#define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10))
-#define TO_CL_FLOAT_2(cap_name, name, x1, x2) \
+#define TO_CL_2(cap_name, name, make, x1, x2) \
cl_object from_##name(const cap_name& q) { \
- cl_object l_ret = LIST2(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2())); \
+ cl_object l_ret = LIST2(make(q.x1()), make(q.x2())); \
return l_ret; \
}
-#define TO_CL_FLOAT_4(cap_name, name, x1, x2, x3, x4) \
+#define TO_CL_4(cap_name, name, make, x1, x2, x3, x4) \
cl_object from_##name(const cap_name& q) { \
- cl_object l_ret = LIST4(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2()), ecl_make_doublefloat(q.x3()), ecl_make_doublefloat(q.x4())); \
+ cl_object l_ret = LIST4(make(q.x1()), make(q.x2()), make(q.x3()), make(q.x4())); \
return l_ret; \
}
-#define TO_QT_FLOAT_2(name) \
+#define TO_QT_2(name, toX) \
name to##name(cl_object x) { \
if (LISTP(x)) { \
- return name(toReal(cl_first(x)), toReal(cl_second(x))); \
+ return name(toX(cl_first(x)), toX(cl_second(x))); \
} \
return name(); \
}
-#define TO_QT_FLOAT_4(name) \
+#define TO_QT_4(name, toX) \
name to##name(cl_object x) { \
if (LISTP(x)) { \
- return name(toReal(cl_first(x)), toReal(cl_second(x)), toReal(cl_third(x)), toReal(cl_fourth(x))); \
+ return name(toX(cl_first(x)), toX(cl_second(x)), toX(cl_third(x)), toX(cl_fourth(x))); \
} \
return name(); \
}
@@ -201,9 +201,13 @@ QString toQString(cl_object l_str) {
return s;
}
-TO_QT_FLOAT_2 (QPointF)
-TO_QT_FLOAT_2 (QSizeF)
-TO_QT_FLOAT_4 (QRectF)
+TO_QT_2 (QPoint, toInt)
+TO_QT_2 (QSize, toInt)
+TO_QT_4 (QRect, toInt)
+
+TO_QT_2 (QPointF, toFloat)
+TO_QT_2 (QSizeF, toFloat)
+TO_QT_4 (QRectF, toFloat)
QVariant toQVariant(cl_object, int = -1);
QVariant toQVariantMap(cl_object);
@@ -213,8 +217,11 @@ QVariant toQVariant(cl_object l_arg, int type) {
QVariant var;
switch (type) {
case QMetaType::QByteArray: var = toQByteArray(l_arg); break;
+ case QMetaType::QPoint: var = toQPoint(l_arg); break;
case QMetaType::QPointF: var = toQPointF(l_arg); break;
+ case QMetaType::QRect: var = toQRect(l_arg); break;
case QMetaType::QRectF: var = toQRectF(l_arg); break;
+ case QMetaType::QSize: var = toQSize(l_arg); break;
case QMetaType::QSizeF: var = toQSizeF(l_arg); break;
case QMetaType::QUrl: var = QUrl(toQString(l_arg)); break;
default:
@@ -295,9 +302,13 @@ cl_object from_qstring(const QString& s) {
return l_s;
}
-TO_CL_FLOAT_2 (QPointF, qpointf, x, y)
-TO_CL_FLOAT_2 (QSizeF, qsizef, width, height)
-TO_CL_FLOAT_4 (QRectF, qrectf, x, y, width, height)
+TO_CL_2 (QPoint, qpoint, ecl_make_fixnum, x, y)
+TO_CL_2 (QSize, qsize, ecl_make_fixnum, width, height)
+TO_CL_4 (QRect, qrect, ecl_make_fixnum, x, y, width, height)
+
+TO_CL_2 (QPointF, qpointf, ecl_make_doublefloat, x, y)
+TO_CL_2 (QSizeF, qsizef, ecl_make_doublefloat, width, height)
+TO_CL_4 (QRectF, qrectf, ecl_make_doublefloat, x, y, width, height)
cl_object from_qvariant(const QVariant& var) {
cl_object l_obj = ECL_NIL;
@@ -312,8 +323,11 @@ cl_object from_qvariant(const QVariant& var) {
case QMetaType::Int: l_obj = ecl_make_integer(var.toInt()); break;
case QMetaType::UInt: l_obj = ecl_make_unsigned_integer(var.toUInt()); break;
case QMetaType::ULongLong: l_obj = ecl_make_unsigned_integer(var.toULongLong()); break;
+ case QMetaType::QPoint: l_obj = from_qpoint(var.toPoint()); break;
case QMetaType::QPointF: l_obj = from_qpointf(var.toPointF()); break;
+ case QMetaType::QRect: l_obj = from_qrect(var.toRect()); break;
case QMetaType::QRectF: l_obj = from_qrectf(var.toRectF()); break;
+ case QMetaType::QSize: l_obj = from_qsize(var.toSize()); break;
case QMetaType::QSizeF: l_obj = from_qsizef(var.toSizeF()); break;
case QMetaType::QString:
case QMetaType::QUrl: l_obj = from_qstring(var.toString()); break;
diff --git a/src/cpp/marshal.cpp b/src/cpp/marshal.cpp
index 1b1ec3a..0ba55aa 100644
--- a/src/cpp/marshal.cpp
+++ b/src/cpp/marshal.cpp
@@ -141,18 +141,30 @@ QStringList toQStringList(cl_object l_list) {
return l;
}
-TO_QT_FLOAT_2 (QPointF)
-TO_QT_FLOAT_2 (QSizeF)
-TO_QT_FLOAT_4 (QRectF)
+TO_QT_2 (QPoint, toInt)
+TO_QT_2 (QSize, toInt)
+TO_QT_4 (QRect, toInt)
+
+TO_QT_2 (QPointF, toFloat)
+TO_QT_2 (QSizeF, toFloat)
+TO_QT_4 (QRectF, toFloat)
QVariant toQVariant(cl_object l_arg, int type) {
QVariant var;
switch (type) {
case QMetaType::QByteArray: var = toQByteArray(l_arg); break;
+ case QMetaType::QPoint: var = toQPoint(l_arg); break;
case QMetaType::QPointF: var = toQPointF(l_arg); break;
+ case QMetaType::QRect: var = toQRect(l_arg); break;
case QMetaType::QRectF: var = toQRectF(l_arg); break;
+ case QMetaType::QSize: var = toQSize(l_arg); break;
case QMetaType::QSizeF: var = toQSizeF(l_arg); break;
case QMetaType::QUrl: var = QUrl(toQString(l_arg)); break;
+ case QMetaType::QObjectStar: {
+ QObject* o = toQObjectPointer(l_arg);
+ var = QVariant::fromValue(o); // QObject*
+ }
+ break;
default:
if (cl_integerp(l_arg) == ECL_T) { // int
var = QVariant(toInt(l_arg));
@@ -170,8 +182,13 @@ QVariant toQVariant(cl_object l_arg, int type) {
: toQVariantList(l_arg);
} else if (cl_vectorp(l_arg) == ECL_T) { // vector (of octets)
var = QVariant(toQByteArray(l_arg));
- } else { // default: undefined
- var = QVariant();
+ } else {
+ QObject* o = toQObjectPointer(l_arg);
+ if (o != nullptr) {
+ var = QVariant::fromValue(o); // e.g. QQuickItem*
+ } else {
+ var = QVariant(); // default: undefined
+ }
}
}
return var;
@@ -270,9 +287,13 @@ cl_object from_qstringlist(const QStringList& l) {
return l_list;
}
-TO_CL_FLOAT_2 (QPointF, qpointf, x, y)
-TO_CL_FLOAT_2 (QSizeF, qsizef, width, height)
-TO_CL_FLOAT_4 (QRectF, qrectf, x, y, width, height)
+TO_CL_2 (QPoint, qpoint, ecl_make_fixnum, x, y)
+TO_CL_2 (QSize, qsize, ecl_make_fixnum, width, height)
+TO_CL_4 (QRect, qrect, ecl_make_fixnum, x, y, width, height)
+
+TO_CL_2 (QPointF, qpointf, ecl_make_doublefloat, x, y)
+TO_CL_2 (QSizeF, qsizef, ecl_make_doublefloat, width, height)
+TO_CL_4 (QRectF, qrectf, ecl_make_doublefloat, x, y, width, height)
cl_object from_qvariant(const QVariant& var) {
cl_object l_obj = ECL_NIL;
@@ -281,26 +302,37 @@ cl_object from_qvariant(const QVariant& var) {
#else
const int type = var.typeId();
#endif
- switch (type) {
- case QMetaType::Bool: l_obj = var.toBool() ? ECL_T : ECL_NIL; break;
- case QMetaType::Double: l_obj = ecl_make_doublefloat(var.toDouble()); break;
- case QMetaType::Int: l_obj = ecl_make_integer(var.toInt()); break;
- case QMetaType::UInt: l_obj = ecl_make_unsigned_integer(var.toUInt()); break;
- case QMetaType::ULongLong: l_obj = ecl_make_unsigned_integer(var.toULongLong()); break;
- case QMetaType::QByteArray: l_obj = from_qbytearray(var.toByteArray()); break;
- case QMetaType::QPointF: l_obj = from_qpointf(var.toPointF()); break;
- case QMetaType::QRectF: l_obj = from_qrectf(var.toRectF()); break;
- case QMetaType::QSizeF: l_obj = from_qsizef(var.toSizeF()); break;
- case QMetaType::QString:
- case QMetaType::QUrl: l_obj = from_qstring(var.toString()); break;
- // special case (can be nested)
- case QMetaType::QVariantList:
- QVariantList list(var.value());
- for (QVariant v : qAsConst(list)) {
- l_obj = CONS(from_qvariant(v), l_obj);
- }
- l_obj = cl_nreverse(l_obj);
- break;
+ if ((type == QMetaType::QObjectStar) || // QObject*
+ (type >= QMetaType::User)) { // e.g. QQuickItem*
+ QObject* o = var.value();
+ if (o != nullptr) {
+ l_obj = from_qobject_pointer(o);
+ }
+ } else {
+ switch (type) {
+ case QMetaType::Bool: l_obj = var.toBool() ? ECL_T : ECL_NIL; break;
+ case QMetaType::Double: l_obj = ecl_make_doublefloat(var.toDouble()); break;
+ case QMetaType::Int: l_obj = ecl_make_integer(var.toInt()); break;
+ case QMetaType::UInt: l_obj = ecl_make_unsigned_integer(var.toUInt()); break;
+ case QMetaType::ULongLong: l_obj = ecl_make_unsigned_integer(var.toULongLong()); break;
+ case QMetaType::QByteArray: l_obj = from_qbytearray(var.toByteArray()); break;
+ case QMetaType::QPoint: l_obj = from_qpoint(var.toPoint()); break;
+ case QMetaType::QPointF: l_obj = from_qpointf(var.toPointF()); break;
+ case QMetaType::QRect: l_obj = from_qrect(var.toRect()); break;
+ case QMetaType::QRectF: l_obj = from_qrectf(var.toRectF()); break;
+ case QMetaType::QSize: l_obj = from_qsize(var.toSize()); break;
+ case QMetaType::QSizeF: l_obj = from_qsizef(var.toSizeF()); break;
+ case QMetaType::QString:
+ case QMetaType::QUrl: l_obj = from_qstring(var.toString()); break;
+ // special case (can be nested)
+ case QMetaType::QVariantList:
+ QVariantList list(var.value());
+ for (QVariant v : qAsConst(list)) {
+ l_obj = CONS(from_qvariant(v), l_obj);
+ }
+ l_obj = cl_nreverse(l_obj);
+ break;
+ }
}
return l_obj;
}
diff --git a/src/cpp/marshal.h b/src/cpp/marshal.h
index 7da9330..0f0c0c1 100644
--- a/src/cpp/marshal.h
+++ b/src/cpp/marshal.h
@@ -43,30 +43,30 @@ QT_BEGIN_NAMESPACE
#define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10))
-#define TO_CL_FLOAT_2(cap_name, name, x1, x2) \
+#define TO_CL_2(cap_name, name, make, x1, x2) \
static cl_object from_##name(const cap_name& q) { \
- cl_object l_ret = LIST2(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2())); \
+ cl_object l_ret = LIST2(make(q.x1()), make(q.x2())); \
return l_ret; \
}
-#define TO_CL_FLOAT_4(cap_name, name, x1, x2, x3, x4) \
+#define TO_CL_4(cap_name, name, make, x1, x2, x3, x4) \
static cl_object from_##name(const cap_name& q) { \
- cl_object l_ret = LIST4(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2()), ecl_make_doublefloat(q.x3()), ecl_make_doublefloat(q.x4())); \
+ cl_object l_ret = LIST4(make(q.x1()), make(q.x2()), make(q.x3()), make(q.x4())); \
return l_ret; \
}
-#define TO_QT_FLOAT_2(name) \
+#define TO_QT_2(name, toX) \
static name to##name(cl_object x) { \
if (LISTP(x)) { \
- return name(toReal(cl_first(x)), toReal(cl_second(x))); \
+ return name(toX(cl_first(x)), toX(cl_second(x))); \
} \
return name(); \
}
-#define TO_QT_FLOAT_4(name) \
+#define TO_QT_4(name, toX) \
static name to##name(cl_object x) { \
if (LISTP(x)) { \
- return name(toReal(cl_first(x)), toReal(cl_second(x)), toReal(cl_third(x)), toReal(cl_fourth(x))); \
+ return name(toX(cl_first(x)), toX(cl_second(x)), toX(cl_third(x)), toX(cl_fourth(x))); \
} \
return name(); \
}
diff --git a/src/lisp/ecl-ext.lisp b/src/lisp/ecl-ext.lisp
index 632155f..37b5b39 100644
--- a/src/lisp/ecl-ext.lisp
+++ b/src/lisp/ecl-ext.lisp
@@ -18,6 +18,7 @@
(defun %qinvoke-method (a b c))
(defun %qload-c++ (a b))
(defun %qlog (a))
+(defun qnull (a))
(defun %qml-get (a b))
(defun %qml-set (a b c))
(defun qobject-name (a))
diff --git a/src/lisp/package.lisp b/src/lisp/package.lisp
index 7847eb7..2f18785 100644
--- a/src/lisp/package.lisp
+++ b/src/lisp/package.lisp
@@ -35,6 +35,7 @@
#:qlater
#:qload-c++
#:qlog
+ #:qnull
#:qprocess-events
#:qq
#:qquit