diff options
author | Alexis Menard <alexis.menard@nokia.com> | 2009-04-17 14:06:06 (GMT) |
---|---|---|
committer | Alexis Menard <alexis.menard@nokia.com> | 2009-04-17 14:06:06 (GMT) |
commit | f15b8a83e2e51955776a3f07cb85ebfc342dd8ef (patch) | |
tree | c5dc684986051654898db11ce73e03b9fec8db99 /demos/undo | |
download | Qt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.zip Qt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.tar.gz Qt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.tar.bz2 |
Initial import of statemachine branch from the old kinetic repository
Diffstat (limited to 'demos/undo')
26 files changed, 1810 insertions, 0 deletions
diff --git a/demos/undo/commands.cpp b/demos/undo/commands.cpp new file mode 100644 index 0000000..4802e34 --- /dev/null +++ b/demos/undo/commands.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "commands.h" + +static const int setShapeRectCommandId = 1; +static const int setShapeColorCommandId = 2; + +/****************************************************************************** +** AddShapeCommand +*/ + +AddShapeCommand::AddShapeCommand(Document *doc, const Shape &shape, QUndoCommand *parent) + : QUndoCommand(parent) +{ + m_doc = doc; + m_shape = shape; +} + +void AddShapeCommand::undo() +{ + m_doc->deleteShape(m_shapeName); +} + +void AddShapeCommand::redo() +{ + // A shape only gets a name when it is inserted into a document + m_shapeName = m_doc->addShape(m_shape); + setText(QObject::tr("Add %1").arg(m_shapeName)); +} + +/****************************************************************************** +** RemoveShapeCommand +*/ + +RemoveShapeCommand::RemoveShapeCommand(Document *doc, const QString &shapeName, + QUndoCommand *parent) + : QUndoCommand(parent) +{ + setText(QObject::tr("Remove %1").arg(shapeName)); + m_doc = doc; + m_shape = doc->shape(shapeName); + m_shapeName = shapeName; +} + +void RemoveShapeCommand::undo() +{ + m_shapeName = m_doc->addShape(m_shape); +} + +void RemoveShapeCommand::redo() +{ + m_doc->deleteShape(m_shapeName); +} + +/****************************************************************************** +** SetShapeColorCommand +*/ + +SetShapeColorCommand::SetShapeColorCommand(Document *doc, const QString &shapeName, + const QColor &color, QUndoCommand *parent) + : QUndoCommand(parent) +{ + setText(QObject::tr("Set %1's color").arg(shapeName)); + + m_doc = doc; + m_shapeName = shapeName; + m_oldColor = doc->shape(shapeName).color(); + m_newColor = color; +} + +void SetShapeColorCommand::undo() +{ + m_doc->setShapeColor(m_shapeName, m_oldColor); +} + +void SetShapeColorCommand::redo() +{ + m_doc->setShapeColor(m_shapeName, m_newColor); +} + +bool SetShapeColorCommand::mergeWith(const QUndoCommand *command) +{ + if (command->id() != setShapeColorCommandId) + return false; + + const SetShapeColorCommand *other = static_cast<const SetShapeColorCommand*>(command); + if (m_shapeName != other->m_shapeName) + return false; + + m_newColor = other->m_newColor; + return true; +} + +int SetShapeColorCommand::id() const +{ + return setShapeColorCommandId; +} + +/****************************************************************************** +** SetShapeRectCommand +*/ + +SetShapeRectCommand::SetShapeRectCommand(Document *doc, const QString &shapeName, + const QRect &rect, QUndoCommand *parent) + : QUndoCommand(parent) +{ + setText(QObject::tr("Change %1's geometry").arg(shapeName)); + + m_doc = doc; + m_shapeName = shapeName; + m_oldRect = doc->shape(shapeName).rect(); + m_newRect = rect; +} + +void SetShapeRectCommand::undo() +{ + m_doc->setShapeRect(m_shapeName, m_oldRect); +} + +void SetShapeRectCommand::redo() +{ + m_doc->setShapeRect(m_shapeName, m_newRect); +} + +bool SetShapeRectCommand::mergeWith(const QUndoCommand *command) +{ + if (command->id() != setShapeRectCommandId) + return false; + + const SetShapeRectCommand *other = static_cast<const SetShapeRectCommand*>(command); + if (m_shapeName != other->m_shapeName) + return false; + + m_newRect = other->m_newRect; + return true; +} + +int SetShapeRectCommand::id() const +{ + return setShapeRectCommandId; +} diff --git a/demos/undo/commands.h b/demos/undo/commands.h new file mode 100644 index 0000000..f98cb6d --- /dev/null +++ b/demos/undo/commands.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COMMANDS_H +#define COMMANDS_H + +#include <QUndoCommand> +#include "document.h" + +class AddShapeCommand : public QUndoCommand +{ +public: + AddShapeCommand(Document *doc, const Shape &shape, QUndoCommand *parent = 0); + void undo(); + void redo(); + +private: + Document *m_doc; + Shape m_shape; + QString m_shapeName; +}; + +class RemoveShapeCommand : public QUndoCommand +{ +public: + RemoveShapeCommand(Document *doc, const QString &shapeName, QUndoCommand *parent = 0); + void undo(); + void redo(); + +private: + Document *m_doc; + Shape m_shape; + QString m_shapeName; +}; + +class SetShapeColorCommand : public QUndoCommand +{ +public: + SetShapeColorCommand(Document *doc, const QString &shapeName, const QColor &color, + QUndoCommand *parent = 0); + + void undo(); + void redo(); + + bool mergeWith(const QUndoCommand *command); + int id() const; + +private: + Document *m_doc; + QString m_shapeName; + QColor m_oldColor; + QColor m_newColor; +}; + +class SetShapeRectCommand : public QUndoCommand +{ +public: + SetShapeRectCommand(Document *doc, const QString &shapeName, const QRect &rect, + QUndoCommand *parent = 0); + + void undo(); + void redo(); + + bool mergeWith(const QUndoCommand *command); + int id() const; + +private: + Document *m_doc; + QString m_shapeName; + QRect m_oldRect; + QRect m_newRect; +}; + +#endif // COMMANDS_H diff --git a/demos/undo/document.cpp b/demos/undo/document.cpp new file mode 100644 index 0000000..df435fd --- /dev/null +++ b/demos/undo/document.cpp @@ -0,0 +1,445 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qevent.h> +#include <QPainter> +#include <QTextStream> +#include <QUndoStack> +#include "document.h" +#include "commands.h" + +static const int resizeHandleWidth = 6; + +/****************************************************************************** +** Shape +*/ + +const QSize Shape::minSize(80, 50); + +Shape::Shape(Type type, const QColor &color, const QRect &rect) + : m_type(type), m_rect(rect), m_color(color) +{ +} + +Shape::Type Shape::type() const +{ + return m_type; +} + +QRect Shape::rect() const +{ + return m_rect; +} + +QColor Shape::color() const +{ + return m_color; +} + +QString Shape::name() const +{ + return m_name; +} + +QRect Shape::resizeHandle() const +{ + QPoint br = m_rect.bottomRight(); + return QRect(br - QPoint(resizeHandleWidth, resizeHandleWidth), br); +} + +QString Shape::typeToString(Type type) +{ + QString result; + + switch (type) { + case Rectangle: + result = QLatin1String("Rectangle"); + break; + case Circle: + result = QLatin1String("Circle"); + break; + case Triangle: + result = QLatin1String("Triangle"); + break; + } + + return result; +} + +Shape::Type Shape::stringToType(const QString &s, bool *ok) +{ + if (ok != 0) + *ok = true; + + if (s == QLatin1String("Rectangle")) + return Rectangle; + if (s == QLatin1String("Circle")) + return Circle; + if (s == QLatin1String("Triangle")) + return Triangle; + + if (ok != 0) + *ok = false; + return Rectangle; +} + +/****************************************************************************** +** Document +*/ + +Document::Document(QWidget *parent) + : QWidget(parent), m_currentIndex(-1), m_mousePressIndex(-1), m_resizeHandlePressed(false) +{ + m_undoStack = new QUndoStack(this); + + setAutoFillBackground(true); + setBackgroundRole(QPalette::Base); + + QPalette pal = palette(); + pal.setBrush(QPalette::Base, QPixmap(":/icons/background.png")); + pal.setColor(QPalette::HighlightedText, Qt::red); + setPalette(pal); +} + +QString Document::addShape(const Shape &shape) +{ + QString name = Shape::typeToString(shape.type()); + name = uniqueName(name); + + m_shapeList.append(shape); + m_shapeList[m_shapeList.count() - 1].m_name = name; + setCurrentShape(m_shapeList.count() - 1); + + return name; +} + +void Document::deleteShape(const QString &shapeName) +{ + int index = indexOf(shapeName); + if (index == -1) + return; + + update(m_shapeList.at(index).rect()); + + m_shapeList.removeAt(index); + + if (index <= m_currentIndex) { + m_currentIndex = -1; + if (index == m_shapeList.count()) + --index; + setCurrentShape(index); + } +} + +Shape Document::shape(const QString &shapeName) const +{ + int index = indexOf(shapeName); + if (index == -1) + return Shape(); + return m_shapeList.at(index); +} + +void Document::setShapeRect(const QString &shapeName, const QRect &rect) +{ + int index = indexOf(shapeName); + if (index == -1) + return; + + Shape &shape = m_shapeList[index]; + + update(shape.rect()); + update(rect); + + shape.m_rect = rect; +} + +void Document::setShapeColor(const QString &shapeName, const QColor &color) +{ + + int index = indexOf(shapeName); + if (index == -1) + return; + + Shape &shape = m_shapeList[index]; + shape.m_color = color; + + update(shape.rect()); +} + +QUndoStack *Document::undoStack() const +{ + return m_undoStack; +} + +bool Document::load(QTextStream &stream) +{ + m_shapeList.clear(); + + while (!stream.atEnd()) { + QString shapeType, shapeName, colorName; + int left, top, width, height; + stream >> shapeType >> shapeName >> colorName >> left >> top >> width >> height; + if (stream.status() != QTextStream::Ok) + return false; + bool ok; + Shape::Type type = Shape::stringToType(shapeType, &ok); + if (!ok) + return false; + QColor color(colorName); + if (!color.isValid()) + return false; + + Shape shape(type); + shape.m_name = shapeName; + shape.m_color = color; + shape.m_rect = QRect(left, top, width, height); + + m_shapeList.append(shape); + } + + m_currentIndex = m_shapeList.isEmpty() ? -1 : 0; + + return true; +} + +void Document::save(QTextStream &stream) +{ + for (int i = 0; i < m_shapeList.count(); ++i) { + const Shape &shape = m_shapeList.at(i); + QRect r = shape.rect(); + stream << Shape::typeToString(shape.type()) << QLatin1Char(' ') + << shape.name() << QLatin1Char(' ') + << shape.color().name() << QLatin1Char(' ') + << r.left() << QLatin1Char(' ') + << r.top() << QLatin1Char(' ') + << r.width() << QLatin1Char(' ') + << r.height(); + if (i != m_shapeList.count() - 1) + stream << QLatin1Char('\n'); + } + m_undoStack->setClean(); +} + +QString Document::fileName() const +{ + return m_fileName; +} + +void Document::setFileName(const QString &fileName) +{ + m_fileName = fileName; +} + +int Document::indexAt(const QPoint &pos) const +{ + for (int i = m_shapeList.count() - 1; i >= 0; --i) { + if (m_shapeList.at(i).rect().contains(pos)) + return i; + } + return -1; +} + +void Document::mousePressEvent(QMouseEvent *event) +{ + event->accept(); + int index = indexAt(event->pos());; + if (index != -1) { + setCurrentShape(index); + + const Shape &shape = m_shapeList.at(index); + m_resizeHandlePressed = shape.resizeHandle().contains(event->pos()); + + if (m_resizeHandlePressed) + m_mousePressOffset = shape.rect().bottomRight() - event->pos(); + else + m_mousePressOffset = event->pos() - shape.rect().topLeft(); + } + m_mousePressIndex = index; +} + +void Document::mouseReleaseEvent(QMouseEvent *event) +{ + event->accept(); + m_mousePressIndex = -1; +} + +void Document::mouseMoveEvent(QMouseEvent *event) +{ + event->accept(); + + if (m_mousePressIndex == -1) + return; + + const Shape &shape = m_shapeList.at(m_mousePressIndex); + + QRect rect; + if (m_resizeHandlePressed) { + rect = QRect(shape.rect().topLeft(), event->pos() + m_mousePressOffset); + } else { + rect = shape.rect(); + rect.moveTopLeft(event->pos() - m_mousePressOffset); + } + + QSize size = rect.size().expandedTo(Shape::minSize); + rect.setSize(size); + + m_undoStack->push(new SetShapeRectCommand(this, shape.name(), rect)); +} + +static QGradient gradient(const QColor &color, const QRect &rect) +{ + QColor c = color; + c.setAlpha(160); + QLinearGradient result(rect.topLeft(), rect.bottomRight()); + result.setColorAt(0, c.dark(150)); + result.setColorAt(0.5, c.light(200)); + result.setColorAt(1, c.dark(150)); + return result; +} + +static QPolygon triangle(const QRect &rect) +{ + QPolygon result(3); + result.setPoint(0, rect.center().x(), rect.top()); + result.setPoint(1, rect.right(), rect.bottom()); + result.setPoint(2, rect.left(), rect.bottom()); + return result; +} + +void Document::paintEvent(QPaintEvent *event) +{ + QRegion paintRegion = event->region(); + QPainter painter(this); + QPalette pal = palette(); + + for (int i = 0; i < m_shapeList.count(); ++i) { + const Shape &shape = m_shapeList.at(i); + + if (!paintRegion.contains(shape.rect())) + continue; + + QPen pen = pal.text().color(); + pen.setWidth(i == m_currentIndex ? 2 : 1); + painter.setPen(pen); + painter.setBrush(gradient(shape.color(), shape.rect())); + + QRect rect = shape.rect(); + rect.adjust(1, 1, -resizeHandleWidth/2, -resizeHandleWidth/2); + + // paint the shape + switch (shape.type()) { + case Shape::Rectangle: + painter.drawRect(rect); + break; + case Shape::Circle: + painter.setRenderHint(QPainter::Antialiasing); + painter.drawEllipse(rect); + painter.setRenderHint(QPainter::Antialiasing, false); + break; + case Shape::Triangle: + painter.setRenderHint(QPainter::Antialiasing); + painter.drawPolygon(triangle(rect)); + painter.setRenderHint(QPainter::Antialiasing, false); + break; + } + + // paint the resize handle + painter.setPen(pal.text().color()); + painter.setBrush(Qt::white); + painter.drawRect(shape.resizeHandle().adjusted(0, 0, -1, -1)); + + // paint the shape name + painter.setBrush(pal.text()); + if (shape.type() == Shape::Triangle) + rect.adjust(0, rect.height()/2, 0, 0); + painter.drawText(rect, Qt::AlignCenter, shape.name()); + } +} + +void Document::setCurrentShape(int index) +{ + QString currentName; + + if (m_currentIndex != -1) + update(m_shapeList.at(m_currentIndex).rect()); + + m_currentIndex = index; + + if (m_currentIndex != -1) { + const Shape ¤t = m_shapeList.at(m_currentIndex); + update(current.rect()); + currentName = current.name(); + } + + emit currentShapeChanged(currentName); +} + +int Document::indexOf(const QString &shapeName) const +{ + for (int i = 0; i < m_shapeList.count(); ++i) { + if (m_shapeList.at(i).name() == shapeName) + return i; + } + return -1; +} + +QString Document::uniqueName(const QString &name) const +{ + QString unique; + + for (int i = 0; ; ++i) { + unique = name; + if (i > 0) + unique += QString::number(i); + if (indexOf(unique) == -1) + break; + } + + return unique; +} + +QString Document::currentShapeName() const +{ + if (m_currentIndex == -1) + return QString(); + return m_shapeList.at(m_currentIndex).name(); +} + diff --git a/demos/undo/document.h b/demos/undo/document.h new file mode 100644 index 0000000..0b12ad0 --- /dev/null +++ b/demos/undo/document.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOCUMENT_H +#define DOCUMENT_H + +#include <QWidget> + +QT_FORWARD_DECLARE_CLASS(QUndoStack) +QT_FORWARD_DECLARE_CLASS(QTextStream) + +class Shape +{ +public: + enum Type { Rectangle, Circle, Triangle }; + + Shape(Type type = Rectangle, const QColor &color = Qt::red, const QRect &rect = QRect()); + + Type type() const; + QString name() const; + QRect rect() const; + QRect resizeHandle() const; + QColor color() const; + + static QString typeToString(Type type); + static Type stringToType(const QString &s, bool *ok = 0); + + static const QSize minSize; + +private: + Type m_type; + QRect m_rect; + QColor m_color; + QString m_name; + + friend class Document; +}; + +class Document : public QWidget +{ + Q_OBJECT + +public: + Document(QWidget *parent = 0); + + QString addShape(const Shape &shape); + void deleteShape(const QString &shapeName); + Shape shape(const QString &shapeName) const; + QString currentShapeName() const; + + void setShapeRect(const QString &shapeName, const QRect &rect); + void setShapeColor(const QString &shapeName, const QColor &color); + + bool load(QTextStream &stream); + void save(QTextStream &stream); + + QString fileName() const; + void setFileName(const QString &fileName); + + QUndoStack *undoStack() const; + +signals: + void currentShapeChanged(const QString &shapeName); + +protected: + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + +private: + void setCurrentShape(int index); + int indexOf(const QString &shapeName) const; + int indexAt(const QPoint &pos) const; + QString uniqueName(const QString &name) const; + + QList<Shape> m_shapeList; + int m_currentIndex; + int m_mousePressIndex; + QPoint m_mousePressOffset; + bool m_resizeHandlePressed; + QString m_fileName; + + QUndoStack *m_undoStack; +}; + +#endif // DOCUMENT_H diff --git a/demos/undo/icons/background.png b/demos/undo/icons/background.png Binary files differnew file mode 100644 index 0000000..3bc5ed8 --- /dev/null +++ b/demos/undo/icons/background.png diff --git a/demos/undo/icons/blue.png b/demos/undo/icons/blue.png Binary files differnew file mode 100644 index 0000000..4e181bb --- /dev/null +++ b/demos/undo/icons/blue.png diff --git a/demos/undo/icons/circle.png b/demos/undo/icons/circle.png Binary files differnew file mode 100644 index 0000000..ed16c6e --- /dev/null +++ b/demos/undo/icons/circle.png diff --git a/demos/undo/icons/exit.png b/demos/undo/icons/exit.png Binary files differnew file mode 100644 index 0000000..539cb2e --- /dev/null +++ b/demos/undo/icons/exit.png diff --git a/demos/undo/icons/fileclose.png b/demos/undo/icons/fileclose.png Binary files differnew file mode 100644 index 0000000..c5483d1 --- /dev/null +++ b/demos/undo/icons/fileclose.png diff --git a/demos/undo/icons/filenew.png b/demos/undo/icons/filenew.png Binary files differnew file mode 100644 index 0000000..57e57e3 --- /dev/null +++ b/demos/undo/icons/filenew.png diff --git a/demos/undo/icons/fileopen.png b/demos/undo/icons/fileopen.png Binary files differnew file mode 100644 index 0000000..33e0d63 --- /dev/null +++ b/demos/undo/icons/fileopen.png diff --git a/demos/undo/icons/filesave.png b/demos/undo/icons/filesave.png Binary files differnew file mode 100644 index 0000000..57fd5e2 --- /dev/null +++ b/demos/undo/icons/filesave.png diff --git a/demos/undo/icons/green.png b/demos/undo/icons/green.png Binary files differnew file mode 100644 index 0000000..e2e7cc9 --- /dev/null +++ b/demos/undo/icons/green.png diff --git a/demos/undo/icons/ok.png b/demos/undo/icons/ok.png Binary files differnew file mode 100644 index 0000000..e355ea9 --- /dev/null +++ b/demos/undo/icons/ok.png diff --git a/demos/undo/icons/rectangle.png b/demos/undo/icons/rectangle.png Binary files differnew file mode 100644 index 0000000..3a7d979 --- /dev/null +++ b/demos/undo/icons/rectangle.png diff --git a/demos/undo/icons/red.png b/demos/undo/icons/red.png Binary files differnew file mode 100644 index 0000000..58c3e72 --- /dev/null +++ b/demos/undo/icons/red.png diff --git a/demos/undo/icons/redo.png b/demos/undo/icons/redo.png Binary files differnew file mode 100644 index 0000000..5591517 --- /dev/null +++ b/demos/undo/icons/redo.png diff --git a/demos/undo/icons/remove.png b/demos/undo/icons/remove.png Binary files differnew file mode 100644 index 0000000..7a7b048 --- /dev/null +++ b/demos/undo/icons/remove.png diff --git a/demos/undo/icons/triangle.png b/demos/undo/icons/triangle.png Binary files differnew file mode 100644 index 0000000..2969131 --- /dev/null +++ b/demos/undo/icons/triangle.png diff --git a/demos/undo/icons/undo.png b/demos/undo/icons/undo.png Binary files differnew file mode 100644 index 0000000..8cf63a8 --- /dev/null +++ b/demos/undo/icons/undo.png diff --git a/demos/undo/main.cpp b/demos/undo/main.cpp new file mode 100644 index 0000000..f36a6e8 --- /dev/null +++ b/demos/undo/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include "mainwindow.h" + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(undo); + + QApplication app(argc, argv); + + MainWindow win; + win.resize(800, 600); + win.show(); + + return app.exec(); +}; diff --git a/demos/undo/mainwindow.cpp b/demos/undo/mainwindow.cpp new file mode 100644 index 0000000..409fd14 --- /dev/null +++ b/demos/undo/mainwindow.cpp @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QUndoGroup> +#include <QUndoStack> +#include <QFileDialog> +#include <QMessageBox> +#include <QTextStream> +#include <QToolButton> +#include "document.h" +#include "mainwindow.h" +#include "commands.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + setupUi(this); + + QWidget *w = documentTabs->widget(0); + documentTabs->removeTab(0); + delete w; + + connect(actionOpen, SIGNAL(triggered()), this, SLOT(openDocument())); + connect(actionClose, SIGNAL(triggered()), this, SLOT(closeDocument())); + connect(actionNew, SIGNAL(triggered()), this, SLOT(newDocument())); + connect(actionSave, SIGNAL(triggered()), this, SLOT(saveDocument())); + connect(actionExit, SIGNAL(triggered()), this, SLOT(close())); + connect(actionRed, SIGNAL(triggered()), this, SLOT(setShapeColor())); + connect(actionGreen, SIGNAL(triggered()), this, SLOT(setShapeColor())); + connect(actionBlue, SIGNAL(triggered()), this, SLOT(setShapeColor())); + connect(actionAddCircle, SIGNAL(triggered()), this, SLOT(addShape())); + connect(actionAddRectangle, SIGNAL(triggered()), this, SLOT(addShape())); + connect(actionAddTriangle, SIGNAL(triggered()), this, SLOT(addShape())); + connect(actionRemoveShape, SIGNAL(triggered()), this, SLOT(removeShape())); + connect(actionAddRobot, SIGNAL(triggered()), this, SLOT(addRobot())); + connect(actionAddSnowman, SIGNAL(triggered()), this, SLOT(addSnowman())); + connect(actionAbout, SIGNAL(triggered()), this, SLOT(about())); + connect(actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt())); + + connect(undoLimit, SIGNAL(valueChanged(int)), this, SLOT(updateActions())); + connect(documentTabs, SIGNAL(currentChanged(int)), this, SLOT(updateActions())); + + actionOpen->setShortcut(QString("Ctrl+O")); + actionClose->setShortcut(QString("Ctrl+W")); + actionNew->setShortcut(QString("Ctrl+N")); + actionSave->setShortcut(QString("Ctrl+S")); + actionExit->setShortcut(QString("Ctrl+Q")); + actionRemoveShape->setShortcut(QString("Del")); + actionRed->setShortcut(QString("Alt+R")); + actionGreen->setShortcut(QString("Alt+G")); + actionBlue->setShortcut(QString("Alt+B")); + actionAddCircle->setShortcut(QString("Alt+C")); + actionAddRectangle->setShortcut(QString("Alt+L")); + actionAddTriangle->setShortcut(QString("Alt+T")); + + m_undoGroup = new QUndoGroup(this); + undoView->setGroup(m_undoGroup); + undoView->setCleanIcon(QIcon(":/icons/ok.png")); + + QAction *undoAction = m_undoGroup->createUndoAction(this); + QAction *redoAction = m_undoGroup->createRedoAction(this); + undoAction->setIcon(QIcon(":/icons/undo.png")); + redoAction->setIcon(QIcon(":/icons/redo.png")); + menuShape->insertAction(menuShape->actions().at(0), undoAction); + menuShape->insertAction(undoAction, redoAction); + + toolBar->addAction(undoAction); + toolBar->addAction(redoAction); + + newDocument(); + updateActions(); +}; + +void MainWindow::updateActions() +{ + Document *doc = currentDocument(); + m_undoGroup->setActiveStack(doc == 0 ? 0 : doc->undoStack()); + QString shapeName = doc == 0 ? QString() : doc->currentShapeName(); + + actionAddRobot->setEnabled(doc != 0); + actionAddSnowman->setEnabled(doc != 0); + actionAddCircle->setEnabled(doc != 0); + actionAddRectangle->setEnabled(doc != 0); + actionAddTriangle->setEnabled(doc != 0); + actionClose->setEnabled(doc != 0); + actionSave->setEnabled(doc != 0 && !doc->undoStack()->isClean()); + undoLimit->setEnabled(doc != 0 && doc->undoStack()->count() == 0); + + if (shapeName.isEmpty()) { + actionRed->setEnabled(false); + actionGreen->setEnabled(false); + actionBlue->setEnabled(false); + actionRemoveShape->setEnabled(false); + } else { + Shape shape = doc->shape(shapeName); + actionRed->setEnabled(shape.color() != Qt::red); + actionGreen->setEnabled(shape.color() != Qt::green); + actionBlue->setEnabled(shape.color() != Qt::blue); + actionRemoveShape->setEnabled(true); + } + + if (doc != 0) { + int index = documentTabs->indexOf(doc); + Q_ASSERT(index != -1); + static const QIcon unsavedIcon(":/icons/filesave.png"); + documentTabs->setTabIcon(index, doc->undoStack()->isClean() ? QIcon() : unsavedIcon); + + if (doc->undoStack()->count() == 0) + doc->undoStack()->setUndoLimit(undoLimit->value()); + } +} + +void MainWindow::openDocument() +{ + QString fileName = QFileDialog::getOpenFileName(this); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, + tr("File error"), + tr("Failed to open\n%1").arg(fileName)); + return; + } + QTextStream stream(&file); + + Document *doc = new Document(); + if (!doc->load(stream)) { + QMessageBox::warning(this, + tr("Parse error"), + tr("Failed to parse\n%1").arg(fileName)); + delete doc; + return; + } + + doc->setFileName(fileName); + addDocument(doc); +} + +QString MainWindow::fixedWindowTitle(const Document *doc) const +{ + QString title = doc->fileName(); + + if (title.isEmpty()) + title = tr("Unnamed"); + else + title = QFileInfo(title).fileName(); + + QString result; + + for (int i = 0; ; ++i) { + result = title; + if (i > 0) + result += QString::number(i); + + bool unique = true; + for (int j = 0; j < documentTabs->count(); ++j) { + const QWidget *widget = documentTabs->widget(j); + if (widget == doc) + continue; + if (result == documentTabs->tabText(j)) { + unique = false; + break; + } + } + + if (unique) + break; + } + + return result; +} + +void MainWindow::addDocument(Document *doc) +{ + if (documentTabs->indexOf(doc) != -1) + return; + m_undoGroup->addStack(doc->undoStack()); + documentTabs->addTab(doc, fixedWindowTitle(doc)); + connect(doc, SIGNAL(currentShapeChanged(QString)), this, SLOT(updateActions())); + connect(doc->undoStack(), SIGNAL(indexChanged(int)), this, SLOT(updateActions())); + connect(doc->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateActions())); + + setCurrentDocument(doc); +} + +void MainWindow::setCurrentDocument(Document *doc) +{ + documentTabs->setCurrentWidget(doc); +} + +Document *MainWindow::currentDocument() const +{ + return qobject_cast<Document*>(documentTabs->currentWidget()); +} + +void MainWindow::removeDocument(Document *doc) +{ + int index = documentTabs->indexOf(doc); + if (index == -1) + return; + + documentTabs->removeTab(index); + m_undoGroup->removeStack(doc->undoStack()); + disconnect(doc, SIGNAL(currentShapeChanged(QString)), this, SLOT(updateActions())); + disconnect(doc->undoStack(), SIGNAL(indexChanged(int)), this, SLOT(updateActions())); + disconnect(doc->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateActions())); + + if (documentTabs->count() == 0) { + newDocument(); + updateActions(); + } +} + +void MainWindow::saveDocument() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + for (;;) { + QString fileName = doc->fileName(); + + if (fileName.isEmpty()) + fileName = QFileDialog::getSaveFileName(this); + if (fileName.isEmpty()) + break; + + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::warning(this, + tr("File error"), + tr("Failed to open\n%1").arg(fileName)); + doc->setFileName(QString()); + } else { + QTextStream stream(&file); + doc->save(stream); + doc->setFileName(fileName); + + int index = documentTabs->indexOf(doc); + Q_ASSERT(index != -1); + documentTabs->setTabText(index, fixedWindowTitle(doc)); + + break; + } + } +} + +void MainWindow::closeDocument() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + if (!doc->undoStack()->isClean()) { + int button + = QMessageBox::warning(this, + tr("Unsaved changes"), + tr("Would you like to save this document?"), + QMessageBox::Yes, QMessageBox::No); + if (button == QMessageBox::Yes) + saveDocument(); + } + + removeDocument(doc); + delete doc; +} + +void MainWindow::newDocument() +{ + addDocument(new Document()); +} + +static QColor randomColor() +{ + int r = (int) (3.0*(rand()/(RAND_MAX + 1.0))); + switch (r) { + case 0: + return Qt::red; + case 1: + return Qt::green; + default: + break; + } + return Qt::blue; +} + +static QRect randomRect(const QSize &s) +{ + QSize min = Shape::minSize; + + int left = (int) ((0.0 + s.width() - min.width())*(rand()/(RAND_MAX + 1.0))); + int top = (int) ((0.0 + s.height() - min.height())*(rand()/(RAND_MAX + 1.0))); + int width = (int) ((0.0 + s.width() - left - min.width())*(rand()/(RAND_MAX + 1.0))) + min.width(); + int height = (int) ((0.0 + s.height() - top - min.height())*(rand()/(RAND_MAX + 1.0))) + min.height(); + + return QRect(left, top, width, height); +} + +void MainWindow::addShape() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + Shape::Type type; + + if (sender() == actionAddCircle) + type = Shape::Circle; + else if (sender() == actionAddRectangle) + type = Shape::Rectangle; + else if (sender() == actionAddTriangle) + type = Shape::Triangle; + else return; + + Shape newShape(type, randomColor(), randomRect(doc->size())); + doc->undoStack()->push(new AddShapeCommand(doc, newShape)); +} + +void MainWindow::removeShape() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + QString shapeName = doc->currentShapeName(); + if (shapeName.isEmpty()) + return; + + doc->undoStack()->push(new RemoveShapeCommand(doc, shapeName)); +} + +void MainWindow::setShapeColor() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + QString shapeName = doc->currentShapeName(); + if (shapeName.isEmpty()) + return; + + QColor color; + + if (sender() == actionRed) + color = Qt::red; + else if (sender() == actionGreen) + color = Qt::green; + else if (sender() == actionBlue) + color = Qt::blue; + else + return; + + if (color == doc->shape(shapeName).color()) + return; + + doc->undoStack()->push(new SetShapeColorCommand(doc, shapeName, color)); +} + +void MainWindow::addSnowman() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + // Create a macro command using beginMacro() and endMacro() + + doc->undoStack()->beginMacro(tr("Add snowman")); + doc->undoStack()->push(new AddShapeCommand(doc, + Shape(Shape::Circle, Qt::blue, QRect(51, 30, 97, 95)))); + doc->undoStack()->push(new AddShapeCommand(doc, + Shape(Shape::Circle, Qt::blue, QRect(27, 123, 150, 133)))); + doc->undoStack()->push(new AddShapeCommand(doc, + Shape(Shape::Circle, Qt::blue, QRect(11, 253, 188, 146)))); + doc->undoStack()->endMacro(); +} + +void MainWindow::addRobot() +{ + Document *doc = currentDocument(); + if (doc == 0) + return; + + // Compose a macro command by explicitly adding children to a parent command + + QUndoCommand *parent = new QUndoCommand(tr("Add robot")); + + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(115, 15, 81, 70)), parent); + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(82, 89, 148, 188)), parent); + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(76, 280, 80, 165)), parent); + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(163, 280, 80, 164)), parent); + new AddShapeCommand(doc, Shape(Shape::Circle, Qt::blue, QRect(116, 25, 80, 50)), parent); + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(232, 92, 80, 127)), parent); + new AddShapeCommand(doc, Shape(Shape::Rectangle, Qt::green, QRect(2, 92, 80, 125)), parent); + + doc->undoStack()->push(parent); +} + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Undo"), tr("The Undo demonstration shows how to use the Qt Undo framework.")); +} + +void MainWindow::aboutQt() +{ + QMessageBox::aboutQt(this, tr("About Qt")); +} diff --git a/demos/undo/mainwindow.h b/demos/undo/mainwindow.h new file mode 100644 index 0000000..5340e94 --- /dev/null +++ b/demos/undo/mainwindow.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> +#include "ui_mainwindow.h" + +class Document; + +class MainWindow : public QMainWindow, public Ui::MainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + + void addDocument(Document *doc); + void removeDocument(Document *doc); + void setCurrentDocument(Document *doc); + Document *currentDocument() const; + +public slots: + void openDocument(); + void saveDocument(); + void closeDocument(); + void newDocument(); + + void addShape(); + void removeShape(); + void setShapeColor(); + + void addSnowman(); + void addRobot(); + + void about(); + void aboutQt(); + +private slots: + void updateActions(); + +private: + QUndoGroup *m_undoGroup; + + QString fixedWindowTitle(const Document *doc) const; +}; + +#endif // MAINWINDOW_H diff --git a/demos/undo/mainwindow.ui b/demos/undo/mainwindow.ui new file mode 100644 index 0000000..91a0b43 --- /dev/null +++ b/demos/undo/mainwindow.ui @@ -0,0 +1,322 @@ +<ui version="4.0" > + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>567</width> + <height>600</height> + </rect> + </property> + <property name="iconSize" > + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <widget class="QWidget" name="centralwidget" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="documentTabs" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <attribute name="title" > + <string>Tab 1</string> + </attribute> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>567</width> + <height>27</height> + </rect> + </property> + <widget class="QMenu" name="menuFile" > + <property name="title" > + <string>File</string> + </property> + <addaction name="actionNew" /> + <addaction name="actionOpen" /> + <addaction name="actionSave" /> + <addaction name="actionClose" /> + <addaction name="separator" /> + <addaction name="actionExit" /> + </widget> + <widget class="QMenu" name="menuShape" > + <property name="title" > + <string>Edit</string> + </property> + <widget class="QMenu" name="menuMacros" > + <property name="title" > + <string>Macros</string> + </property> + <addaction name="actionAddRobot" /> + <addaction name="actionAddSnowman" /> + </widget> + <addaction name="separator" /> + <addaction name="actionAddCircle" /> + <addaction name="actionAddRectangle" /> + <addaction name="actionAddTriangle" /> + <addaction name="actionRemoveShape" /> + <addaction name="separator" /> + <addaction name="actionRed" /> + <addaction name="actionGreen" /> + <addaction name="actionBlue" /> + <addaction name="separator" /> + <addaction name="menuMacros" /> + </widget> + <widget class="QMenu" name="menuHelp" > + <property name="title" > + <string>Help</string> + </property> + <addaction name="actionAbout" /> + <addaction name="actionAboutQt" /> + </widget> + <addaction name="menuFile" /> + <addaction name="menuShape" /> + <addaction name="menuHelp" /> + </widget> + <widget class="QStatusBar" name="statusbar" /> + <widget class="QToolBar" name="toolBar" > + <property name="windowTitle" > + <string>File actions</string> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <attribute name="toolBarArea" > + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak" > + <bool>false</bool> + </attribute> + <addaction name="actionNew" /> + <addaction name="actionOpen" /> + <addaction name="actionSave" /> + <addaction name="actionClose" /> + <addaction name="separator" /> + </widget> + <widget class="QToolBar" name="shapeToolBar" > + <property name="windowTitle" > + <string>Shape actions</string> + </property> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <attribute name="toolBarArea" > + <enum>LeftToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak" > + <bool>false</bool> + </attribute> + <addaction name="actionAddRectangle" /> + <addaction name="actionAddCircle" /> + <addaction name="actionAddTriangle" /> + <addaction name="actionRemoveShape" /> + <addaction name="separator" /> + <addaction name="actionRed" /> + <addaction name="actionGreen" /> + <addaction name="actionBlue" /> + </widget> + <widget class="QDockWidget" name="dockWidget" > + <property name="windowTitle" > + <string>Undo Stack</string> + </property> + <attribute name="dockWidgetArea" > + <number>2</number> + </attribute> + <widget class="QWidget" name="dockWidgetContents" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>4</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>Undo limit</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="undoLimit" /> + </item> + </layout> + </item> + <item> + <widget class="QUndoView" name="undoView" > + <property name="alternatingRowColors" > + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + <action name="actionOpen" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/fileopen.png</iconset> + </property> + <property name="text" > + <string>&Open</string> + </property> + </action> + <action name="actionClose" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/fileclose.png</iconset> + </property> + <property name="text" > + <string>&Close</string> + </property> + </action> + <action name="actionNew" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/filenew.png</iconset> + </property> + <property name="text" > + <string>&New</string> + </property> + </action> + <action name="actionSave" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/filesave.png</iconset> + </property> + <property name="text" > + <string>&Save</string> + </property> + </action> + <action name="actionExit" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/exit.png</iconset> + </property> + <property name="text" > + <string>E&xit</string> + </property> + </action> + <action name="actionRed" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/red.png</iconset> + </property> + <property name="text" > + <string>Red</string> + </property> + </action> + <action name="actionGreen" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/green.png</iconset> + </property> + <property name="text" > + <string>Green</string> + </property> + </action> + <action name="actionBlue" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/blue.png</iconset> + </property> + <property name="text" > + <string>Blue</string> + </property> + </action> + <action name="actionAddRectangle" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/rectangle.png</iconset> + </property> + <property name="text" > + <string>Add Rectangle</string> + </property> + </action> + <action name="actionAddCircle" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/circle.png</iconset> + </property> + <property name="text" > + <string>Add Circle</string> + </property> + </action> + <action name="actionRemoveShape" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/remove.png</iconset> + </property> + <property name="text" > + <string>Remove Shape</string> + </property> + </action> + <action name="actionAddRobot" > + <property name="text" > + <string>Add robot</string> + </property> + </action> + <action name="actionAddSnowman" > + <property name="text" > + <string>Add snowan</string> + </property> + </action> + <action name="actionAddTriangle" > + <property name="icon" > + <iconset resource="undo.qrc" >:/icons/triangle.png</iconset> + </property> + <property name="text" > + <string>addTriangle</string> + </property> + </action> + <action name="actionAbout" > + <property name="text" > + <string>About</string> + </property> + </action> + <action name="actionAboutQt" > + <property name="text" > + <string>About Qt</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QUndoView</class> + <extends>QListView</extends> + <header>qundoview.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="undo.qrc" /> + </resources> + <connections/> +</ui> diff --git a/demos/undo/undo.pro b/demos/undo/undo.pro new file mode 100644 index 0000000..e26d07c --- /dev/null +++ b/demos/undo/undo.pro @@ -0,0 +1,17 @@ +SOURCES += main.cpp mainwindow.cpp commands.cpp document.cpp +HEADERS += mainwindow.h commands.h document.h +FORMS += mainwindow.ui + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +RESOURCES += undo.qrc + +# install +target.path = $$[QT_INSTALL_DEMOS]/undo +sources.files = $$SOURCES $$HEADERS *.pro icons $$RESOURCES $$FORMS +sources.path = $$[QT_INSTALL_DEMOS]/undo +INSTALLS += target sources + diff --git a/demos/undo/undo.qrc b/demos/undo/undo.qrc new file mode 100644 index 0000000..65619b8 --- /dev/null +++ b/demos/undo/undo.qrc @@ -0,0 +1,20 @@ +<RCC> + <qresource prefix="/" > + <file>icons/background.png</file> + <file>icons/blue.png</file> + <file>icons/circle.png</file> + <file>icons/exit.png</file> + <file>icons/fileclose.png</file> + <file>icons/filenew.png</file> + <file>icons/fileopen.png</file> + <file>icons/filesave.png</file> + <file>icons/green.png</file> + <file>icons/ok.png</file> + <file>icons/rectangle.png</file> + <file>icons/red.png</file> + <file>icons/redo.png</file> + <file>icons/remove.png</file> + <file>icons/triangle.png</file> + <file>icons/undo.png</file> + </qresource> +</RCC> |