<!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="ntqtextedit.html">TQTextEdit</a> widget source code. <p> <h2> Dragging </h2> <a name="1"></a><p> To start a drag, for example in a <a href="ntqwidget.html#mouseMoveEvent">mouse motion event</a>, create an object of the <a href="ntqdragobject.html">TQDragObject</a> subclass appropriate for your media, such as <a href="qtextdrag.html">TQTextDrag</a> for text and <a href="qimagedrag.html">TQImageDrag</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="ntqdragobject.html">TQDragObject</a> *d = new <a href="qtextdrag.html">TQTextDrag</a>( myHighlightedText(), this ); d-><a href="ntqdragobject.html#dragCopy">dragCopy</a>(); // do NOT delete d. } </pre> <p> Note that the TQDragObject is not deleted after the drag. The TQDragObject needs to persist after the drag is apparently finished since it may still be communicating with another process. Eventually TQt 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="ntqwidget.html#setAcceptDrops">setAcceptDrops(TRUE)</a> for the widget (e.g. in its constructor), and override the event handler methods <a href="ntqwidget.html#dragEnterEvent">dragEnterEvent()</a> and <a href="ntqwidget.html#dropEvent">dropEvent()</a>. For more sophisticated applications overriding <a href="ntqwidget.html#dragMoveEvent">dragMoveEvent()</a> and <a href="ntqwidget.html#dragLeaveEvent">dragLeaveEvent()</a> will also be necessary. <p> For example, to accept text and image drops: <pre> MyWidget::MyWidget(...) : <a href="ntqwidget.html">TQWidget</a>(...) { ... setAcceptDrops(TRUE); } void MyWidget::dragEnterEvent(TQDragEnterEvent* event) { event->accept( TQTextDrag::<a href="qtextdrag.html#canDecode">canDecode</a>(event) || TQImageDrag::<a href="qimagedrag.html#canDecode">canDecode</a>(event) ); } void MyWidget::dropEvent(TQDropEvent* event) { <a href="ntqimage.html">TQImage</a> image; <a href="ntqstring.html">TQString</a> text; if ( TQImageDrag::<a href="qimagedrag.html#decode">decode</a>(event, image) ) { insertImageAt(image, event->pos()); } else if ( TQTextDrag::<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="ntqdragobject.html">TQDragObject</a>, <a href="qdragenterevent.html">TQDragEnterEvent</a>, <a href="qdragmoveevent.html">TQDragMoveEvent</a>, and <a href="qdropevent.html">TQDropEvent</a> classes are all subclasses of TQMimeSource: the class of objects which provide typed information. If you base your data transfers on TQDragObject, you not only get drag-and-drop, but you also get traditional cut-and-paste for free. The <a href="ntqclipboard.html">TQClipboard</a> has two functions: <pre> setData(TQMimeSource*) <a href="qmimesource.html">TQMimeSource</a>* data()const </pre> With these functions you can trivially put your drag-and-drop oriented information on the clipboard: <pre> void MyWidget::copy() { TQApplication::<a href="ntqapplication.html#clipboard">clipboard</a>()->setData( new <a href="qtextdrag.html">TQTextDrag</a>(myHighlightedText()) ); } void MyWidget::paste() { <a href="ntqstring.html">TQString</a> text; if ( TQTextDrag::<a href="qtextdrag.html#decode">decode</a>(TQApplication::<a href="ntqapplication.html#clipboard">clipboard</a>()->data(), text) ) insertText( text ); } </pre> You can even use <a href="ntqdragobject.html">TQDragObject</a> subclasses as part of file IO. For example, if your application has a subclass of TQDragObject that encodes CAD designs in DXF format, your saving and loading code might be: <pre> void MyWidget::save() { <a href="ntqfile.html">TQFile</a> out(current_file_name); if ( out.<a href="ntqfile.html#open">open</a>(IO_WriteOnly) ) { MyCadDrag tmp(current_design); out.<a href="ntqiodevice.html#writeBlock">writeBlock</a>( tmp->encodedData( "image/x-dxf" ) ); } } void MyWidget::load() { <a href="ntqfile.html">TQFile</a> in(current_file_name); if ( in.<a href="ntqfile.html#open">open</a>(IO_ReadOnly) ) { if ( !MyCadDrag::decode(in.<a href="ntqiodevice.html#readAll">readAll</a>(), current_design) ) { TQMessageBox::<a href="ntqmessagebox.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="ntqdragobject.html">TQDragObject</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="ntqpicture.html">TQPicture</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">TQDropEvent</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">TQTextDrag</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">TQImageDrag</a> provides for "<tt>image/*</tt>", where <tt>*</tt> is any image format that <a href="qimageio.html">TQImageIO</a> supports; and the <a href="quridrag.html">TQUriDrag</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="ntqdragobject.html">TQDragObject</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 TQDragObject or <a href="qstoreddrag.html">TQStoredDrag</a>. Subclass TQDragObject when you need to provide support for multiple media types. Subclass the simpler TQStoredDrag when one type is sufficient. <p> Subclasses of TQDragObject will override the <a href="qmimesource.html#format">const char* format(int i) const</a> and <a href="qmimesource.html#encodedData">TQByteArray 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(TQMimeSource*) const</a> and <a href="qimagedrag.html#decode">TQByteArray decode(TQMimeSource*) const</a> of <a href="qimagedrag.html">TQImageDrag</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 TQStoredDrag 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="ntqdragobject.html">TQDragObject</a> *d = new <a href="qtextdrag.html">TQTextDrag</a>(myHighlightedText(), this); if ( d-><a href="ntqdragobject.html#drag">drag</a>() && d-><a href="ntqdragobject.html#target">target</a>() != this ) cutMyHighlightedText(); } void MyEditor::dropEvent(TQDropEvent* event) { <a href="ntqstring.html">TQString</a> text; if ( TQTextDrag::<a href="qtextdrag.html#decode">decode</a>(event, text) ) { if ( event->source() == this && event->action() == TQDropEvent::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="ntqwidget.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(TQDragMoveEvent* event) { if ( TQTextDrag::<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(TQDragMoveEvent* event) { if ( TQTextDrag::<a href="qtextdrag.html#canDecode">canDecode</a>(event) ) { MyCadItem* item = findMyItemAt(event->pos()); if ( item ) { <a href="ntqrect.html">TQRect</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="ntqapplication.html">TQApplication</a> object (available as the <tt>tqApp</tt> global) also provides some drag and drop related functions: <a href="ntqapplication.html#setStartDragTime">TQApplication::setStartDragTime</a>(), <a href="ntqapplication.html#setStartDragDistance">TQApplication::setStartDragDistance</a>(), and their corresponding getters, <a href="ntqapplication.html#startDragTime">TQApplication::startDragTime</a>() and <a href="ntqapplication.html#startDragDistance">TQApplication::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 TQt uses the OLE standard, and TQt/Mac uses the Carbon Drag Manager. On X11, XDND uses MIME, so no translation is necessary. The TQt 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, TQt 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 TQt Technical Support service. <p> On X11, TQt 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 TQt 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>TQt 3.3.8</div> </table></div></address></body> </html>