-1

I have QGraphicsView, which has multiple QGraphicsItem's. On this view, I am applying some transformation using features like Zoom-in, zoom-out, fit -In etc.
So before applying fit-in feature on my current view, I want to store view's current transformation ( view's current situation ) in a variable. And then I want to apply Fit-in feature. ( so that, in Undo-Redo I can use that stored position)
But I do not know how to store current position of view in a variable. I tried this way :

void myClass::FitIn()
{
     QTransform t = _view->transform();
     QScrollBar* hrSBar = _view->horizontalScrollBar();
     QScrollBar* verSBar = _view->verticalScrollBar();

     myCommand* c = new myCommand(t,hrSBar,verSBar);
     undoStack->push(c);
     _view->resetTransform();
}       
           

How to store, current view in another variable ?

***** EDIT ******

myCommand.cpp          
myCommand::myCommand(QTransform t, QScrollBar *hr, QScrollBar *vr)
{
    this->trans = t;
    this->horizontalSBar = hr;
    this->verticalSBar = vr;
}

void myCommand::undo()
{
    _mView->setTransform(trans);
    _mView->horizontalScrollBar()->setValue(horizontalSBar->maximum());
    _mView->verticalScrollBar()->setValue(verticalSBar->maximum());
}

void myCommand::redo()
{
    _mView->setTransform(trans);  // Segmentation Fault occurs
    _mView->horizontalScrollBar()->setValue(horizontalSBar->maximum());
    _mView->verticalScrollBar()->setValue(verticalSBar->maximum());
}

myCommand.h

class myCommand: public QUndoCommand
{
public:
    myCommand(QTransform t, QScrollBar* hr, QScrollBar* vr);
private:
    QGraphicsScene* _mScene;
    QGraphicsView* _mView;
}
tushar
  • 313
  • 4
  • 10

1 Answers1

1

As revealed by source code of mapToScene, three parameters define the part of the scene that is visible on the viewport:

To implement an undo-redo framework, those three parameters should be stored before every operation an restored upon undo.

m7913d
  • 10,244
  • 7
  • 28
  • 56
  • I tried this code but got run time error (Verbose stack trace ) `QTransform t = view->transform();` `QScrollBar* hrSBar = view->horizontalScrollBar();` `QScrollBar* verSBar = view->verticalScrollBar();` `myCommand* c = new myCommand(t,hrSBar,verSBar);` `undoStack->push(c);` `_view->resetTransform();` – tushar Mar 27 '22 at 15:02
  • And what is the error message? – m7913d Mar 27 '22 at 15:07
  • `(_ZN21ennoComDumpStackTrace7HandlerEi+0xa8) [0xd120be] /lib64/libc.so.6(+0x36400) [0x7fe6e3e9e400]` `QT/5.12.12/gcc_64/lib/libQt5Core.so.5(_ZN11QMetaObject8activateEP7QObjectiiPPv+0x689) [0x7fe6e4dc8e19]` Like this there are many lines – tushar Mar 27 '22 at 15:14
  • and then `Stack Trace:` `0xd120be` `0x7fe6e3e9e400` `0x7fe6e5f88629` `0x14fce22` many lines – tushar Mar 27 '22 at 15:15
  • Have you tried to use a debugger to analyse this error? The stack trace seems unrelated to the code you posted earlier. – m7913d Mar 27 '22 at 16:38
  • I have updated code, Please look into it. I have tried debugger. After `undoStack->push(c);` control goes to `void myCommand::redo()`. And there `scaleFactor : 7.83091e-295` . At `_mView->scale(_scaleFactor,_scaleFactor);` this line gets segmentation fault. – tushar Mar 27 '22 at 18:14
  • Am I wrong in `undo()` and `redo()` code ? – tushar Mar 27 '22 at 18:17
  • 1
    `_scaleFactor` seems to be never initialised, is it? – m7913d Mar 27 '22 at 18:41
  • If I do 1st `zoomIn`, then output at console is `scaleFactor in redo 1.1` Then If I do `zoomOut` then output at console is `scaleFactor in redo 0.909091` And then if I do at 3rd time `Fit in` then output at console is `scaleFactor in redo 1.49162e-154` and error comes – tushar Mar 27 '22 at 18:45
  • I think `_scaleFactor` is getting initialized. – tushar Mar 27 '22 at 18:48
  • 1
    The constructor `myCommand::myCommand(QTransform t, QScrollBar *hr, QScrollBar *vr)` doesn't initialise `_scaleFactor` (and shouldn't, as you should use the stored transform and values of the scrollbar positions in this case). Note that it may be usefull to create separate classes depending on which action you want to undo, i.e. zoom vs fit-in. Also `_mView` isn't initialised in this case. – m7913d Mar 27 '22 at 18:49
  • If I understand you, should I create separate function for `fitIn` like `undo()` and `redo()` ? It means, for `fitIn`, that new function will get call and there we will not execute `_scaleFactor` ? – tushar Mar 27 '22 at 18:54
  • 1
    I would use a separate __class__, f.ex. `ZoomCommand`, `FitCommand`, ... In case of fit, you should use the transform matrix and not the _scaleFactor. – m7913d Mar 27 '22 at 18:58
  • I think I understood what you want to say. But 1 thing , not understanding, what could be the `undo()` and `redo()` in my separate class. Here I have used ( scale method) like ` _mView->scale(1/_scaleFactor,1/_scaleFactor);` But what should I write in new class's `undo()` and `redo()` ? – tushar Mar 27 '22 at 19:11
  • Sorry but I could not get a `QGraphicsView`'s method which will incorporate `QTransform`, `ScrollBar` and `ScrollBar` so that I can call that method from `undo()` and `redo()` Can you help me in that ? Or still I could not get you properly ? – tushar Mar 28 '22 at 03:28
  • 1
    `_view->setTransform(storedTransform); _view->horizontalScrollbar()->setValue(storedHorizontalValue); _view->verticalScrollbar()->setValue(storedVerticalValue);` – m7913d Mar 28 '22 at 07:33
  • I have updated my FitIn() code. I know, I am wrong in writting `undo()` and `redo()` code. And I am getting error in `redo()` ( 1st line). I am not understanding how to write in `undo()` and `redo()`. – tushar Mar 28 '22 at 09:43
  • I have stored `HorizontalScrollBar` value like `horizontalSBar->maximum()` is this right ? – tushar Mar 28 '22 at 09:47
  • 1
    1. `_mView` is not initialised in that case, you should probably pass the view in the constructor. 2. Why using the maximum? You should store the scrollbar position (i.e. horizontalSBar->value()) and use this value to undo/redo. 3. To implement undo/redo, the easiest approach may be to store the initial and final value (of the transform matrix and scrollbar positions). Another alternative is to store incremental values, i.e. the difference between the initial and final value. – m7913d Mar 28 '22 at 11:27
  • Now it is working perfectly. Thank you for your help ! One more question, how many `undo`-`redo` operation we can perform ? Can we use our own stack and give more `undo`-`redo` operation ? Thank you once again ! – tushar Mar 28 '22 at 19:51
  • By default, there is no limit, see: https://doc.qt.io/qt-5/qundostack.html#undoLimit-pro – m7913d Mar 28 '22 at 19:57
  • Sorry but still I have one question. for `zoom-in` and `zoom-out` if I use logic same as `fit-in` will this be ok ? means, If I use `Qtransform` and value of `horizontalScrollBar` and value of `verticalScroolBar` will it be ok ? – tushar Mar 30 '22 at 07:34
  • 1
    Zoom is a simple form of transformation, so yes, that should be possible too. – m7913d Mar 30 '22 at 15:47