diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2020-03-10 15:40:56 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-03-30 12:36:29 +0200 |
commit | 3f73995a03c4b40e2648cb9af5d3e7ca393bf597 (patch) | |
tree | f7f9f4c63a5506287de4d44d4f01cdc57e093a27 /src/widgets/util | |
parent | adc1be3c33b4237a13e423c140bcb1c06aeb11d9 (diff) |
Move undo framework out of Qt Widgets
- Moves QUndo* classes (except QUndoView) from src/widgets/utils to src/gui/utils
- Moves related auto tests from widgets to gui
- Replaces QUndoAction with lambdas that do text prefixing
[ChangeLog][Undo Framework] QUndo* classes (except QUndoView) were moved from Qt
Widgets to Qt GUI.
Done-with: volker.hilsheimer@qt.io
Fixes: QTBUG-40040
Change-Id: I3bd8d4d32c64f8dee548f62159a1df2126da89d8
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/widgets/util')
-rw-r--r-- | src/widgets/util/qundogroup.cpp | 502 | ||||
-rw-r--r-- | src/widgets/util/qundogroup.h | 101 | ||||
-rw-r--r-- | src/widgets/util/qundostack.cpp | 1388 | ||||
-rw-r--r-- | src/widgets/util/qundostack.h | 159 | ||||
-rw-r--r-- | src/widgets/util/qundostack_p.h | 115 | ||||
-rw-r--r-- | src/widgets/util/qundoview.cpp | 4 | ||||
-rw-r--r-- | src/widgets/util/util.pri | 13 |
7 files changed, 2 insertions, 2280 deletions
diff --git a/src/widgets/util/qundogroup.cpp b/src/widgets/util/qundogroup.cpp deleted file mode 100644 index ae439743bc..0000000000 --- a/src/widgets/util/qundogroup.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qundogroup.h" -#include "qundostack.h" -#include "qundostack_p.h" - -QT_BEGIN_NAMESPACE - -class QUndoGroupPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QUndoGroup) -public: - QUndoGroupPrivate() : active(nullptr) {} - - QUndoStack *active; - QList<QUndoStack*> stack_list; -}; - -/*! - \class QUndoGroup - \brief The QUndoGroup class is a group of QUndoStack objects. - \since 4.2 - \inmodule QtWidgets - - For an overview of the Qt's undo framework, see the - \l{qundo.html}{overview}. - - An application often has multiple undo stacks, one for each opened document. At the - same time, an application usually has one undo action and one redo action, which - triggers undo or redo in the active document. - - QUndoGroup is a group of QUndoStack objects, one of which may be active. It has - an undo() and redo() slot, which calls QUndoStack::undo() and QUndoStack::redo() - for the active stack. It also has the functions createUndoAction() and createRedoAction(). - The actions returned by these functions behave in the same way as those returned by - QUndoStack::createUndoAction() and QUndoStack::createRedoAction() of the active - stack. - - Stacks are added to a group with addStack() and removed with removeStack(). A stack - is implicitly added to a group when it is created with the group as its parent - QObject. - - It is the programmer's responsibility to specify which stack is active by - calling QUndoStack::setActive(), usually when the associated document window receives focus. - The active stack may also be set with setActiveStack(), and is returned by activeStack(). - - When a stack is added to a group using addStack(), the group does not take ownership - of the stack. This means the stack has to be deleted separately from the group. When - a stack is deleted, it is automatically removed from a group. A stack may belong to - only one group. Adding it to another group will cause it to be removed from the previous - group. - - A QUndoGroup is also useful in conjunction with QUndoView. If a QUndoView is - set to watch a group using QUndoView::setGroup(), it will update itself to display - the active stack. -*/ - -/*! - Creates an empty QUndoGroup object with parent \a parent. - - \sa addStack() -*/ - -QUndoGroup::QUndoGroup(QObject *parent) - : QObject(*new QUndoGroupPrivate(), parent) -{ -} - -/*! - Destroys the QUndoGroup. -*/ -QUndoGroup::~QUndoGroup() -{ - // Ensure all QUndoStacks no longer refer to this group. - Q_D(QUndoGroup); - QList<QUndoStack *>::iterator it = d->stack_list.begin(); - QList<QUndoStack *>::iterator end = d->stack_list.end(); - while (it != end) { - (*it)->d_func()->group = nullptr; - ++it; - } -} - -/*! - Adds \a stack to this group. The group does not take ownership of the stack. Another - way of adding a stack to a group is by specifying the group as the stack's parent - QObject in QUndoStack::QUndoStack(). In this case, the stack is deleted when the - group is deleted, in the usual manner of QObjects. - - \sa removeStack(), stacks(), QUndoStack::QUndoStack() -*/ - -void QUndoGroup::addStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - - if (d->stack_list.contains(stack)) - return; - d->stack_list.append(stack); - - if (QUndoGroup *other = stack->d_func()->group) - other->removeStack(stack); - stack->d_func()->group = this; -} - -/*! - Removes \a stack from this group. If the stack was the active stack in the group, - the active stack becomes 0. - - \sa addStack(), stacks(), QUndoStack::~QUndoStack() -*/ - -void QUndoGroup::removeStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - - if (d->stack_list.removeAll(stack) == 0) - return; - if (stack == d->active) - setActiveStack(nullptr); - stack->d_func()->group = nullptr; -} - -/*! - Returns a list of stacks in this group. - - \sa addStack(), removeStack() -*/ - -QList<QUndoStack*> QUndoGroup::stacks() const -{ - Q_D(const QUndoGroup); - return d->stack_list; -} - -/*! - Sets the active stack of this group to \a stack. - - If the stack is not a member of this group, this function does nothing. - - Synonymous with calling QUndoStack::setActive() on \a stack. - - The actions returned by createUndoAction() and createRedoAction() will now behave - in the same way as those returned by \a stack's QUndoStack::createUndoAction() - and QUndoStack::createRedoAction(). - - \sa QUndoStack::setActive(), activeStack() -*/ - -void QUndoGroup::setActiveStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - if (d->active == stack) - return; - - if (d->active != nullptr) { - disconnect(d->active, SIGNAL(canUndoChanged(bool)), - this, SIGNAL(canUndoChanged(bool))); - disconnect(d->active, SIGNAL(undoTextChanged(QString)), - this, SIGNAL(undoTextChanged(QString))); - disconnect(d->active, SIGNAL(canRedoChanged(bool)), - this, SIGNAL(canRedoChanged(bool))); - disconnect(d->active, SIGNAL(redoTextChanged(QString)), - this, SIGNAL(redoTextChanged(QString))); - disconnect(d->active, SIGNAL(indexChanged(int)), - this, SIGNAL(indexChanged(int))); - disconnect(d->active, SIGNAL(cleanChanged(bool)), - this, SIGNAL(cleanChanged(bool))); - } - - d->active = stack; - - if (d->active == nullptr) { - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - emit cleanChanged(true); - emit indexChanged(0); - } else { - connect(d->active, SIGNAL(canUndoChanged(bool)), - this, SIGNAL(canUndoChanged(bool))); - connect(d->active, SIGNAL(undoTextChanged(QString)), - this, SIGNAL(undoTextChanged(QString))); - connect(d->active, SIGNAL(canRedoChanged(bool)), - this, SIGNAL(canRedoChanged(bool))); - connect(d->active, SIGNAL(redoTextChanged(QString)), - this, SIGNAL(redoTextChanged(QString))); - connect(d->active, SIGNAL(indexChanged(int)), - this, SIGNAL(indexChanged(int))); - connect(d->active, SIGNAL(cleanChanged(bool)), - this, SIGNAL(cleanChanged(bool))); - emit canUndoChanged(d->active->canUndo()); - emit undoTextChanged(d->active->undoText()); - emit canRedoChanged(d->active->canRedo()); - emit redoTextChanged(d->active->redoText()); - emit cleanChanged(d->active->isClean()); - emit indexChanged(d->active->index()); - } - - emit activeStackChanged(d->active); -} - -/*! - Returns the active stack of this group. - - If none of the stacks are active, or if the group is empty, this function - returns \nullptr. - - \sa setActiveStack(), QUndoStack::setActive() -*/ - -QUndoStack *QUndoGroup::activeStack() const -{ - Q_D(const QUndoGroup); - return d->active; -} - -/*! - Calls QUndoStack::undo() on the active stack. - - If none of the stacks are active, or if the group is empty, this function - does nothing. - - \sa redo(), canUndo(), setActiveStack() -*/ - -void QUndoGroup::undo() -{ - Q_D(QUndoGroup); - if (d->active != nullptr) - d->active->undo(); -} - -/*! - Calls QUndoStack::redo() on the active stack. - - If none of the stacks are active, or if the group is empty, this function - does nothing. - - \sa undo(), canRedo(), setActiveStack() -*/ - - -void QUndoGroup::redo() -{ - Q_D(QUndoGroup); - if (d->active != nullptr) - d->active->redo(); -} - -/*! - Returns the value of the active stack's QUndoStack::canUndo(). - - If none of the stacks are active, or if the group is empty, this function - returns \c false. - - \sa canRedo(), setActiveStack() -*/ - -bool QUndoGroup::canUndo() const -{ - Q_D(const QUndoGroup); - return d->active != nullptr && d->active->canUndo(); -} - -/*! - Returns the value of the active stack's QUndoStack::canRedo(). - - If none of the stacks are active, or if the group is empty, this function - returns \c false. - - \sa canUndo(), setActiveStack() -*/ - -bool QUndoGroup::canRedo() const -{ - Q_D(const QUndoGroup); - return d->active != nullptr && d->active->canRedo(); -} - -/*! - Returns the value of the active stack's QUndoStack::undoText(). - - If none of the stacks are active, or if the group is empty, this function - returns an empty string. - - \sa redoText(), setActiveStack() -*/ - -QString QUndoGroup::undoText() const -{ - Q_D(const QUndoGroup); - return d->active == nullptr ? QString() : d->active->undoText(); -} - -/*! - Returns the value of the active stack's QUndoStack::redoText(). - - If none of the stacks are active, or if the group is empty, this function - returns an empty string. - - \sa undoText(), setActiveStack() -*/ - -QString QUndoGroup::redoText() const -{ - Q_D(const QUndoGroup); - return d->active == nullptr ? QString() : d->active->redoText(); -} - -/*! - Returns the value of the active stack's QUndoStack::isClean(). - - If none of the stacks are active, or if the group is empty, this function - returns \c true. - - \sa setActiveStack() -*/ - -bool QUndoGroup::isClean() const -{ - Q_D(const QUndoGroup); - return d->active == nullptr || d->active->isClean(); -} - -#ifndef QT_NO_ACTION - -/*! - Creates an undo QAction object with parent \a parent. - - Triggering this action will cause a call to QUndoStack::undo() on the active stack. - The text of this action will always be the text of the command which will be undone - in the next call to undo(), prefixed by \a prefix. If there is no command available - for undo, if the group is empty or if none of the stacks are active, this action will - be disabled. - - If \a prefix is empty, the default template "Undo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Undo" was used by default. - - \sa createRedoAction(), canUndo(), QUndoCommand::text() -*/ - -QAction *QUndoGroup::createUndoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action")); - - result->setEnabled(canUndo()); - result->setPrefixedText(undoText()); - connect(this, SIGNAL(canUndoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(undoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(undo())); - return result; -} - -/*! - Creates an redo QAction object with parent \a parent. - - Triggering this action will cause a call to QUndoStack::redo() on the active stack. - The text of this action will always be the text of the command which will be redone - in the next call to redo(), prefixed by \a prefix. If there is no command available - for redo, if the group is empty or if none of the stacks are active, this action will - be disabled. - - If \a prefix is empty, the default template "Redo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Redo" was used by default. - - \sa createUndoAction(), canRedo(), QUndoCommand::text() -*/ - -QAction *QUndoGroup::createRedoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action")); - - result->setEnabled(canRedo()); - result->setPrefixedText(redoText()); - connect(this, SIGNAL(canRedoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(redoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(redo())); - return result; -} - -#endif // QT_NO_ACTION - -/*! \fn void QUndoGroup::activeStackChanged(QUndoStack *stack) - - This signal is emitted whenever the active stack of the group changes. This can happen - when setActiveStack() or QUndoStack::setActive() is called, or when the active stack - is removed form the group. \a stack is the new active stack. If no stack is active, - \a stack is 0. - - \sa setActiveStack(), QUndoStack::setActive() -*/ - -/*! \fn void QUndoGroup::indexChanged(int idx) - - This signal is emitted whenever the active stack emits QUndoStack::indexChanged() - or the active stack changes. - - \a idx is the new current index, or 0 if the active stack is 0. - - \sa QUndoStack::indexChanged(), setActiveStack() -*/ - -/*! \fn void QUndoGroup::cleanChanged(bool clean) - - This signal is emitted whenever the active stack emits QUndoStack::cleanChanged() - or the active stack changes. - - \a clean is the new state, or true if the active stack is 0. - - \sa QUndoStack::cleanChanged(), setActiveStack() -*/ - -/*! \fn void QUndoGroup::canUndoChanged(bool canUndo) - - This signal is emitted whenever the active stack emits QUndoStack::canUndoChanged() - or the active stack changes. - - \a canUndo is the new state, or false if the active stack is 0. - - \sa QUndoStack::canUndoChanged(), setActiveStack() -*/ - -/*! \fn void QUndoGroup::canRedoChanged(bool canRedo) - - This signal is emitted whenever the active stack emits QUndoStack::canRedoChanged() - or the active stack changes. - - \a canRedo is the new state, or false if the active stack is 0. - - \sa QUndoStack::canRedoChanged(), setActiveStack() -*/ - -/*! \fn void QUndoGroup::undoTextChanged(const QString &undoText) - - This signal is emitted whenever the active stack emits QUndoStack::undoTextChanged() - or the active stack changes. - - \a undoText is the new state, or an empty string if the active stack is 0. - - \sa QUndoStack::undoTextChanged(), setActiveStack() -*/ - -/*! \fn void QUndoGroup::redoTextChanged(const QString &redoText) - - This signal is emitted whenever the active stack emits QUndoStack::redoTextChanged() - or the active stack changes. - - \a redoText is the new state, or an empty string if the active stack is 0. - - \sa QUndoStack::redoTextChanged(), setActiveStack() -*/ - -QT_END_NAMESPACE - -#include "moc_qundogroup.cpp" diff --git a/src/widgets/util/qundogroup.h b/src/widgets/util/qundogroup.h deleted file mode 100644 index 1845f7e057..0000000000 --- a/src/widgets/util/qundogroup.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOGROUP_H -#define QUNDOGROUP_H - -#include <QtWidgets/qtwidgetsglobal.h> -#include <QtCore/qobject.h> -#include <QtCore/qstring.h> - -QT_REQUIRE_CONFIG(undogroup); - -QT_BEGIN_NAMESPACE - -class QUndoGroupPrivate; -class QUndoStack; -class QAction; - -class Q_WIDGETS_EXPORT QUndoGroup : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QUndoGroup) - -public: - explicit QUndoGroup(QObject *parent = nullptr); - ~QUndoGroup(); - - void addStack(QUndoStack *stack); - void removeStack(QUndoStack *stack); - QList<QUndoStack*> stacks() const; - QUndoStack *activeStack() const; - -#ifndef QT_NO_ACTION - QAction *createUndoAction(QObject *parent, - const QString &prefix = QString()) const; - QAction *createRedoAction(QObject *parent, - const QString &prefix = QString()) const; -#endif // QT_NO_ACTION - bool canUndo() const; - bool canRedo() const; - QString undoText() const; - QString redoText() const; - bool isClean() const; - -public Q_SLOTS: - void undo(); - void redo(); - void setActiveStack(QUndoStack *stack); - -Q_SIGNALS: - void activeStackChanged(QUndoStack *stack); - void indexChanged(int idx); - void cleanChanged(bool clean); - void canUndoChanged(bool canUndo); - void canRedoChanged(bool canRedo); - void undoTextChanged(const QString &undoText); - void redoTextChanged(const QString &redoText); - -private: - Q_DISABLE_COPY(QUndoGroup) -}; - -QT_END_NAMESPACE - -#endif // QUNDOGROUP_H diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp deleted file mode 100644 index 8974f11a13..0000000000 --- a/src/widgets/util/qundostack.cpp +++ /dev/null @@ -1,1388 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qdebug.h> -#include "qundostack.h" -#if QT_CONFIG(undogroup) -#include "qundogroup.h" -#endif -#include "qundostack_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QUndoCommand - \brief The QUndoCommand class is the base class of all commands stored on a QUndoStack. - \since 4.2 - - \inmodule QtWidgets - - For an overview of Qt's Undo Framework, see the - \l{Overview of Qt's Undo Framework}{overview document}. - - A QUndoCommand represents a single editing action on a document; for example, - inserting or deleting a block of text in a text editor. QUndoCommand can apply - a change to the document with redo() and undo the change with undo(). The - implementations for these functions must be provided in a derived class. - - \snippet code/src_gui_util_qundostack.cpp 0 - - A QUndoCommand has an associated text(). This is a short string - describing what the command does. It is used to update the text - properties of the stack's undo and redo actions; see - QUndoStack::createUndoAction() and QUndoStack::createRedoAction(). - - QUndoCommand objects are owned by the stack they were pushed on. - QUndoStack deletes a command if it has been undone and a new command is pushed. For example: - -\snippet code/src_gui_util_qundostack.cpp 1 - - In effect, when a command is pushed, it becomes the top-most command - on the stack. - - To support command compression, QUndoCommand has an id() and the virtual function - mergeWith(). These functions are used by QUndoStack::push(). - - To support command macros, a QUndoCommand object can have any number of child - commands. Undoing or redoing the parent command will cause the child - commands to be undone or redone. A command can be assigned - to a parent explicitly in the constructor. In this case, the command - will be owned by the parent. - - The parent in this case is usually an empty command, in that it doesn't - provide its own implementation of undo() and redo(). Instead, it uses - the base implementations of these functions, which simply call undo() or - redo() on all its children. The parent should, however, have a meaningful - text(). - - \snippet code/src_gui_util_qundostack.cpp 2 - - Another way to create macros is to use the convenience functions - QUndoStack::beginMacro() and QUndoStack::endMacro(). - - \sa QUndoStack -*/ - -/*! - Constructs a QUndoCommand object with the given \a parent and \a text. - - If \a parent is not \nullptr, this command is appended to parent's - child list. The parent command then owns this command and will delete - it in its destructor. - - \sa ~QUndoCommand() -*/ - -QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent) - : QUndoCommand(parent) -{ - setText(text); -} - -/*! - Constructs a QUndoCommand object with parent \a parent. - - If \a parent is not \nullptr, this command is appended to parent's - child list. The parent command then owns this command and will delete - it in its destructor. - - \sa ~QUndoCommand() -*/ - -QUndoCommand::QUndoCommand(QUndoCommand *parent) -{ - d = new QUndoCommandPrivate; - if (parent != nullptr) - parent->d->child_list.append(this); -} - -/*! - Destroys the QUndoCommand object and all child commands. - - \sa QUndoCommand() -*/ - -QUndoCommand::~QUndoCommand() -{ - qDeleteAll(d->child_list); - delete d; -} - -/*! - \since 5.9 - - Returns whether the command is obsolete. - - The boolean is used for the automatic removal of commands that are not necessary in the - stack anymore. The isObsolete function is checked in the functions QUndoStack::push(), - QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex(). - - \sa setObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() -*/ - -bool QUndoCommand::isObsolete() const -{ - return d->obsolete; -} - -/*! - \since 5.9 - - Sets whether the command is obsolete to \a obsolete. - - \sa isObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() -*/ - -void QUndoCommand::setObsolete(bool obsolete) -{ - d->obsolete = obsolete; -} - -/*! - Returns the ID of this command. - - A command ID is used in command compression. It must be an integer unique to - this command's class, or -1 if the command doesn't support compression. - - If the command supports compression this function must be overridden in the - derived class to return the correct ID. The base implementation returns -1. - - QUndoStack::push() will only try to merge two commands if they have the - same ID, and the ID is not -1. - - \sa mergeWith(), QUndoStack::push() -*/ - -int QUndoCommand::id() const -{ - return -1; -} - -/*! - Attempts to merge this command with \a command. Returns \c true on - success; otherwise returns \c false. - - If this function returns \c true, calling this command's redo() must have the same - effect as redoing both this command and \a command. - Similarly, calling this command's undo() must have the same effect as undoing - \a command and this command. - - QUndoStack will only try to merge two commands if they have the same id, and - the id is not -1. - - The default implementation returns \c false. - - \snippet code/src_gui_util_qundostack.cpp 3 - - \sa id(), QUndoStack::push() -*/ - -bool QUndoCommand::mergeWith(const QUndoCommand *command) -{ - Q_UNUSED(command); - return false; -} - -/*! - Applies a change to the document. This function must be implemented in - the derived class. Calling QUndoStack::push(), - QUndoStack::undo() or QUndoStack::redo() from this function leads to - undefined beahavior. - - The default implementation calls redo() on all child commands. - - \sa undo() -*/ - -void QUndoCommand::redo() -{ - for (int i = 0; i < d->child_list.size(); ++i) - d->child_list.at(i)->redo(); -} - -/*! - Reverts a change to the document. After undo() is called, the state of - the document should be the same as before redo() was called. This function must - be implemented in the derived class. Calling QUndoStack::push(), - QUndoStack::undo() or QUndoStack::redo() from this function leads to - undefined beahavior. - - The default implementation calls undo() on all child commands in reverse order. - - \sa redo() -*/ - -void QUndoCommand::undo() -{ - for (int i = d->child_list.size() - 1; i >= 0; --i) - d->child_list.at(i)->undo(); -} - -/*! - Returns a short text string describing what this command does; for example, - "insert text". - - The text is used for names of items in QUndoView. - - \sa actionText(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction() -*/ - -QString QUndoCommand::text() const -{ - return d->text; -} - -/*! - \since 4.8 - - Returns a short text string describing what this command does; for example, - "insert text". - - The text is used when the text properties of the stack's undo and redo - actions are updated. - - \sa text(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction() -*/ - -QString QUndoCommand::actionText() const -{ - return d->actionText; -} - -/*! - Sets the command's text to be the \a text specified. - - The specified text should be a short user-readable string describing what this - command does. - - If you need to have two different strings for text() and actionText(), separate - them with "\\n" and pass into this function. Even if you do not use this feature - for English strings during development, you can still let translators use two - different strings in order to match specific languages' needs. - The described feature and the function actionText() are available since Qt 4.8. - - \sa text(), actionText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction() -*/ - -void QUndoCommand::setText(const QString &text) -{ - int cdpos = text.indexOf(QLatin1Char('\n')); - if (cdpos > 0) { - d->text = text.left(cdpos); - d->actionText = text.mid(cdpos + 1); - } else { - d->text = text; - d->actionText = text; - } -} - -/*! - \since 4.4 - - Returns the number of child commands in this command. - - \sa child() -*/ - -int QUndoCommand::childCount() const -{ - return d->child_list.count(); -} - -/*! - \since 4.4 - - Returns the child command at \a index. - - \sa childCount(), QUndoStack::command() -*/ - -const QUndoCommand *QUndoCommand::child(int index) const -{ - if (index < 0 || index >= d->child_list.count()) - return nullptr; - return d->child_list.at(index); -} - -#if QT_CONFIG(undostack) - -/*! - \class QUndoStack - \brief The QUndoStack class is a stack of QUndoCommand objects. - \since 4.2 - - \inmodule QtWidgets - - For an overview of Qt's Undo Framework, see the - \l{Overview of Qt's Undo Framework}{overview document}. - - An undo stack maintains a stack of commands that have been applied to a - document. - - New commands are pushed on the stack using push(). Commands can be - undone and redone using undo() and redo(), or by triggering the - actions returned by createUndoAction() and createRedoAction(). - - QUndoStack keeps track of the \a current command. This is the command - which will be executed by the next call to redo(). The index of this - command is returned by index(). The state of the edited object can be - rolled forward or back using setIndex(). If the top-most command on the - stack has already been redone, index() is equal to count(). - - QUndoStack provides support for undo and redo actions, command - compression, command macros, and supports the concept of a - \e{clean state}. - - \section1 Undo and Redo Actions - - QUndoStack provides convenient undo and redo QAction objects, which - can be inserted into a menu or a toolbar. When commands are undone or - redone, QUndoStack updates the text properties of these actions - to reflect what change they will trigger. The actions are also disabled - when no command is available for undo or redo. These actions - are returned by QUndoStack::createUndoAction() and QUndoStack::createRedoAction(). - - \section1 Command Compression and Macros - - Command compression is useful when several commands can be compressed - into a single command that can be undone and redone in a single operation. - For example, when a user types a character in a text editor, a new command - is created. This command inserts the character into the document at the - cursor position. However, it is more convenient for the user to be able - to undo or redo typing of whole words, sentences, or paragraphs. - Command compression allows these single-character commands to be merged - into a single command which inserts or deletes sections of text. - For more information, see QUndoCommand::mergeWith() and push(). - - A command macro is a sequence of commands, all of which are undone and - redone in one go. Command macros are created by giving a command a list - of child commands. - Undoing or redoing the parent command will cause the child commands to - be undone or redone. Command macros may be created explicitly - by specifying a parent in the QUndoCommand constructor, or by using the - convenience functions beginMacro() and endMacro(). - - Although command compression and macros appear to have the same effect to the - user, they often have different uses in an application. Commands that - perform small changes to a document may be usefully compressed if there is - no need to individually record them, and if only larger changes are relevant - to the user. - However, for commands that need to be recorded individually, or those that - cannot be compressed, it is useful to use macros to provide a more convenient - user experience while maintaining a record of each command. - - \section1 Clean State - - QUndoStack supports the concept of a clean state. When the - document is saved to disk, the stack can be marked as clean using - setClean(). Whenever the stack returns to this state through undoing and - redoing commands, it emits the signal cleanChanged(). This signal - is also emitted when the stack leaves the clean state. This signal is - usually used to enable and disable the save actions in the application, - and to update the document's title to reflect that it contains unsaved - changes. - - \section1 Obsolete Commands - - QUndoStack is able to delete commands from the stack if the command is no - longer needed. One example may be to delete a command when two commands are - merged together in such a way that the merged command has no function. This - can be seen with move commands where the user moves their mouse to one part - of the screen and then moves it to the original position. The merged command - results in a mouse movement of 0. This command can be deleted since it serves - no purpose. Another example is with networking commands that fail due to connection - issues. In this case, the command is to be removed from the stack because the redo() - and undo() functions have no function since there was connection issues. - - A command can be marked obsolete with the QUndoCommand::setObsolete() function. - The QUndoCommand::isObsolete() flag is checked in QUndoStack::push(), - QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex() after calling - QUndoCommand::undo(), QUndoCommand::redo() and QUndoCommand:mergeWith() where - applicable. - - If a command is set obsolete and the clean index is greater than or equal to the - current command index, then the clean index will be reset when the command is - deleted from the stack. - - \sa QUndoCommand, QUndoView -*/ - -#if QT_CONFIG(action) - -QUndoAction::QUndoAction(const QString &prefix, QObject *parent) - : QAction(parent) -{ - m_prefix = prefix; -} - -void QUndoAction::setPrefixedText(const QString &text) -{ - if (m_defaultText.isEmpty()) { - QString s = m_prefix; - if (!m_prefix.isEmpty() && !text.isEmpty()) - s.append(QLatin1Char(' ')); - s.append(text); - setText(s); - } else { - if (text.isEmpty()) - setText(m_defaultText); - else - setText(m_prefix.arg(text)); - } -} - -void QUndoAction::setTextFormat(const QString &textFormat, const QString &defaultText) -{ - m_prefix = textFormat; - m_defaultText = defaultText; -} - -#endif // QT_CONFIG(action) - -/*! \internal - Sets the current index to \a idx, emitting appropriate signals. If \a clean is true, - makes \a idx the clean index as well. -*/ - -void QUndoStackPrivate::setIndex(int idx, bool clean) -{ - Q_Q(QUndoStack); - - bool was_clean = index == clean_index; - - if (idx != index) { - index = idx; - emit q->indexChanged(index); - emit q->canUndoChanged(q->canUndo()); - emit q->undoTextChanged(q->undoText()); - emit q->canRedoChanged(q->canRedo()); - emit q->redoTextChanged(q->redoText()); - } - - if (clean) - clean_index = index; - - bool is_clean = index == clean_index; - if (is_clean != was_clean) - emit q->cleanChanged(is_clean); -} - -/*! \internal - If the number of commands on the stack exceedes the undo limit, deletes commands from - the bottom of the stack. - - Returns \c true if commands were deleted. -*/ - -bool QUndoStackPrivate::checkUndoLimit() -{ - if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.count()) - return false; - - int del_count = command_list.count() - undo_limit; - - for (int i = 0; i < del_count; ++i) - delete command_list.takeFirst(); - - index -= del_count; - if (clean_index != -1) { - if (clean_index < del_count) - clean_index = -1; // we've deleted the clean command - else - clean_index -= del_count; - } - - return true; -} - -/*! - Constructs an empty undo stack with the parent \a parent. The - stack will initially be in the clean state. If \a parent is a - QUndoGroup object, the stack is automatically added to the group. - - \sa push() -*/ - -QUndoStack::QUndoStack(QObject *parent) - : QObject(*(new QUndoStackPrivate), parent) -{ -#if QT_CONFIG(undogroup) - if (QUndoGroup *group = qobject_cast<QUndoGroup*>(parent)) - group->addStack(this); -#endif -} - -/*! - Destroys the undo stack, deleting any commands that are on it. If the - stack is in a QUndoGroup, the stack is automatically removed from the group. - - \sa QUndoStack() -*/ - -QUndoStack::~QUndoStack() -{ -#if QT_CONFIG(undogroup) - Q_D(QUndoStack); - if (d->group != nullptr) - d->group->removeStack(this); -#endif - clear(); -} - -/*! - Clears the command stack by deleting all commands on it, and returns the stack - to the clean state. - - Commands are not undone or redone; the state of the edited object remains - unchanged. - - This function is usually used when the contents of the document are - abandoned. - - \sa QUndoStack() -*/ - -void QUndoStack::clear() -{ - Q_D(QUndoStack); - - if (d->command_list.isEmpty()) - return; - - bool was_clean = isClean(); - - d->macro_stack.clear(); - qDeleteAll(d->command_list); - d->command_list.clear(); - - d->index = 0; - d->clean_index = 0; - - emit indexChanged(0); - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - - if (!was_clean) - emit cleanChanged(true); -} - -/*! - Pushes \a cmd on the stack or merges it with the most recently executed command. - In either case, executes \a cmd by calling its redo() function. - - If \a cmd's id is not -1, and if the id is the same as that of the - most recently executed command, QUndoStack will attempt to merge the two - commands by calling QUndoCommand::mergeWith() on the most recently executed - command. If QUndoCommand::mergeWith() returns \c true, \a cmd is deleted. - - After calling QUndoCommand::redo() and, if applicable, QUndoCommand::mergeWith(), - QUndoCommand::isObsolete() will be called for \a cmd or the merged command. - If QUndoCommand::isObsolete() returns \c true, then \a cmd or the merged command - will be deleted from the stack. - - In all other cases \a cmd is simply pushed on the stack. - - If commands were undone before \a cmd was pushed, the current command and - all commands above it are deleted. Hence \a cmd always ends up being the - top-most on the stack. - - Once a command is pushed, the stack takes ownership of it. There - are no getters to return the command, since modifying it after it has - been executed will almost always lead to corruption of the document's - state. - - \sa QUndoCommand::id(), QUndoCommand::mergeWith() -*/ - -void QUndoStack::push(QUndoCommand *cmd) -{ - Q_D(QUndoStack); - if (!cmd->isObsolete()) - cmd->redo(); - - bool macro = !d->macro_stack.isEmpty(); - - QUndoCommand *cur = nullptr; - if (macro) { - QUndoCommand *macro_cmd = d->macro_stack.constLast(); - if (!macro_cmd->d->child_list.isEmpty()) - cur = macro_cmd->d->child_list.constLast(); - } else { - if (d->index > 0) - cur = d->command_list.at(d->index - 1); - while (d->index < d->command_list.size()) - delete d->command_list.takeLast(); - if (d->clean_index > d->index) - d->clean_index = -1; // we've deleted the clean state - } - - bool try_merge = cur != nullptr - && cur->id() != -1 - && cur->id() == cmd->id() - && (macro || d->index != d->clean_index); - - if (try_merge && cur->mergeWith(cmd)) { - delete cmd; - - if (macro) { - if (cur->isObsolete()) - delete d->macro_stack.constLast()->d->child_list.takeLast(); - } else { - if (cur->isObsolete()) { - delete d->command_list.takeLast(); - - d->setIndex(d->index - 1, false); - } else { - emit indexChanged(d->index); - emit canUndoChanged(canUndo()); - emit undoTextChanged(undoText()); - emit canRedoChanged(canRedo()); - emit redoTextChanged(redoText()); - } - } - } else if (cmd->isObsolete()) { - delete cmd; // command should be deleted and NOT added to the stack - } else { - if (macro) { - d->macro_stack.constLast()->d->child_list.append(cmd); - } else { - d->command_list.append(cmd); - d->checkUndoLimit(); - d->setIndex(d->index + 1, false); - } - } -} - -/*! - Marks the stack as clean and emits cleanChanged() if the stack was - not already clean. - - This is typically called when a document is saved, for example. - - Whenever the stack returns to this state through the use of undo/redo - commands, it emits the signal cleanChanged(). This signal is also - emitted when the stack leaves the clean state. - - \sa isClean(), resetClean(), cleanIndex() -*/ - -void QUndoStack::setClean() -{ - Q_D(QUndoStack); - if (Q_UNLIKELY(!d->macro_stack.isEmpty())) { - qWarning("QUndoStack::setClean(): cannot set clean in the middle of a macro"); - return; - } - - d->setIndex(d->index, true); -} - -/*! - \since 5.8 - - Leaves the clean state and emits cleanChanged() if the stack was clean. - This method resets the clean index to -1. - - This is typically called in the following cases, when a document has been: - \list - \li created basing on some template and has not been saved, - so no filename has been associated with the document yet. - \li restored from a backup file. - \li changed outside of the editor and the user did not reload it. - \endlist - - \sa isClean(), setClean(), cleanIndex() -*/ - -void QUndoStack::resetClean() -{ - Q_D(QUndoStack); - const bool was_clean = isClean(); - d->clean_index = -1; - if (was_clean) - emit cleanChanged(false); -} - -/*! - \since 5.12 - \property QUndoStack::clean - \brief the clean status of this stack. - - This property indicates whether or not the stack is clean. For example, a - stack is clean when a document has been saved. - - \sa isClean(), setClean(), resetClean(), cleanIndex() -*/ - -/*! - If the stack is in the clean state, returns \c true; otherwise returns \c false. - - \sa setClean(), cleanIndex() -*/ - -bool QUndoStack::isClean() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->clean_index == d->index; -} - -/*! - Returns the clean index. This is the index at which setClean() was called. - - A stack may not have a clean index. This happens if a document is saved, - some commands are undone, then a new command is pushed. Since - push() deletes all the undone commands before pushing the new command, the stack - can't return to the clean state again. In this case, this function returns -1. - The -1 may also be returned after an explicit call to resetClean(). - - \sa isClean(), setClean() -*/ - -int QUndoStack::cleanIndex() const -{ - Q_D(const QUndoStack); - return d->clean_index; -} - -/*! - Undoes the command below the current command by calling QUndoCommand::undo(). - Decrements the current command index. - - If the stack is empty, or if the bottom command on the stack has already been - undone, this function does nothing. - - After the command is undone, if QUndoCommand::isObsolete() returns \c true, - then the command will be deleted from the stack. Additionally, if the clean - index is greater than or equal to the current command index, then the clean - index is reset. - - \sa redo(), index() -*/ - -void QUndoStack::undo() -{ - Q_D(QUndoStack); - if (d->index == 0) - return; - - if (Q_UNLIKELY(!d->macro_stack.isEmpty())) { - qWarning("QUndoStack::undo(): cannot undo in the middle of a macro"); - return; - } - - int idx = d->index - 1; - QUndoCommand *cmd = d->command_list.at(idx); - - if (!cmd->isObsolete()) - cmd->undo(); - - if (cmd->isObsolete()) { // A separate check is done b/c the undo command may set obsolete flag - delete d->command_list.takeAt(idx); - - if (d->clean_index > idx) - resetClean(); - } - - d->setIndex(idx, false); -} - -/*! - Redoes the current command by calling QUndoCommand::redo(). Increments the current - command index. - - If the stack is empty, or if the top command on the stack has already been - redone, this function does nothing. - - If QUndoCommand::isObsolete() returns true for the current command, then - the command will be deleted from the stack. Additionally, if the clean - index is greater than or equal to the current command index, then the clean - index is reset. - - \sa undo(), index() -*/ - -void QUndoStack::redo() -{ - Q_D(QUndoStack); - if (d->index == d->command_list.size()) - return; - - if (Q_UNLIKELY(!d->macro_stack.isEmpty())) { - qWarning("QUndoStack::redo(): cannot redo in the middle of a macro"); - return; - } - - int idx = d->index; - QUndoCommand *cmd = d->command_list.at(idx); - - if (!cmd->isObsolete()) - cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag - - if (cmd->isObsolete()) { - delete d->command_list.takeAt(idx); - - if (d->clean_index > idx) - resetClean(); - } else { - d->setIndex(d->index + 1, false); - } -} - -/*! - Returns the number of commands on the stack. Macro commands are counted as - one command. - - \sa index(), setIndex(), command() -*/ - -int QUndoStack::count() const -{ - Q_D(const QUndoStack); - return d->command_list.size(); -} - -/*! - Returns the index of the current command. This is the command that will be - executed on the next call to redo(). It is not always the top-most command - on the stack, since a number of commands may have been undone. - - \sa undo(), redo(), count() -*/ - -int QUndoStack::index() const -{ - Q_D(const QUndoStack); - return d->index; -} - -/*! - Repeatedly calls undo() or redo() until the current command index reaches - \a idx. This function can be used to roll the state of the document forwards - of backwards. indexChanged() is emitted only once. - - \sa index(), count(), undo(), redo() -*/ - -void QUndoStack::setIndex(int idx) -{ - Q_D(QUndoStack); - if (Q_UNLIKELY(!d->macro_stack.isEmpty())) { - qWarning("QUndoStack::setIndex(): cannot set index in the middle of a macro"); - return; - } - - if (idx < 0) - idx = 0; - else if (idx > d->command_list.size()) - idx = d->command_list.size(); - - int i = d->index; - while (i < idx) { - QUndoCommand *cmd = d->command_list.at(i); - - if (!cmd->isObsolete()) - cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag - - if (cmd->isObsolete()) { - delete d->command_list.takeAt(i); - - if (d->clean_index > i) - resetClean(); - - idx--; // Subtract from idx because we removed a command - } else { - i++; - } - } - - while (i > idx) { - QUndoCommand *cmd = d->command_list.at(--i); - - cmd->undo(); - if (cmd->isObsolete()) { - delete d->command_list.takeAt(i); - - if (d->clean_index > i) - resetClean(); - } - } - - d->setIndex(idx, false); -} - -/*! - \since 5.12 - \property QUndoStack::canUndo - \brief whether this stack can undo. - - This property indicates whether or not there is a command that can be - undone. - - \sa canUndo(), index(), canRedo() -*/ - -/*! - Returns \c true if there is a command available for undo; otherwise returns \c false. - - This function returns \c false if the stack is empty, or if the bottom command - on the stack has already been undone. - - Synonymous with index() == 0. - - \sa index(), canRedo() -*/ - -bool QUndoStack::canUndo() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->index > 0; -} - -/*! - \since 5.12 - \property QUndoStack::canRedo - \brief whether this stack can redo. - - This property indicates whether or not there is a command that can be - redone. - - \sa canRedo(), index(), canUndo() -*/ - -/*! - Returns \c true if there is a command available for redo; otherwise returns \c false. - - This function returns \c false if the stack is empty or if the top command - on the stack has already been redone. - - Synonymous with index() == count(). - - \sa index(), canUndo() -*/ - -bool QUndoStack::canRedo() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->index < d->command_list.size(); -} - -/*! - \since 5.12 - \property QUndoStack::undoText - \brief the undo text of the next command that is undone. - - This property holds the text of the command which will be undone in the - next call to undo(). - - \sa undoText(), QUndoCommand::actionText(), redoText() -*/ - -/*! - Returns the text of the command which will be undone in the next call to undo(). - - \sa QUndoCommand::actionText(), redoText() -*/ - -QString QUndoStack::undoText() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return QString(); - if (d->index > 0) - return d->command_list.at(d->index - 1)->actionText(); - return QString(); -} - -/*! - \since 5.12 - \property QUndoStack::redoText - \brief the redo text of the next command that is redone. - - This property holds the text of the command which will be redone in the - next call to redo(). - - \sa redoText(), QUndoCommand::actionText(), undoText() -*/ - -/*! - Returns the text of the command which will be redone in the next call to redo(). - - \sa QUndoCommand::actionText(), undoText() -*/ - -QString QUndoStack::redoText() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return QString(); - if (d->index < d->command_list.size()) - return d->command_list.at(d->index)->actionText(); - return QString(); -} - -#ifndef QT_NO_ACTION - -/*! - Creates an undo QAction object with the given \a parent. - - Triggering this action will cause a call to undo(). The text of this action - is the text of the command which will be undone in the next call to undo(), - prefixed by the specified \a prefix. If there is no command available for undo, - this action will be disabled. - - If \a prefix is empty, the default template "Undo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Undo" was used by default. - - \sa createRedoAction(), canUndo(), QUndoCommand::text() -*/ - -QAction *QUndoStack::createUndoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action")); - - result->setEnabled(canUndo()); - result->setPrefixedText(undoText()); - connect(this, SIGNAL(canUndoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(undoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(undo())); - return result; -} - -/*! - Creates an redo QAction object with the given \a parent. - - Triggering this action will cause a call to redo(). The text of this action - is the text of the command which will be redone in the next call to redo(), - prefixed by the specified \a prefix. If there is no command available for redo, - this action will be disabled. - - If \a prefix is empty, the default template "Redo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Redo" was used by default. - - \sa createUndoAction(), canRedo(), QUndoCommand::text() -*/ - -QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action")); - - result->setEnabled(canRedo()); - result->setPrefixedText(redoText()); - connect(this, SIGNAL(canRedoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(redoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(redo())); - return result; -} - -#endif // QT_NO_ACTION - -/*! - Begins composition of a macro command with the given \a text description. - - An empty command described by the specified \a text is pushed on the stack. - Any subsequent commands pushed on the stack will be appended to the empty - command's children until endMacro() is called. - - Calls to beginMacro() and endMacro() may be nested, but every call to - beginMacro() must have a matching call to endMacro(). - - While a macro is being composed, the stack is disabled. This means that: - \list - \li indexChanged() and cleanChanged() are not emitted, - \li canUndo() and canRedo() return false, - \li calling undo() or redo() has no effect, - \li the undo/redo actions are disabled. - \endlist - - The stack becomes enabled and appropriate signals are emitted when endMacro() - is called for the outermost macro. - - \snippet code/src_gui_util_qundostack.cpp 4 - - This code is equivalent to: - - \snippet code/src_gui_util_qundostack.cpp 5 - - \sa endMacro() -*/ - -void QUndoStack::beginMacro(const QString &text) -{ - Q_D(QUndoStack); - QUndoCommand *cmd = new QUndoCommand(); - cmd->setText(text); - - if (d->macro_stack.isEmpty()) { - while (d->index < d->command_list.size()) - delete d->command_list.takeLast(); - if (d->clean_index > d->index) - d->clean_index = -1; // we've deleted the clean state - d->command_list.append(cmd); - } else { - d->macro_stack.constLast()->d->child_list.append(cmd); - } - d->macro_stack.append(cmd); - - if (d->macro_stack.count() == 1) { - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - } -} - -/*! - Ends composition of a macro command. - - If this is the outermost macro in a set nested macros, this function emits - indexChanged() once for the entire macro command. - - \sa beginMacro() -*/ - -void QUndoStack::endMacro() -{ - Q_D(QUndoStack); - if (Q_UNLIKELY(d->macro_stack.isEmpty())) { - qWarning("QUndoStack::endMacro(): no matching beginMacro()"); - return; - } - - d->macro_stack.removeLast(); - - if (d->macro_stack.isEmpty()) { - d->checkUndoLimit(); - d->setIndex(d->index + 1, false); - } -} - -/*! - \since 4.4 - - Returns a const pointer to the command at \a index. - - This function returns a const pointer, because modifying a command, - once it has been pushed onto the stack and executed, almost always - causes corruption of the state of the document, if the command is - later undone or redone. - - \sa QUndoCommand::child() -*/ -const QUndoCommand *QUndoStack::command(int index) const -{ - Q_D(const QUndoStack); - - if (index < 0 || index >= d->command_list.count()) - return nullptr; - return d->command_list.at(index); -} - -/*! - Returns the text of the command at index \a idx. - - \sa beginMacro() -*/ - -QString QUndoStack::text(int idx) const -{ - Q_D(const QUndoStack); - - if (idx < 0 || idx >= d->command_list.size()) - return QString(); - return d->command_list.at(idx)->text(); -} - -/*! - \property QUndoStack::undoLimit - \brief the maximum number of commands on this stack. - \since 4.3 - - When the number of commands on a stack exceedes the stack's undoLimit, commands are - deleted from the bottom of the stack. Macro commands (commands with child commands) - are treated as one command. The default value is 0, which means that there is no - limit. - - This property may only be set when the undo stack is empty, since setting it on a - non-empty stack might delete the command at the current index. Calling setUndoLimit() - on a non-empty stack prints a warning and does nothing. -*/ - -void QUndoStack::setUndoLimit(int limit) -{ - Q_D(QUndoStack); - - if (Q_UNLIKELY(!d->command_list.isEmpty())) { - qWarning("QUndoStack::setUndoLimit(): an undo limit can only be set when the stack is empty"); - return; - } - - if (limit == d->undo_limit) - return; - d->undo_limit = limit; - d->checkUndoLimit(); -} - -int QUndoStack::undoLimit() const -{ - Q_D(const QUndoStack); - - return d->undo_limit; -} - -/*! - \property QUndoStack::active - \brief the active status of this stack. - - An application often has multiple undo stacks, one for each opened document. The active - stack is the one associated with the currently active document. If the stack belongs - to a QUndoGroup, calls to QUndoGroup::undo() or QUndoGroup::redo() will be forwarded - to this stack when it is active. If the QUndoGroup is watched by a QUndoView, the view - will display the contents of this stack when it is active. If the stack does not belong to - a QUndoGroup, making it active has no effect. - - It is the programmer's responsibility to specify which stack is active by - calling setActive(), usually when the associated document window receives focus. - - \sa QUndoGroup -*/ - -void QUndoStack::setActive(bool active) -{ -#if !QT_CONFIG(undogroup) - Q_UNUSED(active); -#else - Q_D(QUndoStack); - - if (d->group != nullptr) { - if (active) - d->group->setActiveStack(this); - else if (d->group->activeStack() == this) - d->group->setActiveStack(nullptr); - } -#endif -} - -bool QUndoStack::isActive() const -{ -#if !QT_CONFIG(undogroup) - return true; -#else - Q_D(const QUndoStack); - return d->group == nullptr || d->group->activeStack() == this; -#endif -} - -/*! - \fn void QUndoStack::indexChanged(int idx) - - This signal is emitted whenever a command modifies the state of the document. - This happens when a command is undone or redone. When a macro - command is undone or redone, or setIndex() is called, this signal - is emitted only once. - - \a idx specifies the index of the current command, ie. the command which will be - executed on the next call to redo(). - - \sa index(), setIndex() -*/ - -/*! - \fn void QUndoStack::cleanChanged(bool clean) - - This signal is emitted whenever the stack enters or leaves the clean state. - If \a clean is true, the stack is in a clean state; otherwise this signal - indicates that it has left the clean state. - - \sa isClean(), setClean() -*/ - -/*! - \fn void QUndoStack::undoTextChanged(const QString &undoText) - - This signal is emitted whenever the value of undoText() changes. It is - used to update the text property of the undo action returned by createUndoAction(). - \a undoText specifies the new text. -*/ - -/*! - \fn void QUndoStack::canUndoChanged(bool canUndo) - - This signal is emitted whenever the value of canUndo() changes. It is - used to enable or disable the undo action returned by createUndoAction(). - \a canUndo specifies the new value. -*/ - -/*! - \fn void QUndoStack::redoTextChanged(const QString &redoText) - - This signal is emitted whenever the value of redoText() changes. It is - used to update the text property of the redo action returned by createRedoAction(). - \a redoText specifies the new text. -*/ - -/*! - \fn void QUndoStack::canRedoChanged(bool canRedo) - - This signal is emitted whenever the value of canRedo() changes. It is - used to enable or disable the redo action returned by createRedoAction(). - \a canRedo specifies the new value. -*/ - -QT_END_NAMESPACE - -#include "moc_qundostack.cpp" -#include "moc_qundostack_p.cpp" - -#endif // QT_CONFIG(undostack) diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h deleted file mode 100644 index b5716b2e9b..0000000000 --- a/src/widgets/util/qundostack.h +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOSTACK_H -#define QUNDOSTACK_H - -#include <QtWidgets/qtwidgetsglobal.h> -#include <QtCore/qobject.h> -#include <QtCore/qstring.h> - -QT_REQUIRE_CONFIG(undocommand); - -QT_BEGIN_NAMESPACE - -class QAction; -class QUndoCommandPrivate; -class QUndoStackPrivate; - -class Q_WIDGETS_EXPORT QUndoCommand -{ - QUndoCommandPrivate *d; - -public: - explicit QUndoCommand(QUndoCommand *parent = nullptr); - explicit QUndoCommand(const QString &text, QUndoCommand *parent = nullptr); - virtual ~QUndoCommand(); - - virtual void undo(); - virtual void redo(); - - QString text() const; - QString actionText() const; - void setText(const QString &text); - - bool isObsolete() const; - void setObsolete(bool obsolete); - - virtual int id() const; - virtual bool mergeWith(const QUndoCommand *other); - - int childCount() const; - const QUndoCommand *child(int index) const; - -private: - Q_DISABLE_COPY(QUndoCommand) - friend class QUndoStack; -}; - -#if QT_CONFIG(undostack) - -class Q_WIDGETS_EXPORT QUndoStack : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QUndoStack) - Q_PROPERTY(bool active READ isActive WRITE setActive) - Q_PROPERTY(int undoLimit READ undoLimit WRITE setUndoLimit) - Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged) - Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged) - Q_PROPERTY(QString undoText READ undoText NOTIFY undoTextChanged) - Q_PROPERTY(QString redoText READ redoText NOTIFY redoTextChanged) - Q_PROPERTY(bool clean READ isClean NOTIFY cleanChanged) - -public: - explicit QUndoStack(QObject *parent = nullptr); - ~QUndoStack(); - void clear(); - - void push(QUndoCommand *cmd); - - bool canUndo() const; - bool canRedo() const; - QString undoText() const; - QString redoText() const; - - int count() const; - int index() const; - QString text(int idx) const; - -#ifndef QT_NO_ACTION - QAction *createUndoAction(QObject *parent, - const QString &prefix = QString()) const; - QAction *createRedoAction(QObject *parent, - const QString &prefix = QString()) const; -#endif // QT_NO_ACTION - - bool isActive() const; - bool isClean() const; - int cleanIndex() const; - - void beginMacro(const QString &text); - void endMacro(); - - void setUndoLimit(int limit); - int undoLimit() const; - - const QUndoCommand *command(int index) const; - -public Q_SLOTS: - void setClean(); - void resetClean(); - void setIndex(int idx); - void undo(); - void redo(); - void setActive(bool active = true); - -Q_SIGNALS: - void indexChanged(int idx); - void cleanChanged(bool clean); - void canUndoChanged(bool canUndo); - void canRedoChanged(bool canRedo); - void undoTextChanged(const QString &undoText); - void redoTextChanged(const QString &redoText); - -private: - Q_DISABLE_COPY(QUndoStack) - friend class QUndoGroup; -}; - -#endif // QT_CONFIG(undostack) - -QT_END_NAMESPACE - -#endif // QUNDOSTACK_H diff --git a/src/widgets/util/qundostack_p.h b/src/widgets/util/qundostack_p.h deleted file mode 100644 index efe0ceeef8..0000000000 --- a/src/widgets/util/qundostack_p.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOSTACK_P_H -#define QUNDOSTACK_P_H - -#include <QtWidgets/private/qtwidgetsglobal_p.h> -#include <private/qobject_p.h> -#include <QtCore/qlist.h> -#include <QtCore/qstring.h> -#if QT_CONFIG(action) -# include <QtGui/qaction.h> -#endif - -#include "qundostack.h" - -QT_BEGIN_NAMESPACE -class QUndoCommand; -class QUndoGroup; - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -class QUndoCommandPrivate -{ -public: - QUndoCommandPrivate() : id(-1), obsolete(false) {} - QList<QUndoCommand*> child_list; - QString text; - QString actionText; - int id; - bool obsolete; -}; - -#if QT_CONFIG(undostack) - -class QUndoStackPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QUndoStack) -public: - QUndoStackPrivate() : index(0), clean_index(0), group(nullptr), undo_limit(0) {} - - QList<QUndoCommand*> command_list; - QList<QUndoCommand*> macro_stack; - int index; - int clean_index; - QUndoGroup *group; - int undo_limit; - - void setIndex(int idx, bool clean); - bool checkUndoLimit(); -}; - -#ifndef QT_NO_ACTION -class QUndoAction : public QAction -{ - Q_OBJECT -public: - explicit QUndoAction(const QString &prefix, QObject *parent = nullptr); - void setTextFormat(const QString &textFormat, const QString &defaultText); -public Q_SLOTS: - void setPrefixedText(const QString &text); -private: - QString m_prefix; - QString m_defaultText; -}; -#endif // QT_NO_ACTION - -QT_END_NAMESPACE -#endif // QT_CONFIG(undostack) -#endif // QUNDOSTACK_P_H diff --git a/src/widgets/util/qundoview.cpp b/src/widgets/util/qundoview.cpp index a39276a2b8..a823c005c1 100644 --- a/src/widgets/util/qundoview.cpp +++ b/src/widgets/util/qundoview.cpp @@ -37,12 +37,12 @@ ** ****************************************************************************/ -#include "qundostack.h" #include "qundoview.h" #if QT_CONFIG(undogroup) -#include "qundogroup.h" +#include <QtGui/qundogroup.h> #endif +#include <QtGui/qundostack.h> #include <QtCore/qabstractitemmodel.h> #include <QtCore/qpointer.h> #include <QtGui/qicon.h> diff --git a/src/widgets/util/util.pri b/src/widgets/util/util.pri index 363291528e..2819ac565a 100644 --- a/src/widgets/util/util.pri +++ b/src/widgets/util/util.pri @@ -31,19 +31,6 @@ qtConfig(scroller) { util/qflickgesture.cpp \ } -qtConfig(undocommand) { - HEADERS += \ - util/qundostack.h \ - util/qundostack_p.h - - SOURCES += util/qundostack.cpp -} - -qtConfig(undogroup) { - HEADERS += util/qundogroup.h - SOURCES += util/qundogroup.cpp -} - qtConfig(undoview) { HEADERS += util/qundoview.h SOURCES += util/qundoview.cpp |