PDA

View Full Version : Drag and Dropping items in QTreeView



jshafferman
1st December 2010, 21:56
Hello everyone,

I am relatively new to Qt programming however I am pretty skilled in C++ programming and so I was hired on as a C++ GUI Programmer for a company. I have ran into a little bit of an issue that I can't seem to figure out. I have a built a QTreeView view that just shows the data in a selected hierarchical fashion. I am trying to enable the user to be able to drag and drop items from one place to another. I have a MainWindow class that inherits from QMainWindow and I am trying to get the MainWindow to catch the dropAction when moving items from one to place to another on the QTreeView (I will call view from now on). In doing so I have set the MainWindow in the constructor to accept drops and then disabled the view from excepting drops. As far as this is concerned it appears to be doing what I want. I then reimplemented the dragEnterEvent so that the MainWindow will know when something is being dragged and again that works as I would expect. Finally, I reimplemented the dropEvent and I am trying to get the correct index of the item that the drop event is trying to drop to so that I can call a function that I have already made that will correctly place the item where it needs to go. I am unable to get the correct index from the QTreeView and I am not sure how to proceed.

Visual example of what I am trying to do:

Before Move: After Move G to Directly underneath A:
- A - A
- B - G
- C - B
- D - C
- E - D
- F - E
- G - F
- H - H

If this isn't formatting the way I would like Ill explain the above:

A is the parent index of B,C, and D. D is the parent index of E and F. G and H only have the default parent index. I am trying to move G from default parent index to have A as its parent index when dropping. However I am unable to get the correct index of A, in this situation index (0,0) with parent item being default parent index (QModelIndex()), to be found by dropEvent.
I have a function that already does exactly what I want but it's dependent on the QModelIndex of the view.

My question is how do I get the dropEvent to give me the correct QModelIndex of the QTreeView to place G in the correct location?

Here is the relevant code:




MainWindow::MainWindow()
{
//...

setAcceptDrops(true);

//...
}

bool MainWindow::loadFile(const QString &fileName)
{
//...
view->reset();
view->setDragDropMode(QAbstractItemView::DragOnly);
view->setDropIndicatorShown(true);
view->setAcceptDrops(false);
view->setModel(urnTree);
view->setWindowTitle(tr("Urn Description"));

//...
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}

void MainWindow::dropEvent(QDropEvent *event)
{
cout << "Drop Event has occured!\n";
QPoint curPos = event->
QModelIndex curIndex = view->indexAt(curPos);
curIndex = view->model()->index(curIndex.row(), curIndex.column(), curIndex.parent());
TreeItem *curItem = urnTree->getItem(curIndex);
cout << "Current index is: " << curIndex.row() << "," << curIndex.column() << endl;
cout << "Current item on drop is: " << curItem->data(0).toString().toStdString() << endl;
}



As you can see I am lost in how to get the correct QModelIndex from dropEvent and I am running out of ideas and appreciate any help. Please feel free to ask for more code if necessary.

Thanks!!

wysota
1st December 2010, 22:11
If the event propagates from the view to the parent widget, it's coordinates are mapped to the coordinates of the parent widget whereas if you call any of the view's methods (like indexAt) it expects the coordinates to be in either the view's or the view's viewport (depending on the method) coordinate space. So you first have to map those coordinates using the family of mapTo*/mapFrom* methods.

And with all do respect to your C++ skills think if exposing the internal representation of the tree and handling internal affairs of the tree in some external place (like the MainWindow class) is a good design decision of a skilled C++ developer.

jshafferman
1st December 2010, 23:05
And with all do respect to your C++ skills think if exposing the internal representation of the tree and handling internal affairs of the tree in some external place (like the MainWindow class) is a good design decision of a skilled C++ developer.


I am very new to Qt Programming and this is my first professional experience with Qt GUI programming (First programming job period to be exact). I work for a very small company so I pretty much have had to learn Qt on the fly and so that is why the code is pretty rough and my understanding of Qt GUI programming isn't the greatest. What would be a better design approach? Thanks for any help and keep the criticism as it is the only way I will get better.

wysota
1st December 2010, 23:08
This was a C++ related comment not a Qt related one. I would definitely try to handle the drag&drop mechanism in the view object. And would definitely get rid of the getItem() method in the tree.