PDA

View Full Version : Drag & drop with model/view (Qt4)



yogeshm02
20th March 2006, 15:21
Hi

I have two suggestions/ideas/requests (you choose the correct one!) regarding drag & drop with model/view classes, for the Qt developers: -

While moving an item in a view using drag & drop, insertRows() and removeRows() functions are used. Can't models have single function (may be moveRows()) to achieve this?
Can drag&drop action from one view to another, both having same models, be made to work like a move operation?


What do you think?
Do Qt developers have an eye on this forum or I'll have to submit a wish (Can I?)?

I am using model/view classes extensively in my application. Models in my app are not only used to store data but are also used for anything which needs to be done with it and at times two views display data from single model.

Also, those who are working with custom models may have noticed very buggy behaviour of drag & drop operations. Right? Or there is there something seriously wrong with my implementation? I tried hard but failed to generate a smaller variation of my model to show you code.

With regards

wysota
20th March 2006, 16:26
I have two suggestions/ideas/requests (you choose the correct one!) regarding drag & drop with model/view classes, for the Qt developers: -

- While moving an item in a view using drag & drop, insertRows() and removeRows() functions are used. Can't models have single function (may be moveRows()) to achieve this?

They probably could, but would it differ from using removeRows() and insertRows() in sequence? Now, because there are more than one drag operations (move, copy and link), it would make sense for all of them to have an own method -- moveRows(), copyRows(), linkRows() which would make the model framework more complicated.



- Can drag&drop action from one view to another, both having same models, be made to work like a move operation?


They could. But what about operations, which do not come from a view? It could make those operations more complex (one would have to implement many situations -- view A -- view A, view A - view B, non-view - view, view - non-view, non-view - non-view -- maybe even more).


Do Qt developers have an eye on this forum or I'll have to submit a wish (Can I?)?
They sometimes do, but you should submit a report anyway.


I am using model/view classes extensively in my application. Models in my app are not only used to store data but are also used for anything which needs to be done with it and at times two views display data from single model.
That's how they should be used, right? :)


Also, those who are working with custom models may have noticed very buggy behaviour of drag & drop operations. Right? Or there is there something seriously wrong with my implementation? I tried hard but failed to generate a smaller variation of my model to show you code.

Drag and drop is really associated with views, not models. This could be an argument against implementing move/copy/linkRows() into the model. It should be as simple as possible. The Interview framework is not perfect. If you try to explain us your problems, maybe we'll be able to help.

yogeshm02
21st March 2006, 16:41
They probably could, but would it differ from using removeRows() and insertRows() in sequence? Now, because there are more than one drag operations (move, copy and link), it would make sense for all of them to have an own method -- moveRows(), copyRows(), linkRows() which would make the model framework more complicated.

But that would give additional power to models, e.g. my implemented model uses custom function for inserting data and inserting data in model take some time. So, either I will do re-validation of data in each insertRow() or assume that everything is always correct. If my suggestion is implemented, model can decide whether rows can be inserted/moved/linked.



They could. But what about operations, which do not come from a view? It could make those operations more complex (one would have to implement many situations -- view A -- view A, view A - view B, non-view - view, view - non-view, non-view - non-view -- maybe even more).

Now it looks very hard! Though I can tweak my model to behave like this because items in my model are unique, so it will be easy for me to implement (with some assumptions).



Drag and drop is really associated with views, not models. This could be an argument against implementing move/copy/linkRows() into the model. It should be as simple as possible. The Interview framework is not perfect. If you try to explain us your problems, maybe we'll be able to help.
I was unable to downgrade my implementation so I started from scratch hoping standard classes will prove buggy, and I tasted success. Example is attached (20 lines only).

Just try to move any item to the point where all items end and see the results like in the screenshots.
This sometimes also happens when items are dropped between two items (occurs very rarely) and also sometimes two rows are inserted in that place. I am unable to get that done ATM.

wysota
21st March 2006, 18:02
But that would give additional power to models, e.g. my implemented model uses custom function for inserting data and inserting data in model take some time. So, either I will do re-validation of data in each insertRow() or assume that everything is always correct. If my suggestion is implemented, model can decide whether rows can be inserted/moved/linked.

This can be implemented on the view level. Check if target and source are the same and handle the input accordingly.

yogeshm02
26th March 2006, 15:35
I was unable to downgrade my implementation so I started from scratch hoping standard classes will prove buggy, and I tasted success. Example is attached (20 lines only).

Just try to move any item to the point where all items end and see the results like in the screenshots.
This sometimes also happens when items are dropped between two items (occurs very rarely) and also sometimes two rows are inserted in that place. I am unable to get that done ATM.

