I have a QGraphicsView, which contains rectangle, polyline, text etc. I also have some features to transform the view like zoom in, zoom out, Fit in view, change the color on mouse right click etc. I want to add few more features like Undo and Redo.
Undo means, user should cancel the effect of last command executed and show previous transformation. So If user did transformation like zoom in -> zoom in -> fit in -> zoom in and now pressed Undo then view's fit in position should get displayed.
I have tried Command pattern
to implement Undo-Redo feature. But I did it to add/remove rectangle,polyline in design. And it worked.
HCommand.h
#include <QUndoCommand>
#include<QGraphicsItem>
#include<QGraphicsScene>
class myCommand : public QUndoCommand
{
public:
HCommand(QGraphicsItem* mItem, QGraphicsScene* scene);
HCommand(QGraphicsScene* scene, QGraphicsView* mView);// for fitIn
private:
QGraphicsItem* mItem;
QGraphicsScene* mScene;
QGraphicsView* mView;
void undo();
void redo();
};
HCommand.cpp
#include "hcommand.h"
HCommand::HCommand(QGraphicsItem* item, QGraphicsScene* scene):
mItem(item), mScene(scene)
{}
void HCommand::undo()
{
if(mItem)
mScene->removeItem(mItem);
}
void HCommand::redo()
{
if(mItem)
mScene->addItem(mItem);
}
Widget.h
class Widget : public QGraphicsView
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
Rectangle r;
PolyLine p;
QUndoStack* undoStack;
void undo();
void redo();
private:
Ui::Widget *ui;
QGraphicsScene* scene;
QGraphicsView* view;
}
Widget.cpp
Widget::Widget(QWidget *parent)
: QGraphicsView(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
view = new QGraphicsView(this);
view->setScene(scene);
undoStack = new QUndoStack(this);
ui->verticalLayout_2->addWidget(view);
}
void Widget::undo()
{
undoStack->undo();
}
void Widget::redo()
{
undoStack->redo();
}
void Widget::on_schematicBtn_clicked()
{
QGraphicsRectItem* in = r.createRect(20,160,20,20);
scene->addItem(in);
HCommand* com = new HCommand(in,scene);
undoStack->push(com);
// many rectangles and polyline code, same as above
}
But now I want to do Undo-Redo for Zoom In , Zoom Out, Fit In. But whenever I zoom in/out, I zoomed in/out full view
void Widget::on_zoomIn_clicked()
{
double sFactor = 1.2;
view->scale(sFactor,sFactor);
}
void Widget::on_zoomOut_clicked()
{
double sFactor = 1.2;
view->scale(1/sFactor,1/sFactor);
}
void Widget::on_fitInBtn_clicked()
{
view->resetTransform();
}
So the question is :
In above code I am pushing particular rectangle in stack so for zoom in/out how to push full view in stack ? So that, later I can pull it out from stack ? Or this can be implemented differently ?
Any help is appreciated.