changeset 319:894d40eb89b6 signals

new signals and slots syntax. have to use prefixes now: signal_fooed and slot_onFooed
author eldar_ins@eldar-laptop
date Fri, 25 Dec 2009 21:48:32 +0500
parents ce07227f00c1
children 5c6455c4889b
files build/core.txt qt/d2/qt/Signal.d qt/qtd/MOC.d qt/qtd/Meta.d qt/qtd/MetaMarshall.d
diffstat 5 files changed, 249 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/build/core.txt	Thu Dec 24 05:19:40 2009 +0500
+++ b/build/core.txt	Fri Dec 25 21:48:32 2009 +0500
@@ -24,6 +24,7 @@
     qtd/Atomic
     qtd/MetaMarshall
     qtd/MOC
+    qtd/Meta
     qtd/util/Tuple
     qtd/ctfe/Integer
     qtd/ctfe/String
--- a/qt/d2/qt/Signal.d	Thu Dec 24 05:19:40 2009 +0500
+++ b/qt/d2/qt/Signal.d	Fri Dec 25 21:48:32 2009 +0500
@@ -13,6 +13,7 @@
 
 public import qt.QGlobal;
 import qt.qtd.MetaMarshall;
+import qt.qtd.Meta;
 
 import core.stdc.stdlib : crealloc = realloc, cfree = free;
 import core.stdc.string : memmove;
@@ -29,7 +30,12 @@
     std.metastrings;
 
    
-// returns name, arguments or tuple of the function depending on type parameter
+/* returns name, arguments or tuple of the function depending on type parameter
+    foo(int, float)
+    _Name:  "foo"
+    _Tuple: "(int, float)"
+    _Args:  "int, float"
+*/
 enum {_Name, _Tuple, _Args}
 string getFunc(int type)(string fullName)
 {
@@ -38,10 +44,10 @@
         if (c == '(')
             static if (type == _Tuple)
                 return fullName[i..$];
-            else if (type == _Name)
+            else static if (type == _Name)
                 return fullName[0..i];
-            else if (type == _Args)
-                for(int j = fullName.length-1;; j--)
+            else static if (type == _Args)
+                for(int j = fullName.length-1; ; j--)
                     if(fullName[j] == ')')
                         return fullName[i+1 .. j];
     return null;
@@ -136,7 +142,7 @@
 
 template MetaEntryArgs(source...)
 {
-    alias source[3 .. $] MetaEntryArgs; // arguments-tuple starts from the fourth position
+    alias ParameterTypeTuple!(source[1]) MetaEntryArgs; // arguments-tuple starts from the fourth position
 }
 
 template TupleWrapper(A...) { alias A at; }
@@ -491,4 +497,116 @@
         enum lastSignalIndexImpl = lastSignalIndexImpl!(T, index + 1);
     else
         enum lastSignalIndexImpl = index - 1;
+}
+
+// ------------------------------------------------------------------
+
+string[] getSymbols(C)(string prefix)
+{
+    string[] result;
+    auto allSymbols = __traits(derivedMembers, C);
+    foreach(s; allSymbols)
+        if(ctfeStartsWith(s, prefix))
+            result ~= s;
+    return result;
+}
+
+string removePrefix(string source)
+{
+    foreach (i, c; source)
+        if (c == '_')
+            return source[i+1..$];
+    return source;
+}
+
+template Alias(T...)
+{
+    alias T Alias;
+}
+
+// recursive search in the static meta-information
+template findSymbolsImpl2(C, alias signals, int id)
+{
+    alias Alias!(__traits(getOverloads, C, signals[id])) current;
+    static if (signals.length - id - 1 > 0)
+        alias TypeTuple!(current, findSymbolsImpl2!(C, signals, id + 1).result) result;
+    else
+        alias current result;
+}
+
+template findSymbols2(C, string prefix)
+{
+    enum signals = getSymbols!(C)(prefix);
+    static if (signals)
+        alias findSymbolsImpl2!(C, signals, 0).result result;
+    else
+        alias TypeTuple!() result;
+}
+
+template findSignals(C)
+{
+    alias findSymbols2!(C, "signal_").result findSignals;
+}
+
+template findSlots(C)
+{
+    alias findSymbols2!(C, "slot_").result findSlots;
+}
+
+
+template metaMethods(alias func, int index, int defValsCount)
+{
+    static if(defValsCount >= 0) {
+        alias TupleWrapper!(func, index) current;
+//        pragma(msg, __traits(identifier, (current.at)[0]) ~ " " ~ typeof(&(current.at)[0]).stringof);
+        alias metaMethods!(func, index+1, defValsCount-1).result next;
+        alias TypeTuple!(current, next) result;
+    }
+    else
+    {
+        alias TypeTuple!() result;
+    }
+}
+
+template toMetaEntriesImpl(int id, Methods...)
+{
+    static if (Methods.length > id)
+    {
+        alias typeof(&Methods[id]) Fn;
+//        enum defValsLength = 0; //ParameterTypeTuple!(Fn).length - requiredArgCount!(Methods[id])();
+//        pragma(msg, __traits(identifier, Methods[id]) ~ " " ~ typeof(&Methods[id]).stringof);
+//        alias metaMethods!(Methods[id], 0, defValsLength).result subres;
+        alias TupleWrapper!(removePrefix(__traits(identifier, Methods[id])), typeof(&Methods[id])) subres;
+        alias TypeTuple!(subres, toMetaEntriesImpl!(id+1, Methods).result) result;
+    }
+    else
+    {
+        alias TypeTuple!() result;
+    }
+}
+
+template toMetaEntries(Methods...)
+{
+    alias TupleWrapper!(toMetaEntriesImpl!(0, Methods).result) toMetaEntries;
+}
+
+
+bool printRawFuncs(T...)()
+{
+    pragma(msg, "---Raw---");
+    foreach(i, _; T)
+        pragma(msg, __traits(identifier, T[i]) ~ " " ~ typeof(&T[i]).stringof);
+    return true;
+}
+
+
+bool printFuncs(alias T)()
+{
+    pragma(msg, "---MetaEntries---");
+    alias T.at tuple;
+    enum num = tuple.length;
+    foreach(i, _; Repeat!(void, num))
+        pragma(msg, tuple[i].at[0] ~ " " ~ tuple[i].at[1].stringof);
+//        pragma(msg, typeof(&tuple[i].at[0]).stringof ~ " " ~ __toString(tuple[i].at[1]));
+    return true;
 }
