[krita] libs: Fix changing default projection color in Instant Preview mode

Dmitry Kazakov dimula73 at gmail.com
Fri Apr 1 11:51:36 UTC 2016


Git commit 3855d69762342c8faf3f77b71acf02f59ef989ec by Dmitry Kazakov.
Committed on 01/04/2016 at 11:51.
Pushed by dkazakov into branch 'master'.

Fix changing default projection color in Instant Preview mode

0) Changing projection color is now undoable!

1) Now the strokes executed with KisProcessingApplicator can be merged.
   To achieve this one should pass a macroId parameter to its c-tor.

CC:kimageshop at kde.org

Fixes T1228

M  +1    -0    libs/image/CMakeLists.txt
A  +68   -0    libs/image/commands_new/kis_change_projection_color_command.cpp     [License: GPL (v2+)]
A  +48   -0    libs/image/commands_new/kis_change_projection_color_command.h     [License: GPL (v2+)]
M  +58   -0    libs/image/commands_new/kis_saved_commands.cpp
M  +5    -0    libs/image/commands_new/kis_saved_commands.h
M  +10   -0    libs/image/kis_paint_device_data.h
M  +4    -1    libs/image/kis_processing_applicator.cpp
M  +2    -1    libs/image/kis_processing_applicator.h
M  +9    -1    libs/image/kis_stroke_strategy_undo_command_based.cpp
M  +11   -1    libs/image/kis_stroke_strategy_undo_command_based.h
M  +14   -2    libs/ui/dialogs/kis_dlg_image_properties.cc

http://commits.kde.org/krita/3855d69762342c8faf3f77b71acf02f59ef989ec

diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt
index 271d471..7b4599a 100644
--- a/libs/image/CMakeLists.txt
+++ b/libs/image/CMakeLists.txt
@@ -92,6 +92,7 @@ set(kritaimage_LIB_SRCS
    commands_new/kis_selection_move_command2.cpp
    commands_new/kis_update_command.cpp
    commands_new/kis_switch_current_time_command.cpp
+   commands_new/kis_change_projection_color_command.cpp
    commands_new/kis_activate_selection_mask_command.cpp
    processing/kis_do_nothing_processing_visitor.cpp
    processing/kis_simple_processing_visitor.cpp
diff --git a/libs/image/commands_new/kis_change_projection_color_command.cpp b/libs/image/commands_new/kis_change_projection_color_command.cpp
new file mode 100644
index 0000000..6cc1605
--- /dev/null
+++ b/libs/image/commands_new/kis_change_projection_color_command.cpp
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2015 Dmitry Kazakov <dimula73 at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_change_projection_color_command.h"
+
+#include "kis_image.h"
+#include "kis_image_animation_interface.h"
+
+
+
+KisChangeProjectionColorCommand::KisChangeProjectionColorCommand(KisImageSP image, const KoColor &newColor, KUndo2Command *parent)
+    : KUndo2Command(kundo2_noi18n("CHANGE_PROJECTION_COLOR_COMMAND"), parent),
+      m_image(image),
+      m_oldColor(image->defaultProjectionColor()),
+      m_newColor(newColor)
+{
+}
+
+KisChangeProjectionColorCommand::~KisChangeProjectionColorCommand()
+{
+}
+
+int KisChangeProjectionColorCommand::id() const
+{
+    // we don't have a common commands id source in Krita yet, so
+    // just use a random one ;)
+
+    // http://www.scientificamerican.com/article/most-popular-numbers-grapes-of-math/
+    return 142857;
+}
+
+bool KisChangeProjectionColorCommand::mergeWith(const KUndo2Command* command)
+{
+    const KisChangeProjectionColorCommand *other =
+        dynamic_cast<const KisChangeProjectionColorCommand*>(command);
+
+    if (!other || other->id() != id()) {
+        return false;
+    }
+
+    m_newColor = other->m_newColor;
+    return true;
+}
+
+void KisChangeProjectionColorCommand::redo()
+{
+    m_image->setDefaultProjectionColor(m_newColor);
+}
+
+void KisChangeProjectionColorCommand::undo()
+{
+    m_image->setDefaultProjectionColor(m_oldColor);
+}
diff --git a/libs/image/commands_new/kis_change_projection_color_command.h b/libs/image/commands_new/kis_change_projection_color_command.h
new file mode 100644
index 0000000..e57e9ae
--- /dev/null
+++ b/libs/image/commands_new/kis_change_projection_color_command.h
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2015 Dmitry Kazakov <dimula73 at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_CHANGE_PROJECTION_COLOR_COMMAND_H
+#define __KIS_CHANGE_PROJECTION_COLOR_COMMAND_H
+
+#include "kritaimage_export.h"
+#include "kis_types.h"
+
+#include <KoColor.h>
+
+#include <kundo2command.h>
+
+
+class KRITAIMAGE_EXPORT KisChangeProjectionColorCommand : public KUndo2Command
+{
+public:
+    KisChangeProjectionColorCommand(KisImageSP image, const KoColor &newColor, KUndo2Command *parent = 0);
+    ~KisChangeProjectionColorCommand();
+
+    void redo();
+    void undo();
+
+    int id() const;
+    bool mergeWith(const KUndo2Command* command);
+
+private:
+    KisImageWSP m_image;
+    KoColor m_oldColor;
+    KoColor m_newColor;
+};
+
+#endif /* __KIS_CHANGE_PROJECTION_COLOR_COMMAND_H */
diff --git a/libs/image/commands_new/kis_saved_commands.cpp b/libs/image/commands_new/kis_saved_commands.cpp
index d203ea7..44d1f2d 100644
--- a/libs/image/commands_new/kis_saved_commands.cpp
+++ b/libs/image/commands_new/kis_saved_commands.cpp
@@ -157,6 +157,7 @@ struct KisSavedMacroCommand::Private
     };
 
     QVector<SavedCommand> commands;
