Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Undo and Redo button

Undo and Redo button

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 3.7k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • AlvaroSA Offline
    AlvaroSA Offline
    AlvaroS
    wrote on last edited by
    #1

    Hello to all.
    First of all thank for helping me and reading this post.

    I would like to do a undo and redo button in a Scene and QGraphicsView.

    I did this:

    void MainWindow::on_MoveLines_clicked()
    {
        sceneOld=scene;
    
        for (int i=0; i<num_item_selected; i++) //We get the values of X1,x2,y1,y2 of each line.
        {
    ..................
    ..................
            scene->removeItem(my_item); //Remove the item to add the new item moved.
            linea_moved = scene->addLine(.....)
            linea_moved ->setFlag(QGraphicsItem::ItemIsSelectable, true); // Every items can be selected
              }
    }
    
    
    void MainWindow::on_Undo_Button_clicked()
    {
        scene=sceneOld;
        ui->graphicsView->setScene(sceneOld);
    }
    

    So when I click on MoveLines button I move lines selected.
    Then when I click on Undo_Button I would like to undo the line selected and come back to the last scene.

    I save the scene in sceneOld before to move lines. Then when I click on Undo_button I set the sceneOld in graphicsView.
    It compiles fine but it does not work.
    When I click the undo_button it happens nothing... the scene is the same...

    How can I do that or what I am doing wrong¿

    thanks a lot.

    1 Reply Last reply
    0
    • jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Since scene is a pointer this:

      sceneOld=scene;
      

      just stores pointer to the same scene in sceneOld.
      If you want to do it this way you need to make a copy of the scene and handle memory management to avoid memory leaks.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      AlvaroSA 1 Reply Last reply
      0
      • jsulmJ jsulm

        Since scene is a pointer this:

        sceneOld=scene;
        

        just stores pointer to the same scene in sceneOld.
        If you want to do it this way you need to make a copy of the scene and handle memory management to avoid memory leaks.

        AlvaroSA Offline
        AlvaroSA Offline
        AlvaroS
        wrote on last edited by
        #3

        @jsulm Yes. Tha is what happen.
        How can I do a copy of the scene?

        1 Reply Last reply
        0
        • jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          I think you should not do it this way. Else memory consumption will grow and you have to ensure the correct scene is used. And I don't know whether you can have more than one scene.
          You should record changes you did to the scene and undo them (move the lines back to their old positions).
          Especially if you're going to have more than one undo steps.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          AlvaroSA 1 Reply Last reply
          0
          • jsulmJ jsulm

            I think you should not do it this way. Else memory consumption will grow and you have to ensure the correct scene is used. And I don't know whether you can have more than one scene.
            You should record changes you did to the scene and undo them (move the lines back to their old positions).
            Especially if you're going to have more than one undo steps.

            AlvaroSA Offline
            AlvaroSA Offline
            AlvaroS
            wrote on last edited by
            #5

            @jsulm Yes but How can I undo the accions? I have just one scene.
            I have had a look to http://doc.qt.io/qt-4.8/qundocommand.html#undo
            should I use that?

            thanks a lot.

            1 Reply Last reply
            0
            • jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

              You can undo the actions in the same way you change the scene in on_MoveLines_clicked().
              You need to know how you changed it before to undo the change.
              I think you can use QUndoCommand.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by mrjj
                #7

                HI
                as @jsulm mentions you should have a look at
                http://doc.qt.io/qt-5/qundo.html

                Keeping a copy of scene for each change will fast be
                non optimal.

                Also user expect undo to undo more than a line move.
                Like on delete and other changes so handling all operations
                that should be undoable will be complex.
                The Undo Framework helps manage this but
                it does takes some reading and setting up.

                AlvaroSA 1 Reply Last reply
                1
                • mrjjM mrjj

                  HI
                  as @jsulm mentions you should have a look at
                  http://doc.qt.io/qt-5/qundo.html

                  Keeping a copy of scene for each change will fast be
                  non optimal.

                  Also user expect undo to undo more than a line move.
                  Like on delete and other changes so handling all operations
                  that should be undoable will be complex.
                  The Undo Framework helps manage this but
                  it does takes some reading and setting up.

                  AlvaroSA Offline
                  AlvaroSA Offline
                  AlvaroS
                  wrote on last edited by
                  #8

                  @mrjj I do not understand at all..

                  I imagine that I have to save the position of Stack before moving a line and when I click on undoButton the application has to come back to the oldPosition.
                  I have had a look at this example but I can not understand at all... http://doc.qt.io/qt-5/qtwidgets-tools-undoframework-example.html

                  mrjjM 1 Reply Last reply
                  0
                  • AlvaroSA AlvaroS

                    @mrjj I do not understand at all..

                    I imagine that I have to save the position of Stack before moving a line and when I click on undoButton the application has to come back to the oldPosition.
                    I have had a look at this example but I can not understand at all... http://doc.qt.io/qt-5/qtwidgets-tools-undoframework-example.html

                    mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @AlvaroS
                    hi
                    Good example.
                    Yes, you will implement all operations as QUndoCommand childs
                    and undoStack->push them when applied.

                    void MainWindow::addTriangle()
                    {
                        QUndoCommand *addCommand = new AddCommand(DiagramItem::Triangle,
                                                                  diagramScene);
                        undoStack->push(addCommand);
                    }
                    
                    1 Reply Last reply
                    0
                    • jsulmJ Offline
                      jsulmJ Offline
                      jsulm
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      "when I click on undoButton the application has to come back to the oldPosition" - you are responsible for that. The undo/redo framework only provides some help to simplify it, but it cannot know what undo/redo in each and every application means.
                      So, before changing something you store the information about what you change on the stack. If undo button is clicked you get this information from the stack and change the scene, so it is like it was before that change.
                      From the example:

                      MoveCommand::MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos,
                                       QUndoCommand *parent)
                          : QUndoCommand(parent)
                      {
                          myDiagramItem = diagramItem;
                          newPos = diagramItem->pos();
                          myOldPos = oldPos;
                      }
                      
                      We save both the old and new positions for undo and redo respectively.
                      
                      void MoveCommand::undo()
                      {
                          myDiagramItem->setPos(myOldPos);
                          myDiagramItem->scene()->update();
                          setText(QObject::tr("Move %1")
                              .arg(createCommandString(myDiagramItem, newPos)));
                      }
                      

                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      1
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Hi,

                        In the absolute, you should rather store both parameters and do the initial move in the redo function reimplementation. That way you can go back and forth in the undo stack.

                        i.e.:

                        MoveCommand::MoveCommand(DiagramItem *diagramItem, const QPointF &newPosition,
                                         QUndoCommand *parent)
                            : QUndoCommand(parent)
                           ,  newPosition(newPosition)
                           , oldPosition(diagramItem->pos())
                           , diagramItem(diagramItem)
                        {
                        }
                        
                        void MoveCommand::redo()
                        {
                            diagramItem->setPos(newPosition);
                            diagramItem->scene()->update();
                        }
                        
                        
                        void MoveCommand::undo()
                        {
                            diagramItem->setPos(oldPosition);
                            diagramItem->scene()->update();
                        }
                        

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        AlvaroSA 1 Reply Last reply
                        1
                        • SGaistS SGaist

                          Hi,

                          In the absolute, you should rather store both parameters and do the initial move in the redo function reimplementation. That way you can go back and forth in the undo stack.

                          i.e.:

                          MoveCommand::MoveCommand(DiagramItem *diagramItem, const QPointF &newPosition,
                                           QUndoCommand *parent)
                              : QUndoCommand(parent)
                             ,  newPosition(newPosition)
                             , oldPosition(diagramItem->pos())
                             , diagramItem(diagramItem)
                          {
                          }
                          
                          void MoveCommand::redo()
                          {
                              diagramItem->setPos(newPosition);
                              diagramItem->scene()->update();
                          }
                          
                          
                          void MoveCommand::undo()
                          {
                              diagramItem->setPos(oldPosition);
                              diagramItem->scene()->update();
                          }
                          
                          AlvaroSA Offline
                          AlvaroSA Offline
                          AlvaroS
                          wrote on last edited by
                          #12

                          @SGaist @jsulm @mrjj Thanks a lot for answering. I am going to take the tips that you gave me in this post. When I achieve it I will post here!!! Thanks!!

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved