int main() { Pt::Gui::Application app; Pt::Gui::Button b; connect( b.clicked, app, &Pt::Gui::Application::exit); b.setText(L"Quit"); b.show(); return app.run(); }
The application will simply quit if the button is clicked. The Pt::Gui:.Application object is the callee and the Pt::Gui::Button is the caller, which has a signal called clicked. In this case Pt::Gui::Application::exit is a regular member function.
Pt::Signal<> sig0; // Signal without arguments Pt::Signal<int> sig1; // Signal with one argument Pt::Signal<const std::string&, int> sig2; // Signal with two arguments
class Callee : public Pt::Connectable { public: void slot() { printf("Callee::slot() called\n"); } }; void slot() { printf("slot() called.\n"); } int main() { Pt::Signal<> signal; Callee calee; connect( signal, slot ); connect( signal, callee, &Callee::slot); return 0; }
The first argument to connect is aleays the signal object. When a signal is connected to a free function the second parameter to the connect call is a function pointer. When a signal is connected to a member function of an object, the second argument is an object instance and the third one the member function pointer. Signals can only be connected to objects that derive from Pt::Connectable to ensure that all connections are closed when the object goes out of scope and no dangling connections are left.
The connecting functions return Connection objects, which can be used to disconnect signals from slots manually. The following code illustrates this:
void slot() { printf("slot() called.\n"); } int main() { Pt::Signal<> signal; Connection c = connect( signal, slot ); c.valid() // returns true c.close(); c.valid() // returns false now return 0; }
A connection is reference counted and can not be duplicated as such, but always refers to the same shared connection data. If one peer of a connection is destroyed or connection::close is called, the connection becomes invalid. A connection can also become invalid if one of the connection peers rejects being connected. Pt::Signal never rejects connections, however other signal types might.
Besides the overloaded versions of connect, Pt::Signal::connect can be used to connect to any matching slot type, and thus Pt::Signal::connect takes a reference to a Pt::BasicSlot. Slots are lightweight proxy-objects and one example is Pt::MethodSlot, which describes a member function slot. This way, signals can be connected to any callable entity.
void tellAge(int age) { std::cout << "I am " << age << " years old\n; } int main () { Pt::Signal<int> signal; connect( signal, tellAge ); signal.send(26); return 0; }
When the signal is send, the slot is called with the value passed to Signal::send. Nothing will happen if the signal is not connected to any slots. When a signal is sent, the slot is called immediatly and directly and does not depend on an event loop. If multiple slots are connected to a signal, the slots will be called one after another.
int slotA() { return 5; } int slotB() { return 6; } int main() { Pt::Delegate<int> delegate; connect( delegate, slotA ); connect( delegate, slotB ); // disconnects from slotA return 0; }
int slot() { return 5; } int main() { Pt::Delegate<int> delegate; connection conection = connect( delegate, slot ); int i = delegate.call(); // i is 5 now connection.close(); delegate.invoke() // does not throw delegate.call(); // will throw because not connected return 0; }