+    int macroId = -1;
 };
 
 KisSavedMacroCommand::KisSavedMacroCommand(const KUndo2MagicString &name,
@@ -171,6 +172,63 @@ KisSavedMacroCommand::~KisSavedMacroCommand()
     delete m_d;
 }
 
+void KisSavedMacroCommand::setMacroId(int value)
+{
+    m_d->macroId = value;
+}
+
+int KisSavedMacroCommand::id() const
+{
+    return m_d->macroId;
+}
+
+bool KisSavedMacroCommand::mergeWith(const KUndo2Command* command)
+{
+    const KisSavedMacroCommand *other =
+        dynamic_cast<const KisSavedMacroCommand*>(command);
+
+    if (other && other->id() != id()) return false;
+
+    QVector<Private::SavedCommand> &otherCommands = other->m_d->commands;
+
+    if (m_d->commands.size() != otherCommands.size()) return false;
+
+    auto it = m_d->commands.constBegin();
+    auto end = m_d->commands.constEnd();
+
+    auto otherIt = otherCommands.constBegin();
+    auto otherEnd = otherCommands.constEnd();
+
+    bool sameCommands = true;
+    while (it != end && otherIt != otherEnd) {
+        if (it->command->id() != otherIt->command->id() ||
+            it->sequentiality != otherIt->sequentiality ||
+            it->exclusivity != otherIt->exclusivity) {
+
+            sameCommands = false;
+            break;
+        }
+        ++it;
+        ++otherIt;
+    }
+
+    if (!sameCommands) return false;
+
+    it = m_d->commands.constBegin();
+    otherIt = otherCommands.constBegin();
+
+    while (it != end && otherIt != otherEnd) {
+        if (it->command->id() != -1) {
+            bool result = it->command->mergeWith(otherIt->command.data());
+            KIS_ASSERT_RECOVER(result) { return false; }
+        }
+        ++it;
+        ++otherIt;
+    }
+
+    return true;
+}
+
 void KisSavedMacroCommand::addCommand(KUndo2CommandSP command,
                                       KisStrokeJobData::Sequentiality sequentiality,
                                       KisStrokeJobData::Exclusivity exclusivity)