\ No newline at end of file
--- a/qt/qtd/MOC.d	Thu Dec 24 05:19:40 2009 +0500
+++ b/qt/qtd/MOC.d	Fri Dec 25 21:48:32 2009 +0500
@@ -6,6 +6,8 @@
 
 import qt.Signal;
 import qt.qtd.MetaMarshall;
+import qt.qtd.Meta;
+
 public import qt.core.QString;
 
 public import std.traits;
@@ -83,12 +85,6 @@
     return cast(string)ret;
 }
 
-template Repeat(T, int I)
-{
-    static if (!I) alias TypeTuple!() Repeat;
-    else alias TypeTuple!(T, Repeat!(T, I - 1)) Repeat;
-}
-
 /**
    CTFE MOC port.
   */
@@ -409,7 +405,7 @@
         res ~= "
         if (_c == QMetaObject.Call.InvokeMetaMethod) {
             switch (_id) {";
-        foreach(i, bogus; Repeat!(void, methodCount)) {
+        foreach(i, _; Repeat!(void, methodCount)) {
             res ~= "
             case " ~ __toString(i) ~ ": " ~ MetaEntryName!(Methods[i].at) ~ "(" ~ metaCallArgs!(MetaEntryArgs!(Methods[i].at))() ~ "); break;";
         }
@@ -506,23 +502,11 @@
     return res;
 }
 
-string generateMetaInfo(string className, alias Signals, alias Slots)()
-{
-    string res = "";
-    auto signalList = genFuncDefs!(Signals, newSignal)();
-    auto slotList = genFuncDefs!(Slots, newSlot)();
-    res ~= generateCode(className, signalList, slotList);
-    res ~= generate_qt_metacall!(Signals, Slots);
-    res ~= generateMetaObjectConstruction!(Signals, Slots);
-    res ~= generateQMetaObject(className);
-    return res;
-}
-
 template Q_OBJECT_BIND()
 {
     mixin ("enum lastSignalIndex_" ~ typeof(this).stringof ~ " = " ~ toStringNow!(lastSignalIndex!(typeof(this))) ~ ";");
 }
-
+/*
 template Q_OBJECT()
 {
 //    pragma(msg, toStringNow!(lastSignalIndex!(typeof(this))));
@@ -533,3 +517,54 @@
     pragma(msg, generateMetaInfo!((typeof(this)).stringof, Signals, Slots)());
     mixin(generateMetaInfo!((typeof(this)).stringof, Signals, Slots)());
 }
+*/
+// ------------------------------------------------------------------------------------------
+
+string generateSignalEmitters(alias Funcs)()
+{
+    string res;
+    enum funcsCount = Funcs.at.length;
+    foreach(i, bogus; Repeat!(void, funcsCount))
+    {
+        res ~= SignalEmitter!(MetaEntryArgs!(Funcs.at[i].at))(SignalType.NewSignal, MetaEntryName!(Funcs.at[i].at), [], i);
+    }
+    return res;
+}
+
+string generateSlotAliases(alias Funcs)()
+{
+    string res;
+    enum funcsCount = Funcs.at.length;
+    foreach(i, bogus; Repeat!(void, funcsCount))
+    {
+        string name = MetaEntryName!(Funcs.at[i].at);
+        res ~= format_ctfe("    alias slot_${} ${};\n", name, name);
+    }
+    return res;
+}
+
+
+string generateMetaInfo(T, alias Signals, alias Slots)()
+{
+    string res = "";
+    auto signalList = genFuncDefs!(Signals, newSignal)();
+    auto slotList = genFuncDefs!(Slots, newSlot)();
+    res ~= generateSignalEmitters!(Signals)();
+    res ~= generateSlotAliases!(Slots)();
+    res ~= generateCode(T.stringof, signalList, slotList);
+    res ~= generate_qt_metacall!(Signals, Slots);
+    res ~= generateMetaObjectConstruction!(Signals, Slots);
+    res ~= generateQMetaObject(T.stringof);
+    return res;
+}
+
+template Q_OBJECT()
+{
+    alias findSignals!(typeof(this)) SignalFuncs;
+    alias toMetaEntries!(SignalFuncs) SignalMetaEntries;
+    alias findSlots!(typeof(this)) SlotFuncs;
+    alias toMetaEntries!(SlotFuncs) SlotMetaEntries;
+
+    mixin(generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)());
+    pragma(msg, generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)());
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qt/qtd/Meta.d	Fri Dec 25 21:48:32 2009 +0500
@@ -0,0 +1,68 @@
+module qt.qtd.Meta;
+
+import std.traits;
+import std.typetuple;
+
+// Various compile time utilities
+
+public bool ctfeStartsWith(T)(T[] source, T[] pattern)
+{
+    return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
+}
+
+// compile-time toString, maybe to!string is already working in CT
+string __toString(long v)
+{
+    if (v == 0)
+        return "0";
+
+    string ret;
+
+    bool neg;
+    if (v < 0)
+    {
+        neg = true;
+        v = -v;
+    }
+
+    while (v != 0)
+    {
+        ret = cast(char)(v % 10 + '0') ~ ret;
+        v = cast(long)(v / 10);
+    }
+
+    if (neg)
+        ret = "-" ~ ret;
+
+    return ret;
+}
+
+// returns the type of a template parameter if there is one
+template templateParam(U : V!(U), alias V)
+{
+    alias U templateParam;
+}
+
+// to workaround buggy foreach, returns a tuple of Ts of size I
+template Repeat(T, int I)
+{
+    static if (!I) alias TypeTuple!() Repeat;
+    else alias TypeTuple!(T, Repeat!(T, I - 1)) Repeat;
+}
+
+//returns number of required function arguments, optional arguments excluded
+int requiredArgCount(alias fn)() {
+    alias ParameterTypeTuple!(typeof(&fn)) P;
+    P p;
+    static if (P.length == 0)
+        return 0;
+    
+    foreach(i, _; P)
+    {
+        static if (!__traits(compiles, fn(p[0..$-i-1])))
+        {
+            return p.length - i;
+        }
+    }
+    return 0;
+}
\ No newline at end of file
--- a/qt/qtd/MetaMarshall.d	Thu Dec 24 05:19:40 2009 +0500
+++ b/qt/qtd/MetaMarshall.d	Fri Dec 25 21:48:32 2009 +0500
@@ -2,49 +2,7 @@
 
 import std.traits;
 
-// utilities
-// shouldn't be here
-
-public bool startsWith(T)(T[] source, T[] pattern)
-{
-    return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
-}
-
-string __toString(long v)
-{
-    if (v == 0)
-        return "0";
-
-    string ret;
-
-    bool neg;
-    if (v < 0)
-    {
-        neg = true;
-        v = -v;
-    }
-
-    while (v != 0)
-    {
-        ret = cast(char)(v % 10 + '0') ~ ret;
-        v = cast(long)(v / 10);
-    }
-
-    if (neg)
-        ret = "-" ~ ret;
-
-    return ret;
-}
-
-template templateParam(U : V!(U), alias V)
-{
-    alias U templateParam;
-}
-
-
-/*
- * actual stuff
- */
+import qt.qtd.Meta;
 
 template isQObjectType(T) // is a QObject type that belongs to the library
 {
@@ -73,7 +31,7 @@
 
 template isQList(T)
 {
-    enum isQList = startsWith(Unqual!(T).stringof, "QList!");
+    enum isQList = ctfeStartsWith(Unqual!(T).stringof, "QList!");
 }
 
 // converts an argumnent from C++ to D in qt_metacall