File indexing completed on 2024-05-12 15:58:22
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_image_signal_router.h" 0008 0009 #include <QThread> 0010 0011 #include "kis_image.h" 0012 0013 0014 #define CONNECT_TO_IMAGE(signal) \ 0015 connect(this, SIGNAL(signal), m_image, SIGNAL(signal), Qt::DirectConnection) 0016 0017 #define CONNECT_TO_IMAGE_QUEUED(signal) \ 0018 connect(this, SIGNAL(signal), m_image, SIGNAL(signal), Qt::QueuedConnection) 0019 0020 0021 struct ImageSignalsStaticRegistrar { 0022 ImageSignalsStaticRegistrar() { 0023 qRegisterMetaType<KisImageSignalType>("KisImageSignalType"); 0024 } 0025 }; 0026 static ImageSignalsStaticRegistrar __registrar; 0027 0028 0029 KisImageSignalRouter::KisImageSignalRouter(KisImageWSP image) 0030 : QObject(image.data()), 0031 m_image(image) 0032 { 0033 connect(this, SIGNAL(sigNotification(KisImageSignalType)), 0034 SLOT(slotNotification(KisImageSignalType))); 0035 0036 CONNECT_TO_IMAGE(sigImageModified()); 0037 CONNECT_TO_IMAGE(sigImageModifiedWithoutUndo()); 0038 CONNECT_TO_IMAGE(sigSizeChanged(const QPointF&, const QPointF&)); 0039 CONNECT_TO_IMAGE(sigResolutionChanged(double, double)); 0040 CONNECT_TO_IMAGE(sigRequestNodeReselection(KisNodeSP, const KisNodeList&)); 0041 0042 CONNECT_TO_IMAGE(sigNodeChanged(KisNodeSP)); 0043 CONNECT_TO_IMAGE(sigNodeAddedAsync(KisNodeSP)); 0044 CONNECT_TO_IMAGE(sigRemoveNodeAsync(KisNodeSP)); 0045 CONNECT_TO_IMAGE(sigLayersChangedAsync()); 0046 0047 /** 0048 * Color space and profile conversion functions run without storkes, 0049 * therefore they are executed in GUI hread under the global lock held. 0050 * 0051 * To ensure that the receiver of the signal will not deadlock by 0052 * barrier-locking the image, we should make these signals queued. 0053 */ 0054 0055 CONNECT_TO_IMAGE_QUEUED(sigProfileChanged(const KoColorProfile*)); 0056 CONNECT_TO_IMAGE_QUEUED(sigColorSpaceChanged(const KoColorSpace*)); 0057 } 0058 0059 KisImageSignalRouter::~KisImageSignalRouter() 0060 { 0061 } 0062 0063 void KisImageSignalRouter::emitImageModifiedNotification() 0064 { 0065 emit sigImageModified(); 0066 } 0067 0068 void KisImageSignalRouter::emitNotifications(KisImageSignalVector notifications) 0069 { 0070 Q_FOREACH (const KisImageSignalType &type, notifications) { 0071 emitNotification(type); 0072 } 0073 } 0074 0075 void KisImageSignalRouter::emitNotification(KisImageSignalType type) 0076 { 0077 /** 0078 * All the notifications except LayersChangedSignal should go in a 0079 * queued way. And LayersChangedSignal should be delivered to the 0080 * recipients in a non-reordered way 0081 */ 0082 0083 if (type.id == LayersChangedSignal || 0084 type.id == NodeReselectionRequestSignal) { 0085 slotNotification(type); 0086 } else { 0087 emit sigNotification(type); 0088 } 0089 } 0090 0091 void KisImageSignalRouter::emitNodeChanged(KisNodeSP node) 0092 { 0093 emit sigNodeChanged(node); 0094 } 0095 0096 void KisImageSignalRouter::emitNodeHasBeenAdded(KisNode *parent, int index) 0097 { 0098 KisNodeSP newNode = parent->at(index); 0099 0100 // overlay selection masks reset frames themselves 0101 if (!newNode->inherits("KisSelectionMask")) { 0102 KisImageSP image = m_image.toStrongRef(); 0103 if (image) { 0104 image->invalidateAllFrames(); 0105 } 0106 } 0107 0108 emit sigNodeAddedAsync(newNode); 0109 } 0110 0111 void KisImageSignalRouter::emitAboutToRemoveANode(KisNode *parent, int index) 0112 { 0113 KisNodeSP removedNode = parent->at(index); 0114 0115 // overlay selection masks reset frames themselves 0116 if (!removedNode->inherits("KisSelectionMask")) { 0117 KisImageSP image = m_image.toStrongRef(); 0118 if (image) { 0119 image->invalidateAllFrames(); 0120 } 0121 } 0122 0123 emit sigRemoveNodeAsync(removedNode); 0124 } 0125 0126 void KisImageSignalRouter::emitRequestLodPlanesSyncBlocked(bool value) 0127 { 0128 emit sigRequestLodPlanesSyncBlocked(value); 0129 } 0130 0131 void KisImageSignalRouter::emitNotifyBatchUpdateStarted() 0132 { 0133 emit sigNotifyBatchUpdateStarted(); 0134 } 0135 0136 void KisImageSignalRouter::emitNotifyBatchUpdateEnded() 0137 { 0138 emit sigNotifyBatchUpdateEnded(); 0139 } 0140 0141 void KisImageSignalRouter::slotNotification(KisImageSignalType type) 0142 { 0143 KisImageSP image = m_image.toStrongRef(); 0144 if (!image) { 0145 return; 0146 } 0147 0148 switch(type.id) { 0149 case LayersChangedSignal: 0150 image->invalidateAllFrames(); 0151 emit sigLayersChangedAsync(); 0152 break; 0153 case ModifiedWithoutUndoSignal: 0154 emit sigImageModifiedWithoutUndo(); 0155 break; 0156 case SizeChangedSignal: 0157 image->invalidateAllFrames(); 0158 emit sigSizeChanged(type.sizeChangedSignal.oldStillPoint, 0159 type.sizeChangedSignal.newStillPoint); 0160 break; 0161 case ProfileChangedSignal: 0162 image->invalidateAllFrames(); 0163 emit sigProfileChanged(image->profile()); 0164 break; 0165 case ColorSpaceChangedSignal: 0166 image->invalidateAllFrames(); 0167 emit sigColorSpaceChanged(image->colorSpace()); 0168 break; 0169 case ResolutionChangedSignal: 0170 image->invalidateAllFrames(); 0171 emit sigResolutionChanged(image->xRes(), image->yRes()); 0172 break; 0173 case NodeReselectionRequestSignal: 0174 if (type.nodeReselectionSignal.newActiveNode || 0175 !type.nodeReselectionSignal.newSelectedNodes.isEmpty()) { 0176 0177 emit sigRequestNodeReselection(type.nodeReselectionSignal.newActiveNode, 0178 type.nodeReselectionSignal.newSelectedNodes); 0179 } 0180 break; 0181 } 0182 }