diff --git a/libs/image/commands_new/kis_saved_commands.h b/libs/image/commands_new/kis_saved_commands.h
index 014125c..a5fce66 100644
--- a/libs/image/commands_new/kis_saved_commands.h
+++ b/libs/image/commands_new/kis_saved_commands.h
@@ -79,6 +79,11 @@ public:
     KisSavedMacroCommand(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade);
     ~KisSavedMacroCommand();
 
+    int id() const;
+    bool mergeWith(const KUndo2Command* command);
+
+    void setMacroId(int value);
+
     void addCommand(KUndo2CommandSP command,
                     KisStrokeJobData::Sequentiality sequentiality = KisStrokeJobData::SEQUENTIAL,
                     KisStrokeJobData::Exclusivity exclusivity = KisStrokeJobData::NORMAL);
diff --git a/libs/image/kis_paint_device_data.h b/libs/image/kis_paint_device_data.h
index 0112348..c5873ae 100644
--- a/libs/image/kis_paint_device_data.h
+++ b/libs/image/kis_paint_device_data.h
@@ -198,6 +198,16 @@ public:
             m_cache.setupCache();
         } else {
             m_dataManager->clear();
+            const quint8 *srcDefPixel = srcData->dataManager()->defaultPixel();
+
+            const int cmp =
+                memcmp(srcDefPixel,
+                       m_dataManager->defaultPixel(),
+                       m_dataManager->pixelSize());
+
+            if (cmp != 0) {
+                m_dataManager->setDefaultPixel(srcDefPixel);
+            }
         }
 
         m_levelOfDetail = srcData->levelOfDetail();
diff --git a/libs/image/kis_processing_applicator.cpp b/libs/image/kis_processing_applicator.cpp
index ef5e696..bb13430 100644
--- a/libs/image/kis_processing_applicator.cpp
+++ b/libs/image/kis_processing_applicator.cpp
@@ -165,7 +165,8 @@ KisProcessingApplicator::KisProcessingApplicator(KisImageWSP image,
                                                  ProcessingFlags flags,
                                                  KisImageSignalVector emitSignals,
                                                  const KUndo2MagicString &name,
-                                                 KUndo2CommandExtraData *extraData)
+                                                 KUndo2CommandExtraData *extraData,
+                                                 int macroId)
     : m_image(image),
       m_node(node),
       m_flags(flags),
@@ -184,6 +185,8 @@ KisProcessingApplicator::KisProcessingApplicator(KisImageWSP image,
         strategy->setCommandExtraData(extraData);
     }
 
+    strategy->setMacroId(macroId);
+
     m_strokeId = m_image->startStroke(strategy);
     if(!m_emitSignals.isEmpty()) {
         applyCommand(new EmitImageSignalsCommand(m_image, m_emitSignals, false), KisStrokeJobData::BARRIER);
diff --git a/libs/image/kis_processing_applicator.h b/libs/image/kis_processing_applicator.h
index e2b0d22..7e563f6 100644
--- a/libs/image/kis_processing_applicator.h
+++ b/libs/image/kis_processing_applicator.h
@@ -46,7 +46,8 @@ public:
                             ProcessingFlags flags = NONE,
                             KisImageSignalVector emitSignals = KisImageSignalVector(),
                             const KUndo2MagicString &name = KUndo2MagicString(),
-                            KUndo2CommandExtraData *extraData = 0);
+                            KUndo2CommandExtraData *extraData = 0,
+                            int macroId = -1);
 
     ~KisProcessingApplicator();
 
