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, QAbstractItemModel and internal move
Forum Update on Monday, May 27th 2025

QTreeView, QAbstractItemModel and internal move

Scheduled Pinned Locked Moved Solved General and Desktop
qtreeviewdrag and dropitemmodel
5 Posts 3 Posters 4.7k 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.
  • A Offline
    A Offline
    Athius
    wrote on 9 May 2018, 13:01 last edited by Athius 5 Sept 2018, 13:10
    #1

    Hi everyone,

    I try to implement an internal move of items within a QTreeView with the mouse.

    My model inherits from QAbstractItemModel with 2 columns. Each items of my model have a boolean, a name, the pointer to the parent and list of children. In the future, I intend to add other data inside my items.

    In my model, I set the flags for each valid QModelIndex to :Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    I implemented moveRows and moveColumns methods inside my custom Model.

    Unfortunately those methods are never called by the view.

    For information, I enable the drag and drop on the QTreeView with setDragEnable(true) and setDragDropMode(Qt::InternalMove).

    Do I need to implement all the mimeData functions just to move some data?

    I can understand the reason of mimeData for drag and drop between widgets but in my case I just want to change the parent. I don't find any documentation/example that explains type of drag and drop move.

    Thanks

    Edit: I forgot to mention my environment: Windows 10/Mac OS X High Sierra, Qt 5.10.1, Visual studio 17, Clang

    R 1 Reply Last reply 9 May 2018, 14:04
    1
    • M Offline
      M Offline
      mpergand
      wrote on 9 May 2018, 13:59 last edited by
      #2

      Hi,

      I think you need to implement dropMineData in the model too.
      And call moveRow in it.

      1 Reply Last reply
      1
      • A Athius
        9 May 2018, 13:01

        Hi everyone,

        I try to implement an internal move of items within a QTreeView with the mouse.

        My model inherits from QAbstractItemModel with 2 columns. Each items of my model have a boolean, a name, the pointer to the parent and list of children. In the future, I intend to add other data inside my items.

        In my model, I set the flags for each valid QModelIndex to :Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;

        I implemented moveRows and moveColumns methods inside my custom Model.

        Unfortunately those methods are never called by the view.

        For information, I enable the drag and drop on the QTreeView with setDragEnable(true) and setDragDropMode(Qt::InternalMove).

        Do I need to implement all the mimeData functions just to move some data?

        I can understand the reason of mimeData for drag and drop between widgets but in my case I just want to change the parent. I don't find any documentation/example that explains type of drag and drop move.

        Thanks

        Edit: I forgot to mention my environment: Windows 10/Mac OS X High Sierra, Qt 5.10.1, Visual studio 17, Clang

        R Offline
        R Offline
        raven-worx
        Moderators
        wrote on 9 May 2018, 14:04 last edited by
        #3

        @Athius
        moveRows() and moveColumns() are not called by QAbstractItemModel. Honestly i do not know what they are used for.

        Nevertheless the item view calls dropMimeData() on the model. The default implementation then calls decodeData().
        Check the implementation of decodeData() to see what functions are called. Those are the ones you need to reimplement (like insertRows(), ...). Then setData() is called on them. So by default the moving is "faked".

        --- 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
        1
        • A Offline
          A Offline
          Athius
          wrote on 10 May 2018, 10:56 last edited by
          #4

          Thanks for your answers.

          @mpergand I try to call moveRow in it but there is no change. Worse: my data are not shown anymore ^^

          @raven-worx I also try to use the default implementation of dropMimeData but when the moved item has some children, then only the item is shown without his children (the data are not corrupted, only the view).

          I already re-implement insertRows but it didn't work.

          I finally succeed by using QStandardItemModel and a custom Item that inherits from QStandardItem. There is some methods to re-implement: QStandardItem *clone() const; void read(QDataStream &in); void write(QDataStream &out) const;

          I found on the Internet a pretty convenient way to put some custom data as pointer inside a QDataStream:

          QDataStream & operator << (QDataStream & s, const Data *& data)
          {
          	qulonglong ptrval(*reinterpret_cast<qulonglong *>(&data));
          	return s << ptrval;
          }
          QDataStream & operator >> (QDataStream & s, Data & data)
          {
          	qulonglong ptrval;
          	s >> ptrval;
          	data = **reinterpret_cast<Data **>(&ptrval);
          	return s;
          }
          

          I don't know if it's the best way but it's working.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mpergand
            wrote on 10 May 2018, 11:15 last edited by mpergand 5 Oct 2018, 11:19
            #5

            @Athius
            Sure it works, here my code for a bookmark tree:

            bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
            { Q_UNUSED(column)
            	if(action EQ Qt::IgnoreAction) return false;
            
                     if(action EQ Qt::MoveAction)
                                {
                                QByteArray bytes=data->data(MIME_Bookmark);
                                QDataStream stream(&bytes,QIODevice::QIODevice::ReadOnly);
                                qintptr i; int r,c; 
                                stream>>i>>r>>c;
                                QModelIndex index=createIndex(r,c,i);
            
                                moveRow(index,index.row(),parent,row);
                                }
            	return true;
            	}
            

            Of course you need to create and return your custom data in mimeData () as well.

            1 Reply Last reply
            0

            1/5

            9 May 2018, 13:01

            • Login

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