# HG changeset patch # User eldar # Date 1254658443 0 # Node ID 5df570e79cfc01e959d7ee1dba0f074047ef659e # Parent 750ea0c5fe833b5ab63d2709298b662f3c38757f new syntax for connecting using static information diff -r 750ea0c5fe83 -r 5df570e79cfc examples/mainwindows/CMakeLists.txt --- 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 diff -r 750ea0c5fe83 -r 5df570e79cfc examples/mainwindows/sdi/CMakeLists.txt --- 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 diff -r 750ea0c5fe83 -r 5df570e79cfc examples/mainwindows/sdi/mainwindow.d --- 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(©Act.setEnabled); } diff -r 750ea0c5fe83 -r 5df570e79cfc qt/d1/qt/Signal.d --- 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); }"); } diff -r 750ea0c5fe83 -r 5df570e79cfc qt/d2/qt/Signal.d --- 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); }"); }