changeset 278:5df570e79cfc

new syntax for connecting using static information
author eldar
date Sun, 04 Oct 2009 12:14:03 +0000
parents 750ea0c5fe83
children 519befd5a5d1
files examples/mainwindows/CMakeLists.txt examples/mainwindows/sdi/CMakeLists.txt examples/mainwindows/sdi/mainwindow.d qt/d1/qt/Signal.d qt/d2/qt/Signal.d
diffstat 5 files changed, 226 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/examples/mainwindows/CMakeLists.txt	Thu Oct 01 11:26:47 2009 +0000
+++ b/examples/mainwindows/CMakeLists.txt	Sun Oct 04 12:14:03 2009 +0000
@@ -1,1 +1,2 @@
-add_subdirectory(dockwidgets)
\ No newline at end of file
+add_subdirectory(dockwidgets)
+add_subdirectory(sdi)
\ No newline at end of file
--- a/examples/mainwindows/sdi/CMakeLists.txt	Thu Oct 01 11:26:47 2009 +0000
+++ b/examples/mainwindows/sdi/CMakeLists.txt	Sun Oct 04 12:14:03 2009 +0000
@@ -1,1 +1,1 @@
-build_example(sdi main.d RESOURCES sdis.qrc)
\ No newline at end of file
+build_example(sdi main.d RESOURCES sdi.qrc)
\ No newline at end of file
--- a/examples/mainwindows/sdi/mainwindow.d	Thu Oct 01 11:26:47 2009 +0000
+++ b/examples/mainwindows/sdi/mainwindow.d	Sun Oct 04 12:14:03 2009 +0000
@@ -249,7 +249,7 @@
     // QtD bug????
     // only one of the following statements can be included
     // otherwise the app crashes when a MainWindow is closeda
-//     textEdit.copyAvailable.connect(&cutAct.setEnabled);
+    textEdit.copyAvailable.connect(&cutAct.setEnabled);
     textEdit.copyAvailable.connect(&copyAct.setEnabled);
   }
 
--- a/qt/d1/qt/Signal.d	Thu Oct 01 11:26:47 2009 +0000
+++ b/qt/d1/qt/Signal.d	Sun Oct 04 12:14:03 2009 +0000
@@ -15,6 +15,7 @@
 import tango.core.Exception;
 import tango.core.Traits;
 import tango.core.Thread;
+public import tango.core.Tuple;
 import tango.stdc.stdlib : crealloc = realloc, cfree = free;
 import tango.stdc.string : memmove;
 
@@ -908,9 +909,115 @@
     {
         signalHandler.unblockSignals();
     }
