comment out unused code
[lqt.git] / old_bindings / script / lqt.cpp
blob194d45dfe8f946f51a23de36bc744b3101e116d9
1 /*
2 * Copyright (c) 2007 Mauro Iazzi
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "lqt.hpp"
28 #include <cstring>
29 #include <QVariant>
30 #include <QPointer>
31 #include <QMetaObject>
32 #include <QMetaProperty>
33 #include <QMetaType>
34 #include <QDebug>
35 #include <QGenericArgument>
36 #include <QPointer>
38 #ifdef QOBJECT_HANDLER
39 static int lqt_handler__gc (lua_State *L);
40 #endif // QOBJECT_HANDLER
42 static int lqt_qpointer__gc (lua_State *L);
43 static int method_index (const QMetaObject *M, QByteArray name, int start = 0);
45 // #define luaL_checkqobject(L, index) (*(QObject**)luaL_checkudata(L, index, QOBJECT_METATABLE))
46 //
47 // int lua_pushqvariant (lua_State *L, QVariant *V);
48 // QVariant lua_toqvariant (lua_State *L, int index);
50 static int lua_isint (lua_State *L, int index) {
51 int i = lua_tointeger(L, index);
52 double d = lua_tonumber(L, index);
53 return i==d;
56 static bool signal_slot_names (QObject *obj, QByteArray& name) {
57 const QMetaObject *M = NULL;
58 int index = -1;
60 name = QMetaObject::normalizedSignature(name);
62 M = obj->metaObject();
63 index = M->indexOfMethod(name);
64 if (index == -1) {
65 return false;
67 switch (M->method(index).methodType()) {
68 case QMetaMethod::Signal:
69 name.prepend('2');
70 break;
71 case QMetaMethod::Slot:
72 name.prepend('1');
73 break;
74 default:
75 return false;
76 break;
78 return true;
81 int lqt_connect (lua_State *L) {
83 QObject *obj1 = luaL_checkqobject(L, 1);
84 QByteArray func1 = QMetaObject::normalizedSignature(luaL_checkstring(L, 2));
85 QObject *obj2 = luaL_checkqobject(L, 3);
86 QByteArray func2 = QMetaObject::normalizedSignature(luaL_checkstring(L, 4));
87 // check for QObjects validity
89 const QMetaObject *M1 = obj1->metaObject();
90 const QMetaObject *M2 = obj2->metaObject();
91 int index1 = M1->indexOfMethod(func1);
92 int index2 = M2->indexOfMethod(func2);
94 if ( index1!=-1 && index2!=-1 ) {
95 // nothing misses
96 } else if ( index1!=-1 && index2==-1 ) {
97 // slot is missing
98 for (index2 = method_index(M2, func2, 0);index2!=-1;index2=method_index(M2, func2, index2+1)) {
99 if ( (M2->method(index2).methodType()==QMetaMethod::Signal ||
100 M2->method(index2).methodType()==QMetaMethod::Slot ) &&
101 QMetaObject::checkConnectArgs(M2->method(index2).signature(), func1))
102 break;
104 if (index2==-1) qDebug() << "no matching slot of name" << func2 << "for signal" << func1;
105 else func2 = M2->method(index2).signature();
106 // slot has been filled at best
107 } else if ( index1==-1 && index2!=-1 ) {
108 // signal is missing
109 for (index1 = method_index(M1, func1, 0);index1!=-1;index1=method_index(M1, func1, index1+1)) {
110 if (M1->method(index1).methodType()==QMetaMethod::Signal &&
111 QMetaObject::checkConnectArgs(M1->method(index1).signature(), func2))
112 break;
114 if (index1==-1) qDebug() << "no matching signal of name" << func1 << "for slot" << func2;
115 else func1 = M1->method(index1).signature();
116 // signal has been filled at best
117 } else if ( index1==-1 && index2==-1 ) {
120 signal_slot_names(obj1, func1);
121 signal_slot_names(obj2, func2);
123 // if (!signal_slot_names(obj1, func1)) {
125 // if (!signal_slot_names(obj2, func2)) {
126 // } else {
127 // // find if a signal has same signature of slot
128 // int m1 = -1;
129 // for (m1 = method_index(M1, func1, 0);m1!=-1;m1=method_index(M1, func1, m1+1)) {
130 // if (M1->method(m1).methodType()==QMetaMethod::Signal &&
131 // QMetaObject::checkConnectArgs(M1->method(m1).signature(), func2))
132 // break;
133 // }
134 // if (m1==-1) qDebug() << "no matching signal of name" << func1 << "for slot" << func2;
135 // }
137 // } else {
138 // if (!signal_slot_names(obj2, func2)) {
139 // // find if a slot has same signature of signal
140 // int m2 = -1;
141 // for (m2 = method_index(M2, func2, 0);m2!=-1;m2=method_index(M2, func2, m2+1)) {
142 // qDebug() << M2->method(m2).signature() << func1;
143 // if ( (M2->method(m2).methodType()==QMetaMethod::Signal ||
144 // M2->method(m2).methodType()==QMetaMethod::Slot ) &&
145 // QMetaObject::checkConnectArgs(M2->method(m2).signature(), func1))
146 // break;
147 // }
148 // if (m2==-1) qDebug() << "no matching slot of name" << func2 << "for signal" << func1;
149 // } else {
150 // }
151 // }
153 qDebug() << "trying to connect signal" << func1 << "to slot" << func2;
154 lua_pushboolean(L, QObject::connect(obj1, func1, obj2, func2));
156 return 1;
159 int lqt_disconnect (lua_State *L) {
161 QObject *obj1 = luaL_checkqobject(L, 1);
162 QByteArray func1= luaL_checkstring(L, 2);
163 QObject *obj2 = luaL_checkqobject(L, 3);
164 QByteArray func2= luaL_checkstring(L, 4);
165 // check fo QObjects validity
167 if (!signal_slot_names(obj1, func1)) {
168 // TODO: handle method missing
170 if (!signal_slot_names(obj2, func2)) {
171 // TODO: handle method missing
174 lua_pushboolean(L, QObject::disconnect(obj1, func1, obj2, func2));
176 return 1;
179 static void method_see (const QMetaObject *M) {
180 if (M->superClass()) method_see(M->superClass());
181 qDebug() << M->className() << "methods:";
182 for (int m=0;m<M->methodCount();m++) {
183 qDebug() << "" << M->method(m).typeName() << M->method(m).signature();
187 int methods_of (lua_State *L) {
189 QObject *Q = luaL_checkqobject(L, 1);
191 if (Q) {
192 method_see(Q->metaObject());
195 return 0;
199 static int method_index (const QMetaObject *M, QByteArray name, int start) {
200 // method_see(M);
201 // qDebug() << name;
202 int ret = M->indexOfMethod(name);
204 if (ret >= start) { return ret; }
206 name.append('(');
207 // qDebug() << name;
209 for (int m=start;m<M->methodCount();m++) {
210 if ( QByteArray(M->method(m).signature()).startsWith(name) ) {
211 ret = m;
212 break;
215 return ret;
218 // void delete_genericret (int type, void *data) {
219 // QMetaType::destroy(type, data);
220 // return;
221 // }
223 // QGenericReturnArgument lua_togenericret (int type, void **data) {
224 // QGenericReturnArgument ret = QGenericReturnArgument();
225 // *data = NULL;
226 // *data = QMetaType::construct(type);
227 // if (*data) ret = QGenericReturnArgument(QMetaType::typeName(type), *data);
228 // return ret;
229 // }
232 // void delete_genericarg (lua_State *L, int index, void *data) {
233 // if (!data) return;
234 // QVariant var = lua_toqvariant(L, index);
235 // QMetaType::destroy(var.type(), data);
236 // return;
237 // }
239 #if 0
240 // TODO: should be done better (e.g. reentrant)
241 #define HANDLE_CASE_OF(T) case (QVariant:: T): { \
242 static typeof(V.to##T ()) my##T = V.to##T (); return &my##T; \
243 } break
244 static const void *data_copy(const QVariant& V, int t) {
245 switch (t) {
246 HANDLE_CASE_OF(Bool);
247 HANDLE_CASE_OF(Int);
248 HANDLE_CASE_OF(Double);
249 HANDLE_CASE_OF(String);
250 default:
251 break;
253 return (const void*)NULL;
255 #undef HANDLE_CASE_OF
256 #endif // 0
258 // QGenericArgument lua_togenericarg (lua_State *L, int index, void **data) {
259 // // qDebug() << "passing QVariant";
260 // QVariant var = lua_toqvariant(L, index);
261 // *data = QMetaType::construct(var.type(), var.data());
262 // QGenericArgument ret = QGenericArgument(var.typeName(), *data);
263 // return ret;
264 // }
266 static int lqt_invoke (lua_State *L) {
267 QVariant qvargs[10];
268 QGenericArgument args[10];
269 QGenericReturnArgument ret;
270 QVariant qvret;
271 // void *args_data[10];
272 // void *ret_data;
273 // int ret_type = -1;
275 QObject *Q = luaL_checkqobject(L, 1);
276 const QMetaObject *M = Q->metaObject();
278 QByteArray method = luaL_checkstring(L, lua_upvalueindex(1));
280 // ret_type = QMetaType::type(luaL_checkstring(L, lua_upvalueindex(2)));
282 // qDebug() << "calling" << method << "on object" << Q << "with return type" << QMetaType::typeName(ret_type);
283 // QMetaObject::invokeMethod(Q, "show");
285 for (int i=0;i<10;i++) {
286 qvargs[i] = lua_toqvariant(L, i+2);
287 // args[i] = lua_togenericarg(L, i+2, &args_data[i]);
289 // ret = lua_togenericret(ret_type, &ret_data);
292 // DONE: find for sure which method the user wants
293 int method_number = -1;
294 int method_result = -1;
295 for (int m = method_index(M, method, 0);m!=-1;m=method_index(M, method, m+1)) {
296 // qDebug() << "checking for match" << M->method(m).signature();
297 int corresponds = 0;
298 QList<QByteArray> sig = M->method(m).parameterTypes();
299 for (int i = 0; i < sig.size(); ++i) {
300 QVariant::Type this_type = QVariant::nameToType(sig.at(i));
301 // qDebug() << "checking for match" << sig.at(i) << qvargs[i].typeName();
302 if (qvargs[i].type()==this_type) {
303 corresponds += 21;
304 } else if (qvargs[i].canConvert(this_type)) {
305 corresponds += 20;
306 } else {
307 corresponds = -1;
308 break;
311 if (corresponds>method_result) {
312 method_number = m;
313 method_result = corresponds;
316 if (method_number!=-1) {
317 qDebug() << "I found best method is" << M->method(method_number).signature();
320 QMetaMethod mmeth = M->method(method_number);
321 QByteArray method_name = mmeth.signature();
322 method_name.truncate(method_name.indexOf('('));
323 // qDebug() << method_name;
324 QList<QByteArray> sig = mmeth.parameterTypes();
325 for (int i = 0; i < sig.size(); ++i) {
326 QVariant::Type this_type = QVariant::nameToType(sig.at(i));
327 qvargs[i].convert(this_type);
328 args[i] = QGenericArgument(qvargs[i].typeName(), qvargs[i].data());
332 qvret = QVariant(QVariant::nameToType(mmeth.typeName()));
333 ret = QGenericReturnArgument(qvret.typeName(), qvret.data());
334 qDebug() << "method call with ret=" << qvret;
336 if ( QMetaObject::invokeMethod(Q, method_name, Qt::AutoConnection, ret,
337 args[0], args[1], args[2], args[3], args[4],
338 args[5], args[6], args[7], args[8], args[9] ) )
340 qDebug() << "method call returned:" << qvret;
341 // QVariant r(ret_type, ret.data());
342 // qDebug() << "method call returned:" << r;
343 lua_pushqvariant(L, &qvret);
344 return 1;
345 } else {
346 qDebug() << "method call failed";
348 // for (int i = 0;i<10;i++) {
349 // delete_genericarg( L, i+2, args_data[i] );
350 // }
351 // delete_genericret( ret_type, ret_data );
352 qDebug() << "method call finished";
353 return 0;
356 // static int canConserve (const QVariant *V, QVariant::Type type) {
357 // QVariant copy(*V);
358 // QVariant::Type oldtype = copy.type();
359 // if (!copy.canConvert(type)) return 0;
360 // copy.convert(type);
361 // if (!copy.canConvert(oldtype)) return 0;
362 // copy.convert(oldtype);
363 // return (copy==*V)?1:0;
364 // }
367 static int lqt__index (lua_State *L) {
368 int index = -1;
369 const char *name = NULL;
370 size_t len = 0;
372 QObject **qp = (QObject**)luaL_checkudata(L, 1, QOBJECT_METATABLE);
373 QObject *Q = qp?*qp:NULL;
375 // TODO: find if object has method overwritten
377 name = lua_tolstring(L, 2, &len);
378 qDebug() << "requested member: " << lua_tostring(L, 2);
379 if (Q) {
380 const QMetaObject *M = Q->metaObject();
382 // for (int m=0;m<M->methodCount();m++){
383 // qDebug() << M->method(m).signature();
384 // }
386 if ( (index=method_index(M, name, len)) != -1 ) {
387 qDebug() << "method requested";
388 lua_pushvalue(L, 2);
389 // lua_pushstring(L, M->method(index).typeName());
390 lua_pushcclosure(L, lqt_invoke, 1);
391 return 1;
392 } else if ( (index=M->indexOfProperty(name)) != -1) {
393 QVariant value(M->property(index).read(Q));
394 return lua_pushqvariant(L, &value);
395 }/* else if ( (index=M->indexOfEnumerator(name)) != -1) {
396 return 0;
398 } else {
399 qDebug() << "NULL Object indexed";
400 lua_pushnil(L);
401 lua_pushstring(L, "QObject destroyed");
402 return 2;
404 return 0;
407 static int lqt__newindex (lua_State *L) {
408 int index = -1;
409 const char *name = NULL;
410 QVariant val;
411 size_t len = 0;
413 QObject **qp = (QObject**)luaL_checkudata(L, 1, QOBJECT_METATABLE);
414 QObject *Q = qp?*qp:NULL;
416 name = lua_tolstring(L, 2, &len);
417 val = lua_toqvariant(L, 3);
418 if (Q) {
419 const QMetaObject *M = Q->metaObject();
421 qDebug() << "setting property: " << name;
423 index=M->indexOfProperty(name);
424 if ( (index=M->indexOfProperty(name)) != -1) {
425 if (!M->property(index).write(Q, val)) {
426 lua_pushnil(L);
427 lua_pushstring(L, "could not set property ");
428 lua_pushstring(L, name);
429 lua_pushstring(L, " for object of type ");
430 lua_pushstring(L, M->className());
431 lua_concat(L, 4);
432 return 2;
434 } else {
435 // qDebug() << "NULL Object assigned";
436 lua_pushnil(L);
437 lua_pushstring(L, "QObject does not have this property");
438 return 2;
440 } else {
441 lua_pushnil(L);
442 lua_pushstring(L, "QObject destroyed");
443 return 2;
445 return 0;
448 static struct luaL_Reg lqt_metatable[] = {
449 { "__newindex", lqt__newindex },
450 { "__index", lqt__index },
451 { "__gc", lqt_qpointer__gc },
452 { NULL, NULL },
458 /************* HANDLER ****************/
460 static int lqt_qpointer__gc (lua_State *L) {
461 QPointer<QObject> *qp = (QPointer<QObject> *)lua_touserdata(L, 1);
462 lua_getfenv(L, 1);
463 if (lua_istable(L, -1)) {
464 lua_getfield(L, -1, "__gc");
465 if (lua_isfunction(L, -1)) {
466 qDebug() << "found a __gc";
467 lua_pushvalue(L, 1);
468 lua_call(L, 1, 0);
469 } else {
470 lua_pop(L, 1);
473 lua_pop(L, 1);
474 *qp = NULL; // hoping this unsets the guard by Qt
475 // qDebug() << "Garbage collecting qp =" << qp << ", *qp =" << *qp;
476 // delete qp;
477 return 0;
481 * This is __gc for the handler, which is not managed by Qt
484 #ifdef QOBJECT_HANDLER
485 static int lqt_handler__gc (lua_State *L) {
486 lua_getfield(L, LUA_REGISTRYINDEX, QOBJECT_HANDLER);
487 QObject **qp1 = (QObject**)lua_touserdata(L, 1);
488 QObject **qp2 = (QObject**)lua_touserdata(L, -1);
489 if (qp1==qp2) {
490 delete *qp1;
491 *qp1 = NULL;
492 qDebug() << "destroying handler";
494 return 0;
497 void QLuaHandler::destroyed (QObject * obj) {
498 luaL_checkstack(L, 2, "Cannot grow stack to destroy QObject");
499 lua_pushlightuserdata(L, obj);
500 lua_gettable(L, LUA_REGISTRYINDEX);
501 QObject **op = (QObject**)lua_touserdata(L, -1);
502 qDebug() << "voiding object: " << *op;
503 lua_pushlightuserdata(L, obj);
504 lua_pushnil(L);
505 lua_settable(L, LUA_REGISTRYINDEX);
506 *op = NULL;
507 lua_pop(L, 1);
509 #endif // QOBJECT_HANDLER
511 /************* STACK FUNCTIONS ****************/
513 int lua_pushqobject (lua_State *L, QObject *Q) {
514 // QPointer<QObject> obj = Q;
515 int ot = lua_gettop(L); /* old stack top */
516 // qDebug() << "creating object: " << Q;
518 // DONE: check stack
519 luaL_checkstack(L, 3, "Cannot grow stack to push QObject");
523 * if we already have it don't rebuild
525 // lua_pushlightuserdata(L, Q);
526 // lua_gettable(L, LUA_REGISTRYINDEX);
527 // if (lua_isqobject(L, -1)) {
528 // return 1;
529 // }
530 // lua_pop(L, 1);
533 * we don't have it: let's create.
534 * push the new userdata (QObject*)
536 QPointer<QObject> *op = (QPointer<QObject> *)lua_newuserdata(L, sizeof(QPointer<QObject>));
537 *op = NULL; /* if we fail later, do not leave invalid pointers */
538 // qDebug() << "Creating qp =" << op << ", *qp =" << *op;
539 /* insert in register indexed by its content */
540 // lua_pushlightuserdata(L, Q);
541 // lua_pushvalue(L, ot+1);
542 // lua_settable(L, LUA_REGISTRYINDEX);
544 /* get the metatable */
545 if (luaL_newmetatable(L, QOBJECT_METATABLE)) {
546 /* create metatable if it did not exist */
547 // DONE: check validity of metatable
548 luaL_register(L, NULL, lqt_metatable);
549 lua_pushvalue(L, -1);
550 lua_setmetatable(L, -2);/* it is its own metatable */
551 lua_pushvalue(L, -1);
552 lua_pushstring(L, QOBJECT_METATABLE);
553 lua_settable(L, LUA_REGISTRYINDEX);
555 lua_setmetatable(L, -2);
557 #ifdef QOBJECT_HANDLER
558 lua_getfield(L, LUA_REGISTRYINDEX, QOBJECT_HANDLER);
559 // DONE: check presence of handler
560 if (lua_isnil(L, -1)) {
561 lua_pop(L, 1);
562 QLuaHandler **qhp = (QLuaHandler **)lua_newuserdata(L, sizeof(*qhp));
563 lua_newtable(L);
564 lua_pushcfunction(L, lqt_handler__gc);
565 lua_setfield(L, -2, "__gc");
566 lua_setmetatable(L, -2);
568 lua_pushvalue(L, -1);
569 lua_setfield(L, LUA_REGISTRYINDEX, QOBJECT_HANDLER);
570 *qhp = new QLuaHandler(L);
572 QObject *H = *(QObject**)lua_touserdata(L, -1);
573 lua_pop(L, 1);
574 #endif // QOBJECT_HANDLER
576 *op = Q;
578 #ifdef QOBJECT_HANDLER
579 if (Q) QObject::connect( Q, SIGNAL(destroyed(QObject*)), H, SLOT(destroyed(QObject*)) );
580 #endif // QOBJECT_HANDLER
582 return 1;
585 int lua_isqobject (lua_State *L, int index) {
586 int ret = 0;
587 if (lua_isuserdata(L, index)) {
588 lua_getmetatable(L, index);
589 luaL_getmetatable(L, QOBJECT_METATABLE);
590 ret = lua_rawequal(L, -1, -2);
591 lua_pop(L, 2);
593 return ret;
596 QObject *lua_toqobject (lua_State *L, int index) {
597 if (lua_isqobject(L, index)) {
598 QPointer<QObject> *qp = (QPointer<QObject> *)lua_touserdata(L, index);
599 return *qp;
601 return NULL;
604 QVariant lua_toqvariant (lua_State *L, int index) {
605 QVariant ret;
606 switch (lua_type(L, index)) {
607 case LUA_TNUMBER:
608 if (lua_isint(L, index)) {
609 // qDebug() << "getting int" << lua_tointeger(L, index);
610 ret = QVariant((int)lua_tointeger(L, index));
611 } else {
612 // qDebug() << "getting double" << lua_tonumber(L, index);
613 ret = QVariant(lua_tonumber(L, index));
615 break;
616 case LUA_TBOOLEAN:
617 // qDebug() << "getting bool" << (bool)lua_toboolean(L, index);
618 ret = QVariant((bool)lua_toboolean(L, index));
619 break;
620 case LUA_TSTRING:
621 // qDebug() << "getting string" << lua_tostring(L, index);
622 ret = QVariant(lua_tostring(L, index));
623 break;
624 case LUA_TUSERDATA:
625 lua_getmetatable(L, index);
626 lua_gettable(L, LUA_REGISTRYINDEX);
627 // qDebug() << "getting userdata";
628 if (lua_isstring(L, -1)) {
629 int type = QMetaType::type(lua_tostring(L, -1));
630 lua_pop(L, 1);
631 const void *obj = (const void*)lua_touserdata(L, index);
632 // qDebug() << "getting userdata" << obj << "of type" << tname;
633 ret = QVariant(type, obj);
635 break;
636 break;
637 case LUA_TNONE:
638 case LUA_TNIL:
639 case LUA_TTABLE:
640 case LUA_TFUNCTION:
641 case LUA_TTHREAD:
642 case LUA_TLIGHTUSERDATA:
643 default:
644 break;
646 return ret;
649 int lua_pushqvariant (lua_State *L, QVariant *V) {
650 // qDebug() << "pushing val: " << *V;
651 switch (V->type()) {
652 case QVariant::Bool: lua_pushboolean(L, (int)V->toBool()); break;
653 case QVariant::Int: lua_pushinteger(L, V->toInt()); break;
654 case QVariant::LongLong: lua_pushinteger(L, V->toLongLong()); break;
655 case QVariant::UInt: lua_pushinteger(L, V->toUInt()); break;
656 case QVariant::ULongLong: lua_pushinteger(L, V->toULongLong()); break;
657 case QVariant::Double: lua_pushnumber (L, V->toDouble()); break;
658 case QVariant::String: lua_pushstring (L, (const char*)V->toString().toAscii().data()); break;
659 case QVariant::KeySequence: lua_pushstring (L, (const char*)V->toString().toAscii().data()); break;
660 case QVariant::Invalid:
661 lua_pushnil(L);
662 lua_pushstring(L, "invalid value can't be pushed");
663 return 2;
664 break;
665 default:
666 if (V->canConvert(QVariant::Bool)) {
667 lua_pushboolean(L, (int)V->toBool());
668 } else if (V->canConvert(QVariant::Double)) {
669 lua_pushnumber (L, V->toDouble());
670 } else if (V->canConvert(QVariant::Int)) {
671 lua_pushinteger(L, V->toInt());
672 } else if (V->canConvert(QVariant::String)) {
673 lua_pushstring (L, (const char*)V->toString().toAscii().data());
674 } else {
675 // lua_getfield(L, LUA_REGISTRYINDEX, V->typeName()); ...
676 lua_pushnil(L);
677 lua_pushstring(L, "QVariant type ");
678 lua_pushstring(L, V->typeName());
679 lua_pushstring(L, " can't be pushed");
680 lua_concat(L, 3);
681 return 2;
683 break;
685 return 1;