File indexing completed on 2024-04-28 04:18:50

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2009 Aurélien Gâteau <agateau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0019 
0020 */
0021 #ifndef BINDER_H
0022 #define BINDER_H
0023 
0024 #include <lib/gwenviewlib_export.h>
0025 
0026 // Qt
0027 #include <QObject>
0028 
0029 namespace Gwenview
0030 {
0031 /**
0032  * @internal
0033  *
0034  * Necessary helper class because a QObject class cannot be a template
0035  */
0036 class GWENVIEWLIB_EXPORT BinderInternal : public QObject
0037 {
0038     Q_OBJECT
0039 public:
0040     explicit BinderInternal(QObject *parent);
0041     ~BinderInternal() override;
0042 
0043 protected Q_SLOTS:
0044     virtual void callMethod()
0045     {
0046     }
0047 };
0048 
0049 /**
0050  * The Binder and BinderRef classes make it possible to "connect" a
0051  * parameter-less signal with a slot which accepts one argument. The
0052  * argument must be known at connection time.
0053  *
0054  * Example:
0055  *
0056  * Assuming a class like this:
0057  *
0058  * class Receiver
0059  * {
0060  * public:
0061  *   void doSomething(Param* p);
0062  * };
0063  *
0064  * This code:
0065  *
0066  * Binder<Receiver, Param*>::bind(emitter, SIGNAL(somethingHappened()), receiver, &Receiver::doSomething, p)
0067  *
0068  * Will result in receiver->doSomething(p) being called when emitter emits
0069  * the somethingHappened() signal.
0070  *
0071  * Just like a regular QObject connection, the connection will last until
0072  * either emitter or receiver are deleted.
0073  *
0074  * Using this system avoids creating an helper slot and adding a member to
0075  * the Receiver class to store the argument of the method to call.
0076  *
0077  * To call a method which accept a pointer or a value argument, use Binder.
0078  * To call a method which accept a const reference argument, use BinderRef.
0079  *
0080  * Note: the method does not need to be a slot.
0081  */
0082 template<class Receiver, class Arg, typename MethodArg>
0083 class BaseBinder : public BinderInternal
0084 {
0085 public:
0086     using Method = void (Receiver::*)(MethodArg);
0087     static void bind(QObject *emitter, const char *signal, Receiver *receiver, Method method, MethodArg arg)
0088     {
0089         auto *binder = new BaseBinder<Receiver, Arg, MethodArg>(emitter);
0090         binder->mReceiver = receiver;
0091         binder->mMethod = method;
0092         binder->mArg = arg;
0093         QObject::connect(emitter, signal, binder, SLOT(callMethod()));
0094         QObject::connect(receiver, SIGNAL(destroyed(QObject *)), binder, SLOT(deleteLater()));
0095     }
0096 
0097 protected:
0098     void callMethod() override
0099     {
0100         (mReceiver->*mMethod)(mArg);
0101     }
0102 
0103 private:
0104     BaseBinder(QObject *emitter)
0105         : BinderInternal(emitter)
0106         , mReceiver(nullptr)
0107         , mMethod(nullptr)
0108     {
0109     }
0110 
0111     Receiver *mReceiver;
0112     Method mMethod;
0113     Arg mArg;
0114 };
0115 
0116 template<class Receiver, class Arg>
0117 class Binder : public BaseBinder<Receiver, Arg, Arg>
0118 {
0119 };
0120 
0121 template<class Receiver, class Arg>
0122 class BinderRef : public BaseBinder<Receiver, Arg, const Arg &>
0123 {
0124 };
0125 
0126 } // namespace
0127 
0128 #endif /* BINDER_H */