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