1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/dnd.doc:36 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Drag and Drop</title>
<style type="text/css"><!--
fn { margin-left: 1cm; text-indent: -1cm; }
a:link { color: #004faf; text-decoration: none }
a:visited { color: #672967; text-decoration: none }
body { background: #ffffff; color: black; }
--></style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr bgcolor="#E5E5E5">
<td valign=center>
<a href="index.html">
<font color="#004faf">Home</font></a>
| <a href="classes.html">
<font color="#004faf">All Classes</font></a>
| <a href="mainclasses.html">
<font color="#004faf">Main Classes</font></a>
| <a href="annotated.html">
<font color="#004faf">Annotated</font></a>
| <a href="groups.html">
<font color="#004faf">Grouped Classes</font></a>
| <a href="functions.html">
<font color="#004faf">Functions</font></a>
</td>
<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Drag and Drop</h1>
<p> Drag and drop provides a simple visual mechanism which users can use
to transfer information between and within applications. (In the
literature this is referred to as a "direct manipulation model".) Drag
and drop is similar in function to the clipboard's cut-and-paste
mechanism.
<p> <!-- toc -->
<ul>
<li><a href="#1"> Dragging
</a>
<li><a href="#2"> Dropping
</a>
<li><a href="#3"> The Clipboard
</a>
<li><a href="#4"> Drag and Drop Actions
</a>
<li><a href="#5"> Adding New Drag and Drop Types
</a>
<li><a href="#6"> Advanced Drag-and-Drop
</a>
<li><a href="#7"> Inter-operating with Other Applications
</a>
</ul>
<!-- endtoc -->
<p> For drag and drop examples see (in increasing order of
sophistication): <tt>qt/examples/iconview/simple_dd</tt>, <tt>qt/examples/dragdrop</tt> and <tt>qt/examples/fileiconview</tt>. See also the
<a href="qtextedit.html">QTextEdit</a> widget source code.
<p> <h2> Dragging
</h2>
<a name="1"></a><p> To start a drag, for example in a <a href="qwidget.html#mouseMoveEvent">mouse motion event</a>, create an object of the <a href="qdragobject.html">QDragObject</a>
subclass appropriate for your media, such as <a href="qtextdrag.html">QTextDrag</a> for text and
<a href="qimagedrag.html">QImageDrag</a> for images. Then call the drag() method. This is all you
need for simple dragging of existing types.
<p> For example, to start dragging some text from a widget:
<pre>
void MyWidget::startDrag()
{
<a href="qdragobject.html">QDragObject</a> *d = new <a href="qtextdrag.html">QTextDrag</a>( myHighlightedText(), this );
d-><a href="qdragobject.html#dragCopy">dragCopy</a>();
// do NOT delete d.
}
</pre>
<p> Note that the QDragObject is not deleted after the drag. The
QDragObject needs to persist after the drag is apparently finished
since it may still be communicating with another process. Eventually
Qt will delete the object. If the widget owning the drag object is
deleted before then, any pending drop will be canceled and the drag
object deleted. For this reason, you should be careful what the object
references.
<p> <h2> Dropping
</h2>
<a name="2"></a><p> To be able to receive media dropped on a widget, call
<a href="qwidget.html#setAcceptDrops">setAcceptDrops(TRUE)</a>
for the widget (e.g. in its constructor), and override the
event handler methods
<a href="qwidget.html#dragEnterEvent">dragEnterEvent()</a> and
<a href="qwidget.html#dropEvent">dropEvent()</a>.
For more sophisticated applications overriding
<a href="qwidget.html#dragMoveEvent">dragMoveEvent()</a> and
<a href="qwidget.html#dragLeaveEvent">dragLeaveEvent()</a> will also be
necessary.
<p> For example, to accept text and image drops:
<pre>
MyWidget::MyWidget(...) :
<a href="qwidget.html">QWidget</a>(...)
{
...
setAcceptDrops(TRUE);
}
void MyWidget::dragEnterEvent(QDragEnterEvent* event)
{
event->accept(
QTextDrag::<a href="qtextdrag.html#canDecode">canDecode</a>(event) ||
QImageDrag::<a href="qimagedrag.html#canDecode">canDecode</a>(event)
);
}
void MyWidget::dropEvent(QDropEvent* event)
{
<a href="qimage.html">QImage</a> image;
<a href="qstring.html">QString</a> text;
if ( QImageDrag::<a href="qimagedrag.html#decode">decode</a>(event, image) ) {
insertImageAt(image, event->pos());
} else if ( QTextDrag::<a href="qtextdrag.html#decode">decode</a>(event, text) ) {
insertTextAt(text, event->pos());
}
}
</pre>
<p> <h2> The Clipboard
</h2>
<a name="3"></a><p> The <a href="qdragobject.html">QDragObject</a>, <a href="qdragenterevent.html">QDragEnterEvent</a>, <a href="qdragmoveevent.html">QDragMoveEvent</a>, and <a href="qdropevent.html">QDropEvent</a>
classes are all subclasses of QMimeSource: the class of objects which
provide typed information. If you base your data transfers on
QDragObject, you not only get drag-and-drop, but you also get
traditional cut-and-paste for free. The <a href="qclipboard.html">QClipboard</a> has two functions:
<pre>
setData(QMimeSource*)
<a href="qmimesource.html">QMimeSource</a>* data()const
</pre>
With these functions you can trivially put your drag-and-drop oriented
information on the clipboard:
<pre>
void MyWidget::copy()
{
QApplication::<a href="qapplication.html#clipboard">clipboard</a>()->setData(
new <a href="qtextdrag.html">QTextDrag</a>(myHighlightedText()) );
}
void MyWidget::paste()
{
<a href="qstring.html">QString</a> text;
if ( QTextDrag::<a href="qtextdrag.html#decode">decode</a>(QApplication::<a href="qapplication.html#clipboard">clipboard</a>()->data(), text) )
insertText( text );
}
</pre>
You can even use <a href="qdragobject.html">QDragObject</a> subclasses as part of file IO. For
example, if your application has a subclass of QDragObject that
encodes CAD designs in DXF format, your saving and loading code might
be:
<pre>
void MyWidget::save()
{
<a href="qfile.html">QFile</a> out(current_file_name);
if ( out.<a href="qfile.html#open">open</a>(IO_WriteOnly) ) {
MyCadDrag tmp(current_design);
out.<a href="qiodevice.html#writeBlock">writeBlock</a>( tmp->encodedData( "image/x-dxf" ) );
}
}
void MyWidget::load()
{
<a href="qfile.html">QFile</a> in(current_file_name);
if ( in.<a href="qfile.html#open">open</a>(IO_ReadOnly) ) {
if ( !MyCadDrag::decode(in.<a href="qiodevice.html#readAll">readAll</a>(), current_design) ) {
QMessageBox::<a href="qmessagebox.html#warning">warning</a>( this, "Format error",
tr("The file \"%1\" is not in any supported format")
.arg(current_file_name)
);
}
}
}
</pre>
Note how the <a href="qdragobject.html">QDragObject</a> subclass is called "MyCadDrag", not
"MyDxfDrag": because in the future you might extend it to provide
DXF, DWG, SVF, WMF, or even <a href="qpicture.html">QPicture</a> data to other applications.
<p> <h2> Drag and Drop Actions
</h2>
<a name="4"></a><p> In the simpler cases, the target of a drag-and-drop receives a copy of
the data being dragged and the source decides whether to delete the
original. This is the "Copy" action in <a href="qdropevent.html">QDropEvent</a>. The target may also
choose to understand other actions, specifically the Move and Link
actions. If the target understands the Move action, <em>the target</em> is responsible for both the copy and delete operations and
the source will not attempt to delete the data itself. If the target
understands the Link, it stores its own reference to the original
information, and again the source does not delete the original. The
most common use of drag-and-drop actions is when performing a Move
within the same widget: see the <a href="#advanced">Advanced
Drag-and-Drop</a> section below.
<p> The other major use of drag actions is when using a reference type
such as text/uri-list, where the dragged data are actually references
to files or objects.
<p> <h2> Adding New Drag and Drop Types
</h2>
<a name="5"></a><p> As suggested in the DXF example above, drag-and-drop is not limited to
text and images. Any information can be dragged and dropped. To drag
information between applications, the applications must be able to
indicate to each other which data formats they can accept and which
they can produce. This is achieved using <a href="http://www.rfc-editor.org/rfc/rfc1341.txt">MIME types</a>: the drag
source provides a list of MIME types that it can produce (ordered from
most appropriate to least appropriate), and the drop target chooses
which of those it can accept. For example, <a href="qtextdrag.html">QTextDrag</a> provides support
for the "<tt>text/plain</tt>" MIME type (ordinary unformatted text), and
the Unicode formats "<tt>text/utf16</tt>" and "<tt>text/utf8</tt>"; <a href="qimagedrag.html">QImageDrag</a>
provides for "<tt>image/*</tt>", where <tt>*</tt> is any image format that
<a href="qimageio.html">QImageIO</a> supports; and the <a href="quridrag.html">QUriDrag</a> subclass provides
"<tt>text/uri-list</tt>", a standard format for transferring a list of
filenames (or URLs).
<p> To implement drag-and-drop of some type of information for which there
is no available <a href="qdragobject.html">QDragObject</a> subclass, the first and most important
step is to look for existing formats that are appropriate: the
Internet Assigned Numbers Authority (<a href="http://www.iana.org">IANA</a>) provides a <a href="http://www.isi.edu/in-notes/iana/assignments/media-types/">hierarchical
list of MIME media types</a> at the Information Sciences Institute
(<a href="http://www.isi.edu">ISI</a>). Using standard MIME types
maximizes the inter-operability of your application with other
software now and in the future.
<p> To support an additional media type, subclass either QDragObject or
<a href="qstoreddrag.html">QStoredDrag</a>. Subclass QDragObject when you need to provide support for
multiple media types. Subclass the simpler QStoredDrag when one type
is sufficient.
<p> Subclasses of QDragObject will override the
<a href="qmimesource.html#format">const char* format(int i) const</a> and
<a href="qmimesource.html#encodedData">QByteArray encodedData(const char* mimetype) const</a>
members, and provide a set-method to encode the media data and static
members canDecode() and decode() to decode incoming data, similar to
<a href="qimagedrag.html#canDecode">bool canDecode(QMimeSource*) const</a> and
<a href="qimagedrag.html#decode">QByteArray decode(QMimeSource*) const</a>
of <a href="qimagedrag.html">QImageDrag</a>.
Of course, you can provide drag-only or drop-only support for a media
type by omitting some of these methods.
<p> Subclasses of QStoredDrag provide a set-method to encode the media
data and the same static members canDecode() and decode() to decode
incoming data.
<p> <a name="advanced"></a>
<h2> Advanced Drag-and-Drop
</h2>
<a name="6"></a><p> In the clipboard model, the user can <em>cut</em> or <em>copy</em> the source
information, then later paste it. Similarly in the drag-and-drop
model, the user can drag a <em>copy</em> of the information or they can drag
the information itself to a new place (<em>moving</em> it). The
drag-and-drop model however has an additional complication for the
programmer: the program doesn't know whether the user wants to cut or
copy until the drop (paste) is done! For dragging between
applications, it makes no difference, but for dragging within an
application, the application must take a little extra care not to
tread on its own feet. For example, to drag text around in a document,
the drag start point and the drop event might look like this:
<p> <pre>
void MyEditor::startDrag()
{
<a href="qdragobject.html">QDragObject</a> *d = new <a href="qtextdrag.html">QTextDrag</a>(myHighlightedText(), this);
if ( d-><a href="qdragobject.html#drag">drag</a>() && d-><a href="qdragobject.html#target">target</a>() != this )
cutMyHighlightedText();
}
void MyEditor::dropEvent(QDropEvent* event)
{
<a href="qstring.html">QString</a> text;
if ( QTextDrag::<a href="qtextdrag.html#decode">decode</a>(event, text) ) {
if ( event->source() == this && event->action() == QDropEvent::Move ) {
// Careful not to tread on my own feet
event->acceptAction();
moveMyHighlightedTextTo(event->pos());
} else {
pasteTextAt(text, event->pos());
}
}
}
</pre>
<p> Some widgets are more specific than just a "yes" or "no" response when
data is dragged onto them. For example, a CAD program might only
accept drops of text onto text objects in the view. In these cases,
the <a href="qwidget.html#dragMoveEvent">dragMoveEvent()</a> is used and
an <em>area</em> is given for which the drag is accepted or ignored:
<pre>
void MyWidget::dragMoveEvent(QDragMoveEvent* event)
{
if ( QTextDrag::<a href="qtextdrag.html#canDecode">canDecode</a>(event) ) {
MyCadItem* item = findMyItemAt(event->pos());
if ( item )
event->accept();
}
}
</pre>
If the computations to find objects are particularly slow, you might
achieve improved performance if you tell the system an area for which
you promise the acceptance persists:
<pre>
void MyWidget::dragMoveEvent(QDragMoveEvent* event)
{
if ( QTextDrag::<a href="qtextdrag.html#canDecode">canDecode</a>(event) ) {
MyCadItem* item = findMyItemAt(event->pos());
if ( item ) {
<a href="qrect.html">QRect</a> r = item->areaRelativeToMeClippedByAnythingInTheWay();
if ( item->type() == MyTextType )
event->accept( r );
else
event->ignore( r );
}
}
}
</pre>
<p> The dragMoveEvent() can also be used if you need to give visual
feedback as the drag progresses, to start timers, to scroll the
window, or whatever is appropriate (don't forget to stop the scrolling
and timers in a dragLeaveEvent() though).
<p> The <a href="qapplication.html">QApplication</a> object (available as the <tt>qApp</tt> global) also
provides some drag and drop related functions:
<a href="qapplication.html#setStartDragTime">QApplication::setStartDragTime</a>(),
<a href="qapplication.html#setStartDragDistance">QApplication::setStartDragDistance</a>(), and their corresponding
getters, <a href="qapplication.html#startDragTime">QApplication::startDragTime</a>() and
<a href="qapplication.html#startDragDistance">QApplication::startDragDistance</a>().
<p> <h2> Inter-operating with Other Applications
</h2>
<a name="7"></a><p> On X11, the public <a class="r"
href="http://www.newplanetsoftware.com/xdnd/">XDND protocol</a> is
used, while on Windows Qt uses the OLE standard, and Qt/Mac uses the
Carbon Drag Manager. On X11, XDND uses MIME, so no translation is
necessary. The Qt API is the same regardless of the platform. On
Windows, MIME-aware applications can communicate by using clipboard
format names that are MIME types. Already some Windows applications
use MIME naming conventions for their clipboard formats. Internally,
Qt has facilities for translating proprietary clipboard formats to and
from MIME types. This interface will be made public at some time, but
if you need to do such translations now, contact your Qt Technical
Support service.
<p> On X11, Qt also supports drops via the <a href="motif-extension.html#Motif">Motif</a> Drag&Drop Protocol. The
implementation incorporates some code that was originally written by
Daniel Dardailler, and adapted for Qt by Matt Koss <koss@napri.sk>
and Trolltech. Here is the original copyright notice:
<p>
<p> Copyright 1996 Daniel Dardailler.
<p> Permission to use, copy, modify, distribute, and sell this software
for any purpose is hereby granted without fee, provided that the above
copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation,
and that the name of Daniel Dardailler not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission. Daniel Dardailler makes no representations
about the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
<p> Modifications Copyright 1999 Matt Koss, under the same license as
above.
<p>
<!-- eof -->
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright © 2007
<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
<td align=right><div align=right>Qt 3.3.8</div>
</table></div></address></body>
</html>
|