Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_node_property_list_command.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2009 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include <klocalizedstring.h>
8#include "kis_node.h"
9#include "kis_layer.h"
10#include "kis_image.h"
11#include "kis_selection_mask.h"
12#include "kis_paint_layer.h"
14#include "kis_undo_adapter.h"
16#include "kis_command_ids.h"
17
18// HACK! please refactor out!
21
22namespace {
23
24QSet<QString> changedProperties(const KisBaseNode::PropertyList &before,
25 const KisBaseNode::PropertyList &after)
26{
27 QSet<QString> changedIds;
28
29 auto valueForId = [] (const QString &id, const KisBaseNode::PropertyList &list) {
30 QVariant value;
31 Q_FOREACH (const KisBaseNode::Property &prop, list) {
32 if (prop.id == id) {
33 value = prop.state;
34 break;
35 }
36
37 }
38 return value;
39 };
40
43 const KisBaseNode::PropertyList &list1 = before.size() >= after.size() ? before : after;
44 const KisBaseNode::PropertyList &list2 = before.size() >= after.size() ? after : before;
45
46 Q_FOREACH (const KisBaseNode::Property &prop, list1) {
47 if (prop.state != valueForId(prop.id, list2)) {
48 changedIds.insert(prop.id);
49 }
50 }
51
52 return changedIds;
53}
54
55}
56
57
59 : KisNodeCommand(kundo2_i18n("Property Changes"), node),
60 m_newPropertyList(newPropertyList),
61 m_oldPropertyList(node->sectionModelProperties())
67{
68}
69
71{
73 const QSet<QString> changed = changedProperties(propsBefore, m_newPropertyList);
74 if (changed.isEmpty()) return;
75
76 const QRect oldExtent = m_node->projectionPlane()->tightUserVisibleBounds();
78
79 if (!propsWithNoUpdates().contains(changed)) {
80 doUpdate(propsBefore, m_node->sectionModelProperties(), oldExtent | m_node->projectionPlane()->tightUserVisibleBounds());
81 }
82}
83
85{
87 const QSet<QString> changed = changedProperties(propsBefore, m_oldPropertyList);
88 if (changed.isEmpty()) return;
89
90 const QRect oldExtent = m_node->projectionPlane()->tightUserVisibleBounds();
92
93 if (!propsWithNoUpdates().contains(changed)) {
94 doUpdate(propsBefore, m_node->sectionModelProperties(), oldExtent | m_node->projectionPlane()->tightUserVisibleBounds());
95 }
96}
97
102
104{
105 const KisNodePropertyListCommand *other =
106 dynamic_cast<const KisNodePropertyListCommand*>(command);
107
108 if (other && other->m_node == m_node &&
109 (changedProperties(m_oldPropertyList, m_newPropertyList).isEmpty() ||
110 changedProperties(m_oldPropertyList, m_newPropertyList) ==
111 changedProperties(other->m_oldPropertyList, other->m_newPropertyList))) {
112
113 const QSet<QString> changedInTheMeantime =
114 changedProperties(m_newPropertyList, other->m_oldPropertyList);
115
116 KIS_SAFE_ASSERT_RECOVER_NOOP(changedInTheMeantime.isEmpty() ||
117 (changedInTheMeantime.size() == 1 &&
118 *changedInTheMeantime.begin() == KisLayerPropertiesIcons::colorOverlay.id()));
119
121 return true;
122 }
123
124 return false;
125}
126
128{
129 const KisNodePropertyListCommand *other =
130 dynamic_cast<const KisNodePropertyListCommand*>(command);
131
132 return other && other->m_node == m_node &&
133 (changedProperties(m_oldPropertyList, m_newPropertyList).isEmpty() ||
134 changedProperties(m_oldPropertyList, m_newPropertyList) ==
135 changedProperties(other->m_oldPropertyList, other->m_newPropertyList));
136}
137
139{
140 const KisNodePropertyListCommand *other =
141 dynamic_cast<const KisNodePropertyListCommand*>(command);
142
143 return other && other->m_node == m_node &&
144 changedProperties(m_oldPropertyList, other->m_newPropertyList).isEmpty();
145}
146
148 const KisBaseNode::PropertyList &newPropertyList)
149{
150 return changedProperties(oldPropertyList, newPropertyList).contains(KisLayerPropertiesIcons::onionSkins.id());
151}
152
153
155 const KisBaseNode::PropertyList &newPropertyList,
156 const QRect &totalUpdateExtent)
157{
162 if (oldPropertyList == newPropertyList) {
163 return;
164 }
165
166 bool oldPassThroughValue = false;
167 bool newPassThroughValue = false;
168
169 bool oldVisibilityValue = false;
170 bool newVisibilityValue = false;
171
172 Q_FOREACH (const KisBaseNode::Property &prop, oldPropertyList) {
174 oldPassThroughValue = prop.state.toBool();
175 }
176 if (prop.id == KisLayerPropertiesIcons::visible.id()) {
177 oldVisibilityValue = prop.state.toBool();
178 }
179 }
180
181 Q_FOREACH (const KisBaseNode::Property &prop, newPropertyList) {
183 newPassThroughValue = prop.state.toBool();
184 }
185 if (prop.id == KisLayerPropertiesIcons::visible.id()) {
186 newVisibilityValue = prop.state.toBool();
187 }
188 }
189
190 if (oldPassThroughValue && !newPassThroughValue) {
191 KisLayerSP layer(qobject_cast<KisLayer*>(m_node.data()));
192 KisImageSP image = layer->image().toStrongRef();
193 if (image) {
194 image->refreshGraphAsync(layer);
195 }
196 } else if ((m_node->parent() && !oldPassThroughValue && newPassThroughValue) ||
197 (oldPassThroughValue && newPassThroughValue &&
198 !oldVisibilityValue && newVisibilityValue)) {
199
200 KisLayerSP layer(qobject_cast<KisLayer*>(m_node->parent().data()));
201 KisImageSP image = layer->image().toStrongRef();
202 if (image) {
203 image->refreshGraphAsync(layer);
204 }
205 } else if (checkOnionSkinChanged(oldPropertyList, newPropertyList)) {
206 m_node->setDirtyDontResetAnimationCache(totalUpdateExtent);
207 } else {
208 m_node->setDirty(totalUpdateExtent); // TODO check if visibility was actually changed or not
209 }
210}
211
225
227{
228 const QSet<QString> properties = changedProperties(node->sectionModelProperties(), proplist);
229
230 const bool undo = !properties.isEmpty() &&
231 properties != QSet<QString>{KisLayerPropertiesIcons::colorizeNeedsUpdate.id()} &&
232 properties != QSet<QString>{KisLayerPropertiesIcons::openFileLayerFile.id()};
233
234 QScopedPointer<KUndo2Command> cmd(new KisNodePropertyListCommand(node, proplist));
235
236 if (undo) {
237 image->undoAdapter()->addCommand(cmd.take());
238 }
239 else {
251 struct SimpleLodResettingStroke : public KisSimpleStrokeStrategy {
252 SimpleLodResettingStroke(KUndo2Command *cmd)
253 : KisSimpleStrokeStrategy(QLatin1String("SimpleLodResettingStroke")),
254 m_cmd(cmd)
255 {
256 setClearsRedoOnStart(false);
257 this->enableJob(JOB_INIT, true);
258 }
259
260 void initStrokeCallback() override {
261 m_cmd->redo();
262 // NOTE: we don't Q_EMIT imageModified signal here because this
263 // branch is only taken for the stasis changes, that do not
264 // change actual image representation.
265 }
266
267 private:
268 QScopedPointer<KUndo2Command> m_cmd;
269 };
270
271 KisStrokeId strokeId = image->startStroke(new SimpleLodResettingStroke(cmd.take()));
272 image->endStroke(strokeId);
273 }
274
275}
float value(const T *src, size_t ch)
KisUndoAdapter * undoAdapter() const
void refreshGraphAsync(KisNodeSP root, const QVector< QRect > &rects, const QRect &cropRect, KisProjectionUpdateFlags flags=KisProjectionUpdateFlag::None) override
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
void endStroke(KisStrokeId id) override
the base command for commands altering a node
The command for changing the property list of a layer.
bool mergeWith(const KUndo2Command *command) override
KisBaseNode::PropertyList m_newPropertyList
KisBaseNode::PropertyList m_oldPropertyList
static void setNodePropertiesAutoUndo(KisNodeSP node, KisImageSP image, PropertyList proplist)
KisNodePropertyListCommand(KisNodeSP node, KisBaseNode::PropertyList newPropertyList)
bool canAnnihilateWith(const KUndo2Command *other) const override
bool canMergeWith(const KUndo2Command *command) const override
void doUpdate(const KisBaseNode::PropertyList &oldPropertyList, const KisBaseNode::PropertyList &newPropertyList, const QRect &totalUpdateExtent)
static const QSet< QString > & propsWithNoUpdates()
virtual void addCommand(KUndo2Command *cmd)=0
KisSharedPtr< T > toStrongRef() const
toStrongRef returns a KisSharedPtr which may be dereferenced.
QString id() const
Definition KoID.cpp:63
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
bool checkOnionSkinChanged(const KisBaseNode::PropertyList &oldPropertyList, const KisBaseNode::PropertyList &newPropertyList)
KUndo2MagicString kundo2_i18n(const char *text)
KisImageWSP image
virtual PropertyList sectionModelProperties() const
virtual void setSectionModelProperties(const PropertyList &properties)
void setDirtyDontResetAnimationCache()
Definition kis_node.cpp:599
virtual KisAbstractProjectionPlaneSP projectionPlane() const
Definition kis_node.cpp:240
KisNodeWSP parent
Definition kis_node.cpp:86
virtual void setDirty()
Definition kis_node.cpp:577