File indexing completed on 2024-05-12 15:57:03

0001 /****************************************************************************
0002 **
0003 ** SPDX-FileCopyrightText: 2016 The Qt Company Ltd.
0004 ** Contact: https://www.qt.io/licensing/
0005 **
0006 ** This file is part of the QtCore module of the Qt Toolkit.
0007 **
0008 ** SPDX-License-Identifier: LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KFQF-Accepted-GPL OR LicenseRef-Qt-Commercial
0009 **
0010 ****************************************************************************/
0011 
0012 #include "KisSignalMapper.h"
0013 #include "qhash.h"
0014 
0015 class KisSignalMapper::Private
0016 {
0017 public:
0018     
0019     Private(KisSignalMapper *_q)
0020         :q(_q)
0021         {}
0022     
0023     void _q_senderDestroyed() {
0024         q->removeMappings(q->sender());
0025     }
0026     QHash<QObject *, int> intHash;
0027     QHash<QObject *, QString> stringHash;
0028     QHash<QObject *, QWidget*> widgetHash;
0029     QHash<QObject *, QObject*> objectHash;
0030 
0031     
0032     KisSignalMapper *q;
0033 };
0034 
0035 /*!
0036     \class KisSignalMapper
0037     \inmodule QtCore
0038     \obsolete The recommended solution is connecting the signal to a lambda.
0039     \brief The KisSignalMapper class bundles signals from identifiable senders.
0040 
0041     \ingroup objectmodel
0042 
0043 
0044     This class collects a set of parameterless signals, and re-emits
0045     them with integer, string or widget parameters corresponding to
0046     the object that sent the signal.
0047 
0048     The class supports the mapping of particular strings or integers
0049     with particular objects using setMapping(). The objects' signals
0050     can then be connected to the map() slot which will emit the
0051     mapped() signal with the string or integer associated with the
0052     original signaling object. Mappings can be removed later using
0053     removeMappings().
0054 
0055     Example: Suppose we want to create a custom widget that contains
0056     a group of buttons (like a tool palette). One approach is to
0057     connect each button's \c clicked() signal to its own custom slot;
0058     but in this example we want to connect all the buttons to a
0059     single slot and parameterize the slot by the button that was
0060     clicked.
0061 
0062     Here's the definition of a simple custom widget that has a single
0063     signal, \c clicked(), which is emitted with the text of the button
0064     that was clicked:
0065 
0066     \snippet KisSignalMapper/buttonwidget.h 0
0067     \snippet KisSignalMapper/buttonwidget.h 1
0068 
0069     The only function that we need to implement is the constructor:
0070 
0071     \snippet KisSignalMapper/buttonwidget.cpp 0
0072     \snippet KisSignalMapper/buttonwidget.cpp 1
0073     \snippet KisSignalMapper/buttonwidget.cpp 2
0074 
0075     A list of texts is passed to the constructor. A signal mapper is
0076     constructed and for each text in the list a QPushButton is
0077     created. We connect each button's \c clicked() signal to the
0078     signal mapper's map() slot, and create a mapping in the signal
0079     mapper from each button to the button's text. Finally we connect
0080     the signal mapper's mapped() signal to the custom widget's \c
0081     clicked() signal. When the user clicks a button, the custom
0082     widget will emit a single \c clicked() signal whose argument is
0083     the text of the button the user clicked.
0084 
0085     This class was mostly useful before lambda functions could be used as
0086     slots. The example above can be rewritten simpler without KisSignalMapper
0087     by connecting to a lambda function.
0088 
0089     \snippet KisSignalMapper/buttonwidget.cpp 3
0090 
0091     \sa QObject, QButtonGroup, QActionGroup
0092 */
0093 
0094 /*!
0095     Constructs a KisSignalMapper with parent \a parent.
0096 */
0097 KisSignalMapper::KisSignalMapper(QObject* parent)
0098     : QObject(parent)
0099     , d(new Private(this))
0100 {
0101 }
0102 
0103 /*!
0104     Destroys the KisSignalMapper.
0105 */
0106 KisSignalMapper::~KisSignalMapper()
0107 {
0108 }
0109 
0110 /*!
0111     Adds a mapping so that when map() is signalled from the given \a
0112     sender, the signal mapped(\a id) is emitted.
0113 
0114     There may be at most one integer ID for each sender.
0115 
0116     \sa mapping()
0117 */
0118 void KisSignalMapper::setMapping(QObject *sender, int id)
0119 {
0120     d->intHash.insert(sender, id);
0121     connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
0122 }
0123 
0124 /*!
0125     Adds a mapping so that when map() is signalled from the \a sender,
0126     the signal mapped(\a text ) is emitted.
0127 
0128     There may be at most one text for each sender.
0129 */
0130 void KisSignalMapper::setMapping(QObject *sender, const QString &text)
0131 {
0132     d->stringHash.insert(sender, text);
0133     connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
0134 }
0135 
0136 /*!
0137     Adds a mapping so that when map() is signalled from the \a sender,
0138     the signal mapped(\a widget ) is emitted.
0139 
0140     There may be at most one widget for each sender.
0141 */
0142 void KisSignalMapper::setMapping(QObject *sender, QWidget *widget)
0143 {
0144     d->widgetHash.insert(sender, widget);
0145     connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
0146 }
0147 
0148 /*!
0149     Adds a mapping so that when map() is signalled from the \a sender,
0150     the signal mapped(\a object ) is emitted.
0151 
0152     There may be at most one object for each sender.
0153 */
0154 void KisSignalMapper::setMapping(QObject *sender, QObject *object)
0155 {
0156     d->objectHash.insert(sender, object);
0157     connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
0158 }
0159 
0160 /*!
0161     Returns the sender QObject that is associated with the \a id.
0162 
0163     \sa setMapping()
0164 */
0165 QObject *KisSignalMapper::mapping(int id) const
0166 {
0167     return d->intHash.key(id);
0168 }
0169 
0170 /*!
0171     \overload mapping()
0172 */
0173 QObject *KisSignalMapper::mapping(const QString &id) const
0174 {
0175     return d->stringHash.key(id);
0176 }
0177 
0178 /*!
0179     \overload mapping()
0180 
0181     Returns the sender QObject that is associated with the \a widget.
0182 */
0183 QObject *KisSignalMapper::mapping(QWidget *widget) const
0184 {
0185     return d->widgetHash.key(widget);
0186 }
0187 
0188 /*!
0189     \overload mapping()
0190 
0191     Returns the sender QObject that is associated with the \a object.
0192 */
0193 QObject *KisSignalMapper::mapping(QObject *object) const
0194 {
0195     return d->objectHash.key(object);
0196 }
0197 
0198 /*!
0199     Removes all mappings for \a sender.
0200 
0201     This is done automatically when mapped objects are destroyed.
0202 
0203     \note This does not disconnect any signals. If \a sender is not destroyed
0204     then this will need to be done explicitly if required.
0205 */
0206 void KisSignalMapper::removeMappings(QObject *sender)
0207 {
0208     d->intHash.remove(sender);
0209     d->stringHash.remove(sender);
0210     d->widgetHash.remove(sender);
0211     d->objectHash.remove(sender);
0212 }
0213 
0214 /*!
0215     This slot emits signals based on which object sends signals to it.
0216 */
0217 void KisSignalMapper::map() { map(sender()); }
0218 
0219 /*!
0220     This slot emits signals based on the \a sender object.
0221 */
0222 void KisSignalMapper::map(QObject *sender)
0223 {
0224     if (d->intHash.contains(sender))
0225         emit mapped(d->intHash.value(sender));
0226     if (d->stringHash.contains(sender))
0227         emit mapped(d->stringHash.value(sender));
0228     if (d->widgetHash.contains(sender))
0229         emit mapped(d->widgetHash.value(sender));
0230     if (d->objectHash.contains(sender))
0231         emit mapped(d->objectHash.value(sender));
0232 }
0233 
0234 
0235 /*!
0236     \fn void KisSignalMapper::mapped(int i)
0237 
0238     This signal is emitted when map() is signalled from an object that
0239     has an integer mapping set. The object's mapped integer is passed
0240     in \a i.
0241 
0242     \sa setMapping()
0243 */
0244 
0245 /*!
0246     \fn void KisSignalMapper::mapped(const QString &text)
0247 
0248     This signal is emitted when map() is signalled from an object that
0249     has a string mapping set. The object's mapped string is passed in
0250     \a text.
0251 
0252     \sa setMapping()
0253 */
0254 
0255 /*!
0256     \fn void KisSignalMapper::mapped(QWidget *widget)
0257 
0258     This signal is emitted when map() is signalled from an object that
0259     has a widget mapping set. The object's mapped widget is passed in
0260     \a widget.
0261 
0262     \sa setMapping()
0263 */
0264 
0265 /*!
0266     \fn void KisSignalMapper::mapped(QObject *object)
0267 
0268     This signal is emitted when map() is signalled from an object that
0269     has an object mapping set. The object provided by the map is passed in
0270     \a object.
0271 
0272     \sa setMapping()
0273 */
0274 
0275 #include "moc_KisSignalMapper.cpp"
0276