Is it really a bug? Please reply so that I it could be submitted to qt folks.

wysota
26th March 2006, 15:42
I don't know. You can report it to the Trolls and they will confirm or deny that.

Nickolay
19th September 2011, 11:59
I have another question about drag&drop inside MVC framework.
I need simply move rows inside QtableView,
I go along proposed in docs way - reimplement: mimeType, mimeData, dropMimeData.

But i need such behaviour: when I start dragging row, I need remove this row from table,
then after droping put them in new place, or return to original position if droping was out of widget bounds.
But in what function I can call models func - removeRows? I cann't do this in mimeData because it const.
Where correct place to initialy(on dragging start) remove row?

Thank you!

Nickolay
19th September 2011, 18:48
Is there no one has done such before?

wysota
19th September 2011, 18:52
What you require is somewhat against traditional approach to drag and drop. What happens if you start a drag (hence remove the item) and then cancel the drag without dropping the item on the widget or if you drop the item on some external application? The drop is traditionally handled by the target and not the source. Of course you can have the behaviour you want by reimplementing mouse events and starting the drag manually (and prior to doing that you need to remove the item from the model) but then you have to handle all possible drop situations manually (and you'll have no information about WHO accepted the drop).

Nickolay
19th September 2011, 18:57
Why not traditional? I use chrome browser, when I start drag tab in horizontal direction, it removes from its initial position and sticks to cursor, then I can move it where I want, of course inside tabbar, seems my approach the same.

Athrough if I move tab outside tab bar, somewhere inside browser window, its like you say, like tab losses it parent. And then if I simply drop tab anywhere, new window will creates for this tab.

So what I required, if I want during move row, detach it from its initial position?

wysota
19th September 2011, 19:06
Why not traditional?
Because typically the operation is performed during the drop and not during the drag.


I use chrome browser, when I start drag tab in horizontal direction, it removes from its initial position and sticks to cursor, then I can move it where I want, of course inside tabbar, seems my approach the same.
Your approach is different. For instance you may have multiple views on the same model, removing the item from all the views handling that model is counter-intuitive.


Athrough if I move tab outside tab bar, somewhere inside browser window, its like you say, like tab losses it parent. And then if I simply drop tab anywhere, new window will creates for this tab.
That's not the case with your situation, is it? Furthermore look that in Chrome the drop is actually performed during the drag, the tab is not removed when you start dragging it but only when you move it past the border of the next tab (or you drag it outside the tab bar).

As I said, you can do what you want, but since this is not a typical approach to drag and drop, there is no built-in support for it. You may implement your own view and handle it the way you want.

Nickolay
19th September 2011, 19:13
That's not the case with your situation, is it? Furthermore look that in Chrome the drop is actually performed during the drag, the tab is not removed when you start dragging it but only when you move it past the border of the next tab (or you drag it outside the tab bar).

What I need to reimplement in therms of MVC? I need subclass QTableView and override mouse handlers?

wysota
19th September 2011, 19:24
You need to remplement mouse events and rendering-related methods (which in practice makes up most if not all of the view code).

Nickolay
19th September 2011, 19:30
In very simple case, in current default implementation, to implement row moving inside one table,
what is the best approach with functions removeRows and insertRows?
Could I use them directly one after another inside dropMimeData?
So I can pack in MIME number of line of dragged item and inside dropMimeData I retrieve number of drop line.

wysota
19th September 2011, 19:55
what is the best approach with functions removeRows and insertRows?
Could I use them directly one after another inside dropMimeData?
I would say it is better to use QAbstractItemModel::beginMoveRows() and QAbstractItemModel::endMoveRows() in this case. In a general case dropMimeData() would only insert rows and rows removal would be done in the code when the drag is started when a "move" operation is detected.

Nickolay
19th September 2011, 20:32
I'm not clearly understand what do you mean.
generally I didn't get what sense of QAbstractItemModel::beginMoveRows() and QAbstractItemModel::endMoveRows()

By docs I should use them from removeRows, like

bool TableModel::removeRows(int position, int rows, const QModelIndex& index)
{
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position + rows - 1);
endRemoveRows();
return true;
}

But dragging begins from const func mimeData, where I can't call non const method.


and rows removal would be done in the code when the drag is started when a "move" operation is detected.

Where that place you have mentioned?

wysota
19th September 2011, 20:36
I suggest you read a little about model-view framework in Qt. Everything should become clearer then. One hint -- drag and drop in Qt is handled in the model and not in the view.