PDA

View Full Version : Drag Drop between Different Views



aamer4yu
20th November 2006, 05:10
I want to drag graphic items from the view and drop them in a Dock widget.
The view is displayed in Mainwindow, derived from QMainWindow. I want a widget that can hold graphic items in the scene temporarily.
For this I added a dock widget, but seems I cant move items outside the scene.:(

help...:confused:

wysota
20th November 2006, 07:03
It will be tricky. You're probably not dragging (in the drag&drop way) the graphical objects but simply interacting with them. You'll have to reimplement the dragging routines for the view (as only the view is the widget, so only the view can actually provide "drags"), providing your own mime type which the dock widget has to understand.

aamer4yu
20th November 2006, 07:13
Ok.. i was reading again the drag drop system, and seems this one gonna take time...
am also trying to see which receives drag events first. ne quick help on this ???

also i wanna know one thing, for dropping the items, I am using a class CMacroHolder derived from QWidget. If i am able to add the drag drop mechanisn to this class, I hope I can use it directly in the layout of QMainWindow, or add it to a DockWidget... ?

aamer4yu
21st November 2006, 06:02
I tried the following but in vain...
Added Drag event on MousePressEvent of graphic item. But doing this I am not able to move the item within the view.
Where exactly do I need to implement drag/drop mechanism ??

In other words, how can i drag/drop items from one view to another ?:confused:

Bitto
21st November 2006, 09:05
It's not that difficult to drag items onto a dock widget. First, you probably have your own custom target widget as a child of the dock widget; a drop site or whatever. So the problem has two sides: How to initiate the drag from an item, and how to accept the drop in the target widget.

To start the drag, you typically create a QDrag object from within QGraphicsItem::mousePressEvent() if you want to initiate the drag when immediately after pressing the mouse, or QGraphicsItem::mouseMoveEvent() if you want to add some "resistance" from the item. See this paragraph:

http://doc.trolltech.com/4.2/graphicsview.html#drag-and-drop

You can also look at the sources for the Drag & Drop Robot. Look for the mousePressEvent() function:

http://doc.trolltech.com/4.2/graphicsview-dragdroprobot-coloritem-cpp.html

To accept a drop, you need to reimplement dragEnterEvent() and dropEvent() in the target widget. In dragEnterEvent() you call event->acceptProposedAction() to indicate whether the drag looks OK or not (you can always accept based on the MIME type or file extension or so). In dropEvent() you then decode the mime data from the event. This is also done in the Robot example.

Just look at the Robot example ;-).

aamer4yu
21st November 2006, 11:12
@ Bitto
Well I already tried what you said.
But I dont need to drag drop items within the same view. I have to move it between one view and another temporary view.
I am attaching a snapshot of the application.
I have a MainWindow derived from QMainWindow. Inside it, I have Frame set as a central widget. This Frame contains two views, and slider/buttons.

What I need is, drag graphic items(Macro's) from Main view to a temporary view. The temporary view is a class in itself, and if this succeeds I will add this to a dockwdiget.

I started a QDrag object when mouse pressed on Macro. But due to this I am not able to move the items within the view. How do i manage automatic drag/drop of items within the view, and drag/drop from one view to another. Items donot move beyond the view.:(

aamer4yu
24th November 2006, 05:39
I am still unable to implement the drag drop from one view to another :(
Meanwhile I implement cut paste instead of drag drop.
On mouse click I took pointer to the object, and on mouse click in other scene, added that item to that scene.

Stil if someone can suggest how I implement drag drop from one scene to another, I would be thankful. I tried adding drag events to both the scenes. I was able to creat a drag event and detect it other. But doing so, Iam not able to move the item within the same view. How do I ensure that default drag movement within the scene are carried smoothly ??:confused:

aamer4yu
30th November 2006, 11:50
Someone help :confused:

wysota
30th November 2006, 14:50
Could we see some code you wrote while trying to solve the issue?

aamer4yu
1st December 2006, 06:04
I am attaching the code I have written till now.
In the toolbar, when Drag option is enabled, the cut paste option starts working. When enabled , u have to click on one item from one scen and click on another scene. U cannot place it in same scene.

I have added code for starting a drag event on mouse press of a item. And also code for accepting the drop in other view (CMAcroHolder)

In CMacro::mousePressEvent(QGraphicsSceneMouseEvent *event), u have drag->start() function, disabling that line, items move freely within the view. But how do i make the items move within the view also while the drag event has started ??

Also i wud be thankful, if any comment on design architecture, i do plan to start another thread discussing design patterns while making an application.

Bitto
2nd December 2006, 08:53
While dragging, the view and scene you are dragging from receive dragMoveEvent() events. You can reimplement dragMoveEvent() in QGraphicsScene to catch these, so that you can move an item in the scene while dragging around. QGraphicsSceneDragDropEvent has a scenePos() member that returns the drag position in scene coordinates, and this can help you position your item. Just remember to call the base implementation.

If the scene gets a dragLeaveEvent() while you're moving an item around, just hide the item. When the drag enters your other view, the scene will get a dragEnterEvent(), which is always followed by a dragMoveEvent(). So in your dragMoveEvent() implementation, you can make the item visible again if it isn't visible already.

The effect will be that as you press and drag the mouse on an item, a drag will start and your item will move with the drag inside the viewport. As the drag exits the viewport, the item will disappear. As the drag enters the other viewport, your item will reappear, and once again follow the drag position. You can choose to ignore the drop event.

aamer4yu
4th December 2006, 05:32
Thanx for ur reply Bitto,
I will try to implement what u said. But if u can provide me a minimal example code to me, it wud be really helpful. I have already spent more than sufficient time on this, and ur help will speed me up :)

Thx again

aamer4yu
6th December 2006, 10:52
am still struggling... help :crying:

well I have made some progress, in dragmovement of Scene, I check the position of the event, and set the item according to that position. I use pointer to the item within the mimedata of the drag event.

The Drag is started in mousepress event of Scene.


void CScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ ...
...
QDrag *drag = new QDrag(event->widget());
...
}



But now while checking if the drag started from this scene or not, I use event->source(), which returns a QWidget* and this is of type QGraphicsScene.

if (qobject_cast<CScene*>(event->source()) == this)
problem is, this condition doesnt matches.

I want to know if handling the events in QGraphicsView will be a better option or not ?
and in what case should I opt to implement them in QGraphicsScene ??

plz help

aamer4yu
8th December 2006, 05:29
Thanx to all of you, I finally managed to implement the drag drop between views.

Bitto, seems I understood ur answer a little late :D thx fr it... i was facing problem like how do I know which item is being dragged and where the drag event originated.
As for the item, I passed a pointer in MimeData and then casted back to QGraphicsItem. Dont know if its a good thing to do, but its working.
As for the origin,one has to set QDrag(event->widget()) , and I didnt knew any way how to know if the event originated from scene, bec event->source() returned the widget set in QDrag.
So I implemented the events in View rather than Scene.


Just one more Question, Did i do good implementing the events in view, or was there some better way to do ?? as implementing in Scene ??