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. QTreeView selecting items programatically issue
QtWS25 Last Chance

QTreeView selecting items programatically issue

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 2.0k Views
  • 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.
  • D Offline
    D Offline
    Dariusz
    wrote on last edited by Dariusz
    #1

    Hey

    I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.

    in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.

    The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.

    Here is how I gather the items:

    void myView::mouseReleaseEvent(QMouseEvent *event) {
        dragActive = false;
        QTreeView::mouseReleaseEvent(event);
        //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad.
        _newSelectionX = selectedIndexes();
    
        //if (_newSelectionX != _oldSelectionX) {
        std::vector<myNode *> _newSelectedNodes;
        for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes.
            myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer());
            _newSelectedNodes.emplace_back(node);
        }
        std::vector<myNode *> _oldSelectedNodes;
        for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) {
            myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer());
            _oldSelectedNodes.emplace_back(node);
        }
        selectionCommand::selectionData data;
        data._newSel = _newSelectedNodes;
        data._oldSel = _oldSelectedNodes;
        data._tree = this;
        emit selectionHasChanged(data);
    

    Here is how I undo/redo :

    void myView::changeMySelection(selectionCommand::selectionData data, bool undo) {
        clearSelection();
        int columnC = 1;//model()->columnCount() - 2;
        if (undo) {
            for (int x = 0; x < data._oldSel.size(); ++x) {
                QModelIndex itemIndex = data._oldSel[x]->index();
                QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC);
                qDebug() << itemIndex << siblingIndex;
                selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
                //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select);
            }
        } else {
            for (int x = 0; x < data._newSel.size(); ++x) {
                QModelIndex itemIndex = data._newSel[x]->index();
                QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC);
                qDebug() << itemIndex << siblingIndex;
                selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
    
            }
        }
    }
    

    Here is the log

    QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
    QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
    QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
    

    Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !

    I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/

    raven-worxR VRoninV 2 Replies Last reply
    0
    • D Dariusz

      Hey

      I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.

      in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.

      The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.

      Here is how I gather the items:

      void myView::mouseReleaseEvent(QMouseEvent *event) {
          dragActive = false;
          QTreeView::mouseReleaseEvent(event);
          //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad.
          _newSelectionX = selectedIndexes();
      
          //if (_newSelectionX != _oldSelectionX) {
          std::vector<myNode *> _newSelectedNodes;
          for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes.
              myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer());
              _newSelectedNodes.emplace_back(node);
          }
          std::vector<myNode *> _oldSelectedNodes;
          for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) {
              myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer());
              _oldSelectedNodes.emplace_back(node);
          }
          selectionCommand::selectionData data;
          data._newSel = _newSelectedNodes;
          data._oldSel = _oldSelectedNodes;
          data._tree = this;
          emit selectionHasChanged(data);
      

      Here is how I undo/redo :

      void myView::changeMySelection(selectionCommand::selectionData data, bool undo) {
          clearSelection();
          int columnC = 1;//model()->columnCount() - 2;
          if (undo) {
              for (int x = 0; x < data._oldSel.size(); ++x) {
                  QModelIndex itemIndex = data._oldSel[x]->index();
                  QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC);
                  qDebug() << itemIndex << siblingIndex;
                  selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
                  //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select);
              }
          } else {
              for (int x = 0; x < data._newSel.size(); ++x) {
                  QModelIndex itemIndex = data._newSel[x]->index();
                  QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC);
                  qDebug() << itemIndex << siblingIndex;
                  selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
      
              }
          }
      }
      

      Here is the log

      QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
      QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
      QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
      

      Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !

      I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @Dariusz
      between the undo / redo command calls, does your model get updated (rows/columns added/removed)?

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Dariusz
        wrote on last edited by
        #3

        Hey

        Nope, I'm only clicking on new rows. I have added my mouseReleaseEvent code in 1st post to show how I'm gathering the items.

        1 Reply Last reply
        0
        • D Dariusz

          Hey

          I'm trying to create undo/redo command system but oh boy getting the selection to work is a headache.

          in my undo I store a list of column 0 elements of all selected items as nodes - no modelIndexes as they get messed up once I do drag/drop.

          The idea was store as items > retrieve their indexes during undo/redo & select them again. But for some reason I cant get it to work.

          Here is how I gather the items:

          void myView::mouseReleaseEvent(QMouseEvent *event) {
              dragActive = false;
              QTreeView::mouseReleaseEvent(event);
              //_newSelection = selectionModel()->selection(); //// Cant use QModelIndex, affter drag/drop/etc they all go bad.
              _newSelectionX = selectedIndexes();
          
              //if (_newSelectionX != _oldSelectionX) {
              std::vector<myNode *> _newSelectedNodes;
              for (int x = 0; x < _newSelectionX.size(); x += model()->columnCount()) { //// get only 1st item from 0 column, well use sibling later to create full selection from indexes.
                  myNode *node = static_cast<myNode*>(_newSelectionX[x].internalPointer());
                  _newSelectedNodes.emplace_back(node);
              }
              std::vector<myNode *> _oldSelectedNodes;
              for (int x = 0; x < _oldSelectionX.size(); x += model()->columnCount()) {
                  myNode *node = static_cast<myNode*>(_oldSelectionX[x].internalPointer());
                  _oldSelectedNodes.emplace_back(node);
              }
              selectionCommand::selectionData data;
              data._newSel = _newSelectedNodes;
              data._oldSel = _oldSelectedNodes;
              data._tree = this;
              emit selectionHasChanged(data);
          

          Here is how I undo/redo :

          void myView::changeMySelection(selectionCommand::selectionData data, bool undo) {
              clearSelection();
              int columnC = 1;//model()->columnCount() - 2;
              if (undo) {
                  for (int x = 0; x < data._oldSel.size(); ++x) {
                      QModelIndex itemIndex = data._oldSel[x]->index();
                      QModelIndex siblingIndex = itemIndex.sibling(data._oldSel[x]->row(), columnC);
                      qDebug() << itemIndex << siblingIndex;
                      selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
                      //selectionModel()->select(QItemSelection(itemIndex, siblingIndex), QItemSelectionModel::Select);
                  }
              } else {
                  for (int x = 0; x < data._newSel.size(); ++x) {
                      QModelIndex itemIndex = data._newSel[x]->index();
                      QModelIndex siblingIndex = itemIndex.sibling(data._newSel[x]->row(), columnC);
                      qDebug() << itemIndex << siblingIndex;
                      selectionModel()->select(QItemSelection(itemIndex, itemIndex), QItemSelectionModel::Select);
          
                  }
              }
          }
          

          Here is the log

          QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
          QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(0,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(0,1,0x15ac176b620,myModel(0x15ac06366f0))
          QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(13,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(15,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(16,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(2,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          QModelIndex(1,0,0x15ac176b620,myModel(0x15ac06366f0)) QModelIndex(-1,-1,0x0,QObject(0x0))
          

          Only some of the selections actually undo/redo. I can not understand at all why on earth I'm getting wrong QModelIndexes. The left model index is valid, so right one next column should be valid as well. duhh !

          I even tried on selecting just 1 item (current example) and that only works in some cases. What am I doing wrong here ? :/

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          @Dariusz said in QTreeView selecting items programatically issue:

          no modelIndexes as they get messed up once I do drag/drop

          QPersistentModelIndex should not get messed up unless the drag-drop implementation has a bug

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          0
          • D Offline
            D Offline
            Dariusz
            wrote on last edited by Dariusz
            #5

            Hey

            Yeah not sure to be honest. I dont use persistend model indexes, they are quite heavy from what I read and sicne I will have thousands of items. I though its more efficient to store pointer to items and then get their indexes from model. I tried storing before the QSelectionModel()->selection() and restoring that, it worked on QTreeWidget system, but on my QAbstractItemModel&treeView seems to be broken. I attached video with me dragging lots of stuff(https://goo.gl/zCiMhv), It seems to be working fine. I fire the before/after remove/add commands and so on. Its puzzling :- ( Over there I store pointers to items in an array>store that in my custom mimeData. The mimeData is used to carry the dragging of data as it should, and at the end of dropMimeData (before row removal/insertion) I store source item row/parent data/ to restore it later/ snipped below.

                    //// Drop mime data function
                    .... 
                    for (int i = count - 1; i >= 0; --i) {
                        if (nodes[i]->row() < row && parentNode == nodes[i]->parentNode())
                            --row;
                        // Remove from old position
            
                        moveCommand::moveData mData;
                        mData._node = nodes[i];
                        mData._source = sourceModel;
                        mData._destination = this;
                        mData._sourceRow = nodes[i]->row();
                        mData._destinationRow = row;
                        //mData._oldParentIndex = createIndex(nodes[i]->row(), 0, nodes[i]); /// obsolete - removed now after clean up - never used it
                        //mData._newParentIndex = parent; /// obsolete - removed now after clean up - never used it
                        mData._oldParent = nodes[i]->parentNode();
                        mData._newParent = parentNode;
                        moveData.push_back(mData);
            
                        sourceModel->removeNode(nodes[i]);
                        // Insert at new position
            
                        beginInsertRows(parent, row, row);
                        parentNode->insertChild(row, nodes[i]);
                        endInsertRows();
                        ++row;
                    }
                    emit treeModelItemMoved(moveData);
            

            Updated snipped a little.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              Dariusz
              wrote on last edited by Dariusz
              #6

              SOLVED!

              In QAbstractItemModel ::indexFromitem() I had wrong argument passed in createIndex(), I was passing item.parent() instead of item as third arg.. argh!!! Thanks for juggling my brain :- )

              The only thing I have to solve now is to re-select items properly after drop action. I wonder whats wrong humhhhh

              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