diff generator/dgenerator.cpp @ 288:f9559a957be9 signals

new signals and slots implementation
author eldar
date Sun, 08 Nov 2009 19:28:01 +0000
parents 1f6923c8cba0
children 19498f420252
line wrap: on
line diff
--- a/generator/dgenerator.cpp	Sun Nov 08 19:20:53 2009 +0000
+++ b/generator/dgenerator.cpp	Sun Nov 08 19:28:01 2009 +0000
@@ -63,7 +63,7 @@
       m_recursive(0),
       m_isRecursive(false)
 {
-    excludedTypes << "long long" << "bool" << "int" << "QString" << "char" << "WId"
+    excludedTypes << "qint64" << "bool" << "int" << "QString" << "char" << "WId"
                   << "unsigned char" << "uint" << "double" << "short" << "float"
                   << "signed char" << "unsigned short" << "QBool" << "unsigned int"
                   << "Qt::HANDLE" << "QChar" << "java.lang.JObjectWrapper" << "void"
@@ -126,7 +126,7 @@
     QString constPrefix, constPostfix;
     if (d_type && d_type->isConstant() && dVersion == 2) {
         constPrefix = "const(";
-        constPostfix = ") ";
+        constPostfix = ")";
     }
 
     if (!d_type) {
@@ -230,7 +230,7 @@
     QString arg;
 
     AbstractMetaType *type = d_argument->type();
-    // if argument is "QString &" ref attribute needed
+    // qtd2 if argument is "QString &" ref attribute needed FIXME maybe we need this not only for QString, but for other Value types??
     if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString")
         arg = "ref ";
 
@@ -983,10 +983,7 @@
     if (!(d_function->isEmptyFunction() || d_function->isNormal() || d_function->isSignal()))
         option = Option(option | SkipReturnType);
     writeFunctionAttributes(s, d_function, included_attributes, excluded_attributes, option);
-/*
-    if(d_function->isSignal())
-        functionName += "_emit";
-*/
+
     s << functionName << "(";
     writeFunctionArguments(s, d_function, argument_count, option);
     s << ")";
@@ -1713,6 +1710,8 @@
 
     QString attr;
 
+//    return; // #TODO Don't need handlers for now. Restore in conversion functions later
+
     s << "// signal handlers" << endl;
     foreach(AbstractMetaFunction *signal, signal_funcs) {
         QString sigExternName = signalExternName(d_class, signal);
@@ -1771,7 +1770,7 @@
                 s << endl;
             }
 //            s << INDENT << "Stdout(\"" << d_class->name() << "\", \"" << signal->name() << "\").newline;" << endl;
-            s << INDENT << "d_object." << signal->name() << "_emit(";
+            s << INDENT << "//d_object." << signal->name() << "_emit(";
             for (int j = 0; j<sz; ++j) {
                 AbstractMetaArgument *argument = arguments.at(j);
                 QString arg_name = argument->indexedName();
@@ -1786,6 +1785,29 @@
     }
 }
 
+AbstractMetaFunctionList DGenerator::generatedClassFunctions(const AbstractMetaClass *d_class)
+{
+    AbstractMetaFunctionList r;
+    AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang();
+    for (int i=0; i<d_funcs.size(); ++i) {
+        AbstractMetaFunction *function = d_funcs.at(i);
+
+        // If a method in an interface class is modified to be private, this should
+        // not be present in the interface at all, only in the implementation.
+        if (d_class->isInterface()) {
+            uint includedAttributes = 0;
+            uint excludedAttributes = 0;
+            retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes);
+            if (includedAttributes & AbstractMetaAttributes::Private)
+                continue;
+        }
+
+        if (!notWrappedYet(function)) // qtd2
+            r += function;
+    }
+    return r;
+}
+
 void DGenerator::write(QTextStream &s, const AbstractMetaClass *d_class)
 {
     ReportHandler::debugSparse("Generating class: " + d_class->fullName());
@@ -1909,6 +1931,7 @@
           << "private import qt.qtd.Array;" << endl;
         if (d_class->isQObject()) {
             s << "public import qt.Signal;" << endl
+              << "public import qt.qtd.MOC;" << endl
               << "public import qt.core.QMetaObject;" << endl
               << "public import qt.qtd.Traits;" << endl;
 
@@ -2148,7 +2171,7 @@
     foreach (AbstractMetaEnum *d_enum, d_class->enums())
         writeEnumAlias(s, d_enum);
 
-    // Signals    
+    // Signals
     if (d_class->isQObject())
     {
         AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false);
@@ -2181,22 +2204,13 @@
 
     // Functions
     AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang();
-    for (int i=0; i<d_funcs.size(); ++i) {
-        AbstractMetaFunction *function = d_funcs.at(i);
-
-        // If a method in an interface class is modified to be private, this should
-        // not be present in the interface at all, only in the implementation.
-        if (d_class->isInterface()) {
-            uint includedAttributes = 0;
-            uint excludedAttributes = 0;
-            retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes);
-            if (includedAttributes & AbstractMetaAttributes::Private)
-                continue;
-        }
-
-        if (!notWrappedYet(function)) // qtd2
-            writeFunction(s, function);
-//        s << function->minimalSignature() << endl;
+    AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class);
+    for (int i=0; i<d_funcs_gen.size(); ++i) {
+        AbstractMetaFunction *function = d_funcs_gen.at(i);
+//        if(function->isSlot())
+//            writeSlot(s, function);
+          writeFunction(s, function);
+// qtd       s << function->minimalSignature() << endl;
     }
     if(d_class->isInterface())
         s << endl << INDENT << "public void* __ptr_" << d_class->name() << "();" << endl << endl;
@@ -2243,6 +2257,17 @@
     if (d_class->isQObject())
         writeQObjectFunctions(s, d_class);
 
+    // flag to mark the type of class (to use in templates to convert arguments)
+    if (d_class->baseClassName().isEmpty())
+    {
+        if (d_class->typeEntry()->isQObject())
+            s << INDENT << "public static enum __isQObjectType = true;" << endl << endl;
+        else if (d_class->typeEntry()->isObject())
+            s << INDENT << "public static enum __isObjectType = true;" << endl << endl;
+        else if (d_class->typeEntry()->isValue())
+            s << INDENT << "public static enum __isValueType = true;" << endl << endl;
+    }
+
     // Add dummy constructor for use when constructing subclasses
     if (!d_class->isNamespace() && !d_class->isInterface() && !fakeClass) {
         s << endl
@@ -2633,10 +2658,7 @@
 
 
     if (d_class->isQObject())
-    {
-      s << "private extern(C) void* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl
-        << "private extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" <<  endl << endl;
-    }
+        writeQObjectFreeFunctions(s, d_class);
 }
 
 void DGenerator::writeConversionFunction(QTextStream &s, const AbstractMetaClass *d_class)
@@ -2674,12 +2696,67 @@
     s << "}" << endl << endl;
 }
 
