diff options
author | George Kiagiadakis <george.kiagiadakis@collabora.co.uk> | 2010-12-25 13:26:12 +0200 |
---|---|---|
committer | George Kiagiadakis <george.kiagiadakis@collabora.co.uk> | 2010-12-25 13:26:12 +0200 |
commit | 64e30d70f2b9d25424c87cf4a1e2effaa4759e57 (patch) | |
tree | c7d1b3d88e2f8487d3eab00d579e341a8580e3f4 | |
parent | 6c56049ceba594fe8f0dbe59874c005ad8ecf403 (diff) |
Write proper documentation for connect() and disconnect().
-rw-r--r-- | src/QGlib/connect.h | 135 | ||||
-rw-r--r-- | src/main.dox | 7 |
2 files changed, 119 insertions, 23 deletions
diff --git a/src/QGlib/connect.h b/src/QGlib/connect.h index 68aae28..d80551d 100644 --- a/src/QGlib/connect.h +++ b/src/QGlib/connect.h @@ -54,38 +54,82 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(ConnectFlags) #if defined(DOXYGEN_RUN) -/*! Connects a signal to a specified \a slot. +/*! Connects \a detailedSignal of \a instance to the specified \a slot of \a receiver. * - * This method will generate a set of template functions and classes that bind on a GClosure. - * When the signal is emitted, this GClosure will be invoked and its templated marshaller - * function will take care of converting the parameters of the signal (which are given as - * GValues) to the types that the \a slot expects. In case the types do not match, a warning - * will be printed to stderr at runtime and the \a slot will not be invoked. You are - * responsible for defining the \a slot with the correct arguments! + * This method provides a way of connecting GObject signals to C++ slots, in a Qt-like fashion. * - * Note that since the implementation uses Value::get() to convert the GValues into the - * specified types, the same rules that apply to Value::get() apply here (i.e. you should - * only use the types of the bindings and not the C types, which means QGst::ObjectPtr instead - * of GstObject*, etc...). + * \a instance needs to be a pointer to a GLib instantiatable type, such as a GObject. You can + * pass a RefPointer as an argument here without any problems; it will automatically cast to void*. + * + * \a detailedSignal should be the name of the signal that you want to conenct to - with an + * optional detail, if the signal supports details. The signal must \em not use the Qt SIGNAL() + * macro; it should use the signal canonical form specified in GLib, i.e. it should be a string + * containing only lowercase letters and dashes. For example, "my-signal" is a valid signal name. + * The detail may be specified by appending "::" to the signal name and the detail after that. + * For example, "my-signal::detail". + * + * \a receiver should be the instance of the class on which \a slot will be invoked. Currently, + * the \a receiver needs to inherit QObject. If you use another class that doesn't inherit + * QObject, a compilation error will occur. + * + * \a slot should be a C++ member function pointer that points to the method that you want + * to be invoked on the \a receiver once the signal is emitted. Note that it must \em not use + * the Qt SLOT() macro. + * + * Special care must be taken with the arguments that \a slot takes. Consider the following + * example. The C API documentation mentions a signal that takes these parameters: + * \code + * void user_function (GObject *object, GParamSpec *pspec, gpointer user_data); + * \endcode + * The first argument is always a pointer to the sender object, the second argument is + * the real signal argument and the third argument is a user defined pointer that is usually + * used in C as a substitute for the \a receiver. In general, the first argument is always + * the sender, the 2nd to Nth-1 arguments are the real signal arguments and the Nth argument + * is a user defined pointer. Now in C++, the following rules apply: + * \li You must use the C++ equivalent types of the arguments that the signal sends. + * So, in the above example, GParamSpec* is translated to QGlib::ParamSpecPtr. + * \li You must not have the user_data argument at the end. + * \li You must not have the sender argument at the beginning, unless QGlib::PassSender + * is used in \a flags. + * \li You may use const references in the arguments to avoid unecessary copying of objects, + * as the C++ marshaller that will call your slot will always hold a copy of the converted + * C++ objects. + * + * So, the C++ signature should eventually be: + * \code + * void MyClass::mySlot(const QGlib::ParamSpecPtr & pspec); + * ... + * //Connected with: + * QGlib::connect(element, "notify::name", myClassInstance, &MyClass::mySlot); + * \endcode + * \em or + * \code + * void MyClass::mySlot(const QGlib::ObjectPtr & sender, const QGlib::ParamSpecPtr & pspec); + * ... + * //Connected with: + * QGlib::connect(element, "notify::name", myClassInstance, &MyClass::mySlot, QGlib::PassSender); + * \endcode + * + * Internally, the signal provides GValues that are converted to the C++ types that your + * \a slot specifies using Value::get(), so all rules that apply there also apply to the + * \a slot arguments. That means that you may actually use different types of arguments + * than the ones that the documentation specifies, given that Value is able to transform + * them (see Value::canTransformTo) to the type that you have requested. Obviously, if you + * specify non-compatible arguments on the \a slot, the conversion will fail, and in this case + * a warning is printed at the time of the signal emission and the \a slot is not invoked. * * \note - * \li You can use const references for the arguments of the slot to avoid unnecessary - * copying of objects. The marshaller will always hold one copy of them during the execution - * of your \a slot. + * \li Include <QGlib/Connect> to use this function + * \li Unlike Qt, in GObject some signals are able to return values back to the sender. + * In this case, your \a slot should specify a compatible return type instead of void. * \li This method makes use of C++0x features (namely, variadic templates and rvalue * references). If your compiler does not support them, a hacky implementation using boost's * preprocessor, function and bind libraries will be compiled instead. That version has a * limit of 9 slot arguments. + * \li This function is thread-safe. * - * \param instance The instance of the object that emits this signal. You can pass - * a RefPointer as an instance without any problems; it will automatically cast to void*. - * \param detailedSignal The name of the signal that you want to connect to, with an optional - * detail if the signal is detailed. The detail may be specified with the following syntax: - * "signal::detail". - * \param receiver The instance of the class on which \a slot will be invoked. - * \param slot A pointer to a member function that will be invoked when the signal is emitted. - * \param flags See ConnectFlag. * \returns whether the connection was successfully made or not + * \sa disconnect(), ConnectFlag, \ref connect_design */ template <typename T, typename R, typename... Args> bool connect(void *instance, const char *detailedSignal, @@ -97,7 +141,52 @@ bool connect(void *instance, const char *detailedSignal, //to use NULL for the receiver and slot arguments. Also, a version that takes void* //for everything is not possible since member function pointers do not cast to void*. -/*! Disconnects \a detailedSignal of \a instance from the \a slot of \a receiver. */ +/*! Disconnects \a detailedSignal of \a instance from the \a slot of \a receiver. + * + * A signal-slot connection typically is broken when either of the objects involved + * are destroyed. However, there are cases in which you might want to break that + * connection manually using this method. + * + * disconnect() can be used in the following ways: + * \li Disconnect everything connected to an object's signals: + * \code + * disconnect(myGObject); + * \endcode + * \li Disconnect everything connected to a specific signal: + * \code + * disconnect(myGObject, "some-signal"); + * \endcode + * \li Disconnect a specific receiver: + * \code + * disconnect(myGObject, 0, myReceiver); + * \endcode + * \li Disconnect a specific slot (note that the receiver must also be specified): + * \code + * disconnect(myGObject, 0, myReceiver, &MyReceiver::mySlot); + * \endcode + * + * 0 can be used as a wildcard, meaning "any signal", "any receiver" or "any slot". + * \a instance can never be 0. + * + * If \a detailedSignal is 0, it disconnects \a receiver and \a slot from any signal. + * Otherwise, only \a detailedSignal is disconnected. A signal detail may or may not + * be specified. If it is not specified, it acts as a wildcard for all details, meaning + * it disconnects all the connections that have been made with a specific detail. + * + * If \a receiver is 0, it disconnects anything connected to \a detailedSignal. If not, + * only slots in \a receiver are disconnected. + * + * If \a slot is 0, it disconnects anything that is connected to \a receiver. If not, + * only the specified \a slot will be disconnected. Note that \a slot must be 0 if + * \a receiver is left out. + * + * \note + * \li Include <QGlib/Connect> to use this function + * \li This function is thread-safe. + * + * \returns true if the connection was successfully broken, or false otherwise + * \sa connect() + */ template <typename T, typename R, typename... Args> bool disconnect(void *instance, const char *detailedSignal = 0, T *receiver = 0, R (T::*slot)(Args...) = 0); diff --git a/src/main.dox b/src/main.dox index 06f8a3e..3c03a58 100644 --- a/src/main.dox +++ b/src/main.dox @@ -61,6 +61,13 @@ * are not faced with exceptions, however, they are used internally from the signals/slots code * to handle errors and show friendlier error messages. Because Value::set/get catch these * exceptions, the signals/slots code uses directly ValueImpl<T>. + * + * \section connect_design Connect Design + * connect() is a template method. When it is used, it takes the arguments of the given + * slot and instantiates a template marshaller that is responsible for converting + * the GValues that the signal provides to the C++ types that the slot expects. + * This marshaller and the structure holding the receiver & slot are then attached on + * the data of a GClosure and this GClosure is connected to the signal. */ /*! \example echo/main.cpp |