diff options
Diffstat (limited to 'doc/dnd.doc')
-rw-r--r-- | doc/dnd.doc | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/doc/dnd.doc b/doc/dnd.doc new file mode 100644 index 000000000..9bddd90ea --- /dev/null +++ b/doc/dnd.doc @@ -0,0 +1,383 @@ +/**************************************************************************** +** +** Drag and drop documentation +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +/*! +\page dnd.html + +\title Drag and Drop + +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. + +\tableofcontents + +For drag and drop examples see (in increasing order of +sophistication): \c qt/examples/iconview/simple_dd, \c +qt/examples/dragdrop and \c qt/examples/fileiconview. See also the +QTextEdit widget source code. + + +\section1 Dragging + +To start a drag, for example in a \link QWidget::mouseMoveEvent() +mouse motion event\endlink, create an object of the QDragObject +subclass appropriate for your media, such as QTextDrag for text and +QImageDrag for images. Then call the drag() method. This is all you +need for simple dragging of existing types. + +For example, to start dragging some text from a widget: +\code +void MyWidget::startDrag() +{ + QDragObject *d = new QTextDrag( myHighlightedText(), this ); + d->dragCopy(); + // do NOT delete d. +} +\endcode + +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. + +\section1 Dropping + +To be able to receive media dropped on a widget, call +\link QWidget::setAcceptDrops() setAcceptDrops(TRUE)\endlink +for the widget (e.g. in its constructor), and override the +event handler methods +\link QWidget::dragEnterEvent() dragEnterEvent()\endlink and +\link QWidget::dropEvent() dropEvent()\endlink. +For more sophisticated applications overriding +\link QWidget::dragMoveEvent() dragMoveEvent()\endlink and +\link QWidget::dragLeaveEvent() dragLeaveEvent()\endlink will also be +necessary. + +For example, to accept text and image drops: +\code +MyWidget::MyWidget(...) : + QWidget(...) +{ + ... + setAcceptDrops(TRUE); +} + +void MyWidget::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( + QTextDrag::canDecode(event) || + QImageDrag::canDecode(event) + ); +} + +void MyWidget::dropEvent(QDropEvent* event) +{ + QImage image; + QString text; + + if ( QImageDrag::decode(event, image) ) { + insertImageAt(image, event->pos()); + } else if ( QTextDrag::decode(event, text) ) { + insertTextAt(text, event->pos()); + } +} +\endcode + +\section1 The Clipboard + +The QDragObject, QDragEnterEvent, QDragMoveEvent, and QDropEvent +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 QClipboard has two functions: +\code + setData(QMimeSource*) + QMimeSource* data()const +\endcode +With these functions you can trivially put your drag-and-drop oriented +information on the clipboard: +\code +void MyWidget::copy() +{ + QApplication::clipboard()->setData( + new QTextDrag(myHighlightedText()) ); +} + +void MyWidget::paste() +{ + QString text; + if ( QTextDrag::decode(QApplication::clipboard()->data(), text) ) + insertText( text ); +} +\endcode +You can even use QDragObject 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: +\code +void MyWidget::save() +{ + QFile out(current_file_name); + if ( out.open(IO_WriteOnly) ) { + MyCadDrag tmp(current_design); + out.writeBlock( tmp->encodedData( "image/x-dxf" ) ); + } +} + +void MyWidget::load() +{ + QFile in(current_file_name); + if ( in.open(IO_ReadOnly) ) { + if ( !MyCadDrag::decode(in.readAll(), current_design) ) { + QMessageBox::warning( this, "Format error", + tr("The file \"%1\" is not in any supported format") + .arg(current_file_name) + ); + } + } +} +\endcode +Note how the QDragObject subclass is called "MyCadDrag", not +"MyDxfDrag": because in the future you might extend it to provide +DXF, DWG, SVF, WMF, or even QPicture data to other applications. + +\section1 Drag and Drop Actions + +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 QDropEvent. The target may also +choose to understand other actions, specifically the Move and Link +actions. If the target understands the Move action, \e{the +target} 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 \link #advanced Advanced +Drag-and-Drop\endlink section below. + +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. + +\section1 Adding New Drag and Drop Types + +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 \link +http://www.rfc-editor.org/rfc/rfc1341.txt MIME types\endlink: 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, QTextDrag provides support +for the "\c{text/plain}" MIME type (ordinary unformatted text), and +the Unicode formats "\c{text/utf16}" and "\c{text/utf8}"; QImageDrag +provides for "\c{image/*}", where \c{*} is any image format that +\l QImageIO supports; and the QUriDrag subclass provides +"\c{text/uri-list}", a standard format for transferring a list of +filenames (or URLs). + +To implement drag-and-drop of some type of information for which there +is no available QDragObject subclass, the first and most important +step is to look for existing formats that are appropriate: the +Internet Assigned Numbers Authority (\link http://www.iana.org +IANA\endlink) provides a \link +http://www.isi.edu/in-notes/iana/assignments/media-types/ hierarchical +list of MIME media types\endlink at the Information Sciences Institute +(\link http://www.isi.edu ISI\endlink). Using standard MIME types +maximizes the inter-operability of your application with other +software now and in the future. + +To support an additional media type, subclass either QDragObject or +QStoredDrag. Subclass QDragObject when you need to provide support for +multiple media types. Subclass the simpler QStoredDrag when one type +is sufficient. + +Subclasses of QDragObject will override the +\link QDragObject::format() +const char* format(int i) const +\endlink and +\link QDragObject::encodedData() +QByteArray encodedData(const char* mimetype) const +\endlink +members, and provide a set-method to encode the media data and static +members canDecode() and decode() to decode incoming data, similar to +\link QImageDrag::canDecode() +bool canDecode(QMimeSource*) const +\endlink and +\link QImageDrag::decode() +QByteArray decode(QMimeSource*) const +\endlink +of QImageDrag. +Of course, you can provide drag-only or drop-only support for a media +type by omitting some of these methods. + +Subclasses of QStoredDrag provide a set-method to encode the media +data and the same static members canDecode() and decode() to decode +incoming data. + +\target advanced +\section1 Advanced Drag-and-Drop + +In the clipboard model, the user can \e cut or \e copy the source +information, then later paste it. Similarly in the drag-and-drop +model, the user can drag a \e copy of the information or they can drag +the information itself to a new place (\e moving 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: + +\code +void MyEditor::startDrag() +{ + QDragObject *d = new QTextDrag(myHighlightedText(), this); + if ( d->drag() && d->target() != this ) + cutMyHighlightedText(); +} + +void MyEditor::dropEvent(QDropEvent* event) +{ + QString text; + + if ( QTextDrag::decode(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()); + } + } +} +\endcode + +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 \link QWidget::dragMoveEvent() dragMoveEvent()\endlink is used and +an \e area is given for which the drag is accepted or ignored: +\code +void MyWidget::dragMoveEvent(QDragMoveEvent* event) +{ + if ( QTextDrag::canDecode(event) ) { + MyCadItem* item = findMyItemAt(event->pos()); + if ( item ) + event->accept(); + } +} +\endcode +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: +\code +void MyWidget::dragMoveEvent(QDragMoveEvent* event) +{ + if ( QTextDrag::canDecode(event) ) { + MyCadItem* item = findMyItemAt(event->pos()); + if ( item ) { + QRect r = item->areaRelativeToMeClippedByAnythingInTheWay(); + if ( item->type() == MyTextType ) + event->accept( r ); + else + event->ignore( r ); + } + } +} +\endcode + +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). + +The QApplication object (available as the \c qApp global) also +provides some drag and drop related functions: +\l{QApplication::setStartDragTime()}, +\l{QApplication::setStartDragDistance()}, and their corresponding +getters, \l{QApplication::startDragTime()} and +\l{QApplication::startDragDistance()}. + +\section1 Inter-operating with Other Applications + +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. + +On X11, Qt also supports drops via the Motif 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: + +\legalese + +Copyright 1996 Daniel Dardailler. + +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. + +Modifications Copyright 1999 Matt Koss, under the same license as +above. + +*/ // NOTE: That notice is from qmotifdnd_x11.cpp. |