forked from qt-creator/qt-creator
Utils: Add Undo facilities for aspects
Change-Id: I2a8acfa23b3a4303414be21af224b08c13561666 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
using namespace Layouting;
|
using namespace Layouting;
|
||||||
|
|
||||||
@@ -84,6 +85,8 @@ public:
|
|||||||
BaseAspect::DataCreator m_dataCreator;
|
BaseAspect::DataCreator m_dataCreator;
|
||||||
BaseAspect::DataCloner m_dataCloner;
|
BaseAspect::DataCloner m_dataCloner;
|
||||||
QList<BaseAspect::DataExtractor> m_dataExtractors;
|
QList<BaseAspect::DataExtractor> m_dataExtractors;
|
||||||
|
|
||||||
|
QUndoStack *m_undoStack = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -302,6 +305,29 @@ void BaseAspect::setToolTip(const QString &tooltip)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseAspect::setUndoStack(QUndoStack *undoStack)
|
||||||
|
{
|
||||||
|
d->m_undoStack = undoStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUndoStack *BaseAspect::undoStack() const
|
||||||
|
{
|
||||||
|
return d->m_undoStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseAspect::pushUndo(QUndoCommand *cmd)
|
||||||
|
{
|
||||||
|
if (!cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d->m_undoStack)
|
||||||
|
d->m_undoStack->push(cmd);
|
||||||
|
else {
|
||||||
|
cmd->redo();
|
||||||
|
delete cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool BaseAspect::isEnabled() const
|
bool BaseAspect::isEnabled() const
|
||||||
{
|
{
|
||||||
return d->m_enabled;
|
return d->m_enabled;
|
||||||
@@ -2645,6 +2671,14 @@ bool AspectContainer::isDirty()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AspectContainer::setUndoStack(QUndoStack *undoStack)
|
||||||
|
{
|
||||||
|
BaseAspect::setUndoStack(undoStack);
|
||||||
|
|
||||||
|
for (BaseAspect *aspect : std::as_const(d->m_items))
|
||||||
|
aspect->setUndoStack(undoStack);
|
||||||
|
}
|
||||||
|
|
||||||
bool AspectContainer::equals(const AspectContainer &other) const
|
bool AspectContainer::equals(const AspectContainer &other) const
|
||||||
{
|
{
|
||||||
// FIXME: Expensive, but should not really be needed in a fully aspectified world.
|
// FIXME: Expensive, but should not really be needed in a fully aspectified world.
|
||||||
|
@@ -15,9 +15,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAction;
|
class QAction;
|
||||||
class QSettings;
|
class QSettings;
|
||||||
|
class QUndoStack;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Layouting { class LayoutItem; }
|
namespace Layouting { class LayoutItem; }
|
||||||
@@ -81,6 +84,10 @@ public:
|
|||||||
bool isAutoApply() const;
|
bool isAutoApply() const;
|
||||||
virtual void setAutoApply(bool on);
|
virtual void setAutoApply(bool on);
|
||||||
|
|
||||||
|
virtual void setUndoStack(QUndoStack *undoStack);
|
||||||
|
QUndoStack *undoStack() const;
|
||||||
|
void pushUndo(QUndoCommand *cmd);
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setEnabler(BoolAspect *checker);
|
void setEnabler(BoolAspect *checker);
|
||||||
@@ -862,6 +869,7 @@ public:
|
|||||||
void copyFrom(const AspectContainer &other);
|
void copyFrom(const AspectContainer &other);
|
||||||
void setAutoApply(bool on) override;
|
void setAutoApply(bool on) override;
|
||||||
bool isDirty() override;
|
bool isDirty() override;
|
||||||
|
void setUndoStack(QUndoStack *undoStack) override;
|
||||||
|
|
||||||
template <typename T> T *aspect() const
|
template <typename T> T *aspect() const
|
||||||
{
|
{
|
||||||
@@ -900,4 +908,61 @@ private:
|
|||||||
std::unique_ptr<Internal::AspectContainerPrivate> d;
|
std::unique_ptr<Internal::AspectContainerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Because QObject cannot be a template
|
||||||
|
class QTCREATOR_UTILS_EXPORT UndoSignaller : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
void emitChanged() { emit changed(); }
|
||||||
|
signals:
|
||||||
|
void changed();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class QTCREATOR_UTILS_EXPORT UndoableValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class UndoCmd : public QUndoCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UndoCmd(UndoableValue<T> *value, const T &oldValue, const T &newValue)
|
||||||
|
: m_value(value)
|
||||||
|
, m_oldValue(oldValue)
|
||||||
|
, m_newValue(newValue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void undo() override { m_value->setInternal(m_oldValue); }
|
||||||
|
void redo() override { m_value->setInternal(m_newValue); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
UndoableValue<T> *m_value;
|
||||||
|
T m_oldValue;
|
||||||
|
T m_newValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
QUndoCommand *set(const T &value)
|
||||||
|
{
|
||||||
|
if (m_value == value)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return new UndoCmd(this, m_value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSilently(const T &value) { m_value = value; }
|
||||||
|
|
||||||
|
T get() const { return m_value; }
|
||||||
|
|
||||||
|
UndoSignaller m_signal;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setInternal(const T &value)
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
m_signal.emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
Reference in New Issue
Block a user