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 */