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 <QSpinBox>
|
||||
#include <QTextEdit>
|
||||
#include <QUndoStack>
|
||||
|
||||
using namespace Layouting;
|
||||
|
||||
@@ -84,6 +85,8 @@ public:
|
||||
BaseAspect::DataCreator m_dataCreator;
|
||||
BaseAspect::DataCloner m_dataCloner;
|
||||
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
|
||||
{
|
||||
return d->m_enabled;
|
||||
@@ -2645,6 +2671,14 @@ bool AspectContainer::isDirty()
|
||||
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
|
||||
{
|
||||
// FIXME: Expensive, but should not really be needed in a fully aspectified world.
|
||||
|
@@ -15,9 +15,12 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QSettings;
|
||||
class QUndoStack;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Layouting { class LayoutItem; }
|
||||
@@ -81,6 +84,10 @@ public:
|
||||
bool isAutoApply() const;
|
||||
virtual void setAutoApply(bool on);
|
||||
|
||||
virtual void setUndoStack(QUndoStack *undoStack);
|
||||
QUndoStack *undoStack() const;
|
||||
void pushUndo(QUndoCommand *cmd);
|
||||
|
||||
bool isEnabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
void setEnabler(BoolAspect *checker);
|
||||
@@ -862,6 +869,7 @@ public:
|
||||
void copyFrom(const AspectContainer &other);
|
||||
void setAutoApply(bool on) override;
|
||||
bool isDirty() override;
|
||||
void setUndoStack(QUndoStack *undoStack) override;
|
||||
|
||||
template <typename T> T *aspect() const
|
||||
{
|
||||
@@ -900,4 +908,61 @@ private:
|
||||
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
|
||||
|
Reference in New Issue
Block a user