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