Commit 89daca00 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Add undo-redo copabilities to the Layer Properties dialog

parent 7167c6be
......@@ -26,7 +26,7 @@
class KisStrokesFacade;
class KisSavedCommandBase : public KUndo2Command
class KRITAIMAGE_EXPORT KisSavedCommandBase : public KUndo2Command
{
public:
KisSavedCommandBase(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade);
......@@ -48,7 +48,7 @@ private:
bool m_skipOneRedo;
};
class KisSavedCommand : public KisSavedCommandBase
class KRITAIMAGE_EXPORT KisSavedCommand : public KisSavedCommandBase
{
public:
KisSavedCommand(KUndo2CommandSP command, KisStrokesFacade *strokesFacade);
......@@ -73,15 +73,15 @@ private:
KUndo2CommandSP m_command;
};
class KisSavedMacroCommand : public KisSavedCommandBase
class KRITAIMAGE_EXPORT KisSavedMacroCommand : public KisSavedCommandBase
{
public:
KisSavedMacroCommand(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade);
~KisSavedMacroCommand();
void addCommand(KUndo2CommandSP command,
KisStrokeJobData::Sequentiality sequentiality,
KisStrokeJobData::Exclusivity exclusivity);
KisStrokeJobData::Sequentiality sequentiality = KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::Exclusivity exclusivity = KisStrokeJobData::NORMAL);
void performCancel(KisStrokeId id, bool strokeUndo);
......
......@@ -810,4 +810,20 @@ namespace KisLayerUtils {
mergeMultipleLayersImpl(image, mergedNodes, 0, true, kundo2_i18n("Flatten Image"));
}
KisSimpleUpdateCommand::KisSimpleUpdateCommand(KisNodeList nodes, bool finalize, KUndo2Command *parent)
: FlipFlopCommand(finalize, parent),
m_nodes(nodes)
{
}
void KisSimpleUpdateCommand::end()
{
updateNodes(m_nodes);
}
void KisSimpleUpdateCommand::updateNodes(const KisNodeList &nodes)
{
Q_FOREACH(KisNodeSP node, nodes) {
node->setDirty(node->extent());
}
}
}
......@@ -87,6 +87,16 @@ namespace KisLayerUtils
private:
bool checkIsSourceForClone(KisNodeSP src, const QList<KisNodeSP> &nodes);
};
class KRITAIMAGE_EXPORT KisSimpleUpdateCommand : public KisCommandUtils::FlipFlopCommand
{
public:
KisSimpleUpdateCommand(KisNodeList nodes, bool finalize, KUndo2Command *parent = 0);
void end();
static void updateNodes(const KisNodeList &nodes);
private:
KisNodeList m_nodes;
};
};
#endif /* __KIS_LAYER_UTILS_H */
......@@ -41,6 +41,8 @@
#include "kis_image.h"
#include "kis_layer_properties_icons.h"
#include "kis_signal_compressor.h"
#include "commands_new/kis_saved_commands.h"
#include "kis_post_execution_undo_adapter.h"
struct KisDlgLayerProperties::Private
......@@ -191,7 +193,18 @@ KisDlgLayerProperties::~KisDlgLayerProperties()
d->updatesCompressor.stop();
updatePreview();
}
// TODO: save the undo command
KisPostExecutionUndoAdapter *adapter =
d->view->image()->postExecutionUndoAdapter();
KisSavedMacroCommand *macro = adapter->createMacro(kundo2_i18n("Change Layer Properties"));
macro->addCommand(toQShared(new KisLayerUtils::KisSimpleUpdateCommand(d->nodes, false)));
Q_FOREACH(auto prop, d->allProperties()) {
if (!prop->isIgnored()) {
macro->addCommand(toQShared(prop->createPostExecutionUndoCommand()));
}
}
macro->addCommand(toQShared(new KisLayerUtils::KisSimpleUpdateCommand(d->nodes, true)));
adapter->addMacro(macro);
}
else /* if (result() == QDialog::Rejected) */ {
Q_FOREACH(auto prop, d->allProperties()) {
......@@ -254,7 +267,5 @@ void KisDlgLayerProperties::slotFlagsValueChangedInternally()
void KisDlgLayerProperties::updatePreview()
{
Q_FOREACH(KisNodeSP node, d->nodes) {
node->setDirty(node->extent());
}
KisLayerUtils::KisSimpleUpdateCommand::updateNodes(d->nodes);
}
......@@ -25,6 +25,7 @@
#include <QRegExp>
#include <QBitArray>
#include <kundo2command.h>
#include <KoColorSpace.h>
#include <KoChannelInfo.h>
......@@ -402,6 +403,52 @@ private:
PropertyType *m_parent;
};
/******************************************************************/
/* MultinodePropertyUndoCommand */
/******************************************************************/
template <class PropertyAdapter>
class MultinodePropertyUndoCommand : public KUndo2Command
{
public:
typedef typename PropertyAdapter::ValueType ValueType;
public:
MultinodePropertyUndoCommand(PropertyAdapter propAdapter,
KisNodeList nodes,
const QList<ValueType> &oldValues,
ValueType newValue,
KUndo2Command *parent = 0)
: KUndo2Command(parent),
m_propAdapter(propAdapter),
m_nodes(nodes),
m_oldValues(oldValues),
m_newValue(newValue)
{
}
void undo() {
int index = 0;
Q_FOREACH (KisNodeSP node, m_nodes) {
m_propAdapter.setPropForNode(node, m_oldValues[index], -1);
index++;
}
}
void redo() {
int index = 0;
Q_FOREACH (KisNodeSP node, m_nodes) {
m_propAdapter.setPropForNode(node, m_newValue, index);
index++;
}
}
private:
PropertyAdapter m_propAdapter;
KisNodeList m_nodes;
QList<ValueType> m_oldValues;
ValueType m_newValue;
};
/******************************************************************/
/* KisMultinodePropertyInterface */
/******************************************************************/
......@@ -422,6 +469,8 @@ public:
virtual void connectValueChangedSignal(const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection) = 0;
virtual void connectIgnoreCheckBox(QCheckBox *ignoreBox) = 0;
virtual KUndo2Command* createPostExecutionUndoCommand() = 0;
};
typedef QSharedPointer<KisMultinodePropertyInterface> KisMultinodePropertyInterfaceSP;
......@@ -532,6 +581,13 @@ public:
return m_isIgnored;
}
KUndo2Command* createPostExecutionUndoCommand() {
KIS_ASSERT_RECOVER(!m_isIgnored) { return new KUndo2Command(); }
return new MultinodePropertyUndoCommand<PropertyAdapter>(m_propAdapter, m_nodes,
m_savedValues, m_currentValue);
}
// TODO: disconnect methods...
void connectIgnoreCheckBox(QCheckBox *ignoreBox) {
m_connector->connectIgnoreCheckBox(ignoreBox);
......
......@@ -39,6 +39,7 @@ void KisMultinodePropertyTest::test()
nodes << layer2;
nodes << layer3;
// Test uniform initial state
{
QScopedPointer<QCheckBox> box(new QCheckBox("test ignore"));
KisMultinodeCompositeOpProperty prop(nodes);
......@@ -78,6 +79,8 @@ void KisMultinodePropertyTest::test()
QCOMPARE(box->isChecked(), true);
}
// Test non-uniform initial state
layer1->setCompositeOpId(COMPOSITE_ALPHA_DARKEN);
layer2->setCompositeOpId(COMPOSITE_OVER);
layer3->setCompositeOpId(COMPOSITE_OVER);
......@@ -124,6 +127,38 @@ void KisMultinodePropertyTest::test()
QCOMPARE(box->isEnabled(), true);
QCOMPARE(box->isChecked(), false);
}
// Test undo-redo
{
QScopedPointer<QCheckBox> box(new QCheckBox("test ignore"));
KisMultinodeCompositeOpProperty prop(nodes);
prop.connectIgnoreCheckBox(box.data());
QCOMPARE(layer1->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer2->compositeOpId(), COMPOSITE_OVER);
QCOMPARE(layer3->compositeOpId(), COMPOSITE_OVER);
prop.setIgnored(false);
QCOMPARE(layer1->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer2->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer3->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QScopedPointer<KUndo2Command> cmd(prop.createPostExecutionUndoCommand());
cmd->undo();
QCOMPARE(layer1->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer2->compositeOpId(), COMPOSITE_OVER);
QCOMPARE(layer3->compositeOpId(), COMPOSITE_OVER);
cmd->redo();
QCOMPARE(layer1->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer2->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
QCOMPARE(layer3->compositeOpId(), COMPOSITE_ALPHA_DARKEN);
}
}
QTEST_MAIN(KisMultinodePropertyTest)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment