Results 1 to 3 of 3

Thread: QtScript Bindings Generator ScriptShell Event Binding

  1. #1
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QtScript Bindings Generator ScriptShell Event Binding

    Hi there!

    How can I call the native event handler when using the scriptshell binding of the qt script binding generator?

    I'm using the splendid qt script binding generator lab-project to make all qt classes fully scriptable. Through the scriptshells it allows binding a script function to otherwise inaccessible protected event handlers. In non script you would derive from the class to access these..

    Qt Code:
    1. scriptcode:
    2.  
    3. var a = new QWidget();
    4. a.setGeometry(50,50,200,100);
    5. a.show();
    6. a.event = function (event) {
    7. print(event.type().toString());
    8. };
    To copy to clipboard, switch view to plain text mode 

    This works perfectly, but it hides the native implementation. If you look into the generated scriptshell files of the generator:

    Qt Code:
    1. from: ..\com_trolltech_qt_gui\qtscriptshell_QWidget.cpp
    2.  
    3. bool QtScriptShell_QWidget::event(QEvent* arg__1)
    4. {
    5. QScriptValue _q_function = __qtscript_self.property("event");
    6. if (!_q_function.isFunction() || QTSCRIPT_IS_GENERATED_FUNCTION(_q_function)
    7. || (__qtscript_self.propertyFlags("event") & QScriptValue::QObjectMember)) {
    8. return QWidget::event(arg__1);
    9. } else {
    10. QScriptEngine *_q_engine = __qtscript_self.engine();
    11. return qscriptvalue_cast<bool >(_q_function.call(__qtscript_self,
    12. QScriptValueList()
    13. << qScriptValueFromValue(_q_engine, arg__1)));
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 
    So either the native or the script event handler is called. Now my question is, if I missed an obvious way to call the native event handler from script.

    If thats not possible I'm thinking of changing the scriptshell-generator-code (..\generator\shellimplgenerator.cpp ) to call the native handler for all events that have not been accepted inside the script-method. That's easy enough, but I want to know, if there is an out-of-the-box way.

    Thx!

    Johannes

  2. #2
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtScript Bindings Generator ScriptShell Event Binding

    Hey there!

    Here is what I came up with:

    I changed the scriptshellgenerator code so that the generated code looks like this:

    Qt Code:
    1. bool QtScriptShell_QWidget::event(QEvent* arg__1)
    2. {
    3. QScriptValue _q_function = __qtscript_self.property("event");
    4. if (!_q_function.isFunction() || QTSCRIPT_IS_GENERATED_FUNCTION(_q_function)
    5. || (__qtscript_self.propertyFlags("event") & QScriptValue::QObjectMember)) {
    6. return QWidget::event(arg__1);
    7. } else {
    8. QScriptEngine *_q_engine = __qtscript_self.engine();
    9. // callmode. first bit: 1:callcpp|0:don't call cpp
    10. // 2nd-bit: 1:returncpp|0:returnscript
    11. int _callmode = 3;
    12. QScriptValue _q_callmode = __qtscript_self.property("event_callmode");
    13. if (_q_callmode.isValid()) _callmode = _q_callmode.toInt32();
    14. if ((_callmode & 1) > 0) {
    15. bool resultcpp = QWidget::event(arg__1);
    16. bool resultscript = qscriptvalue_cast<bool >(_q_function.call(__qtscript_self,
    17. QScriptValueList()
    18. << qScriptValueFromValue(_q_engine, arg__1)));
    19. if ((_callmode & 2) > 0) {
    20. return resultcpp;
    21. } else {
    22. return resultscript;
    23. }
    24. } else {
    25. return qscriptvalue_cast<bool >(_q_function.call(__qtscript_self,
    26. QScriptValueList()
    27. << qScriptValueFromValue(_q_engine, arg__1)));
    28. }
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 
    instead of the above.. So the default behaviour is to call both. And to return the value of the c++ implementation. If you want another behaviour, you need to specifiy a value for <eventname>_callmode.

  3. #3
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtScript Bindings Generator ScriptShell Event Binding

    This is the ShellImplGenerator::write method in generator/shellimplgenerator.cpp which you need to change in the bindings generator.

    Qt Code:
    1. void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
    2. {
    3. if (FileOut::license)
    4. writeQtScriptQtBindingsLicense(s);
    5.  
    6. QString packName = meta_class->package().replace(".", "_");
    7.  
    8. priGenerator->addSource(packName, fileNameForClass(meta_class));
    9.  
    10. s << "#include \"qtscriptshell_" << meta_class->name() << ".h\"" << endl << endl;
    11.  
    12. if (!meta_class->generateShellClass())
    13. return;
    14.  
    15. s << "#include <QtScript/QScriptEngine>" << endl;
    16.  
    17. IncludeList list = meta_class->typeEntry()->extraIncludes();
    18. qSort(list.begin(), list.end(), include_less_than);
    19. foreach (const Include &inc, list) {
    20. if (inc.type == Include::TargetLangImport)
    21. continue;
    22.  
    23. s << "#include ";
    24. if (inc.type == Include::LocalPath)
    25. s << "\"";
    26. else
    27. s << "<";
    28.  
    29. s << inc.name;
    30.  
    31. if (inc.type == Include::LocalPath)
    32. s << "\"";
    33. else
    34. s << ">";
    35.  
    36. s << endl;
    37. }
    38. s << endl;
    39.  
    40. writeHelperCode(s, meta_class);
    41.  
    42. // find constructors
    43. AbstractMetaFunctionList ctors;
    44. ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
    45. | AbstractMetaClass::WasVisible
    46. | AbstractMetaClass::NotRemovedFromTargetLang);
    47. // find member functions
    48. AbstractMetaFunctionList functions = meta_class->queryFunctions(
    49. AbstractMetaClass:: VirtualFunctions | AbstractMetaClass::WasVisible
    50. | AbstractMetaClass::NotRemovedFromTargetLang
    51. );
    52.  
    53. // write metatype declarations
    54. {
    55. QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
    56. declareFunctionMetaTypes(s, functions, registeredTypeNames);
    57. s << endl;
    58. }
    59.  
    60. // write constructors
    61. foreach (const AbstractMetaFunction *ctor, ctors) {
    62. s << "QtScriptShell_" << meta_class->name() << "::";
    63. writeFunctionSignature(s, ctor, 0, QString(), Option(OriginalName | ShowStatic));
    64. s << endl;
    65. s << " : " << meta_class->qualifiedCppName() << "(";
    66. AbstractMetaArgumentList args = ctor->arguments();
    67. for (int i = 0; i < args.size(); ++i) {
    68. if (i > 0)
    69. s << ", ";
    70. s << args.at(i)->argumentName();
    71. }
    72. s << ")" << " {}" << endl << endl;
    73. }
    74.  
    75. // write destructor
    76. s << "QtScriptShell_" << meta_class->name() << "::"
    77. << "~QtScriptShell_" << meta_class->name() << "()";
    78. if (!meta_class->destructorException().isEmpty())
    79. s << " " << meta_class->destructorException();
    80. s << " {}" << endl << endl;
    81.  
    82. // write member functions
    83. for (int i = 0; i < functions.size(); ++i) {
    84. AbstractMetaFunction *fun = functions.at(i);
    85. writeFunctionSignature(s, fun, meta_class, QString(),
    86. Option(OriginalName | ShowStatic | UnderscoreSpaces),
    87. "QtScriptShell_");
    88. s << endl << "{" << endl;
    89. QString scriptFunctionName = fun->name();
    90. {
    91. QPropertySpec *read = 0;
    92. for (const AbstractMetaClass *cls = meta_class; !read && cls; cls = cls->baseClass())
    93. read = cls->propertySpecForRead(fun->name());
    94. if (read && (read->name() == fun->name())) {
    95. // use different name to avoid infinite recursion
    96. // ### not sure if this is the best solution though...
    97. scriptFunctionName.prepend("_qs_");
    98. }
    99. }
    100.  
    101. s << " QScriptValue _q_function = __qtscript_self.property(\""
    102. << scriptFunctionName << "\");" << endl;
    103. s << " if (!_q_function.isFunction() || QTSCRIPT_IS_GENERATED_FUNCTION(_q_function)" << endl
    104. << " || (__qtscript_self.propertyFlags(\"" << scriptFunctionName << "\") & QScriptValue::QObjectMember)) {" << endl;
    105.  
    106. AbstractMetaArgumentList args = fun->arguments();
    107. s << " ";
    108. if (fun->isAbstract()) {
    109. s << "qFatal(\"" << meta_class->name() << "::" << fun->name()
    110. << "() is abstract!\");" << endl;
    111. } else {
    112. // call the C++ implementation
    113. if (fun->type()) {
    114. s << "return ";
    115. }
    116. s << meta_class->qualifiedCppName() << "::" << fun->originalName() << "(";
    117. for (int i = 0; i < args.size(); ++i) {
    118. if (i > 0)
    119. s << ", ";
    120. s << args.at(i)->argumentName();
    121. }
    122. s << ");" << endl;
    123. }
    124.  
    125. s << " } else {" << endl;
    126.  
    127. // call the script function
    128. if (args.size() > 0)
    129. s << " QScriptEngine *_q_engine = __qtscript_self.engine();" << endl;
    130.  
    131. // NTS Addon
    132. if (!fun->isAbstract()) {
    133. s << " // callmode. first bit: 1:callcpp|0:don't call cpp" << endl;
    134. s << " // 2nd-bit: 1:returncpp|0:returnscript" << endl;
    135. s << " int _callmode = 3;" << endl;
    136. s << " QScriptValue _q_callmode = __qtscript_self.property(\""
    137. << scriptFunctionName << "_callmode\");" << endl;
    138. s << " if (_q_callmode.isValid()) _callmode = _q_callmode.toInt32();" << endl;
    139. s << " if ((_callmode & 1) > 0) {" << endl;
    140.  
    141. // First call the c++ implementation
    142. s << " ";
    143. if (fun->type()) {
    144. writeTypeInfo(s, fun->type());
    145. s << "resultcpp = ";
    146. }
    147. s << meta_class->qualifiedCppName() << "::" << fun->originalName() << "(";
    148. for (int i = 0; i < args.size(); ++i) {
    149. if (i > 0)
    150. s << ", ";
    151. s << args.at(i)->argumentName();
    152. }
    153. s << ");" << endl;
    154.  
    155. // Then call the script implementation
    156. s << " ";
    157. if (fun->type()) {
    158. writeTypeInfo(s, fun->type());
    159. s << "resultscript = qscriptvalue_cast<";
    160. writeTypeInfo(s, fun->type());
    161. s << ">(";
    162. }
    163. s << "_q_function.call(__qtscript_self";
    164. if (args.size() > 0) {
    165. s << "," << endl;
    166. s << " QScriptValueList()";
    167. int i = 0;
    168. for (int j = 0; j < args.size(); ++j) {
    169. if (fun->argumentRemoved(j+1))
    170. continue;
    171. s << endl << " << ";
    172. s << "qScriptValueFromValue(_q_engine, ";
    173. AbstractMetaType *atype = args.at(j)->type();
    174. QString asig = atype->cppSignature();
    175. bool constCastArg = asig.endsWith('*') && asig.startsWith("const ");
    176. if (constCastArg)
    177. s << "const_cast<" << asig.mid(6) << ">(";
    178. s << args.at(i)->argumentName() << ")";
    179. if (constCastArg)
    180. s << ")";
    181. ++i;
    182. }
    183. }
    184. s << ")";
    185. if (fun->type())
    186. s << ")";
    187. s << ";" << endl;
    188.  
    189. if (fun->type()) {
    190. // Decide which value to return
    191. s << " if ((_callmode & 2) > 0) {" << endl;
    192. s << " return resultcpp;" << endl;
    193. s << " } else {" << endl;
    194. s << " return resultscript;" << endl;
    195. s << " }"<< endl;
    196. }
    197.  
    198. s << " } else {" << endl;
    199. }
    200.  
    201. // only call the script implementation
    202. s << " ";
    203. if (fun->type()) {
    204. s << "return qscriptvalue_cast<";
    205. writeTypeInfo(s, fun->type());
    206. s << ">(";
    207. }
    208. s << "_q_function.call(__qtscript_self";
    209. if (args.size() > 0) {
    210. s << "," << endl;
    211. s << " QScriptValueList()";
    212. int i = 0;
    213. for (int j = 0; j < args.size(); ++j) {
    214. if (fun->argumentRemoved(j+1))
    215. continue;
    216. s << endl << " << ";
    217. s << "qScriptValueFromValue(_q_engine, ";
    218. AbstractMetaType *atype = args.at(j)->type();
    219. QString asig = atype->cppSignature();
    220. bool constCastArg = asig.endsWith('*') && asig.startsWith("const ");
    221. if (constCastArg)
    222. s << "const_cast<" << asig.mid(6) << ">(";
    223. s << args.at(i)->argumentName() << ")";
    224. if (constCastArg)
    225. s << ")";
    226. ++i;
    227. }
    228. }
    229. s << ")";
    230. if (fun->type())
    231. s << ")";
    232. s << ";" << endl;
    233.  
    234. if (!fun->isAbstract()) {
    235. s << " }" << endl;
    236. }
    237.  
    238. s << " }" << endl;
    239.  
    240. s << "}" << endl << endl;
    241. }
    242. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,

    Johannes

Similar Threads

  1. Replies: 0
    Last Post: 25th November 2009, 07:46
  2. QtScript Binding problem with QWidget
    By zack in forum Qt Programming
    Replies: 3
    Last Post: 17th February 2009, 09:38
  3. New Ada2005 language bindings to Qt 4.2
    By karlson in forum Qt-based Software
    Replies: 3
    Last Post: 7th September 2007, 20:47
  4. Random No Generator in C/C++
    By ankurjain in forum General Programming
    Replies: 1
    Last Post: 6th July 2006, 11:33

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.