+    
+    void connect(string signalName, T, R, B...)(T sender, R function(B) dg, ConnectionFlags flags = ConnectionFlags.None)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        alias CheckSlot!(typeof(fn), sig[2].at) check;
+        auto sh = sender.signalHandler();
+        auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at));
+        sh.connect(sig[1], Fn(fn), invoker, flags);
+    }
+
+    void connect(string signalName, T, R, B...)(T sender, R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        alias CheckSlot!(typeof(dg), sig[2].at) check;
+        auto sh = sender.signalHandler();
+        auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at));
+        sh.connect(sig[1], Dg(dg), invoker, flags);
+    }
+
+    void disconnect(string signalName, T, R, B...)(T sender, R function(B) fn)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = sender.signalHandler();
+        sh.disconnect(sig[1], Fn(fn));
+    }
+
+    void disconnect(string signalName, T, R, B...)(T sender, R delegate(B) dg)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = sender.signalHandler();
+        sh.disconnect(sig[1], Dg(dg));
+    }
+
+    debug size_t slotCount(string signalName, T)(T sender)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = sender.signalHandler();
+        return sh.slotCount(sig[1]);
+    }
 }
 
 /**
+    New implementation.
+*/
+
+public bool startsWith(T)(T[] source, T[] pattern)
+{
+    return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
+}
+
+template TupleWrapper(A...) { alias A at; }
+
+string joinArgs(A...)()
+{
+    string res = "";
+    static if(A.length)
+    {
+        res = A[0].stringof;
+        foreach(k; A[1..$])
+            res ~= "," ~ k.stringof;
+    }
+    return res;
+}
+
+struct SignalQualifier
+{
+    const string staticSymbolPrefix = "__signal";
+    const string name = "signal";
+    
+    static bool matches(alias source, string sigName)()
+    {
+        return startsWith(source.at[0], sigName);
+    }
+}
+
+template staticSymbolName(Qualifier, int id)
+{
+    const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id);
+}
+
+template signatureString(string name, A...)
+{
+    const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
+}
+
+template findSymbolImpl(Qualifier, C, int id, string key)
+{
+    static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) )
+    {
+        mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;");
+        static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) {
+            alias current result;
+        }
+        else
+            alias findSymbolImpl!(Qualifier, C, id + 1, key).result result;
+    }
+    else
+    {
+        static assert(0, Qualifier.name ~ " " ~ key ~ " not found.");
+    }
+}
+
+template findSymbol(Qualifier, C, string key)
+{
+    alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol;
+}
+
+
+/**
     Examples:
 ----
 struct Args
@@ -959,6 +1066,7 @@
             mixin SignalHandlerOps;
         }
         mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";");
+        mixin("public alias Tuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
         mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
             ~ ToString!(index) ~ ", A)(signalHandler); }");
     }
--- a/qt/d2/qt/Signal.d	Thu Oct 01 11:26:47 2009 +0000
+++ b/qt/d2/qt/Signal.d	Sun Oct 04 12:14:03 2009 +0000
@@ -12,7 +12,9 @@
 module qt.Signal;
 
 public import qt.QGlobal;
-public import std.metastrings;
+public import
+    std.metastrings,
+    std.typetuple;
 import core.stdc.stdlib : crealloc = realloc, cfree = free;
 import core.stdc.string : memmove;
 import
@@ -834,11 +836,7 @@
     {
         static assert (is(SlotArgs[i] : A[i]), "Argument " ~ ToString!(i) ~
             ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter "
-
-
-
-
-                       ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
+            ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
         alias CheckSlotImpl!(Slot, i + 1, A) next;
     }
 }
@@ -875,9 +873,117 @@
     {
         signalHandler.unblockSignals();
     }
+
+    void connect(string signalName, this T, R, B...)(R function(B) dg, ConnectionFlags flags = ConnectionFlags.None)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        alias CheckSlot!(typeof(fn), sig[2].at) check;
+        auto sh = signalHandler();
+        auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at));
+        sh.connect(sig[1], Fn(fn), invoker, flags);
+    }
+
+    void connect(string signalName, this T, R, B...)(R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        alias CheckSlot!(typeof(dg), sig[2].at) check;
+        auto sh = signalHandler();
+        auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at));
+        sh.connect(sig[1], Dg(dg), invoker, flags);
+    }
+
+    void disconnect(string signalName, this T, R, B...)(R function(B) fn)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = signalHandler();
+        sh.disconnect(sig[1], Fn(fn));
+    }
+
+    void disconnect(string signalName, this T, R, B...)(R delegate(B) dg)
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = signalHandler();
+        sh.disconnect(sig[1], Dg(dg));
+    }
+
+    debug size_t slotCount(string signalName, this T)()
+    {
+        alias findSymbol!(SignalQualifier, T, signalName) sig;
+        auto sh = signalHandler();
+        return sh.slotCount(sig[1]);
+    }
 }
 
 /**
+    New implementation.
+*/
+
+public bool startsWith(T)(T[] source, T[] pattern)
+{
+    return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
+}
+
+template TupleWrapper(A...) { alias A at; }
+
+string joinArgs(A...)()
+{
+    string res = "";
+    static if(A.length)
+    {
+        res = A[0].stringof;
+        foreach(k; A[1..$])
+            res ~= "," ~ k.stringof;
+    }
+    return res;
+}
+
+struct SignalQualifier
+{
+    const string staticSymbolPrefix = "__signal";
+    const string name = "signal";
+    
+    static bool matches(alias source, string sigName)()
+    {
+        return startsWith(source.at[0], sigName);
+    }
+}
+
+template staticSymbolName(Qualifier, int id)
+{
+    const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id);
+}
+
+template signatureString(string name, A...)
+{
+    const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
+}
+
+template findSymbolImpl(Qualifier, C, int id, string key)
+{
+    static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) )
+    {
+        mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;");
+        static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) {
+            alias current result;
+        }
+        else
+            alias findSymbolImpl!(Qualifier, C, id + 1, key).result result;
+    }
+    else
+    {
+        static assert(0, Qualifier.name ~ " " ~ key ~ " not found.");
+    }
+}
+
+template findSymbol(Qualifier, C, string key)
+{
+    alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol;
+}
+
+/** ---------------- */
+
+
+/**
     Examples:
 ----
 struct Args
@@ -925,7 +1031,8 @@
         {
             mixin SignalHandlerOps;
         }
-        mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";");
+        /* deprecated */ mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";");
+        mixin("public alias TypeTuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
         mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
             ~ ToString!(index) ~ ", A)(signalHandler); }");
     }