+void DGenerator::writeQObjectFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class)
+{
+    s << "private extern(C) QMetaObjectNative* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl
+      << "private extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" <<  endl << endl;
+
+  if (!d_class->isFinal())
+    s << "private extern(C) int qtd_" << d_class->name() << "_qt_metacall(void* __this_nativeId, QMetaObject.Call _c, int _id, void **_a);"
+      << "private extern(C) int qtd_" << d_class->name() << "_qt_metacall_dispatch(void *d_entity, QMetaObject.Call _c, int _id, void **_a) {"
+      << "    auto d_object = cast(" << d_class->name() << ") d_entity;"
+      << "    return d_object.qt_metacall(_c, _id, _a);"
+      << "}" << endl << endl;
+}
+
+void writeMetaMethodSignatures(QTextStream &s, const QString &var_name, AbstractMetaFunctionList meta_funcs)
+{
+    s << INDENT << "private static const string[] " << var_name << " = [";
+    {
+        Indentation indent(INDENT);
+        for (int i = 0; i < meta_funcs.size(); ++i)
+        {
+            if (i)
+                s << ", ";
+            int j = 0;
+            bool hasDefault = false;
+            do // need this to look for default arguments and generate extra signatures
+            {
+                if (i || j)
+                    s << ", ";
+                s << endl << INDENT << "    \"" << meta_funcs.at(i)->minimalSignature(j) << "\"";
+                AbstractMetaArgumentList args = meta_funcs.at(i)->arguments();
+                if(args.size() && j<args.size())
+                    hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty();
+                else
+                    hasDefault = false;
+                j++;
+            } while (hasDefault);
+        }
+    }
+    s << INDENT << "];" << endl << endl;
+}
+
 void DGenerator::writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *d_class)
 {
-    QString concreteArg;
+  AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class);
+  AbstractMetaFunctionList slot_funcs;
+  for (int i=0; i<d_funcs_gen.size(); ++i) {
+      AbstractMetaFunction *function = d_funcs_gen.at(i);
+      if(function->isSlot())
+          slot_funcs += function;
+  }
+  writeMetaMethodSignatures(s, "__slotSignatures", slot_funcs);
+
+  QString concreteArg;
     if (d_class->isAbstract())
         concreteArg += ", " + d_class->name() + "_ConcreteWrapper";
 
+  if (!d_class->isFinal())
+  s << "    int qt_metacall(QMetaObject.Call _c, int _id, void **_a) {" << endl
+    << "        return qtd_" << d_class->name() << "_qt_metacall(__nativeId, _c, _id, _a);" << endl
+    << "    }" << endl << endl;
+
   s << "    private static QMetaObject _staticMetaObject;" << endl
     << "    protected static void createStaticMetaObject() {" << endl
     << "        assert(!_staticMetaObject);" << endl
@@ -2695,6 +2772,7 @@
 
   s << "        _staticMetaObject = new QMetaObject(qtd_" << d_class->name() << "_staticMetaObject, base);"   << endl
     << "        _staticMetaObject.construct!(" << d_class->name() << concreteArg << ");" << endl
+    << "        _populateMetaInfo();" << endl
     << "    }" << endl << endl
 
     << "    QMetaObject metaObject() {" << endl
