File indexing completed on 2024-05-12 15:56:59
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_SIGNAL_COMPRESSOR_WITH_PARAM_H 0008 #define __KIS_SIGNAL_COMPRESSOR_WITH_PARAM_H 0009 0010 #include <kis_signal_compressor.h> 0011 #include <functional> 0012 0013 0014 /** 0015 * A special class that converts a Qt signal into a std::function call. 0016 * 0017 * Usage: 0018 * 0019 * \code{.cpp} 0020 * 0021 * std::function<void ()> destinationFunctionCall(std::bind(someNiceFunc, firstParam, secondParam)); 0022 * SignalToFunctionProxy proxy(destinationFunctionCall); 0023 * connect(srcObject, SIGNAL(sigSomethingChanged()), &proxy, SLOT(start())); 0024 * 0025 * \endcode 0026 * 0027 * Now every time sigSomethingChanged() is emitted, someNiceFunc is 0028 * called. std::bind allows us to call any method of any class without 0029 * changing signature of the class or creating special wrappers. 0030 */ 0031 class KRITAGLOBAL_EXPORT SignalToFunctionProxy : public QObject 0032 { 0033 Q_OBJECT 0034 public: 0035 using TrivialFunction = std::function<void ()>; 0036 0037 public: 0038 SignalToFunctionProxy(TrivialFunction function) 0039 : m_function(function) 0040 { 0041 } 0042 0043 public Q_SLOTS: 0044 void start() { 0045 m_function(); 0046 } 0047 0048 private: 0049 TrivialFunction m_function; 0050 }; 0051 0052 /** 0053 * A special class that converts a standard function call into Qt signal 0054 * 0055 * Usage: 0056 * 0057 * \code{.cpp} 0058 * 0059 * FunctionToSignalProxy proxy; 0060 * connect(&proxy, SIGNAL(timeout()), &dstObject, SLOT(someDestinationSlot())); 0061 * 0062 * \endcode 0063 * 0064 * Now every time `proxy.start()` is called, the signal `timeout()` is 0065 * forwarded to `someDestinationSlot()` 0066 */ 0067 class KRITAGLOBAL_EXPORT FunctionToSignalProxy : public QObject 0068 { 0069 Q_OBJECT 0070 0071 public: 0072 void start() { 0073 emit timeout(); 0074 } 0075 0076 Q_SIGNALS: 0077 void timeout(); 0078 }; 0079 0080 0081 0082 /** 0083 * A special class for deferring and comressing events with one 0084 * parameter of type T. This works like KisSignalCompressor but can 0085 * handle events with one parameter. Due to limitation of the Qt this 0086 * doesn't allow signal/slots, so it uses std::function instead. 0087 * 0088 * In the end (after a timeout) the latest param value is returned to 0089 * the callback. 0090 * 0091 * Usage: 0092 * 0093 * \code{.cpp} 0094 * 0095 * using namespace std::placeholders; // For _1 placeholder 0096 * 0097 * // prepare the callback function 0098 * std::function<void (qreal)> callback( 0099 * std::bind(&LutDockerDock::setCurrentExposureImpl, this, _1)); 0100 * 0101 * // Create the compressor object 0102 * KisSignalCompressorWithParam<qreal> compressor(40, callback); 0103 * 0104 * // When event comes: 0105 * compressor.start(0.123456); 0106 * 0107 * \endcode 0108 */ 0109 0110 template <typename T> 0111 class KisSignalCompressorWithParam 0112 { 0113 public: 0114 using CallbackFunction = std::function<void (T)>; 0115 0116 public: 0117 KisSignalCompressorWithParam(int delay, CallbackFunction function, KisSignalCompressor::Mode mode = KisSignalCompressor::FIRST_ACTIVE) 0118 : m_compressor(delay, mode), 0119 m_function(function) 0120 { 0121 std::function<void ()> callback( 0122 std::bind(&KisSignalCompressorWithParam<T>::fakeSlotTimeout, this)); 0123 m_signalProxy.reset(new SignalToFunctionProxy(callback)); 0124 0125 m_compressor.connect(&m_compressor, SIGNAL(timeout()), m_signalProxy.data(), SLOT(start())); 0126 } 0127 0128 ~KisSignalCompressorWithParam() 0129 { 0130 } 0131 0132 void start(T param) { 0133 m_currentParamValue = param; 0134 m_compressor.start(); 0135 } 0136 0137 void stop() { 0138 m_compressor.stop(); 0139 } 0140 0141 bool isActive() const { 0142 return m_compressor.isActive(); 0143 } 0144 0145 void setDelay(int value) { 0146 m_compressor.setDelay(value); 0147 } 0148 0149 private: 0150 void fakeSlotTimeout() { 0151 m_function(m_currentParamValue); 0152 } 0153 0154 private: 0155 KisSignalCompressor m_compressor; 0156 CallbackFunction m_function; 0157 QScopedPointer<SignalToFunctionProxy> m_signalProxy; 0158 T m_currentParamValue; 0159 }; 0160 0161 #endif /* __KIS_SIGNAL_COMPRESSOR_WITH_PARAM_H */