EQL5/src/ecl_fun.cpp
2021-03-23 22:15:43 +01:00

3141 lines
157 KiB
C++

// copyright (c) Polos Ruetz
#include "ecl_fun.h"
#include "eql5/eql.h"
#include "eql5/dyn_object.h"
#include "gen/_lobjects.h"
#include "ui_loader.h"
#include "single_shot.h"
#include "module_interface.h"
#include <QLibrary>
#include <QQmlProperty>
#ifdef STATIC_MODULES
#include "gen/help/_ini.h"
#include "gen/network/_ini.h"
#include "gen/multimedia/_ini.h"
#include "gen/quick/_ini.h"
#include "gen/sql/_ini.h"
#include "gen/svg/_ini.h"
#include "gen/webengine/_ini.h"
#include "gen/webkit/_ini.h"
#endif
QT_BEGIN_NAMESPACE
// switches
static bool _check_argument_types_ = true;
static bool _garbage_collection_ = true;
static const char SIG = '2';
static const char SLO = '1';
static bool _ok_ = false;
static StrList _cstring_buffer_;
static const QMetaObject* staticQtMetaObject = QtMetaObject::get();
META_TYPE (T_bool_ok_pointer, bool*)
META_TYPE (T_GLint, GLint)
META_TYPE (T_GLuint, GLuint)
META_TYPE (T_GLenum, GLenum)
META_TYPE (T_short, short)
META_TYPE (T_ushort, ushort)
META_TYPE (T_GLfloat, GLfloat)
META_TYPE (T_qint32, qint32)
META_TYPE (T_qint64, qint64)
META_TYPE (T_quint8, quint8)
META_TYPE (T_quint16, quint16)
META_TYPE (T_quint32, quint32)
META_TYPE (T_quint64, quint64)
META_TYPE (T_FunctorOrLambda, FunctorOrLambda)
META_TYPE (T_QFileInfo, QFileInfo)
META_TYPE (T_QFileInfoList, QFileInfoList)
META_TYPE (T_QGradient, QGradient)
META_TYPE (T_QGradientStop, QGradientStop)
META_TYPE (T_QHash_int_QByteArray, QHashIntQByteArray);
META_TYPE (T_QList_QAbstractAnimation, QList<QAbstractAnimation*>)
META_TYPE (T_QList_QAbstractButton, QList<QAbstractButton*>)
META_TYPE (T_QList_QAbstractState, QList<QAbstractState*>)
META_TYPE (T_QList_QAction, QList<QAction*>)
META_TYPE (T_QList_QByteArray, QList<QByteArray>)
META_TYPE (T_QList_QDockWidget, QList<QDockWidget*>)
META_TYPE (T_QList_QGesture, QList<QGesture*>)
META_TYPE (T_QList_QGraphicsItem, QList<QGraphicsItem*>)
META_TYPE (T_QList_QGraphicsTransform, QList<QGraphicsTransform*>)
META_TYPE (T_QList_QGraphicsView, QList<QGraphicsView*>)
META_TYPE (T_QList_QGraphicsWidget, QList<QGraphicsWidget*>)
META_TYPE (T_QList_QKeySequence, QList<QKeySequence>)
META_TYPE (T_QList_QListWidgetItem, QList<QListWidgetItem*>)
META_TYPE (T_QList_QMdiSubWindow, QList<QMdiSubWindow*>)
META_TYPE (T_QModelIndexList, QModelIndexList)
META_TYPE (T_QList_QObject, QList<QObject*>)
META_TYPE (T_QObjectList, QObjectList)
META_TYPE (T_QList_QPolygonF, QList<QPolygonF>)
META_TYPE (T_QList_QSize, QList<QSize>)
META_TYPE (T_QList_QStandardItem, QList<QStandardItem*>)
META_TYPE (T_QList_QStorageInfo, QList<QStorageInfo>)
META_TYPE (T_QList_QTableWidgetItem, QList<QTableWidgetItem*>)
META_TYPE (T_QList_QTableWidgetSelectionRange, QList<QTableWidgetSelectionRange>)
META_TYPE (T_QList_QTextBlock, QList<QTextBlock>)
META_TYPE (T_QList_QTextEdit_ExtraSelection, QList<QTextEdit::ExtraSelection>)
META_TYPE (T_QList_QTextFrame, QList<QTextFrame*>)
META_TYPE (T_QList_QTouchDevice, QList<const QTouchDevice*>)
META_TYPE (T_QList_QTreeWidgetItem, QList<QTreeWidgetItem*>)
META_TYPE (T_QList_QUndoStack, QList<QUndoStack*>)
META_TYPE (T_QList_QUrl, QList<QUrl>)
META_TYPE (T_QList_QWidget, QList<QWidget*>)
META_TYPE (T_QWidgetList, QWidgetList)
META_TYPE (T_QList_int, QList<int>)
META_TYPE (T_QList_qreal, QList<qreal>)
META_TYPE (T_QMargins, QMargins)
META_TYPE (T_QMarginsF, QMarginsF)
META_TYPE (T_QModelIndex, QModelIndex)
META_TYPE (T_QPageLayout, QPageLayout)
META_TYPE (T_QPageSize, QPageSize)
META_TYPE (T_QPainterPath, QPainterPath)
META_TYPE (T_QPolygonF, QPolygonF)
META_TYPE (T_QRgb, QRgb)
META_TYPE (T_QStorageInfo, QStorageInfo)
META_TYPE (T_QTableWidgetSelectionRange, QTableWidgetSelectionRange)
META_TYPE (T_QTextBlock, QTextBlock)
META_TYPE (T_QTextBlockFormat, QTextBlockFormat)
META_TYPE (T_QTextCharFormat, QTextCharFormat)
META_TYPE (T_QTextFrameFormat, QTextFrameFormat)
META_TYPE (T_QTextListFormat, QTextListFormat)
META_TYPE (T_QTextCursor, QTextCursor)
META_TYPE (T_QTextDocumentFragment, QTextDocumentFragment)
META_TYPE (T_QTextLine, QTextLine)
META_TYPE (T_QTextOption, QTextOption)
META_TYPE (T_QVector_QGradientstop, QVector<QGradientStop>)
META_TYPE (T_QVector_QLine, QVector<QLine>)
META_TYPE (T_QVector_QLineF, QVector<QLineF>)
META_TYPE (T_QVector_QPoint, QVector<QPoint>)
META_TYPE (T_QVector_QPointF, QVector<QPointF>)
META_TYPE (T_QVector_QRect, QVector<QRect>)
META_TYPE (T_QVector_QRectF, QVector<QRectF>)
META_TYPE (T_QVector_QRgb, QVector<QRgb>)
META_TYPE (T_QVector_QTextFormat, QVector<QTextFormat>)
META_TYPE (T_QVector_QTextLength, QVector<QTextLength>)
META_TYPE (T_QVector_float, QVector<float>)
META_TYPE (T_QVector_int, QVector<int>)
META_TYPE (T_QVector_qreal, QVector<qreal>)
META_TYPE (T_WId, WId)
void iniCLFunctions() {
cl_object eql(STRING("EQL"));
if(cl_find_package(eql) == ECL_NIL) {
cl_make_package(1, eql); }
si_select_package(eql);
DEFUN ("%error-msg", error_msg2, 2)
DEFUN ("%make-qimage/dangerous", make_qimage_dangerous, 5)
DEFUN ("no-qexec", no_qexec, 0)
DEFUN ("qadd-event-filter", qadd_event_filter, 3)
DEFUN ("%qapropos", qapropos2, 4)
DEFUN ("qapp", qapp, 0)
DEFUN ("qcall-default", qcall_default, 0)
DEFUN ("qclear-event-filters", qclear_event_filters, 0)
DEFUN ("%qconnect", qconnect2, 4)
DEFUN ("qcopy", qcopy, 1)
DEFUN ("%qdelete", qdelete2, 2)
DEFUN ("%qdisconnect", qdisconnect2, 4)
DEFUN ("%qenums", qenums2, 2)
DEFUN ("qescape", qescape, 1)
DEFUN ("%qexec", qexec2, 1)
DEFUN ("qexit", qexit, 0)
DEFUN ("qfind-child", qfind_child, 2)
DEFUN ("%qfind-children", qfind_children2, 3)
DEFUN ("qfrom-utf8", qfrom_utf8, 1)
DEFUN ("qid", qid, 1)
DEFUN ("%qinvoke-method", qinvoke_method2, 4)
DEFUN ("qjs-call", qjs_call, 3)
DEFUN ("%qload-c++", qload_cpp, 2)
DEFUN ("qload-ui", qload_ui, 1)
DEFUN ("qlocal8bit", qlocal8bit, 1)
DEFUN ("%qlog", qlog2, 1)
DEFUN ("%qml-get", qml_get2, 2)
DEFUN ("%qml-set", qml_set2, 3)
DEFUN ("%qnew-instance", qnew_instance2, 2)
DEFUN ("%qobject-names", qobject_names2, 1)
DEFUN ("qok", qok, 0)
DEFUN ("qoverride", qoverride, 3)
DEFUN ("qprocess-events", qprocess_events, 0)
DEFUN ("qproperty", qproperty, 2)
DEFUN ("%qrequire", qrequire2, 2)
DEFUN ("qremove-event-filter", qremove_event_filter, 1)
DEFUN ("%qrun-on-ui-thread", qrun_on_ui_thread2, 2)
DEFUN ("qsender", qsender, 0)
DEFUN ("%qset-gc", qset_gc, 1)
DEFUN ("qset-property", qset_property, 3)
DEFUN ("%qsingle-shot", qsingle_shot2, 2)
DEFUN ("qstatic-meta-object", qstatic_meta_object, 1)
DEFUN ("qsuper-class-name", qsuper_class_name, 1)
DEFUN ("qtranslate", qtranslate, 3)
DEFUN ("qt-object-name", qt_object_name, 1)
DEFUN ("qt-object-?", qt_object_x, 1)
DEFUN ("%qui-class", qui_class2, 2)
DEFUN ("qui-names", qui_names, 1)
DEFUN ("qutf8", qutf8, 1)
DEFUN ("%qvariant-equal", qvariant_equal2, 2)
DEFUN ("qvariant-from-value", qvariant_from_value, 2)
DEFUN ("qvariant-value", qvariant_value, 1)
DEFUN ("qversion", qversion, 0) }
// QtObject methods
QByteArray QtObject::idToClassName(int id) {
return (id > 0) ? LObjects::qNames.at(id - 1) : LObjects::nNames.at(-id - 1); }
QByteArray QtObject::className() const {
return id ? idToClassName(id) : QByteArray("?"); }
// *** utilities ***
static QByteArray toCString(cl_object l_str) {
QByteArray ba;
if(ECL_STRINGP(l_str)) {
if(ECL_BASE_STRING_P(l_str)) {
ba = QByteArray((char*)l_str->base_string.self, l_str->base_string.fillp); }
else {
uint l = l_str->string.fillp;
ba.reserve(l);
ecl_character* l_s = l_str->string.self;
for(uint i = 0; i < l; ++i) {
ba[i] = l_s[i]; }}}
return ba; }
static cl_object from_cstring(const QByteArray& s) {
cl_object l_s = ecl_alloc_simple_base_string(s.length());
memcpy(l_s->base_string.self, s.constData(), s.length());
return l_s; }
static void type_msg(const QByteArray& wanted, const QByteArray& got) {
STATIC_SYMBOL (s_error_output, "*ERROR-OUTPUT*")
cl_format(4,
cl_symbol_value(s_error_output),
STRING("~%[EQL:typ] wanted <~A> got <~A>"),
from_cstring(wanted),
from_cstring(got.isEmpty() ? "no Qt object" : got)); }
void error_msg(const char* fun, cl_object l_args) {
STATIC_SYMBOL_PKG (s_break_on_errors, "*BREAK-ON-ERRORS*", "EQL")
if(cl_symbol_value(s_break_on_errors) != ECL_NIL) {
STATIC_SYMBOL_PKG (s_break, "%BREAK", "EQL") // see "lisp/ini.lisp"
cl_funcall(4,
s_break,
STRING("~%[EQL:err] ~A ~{~S~^ ~}~%"),
STRING(fun),
l_args); }
else {
STATIC_SYMBOL (s_error_output, "*ERROR-OUTPUT*")
cl_format(4,
cl_symbol_value(s_error_output),
STRING("~%[EQL:err] ~A ~{~S~^ ~}~%"),
STRING(fun),
l_args); }}
cl_object error_msg2(cl_object l_fun, cl_object l_args) { // to be called from Lisp (see "lisp/ini.lisp")
error_msg(toCString(l_fun), l_args);
ecl_return1(ecl_process_env(), ECL_NIL); }
static const QMetaObject* staticMetaObject(const QtObject& qt) {
return LObjects::staticMetaObject(QByteArray(), qt.id); }
static const QMetaObject* methodMetaObject(const QtObject& qt) {
QObject* obj = qt.isQObject() ? LObjects::Q[qt.id - 1] : LObjects::N[-qt.id - 1];
return obj ? obj->metaObject() : 0; }
static const QMetaObject* methodMetaObjectFromName(const QByteArray& name, bool qobject) {
const QMetaObject* mo = 0;
int n = qobject ? LObjects::q_names.value(name, 0) : LObjects::n_names.value(name, 0);
if(n) {
QObject* o = qobject ? LObjects::Q[n - 1] : LObjects::N[n - 1];
if(o) {
mo = o->metaObject(); }}
return mo; }
static QByteArray superClassName(const QByteArray& name, bool* found = 0) {
QByteArray super;
if(LObjects::q_names.value(name, 0)) {
if(found) {
*found = true; }
const QMetaObject* moStatic = LObjects::staticMetaObject(name);
if(moStatic) {
const QMetaObject* mo = moStatic->superClass();
if(mo) {
super = mo->className(); }}}
else if(LObjects::n_names.value(name, 0)) {
if(found) {
*found = true; }
super = LObjects::nObjectSuperClass(name); }
return super; }
static bool inherits(const QByteArray& sub, const QByteArray& super) {
if(sub == super) {
return true; }
QByteArray upper(sub);
while(!(upper = superClassName(upper)).isEmpty()) {
// multiple inheritance exceptions (see "helper/multiple-inheritance.txt")
if("QGraphicsObject" == upper) {
if("QObject" == super) {
return true; }
upper = "QGraphicsItem"; }
if(upper == super) {
return true; }}
return false; }
enum CallType { SignalOrSlot, Method, Static, Qt_EQL };
static IntList findMethodIndex(CallType type, const QByteArray& name, const QMetaObject* mo, int len) {
IntList method_i;
bool this_arg = (Method == type);
QByteArray search(name);
bool exact = true;
if(search.endsWith(')')) {
if(search.endsWith("...)")) {
exact = false;
search.truncate(search.length() - 4);
if(!search.endsWith(',')) {
search.append(','); }}}
else {
if(!len && !this_arg) {
if(search.endsWith('(')) {
search.append(')'); }
else {
search.append("()"); }}
else {
exact = false; }}
if(exact) {
int i = mo->indexOfMethod(search);
if(i != -1) {
method_i << i; }}
else {
if(!search.contains('(')) {
search.append('('); }
StrList candidates;
int min = ((SignalOrSlot == type) || (Qt_EQL == type)) ? 0 : mo->methodOffset();
for(int i = mo->methodCount() - 1; i >= min; --i) {
QByteArray sig(mo->method(i).methodSignature());
int len_args = sig.count(',');
if(!this_arg) {
if(!sig.endsWith("()")) {
++len_args; }}
if(len_args == len) {
if(sig.startsWith(search)) {
method_i << i;
candidates << sig; }}}
// eliminate ambiguous ...F float 'primitive' argument lists by simply choosing the float one
// (of course this can be overridden by simply providing the non float argument list)
if(candidates.size() > 1) {
IntList mi, mi_F;
for(int i = 0; i < candidates.size(); i++) {
QByteArray sig(candidates.at(i));
if(sig.contains("QPointF") ||
sig.contains("QLineF") ||
sig.contains("QRectF") ||
sig.contains("QSizeF") ||
sig.contains("QPolygonF")) {
mi_F << method_i.at(i); }
else
if(sig.contains("QPoint") ||
sig.contains("QLine") ||
sig.contains("QRect") ||
sig.contains("QSize") ||
sig.contains("QPolygon")) {
mi << method_i.at(i); }}
if(mi_F.size() && mi.size()) {
IntList mi_ok;
Q_FOREACH(int i, method_i) {
if(!mi.contains(i)) {
mi_ok << i; }}
method_i = mi_ok; }}}
return method_i; }
static cl_object q_keyword() {
STATIC_SYMBOL_PKG (s_q, "Q", "KEYWORD")
return s_q; }
static cl_object qt_keyword() {
STATIC_SYMBOL_PKG (s_qt, "QT", "KEYWORD")
return s_qt; }
static cl_object make_vector() {
STATIC_SYMBOL_PKG (s_make_vector, "%MAKE-VECTOR", "EQL") // see "lisp/ini.lisp"
cl_object l_vector = cl_funcall(1, s_make_vector);
return l_vector; }
// *** type conversions ***
template<typename T>
static T toInt(cl_object l_num) {
T i = 0;
if(cl_integerp(l_num) == ECL_T) {
i = fixint(l_num); }
return i; }
static int toInt(cl_object l_num) {
return toInt<int>(l_num); }
template<typename T>
static T toUInt(cl_object l_num) {
T i = 0;
if(cl_integerp(l_num) == ECL_T) {
i = fixnnint(l_num); }
return i; }
static uint toUInt(cl_object l_num) {
return toUInt<uint>(l_num); }
template<typename T>
static T toFloat(cl_object l_num) {
T f = 0;
if(ECL_SINGLE_FLOAT_P(l_num)) {
f = sf(l_num); }
else if(ECL_DOUBLE_FLOAT_P(l_num)) {
f = df(l_num); }
#ifdef ECL_LONG_FLOAT
else if(ECL_LONG_FLOAT_P(l_num)) {
f = ecl_long_float(l_num); }
#endif
else if(cl_integerp(l_num) == ECL_T) {
f = fixint(l_num); }
else {
cl_object l_f = cl_float(1, l_num);
if(ECL_DOUBLE_FLOAT_P(l_f)) {
f = df(l_f); }
else if(ECL_SINGLE_FLOAT_P(l_f)) {
f = sf(l_f); }
#ifdef ECL_LONG_FLOAT
else if(ECL_LONG_FLOAT_P(l_f)) {
f = ecl_long_float(l_f); }
#endif
}
return f; }
static float toFloat(cl_object l_num) {
return toFloat<float>(l_num); }
static qreal toReal(cl_object l_num) {
return toFloat<qreal>(l_num); }
static char toChar(cl_object l_ch) {
char ch = 0;
if(ECL_CHARACTERP(l_ch)) {
ch = toInt(cl_char_code(l_ch)); }
return ch; }
static QChar toQChar(cl_object l_ch) {
QChar ch;
if(ECL_CHARACTERP(l_ch)) {
ch = QChar(toInt(cl_char_code(l_ch))); }
return ch; }
static QByteArray toQByteArray(cl_object l_vec) {
QByteArray ba;
if(ECL_VECTORP(l_vec)) {
int len = LEN(l_vec);
ba.reserve(len);
for(int i = 0; i < len; ++i) {
ba[i] = toInt(ecl_aref(l_vec, i)); }}
return ba; }
static QString toQString(cl_object l_str) {
QString s;
if(ECL_STRINGP(l_str)) {
if(ECL_BASE_STRING_P(l_str)) {
s = QString::fromLatin1((char*)l_str->base_string.self, l_str->base_string.fillp); }
else {
uint l = l_str->string.fillp;
s.reserve(l);
ecl_character* l_s = l_str->string.self;
for(uint i = 0; i < l; ++i) {
s[i] = QChar(l_s[i]); }}}
return s; }
static int classId(cl_object l_class) {
QByteArray name(toCString(l_class));
if('L' == name.at(0)) {
name[0] = 'Q'; }
int id = LObjects::q_names.value(name, 0);
if(!id) {
id = -LObjects::n_names.value(name, 0); }
return id; }
static const char* eventName(QEvent::Type type) {
const char* name = 0;
switch(type) {
case QEvent::ActionRemoved:
case QEvent::ActionChanged:
case QEvent::ActionAdded:
name = "QActionEvent";
break;
case QEvent::ChildRemoved:
case QEvent::ChildPolished:
case QEvent::ChildAdded:
name = "QChildEvent";
break;
case QEvent::Close:
name = "QCloseEvent";
break;
case QEvent::ContextMenu:
name = "QContextMenuEvent";
break;
case QEvent::DeferredDelete:
name = "QDeferredDeleteEvent";
break;
case QEvent::DragEnter:
name = "QDragEnterEvent";
break;
case QEvent::DragLeave:
name = "QDragLeaveEvent";
break;
case QEvent::DragMove:
name = "QDragMoveEvent";
break;
case QEvent::Drop:
name = "QDropEvent";
break;
case QEvent::Enter:
name = "QEnterEvent";
break;
case QEvent::FileOpen:
name = "QFileOpenEvent";
break;
case QEvent::FocusOut:
case QEvent::FocusIn:
case QEvent::FocusAboutToChange:
name = "QFocusEvent";
break;
case QEvent::GraphicsSceneContextMenu:
name = "QGraphicsSceneContextMenuEvent";
break;
case QEvent::GraphicsSceneDrop:
case QEvent::GraphicsSceneDragMove:
case QEvent::GraphicsSceneDragLeave:
case QEvent::GraphicsSceneDragEnter:
name = "QGraphicsSceneDragDropEvent";
break;
case QEvent::GraphicsSceneHoverMove:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverEnter:
name = "QGraphicsSceneHoverEvent";
break;
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMousePress:
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseDoubleClick:
name = "QGraphicsSceneMouseEvent";
break;
case QEvent::GraphicsSceneMove:
name = "QGraphicsSceneMoveEvent";
break;
case QEvent::GraphicsSceneResize:
name = "QGraphicsSceneResizeEvent";
break;
case QEvent::GraphicsSceneWheel:
name = "QGraphicsSceneWheelEvent";
break;
case QEvent::GraphicsSceneHelp:
name = "QHelpEvent";
break;
case QEvent::Hide:
name = "QHideEvent";
break;
case QEvent::HoverMove:
case QEvent::HoverLeave:
case QEvent::HoverEnter:
name = "QHoverEvent";
break;
case QEvent::IconDrag:
name = "QIconDragEvent";
break;
case QEvent::InputMethod:
name = "QInputMethodEvent";
break;
case QEvent::InputMethodQuery:
name = "QInputMethodQueryEvent";
break;
case QEvent::ShortcutOverride:
case QEvent::KeyRelease:
case QEvent::KeyPress:
name = "QKeyEvent";
break;
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
name = "QMouseEvent";
break;
case QEvent::Move:
name = "QMoveEvent";
break;
case QEvent::NativeGesture:
name = "QNativeGestureEvent";
break;
case QEvent::Paint:
name = "QPaintEvent";
break;
case QEvent::PlatformSurface:
name = "QPlatformSurfaceEvent";
break;
case QEvent::Resize:
name = "QResizeEvent";
break;
case QEvent::OrientationChange:
name = "QScreenOrientationChangeEvent";
break;
case QEvent::Scroll:
name = "QScrollEvent";
break;
case QEvent::ScrollPrepare:
name = "QScrollPrepareEvent";
break;
case QEvent::Shortcut:
name = "QShortcutEvent";
break;
case QEvent::Show:
name = "QShowEvent";
break;
case QEvent::StatusTip:
name = "QStatusTipEvent";
break;
case QEvent::TabletLeaveProximity:
case QEvent::TabletEnterProximity:
case QEvent::TabletRelease:
case QEvent::TabletPress:
case QEvent::TabletMove:
name = "QTabletEvent";
break;
case QEvent::Timer:
name = "QTimerEvent";
break;
case QEvent::WhatsThis:
case QEvent::ToolTip:
name = "QHelpEvent";
break;
case QEvent::Wheel:
name = "QWheelEvent";
break;
case QEvent::WindowStateChange:
name = "QWindowStateChangeEvent";
break;
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
case QEvent::TouchCancel:
case QEvent::TouchBegin:
name = "QTouchEvent";
break;
case QEvent::GestureOverride:
case QEvent::Gesture:
name = "QGestureEvent";
break;
default:
name = "QEvent"; }
return name; }
static QByteArray qtObjectName(cl_object l_obj, const QByteArray& type = QByteArray()) {
STATIC_SYMBOL_PKG (s_qt_object_p, "QT-OBJECT-P", "EQL")
STATIC_SYMBOL_PKG (s_ensure_qt_object, "ENSURE-QT-OBJECT", "EQL")
STATIC_SYMBOL_PKG (s_qt_object_id, "QT-OBJECT-ID", "EQL")
// 'primitives' first
QByteArray name;
if(cl_integerp(l_obj) == ECL_T) {
name = "int"; }
else if(cl_characterp(l_obj) == ECL_T) {
name = "QChar"; }
else if(cl_stringp(l_obj) == ECL_T) {
name = "QString QColor"; }
else if(cl_listp(l_obj) == ECL_T) {
int l = LEN(l_obj);
switch(l) {
case 0: break;
case 2: name = "QPointF QSizeF QList"; break;
case 4: name = "QRectF QLineF QList"; break;
default: name = "QPolygonF QList"; }}
else if(cl_vectorp(l_obj) == ECL_T) {
name = "QVector"; }
else {
// qt-object
// (this is carefully optimized, in a probably non-obvious way, because THE-QT-OBJECT is really slow)
if(type.isNull() || LObjects::q_names.contains(type) || LObjects::n_names.contains(type)) {
l_obj = cl_funcall(3, s_ensure_qt_object, l_obj, ECL_T); }
if(cl_funcall(2, s_qt_object_p, l_obj) == ECL_T) {
name = QtObject::idToClassName(toInt(cl_funcall(2, s_qt_object_id, l_obj))); }
// special case
else if((cl_functionp(l_obj) == ECL_T) || (cl_symbolp(l_obj) == ECL_T)) {
name = "FunctorOrLambda"; }}
return name; }
QtObject toQtObject(cl_object l_obj, cl_object l_cast, bool* qobject_align, bool quiet) {
STATIC_SYMBOL_PKG (s_ensure_qt_object, "ENSURE-QT-OBJECT", "EQL")
STATIC_SYMBOL_PKG (s_qt_object_pointer, "QT-OBJECT-POINTER", "EQL")
STATIC_SYMBOL_PKG (s_qt_object_unique, "QT-OBJECT-UNIQUE", "EQL")
STATIC_SYMBOL_PKG (s_qt_object_id, "QT-OBJECT-ID", "EQL")
QtObject o;
if(ECL_STRINGP(l_obj)) { // string name, for static methods
o.id = classId(l_obj); }
else {
if(quiet) {
l_obj = cl_funcall(3, s_ensure_qt_object, l_obj, ECL_T); }
else {
l_obj = cl_funcall(2, s_ensure_qt_object, l_obj); }
if(l_obj != ECL_NIL) {
o.pointer = (void*)fixnnint(cl_funcall(2, s_qt_object_pointer, l_obj));
o.unique = fixnnint(cl_funcall(2, s_qt_object_unique, l_obj));
o.id = toInt(cl_funcall(2, s_qt_object_id, l_obj));
if(l_cast != ECL_NIL) {
int id_orig = o.id;
o.id = classId(l_cast);
if((id_orig > 0) && (o.id < 0)) {
*qobject_align = true; }}}}
return o; }
static cl_object new_qt_object(void* pointer, uint unique, int id, bool finalize = false) {
STATIC_SYMBOL_PKG (s_new_qt_object, "NEW-QT-OBJECT", "EQL")
cl_object l_qt_object = cl_funcall(5,
s_new_qt_object,
ecl_make_unsigned_integer((quintptr)pointer),
ecl_make_unsigned_integer(unique),
ecl_make_fixnum(id),
finalize ? ECL_T : ECL_NIL);
return l_qt_object; }
cl_object qt_object_from_name(const QByteArray& name, void* pointer, uint unique, bool finalize) {
QByteArray name2(name);
if(name2.endsWith('*')) {
name2.truncate(name2.length() - 1); }
if(name2.startsWith("const ")) {
name2 = name2.mid(6); }
if('L' == name2.at(0)) {
name2[0] = 'Q'; }
int id = LObjects::q_names.value(name2, 0);
if(!id) {
id = -LObjects::n_names.value(name2, 0); }
cl_object l_qt_object = new_qt_object(pointer, unique, id, finalize);
return l_qt_object; }
static QString symbolName(cl_object l_symbol) {
QString name;
if((cl_symbolp(l_symbol) == ECL_T)) {
name = toQString(cl_symbol_name(l_symbol)).toLower(); }
else if(ECL_STRINGP(l_symbol)) {
name = toQString(l_symbol); }
return name; }
static QStringList toQStringList(cl_object l_list) {
QStringList l;
if(ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while(l_el != ECL_NIL) {
l << toQString(cl_car(l_el));
l_el = cl_cdr(l_el); }}
return l; }
static QPolygon toQPolygon(cl_object l_list) {
QPolygon p;
if(ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while(l_el != ECL_NIL) {
p << QPoint(toInt(cl_first(l_el)), toInt(cl_second(l_el)));
l_el = cl_cddr(l_el); }}
return p; }
static QPolygonF toQPolygonF(cl_object l_list) {
QPolygonF p;
if(ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while(l_el != ECL_NIL) {
p << QPointF(toReal(cl_first(l_el)), toReal(cl_second(l_el)));
l_el = cl_cddr(l_el); }}
return p; }
static QColor toQColor(cl_object l_c) {
if(ECL_STRINGP(l_c)) {
return QColor(toQString(l_c)); }
QtObject o = toQtObject(l_c);
if("QColor" == o.className() && o.pointer) {
QColor* p = (QColor*)o.pointer;
return *p; }
return QColor(); }
static QGradient toQGradient(cl_object l_g) {
QtObject o = toQtObject(l_g);
if(inherits(o.className(), "QGradient") && o.pointer) {
QGradient* p = (QGradient*)o.pointer;
return *p; }
return QGradient(); }
static QGradientStop toQGradientStop(cl_object l_gs) {
QGradientStop gs;
if(cl_consp(l_gs)) {
gs = qMakePair(toReal(cl_car(l_gs)), toQColor(cl_cdr(l_gs))); }
return gs; }
static QList<QTextEdit::ExtraSelection> toQTextEditExtraSelectionList(cl_object l_list) {
QList<QTextEdit::ExtraSelection> l;
if(ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while(l_el != ECL_NIL) {
cl_object l_curr = cl_first(l_el);
QtObject q_cursor = toQtObject(cl_first(l_curr));
QtObject q_format = toQtObject(cl_second(l_curr));
if(("QTextCursor" == q_cursor.className()) &&
("QTextCharFormat" == q_format.className())) {
QTextEdit::ExtraSelection sel;
sel.cursor = *(QTextCursor*)q_cursor.pointer;
sel.format = *(QTextCharFormat*)q_format.pointer;
l << sel; }
l_el = cl_rest(l_el); }}
return l; }
static QHashIntQByteArray toQHashIntQByteArray(cl_object l_alist) {
QHash<int, QByteArray> hash;
if(ECL_LISTP(l_alist)) {
cl_object l_el = l_alist;
while(l_el != ECL_NIL) {
cl_object l_curr = cl_first(l_el);
int i = toInt(cl_car(l_curr));
QByteArray ba(toCString(cl_cdr(l_curr)));
hash.insert(i, ba);
l_el = cl_rest(l_el); }}
return hash; }
// implicit pointer types
TO_QT_TYPE_PTR (QBitmap, qbitmap)
TO_QT_TYPE_PTR2 (QBrush, qbrush)
TO_QT_TYPE_PTR2 (QCursor, qcursor)
TO_QT_TYPE_PTR2 (QDate, qdate)
TO_QT_TYPE_PTR2 (QDateTime, qdatetime)
TO_QT_TYPE_PTR (QEasingCurve, qeasingcurve)
TO_QT_TYPE_PTR2 (QFileInfo, qfileinfo)
TO_QT_TYPE_PTR2 (QFont, qfont)
TO_QT_TYPE_PTR2 (QIcon, qicon)
TO_QT_TYPE_PTR2 (QImage, qimage)
TO_QT_TYPE_PTR2 (QKeySequence, qkeysequence)
TO_QT_TYPE_PTR2 (QLocale, qlocale)
TO_QT_TYPE_PTR2 (QMatrix, qmatrix)
TO_QT_TYPE_PTR (QMargins, qmargins)
TO_QT_TYPE_PTR (QMarginsF, qmarginsf)
TO_QT_TYPE_PTR2 (QModelIndex, qmodelindex)
TO_QT_TYPE_PTR (QPageLayout, qpagelayout)
TO_QT_TYPE_PTR (QPageSize, qpagesize)
TO_QT_TYPE_PTR (QPainterPath, qpainterpath)
TO_QT_TYPE_PTR2 (QPalette, qpalette)
TO_QT_TYPE_PTR2 (QPen, qpen)
TO_QT_TYPE_PTR2 (QPixmap, qpixmap)
TO_QT_TYPE_PTR (QRegion, qregion)
TO_QT_TYPE_PTR (QRegExp, qregexp)
TO_QT_TYPE_PTR (QRegularExpression, qregularexpression)
TO_QT_TYPE_PTR2 (QSizePolicy, qsizepolicy)
TO_QT_TYPE_PTR (QStorageInfo, qstorageinfo)
TO_QT_TYPE_PTR2 (QTableWidgetSelectionRange, qtablewidgetselectionrange)
TO_QT_TYPE_PTR2 (QTextBlock, qtextblock)
TO_QT_TYPE_PTR (QTextBlockFormat, qtextblockformat)
TO_QT_TYPE_PTR (QTextCharFormat, qtextcharformat)
TO_QT_TYPE_PTR (QTextFrameFormat, qtextframeformat)
TO_QT_TYPE_PTR (QTextListFormat, qtextlistformat)
TO_QT_TYPE_PTR (QTextCursor, qtextcursor)
TO_QT_TYPE_PTR (QTextDocumentFragment, qtextdocumentfragment)
TO_QT_TYPE_PTR2 (QTextFormat, qtextformat)
TO_QT_TYPE_PTR2 (QTextLength, qtextlength)
TO_QT_TYPE_PTR (QTextLine, qtextline)
TO_QT_TYPE_PTR (QTextOption, qtextoption)
TO_QT_TYPE_PTR2 (QTime, qtime)
TO_QT_TYPE_PTR2 (QTransform, qtransform)
TO_QT_TYPE_PTR2 (QUrl, qurl)
TO_QT_TYPE_PTR (QVariant, qvariant)
TO_QT_TYPEF (QPoint)
TO_QT_TYPEF (QSize)
TO_QT_TYPEF2 (QLine)
TO_QT_TYPEF2 (QRect)
TO_QT_LIST_PTR (QAbstractAnimation)
TO_QT_LIST_PTR (QAbstractButton)
TO_QT_LIST_PTR (QAbstractState)
TO_QT_LIST_PTR (QAction)
TO_QT_LIST_PTR (QDockWidget)
TO_QT_LIST_PTR (QGesture)
TO_QT_LIST_PTR (QGraphicsItem)
TO_QT_LIST_PTR (QGraphicsTransform)
TO_QT_LIST_PTR (QGraphicsView)
TO_QT_LIST_PTR (QGraphicsWidget)
TO_QT_LIST_PTR (QListWidgetItem)
TO_QT_LIST_PTR (QMdiSubWindow)
TO_QT_LIST_PTR (QObject)
TO_QT_LIST_PTR (QStandardItem)
TO_QT_LIST_PTR (QTableWidgetItem)
TO_QT_LIST_PTR (QTextFrame)
TO_QT_LIST_PTR (QTreeWidgetItem)
TO_QT_LIST_PTR (QUndoStack)
TO_QT_LIST_PTR (QWidget)
TO_QT_LIST_VAL (QByteArray)
TO_QT_LIST_VAL (QFileInfo)
TO_QT_LIST_VAL (QKeySequence)
TO_QT_LIST_VAL (QModelIndex)
TO_QT_LIST_VAL (QPolygonF)
TO_QT_LIST_VAL (QSize)
TO_QT_LIST_VAL (QTableWidgetSelectionRange)
TO_QT_LIST_VAL (QTextBlock)
TO_QT_LIST_VAL (QUrl)
TO_QT_LIST_VAL2 (int, Int)
TO_QT_LIST_VAL2 (qreal, Real)
TO_QT_VECTOR_VAL (QGradientStop)
TO_QT_VECTOR_VAL (QLine)
TO_QT_VECTOR_VAL (QLineF)
TO_QT_VECTOR_VAL (QPoint)
TO_QT_VECTOR_VAL (QPointF)
TO_QT_VECTOR_VAL (QRect)
TO_QT_VECTOR_VAL (QRectF)
TO_QT_VECTOR_VAL (QTextFormat)
TO_QT_VECTOR_VAL (QTextLength)
TO_QT_VECTOR_VAL2 (QRgb, UInt)
TO_QT_VECTOR_VAL2 (float, Float)
TO_QT_VECTOR_VAL2 (int, Int)
TO_QT_VECTOR_VAL2 (qreal, Real)
QVariant toQVariant(cl_object l_obj, const char* s_type, int type, bool* ok) {
QVariant var;
if(type == -1) {
type = QVariant::nameToType(s_type); }
if(type == QVariant::Invalid) {
*ok = false;
return var; }
switch(type) {
case QVariant::Bool: var = (l_obj != ECL_NIL); break;
case QVariant::Brush: var = toQBrush(l_obj); break;
case QVariant::ByteArray: var = toQByteArray(l_obj); break;
case QVariant::Char: var = toQChar(l_obj); break;
case QVariant::Color: var = toQColor(l_obj); break;
case QVariant::Cursor: var = toQCursor(l_obj); break;
case QVariant::Date: var = toQDate(l_obj); break;
case QVariant::DateTime: var = toQDateTime(l_obj); break;
case QVariant::Double: var = toFloat<double>(l_obj); break;
case QVariant::Font: var = toQFont(l_obj); break;
case QVariant::Icon: var = toQIcon(l_obj); break;
case QVariant::Image: var = toQImage(l_obj); break;
case QVariant::Int: var = toInt(l_obj); break;
case QVariant::KeySequence: var = toQKeySequence(l_obj); break;
case QVariant::Line: var = toQLine(l_obj); break;
case QVariant::LineF: var = toQLineF(l_obj); break;
case QVariant::Locale: var = toQLocale(l_obj); break;
case QVariant::LongLong: var = toInt<qlonglong>(l_obj); break;
case QVariant::Matrix: var = toQMatrix(l_obj); break;
case QVariant::ModelIndex: var = toQModelIndex(l_obj); break;
case QVariant::Palette: var = toQPalette(l_obj); break;
case QVariant::Pen: var = toQPen(l_obj); break;
case QVariant::Pixmap: var = toQPixmap(l_obj); break;
case QVariant::Point: var = toQPoint(l_obj); break;
case QVariant::PointF: var = toQPointF(l_obj); break;
case QVariant::Polygon: var = toQPolygon(l_obj); break;
case QVariant::Rect: var = toQRect(l_obj); break;
case QVariant::RectF: var = toQRectF(l_obj); break;
case QVariant::Size: var = toQSize(l_obj); break;
case QVariant::SizeF: var = toQSizeF(l_obj); break;
case QVariant::SizePolicy: var = toQSizePolicy(l_obj); break;
case QVariant::String: var = toQString(l_obj); break;
case QVariant::StringList: var = toQStringList(l_obj); break;
case QVariant::TextFormat: var = toQTextFormat(l_obj); break;
case QVariant::TextLength: var = toQTextLength(l_obj); break;
case QVariant::Time: var = toQTime(l_obj); break;
case QVariant::Transform: var = toQTransform(l_obj); break;
case QVariant::Url: var = toQUrl(l_obj); break;
case QVariant::UInt: var = toUInt(l_obj); break;
case QVariant::ULongLong: var = toUInt<qulonglong>(l_obj); break;
default:
// Qt_EQL: a type safe object pointer (checked at run-time)
if(QMetaType::VoidStar == type) {
QtObject obj = toQtObject(l_obj);
if(obj.pointer) {
var.setValue(eql_pointer(obj.pointer, obj.id)); }}}
return var; }
static QVariantList toQVariantList(cl_object l_list) {
QVariantList l;
if(ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while(l_el != ECL_NIL) {
QtObject q_var = toQtObject(cl_car(l_el));
if("QVariant" == q_var.className()) {
l << *(QVariant*)q_var.pointer; }
l_el = cl_cdr(l_el); }}
return l; }
static cl_object from_char(char ch) {
cl_object l_char = cl_code_char(ecl_make_fixnum((int)ch));
return l_char; }
static cl_object from_qchar(const QChar& ch) {
cl_object l_char = cl_code_char(ecl_make_fixnum(ch.unicode()));
return l_char; }
static cl_object from_qbytearray(const QByteArray& ba) {
cl_object l_vec = make_vector();
for(int i = 0; i < ba.size(); ++i) {
cl_vector_push_extend(2, ecl_make_fixnum(ba.at(i)), l_vec); }
return l_vec; }
static cl_object from_qstring(const QString& s) {
cl_object l_s = ecl_alloc_simple_extended_string(s.length());
ecl_character* l_p = l_s->string.self;
for(int i = 0; i < s.length(); ++i) {
l_p[i] = s.at(i).unicode(); }
return l_s; }
static cl_object from_qstringlist(const QStringList& l) {
cl_object l_list = ECL_NIL;
Q_FOREACH(QString s, l) {
l_list = CONS(from_qstring(s), l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_intlist(const QList<int>& l) {
cl_object l_list = ECL_NIL;
Q_FOREACH(int i, l) {
l_list = CONS(ecl_make_integer(i), l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qreallist(const QList<qreal>& l) {
cl_object l_list = ECL_NIL;
Q_FOREACH(qreal r, l) {
l_list = CONS(ecl_make_doublefloat(r), l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qcolor(const QColor& col) {
cl_object l_ret = ECL_NIL;
if(col.isValid()) { // return NIL for invalid QColors
if(EQL::return_value_p) {
l_ret = qt_object_from_name("QColor", new QColor(col), 0, true); } // GC
else {
l_ret = qt_object_from_name("QColor", (void*)&col); }}
return l_ret; }
static cl_object from_qpolygon(const QPolygon& p) {
cl_object l_list = ECL_NIL;
for(int i = 0; i < p.size(); ++i) {
int x, y;
p.point(i, &x, &y);
l_list = CONS(ecl_make_integer(y), CONS(ecl_make_integer(x), l_list)); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qpolygonf(const QPolygonF& pol) {
cl_object l_list = ECL_NIL;
for(int i = 0; i < pol.size(); ++i) {
QPointF p = pol.at(i);
l_list = CONS(ecl_make_doublefloat(p.y()), CONS(ecl_make_doublefloat(p.x()), l_list)); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qgradientstop(const QGradientStop& gs) {
cl_object l_gs = CONS(ecl_make_doublefloat(gs.first), from_qcolor(gs.second));
return l_gs; }
static cl_object from_qwidgetlist(const QWidgetList& wl) {
cl_object l_list = ECL_NIL;
Q_FOREACH(QWidget* w, wl) {
l_list = CONS(qt_object_from_name(w->metaObject()->className(),
w,
w->property("EQL.unique").toUInt()),
l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qobjectlist(const QObjectList& ol) {
cl_object l_list = ECL_NIL;
Q_FOREACH(QObject* o, ol) {
l_list = CONS(qt_object_from_name(o->metaObject()->className(),
o,
o->property("EQL.unique").toUInt()),
l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qtexteditextraselectionlist(const QList<QTextEdit::ExtraSelection>& list) {
cl_object l_list = ECL_NIL;
Q_FOREACH(QTextEdit::ExtraSelection sel, list) {
l_list = CONS(LIST2(qt_object_from_name("QTextCursor", new QTextCursor(sel.cursor)),
qt_object_from_name("QTextCharFormat", new QTextCharFormat(sel.format))),
l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static cl_object from_qhashintbytearray(const QHashIntQByteArray& hash) {
cl_object l_list = ECL_NIL;
QHashIterator<int, QByteArray> it(hash);
while(it.hasNext()) {
it.next();
l_list = CONS(CONS(ecl_make_integer(it.key()),
from_cstring(it.value())),
l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
TO_CL_TYPEF (QPoint, qpoint, x, y)
TO_CL_TYPEF (QSize, qsize, width, height)
TO_CL_TYPEF2 (QLine, qline, x1, y1, x2, y2)
TO_CL_TYPEF2 (QRect, qrect, x, y, width, height)
TO_CL_LIST_PTR (QAbstractAnimation, qabstractanimation)
TO_CL_LIST_PTR (QAbstractButton, qabstractbutton)
TO_CL_LIST_PTR (QAbstractState, qabstractstate)
TO_CL_LIST_PTR (QAction, qaction)
TO_CL_LIST_PTR (QDockWidget, qdockwidget)
TO_CL_LIST_PTR (QGesture, qgesture)
TO_CL_LIST_PTR (QGraphicsItem, qgraphicsitem)
TO_CL_LIST_PTR (QGraphicsTransform, qgraphicstransform)
TO_CL_LIST_PTR (QGraphicsView, qgraphicsview)
TO_CL_LIST_PTR (QGraphicsWidget, qgraphicswidget)
TO_CL_LIST_PTR (QListWidgetItem, qlistwidgetitem)
TO_CL_LIST_PTR (QMdiSubWindow, qmdisubwindow)
TO_CL_LIST_PTR (QStandardItem, qstandarditem)
TO_CL_LIST_PTR (QTableWidgetItem, qtablewidgetitem)
TO_CL_LIST_PTR (QTextFrame, qtextframe)
TO_CL_LIST_PTR (QTouchDevice, qtouchdevice)
TO_CL_LIST_PTR (QTreeWidgetItem, qtreewidgetitem)
TO_CL_LIST_PTR (QUndoStack, qundostack)
TO_CL_LIST_VAL (QByteArray, qbytearray)
TO_CL_LIST_VAL (QFileInfo, qfileinfo)
TO_CL_LIST_VAL (QKeySequence, qkeysequence)
TO_CL_LIST_VAL (QModelIndex, qmodelindex)
TO_CL_LIST_VAL (QPolygonF, qpolygonf)
TO_CL_LIST_VAL (QSize, qsize)
TO_CL_LIST_VAL (QStorageInfo, qstorageinfo)
TO_CL_LIST_VAL (QTableWidgetSelectionRange, qtablewidgetselectionrange)
TO_CL_LIST_VAL (QTextBlock, qtextblock)
TO_CL_LIST_VAL (QUrl, qurl)
TO_CL_VECTOR_VAL (QGradientStop, qgradientstop)
TO_CL_VECTOR_VAL (QLine, qline)
TO_CL_VECTOR_VAL (QLineF, qlinef)
TO_CL_VECTOR_VAL (QPoint, qpoint)
TO_CL_VECTOR_VAL (QPointF, qpointf)
TO_CL_VECTOR_VAL (QRect, qrect)
TO_CL_VECTOR_VAL (QRectF, qrectf)
TO_CL_VECTOR_VAL (QTextFormat, qtextformat)
TO_CL_VECTOR_VAL (QTextLength, qtextlength)
TO_CL_VECTOR_VAL2 (QRgb, qrgb, ecl_make_unsigned_integer)
TO_CL_VECTOR_VAL2 (float, float, ecl_make_singlefloat)
TO_CL_VECTOR_VAL2 (int, int, ecl_make_integer)
TO_CL_VECTOR_VAL2 (qreal, qreal, ecl_make_doublefloat)
static cl_object from_qvariant_value(const QVariant& var) {
cl_object l_obj = ECL_NIL;
int type = var.type();
switch(type) {
case QVariant::Bool: l_obj = var.toBool() ? ECL_T : ECL_NIL; break;
case QVariant::Brush: l_obj = from_qbrush(var.value<QBrush>()); break;
case QVariant::ByteArray: l_obj = from_qbytearray(var.toByteArray()); break;
case QVariant::Char: l_obj = from_qchar(var.toChar()); break;
case QVariant::Color: l_obj = from_qstring(var.toString()); break;
case QVariant::Cursor: l_obj = from_qcursor(var.value<QCursor>()); break;
case QVariant::Date: l_obj = from_qdate(var.toDate()); break;
case QVariant::DateTime: l_obj = from_qdatetime(var.toDateTime()); break;
case QVariant::Double: l_obj = ecl_make_doublefloat(var.toDouble()); break;
case QVariant::Font: l_obj = from_qfont(var.value<QFont>()); break;
case QVariant::Icon: l_obj = from_qicon(var.value<QIcon>()); break;
case QVariant::Int: l_obj = ecl_make_integer(var.toInt()); break;
case QVariant::Image: l_obj = from_qimage(var.value<QImage>()); break;
case QVariant::KeySequence: l_obj = from_qkeysequence(var.value<QKeySequence>()); break;
case QVariant::Line: l_obj = from_qline(var.toLine()); break;
case QVariant::LineF: l_obj = from_qlinef(var.toLineF()); break;
case QVariant::Locale: l_obj = from_qlocale(var.toLocale()); break;
case QVariant::LongLong: l_obj = ecl_make_integer(var.toLongLong()); break;
case QVariant::ModelIndex: l_obj = from_qmodelindex(var.value<QModelIndex>()); break;
case QVariant::Palette: l_obj = from_qpalette(var.value<QPalette>()); break;
case QVariant::Pen: l_obj = from_qpen(var.value<QPen>()); break;
case QVariant::Pixmap: l_obj = from_qpixmap(var.value<QPixmap>()); break;
case QVariant::Point: l_obj = from_qpoint(var.toPoint()); break;
case QVariant::PointF: l_obj = from_qpointf(var.toPointF()); break;
case QVariant::Polygon: l_obj = from_qpolygon(var.value<QPolygon>()); break;
case QVariant::Rect: l_obj = from_qrect(var.toRect()); break;
case QVariant::RectF: l_obj = from_qrectf(var.toRectF()); break;
case QVariant::Size: l_obj = from_qsize(var.toSize()); break;
case QVariant::SizeF: l_obj = from_qsizef(var.toSizeF()); break;
case QVariant::SizePolicy: l_obj = from_qsizepolicy(var.value<QSizePolicy>()); break;
case QVariant::String: l_obj = from_qstring(var.toString()); break;
case QVariant::StringList: l_obj = from_qstringlist(var.toStringList()); break;
case QVariant::TextFormat: l_obj = from_qtextformat(var.value<QTextFormat>()); break;
case QVariant::TextLength: l_obj = from_qtextlength(var.value<QTextLength>()); break;
case QVariant::Time: l_obj = from_qtime(var.toTime()); break;
case QVariant::Url: l_obj = from_qurl(var.toUrl()); break;
case QVariant::UInt: l_obj = ecl_make_unsigned_integer(var.toUInt()); break;
case QVariant::ULongLong: l_obj = ecl_make_unsigned_integer(var.toULongLong()); break;
// special case: QVariantList (can be nested)
case QVariant::List:
Q_FOREACH(QVariant v, var.value<QVariantList>()) {
l_obj = CONS(from_qvariant_value(v), l_obj); }
l_obj = cl_nreverse(l_obj);
break; }
return l_obj; }
static cl_object from_qvariantlist(const QVariantList& l) {
cl_object l_list = ECL_NIL;
Q_FOREACH(QVariant v, l) {
l_list = CONS(from_qvariant_value(v), l_list); }
l_list = cl_nreverse(l_list);
return l_list; }
static void* ensurePersistentFunction(cl_object l_fun) {
STATIC_SYMBOL_PKG (s_ensure_persistent_function, "%ENSURE-PERSISTENT-FUNCTION", "EQL") // see "lisp/ini.lisp"
cl_object l_ret = cl_funcall(2, s_ensure_persistent_function, l_fun);
return (ECL_NIL == l_ret) ? 0 : (void*)l_ret; }
void FunctorOrLambda::operator()(const QVariant& var) {
if(function) {
cl_funcall(2, (cl_object)function, from_qvariant_value(var)); }}
static MetaArg toMetaArg(const QByteArray& sType, cl_object l_arg) {
void* p = 0;
const int n = QMetaType::type(sType);
switch(n) {
case QMetaType::Bool: p = new bool(l_arg != ECL_NIL); break;
case QMetaType::Char: p = new char(toChar(l_arg)); break;
case QMetaType::Double: p = new double(toFloat<double>(l_arg)); break;
case QMetaType::Float: p = new float(toFloat<float>(l_arg)); break;
case QMetaType::Int: p = new int(toInt(l_arg)); break;
case QMetaType::Long: p = new int(toInt<long>(l_arg)); break;
case QMetaType::LongLong: p = new qlonglong(toInt<qlonglong>(l_arg)); break;
case QMetaType::UChar: p = new uchar(toUInt(l_arg)); break;
case QMetaType::UInt: p = new uint(toUInt(l_arg)); break;
case QMetaType::ULong: p = new ulong(toUInt<ulong>(l_arg)); break;
case QMetaType::ULongLong: p = new qulonglong(toUInt<qulonglong>(l_arg)); break;
case QMetaType::QBitmap: p = new QBitmap(*toQBitmapPointer(l_arg)); break;
case QMetaType::QByteArray: p = new QByteArray(toQByteArray(l_arg)); break;
case QMetaType::QChar: p = new QChar(toQChar(l_arg)); break;
case QMetaType::QColor: p = new QColor(toQColor(l_arg)); break;
case QMetaType::QCursor: p = new QCursor(toQCursor(l_arg)); break;
case QMetaType::QDate: p = new QDate(*toQDatePointer(l_arg)); break;
case QMetaType::QDateTime: p = new QDateTime(*toQDateTimePointer(l_arg)); break;
case QMetaType::QEasingCurve: p = new QEasingCurve(*toQEasingCurvePointer(l_arg)); break;
case QMetaType::QFont: p = new QFont(*toQFontPointer(l_arg)); break;
case QMetaType::QKeySequence: p = new QKeySequence(*toQKeySequencePointer(l_arg)); break;
case QMetaType::QLine: p = new QLine(toQLine(l_arg)); break;
case QMetaType::QLineF: p = new QLineF(toQLineF(l_arg)); break;
case QMetaType::QLocale: p = new QLocale(*toQLocalePointer(l_arg)); break;
case QMetaType::QMatrix: p = new QMatrix(*toQMatrixPointer(l_arg)); break;
case QMetaType::QPoint: p = new QPoint(toQPoint(l_arg)); break;
case QMetaType::QPointF: p = new QPointF(toQPointF(l_arg)); break;
case QMetaType::QPolygon: p = new QPolygon(toQPolygon(l_arg)); break;
case QMetaType::QRect: p = new QRect(toQRect(l_arg)); break;
case QMetaType::QRectF: p = new QRectF(toQRectF(l_arg)); break;
case QMetaType::QRegion: p = new QRegion(*toQRegionPointer(l_arg)); break;
case QMetaType::QRegExp: p = new QRegExp(*toQRegExpPointer(l_arg)); break;
case QMetaType::QRegularExpression: p = new QRegularExpression(*toQRegularExpressionPointer(l_arg)); break;
case QMetaType::QSize: p = new QSize(toQSize(l_arg)); break;
case QMetaType::QSizeF: p = new QSizeF(toQSizeF(l_arg)); break;
case QMetaType::QSizePolicy: p = new QSizePolicy(*toQSizePolicyPointer(l_arg)); break;
case QMetaType::QString: p = new QString(toQString(l_arg)); break;
case QMetaType::QStringList: p = new QStringList(toQStringList(l_arg)); break;
case QMetaType::QBrush: p = new QBrush(*toQBrushPointer(l_arg)); break;
case QMetaType::QIcon: p = new QIcon(*toQIconPointer(l_arg)); break;
case QMetaType::QImage: p = new QImage(*toQImagePointer(l_arg)); break;
case QMetaType::QPalette: p = new QPalette(*toQPalettePointer(l_arg)); break;
case QMetaType::QPen: p = new QPen(*toQPenPointer(l_arg)); break;
case QMetaType::QPixmap: p = new QPixmap(*toQPixmapPointer(l_arg)); break;
case QMetaType::QTextFormat: p = new QTextFormat(*toQTextFormatPointer(l_arg)); break;
case QMetaType::QTextLength: p = new QTextLength(*toQTextLengthPointer(l_arg)); break;
case QMetaType::QTime: p = new QTime(*toQTimePointer(l_arg)); break;
case QMetaType::QTransform: p = new QTransform(*toQTransformPointer(l_arg)); break;
case QMetaType::QUrl: p = new QUrl(*toQUrlPointer(l_arg)); break;
case QMetaType::QVariant: p = new QVariant(*toQVariantPointer(l_arg)); break;
case QMetaType::QVariantList: p = new QVariantList(toQVariantList(l_arg)); break;
default:
if(T_bool_ok_pointer == n) {
p = new void*(&_ok_); }
else if(sType.endsWith('*')) {
if(sType.startsWith('Q') || sType.startsWith("const Q")) {
QtObject o = toQtObject(l_arg);
quintptr l = (quintptr)o.pointer;
// cast from QObject to non QObject + multiple inheritance problem
// e.g. QGraphicsObject, which inherits both QObject and QGraphicsItem
int q = sType.indexOf('Q');
if((o.id > 0) && LObjects::n_names.contains(sType.mid(q, sType.length() - q - 1))) {
l += sizeof(QObject); }
void** v = new void*((void*)l);
p = v; }
else if("const char*" == sType) {
QByteArray ba(toCString(l_arg));
_cstring_buffer_ << ba;
const char** s = new const char*(ba.constData());
p = s; }}
else if(T_QFileInfo == n) p = new QFileInfo(toQFileInfo(l_arg));
else if(T_QFileInfoList == n) p = new QFileInfoList(toQFileInfoList(l_arg));
else if(T_QGradient == n) p = new QGradient(toQGradient(l_arg));
else if(T_QGradientStop == n) p = new QGradientStop(toQGradientStop(l_arg));
else if(T_QHash_int_QByteArray == n) p = new QHash<int, QByteArray>(toQHashIntQByteArray(l_arg));
else if(T_QList_QAbstractAnimation == n) p = new QList<QAbstractAnimation*>(toQAbstractAnimationList(l_arg));
else if(T_QList_QAbstractButton == n) p = new QList<QAbstractButton*>(toQAbstractButtonList(l_arg));
else if(T_QList_QAbstractState == n) p = new QList<QAbstractState*>(toQAbstractStateList(l_arg));
else if(T_QList_QAction == n) p = new QList<QAction*>(toQActionList(l_arg));
else if(T_QList_QByteArray == n) p = new QList<QByteArray>(toQByteArrayList(l_arg));
else if(T_QList_QDockWidget == n) p = new QList<QDockWidget*>(toQDockWidgetList(l_arg));
else if(T_QList_QGesture == n) p = new QList<QGesture*>(toQGestureList(l_arg));
else if(T_QList_QGraphicsItem == n) p = new QList<QGraphicsItem*>(toQGraphicsItemList(l_arg));
else if(T_QList_QGraphicsTransform == n) p = new QList<QGraphicsTransform*>(toQGraphicsTransformList(l_arg));
else if(T_QList_QGraphicsView == n) p = new QList<QGraphicsView*>(toQGraphicsViewList(l_arg));
else if(T_QList_QGraphicsWidget == n) p = new QList<QGraphicsWidget*>(toQGraphicsWidgetList(l_arg));
else if(T_QList_QKeySequence == n) p = new QList<QKeySequence>(toQKeySequenceList(l_arg));
else if(T_QList_QListWidgetItem == n) p = new QList<QListWidgetItem*>(toQListWidgetItemList(l_arg));
else if(T_QList_QMdiSubWindow == n) p = new QList<QMdiSubWindow*>(toQMdiSubWindowList(l_arg));
else if(T_QModelIndexList == n) p = new QModelIndexList(toQModelIndexList(l_arg));
else if((T_QObjectList == n) || (T_QList_QObject == n))
p = new QList<QObject*>(toQObjectList(l_arg));
else if(T_QList_QPolygonF == n) p = new QList<QPolygonF>(toQPolygonFList(l_arg));
else if(T_QList_QSize == n) p = new QList<QSize>(toQSizeList(l_arg));
else if(T_QList_QStandardItem == n) p = new QList<QStandardItem*>(toQStandardItemList(l_arg));
else if(T_QList_QTableWidgetItem == n) p = new QList<QTableWidgetItem*>(toQTableWidgetItemList(l_arg));
else if(T_QList_QTableWidgetSelectionRange == n) p = new QList<QTableWidgetSelectionRange>(toQTableWidgetSelectionRangeList(l_arg));
else if(T_QList_QTextBlock == n) p = new QList<QTextBlock>(toQTextBlockList(l_arg));
else if(T_QList_QTextEdit_ExtraSelection == n) p = new QList<QTextEdit::ExtraSelection>(toQTextEditExtraSelectionList(l_arg));
else if(T_QList_QTextFrame == n) p = new QList<QTextFrame*>(toQTextFrameList(l_arg));
else if(T_QList_QTreeWidgetItem == n) p = new QList<QTreeWidgetItem*>(toQTreeWidgetItemList(l_arg));
else if(T_QList_QUndoStack == n) p = new QList<QUndoStack*>(toQUndoStackList(l_arg));
else if(T_QList_QUrl == n) p = new QList<QUrl>(toQUrlList(l_arg));
else if((T_QWidgetList == n) || (T_QList_QWidget == n))
p = new QList<QWidget*>(toQWidgetList(l_arg));
else if(T_QList_int == n) p = new QList<int>(toIntList(l_arg));
else if(T_QList_qreal == n) p = new QList<qreal>(toRealList(l_arg));
else if(T_QMargins == n) p = new QMargins(*toQMarginsPointer(l_arg));
else if(T_QMarginsF == n) p = new QMarginsF(*toQMarginsFPointer(l_arg));
else if(T_QModelIndex == n) p = new QModelIndex(*toQModelIndexPointer(l_arg));
else if(T_QPageLayout == n) p = new QPageLayout(*toQPageLayoutPointer(l_arg));
else if(T_QPageSize == n) p = new QPageSize(*toQPageSizePointer(l_arg));
else if(T_QPainterPath == n) p = new QPainterPath(*toQPainterPathPointer(l_arg));
else if(T_QPolygonF == n) p = new QPolygonF(toQPolygonF(l_arg));
else if(T_QRgb == n) p = new QRgb(toUInt(l_arg));
else if(T_QStorageInfo == n) p = new QStorageInfo(*toQStorageInfoPointer(l_arg));
else if(T_QTableWidgetSelectionRange == n) p = new QTableWidgetSelectionRange(*toQTableWidgetSelectionRangePointer(l_arg));
else if(T_QTextBlock == n) p = new QTextBlock(*toQTextBlockPointer(l_arg));
else if(T_QTextBlockFormat == n) p = new QTextBlockFormat(*toQTextBlockFormatPointer(l_arg));
else if(T_QTextCharFormat == n) p = new QTextCharFormat(*toQTextCharFormatPointer(l_arg));
else if(T_QTextFrameFormat == n) p = new QTextFrameFormat(*toQTextFrameFormatPointer(l_arg));
else if(T_QTextListFormat == n) p = new QTextListFormat(*toQTextListFormatPointer(l_arg));
else if(T_QTextCursor == n) p = new QTextCursor(*toQTextCursorPointer(l_arg));
else if(T_QTextDocumentFragment == n) p = new QTextDocumentFragment(*toQTextDocumentFragmentPointer(l_arg));
else if(T_QTextLine == n) p = new QTextLine(*toQTextLinePointer(l_arg));
else if(T_QTextOption == n) p = new QTextOption(*toQTextOptionPointer(l_arg));
else if(T_QVector_QGradientstop == n) p = new QVector<QGradientStop>(toQGradientStopVector(l_arg));
else if(T_QVector_QLine == n) p = new QVector<QLine>(toQLineVector(l_arg));
else if(T_QVector_QLineF == n) p = new QVector<QLineF>(toQLineFVector(l_arg));
else if(T_QVector_QPoint == n) p = new QVector<QPoint>(toQPointVector(l_arg));
else if(T_QVector_QPointF == n) p = new QVector<QPointF>(toQPointFVector(l_arg));
else if(T_QVector_QRect == n) p = new QVector<QRect>(toQRectVector(l_arg));
else if(T_QVector_QRectF == n) p = new QVector<QRectF>(toQRectFVector(l_arg));
else if(T_QVector_QRgb == n) p = new QVector<QRgb>(toQRgbVector(l_arg));
else if(T_QVector_QTextFormat == n) p = new QVector<QTextFormat>(toQTextFormatVector(l_arg));
else if(T_QVector_QTextLength == n) p = new QVector<QTextLength>(toQTextLengthVector(l_arg));
else if(T_QVector_float == n) p = new QVector<float>(tofloatVector(l_arg));
else if(T_QVector_int == n) p = new QVector<int>(tointVector(l_arg));
else if(T_QVector_qreal == n) p = new QVector<qreal>(toqrealVector(l_arg));
else if(T_WId == n) p = new ulong(toUInt<ulong>(l_arg));
else if(T_GLint == n) p = new GLint(toInt<GLint>(l_arg));
else if(T_GLuint == n) p = new GLuint(toUInt<GLuint>(l_arg));
else if(T_GLenum == n) p = new GLenum(toUInt<GLenum>(l_arg));
else if(T_GLfloat == n) p = new GLfloat(toFloat<GLfloat>(l_arg));
else if(T_short == n) p = new short(toInt<short>(l_arg));
else if(T_ushort == n) p = new ushort(toUInt<ushort>(l_arg));
else if(T_qint32 == n) p = new qint32(toInt<qint32>(l_arg));
else if(T_qint64 == n) p = new qint64(toInt<qint64>(l_arg));
else if(T_quint8 == n) p = new quint8(toUInt<quint8>(l_arg));
else if(T_quint16 == n) p = new quint16(toUInt<quint16>(l_arg));
else if(T_quint32 == n) p = new quint32(toUInt<quint32>(l_arg));
else if(T_quint64 == n) p = new quint64(toUInt<quint64>(l_arg));
else if(T_FunctorOrLambda == n) p = new FunctorOrLambda(ensurePersistentFunction(l_arg));
// module types
else {
bool found = false;
if(ModuleInterface::help) {
p = ModuleInterface::help->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::multimedia) {
p = ModuleInterface::multimedia->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::network) {
p = ModuleInterface::network->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::quick) {
p = ModuleInterface::quick->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::sql) {
p = ModuleInterface::sql->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::webengine) {
p = ModuleInterface::webengine->toMetaArg(n, l_arg, &found); }
if(!found && ModuleInterface::webkit) {
p = ModuleInterface::webkit->toMetaArg(n, l_arg, &found); }
if(!found) {
// enum
if(!sType.endsWith('>') && sType.contains(':')) {
int* i = new int(toInt(l_arg));
p = i; }}}}
return MetaArg(sType, p); }
cl_object to_lisp_arg(const MetaArg& arg) {
cl_object l_ret = ECL_NIL;
void* p = arg.second;
if(p) {
QByteArray sType(arg.first);
const int n = QMetaType::type(sType);
switch(n) {
case QMetaType::Bool: l_ret = *(bool*)p ? ECL_T : ECL_NIL; break;
case QMetaType::Char: l_ret = from_char(*(char*)p); break;
case QMetaType::Double: l_ret = ecl_make_doublefloat(*(double*)p); break;
case QMetaType::Float: l_ret = ecl_make_singlefloat(*(float*)p); break;
case QMetaType::Int: l_ret = ecl_make_integer(*(int*)p); break;
case QMetaType::Long: l_ret = ecl_make_integer(*(long*)p); break;
case QMetaType::LongLong: l_ret = ecl_make_integer(*(qlonglong*)p); break;
case QMetaType::UChar: l_ret = ecl_make_fixnum(*(uchar*)p); break;
case QMetaType::UInt: l_ret = ecl_make_unsigned_integer(*(uint*)p); break;
case QMetaType::ULong: l_ret = ecl_make_unsigned_integer(*(ulong*)p); break;
case QMetaType::ULongLong: l_ret = ecl_make_unsigned_integer(*(qulonglong*)p); break;
case QMetaType::QBitmap: l_ret = from_qbitmap(*(QBitmap*)p); break;
case QMetaType::QBrush: l_ret = from_qbrush(*(QBrush*)p); break;
case QMetaType::QByteArray: l_ret = from_qbytearray(*(QByteArray*)p); break;
case QMetaType::QChar: l_ret = from_qchar(*(QChar*)p); break;
case QMetaType::QColor: l_ret = from_qcolor(*(QColor*)p); break;
case QMetaType::QCursor: l_ret = from_qcursor(*(QCursor*)p); break;
case QMetaType::QDate: l_ret = from_qdate(*(QDate*)p); break;
case QMetaType::QDateTime: l_ret = from_qdatetime(*(QDateTime*)p); break;
case QMetaType::QEasingCurve: l_ret = from_qeasingcurve(*(QEasingCurve*)p); break;
case QMetaType::QFont: l_ret = from_qfont(*(QFont*)p); break;
case QMetaType::QIcon: l_ret = from_qicon(*(QIcon*)p); break;
case QMetaType::QImage: l_ret = from_qimage(*(QImage*)p); break;
case QMetaType::QKeySequence: l_ret = from_qkeysequence(*(QKeySequence*)p); break;
case QMetaType::QLine: l_ret = from_qline(*(QLine*)p); break;
case QMetaType::QLineF: l_ret = from_qlinef(*(QLineF*)p); break;
case QMetaType::QLocale: l_ret = from_qlocale(*(QLocale*)p); break;
case QMetaType::QMatrix: l_ret = from_qmatrix(*(QMatrix*)p); break;
case QMetaType::QPalette: l_ret = from_qpalette(*(QPalette*)p); break;
case QMetaType::QPen: l_ret = from_qpen(*(QPen*)p); break;
case QMetaType::QPixmap: l_ret = from_qpixmap(*(QPixmap*)p); break;
case QMetaType::QPoint: l_ret = from_qpoint(*(QPoint*)p); break;
case QMetaType::QPointF: l_ret = from_qpointf(*(QPointF*)p); break;
case QMetaType::QPolygon: l_ret = from_qpolygon(*(QPolygon*)p); break;
case QMetaType::QRect: l_ret = from_qrect(*(QRect*)p); break;
case QMetaType::QRectF: l_ret = from_qrectf(*(QRectF*)p); break;
case QMetaType::QRegion: l_ret = from_qregion(*(QRegion*)p); break;
case QMetaType::QRegExp: l_ret = from_qregexp(*(QRegExp*)p); break;
case QMetaType::QRegularExpression: l_ret = from_qregularexpression(*(QRegularExpression*)p); break;
case QMetaType::QSize: l_ret = from_qsize(*(QSize*)p); break;
case QMetaType::QSizePolicy: l_ret = from_qsizepolicy(*(QSizePolicy*)p); break;
case QMetaType::QSizeF: l_ret = from_qsizef(*(QSizeF*)p); break;
case QMetaType::QString: l_ret = from_qstring(*(QString*)p); break;
case QMetaType::QStringList: l_ret = from_qstringlist(*(QStringList*)p); break;
case QMetaType::QTextFormat: l_ret = from_qtextformat(*(QTextFormat*)p); break;
case QMetaType::QTextLength: l_ret = from_qtextlength(*(QTextLength*)p); break;
case QMetaType::QTransform: l_ret = from_qtransform(*(QTransform*)p); break;
case QMetaType::QTime: l_ret = from_qtime(*(QTime*)p); break;
case QMetaType::QUrl: l_ret = from_qurl(*(QUrl*)p); break;
case QMetaType::QVariant: l_ret = from_qvariant(*(QVariant*)p); break;
case QMetaType::QVariantList: l_ret = from_qvariantlist(*(QVariantList*)p); break;
default:
if(T_bool_ok_pointer == n) {
l_ret = _ok_ ? ECL_T : ECL_NIL; }
else if(sType.endsWith('*')) {
if(sType.startsWith('Q') || sType.startsWith("const Q")) {
l_ret = qt_object_from_name(sType, *(void**)p); }
else if("const char*" == sType) {
l_ret = STRING_COPY(*(char**)p); }
else {
l_ret = ecl_make_unsigned_integer((quintptr)*(void**)p); }}
else if(T_QFileInfo == n) l_ret = from_qfileinfo(*(QFileInfo*)p);
else if(T_QFileInfoList == n) l_ret = from_qfileinfolist(*(QFileInfoList*)p);
else if(T_QGradientStop == n) l_ret = from_qgradientstop(*(QGradientStop*)p);
else if(T_QHash_int_QByteArray == n) l_ret = from_qhashintbytearray(*(QHashIntQByteArray*)p);
else if(T_QList_QAbstractAnimation == n) l_ret = from_qabstractanimationlist(*(QList<QAbstractAnimation*>*)p);
else if(T_QList_QAbstractButton == n) l_ret = from_qabstractbuttonlist(*(QList<QAbstractButton*>*)p);
else if(T_QList_QAbstractState == n) l_ret = from_qabstractstatelist(*(QList<QAbstractState*>*)p);
else if(T_QList_QAction == n) l_ret = from_qactionlist(*(QList<QAction*>*)p);
else if(T_QList_QByteArray == n) l_ret = from_qbytearraylist(*(QList<QByteArray>*)p);
else if(T_QList_QDockWidget == n) l_ret = from_qdockwidgetlist(*(QList<QDockWidget*>*)p);
else if(T_QList_QGesture == n) l_ret = from_qgesturelist(*(QList<QGesture*>*)p);
else if(T_QList_QGraphicsItem == n) l_ret = from_qgraphicsitemlist(*(QList<QGraphicsItem*>*)p);
else if(T_QList_QGraphicsTransform == n) l_ret = from_qgraphicstransformlist(*(QList<QGraphicsTransform*>*)p);
else if(T_QList_QGraphicsView == n) l_ret = from_qgraphicsviewlist(*(QList<QGraphicsView*>*)p);
else if(T_QList_QGraphicsWidget == n) l_ret = from_qgraphicswidgetlist(*(QList<QGraphicsWidget*>*)p);
else if(T_QList_QKeySequence == n) l_ret = from_qkeysequencelist(*(QList<QKeySequence>*)p);
else if(T_QList_QListWidgetItem == n) l_ret = from_qlistwidgetitemlist(*(QList<QListWidgetItem*>*)p);
else if(T_QList_QMdiSubWindow == n) l_ret = from_qmdisubwindowlist(*(QList<QMdiSubWindow*>*)p);
else if(T_QModelIndexList == n) l_ret = from_qmodelindexlist(*(QModelIndexList*)p);
else if((T_QObjectList == n) || (T_QList_QObject == n))
l_ret = from_qobjectlist(*(QList<QObject*>*)p);
else if(T_QList_QPolygonF == n) l_ret = from_qpolygonflist(*(QList<QPolygonF>*)p);
else if(T_QList_QSize == n) l_ret = from_qsizelist(*(QList<QSize>*)p);
else if(T_QList_QStandardItem == n) l_ret = from_qstandarditemlist(*(QList<QStandardItem*>*)p);
else if(T_QList_QStorageInfo == n) l_ret = from_qstorageinfolist(*(QList<QStorageInfo>*)p);
else if(T_QList_QTableWidgetItem == n) l_ret = from_qtablewidgetitemlist(*(QList<QTableWidgetItem*>*)p);
else if(T_QList_QTableWidgetSelectionRange == n) l_ret = from_qtablewidgetselectionrangelist(*(QList<QTableWidgetSelectionRange>*)p);
else if(T_QList_QTextBlock == n) l_ret = from_qtextblocklist(*(QList<QTextBlock>*)p);
else if(T_QList_QTextEdit_ExtraSelection == n) l_ret = from_qtexteditextraselectionlist(*(QList<QTextEdit::ExtraSelection>*)p);
else if(T_QList_QTextFrame == n) l_ret = from_qtextframelist(*(QList<QTextFrame*>*)p);
else if(T_QList_QTouchDevice == n) l_ret = from_qtouchdevicelist(*(QList<QTouchDevice*>*)p);
else if(T_QList_QTreeWidgetItem == n) l_ret = from_qtreewidgetitemlist(*(QList<QTreeWidgetItem*>*)p);
else if(T_QList_QUndoStack == n) l_ret = from_qundostacklist(*(QList<QUndoStack*>*)p);
else if(T_QList_QUrl == n) l_ret = from_qurllist(*(QList<QUrl>*)p);
else if((T_QWidgetList == n) || (T_QList_QWidget == n))
l_ret = from_qwidgetlist(*(QList<QWidget*>*)p);
else if(T_QList_int == n) l_ret = from_intlist(*(QList<int>*)p);
else if(T_QList_qreal == n) l_ret = from_qreallist(*(QList<qreal>*)p);
else if(T_QMargins == n) l_ret = from_qmargins(*(QMargins*)p);
else if(T_QMarginsF == n) l_ret = from_qmarginsf(*(QMarginsF*)p);
else if(T_QModelIndex == n) l_ret = from_qmodelindex(*(QModelIndex*)p);
else if(T_QPageLayout == n) l_ret = from_qpagelayout(*(QPageLayout*)p);
else if(T_QPageSize == n) l_ret = from_qpagesize(*(QPageSize*)p);
else if(T_QPainterPath == n) l_ret = from_qpainterpath(*(QPainterPath*)p);
else if(T_QPolygonF == n) l_ret = from_qpolygonf(*(QPolygonF*)p);
else if(T_QRgb == n) l_ret = ecl_make_unsigned_integer(*(QRgb*)p);
else if(T_QStorageInfo == n) l_ret = from_qstorageinfo(*(QStorageInfo*)p);
else if(T_QTableWidgetSelectionRange == n) l_ret = from_qtablewidgetselectionrange(*(QTableWidgetSelectionRange*)p);
else if(T_QTextBlock == n) l_ret = from_qtextblock(*(QTextBlock*)p);
else if(T_QTextBlockFormat == n) l_ret = from_qtextblockformat(*(QTextBlockFormat*)p);
else if(T_QTextCharFormat == n) l_ret = from_qtextcharformat(*(QTextCharFormat*)p);
else if(T_QTextFrameFormat == n) l_ret = from_qtextframeformat(*(QTextFrameFormat*)p);
else if(T_QTextListFormat == n) l_ret = from_qtextlistformat(*(QTextListFormat*)p);
else if(T_QTextCursor == n) l_ret = from_qtextcursor(*(QTextCursor*)p);
else if(T_QTextDocumentFragment == n) l_ret = from_qtextdocumentfragment(*(QTextDocumentFragment*)p);
else if(T_QTextLine == n) l_ret = from_qtextline(*(QTextLine*)p);
else if(T_QTextOption == n) l_ret = from_qtextoption(*(QTextOption*)p);
else if(T_QVector_QGradientstop == n) l_ret = from_qgradientstopvector(*(QVector<QGradientStop>*)p);
else if(T_QVector_QLine == n) l_ret = from_qlinevector(*(QVector<QLine>*)p);
else if(T_QVector_QLineF == n) l_ret = from_qlinefvector(*(QVector<QLineF>*)p);
else if(T_QVector_QPoint == n) l_ret = from_qpointvector(*(QVector<QPoint>*)p);
else if(T_QVector_QPointF == n) l_ret = from_qpointfvector(*(QVector<QPointF>*)p);
else if(T_QVector_QRect == n) l_ret = from_qrectvector(*(QVector<QRect>*)p);
else if(T_QVector_QRectF == n) l_ret = from_qrectfvector(*(QVector<QRectF>*)p);
else if(T_QVector_QRgb == n) l_ret = from_qrgbvector(*(QVector<QRgb>*)p);
else if(T_QVector_QTextFormat == n) l_ret = from_qtextformatvector(*(QVector<QTextFormat>*)p);
else if(T_QVector_QTextLength == n) l_ret = from_qtextlengthvector(*(QVector<QTextLength>*)p);
else if(T_QVector_float == n) l_ret = from_floatvector(*(QVector<float>*)p);
else if(T_QVector_int == n) l_ret = from_intvector(*(QVector<int>*)p);
else if(T_QVector_qreal == n) l_ret = from_qrealvector(*(QVector<qreal>*)p);
else if(T_WId == n) l_ret = ecl_make_unsigned_integer(*(ulong*)p);
else if(T_GLint == n) l_ret = ecl_make_integer(*(GLint*)p);
else if(T_GLuint == n) l_ret = ecl_make_unsigned_integer(*(GLuint*)p);
else if(T_GLenum == n) l_ret = ecl_make_unsigned_integer(*(GLenum*)p);
else if(T_GLfloat == n) l_ret = ecl_make_singlefloat(*(GLfloat*)p);
else if(T_short == n) l_ret = ecl_make_integer(*(short*)p);
else if(T_ushort == n) l_ret = ecl_make_unsigned_integer(*(ushort*)p);
else if(T_qint32 == n) l_ret = ecl_make_integer(*(qint32*)p);
else if(T_qint64 == n) l_ret = ecl_make_integer(*(qint64*)p);
else if(T_quint8 == n) l_ret = ecl_make_unsigned_integer(*(quint8*)p);
else if(T_quint16 == n) l_ret = ecl_make_unsigned_integer(*(quint16*)p);
else if(T_quint32 == n) l_ret = ecl_make_unsigned_integer(*(quint32*)p);
else if(T_quint64 == n) l_ret = ecl_make_unsigned_integer(*(quint64*)p);
// module types
else {
bool found = false;
if(ModuleInterface::help) {
l_ret = ModuleInterface::help->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::multimedia) {
l_ret = ModuleInterface::multimedia->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::network) {
l_ret = ModuleInterface::network->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::quick) {
l_ret = ModuleInterface::quick->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::sql) {
l_ret = ModuleInterface::sql->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::webengine) {
l_ret = ModuleInterface::webengine->to_lisp_arg(n, p, &found); }
if(!found && ModuleInterface::webkit) {
l_ret = ModuleInterface::webkit->to_lisp_arg(n, p, &found); }
// enum
if(!found) {
if(!sType.endsWith('>') && sType.contains(':')) {
int* i = (int*)p;
l_ret = ecl_make_integer(*i); }}}}}
return l_ret; }
static void clearMetaArg(const MetaArg& arg, bool is_ret = false) {
void* p = arg.second;
QByteArray sType(arg.first);
const int n = QMetaType::type(sType);
// catch all exceptions first
if(T_bool_ok_pointer == n) {
delete (void**)p; }
else if(sType.endsWith('*')) {
if("const char*" == sType) {
if(!is_ret && !_cstring_buffer_.isEmpty()) {
_cstring_buffer_.removeLast(); }
delete (char**)p; }
else {
delete (void**)p; }}
// enums
else if(!sType.endsWith('>') && sType.contains(':')) {
delete (int*)p; }
else {
QMetaType::destroy(n, p); }}
static void clearMetaArgList(const MetaArgList& args) {
MetaArgIterator it(args);
it.toBack();
while(it.hasPrevious()) {
clearMetaArg(it.previous()); }}
static MetaArg retArg(const QByteArray& name) {
void* p = 0;
MetaArg ret(name, p);
if(name.endsWith('*')) {
if("const char*" == name) {
p = new char**; }
else {
p = new void**; }}
else {
p = QMetaType::create(QMetaType::type(name)); }
ret.second = p;
return ret; }
// *** meta info ***
static StrList metaInfo(const QByteArray& type, const QByteArray& qclass, const QByteArray& search,
bool non, const QMetaObject* mo, bool no_offset = false) {
StrList info;
if("methods" == type) {
if(!mo) {
mo = methodMetaObjectFromName(qclass, !non); }
if(mo) {
for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
QMetaMethod mm(mo->method(i));
if(mm.methodType() == QMetaMethod::Method) {
QString sig(mm.methodSignature());
bool constructor = sig.startsWith('C');
QString ret;
if(constructor) {
sig = qclass + "(" + sig.mid(sig.contains(',') ? 7 : 6);
ret = "constructor"; }
else {
ret = mm.typeName();
if(ret.isEmpty()) {
ret = "void"; }}
ret.append(" ");
if(!sig.startsWith("_q_")) {
bool _static = false;
if(sig.startsWith('M')) {
sig = sig.mid(1); }
else if(sig.startsWith('S')) {
_static = true;
sig = sig.mid(1); }
QString name(ret + sig + (_static ? " static" : ""));
if(!_static && !constructor) {
QByteArray rm('(' + qclass + '*');
if(mm.parameterNames().size() > 1) {
rm.append(','); }
name.replace(rm, "("); }
if(name.contains(search, Qt::CaseInsensitive)) {
info << name.toLatin1(); }}}}}}
else if("override" == type) {
Q_FOREACH(QByteArray name, LObjects::overrideFunctions(qclass)) {
if(QString(name).contains(search, Qt::CaseInsensitive)) {
info << name; }}}
else if(!non) {
if(!mo) {
mo = LObjects::staticMetaObject(qclass); }
if(mo) {
if("properties" == type) {
// 'no_offset' is for properties only (QML)
for(int i = (no_offset ? 0 : mo->propertyOffset()); i < mo->propertyCount(); ++i) {
QMetaProperty mp(mo->property(i));
QString name = QString("%1 %2%3")
.arg(mp.typeName())
.arg(mp.name())
.arg(mp.isWritable() ? "" : " const");
if(name.contains(search, Qt::CaseInsensitive)) {
info << name.toLatin1(); }}}
else {
int _type = ("signals" == type) ? QMetaMethod::Signal : QMetaMethod::Slot;
for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
QMetaMethod mm(mo->method(i));
if(mm.methodType() == _type) {
QString ret(mm.typeName());
if(ret.isEmpty()) {
ret = "void"; }
QString sig(mm.methodSignature());
if(!sig.startsWith("_q_")) {
QString name(QString("%1 %2").arg(ret).arg(sig));
if(name.contains(search, Qt::CaseInsensitive)) {
info << name.toLatin1(); }}}}}}}
return info; }
static bool metaInfoLessThan(const QByteArray& s1, const QByteArray& s2) {
if(s1.contains('(')) {
return s1.mid(1 + s1.lastIndexOf(' ', s1.indexOf('('))) <
s2.mid(1 + s2.lastIndexOf(' ', s2.indexOf('('))); }
return s1.mid(1 + s1.indexOf(' ')) <
s2.mid(1 + s2.indexOf(' ')); }
static cl_object collect_info(const QByteArray& type, const QByteArray& qclass, const QByteArray& qsearch,
bool non, bool* found, const QMetaObject* mo, bool no_offset = false) {
cl_object l_info = ECL_NIL;
StrList info = metaInfo(type, qclass, qsearch, non, mo, no_offset);
qSort(info.begin(), info.end(), metaInfoLessThan);
if(info.size()) {
*found = true;
Q_FOREACH(QByteArray i, info) {
l_info = CONS(STRING_COPY(i.constData()), l_info); }}
l_info = cl_nreverse(l_info);
return l_info; }
cl_object qapropos2(cl_object l_search, cl_object l_class, cl_object l_type, cl_object l_no_offset) {
/// args: (&optional search-string class-name)
/// Finds all occurrencies of the given search string in the given object's meta information.<br>Constructors are listed under "Methods".<br>To list the user defined functions of external C++ classes (see Qt_EQL), pass the object instead of the class name.
/// (qapropos "html" "QTextEdit")
/// (qapropos nil "QWidget")
/// (qapropos)
/// (qapropos '|toString|) ; wrapper function symbol
/// (qapropos nil *qt-main*) ; see Qt_EQL (QObject derived C++ classes)
ecl_process_env()->nvalues = 1;
QByteArray search;
if(ECL_STRINGP(l_search)) {
search = toCString(l_search); }
bool all = (ECL_NIL == l_type);
bool q = all ? false : (ECL_T == cl_eql(q_keyword(), l_type));
bool no_offset = (l_no_offset != ECL_NIL); // for QML (all instance properties)
StrList classes;
bool qt_eql = false;
const QMetaObject* mo = 0;
if(ECL_STRINGP(l_class)) {
if(!classId(l_class)) {
error_msg("QAPROPOS: class not found:", LIST1(l_class));
return ECL_NIL; }
classes << toCString(l_class); }
else if(ECL_NIL == l_class) {
if(all) {
classes << LObjects::qNames;
classes << LObjects::nNames;
qSort(classes.begin(), classes.end()); }
else {
classes = q ? LObjects::qNames : LObjects::nNames; }}
else {
QtObject obj = toQtObject(l_class);
if(obj.isQObject()) {
if(obj.pointer) {
qt_eql = true;
mo = ((QObject*)obj.pointer)->metaObject();
classes << QString("%1 : %2")
.arg(mo->className())
.arg(QString(obj.className()))
.toLatin1(); }}}
cl_object l_docs = ECL_NIL;
Q_FOREACH(QByteArray cl, classes) {
bool found = false;
bool non = LObjects::n_names.contains(cl);
if(non || qt_eql || LObjects::q_names.contains(cl)) {
cl_object l_doc_pro = ECL_NIL;
cl_object l_doc_slo = ECL_NIL;
cl_object l_doc_sig = ECL_NIL;
cl_object l_doc_ovr = ECL_NIL;
if(!non) {
l_doc_pro = collect_info("properties", cl, search, non, &found, mo, no_offset); }
cl_object l_doc_met = collect_info("methods", cl, search, non, &found, mo);
if(!non) {
l_doc_slo = collect_info("slots", cl, search, non, &found, mo);
l_doc_sig = collect_info("signals", cl, search, non, &found, mo); }
l_doc_ovr = collect_info("override", cl, search, non, &found, mo);
if(found) {
cl_object l_doc = ECL_NIL;
if(l_doc_pro != ECL_NIL) {
l_doc = CONS(CONS(STRING("Properties:"), l_doc_pro), l_doc); }
if(l_doc_met != ECL_NIL) {
l_doc = CONS(CONS(STRING("Methods:"), l_doc_met), l_doc); }
if(l_doc_slo != ECL_NIL) {
l_doc = CONS(CONS(STRING("Slots:"), l_doc_slo), l_doc); }
if(l_doc_sig != ECL_NIL) {
l_doc = CONS(CONS(STRING("Signals:"), l_doc_sig), l_doc); }
if((l_doc_ovr != ECL_NIL) && !qt_eql) {
l_doc = CONS(CONS(STRING("Override:"), l_doc_ovr), l_doc); }
l_doc = cl_nreverse(l_doc);
if(l_doc != ECL_NIL) {
l_docs = CONS(CONS(STRING_COPY(cl.data()), l_doc), l_docs); }}}}
cl_object l_ret = cl_nreverse(l_docs);
return l_ret; }
// *** main functions ***
cl_object qnew_instance2(cl_object l_name, cl_object l_args) {
/// args: (class-name &rest arguments/properties)
/// alias: qnew
/// Creates a new Qt object, optionally passing the given arguments to the constructor.<br>Additionally you can pass any number of property/value pairs.<br>Please note how you can abbreviate long type lists.
/// (qnew "QWidget")
/// (qnew "QPixmap(int,int)" 50 50) ; providing constructor types
/// (qnew "QLabel" "text" "Readme") ; set properties (any number); can be combined with above
/// (qnew "QMatrix4x4(qreal...)" 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4) ; abbreviate long type lists
/// (qnew "QSizePolicy(...)" |QSizePolicy.Expanding| |QSizePolicy.Expanding|) ; will work if type unambiguous, and no properties are passed
ecl_process_env()->nvalues = 1;
static QHash<QByteArray, int> i_constructor;
if(ECL_STRINGP(l_name)) {
QByteArray name(QMetaObject::normalizedSignature(toCString(l_name)));
QByteArray nameOnly(name);
int p = name.indexOf('(');
if(p != -1) {
nameOnly = name.left(p); }
int id = LObjects::q_names.value(nameOnly, 0);
if(!id) {
id = -LObjects::n_names.value(nameOnly, 0); }
if(id) {
QObject* caller = (id > 0) ? LObjects::Q[id - 1] : LObjects::N[-id - 1];
if(caller) {
const QMetaObject* mo = caller->metaObject();
int method_i = i_constructor.value(name, -1);
int len = LEN(l_args);
if(method_i == -1) {
IntList method_list = findMethodIndex(Method, QByteArray("C(uint") + ((p == -1) ? ")" : ("," + name.mid(p + 1))), mo, len);
if(method_list.size()) {
method_i = method_list.at(0);
i_constructor[name] = method_i; }}
if(method_i != -1) {
// qt_metacall to given constructor "C(uint...)"
QMetaMethod mm(mo->method(method_i));
StrList types(mm.parameterTypes());
if(len >= (types.length() - 1)) {
const int MAX_ARGS = 16;
// r = return, u = unique
// r u 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
void* args[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void* pointer = 0;
args[0] = &pointer; // return value
uint unique = LObjects::unique();
args[1] = &unique;
MetaArgList mArgs;
cl_object l_do_args = l_args;
if(p != -1) {
for(int i = 0; (i < (types.length() - 1)) && (i < MAX_ARGS) && (l_do_args != ECL_NIL); ++i) {
MetaArg m_arg(toMetaArg(types.at(i + 1), cl_car(l_do_args)));
args[i + 2] = m_arg.second;
mArgs << m_arg;
l_do_args = cl_cdr(l_do_args); }}
caller->qt_metacall(QMetaObject::InvokeMetaMethod, method_i, args);
clearMetaArgList(mArgs);
if(pointer) {
cl_object l_ret = new_qt_object(pointer, unique, id);
if(id > 0) { // QObject derived
QObject* obj = (QObject*)pointer;
if(obj->isWidgetType()) {
obj->setProperty("EQL.unique", unique); }
while(l_do_args != ECL_NIL) {
qset_property(l_ret, cl_first(l_do_args), cl_second(l_do_args));
l_do_args = cl_cddr(l_do_args); }}
return l_ret; }}}}}}
error_msg("QNEW-INSTANCE", LIST2(l_name, l_args));
return ECL_NIL; }
cl_object qcopy(cl_object l_obj) {
/// args: (object)
/// Copies <code>object</code> using copy-on-write, if such a constructor is available (non QObject derived classes only).<br>This function is short for e.g: <code>(qnew "QPixmap(QPixmap)" pixmap)</code><br><br>Note that the returned value will not be garbage collected (analogous to <code>qnew</code>).
/// (qcopy pixmap) ; QPen, QBrush, QFont, QPalette, QPixmap, QImage...
ecl_process_env()->nvalues = 1;
QtObject o = toQtObject(l_obj);
if(!o.isQObject()) {
if(o.pointer) {
// qt_metacall to constructor "C(uint,<object>)"
QObject* caller = LObjects::N[-o.id - 1];
const QMetaObject* mo = caller->metaObject();
int n = mo->indexOfMethod(QByteArray("C(uint,") + o.className() + ")");
if(n != -1) {
void* args[] = { 0, 0, 0 };
void* pointer = 0;
args[0] = &pointer; // return value
uint unique = LObjects::unique();
args[1] = &unique;
args[2] = o.pointer;
caller->qt_metacall(QMetaObject::InvokeMetaMethod, n, args);
if(pointer) {
cl_object l_ret = new_qt_object(pointer, unique, o.id);
return l_ret; }}}}
error_msg("QCOPY", LIST1(l_obj));
return ECL_NIL; }
cl_object qset_gc(cl_object l_obj) {
_garbage_collection_ = (l_obj != ECL_NIL);
ecl_return1(ecl_process_env(), l_obj); }
enum { GarbageCollection = 1 };
cl_object qdelete2(cl_object l_obj, cl_object l_later) {
/// args: (object &optional later)
/// alias: qdel
/// Deletes any Qt object, and sets the <code>pointer</code> value to <code>0</code>. Deleting a widget deletes all its child widgets, too.<br>If <code>later</code> is not <code>NIL</code>, the function <code>QObject::deleteLater()</code> will be called instead (but note: the <code>object</code> pointer will be set to <code>0</code> immediately.)<br>Returns <code>T</code> if the object has effectively been deleted.<br><br>See also <code>qlet</code> for local Qt objects.
/// (qdel widget)
/// (qdel socket :later)
ecl_process_env()->nvalues = 1;
QtObject o = toQtObject(l_obj);
if(o.pointer) {
bool ok = false;
STATIC_SYMBOL_PKG (s_qt_object_finalize, "QT-OBJECT-FINALIZE", "EQL")
if(cl_funcall(2, s_qt_object_finalize, l_obj) != ECL_NIL) {
if(_garbage_collection_) {
if(o.isQObject()) {
QObject* obj = (QObject*)o.pointer;
delete obj; }
else {
LObjects::deleteNObject(-o.id, o.pointer, GarbageCollection); }
ok = true; }
else {
return ECL_NIL; }}
else {
if(o.isQObject()) {
QObject* obj = (QObject*)o.pointer;
if(ECL_NIL == l_later) {
delete obj; }
else {
obj->deleteLater(); }}
else {
LObjects::deleteNObject(-o.id, o.pointer); }
ok = true; }
if(ok) {
STATIC_SYMBOL_PKG (s_qset_null, "QSET-NULL", "EQL")
cl_funcall(3, s_qset_null, l_obj, ECL_NIL);
return ECL_T; }}
// no error message (unintentional multiple deletion)
return ECL_NIL; }
cl_object qproperty(cl_object l_obj, cl_object l_name) {
/// args: (object name)
/// alias: qget
/// Gets a Qt property. Enumerator values are returned as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
/// (qget label "text")
QtObject o = toQtObject(l_obj);
if(ECL_STRINGP(l_name)) {
if(o.isQObject() && o.pointer) {
const QMetaObject* mo = ((QObject*)o.pointer)->metaObject();
int n = mo->indexOfProperty(toCString(l_name));
if(n != -1) {
QMetaProperty mp(mo->property(n));
QVariant var(mp.read((QObject*)o.pointer));
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
cl_object l_ret1 = from_qvariant_value(var);
EQL::return_value_p = return_value_p;
ecl_return2(ecl_process_env(), l_ret1, ECL_T); }}}
ecl_process_env()->nvalues = 1;
error_msg("QPROPERTY", LIST2(l_obj, l_name));
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qset_property(cl_object l_obj, cl_object l_name, cl_object l_val) {
/// args: (object name value)
/// alias: qset
/// Sets a Qt property. Enumerators have to be passed as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
/// (qset label "alignment" |Qt.AlignCenter|)
QtObject o = toQtObject(l_obj);
if(ECL_STRINGP(l_name)) {
if(o.isQObject() && o.pointer) {
const QMetaObject* mo = ((QObject*)o.pointer)->metaObject();
int n = mo->indexOfProperty(toCString(l_name));
if(n != -1) {
QMetaProperty mp(mo->property(n));
QVariant var;
if(mp.isEnumType()) {
var = toInt(l_val); }
else {
var = toQVariant(l_val, mp.typeName()); }
if(mp.write((QObject*)o.pointer, var)) {
ecl_return2(ecl_process_env(), l_val, ECL_T); }}}}
error_msg("QSET-PROPERTY", LIST3(l_obj, l_name, l_val));
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qvariant_value(cl_object l_obj) {
/// args: (object)
/// Returns the Lisp value of the <code>QVariant</code> object.
ecl_process_env()->nvalues = 1;
QtObject o = toQtObject(l_obj);
if("QVariant" == o.className() && o.pointer) {
QVariant* p = (QVariant*)o.pointer;
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
cl_object l_ret = from_qvariant_value(*p);
EQL::return_value_p = return_value_p;
return l_ret; }
error_msg("QVARIANT-VALUE", LIST1(l_obj));
return ECL_NIL; }
cl_object qvariant_from_value(cl_object l_val, cl_object l_type) {
/// args: (value type-name)
/// Constructs a new <code>QVariant</code>. This is needed for types that don't have a direct constructor, like <code>QPixmap</code>, or primitive types, like <code>QSize</code>.
/// (qvariant-from-value "red" "QColor")
ecl_process_env()->nvalues = 1;
QByteArray typeName(toCString(l_type));
if(!typeName.isEmpty()) {
bool ok = true;
QVariant var(toQVariant(l_val, typeName, -1, &ok));
if(ok) {
QVariant* p = new QVariant(var);
cl_object l_ret = ECL_NIL;
if(EQL::return_value_p) {
l_ret = qt_object_from_name("QVariant", p, 0, true); } // GC
else {
l_ret = qt_object_from_name("QVariant", p); }
return l_ret; }}
error_msg("QVARIANT-FROM-VALUE", LIST2(l_val, l_type));
return ECL_NIL; }
cl_object qinvoke_method2(cl_object l_obj, cl_object l_cast, cl_object l_name, cl_object l_args) {
/// args: (object function-name &rest arguments)
/// alias: qfun
/// Calls any of Qt methods, slots, signals. Static methods can be called by passing the string name of an object.<br><br>The most convenient way of calling Qt methods is to use the wrapper functions (see alternative 2 below), which allows for tab completion, showing all possible candidates in case of ambiguous type lists (overloaded methods). Additionally, static functions are shown as one symbol (easily catching the eye).<br><br>(Optionally you can pass the argument types (as for <code>qconnect</code> and <code>qoverride</code>), which may result in better performance, but only in some edge cases.)
/// (qfun item "setText" 0 "Some objects are EQL.")
/// (qfun "QDateTime" "currentDateTime") ; static method
/// (qfun slider "valueChanged" 10) ; emit signal
///
/// ;; alternative 1: (macro '!')
///
/// (! "setText" item 0 "Some objects are EQL.")
/// (! "currentDateTime" "QDateTime")
/// (! "valueChanged" slider 10)
///
/// ;; alternative 2: (wrapper functions)
///
/// (|setText| item 0 "Some objects are EQL.")
/// (|currentDateTime.QDateTime|)
/// (|valueChanged| slider 10)
static QHash<QByteArray, IntList> i_slot;
static QHash<QByteArray, IntList> i_method;
if((l_obj != ECL_NIL) && ECL_STRINGP(l_name)) {
bool qobject_align = false;
bool qt_eql = false;
QByteArray castClass;
if(l_cast != ECL_NIL) {
if(ECL_STRINGP(l_cast)) {
castClass = toCString(l_cast); }
else if(cl_eql(qt_keyword(), l_cast)) {
qt_eql = true; }}
QtObject obj = toQtObject(l_obj, qt_eql ? ECL_NIL : l_cast, &qobject_align);
IntList method_i;
if(obj.id) {
QByteArray name(QMetaObject::normalizedSignature(toCString(l_name)));
int len_args = LEN(l_args);
QByteArray cacheName((castClass.isEmpty()
? (qt_eql
? QByteArray(obj.pointer ? ((QObject*)obj.pointer)->metaObject()->className() : "Qt")
: obj.className())
: castClass)
+ '_' + name + char('A' + len_args));
bool method = false;
const QMetaObject* mo = 0;
method_i = i_slot.value(cacheName);
if(method_i.size()) {
mo = staticMetaObject(obj); }
else {
method_i = i_method.value(cacheName);
if(method_i.size()) {
if(qt_eql) {
if(obj.pointer) {
mo = ((QObject*)obj.pointer)->metaObject(); }}
else {
method = true;
mo = methodMetaObject(obj); }}}
if(method_i.isEmpty()) {
if(qt_eql) {
if(obj.pointer) {
mo = ((QObject*)obj.pointer)->metaObject();
method_i = findMethodIndex(Qt_EQL, name, mo, len_args); }}
else {
mo = staticMetaObject(obj);
if(castClass.isEmpty() && obj.isQObject()) {
method_i = findMethodIndex(SignalOrSlot, name, mo, len_args); }
if(method_i.isEmpty()) {
method = true;
int p = name.indexOf('(');
if(p == -1) {
p = name.length();
name.append('('); }
if(obj.isStatic()) {
mo = methodMetaObject(obj);
// static methods start with 'S'
method_i = findMethodIndex(Static, QByteArray("S") + name.left(p + 1) + name.mid(p + 1), mo, len_args); }
else {
QString sep;
if(len_args) {
sep = ","; }
// ordinary methods start with 'M'
QString _name("M" + name.left(p + 1) + "%1*" + sep + name.mid(p + 1));
if(castClass.isEmpty()) {
const QMetaObject* _mo = mo;
mo = methodMetaObject(obj);
if(obj.isQObject()) {
do {
method_i = findMethodIndex(Method, _name.arg(_mo->className()).toLatin1(), mo, len_args);
if(method_i.size()) {
break; }
_mo = _mo->superClass();
mo = mo->superClass(); }
while(mo && _mo); }
else {
const char* _class = obj.className().constData();
do {
method_i = findMethodIndex(Method, _name.arg(_class).toLatin1(), mo, len_args);
if(method_i.size()) {
break; }
_class = LObjects::nObjectSuperClass(_class);
mo = mo->superClass(); }
while(_class && mo); }}
else {
// very rare need of cast, see QFUN* for examples
mo = methodMetaObject(obj);
method_i = findMethodIndex(Method, _name.arg(castClass.constData()).toLatin1(), mo, len_args); }}}}
if(method_i.size()) {
if(method || qt_eql) {
i_method[cacheName] = method_i; }
else {
i_slot[cacheName] = method_i; }}}
if(mo && method_i.size()) {
// qt_metacall
int method_index = method_i.at(0);
QMetaMethod mm(mo->method(method_index));
StrList types(mm.parameterTypes());
bool this_arg = method && !obj.isStatic();
cl_object l_do_args = l_args;
if((types.length() - (this_arg ? 1 : 0)) == len_args) {
const int MAX_ARGS = 10;
// r = return, o = object
// r o 1 2 3 4 5 6 7 8 9 10
void* args[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
MetaArgList mArgs;
int i = -1;
void* _this = 0;
if(this_arg) {
quintptr l = (quintptr)obj.pointer;
if(qobject_align) {
// cast from QObject to non QObject + multiple inheritance problem
l += sizeof(QObject); }
_this = (void*)l;
args[++i + 1] = &_this; }
bool types_ok = true;
int i_start = i;
int already_checked = -1;
// type ambiguity (same number of arguments): find method for matching type list
if(method_i.size() > 1) {
// verify if first option already matches, since latest matching option will be put
// in front of the list (auto-optimization of inner loops)
int m1 = method_i.at(0);
StrList types1(mo->method(m1).parameterTypes());
while((l_do_args != ECL_NIL) && (i < MAX_ARGS)) {
++i;
QByteArray curr(types1.at(i));
if(curr.endsWith('*')) {
curr.truncate(curr.length() - 1); }
QByteArray typeName(qtObjectName(cl_car(l_do_args), curr));
bool match = (inherits(typeName, curr) ||
((curr == "int") ? (typeName == "int") : typeName.contains(curr)) ||
(curr.contains("::") && (typeName == "int")) ||
(curr.contains("QList") && typeName.contains("QList")) ||
(curr.contains("QVector") && typeName.contains("QVector")));
if(!match) {
goto ok1; }
l_do_args = cl_cdr(l_do_args); }
goto ok3;
ok1:
i = i_start;
l_do_args = l_args;
IntList method_i_orig = method_i;
while((l_do_args != ECL_NIL) && (i < MAX_ARGS)) {
++i;
cl_object l_arg = cl_car(l_do_args);
QByteArray typeName(qtObjectName(l_arg));
IntList matches;
Q_FOREACH(int mi, method_i) {
StrList types_i(mo->method(mi).parameterTypes());
QByteArray curr(types_i.at(i));
if(curr.endsWith('*')) {
curr.truncate(curr.length() - 1); }
if(inherits(typeName, curr) ||
((curr == "int") ? (typeName == "int") : typeName.contains(curr)) ||
(curr.contains("::") && (typeName == "int")) ||
(curr.contains("QList") && typeName.contains("QList")) ||
(curr.contains("QVector") && typeName.contains("QVector"))) {
matches << mi;
method_index = mi;
mm = mo->method(method_index);
types = types_i;
if(types.size() == (i + 1)) { // last argument
goto ok2; }}}
if(matches.size() == 1) {
goto ok2; }
else if(matches.size() > 1) {
method_i = matches; }
l_do_args = cl_cdr(l_do_args); }
ok2:
// put method_index in front (optimization for repeated calls)
method_i = method_i_orig;
method_i.removeOne(method_index);
method_i.prepend(method_index);
if(method || qt_eql) {
i_method[cacheName] = method_i; }
else {
i_slot[cacheName] = method_i; }}
ok3:
l_do_args = l_args;
already_checked = i;
i = i_start;
while((l_do_args != ECL_NIL) && (i < MAX_ARGS)) {
++i;
cl_object l_arg = cl_car(l_do_args);
// type check
if(_check_argument_types_ && (i > already_checked)) {
if((l_arg != ECL_NIL) &&
(types.at(i).startsWith('Q')) &&
!types.at(i).contains(':') &&
!types.at(i).endsWith('>')) {
if(!strstr("QByteArray QChar QColor QGradientStop QLineF QPointF QPolygonF QRectF QRgb QSizeF QStringList", // primitives
types.at(i))) {
if(types.at(i) != "QVariantList") { // special case
QByteArray name1(types.at(i));
if(name1.endsWith('*')) {
name1.truncate(name1.length() - 1); }
QByteArray name2(qtObjectName(l_arg, name1));
if(!inherits(name2, name1)) {
type_msg(name1, name2);
types_ok = false;
break; }}}}}
MetaArg m_arg(toMetaArg(types.at(i), l_arg));
args[i + 1] = m_arg.second;
mArgs << m_arg;
l_do_args = cl_cdr(l_do_args); }
if(types_ok) {
MetaArg ret(retArg(mm.typeName()));
args[0] = ret.second; // return value
QObject* caller = 0;
if(method) {
caller = obj.isQObject() ? LObjects::Q[obj.id - 1] : LObjects::N[-obj.id - 1]; }
else {
caller = obj.isQObject() ? (QObject*)obj.pointer : 0; }
if(caller) {
caller->qt_metacall(QMetaObject::InvokeMetaMethod, method_index, args);
clearMetaArgList(mArgs);
cl_object l_ret = ECL_NIL;
if(ret.second) {
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
l_ret = to_lisp_arg(ret);
EQL::return_value_p = return_value_p;
clearMetaArg(ret, true); }
ecl_return2(ecl_process_env(), l_ret, ECL_T); }
else {
clearMetaArgList(mArgs); }}}}}}
error_msg("QINVOKE-METHOD", LIST4(l_obj, l_cast, l_name, l_args));
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qconnect2(cl_object l_caller, cl_object l_signal, cl_object l_receiver, cl_object l_slot) {
/// args: (caller signal receiver/function &optional slot)
/// Connects either a Qt signal to a Qt slot, or a Qt signal to a Lisp function.
/// (qconnect edit "textChanged(QString)" label "setText(QString)")
/// (qconnect edit "textChanged(QString)" (lambda (txt) (print txt)))
ecl_process_env()->nvalues = 1;
if(ECL_STRINGP(l_signal)) {
QtObject o1 = toQtObject(l_caller);
if(o1.isQObject() && o1.pointer) {
QByteArray signal(QMetaObject::normalizedSignature(toCString(l_signal)));
if(ECL_STRINGP(l_slot)) {
QtObject o2 = toQtObject(l_receiver);
if(o2.isQObject() && o2.pointer) {
QByteArray slot(QMetaObject::normalizedSignature(toCString(l_slot)));
if(QMetaObject::checkConnectArgs(signal, slot)) {
if(QObject::connect((QObject*)o1.pointer, SIG + signal, (QObject*)o2.pointer, SLO + slot)) {
return ECL_T; }}}}
else if(ECL_NIL == l_slot) {
void* fun = ensurePersistentFunction(l_receiver);
if(fun) {
QObject* object = (QObject*)o1.pointer;
if(DynObject::connect(object, SIG + signal, LObjects::dynObject, fun)) {
// when object gets deleted, remove all Lisp connections
QObject::connect(object, QSIGNAL(destroyed(QObject*)),
LObjects::eql, QSLOT(removeConnections(QObject*)));
return ECL_T; }}}}}
error_msg("QCONNECT", LIST4(l_caller, l_signal, l_receiver, l_slot));
return ECL_NIL; }
cl_object qdisconnect2(cl_object l_caller, cl_object l_signal, cl_object l_receiver, cl_object l_slot) {
/// args: (caller &optional signal receiver/function slot)
/// Disconnects signals to either Qt slots or Lisp functions. Anything but the caller can be either <code>NIL</code> or omitted.<br>Returns <code>T</code> if something has effectively been disconnected.
/// (qdisconnect edit "textChanged(QString)" label "setText(QString)")
/// (qdisconnect edit "textChanged(QString)")
/// (qdisconnect edit nil label)
/// (qdisconnect edit)
ecl_process_env()->nvalues = 1;
QtObject o1 = toQtObject(l_caller);
if(o1.isQObject() && o1.pointer) {
QtObject o2 = toQtObject(l_receiver, ECL_NIL, 0, true); // quiet
QByteArray signal(toCString(l_signal));
QByteArray slot(toCString(l_slot));
if(!signal.isEmpty()) {
signal = QMetaObject::normalizedSignature(signal);
signal.prepend(SIG); }
if(!slot.isEmpty()) {
slot = QMetaObject::normalizedSignature(slot);
slot.prepend(SLO); }
bool disconnected = false;
bool null_receiver = (l_receiver == ECL_NIL);
if(null_receiver || o2.isQObject()) {
if(QObject::disconnect((QObject*)o1.pointer,
signal.isEmpty() ? 0: signal.constData(),
o2.isQObject() ? (QObject*)o2.pointer : 0,
slot.isEmpty() ? 0 : slot.constData())) {
disconnected = true; }}
if(null_receiver || !o2.isQObject()) {
if(DynObject::disconnect((QObject*)o1.pointer,
signal.isEmpty() ? 0 : signal.constData(),
LObjects::dynObject,
l_receiver)) {
disconnected = true; }}
return disconnected ? ECL_T : ECL_NIL; }
error_msg("QDISCONNECT", LIST4(l_caller, l_signal, l_receiver, l_slot));
return ECL_NIL; }
cl_object qsender() {
/// args: ()
/// Corresponding to <code>QObject::sender()</code>. To use inside a Lisp function connected to a Qt signal.
ecl_process_env()->nvalues = 1;
QObject* curr = DynObject::currentSender;
if(curr) {
cl_object l_ret = qt_object_from_name(curr->metaObject()->className(),
curr,
curr->property("EQL.unique").toUInt());
return l_ret; }
error_msg("QSENDER", ECL_NIL);
return ECL_NIL; }
static cl_object call_lisp_fun(cl_object l_fun, cl_object l_args, quint64 override_id = 0) {
cl_object l_ret = ECL_NIL;
const cl_env_ptr l_env = ecl_process_env();
if(override_id) {
LObjects::callingList.append(override_id);
LObjects::calling = override_id; }
CL_CATCH_ALL_BEGIN(l_env) {
CL_UNWIND_PROTECT_BEGIN(l_env) {
l_ret = cl_apply(2, l_fun, l_args); }
CL_UNWIND_PROTECT_EXIT {
if(override_id) {
LObjects::callingList.removeLast();
LObjects::calling = LObjects::callingList.isEmpty() ? 0 : LObjects::callingList.last(); }}
CL_UNWIND_PROTECT_END; }
CL_CATCH_ALL_END;
return l_ret; }
void callConnectFun(void* fun, const StrList& types, void** args) {
int i = 0;
cl_object l_args = ECL_NIL;
Q_FOREACH(QByteArray type, types) {
l_args = CONS(to_lisp_arg(MetaArg(type, args[++i])), l_args); }
call_lisp_fun((cl_object)fun, cl_nreverse(l_args)); }
cl_object qoverride(cl_object l_obj, cl_object l_name, cl_object l_fun) {
/// args: (object name function)
/// Sets a Lisp function to be called on a virtual Qt method.<br>To remove a function, pass <code>NIL</code> instead of the function argument.<br><br>If you call <code>qcall-default</code> anywhere inside your overridden function, the base implementation will be called <b>afterwards</b>.<br>Instead of <code>qcall-default</code> you can directly call the base implementation, which is useful if you want to do post-processing of the returned value.
/// (qoverride edit "keyPressEvent(QKeyEvent*)" (lambda (ev) (print (|key| ev)) (qcall-default)))
ecl_process_env()->nvalues = 1;
QtObject o = toQtObject(l_obj);
void* fun = (ECL_NIL == l_fun) ? 0 : ensurePersistentFunction(l_fun);
if(o.pointer) {
QByteArray name(QMetaObject::normalizedSignature(toCString(l_name)));
uint id = LObjects::override_function_ids.value(name, 0);
if(id) {
LObjects::setOverrideFun(LObjects::override_id(o.unique, id), fun);
return ECL_T; }}
error_msg("QOVERRIDE", LIST3(l_obj, l_name, l_fun));
return ECL_NIL; }
cl_object qcall_default() {
/// args: ()
/// To use anywhere inside an overridden function (see <code>qoverride</code>).<br>Calls the base implementation of the virtual Qt method <b>after</b> leaving the function body.<br><br>Optionally call the base implementation directly (if you want to do post-processing of the return value).
LObjects::call_default = true;
ecl_return1(ecl_process_env(), ECL_T); }
QVariant callOverrideFun(void* fun, int id, const void** args, quint64 override_id) {
STATIC_SYMBOL_PKG (s_qt_object_p, "QT-OBJECT-P", "EQL")
STATIC_SYMBOL_PKG (s_qt_object_pointer, "QT-OBJECT-POINTER", "EQL")
int n = id - 1;
int i = 0;
const char* arg_type = 0;
cl_object l_args = ECL_NIL;
while((arg_type = LObjects::override_arg_types[n][i + 1])) {
l_args = CONS(to_lisp_arg(MetaArg(arg_type, (void*)args[i])), l_args);
++i; }
LObjects::call_default = false; // see qcall_default()
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
cl_object l_ret = call_lisp_fun((cl_object)fun, cl_nreverse(l_args), override_id);
EQL::return_value_p = return_value_p;
QVariant ret;
const char* ret_type = LObjects::override_arg_types[n][0];
if(ret_type) {
QByteArray retType(ret_type);
void* pointer = 0;
if(cl_funcall(2, s_qt_object_p, l_ret) == ECL_T) {
pointer = (void*)fixnnint(cl_funcall(2, s_qt_object_pointer, l_ret)); }
if(retType.startsWith('Q') && retType.endsWith('*')) {
ret.setValue(pointer); }
else {
const int type = QMetaType::type(ret_type);
if(type == QMetaType::QVariant) ret = *(QVariant*)pointer;
else if(type == T_QFileInfo) ret.setValue(*(QFileInfo*)pointer);
else if(type == T_QHash_int_QByteArray) ret.setValue(toQHashIntQByteArray(l_ret));
else if(type == T_QModelIndex) ret.setValue(*(QModelIndex*)pointer);
else if(type == T_QPainterPath) ret.setValue(*(QPainterPath*)pointer);
else if(type == T_QTableWidgetSelectionRange) ret.setValue(*(QTableWidgetSelectionRange*)pointer);
else if(type == T_QTextBlock) ret.setValue(*(QTextBlock*)pointer);
else if(type == T_QTextCharFormat) ret.setValue(*(QTextCharFormat*)pointer);
else if(type == T_QTextCursor) ret.setValue(*(QTextCursor*)pointer);
else if(type == T_QTextDocumentFragment) ret.setValue(*(QTextDocumentFragment*)pointer);
else if(type == T_QTextOption) ret.setValue(*(QTextOption*)pointer);
else ret = toQVariant(l_ret, 0, type); }}
return ret; }
cl_object qadd_event_filter(cl_object l_obj, cl_object l_ev, cl_object l_fun) {
/// args: (object event function)
/// Convenience function. Adds a Lisp function to be called on a given event type.<br>If the object argument is <code>NIL</code>, the event will be captured for the whole application.<br>If the Lisp function returns <code>NIL</code>, the event will be processed by Qt afterwards.<br><br>Returns a handle which can be used to remove the filter, see <code>qremove-event-filter</code>.<br><br>See also <code>qoverride</code> for <code>QObject::eventFilter(QObject*,QEvent*)</code> and <br><code>QObject::installEventFilter(QObject*)</code>,<br><code>QObject::removeEventFilter(QObject*)</code>.<br><br>The event class corresponds to the respective event type (no cast needed).
/// (qadd-event-filter nil |QEvent.MouseButtonPress| (lambda (object mouse-event) (print object) nil))
ecl_process_env()->nvalues = 1;
void* fun = ensurePersistentFunction(l_fun);
if(fun) {
QObject* obj = 0;
if(l_obj != ECL_NIL) {
QtObject o = toQtObject(l_obj);
if(o.isQObject()) {
obj = (QObject*)o.pointer; }}
int id = LObjects::dynObject->addEventFilter(obj, toInt(l_ev), fun);
cl_object l_id = ecl_make_integer(id);
return l_id; }
error_msg("QADD-EVENT-FILTER", LIST3(l_obj, l_ev, l_fun));
return ECL_NIL; }
cl_object qremove_event_filter(cl_object l_handle) {
/// args: (handle)
/// Removes the event filter corresponding to <code>handle</code>, which is the return value of <code>qadd-event-filter</code>.<br>Returns <code>handle</code> if the event filter has effectively been removed.<br>See also <code>qclear-event-filters</code>.
ecl_process_env()->nvalues = 1;
if(cl_integerp(l_handle) == ECL_T) {
return LObjects::dynObject->removeEventFilter(toInt(l_handle)) ? l_handle : ECL_NIL; }
error_msg("QREMOVE-EVENT-FILTER", LIST1(l_handle));
return ECL_NIL; }
bool callEventFun(void* fun, QObject* obj, QEvent* ev) {
if(fun) {
if(obj->objectName().endsWith("viewport")) {
obj = obj->parent(); }
return (call_lisp_fun((cl_object)fun,
LIST2(qt_object_from_name(obj->metaObject()->className(), (void*)obj),
qt_object_from_name(eventName(ev->type()), (void*)ev)))
!= ECL_NIL); }
return true; }
cl_object qclear_event_filters() {
/// args: ()
/// Clears all added event filters.
LObjects::dynObject->clearEventFilters();
ecl_return1(ecl_process_env(), ECL_T); }
cl_object qrequire2(cl_object l_name, cl_object l_quiet) { /// qrequire
/// args: (module &optional quiet)
/// Loads an EQL module, corresponding to a Qt module.<br>Returns the module name if both loading and initializing have been successful.<br>If the <code>quiet</code> argument is not <code>NIL</code>, no error message will be shown on failure.<br><br>Currently available modules: <code>:help :multimedia :network :quick :sql :svg :webengine :webkit</code>
/// (qrequire :network)
ecl_process_env()->nvalues = 1;
QString name = symbolName(l_name);
QString file("eql5_" + name);
QString path("/usr/local/lib/"); // 'local' might not be in library search paths
#ifdef Q_OS_MACOS
// try bundle first
QString appPath(QCoreApplication::applicationDirPath());
if(appPath.contains(".app/")) {
path = appPath + "/../libs/"; }
#endif
#ifdef STATIC_MODULES
#ifndef OS_SAILFISH
if("help" == name) {
if(!ModuleInterface::help) {
ModuleInterface::help = new ModuleHelp; }}
else
#endif
if("multimedia" == name) {
if(!ModuleInterface::multimedia) {
ModuleInterface::multimedia = new ModuleMultimedia; }}
else if("network" == name) {
if(!ModuleInterface::network) {
ModuleInterface::network = new ModuleNetwork; }}
else if("quick" == name) {
if(!ModuleInterface::quick) {
ModuleInterface::quick = new ModuleQuick; }}
else if("sql" == name) {
if(!ModuleInterface::sql) {
ModuleInterface::sql = new ModuleSql; }}
#ifndef OS_SAILFISH
else if("svg" == name) {
if(!ModuleInterface::svg) {
ModuleInterface::svg = new ModuleSvg; }}
else if("webengine" == name) {
if(!ModuleInterface::webengine) {
ModuleInterface::webengine = new ModuleWebengine; }}
/* (uncomment if needed)
else if("webkit" == name) {
if(!ModuleInterface::webkit) {
ModuleInterface::webkit = new ModuleWebkit; }} */
#endif
else if(l_quiet == ECL_NIL) {
error_msg("QREQUIRE", LIST1(l_name)); }
return l_name;
#else
QLibrary lib(path + file);
if(!lib.load()) {
lib.setFileName(file); } // use default library paths
typedef ModuleInterface* (*Ini)();
Ini ini = 0;
if("help" == name) {
if(ModuleInterface::help) {
return l_name; }
ini = (Ini)lib.resolve("help_ini");
if(ini) {
ModuleInterface::help = ini();
return l_name; }}
else if("multimedia" == name) {
if(ModuleInterface::multimedia) {
return l_name; }
ini = (Ini)lib.resolve("multimedia_ini");
if(ini) {
ModuleInterface::multimedia = ini();
return l_name; }}
else if("network" == name) {
if(ModuleInterface::network) {
return l_name; }
ini = (Ini)lib.resolve("network_ini");
if(ini) {
ModuleInterface::network = ini();
return l_name; }}
else if("quick" == name) {
if(ModuleInterface::quick) {
return l_name; }
ini = (Ini)lib.resolve("quick_ini");
if(ini) {
ModuleInterface::quick = ini();
return l_name; }}
else if("sql" == name) {
if(ModuleInterface::sql) {
return l_name; }
ini = (Ini)lib.resolve("sql_ini");
if(ini) {
ModuleInterface::sql = ini();
return l_name; }}
else if("svg" == name) {
if(ModuleInterface::svg) {
return l_name; }
ini = (Ini)lib.resolve("svg_ini");
if(ini) {
ModuleInterface::svg = ini();
return l_name; }}
else if("webengine" == name) {
if(ModuleInterface::webengine) {
return l_name; }
ini = (Ini)lib.resolve("webengine_ini");
if(ini) {
ModuleInterface::webengine = ini();
return l_name; }}
else if("webkit" == name) {
if(ModuleInterface::webkit) {
return l_name; }
ini = (Ini)lib.resolve("webkit_ini");
if(ini) {
ModuleInterface::webkit = ini();
return l_name; }}
#endif
if(l_quiet == ECL_NIL) {
error_msg("QREQUIRE", LIST1(l_name)); }
return ECL_NIL; }
cl_object qload_cpp(cl_object l_lib_name, cl_object l_unload) { /// qload-c++
/// args: (library-name &optional unload)
/// Loads a custom Qt/C++ plugin (see <code>Qt_EQL/</code>).<br>The <code>library-name</code> has to be passed as path to the plugin, without file ending.<br><br>This offers a simple way to extend your application with your own Qt/C++ functions.<br>The plugin will be reloaded (if supported by the OS) every time you call this function (Linux: see also <code>qauto-reload-c++</code>).<br>If the <code>unload</code> argument is not <code>NIL</code>, the plugin will be unloaded (if supported by the OS).
/// (defparameter *c++* (qload-c++ "eql_cpp")) ; load (Linux: see also QAUTO-RELOAD-C++)
///
/// (qapropos nil *c++*) ; documentation
///
/// (! "mySpeedyQtFunction" (:qt *c++*)) ; call library function (see also DEFINE-QT-WRAPPERS)
static QHash<QString, QLibrary*> libraries;
QString libName = toQString(l_lib_name);
bool unload = (l_unload != ECL_NIL);
if(!libName.isEmpty()) {
if(!libName.contains('/')) {
libName.prepend("./"); }
QLibrary* lib = libraries.value(libName, 0);
if(lib) {
if(lib->isLoaded()) {
lib->unload(); // for both unload/reload
if(!unload) {
cl_sleep(ecl_make_singlefloat(0.5)); }}}
if(unload) {
ecl_process_env()->nvalues = 1;
if(lib) {
delete lib;
libraries.remove(libName);
return l_lib_name; }
return ECL_NIL; }
if(!lib) {
lib = new QLibrary(libName);
libraries[libName] = lib; }
typedef QObject* (*Ini)();
Ini ini = (Ini)lib->resolve("ini");
if(ini) {
QObject* main = ini();
if(main) {
cl_object l_ret1 = qt_object_from_name(LObjects::vanillaQtSuperClassName(main->metaObject()),
main,
main->property("EQL.unique").toUInt());
// for QFileSystemWatcher (QAUTO-RELOAD-C++)
QString fileName(lib->fileName());
if(fileName.startsWith("./")) {
fileName.prepend(QDir::currentPath() + "/"); }
cl_object l_ret2 = from_qstring(fileName);
ecl_return2(ecl_process_env(), l_ret1, l_ret2); }}}
error_msg("QLOAD-C++", LIST2(l_lib_name, l_unload));
ecl_return1(ecl_process_env(), ECL_NIL); }
// *** convenience functions ***
cl_object qtranslate(cl_object l_con, cl_object l_src, cl_object l_n) {
QByteArray context(toQString(l_con).toUtf8());
QByteArray source(toQString(l_src).toUtf8());
int n = toInt(l_n);
cl_object l_ret;
if(n == -1) {
l_ret = from_qstring(QCoreApplication::translate(context, source)); }
else {
l_ret = from_qstring(QCoreApplication::translate(context, source, 0, n)); }
ecl_return1(ecl_process_env(), l_ret); }
cl_object qlocal8bit(cl_object l_str) {
/// args: (string)
/// Converts a Unicode pathname to a simple ECL base string, using <code>QString::toLocal8Bit()</code> (see <code>QLocale</code> settings).<br>Depending on the OS (namely Windows), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QUTF8</b>.
cl_object l_ret = from_cstring(toQString(l_str).toLocal8Bit()); // returns 'ecl_simple_base_string', not Unicode
ecl_return1(ecl_process_env(), l_ret); }
cl_object qutf8(cl_object l_str) {
/// args: (string)
/// Converts a Unicode pathname to a simple ECL base string, using <code>QString::toUtf8()</code>.<br>Depending on the OS (namely OSX, Linux), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QLOCAL8BIT</b>.
cl_object l_ret = from_cstring(toQString(l_str).toUtf8()); // returns 'ecl_simple_base_string', not Unicode
ecl_return1(ecl_process_env(), l_ret); }
cl_object qfrom_utf8(cl_object l_ba) {
/// args: (byte-array)
/// Returns the byte array (vector of octets) converted using <code>QString::fromUtf8()</code>.
cl_object l_ret = from_qstring(QString::fromUtf8(toQByteArray(l_ba)));
ecl_return1(ecl_process_env(), l_ret); }
cl_object qescape(cl_object l_str) {
/// args: (string)
/// Calls <code>QString::toHtmlEscaped()</code>.
cl_object l_ret = from_qstring(toQString(l_str).toHtmlEscaped());
ecl_return1(ecl_process_env(), l_ret); }
cl_object qt_object_name(cl_object l_obj) {
/// args: (object)
/// Returns the Qt class name.
QtObject o = toQtObject(l_obj);
cl_object l_ret = from_cstring(o.className());
ecl_return1(ecl_process_env(), l_ret); }
cl_object qt_object_x(cl_object l_obj) { /// qt-object-?
/// args: (object)
/// Returns the specific <code>qt-object</code> of a generic <code>qt-object</code>.<br>Works for QObject and QEvent inherited classes only.
/// (qt-object-? (|parentWidget| widget))
/// (qt-object-? (|widget| (|itemAt| box-layout 0)))
/// (qt-object-? event)
QtObject o = toQtObject(l_obj);
cl_object l_ret = l_obj;
if(o.pointer) {
// QObject
if(o.isQObject()) {
QObject* obj = (QObject*)o.pointer;
l_ret = qt_object_from_name(LObjects::vanillaQtSuperClassName(obj->metaObject()),
obj,
obj->property("EQL.unique").toUInt()); }
// QEvent
else if(o.id == -LObjects::n_names.value("QEvent")) {
const char* name = eventName(((QEvent*)o.pointer)->type());
if(name) {
l_ret = qt_object_from_name(name, o.pointer, o.unique); }}}
ecl_return1(ecl_process_env(), l_ret); }
cl_object qobject_names2(cl_object l_type) {
/// args: (&optional type)
/// Returns all supported object names. Passing either <code>:q</code> or <code>:n</code> returns only the QObject inherited, or not QObject inherited names, respectively.
bool all = (ECL_NIL == l_type);
StrList names;
if(all) {
names << LObjects::qNames;
names << LObjects::nNames;
qSort(names.begin(), names.end()); }
else {
names = (ECL_T == cl_eql(q_keyword(), l_type)) ? LObjects::qNames : LObjects::nNames; }
QStringList list;
Q_FOREACH(QByteArray name, names) {
list << QString(name); }
cl_object l_ret = from_qstringlist(list);
ecl_return1(ecl_process_env(), l_ret); }
cl_object qenums2(cl_object l_class, cl_object l_name) {
/// args: (class-name &optional enum-name)
/// Returns the meta enum list of the given <code>class-name</code> and <code>enum-name</code> (see <code>Q_ENUMS</code> in Qt sources).<br>Omitting <code>enum-name</code> will return all meta enum lists of the class/scope.
/// (qenums "QLineEdit" "EchoMode") ; gives '("QLineEdit" ("EchoMode" ("Normal" . 0) ...))
/// (qenums "Qt")
ecl_process_env()->nvalues = 1;
if(ECL_STRINGP(l_class)) {
QByteArray className(toCString(l_class));
QByteArray name(toCString(l_name));
const QMetaObject* mo = ("Qt" == className) ? staticQtMetaObject : LObjects::staticMetaObject(className);
if(mo) {
cl_object l_enums = ECL_NIL;
for(int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) {
QMetaEnum me(mo->enumerator(i));
if((l_name == ECL_NIL) || (me.name() == name)) {
cl_object l_keys = LIST1(from_cstring(me.name()));
for(int j = 0; j < me.keyCount(); ++j) {
QByteArray key(me.key(j));
int val = (me.isFlag() ? me.keysToValue(key) : me.keyToValue(key));
l_keys = CONS(CONS(from_cstring(key), ecl_make_integer(val)), l_keys); }
l_enums = CONS(cl_nreverse(l_keys), l_enums); }}
l_enums = CONS(l_class, cl_nreverse(l_enums));
return l_enums; }}
error_msg("QENUMS", LIST2(l_class, l_name));
return ECL_NIL; }
cl_object qapp() {
/// args: ()
/// Convenience function returning <code>qApp</code>.
cl_object l_ret = qt_object_from_name("QApplication", (void*)qApp);
ecl_return1(ecl_process_env(), l_ret); }
cl_object qprocess_events() {
/// args: ()
/// Convenience function to call <code>QApplication::processEvents()</code>.
QApplication::processEvents();
ecl_return1(ecl_process_env(), ECL_T); }
cl_object qexec2(cl_object l_milliseconds) {
/// args: (&optional milliseconds)
/// Convenience function to call <code>QApplication::exec()</code>.<br>Optionally pass the time in milliseconds after which <code>QEventLoop::exit()</code> will be called.<br>See also <code>qsleep</code>.
ecl_process_env()->nvalues = 1;
if(l_milliseconds != ECL_NIL) {
static QTimer* timer = 0;
if(!timer) {
timer = new QTimer;
EQL::eventLoop = new QEventLoop;
timer->setSingleShot(true);
QObject::connect(timer, QSIGNAL(timeout()), LObjects::eql, QSLOT(exitEventLoop())); }
timer->start(toInt(l_milliseconds));
EQL::eventLoop->exec();
return l_milliseconds; }
QCoreApplication::exit(); // prevent "The event loop is already running"
QApplication::exec();
return ECL_T; }
cl_object no_qexec() {
EQL::qexec = false;
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qexit() {
/// args: ()
/// Calls <code>QEventLoop::exit()</code>, in order to exit event processing after a call to <code>qexec</code> with a timeout.<br>Returns <code>T</code> if the event loop has effectively been exited.
ecl_process_env()->nvalues = 1;
if(EQL::eventLoop) {
if(EQL::eventLoop->isRunning()) {
EQL::eventLoop->exit();
return ECL_T; }}
return ECL_NIL; }
cl_object qstatic_meta_object(cl_object l_class) {
/// args: (class-name)
/// Returns the <code>::staticMetaObject</code> of the given class name.
/// (qstatic-meta-object "QEasingCurve")
ecl_process_env()->nvalues = 1;
if(ECL_STRINGP(l_class)) {
const QMetaObject* m = LObjects::staticMetaObject(toCString(l_class));
if(m) {
cl_object l_ret = qt_object_from_name("QMetaObject", (void*)m);
return l_ret; }}
error_msg("QSTATIC-META-OBJECT", LIST1(l_class));
return ECL_NIL; }
cl_object qload_ui(cl_object l_ui) {
/// args: (file-name)
/// Calls a custom <code>QUiLoader::load()</code> function, loading a UI file created by Qt Designer. Returns the top level widget of the UI.<br>Use <code>qfind-child</code> to retrieve the child widgets.
/// (qload-ui "my-fancy-gui.ui")
ecl_process_env()->nvalues = 1;
#ifdef OS_SAILFISH
error_msg("QLOAD-UI not available on Sailfish", LIST1(l_ui));
#else
QString ui(toQString(l_ui));
if(!ui.isEmpty()) {
if(!ui.endsWith(".ui")) {
ui.append(".ui"); }
UiLoader loader;
QFile file(ui);
if(file.open(QIODevice::ReadOnly)) {
QWidget* w = loader.load(&file);
file.close();
if(w) {
cl_object l_ret = qt_object_from_name(LObjects::vanillaQtSuperClassName(w->metaObject()),
w,
w->property("EQL.unique").toUInt());
return l_ret; }}}
error_msg("QLOAD-UI", LIST1(l_ui));
#endif
return ECL_NIL; }
cl_object qfind_child(cl_object l_obj, cl_object l_name) {
/// args: (object object-name)
/// Calls <code>QObject::findChild&lt;QObject*&gt;()</code>.<br>Can be used to get the child objects of any Qt object (typically from a UI, see <code>qload-ui</code>), identified by <code>QObject::objectName()</code>.
/// (qfind-child *main* "editor")
ecl_process_env()->nvalues = 1;
QString name(toQString(l_name));
if(!name.isEmpty()) {
QtObject o = toQtObject(l_obj);
if(o.isQObject()) {
QObject* obj = ((QObject*)o.pointer)->findChild<QObject*>(name);
if(obj) {
cl_object l_ret = qt_object_from_name(LObjects::vanillaQtSuperClassName(obj->metaObject()),
obj,
obj->property("EQL.unique").toUInt());
return l_ret; }}}
error_msg("QFIND-CHILD", LIST2(l_obj, l_name));
return ECL_NIL; }
cl_object qfind_children2(cl_object l_obj, cl_object l_name, cl_object l_class) {
/// args: (object &optional object-name class-name)
/// Calls <code>QObject::findChildren&lt;QObject*&gt;()</code>, returning a list of all child objects matching <code>object-name</code> and <code>class-name</code>.<br>Omitting the <code>&optional</code> arguments will find all children, recursively.
/// (qfind-children *qt-main* nil "LightWidget") ; see Qt_EQL example
ecl_process_env()->nvalues = 1;
QString objectName(toQString(l_name));
QByteArray className(toCString(l_class));
QtObject o = toQtObject(l_obj);
if(o.isQObject()) {
QObjectList children = ((QObject*)o.pointer)->findChildren<QObject*>(objectName);
cl_object l_children = ECL_NIL;
Q_FOREACH(QObject* child, children) {
QByteArray className2(child->metaObject()->className());
QByteArray className3(LObjects::vanillaQtSuperClassName(child->metaObject()));
if(className.isEmpty() ||
(className == className2) ||
(className == className3)) {
l_children = CONS(qt_object_from_name(className3, child, child->property("EQL.unique").toUInt()),
l_children); }}
l_children = cl_nreverse(l_children);
return l_children; }
error_msg("QFIND-CHILDREN", LIST3(l_obj, l_name, l_class));
return ECL_NIL; }
cl_object qui_class2(cl_object l_ui, cl_object l_name) {
/// args: (file-name &optional object-name)
/// Finds the class name for the given user-defined object name in the given UI file.<br>Omitting the object name will return the top level class name of the UI.
/// (qui-class "examples/data/main-window.ui" "editor") ; returns "QTextEdit"
ecl_process_env()->nvalues = 1;
QString ui(toQString(l_ui));
QString name(toQString(l_name));
if(!ui.isEmpty()) {
if(!ui.endsWith(".ui")) {
ui.append(".ui"); }
bool main = name.isEmpty();
QFile file(ui);
QString className;
if(file.open(QIODevice::ReadOnly)) {
QXmlStreamReader reader(&file);
while(!reader.atEnd()) {
reader.readNext();
if(reader.isStartElement()) {
QStringRef el(reader.name());
if("widget" == el) {
if(main) {
className = reader.attributes().value("class").toString();
break; }
else if(name == reader.attributes().value("name")) {
className = reader.attributes().value("class").toString();
break; }
main = false; }
else if("action" == el) {
if(name == reader.attributes().value("name")) {
className = "QAction";
break; }}
else if("actiongroup" == el) {
if(name == reader.attributes().value("name")) {
className = "QActionGroup";
break; }}
else if("layout" == el) {
if(name == reader.attributes().value("name")) {
className = reader.attributes().value("class").toString();
break; }}}}
if(!className.isEmpty()) {
cl_object l_ret = from_qstring(className);
return l_ret; }}}
error_msg("QUI-CLASS", LIST2(l_ui, l_name));
return ECL_NIL; }
cl_object qui_names(cl_object l_ui) {
/// args: (file-name)
/// Finds all user-defined object names in the given UI file.
/// (qui-names "examples/data/main-window.ui")
ecl_process_env()->nvalues = 1;
QString ui(toQString(l_ui));
if(!ui.isEmpty()) {
if(!ui.endsWith(".ui")) {
ui.append(".ui"); }
QFile file(ui);
if(file.open(QIODevice::ReadOnly)) {
QStringList names;
QXmlStreamReader reader(&file);
while(!reader.atEnd()) {
reader.readNext();
if(reader.isStartElement()) {
QStringRef el(reader.name());
if(("widget" == el) ||
("action" == el) ||
("actiongroup" == el) ||
("layout" == el)) {
QString name(reader.attributes().value("name").toString());
if(!name.isEmpty()) {
names << name; }}}}
names.sort();
cl_object l_ret = from_qstringlist(names);
return l_ret; }}
error_msg("QUI-NAMES", LIST1(l_ui));
return ECL_NIL; }
cl_object qsuper_class_name(cl_object l_name) {
/// args: (name)
/// Returns the super class of an object name, or <code>NIL</code> if the class doesn't inherit another Qt class.<br>Returns <code>T</code> as second return value for successful calls.
/// (qsuper-class-name "QGraphicsLineItem")
if(ECL_STRINGP(l_name)) {
bool found = false;
QByteArray super = superClassName(toCString(l_name), &found);
if(found) {
cl_object l_ret1 = super.isEmpty() ? ECL_NIL : from_cstring(super);
ecl_return2(ecl_process_env(), l_ret1, ECL_T); }}
error_msg("QSUPER-CLASS-NAME", LIST1(l_name));
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qsingle_shot2(cl_object l_msec, cl_object l_fun) {
/// args: (milliseconds function)
/// A single shot timer similar to <code>QTimer::singleShot()</code>.
/// (qsingle-shot 1000 'one-second-later)
///
/// (let ((ms 500))
/// &nbsp;&nbsp;(qsingle-shot ms (lambda () (qmsg ms))))
ecl_process_env()->nvalues = 1;
if(l_fun != ECL_NIL) {
new SingleShot(toInt(l_msec), l_fun); // see "delete this;" in "single_shot.h"
return l_msec; }
error_msg("QSINGLE-SHOT", LIST2(l_msec, l_fun));
return ECL_NIL; }
cl_object qok() {
/// args: ()
/// Needed to get the boolean <b>ok</b> value in cases like this:
/// (! "getFont(bool*)" "QFontDialog" nil)
///
/// (|getFont.QFontDialog| nil) ; NIL needed for &lt;bool*&gt;
cl_object l_ret = _ok_ ? ECL_T : ECL_NIL;
ecl_return1(ecl_process_env(), l_ret); }
cl_object qid(cl_object l_class) {
/// args: (name)
/// Returns the internally used ID of the object name. Non QObject classes have negative ids.
/// (qid "QWidget")
ecl_process_env()->nvalues = 1;
if(ECL_STRINGP(l_class)) {
int id = classId(l_class);
if(id) {
cl_object l_ret = ecl_make_fixnum(id);
return l_ret; }}
// no error message (testing for a supported Qt class)
return ECL_NIL; }
cl_object qvariant_equal2(cl_object l_var1, cl_object l_var2) {
// for internal use only (use QEQL instead, which will call this function for QVariants)
ecl_process_env()->nvalues = 1;
QtObject var1 = toQtObject(l_var1);
QtObject var2 = toQtObject(l_var2);
int id_var = -LObjects::n_names.value("QVariant", 0);
if((var1.id == id_var) && (var2.id == id_var)) {
QVariant* vp1 = (QVariant*)var1.pointer;
QVariant* vp2 = (QVariant*)var2.pointer;
cl_object l_ret = (*vp1 == *vp2) ? ECL_T : ECL_NIL; // QVariant::operator==
return l_ret; }
return ECL_NIL; }
cl_object qversion() {
/// args: ()
/// Returns the EQL version number as "&lt;year&gt;.&lt;month&gt;.&lt;counter&gt;".<br>The second return value is the Qt version as returned by <code>qVersion()</code>.
cl_object l_ret1 = from_cstring(EQL::version);
cl_object l_ret2 = from_cstring(qVersion());
ecl_return2(ecl_process_env(), l_ret1, l_ret2); }
cl_object qrun_on_ui_thread2(cl_object l_function_or_closure, cl_object l_blocking) {
/// args: (function &optional (blocking t))
/// alias: qrun
/// Runs <code>function</code> on the UI thread while (by default) blocking the calling thread (if called from main thread, <code>function</code> will simply be called directly).<br>This is needed to run GUI code from ECL threads other than the main thread.<br>Returns <code>T</code> on success.<br><br>There are 2 reasons to always wrap any EQL function like this, if called from another ECL thread:<ul><li>Qt UI methods always need to run on the UI thread<li>EQL functions are not designed to be reentrant (not needed for UI code)</ul>See also macro <code>qrun*</code>.
/// (qrun 'update-view-data)
ecl_process_env()->nvalues = 1;
if(l_function_or_closure != ECL_NIL) {
QObject o;
if(o.thread() == QApplication::instance()->thread()) {
// direct call
LObjects::eql->runOnUiThread(l_function_or_closure);
return ECL_T; }
else {
// queued call in main event loop (GUI thread)
QMetaObject::invokeMethod(LObjects::eql,
"runOnUiThread",
(l_blocking != ECL_NIL) ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
Q_ARG(void*, l_function_or_closure));
return ECL_T; }}
error_msg("QRUN-ON-UI-THREAD", LIST1(l_function_or_closure));
return ECL_NIL; }
cl_object qlog2(cl_object l_msg) {
// for android logging only; see 'lisp/ini.lisp::qlog' and 'eql.cpp::logMessageHandler'
qDebug() << toQString(l_msg);
ecl_return1(ecl_process_env(), ECL_NIL); }
QVariantList lispToQVariantList(cl_object);
static QVariant lispToQVariant(cl_object l_arg) {
// helper for lispToQVariantList()
QVariant var;
if(cl_integerp(l_arg) == ECL_T) { // int
var = QVariant(toInt(l_arg)); }
else if(cl_floatp(l_arg) == ECL_T) { // double
var = QVariant(toFloat<double>(l_arg)); }
else if(cl_stringp(l_arg) == ECL_T) { // string
var = QVariant(toQString(l_arg)); }
else if(l_arg == ECL_T) { // true
var = QVariant(true); }
else if(l_arg == ECL_NIL) { // false
var = QVariant(false); }
else if(cl_listp(l_arg) == ECL_T) { // list
var = QVariant::fromValue(lispToQVariantList(l_arg)); }
else { // default: undefined
var = QVariant(); }
return var; }
QVariantList lispToQVariantList(cl_object l_list) {
// helper for QJS_CALL
// converts (nested) Lisp lists to (nested) QVariant lists
QVariantList l;
if(ECL_LISTP(l_list)) {
cl_object l_do_list = l_list;
for(cl_object l_do_list = l_list; l_do_list != ECL_NIL; l_do_list = cl_cdr(l_do_list)) {
cl_object l_el = cl_car(l_do_list);
l << lispToQVariant(l_el); }}
return l; }
cl_object qjs_call(cl_object l_item, cl_object l_name, cl_object l_args) {
// direct, fast JS calls, see 'qml-lisp' in QML examples
// max. 10 arguments
// supported argument types: T, NIL, INTEGER, FLOAT, STRING, (nested) LIST of mentioned arguments
ecl_process_env()->nvalues = 1;
const int MAX = 10;
QVariant arg[MAX];
QGenericArgument genA[MAX];
const char* v = "QVariant";
int i = 0;
for(cl_object l_do_list = l_args; l_do_list != ECL_NIL; l_do_list = cl_cdr(l_do_list), i++) {
cl_object l_el = cl_car(l_do_list);
arg[i] = lispToQVariant(l_el);
genA[i] = QGenericArgument(v, &arg[i]); }
QGenericArgument null;
for(; i < MAX; i++) {
genA[i] = null; }
QtObject o = toQtObject(l_item);
QByteArray name(toCString(l_name));
if(o.isQObject() && o.pointer && !name.isEmpty()) {
QVariant ret;
QGenericReturnArgument genR(v, &ret);
QMetaObject::invokeMethod((QObject*)o.pointer, name, genR,
genA[0], genA[1], genA[2], genA[3], genA[4], genA[5], genA[6], genA[7], genA[8], genA[9]);
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
cl_object l_ret = from_qvariant_value(ret);
EQL::return_value_p = return_value_p;
return l_ret; }
error_msg("QJS-CALL", LIST3(l_item, l_name, l_args));
return ECL_NIL; }
// *** QML ***
cl_object qml_get2(cl_object l_item, cl_object l_name) {
QtObject o = toQtObject(l_item);
QByteArray name = toCString(l_name);
if(o.isQObject() && o.pointer && !name.isEmpty()) {
QObject* qobject = (QObject*)o.pointer;
QQmlProperty property(qobject, name);
if(property.isValid()) {
bool return_value_p = EQL::return_value_p;
EQL::return_value_p = true;
cl_object l_val = from_qvariant_value(property.read());
EQL::return_value_p = return_value_p;
ecl_return2(ecl_process_env(), l_val, ECL_T); }}
error_msg("QML-GET", LIST2(l_item, l_name));
ecl_return1(ecl_process_env(), ECL_NIL); }
cl_object qml_set2(cl_object l_item, cl_object l_name, cl_object l_value) {
ecl_process_env()->nvalues = 1;
QtObject o = toQtObject(l_item);
QByteArray name = toCString(l_name);
if(o.isQObject() && o.pointer && !name.isEmpty()) {
QObject* qobject = (QObject*)o.pointer;
QQmlProperty property(qobject, name);
if(property.isValid()) {
QByteArray type(property.propertyTypeName());
if(type.contains(':')) {
type = "int"; }
return property.write(toQVariant(l_value, type)) ? ECL_T : ECL_NIL; }}
error_msg("QML-SET", LIST3(l_item, l_name, l_value));
return ECL_NIL; }
// *** special extensions ***
//
// Contributed by Mark Cox, please see "LICENSE-MAKE-QIMAGE.txt"
//
cl_object make_qimage_dangerous(cl_object l_vector, cl_object l_width, cl_object l_height, cl_object l_bytes_per_line, cl_object l_format) {
ecl_process_env()->nvalues = 1;
// make sure all the input data is of the correct type.
if (!ECL_VECTORP(l_vector) || !ECL_FIXNUMP(l_width) || !ECL_FIXNUMP(l_height) || !ECL_FIXNUMP(l_bytes_per_line) || !ECL_FIXNUMP(l_format)) {
error_msg("MAKE-QIMAGE", LIST5(l_vector, l_width, l_height, l_bytes_per_line, l_format));
return ECL_NIL; }
ecl_vector *v = &l_vector->vector;
switch (v->elttype) {
case aet_bit:
case aet_b8:
case aet_b16:
case aet_b32:
break;
default:
error_msg("MAKE-QIMAGE", LIST5(l_vector, l_width, l_height, l_bytes_per_line, l_format));
return ECL_NIL; }
int width = toInt<int>(l_width);
int height = toInt<int>(l_height);
int bytes_per_line = toInt<int>(l_bytes_per_line);
QImage::Format image_format = (QImage::Format)toInt<int>(l_format);
QImage *image = new QImage(width, height, image_format);
Q_ASSERT(image->bytesPerLine() >= bytes_per_line);
uint8_t *current = v->self.b8;
for (int row = 0; row < height; row++) {
uint8_t *destination = (uint8_t *)image->scanLine(row);
std::copy(current, current + bytes_per_line, destination);
current += bytes_per_line; }
cl_object l_image = qt_object_from_name("QImage", (void*)image); // assign return value to avoid erroneous GC
return l_image; }
QT_END_NAMESPACE