@@ -2711,7 +2789,64 @@
 
     << "    static void __createEntity(void* nativeId, void* dId) {" << endl
     << "        return qtd_" << d_class->name() << "_createEntity(nativeId, dId);" << endl
-    << "    }" << endl << endl;
+    << "    }" << endl << endl
+
+    << "    private static void _populateMetaInfo() {" << endl
+    << "        int index;" << endl << endl;
+
+  AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false);
+
+  int staticId = 0;
+  for (int i = 0; i < signal_funcs.size(); ++i)
+  {
+      int j = 0;
+      bool hasDefault = false;
+      do // need this to look for default arguments and generate extra signatures
+      {
+          AbstractMetaFunction *fn = signal_funcs.at(i);
+  s << "        index = _staticMetaObject.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl
+    << "        _staticMetaObject.addMethod(new QMetaSignal(signature!(\"" << fn->name() << "\"";
+          if(fn->arguments().size()-j > 0)
+              s << ", ";
+          writeMetaMethodArguments(s, fn, j);
+  s << "), index));" << endl << endl;
+          AbstractMetaArgumentList args = fn->arguments();
+          if(args.size() && j<args.size())
+              hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty();
+          else
+              hasDefault = false;
+          j++;
+          staticId++;
+      } while (hasDefault);
+  }
+
+  staticId = 0;
+  for (int i = 0; i < slot_funcs.size(); ++i)
+  {
+      int j = 0;
+      bool hasDefault = false;
+      do // need this to look for default arguments and generate extra signatures
+      {
+          AbstractMetaFunction *fn = slot_funcs.at(i);
+  s << "        index = _staticMetaObject.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl
+    << "        _staticMetaObject.addMethod(new QMetaSlot(signature!(\"" << fn->name() << "\"";
+          if(fn->arguments().size()-j > 0)
+              s << ", ";
+          writeMetaMethodArguments(s, fn, j);
+  s << "), index));" << endl << endl;
+          AbstractMetaArgumentList args = fn->arguments();
+          if(args.size() && j<args.size())
+              hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty();
+          else
+              hasDefault = false;
+          j++;
+          staticId++;
+      } while (hasDefault);
+  }
+
+  s  << "    }" << endl << endl;
+
+  s << INDENT << "mixin Q_OBJECT_BIND;" << endl << endl;
 }
 
 /*
@@ -2778,17 +2913,7 @@
 
 void DGenerator::writeSignalSignatures(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunctionList signal_funcs)
 {
-    s << INDENT << "private const string[" << signal_funcs.size() << "] __signalSignatures = [";
-    {
-        Indentation indent(INDENT);
-        for (int i = 0; i < signal_funcs.size(); ++i)
-        {            
-            if (i)
-                s << ", ";                
-            s << endl << INDENT << "    \"" << signal_funcs.at(i)->minimalSignature() << "\"";
-        }
-    }
-    s << INDENT << "];" << endl << endl;
+    writeMetaMethodSignatures(s, "__signalSignatures", signal_funcs);
 
     s << INDENT << "int signalSignature(int signalId, ref stringz signature) {" << endl;
     {
@@ -2810,29 +2935,42 @@
     s << INDENT << "}" << endl;
 }
 
+void DGenerator::writeMetaMethodArguments(QTextStream &s, const AbstractMetaFunction *d_function, int reduce)
+{
+    bool withDefArgs = false;
+    if(reduce == -1) {
+        reduce = 0;
+        withDefArgs = true;
+    }
+
+    AbstractMetaArgumentList arguments = d_function->arguments();
+    int sz = arguments.count() - reduce;
+
+    for (int i=0; i<sz; ++i) {
+        if(i != 0)
+            s << ",";
+
+        QString modifiedType = d_function->typeReplaced(i+1);
+
+        if (modifiedType.isEmpty())
+            s << translateType(arguments.at(i)->type(), d_function->implementingClass(), BoxedPrimitive);
+        else
+            s << modifiedType;
+
+        if (!arguments.at(i)->defaultValueExpression().isEmpty() && withDefArgs) // qtd
+            s << " = " + arguments.at(i)->defaultValueExpression();
+    }
+}
+
 void DGenerator::writeSignal(QTextStream &s, const AbstractMetaFunction *d_function)
 {
     Q_ASSERT(d_function->isSignal());
 
-    AbstractMetaArgumentList arguments = d_function->arguments();
-    int sz = arguments.count();
-
-    s << INDENT << "mixin BindQtSignal!(\"" << d_function->name() << "\"";
-
-    if (sz > 0) {
-        for (int i=0; i<sz; ++i) {
-            s << ", ";
-
-            QString modifiedType = d_function->typeReplaced(i+1);
-
-            if (modifiedType.isEmpty())
-                s << translateType(arguments.at(i)->type(), d_function->implementingClass(), BoxedPrimitive);
-            else
-                s << modifiedType;
-        }
-    }
-
-    s << ");" << endl;
+    s << INDENT << "mixin BindQtSignal!(\"" << d_function->name() << "(";
+
+    writeMetaMethodArguments(s, d_function);
+
+    s << ")\");" << endl;
 }
 
 void DGenerator::writeShellVirtualFunction(QTextStream &s, const AbstractMetaFunction *d_function,