Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-89718

QUndoStack does not compress commands

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P1: Critical
    • None
    • 5.12.10
    • None
    • Linux/X11

    Description

      Command compression does not work at all:

      1) With parent command still need to call QUndoStack::undo() twice.

      2) with beginMacro()/endMacro() does not work at all - undoes nothing and breaks undo sequence integrity so underlying object list crashes application with QList<T>::operator[]: "index out of range" error which does not happen if we do not compress commands.

      So beginMacro()/endMacro() is not an equivalent to parent command like documentation mentions here: https://doc.qt.io/qt-5/qundostack.html#beginMacro.

      I wonder if you tested this feature at all?

      Sample code:

      class RemoveItemCommand : public QUndoCommand
      {
      public:
          RemoveItemCommand(ItemListController *controller, Item *item,
                           QUndoCommand *parent = nullptr);
      
          void undo() override;
          void redo() override;
          int id() const { return 1; }
          bool mergeWith(const QUndoCommand *command) { return true; }
      
      private:
          ItemListController *_controller;
          Item *_item;
      };
      
      class MoveItemCommand : public QUndoCommand
      {
      public:
          MoveItemCommand(ItemListController *controller, int from, int to,
                         QUndoCommand *parent = nullptr);
      
          void undo() override;
          void redo() override;
          int id() const { return 1; }
          bool mergeWith(const QUndoCommand *command) { return true; }
      
      private:
          ItemListController *_controller;
          int _from, _to;
      };
      
      

      Undo stack variants (both do not work as expected):

      Variant 1:

      // Several commands can be compressed into a single command that can be undone and
      // redone in a single operation. This allows Item to move back to its original
      // position with undo.
      QUndoCommand *removeCommand = new QUndoCommand(); // Compressed command
      new MoveItemCommand(this, from, visualItems()->count() - 1, removeCommand);
      new RemoveItemCommand(this, removedItem, removeCommand);
      _undoStack.push(removeCommand);
      

      Variant 2:

      // A command macro is a sequence of commands, all of which are undone and redone
      // in one go. This allows Item to move back to its original position with undo.
      _undoStack.beginMacro("Remove Item");
      _undoStack.push(new MoveItemCommand(this, from, visualItems()->count() - 1));
      _undoStack.push(new RemoveItemCommand(this, removedItem));
      _undoStack.endMacro();
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            jirauser39314 user-45b5b (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes