File indexing completed on 2024-05-12 15:56:55
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_ACYCLIC_SIGNAL_CONNECTOR_H 0008 #define __KIS_ACYCLIC_SIGNAL_CONNECTOR_H 0009 0010 #include <QObject> 0011 #include "kritaglobal_export.h" 0012 #include <mutex> 0013 0014 class KisAcyclicSignalConnector; 0015 class KoColor; 0016 0017 #include <QVector> 0018 #include <QPointer> 0019 0020 /** 0021 * A special class for connecting UI elements to manager classes. 0022 * It allows to avoid direct calling blockSignals() for the sender UI 0023 * element all the time. This is the most important when the measured 0024 * value can be changed not only by the user through the UI, but also 0025 * by the manager according to some internal rules. 0026 * 0027 * Example: 0028 * 0029 * Suppose we have the following connections: 0030 * 0031 * 1) QDoubleSpinBox::valueChanged(double) -> Manager::slotSetValue(double) 0032 * 2) Manager::valueChanged(double) -> QDoubleSpinBox::setValue(double) 0033 * 0034 * Now if the manager decides to change/correct the value, the spinbox 0035 * will go into an infinite loop. 0036 * 0037 * See an example in KisToolCropConfigWidget. 0038 * 0039 * NOTE (coordinated connectors): 0040 * 0041 * Please make sure that you don't convert more than one forward and one backward 0042 * connection to the connector! If you do so, they will become connected to the 0043 * same forwarding slot and, therefore, both output signals will be emitted on 0044 * every incoming signal. 0045 * 0046 * To connect multiple connections that block recursive calls, please use 0047 * "coordinated connectors". Each such connector will have two more connection 0048 * slots that you can reuse. 0049 * 0050 */ 0051 0052 class KRITAGLOBAL_EXPORT KisAcyclicSignalConnector : public QObject 0053 { 0054 Q_OBJECT 0055 public: 0056 typedef std::unique_lock<KisAcyclicSignalConnector> Blocker; 0057 0058 public: 0059 0060 KisAcyclicSignalConnector(QObject *parent = 0); 0061 ~KisAcyclicSignalConnector(); 0062 0063 void connectForwardDouble(QObject *sender, const char *signal, 0064 QObject *receiver, const char *method); 0065 0066 void connectBackwardDouble(QObject *sender, const char *signal, 0067 QObject *receiver, const char *method); 0068 0069 void connectForwardInt(QObject *sender, const char *signal, 0070 QObject *receiver, const char *method); 0071 0072 void connectBackwardInt(QObject *sender, const char *signal, 0073 QObject *receiver, const char *method); 0074 0075 void connectForwardBool(QObject *sender, const char *signal, 0076 QObject *receiver, const char *method); 0077 0078 void connectBackwardBool(QObject *sender, const char *signal, 0079 QObject *receiver, const char *method); 0080 0081 void connectForwardVoid(QObject *sender, const char *signal, 0082 QObject *receiver, const char *method); 0083 0084 void connectBackwardVoid(QObject *sender, const char *signal, 0085 QObject *receiver, const char *method); 0086 0087 void connectForwardVariant(QObject *sender, const char *signal, 0088 QObject *receiver, const char *method); 0089 0090 void connectBackwardVariant(QObject *sender, const char *signal, 0091 QObject *receiver, const char *method); 0092 0093 void connectForwardResourcePair(QObject *sender, const char *signal, 0094 QObject *receiver, const char *method); 0095 0096 void connectBackwardResourcePair(QObject *sender, const char *signal, 0097 QObject *receiver, const char *method); 0098 0099 void connectForwardKoColor(QObject *sender, const char *signal, 0100 QObject *receiver, const char *method); 0101 0102 void connectBackwardKoColor(QObject *sender, const char *signal, 0103 QObject *receiver, const char *method); 0104 0105 /** 0106 * Lock the connector and all its coordinated child connectors 0107 */ 0108 void lock(); 0109 0110 /** 0111 * Unlock the connector and all its coordinated child connectors 0112 */ 0113 void unlock(); 0114 0115 /** 0116 * \return true if the connector is locked by some signal or manually. 0117 * Used for debugging purposes mostly. 0118 */ 0119 bool isLocked() const; 0120 0121 /** 0122 * @brief create a coordinated connector that can be used for extending 0123 * the number of self-locking connection. 0124 * 0125 * The coordinated connector can be used to extend the number of self-locking 0126 * connections. Each coordinated connector adds two more connection slots (forward 0127 * and backward). Lock of any connector in a coordinated group will lock the whole 0128 * group. 0129 * 0130 * The created connector is owned by *this, don't delete it! 0131 */ 0132 KisAcyclicSignalConnector *createCoordinatedConnector(); 0133 0134 private: 0135 0136 /** 0137 * Lock this connector only. 0138 */ 0139 void coordinatedLock(); 0140 0141 /** 0142 * Unlock this connector only. 0143 */ 0144 void coordinatedUnlock(); 0145 0146 private Q_SLOTS: 0147 void forwardSlotDouble(double value); 0148 void backwardSlotDouble(double value); 0149 0150 void forwardSlotInt(int value); 0151 void backwardSlotInt(int value); 0152 0153 void forwardSlotBool(bool value); 0154 void backwardSlotBool(bool value); 0155 0156 void forwardSlotVoid(); 0157 void backwardSlotVoid(); 0158 0159 void forwardSlotVariant(const QVariant &value); 0160 void backwardSlotVariant(const QVariant &value); 0161 0162 void forwardSlotResourcePair(int key, const QVariant &resource); 0163 void backwardSlotResourcePair(int key, const QVariant &resource); 0164 0165 void forwardSlotKoColor(const KoColor &value); 0166 void backwardSlotKoColor(const KoColor &value); 0167 0168 Q_SIGNALS: 0169 void forwardSignalDouble(double value); 0170 void backwardSignalDouble(double value); 0171 0172 void forwardSignalInt(int value); 0173 void backwardSignalInt(int value); 0174 0175 void forwardSignalBool(bool value); 0176 void backwardSignalBool(bool value); 0177 0178 void forwardSignalVoid(); 0179 void backwardSignalVoid(); 0180 0181 void forwardSignalVariant(const QVariant &value); 0182 void backwardSignalVariant(const QVariant &value); 0183 0184 void forwardSignalResourcePair(int key, const QVariant &value); 0185 void backwardSignalResourcePair(int key, const QVariant &value); 0186 0187 void forwardSignalKoColor(const KoColor &value); 0188 void backwardSignalKoColor(const KoColor &value); 0189 0190 private: 0191 int m_signalsBlocked; 0192 QVector<QPointer<KisAcyclicSignalConnector>> m_coordinatedConnectors; 0193 QPointer<KisAcyclicSignalConnector> m_parentConnector; 0194 }; 0195 0196 #endif /* __KIS_ACYCLIC_SIGNAL_CONNECTOR_H */