I have QGraphicsView which contains some QGraphicsItem. This view has some feature like zoom-in, zoom-out, fitIn, Undo-Redo.
My fitIn feature is not working in Undo-Redo functionality.
( To implement Undo-Redo I have used Command-Pattern in Qt. )
myCommand.h
class myCommand: public QUndoCommand
{
public:
myCommand();
myCommand(QTransform t, int hr, int vr, QGraphicsView* v);
void undo();
void redo();
QTransform t;
int hScrollBar;
int vScrollBar;
QGraphicsView* mView;
};
myCommand.cpp
myCommand::myCommand(QTransform t, int hr, int vr, QGraphicsView *v)
{
this->t = t;
this->hScrollBar= hr;
this->vScrollBar= vr;
this->mView = v;
}
void myCommand::undo()
{
mView->setTransform(t);
mView->horizontalScrollBar()->setValue(hScrollBar);
mView->verticalScrollBar()->setValue(vScrollBar);
}
void myCommand::redo()
{
myView mv;
mv.FitInView();
}
myView.cpp
void myView::FitIn()
{
FitInView();
QTransform t = view->transform();
int hrValue = view->horizontalScrollBar()->value();
int vrValue = view->verticalScrollBar()->value();
myCommand* Command1 = new myCommand(t,hrValue,vrValue,view);
undoStack->push(Command1);
}
void myView::DrawDesign()
{
// Logic for inserting all the Rectangles and polylines.
QTimer::singleShot(100, this, [&]() {
FitInView();
});
}
void myView::FitInView()
{
QRectF bounds = scene->sceneRect();
QRectF rect {0,0,200,200};
if (bounds.width() < 200)
{
rect .setWidth(bounds.width());
bounds.setWidth(200);
}
if (bounds.height() < 200)
{
rect.setWidth(bounds.height());
bounds.setHeight(200);
}
view->fitInView(bounds, Qt::KeepAspectRatio);
view->updateGeometry();
}
myView.h
public:
QUndoStack* undoStack;
FitInView fits my design perfectly but it does not work in Undo-Redo feature.
I think I am making a mistake in myCommand::undo() and myCommand::redo() function.
Based on the many question you posted on the Qt's Undo Framework, it seems to me you are missing an essential part of the Command pattern:
So all changes, should be implemented inside the
QUndoCommand(follow the link to discover a basic usage example), i.e. insideQUndoCommand::redo. Once the command is pushed on theQUndoStack, usingQUndoStack::push, the change (i.e.QCommand::redo) is automatically performed:Steps to create a new
QUndoCommandQUndoCommand::redo(and not somewhere else).QUndoCommand::undo. If needed, capture the initial state inside theQUndoCommandconstructor, to easily revertQUndoCommand::redo.Applied to your example
So, the only action that
myView::FitInshould perform, is pushing the command on the undo stack:Implement your changes inside the redo command:
As the inverse operation of fitting is not uniquely defined, we store the initial state inside the
QUndoCommandconstructor (to be able to restore the initial state insideQUndoCommand::undo):Now we can implement the
undocommand to revert theredocommand:Usefull reading material:
QUndoCommand, including basic code example