diff --git a/libs/image/kis_stroke_strategy_undo_command_based.cpp b/libs/image/kis_stroke_strategy_undo_command_based.cpp
index c36659b1..741fcf3 100644
--- a/libs/image/kis_stroke_strategy_undo_command_based.cpp
+++ b/libs/image/kis_stroke_strategy_undo_command_based.cpp
@@ -34,6 +34,7 @@ KisStrokeStrategyUndoCommandBased(const KUndo2MagicString &name,
     m_initCommand(initCommand),
     m_finishCommand(finishCommand),
     m_undoAdapter(undoAdapter),
+    m_macroId(-1),
     m_macroCommand(0)
 {
     enableJob(KisSimpleStrokeStrategy::JOB_INIT);
@@ -151,9 +152,16 @@ void KisStrokeStrategyUndoCommandBased::setCommandExtraData(KUndo2CommandExtraDa
     m_commandExtraData.reset(data);
 }
 
-void KisStrokeStrategyUndoCommandBased::postProcessToplevelCommand(KUndo2Command *command)
+void KisStrokeStrategyUndoCommandBased::setMacroId(int value)
+{
+    m_macroId = value;
+}
+
+void KisStrokeStrategyUndoCommandBased::postProcessToplevelCommand(KisSavedMacroCommand *command)
 {
     if (m_commandExtraData) {
         command->setExtraData(m_commandExtraData.take());
     }
+
+    command->setMacroId(m_macroId);
 }
diff --git a/libs/image/kis_stroke_strategy_undo_command_based.h b/libs/image/kis_stroke_strategy_undo_command_based.h
index b41f977..5d6ebc9 100644
--- a/libs/image/kis_stroke_strategy_undo_command_based.h
+++ b/libs/image/kis_stroke_strategy_undo_command_based.h
@@ -89,6 +89,15 @@ public:
     void setCommandExtraData(KUndo2CommandExtraData *data);
 
     /**
+     * Sets the id of this action. Will be used for merging the undo commands
+     *
+     * The \p value must be set *before* the stroke has been started.
+     * Setting the \p value after the stroke has been started with
+     * image->startStroke(strokeId) leads to an undefined behaviour.
+     */
+    void setMacroId(int value);
+
+    /**
      * The undo-command-based is a low-level strategy, so it allows
      * changing its wraparound mode status.
      *
@@ -110,7 +119,7 @@ protected:
     KisStrokeStrategyUndoCommandBased(const KisStrokeStrategyUndoCommandBased &rhs,
                                       bool suppressUndo);
 
-    virtual void postProcessToplevelCommand(KUndo2Command *command);
+    virtual void postProcessToplevelCommand(KisSavedMacroCommand *command);
 
 private:
     void executeCommand(KUndo2CommandSP command, bool undo);
@@ -122,6 +131,7 @@ private:
     KisPostExecutionUndoAdapter *m_undoAdapter;
 
     QScopedPointer<KUndo2CommandExtraData> m_commandExtraData;
+    int m_macroId;
 
     // protects done commands only
     QMutex m_mutex;
diff --git a/libs/ui/dialogs/kis_dlg_image_properties.cc b/libs/ui/dialogs/kis_dlg_image_properties.cc
index e1d7f1d..f30b41c 100644
--- a/libs/ui/dialogs/kis_dlg_image_properties.cc
+++ b/libs/ui/dialogs/kis_dlg_image_properties.cc
@@ -41,6 +41,8 @@
 #include "kis_annotation.h"
 #include "kis_config.h"
 #include "kis_signal_compressor.h"
+#include "kis_processing_applicator.h"
+#include "commands_new/kis_change_projection_color_command.h"
 #include "widgets/kis_cmb_idlist.h"
 #include "widgets/squeezedcombobox.h"
 
@@ -111,8 +113,18 @@ const KoColorSpace * KisDlgImageProperties::colorSpace()
 
 void KisDlgImageProperties::setCurrentColor()
 {
-    m_image->setDefaultProjectionColor(m_defaultColorAction->currentKoColor());
-    m_image->refreshGraphAsync();
+    KisImageSignalVector emitSignals;
+    emitSignals << ModifiedSignal;
+
+    KisProcessingApplicator applicator(m_image,
+                                       m_image->root(),
+                                       KisProcessingApplicator::RECURSIVE,
+                                       emitSignals,
+                                       kundo2_i18n("Change projection color"),
+                                       0,
+                                       142857 + 1);
+    applicator.applyCommand(new KisChangeProjectionColorCommand(m_image, m_defaultColorAction->currentKoColor()));
+    applicator.end();
 }
 
 void KisDlgImageProperties::setAnnotation(const QString &type)


More information about the kimageshop mailing list