doc/src/examples/fridgemagnets.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/examples/fridgemagnets.qdoc	Thu Apr 08 14:19:33 2010 +0300
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \example draganddrop/fridgemagnets
+    \title Fridge Magnets Example
+
+    The Fridge Magnets example shows how to supply more than one type
+    of MIME-encoded data with a drag and drop operation.
+
+    \image fridgemagnets-example.png
+
+    With this application the user can play around with a collection
+    of fridge magnets, using drag and drop to form new sentences from
+    the words on the magnets. The example consists of two classes:
+
+    \list
+        \o \c DragLabel is a custom widget representing one
+           single fridge magnet.
+        \o \c DragWidget provides the main application window.
+    \endlist
+
+    We will first take a look at the \c DragLabel class, then we will
+    examine the \c DragWidget class.
+
+    \section1 DragLabel Class Definition
+
+    Each fridge magnet is represented by an instance of the \c
+    DragLabel class:
+
+    \snippet examples/draganddrop/fridgemagnets/draglabel.h 0
+
+    Each instance of this QLabel subclass will be used to display an
+    pixmap generated from a text string. Since we cannot store both
+    text and a pixmap in a standard label, we declare a private variable
+    to hold the original text, and we define an additional member
+    function to allow it to be accessed.
+
+    \section1 DragLabel Class Implementation
+
+    In the \c DragLabel constructor, we first create a QImage object
+    on which we will draw the fridge magnet's text and frame:
+
+    \snippet examples/draganddrop/fridgemagnets/draglabel.cpp 0
+
+    Its size depends on the current font size, and its format is
+    QImage::Format_ARGB32_Premultiplied; i.e., the image is stored
+    using a premultiplied 32-bit ARGB format (0xAARRGGBB).
+
+    We then construct a font object that uses the application's
+    default font, and set its style strategy. The style strategy tells
+    the font matching algorithm what type of fonts should be used to
+    find an appropriate default family. The QFont::ForceOutline forces
+    the use of outline fonts.
+
+    To draw the text and frame onto the image, we use the QPainter
+    class. QPainter provides highly optimized methods to do most of
+    the drawing GUI programs require. It can draw everything from
+    simple lines to complex shapes like pies and chords. It can also
+    draw aligned text and pixmaps.
+
+    \snippet examples/draganddrop/fridgemagnets/draglabel.cpp 1
+
+    A painter can be activated by passing a paint device to the
+    constructor, or by using the \l{QPainter::}{begin()} method as we
+    do in this example. The \l{QPainter::}{end()} method deactivates
+    it. Note that the latter function is called automatically upon
+    destruction when the painter is actived by its constructor. The
+    QPainter::Antialiasing render hint ensures that the paint engine
+    will antialias the edges of primitives if possible.
+
+    When the painting is done, we convert our image to a pixmap using
+    QPixmap's \l {QPixmap::}{fromImage()} method. This method also
+    takes an optional flags argument, and converts the given image to
+    a pixmap using the specified flags to control the conversion (the
+    flags argument is a bitwise-OR of the Qt::ImageConversionFlags;
+    passing 0 for flags sets all the default options).
+
+    \snippet examples/draganddrop/fridgemagnets/draglabel.cpp 2
+
+    Finally, we set the label's \l{QLabel::pixmap}{pixmap property}
+    and store the label's text for later use.
+
+    \e{Note that setting the pixmap clears any previous content, including
+    any text previously set using QLabel::setText(), and disables
+    the label widget's buddy shortcut, if any.}
+
+    \section1 DragWidget Class Definition
+
+    The \c DragWidget class inherits QWidget, providing support for
+    drag and drop operations:
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.h 0
+
+    To make the widget responsive to drag and drop operations, we simply
+    reimplement the \l{QWidget::}{dragEnterEvent()},
+    \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
+    handlers inherited from QWidget.
+
+    We also reimplement \l{QWidget::}{mousePressEvent()} to make the
+    widget responsive to mouse clicks. This is where we will write code
+    to start drag and drop operations.
+
+    \section1 DragWidget Class Implementation
+
+    In the constructor, we first open the file containing the words on
+    our fridge magnets:
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 0
+
+    QFile is an I/O device for reading and writing text and binary
+    files and resources, and may be used by itself or in combination
+    with QTextStream or QDataStream. We have chosen to read the
+    contents of the file using the QTextStream class that provides a
+    convenient interface for reading and writing text.
+
+    We then create the fridge magnets. As long as there is data (the
+    QTextStream::atEnd() method returns true if there is no more data
+    to be read from the stream), we read one line at a time using
+    QTextStream's \l {QTextStream::}{readLine()} method.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 1
+
+    For each line, we create a \c DragLabel object using the read line
+    as text, we calculate its position and ensure that it is visible by
+    calling the QWidget::show() method. We set the Qt::WA_DeleteOnClose
+    attribute on each label to ensure that any unused labels will be
+    deleted; we will need to create new labels and delete old ones when
+    they are dragged around, and this ensures that the example does not
+    leak memory.
+
+    We also set the \c FridgeMagnets widget's palette, minimum size
+    and window title.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 2
+
+    Finally, to enable our user to move the fridge magnets around, we
+    must also set the \c FridgeMagnets widget's
+    \l{QWidget::acceptDrops}{acceptDrops} property.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 3
+
+    Setting this property to true announces to the system that this
+    widget \e may be able to accept drop events (events that are sent
+    when drag and drop actions are completed). Later, we will
+    implement the functions that ensure that the widget accepts the
+    drop events it is interested in.
+
+    \section2 Dragging
+
+    Let's take a look at the \l{QWidget::}{mousePressEvent()} event
+    handler, where drag and drop operations begin:
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 13
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 14
+
+    Mouse events occur when a mouse button is pressed or released
+    inside a widget, or when the mouse cursor is moved. By
+    reimplementing the \l{QWidget::}{mousePressEvent()} method we
+    ensure that we will receive mouse press events for the widget
+    containing the fridge magnets.
+
+    Whenever we receive such an event, we first check to see if the
+    position of the click coincides with one of the labels. If not,
+    we simply return.
+
+    If the user clicked a label, we determine the position of the
+    \e{hot spot} (the position of the click relative to the top-left
+    corner of the label). We create a byte array to store the label's
+    text and the hot spot, and we use a QDataStream object to stream
+    the data into the byte array.
+
+    With all the information in place, we create a new QMimeData object.
+    As mentioned above, QMimeData objects associate the data that they
+    hold with the corresponding MIME types to ensure that information
+    can be safely transferred between applications. The
+    \l{QMimeData::}{setData()} method sets the data associated with a
+    given MIME type. In our case, we associate our item data with the
+    custom \c application/x-fridgemagnet type.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 15
+
+    Note that we also associate the magnet's text with the
+    \c text/plain MIME type using QMimeData's \l{QMimeData::}{setText()}
+    method. Below, we will see how our widget detects both these MIME
+    types with its event handlers.
+
+    Finally, we create a QDrag object. It is the QDrag class that
+    handles most of the details of a drag and drop operation,
+    providing support for MIME-based drag and drop data transfer. The
+    data to be transferred by the drag and drop operation is contained
+    in a QMimeData object. When we call QDrag's
+    \l{QDrag::}{setMimeData()} method the ownership of our item data is
+    transferred to the QDrag object.
+
+    We call the \l{QDrag::}{setPixmap()} function to set the pixmap used
+    to represent the data during the drag and drop operation.
+    Typically, this pixmap shows an icon that represents the MIME type
+    of the data being transferred, but any pixmap can be used. In this
+    example, we simply use the pixmap used by the label itself to make
+    it look like the fridge magnet itself is being moved.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 16
+
+    We also specify the cursor's hot spot, its position relative to the
+    top-level corner of the drag pixmap, to be the point we calculated
+    above. This makes the process of dragging the label feel more natural
+    because the cursor always points to the same place on the label
+    during the drag operation. 
+
+    We start the drag operation using QDrag's \l{QDrag::}{exec()} function,
+    requesting that the magnet is copied when the drag is completed.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 17
+
+    The function returns the drop action actually performed by the user
+    (this can be either a copy or a move action in this case); if this
+    action is equal to Qt::MoveAction we will close the activated
+    fridge magnet widget because we will create a new one to replace it
+    (see the \l{drop}{dropEvent()} implementation). Otherwise, if
+    the drop is outside our main widget, we simply show the widget in
+    its original position.
+
+    \section2 Dropping
+
+    When a a drag and drop action enters our widget, we will receive a
+    drag enter \e event. QDragEnterEvent inherits most of its
+    functionality from QDragMoveEvent, which in turn inherits most of
+    its functionality from QDropEvent. Note that we must accept this
+    event in order to receive the drag move events that are sent while
+    the drag and drop action is in progress. The drag enter event is
+    always immediately followed by a drag move event.
+
+    In our \c dragEnterEvent() implementation, we first determine
+    whether we support the event's MIME type or not:
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 4
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 5
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 6
+
+    If the type is \c application/x-fridgemagnet and the event
+    origins from any of this application's fridge magnet widgets, we
+    first set the event's drop action using the
+    QDropEvent::setDropAction() method. An event's drop action is the
+    action to be performed on the data by the target. Qt::MoveAction
+    indicates that the data is moved from the source to the target.
+
+    Then we call the event's \l {QDragMoveEvent::}{accept()} method to
+    indicate that we have handled the event. In general, unaccepted
+    events might be propagated to the parent widget. If the event
+    origins from any other widget, we simply accept the proposed
+    action.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 7
+
+    We also accept the proposed action if the event's MIME type is \c
+    text/plain, i.e., if QMimeData::hasText() returns true. If the
+    event has any other type, on the other hand, we call the event's
+    \l {QDragMoveEvent::}{ignore()} method allowing the event to be
+    propagated further.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 8
+
+    Drag move events occur when the cursor enters a widget, when it
+    moves within the widget, and when a modifier key is pressed on the
+    keyboard while the widget has focus. Our widget will receive drag
+    move events repeatedly while a drag is within its boundaries. We
+    reimplement the \l {QWidget::}{dragMoveEvent()} method, and
+    examine the event in the exact same way as we did with drag enter
+    events.
+
+    Note that the \l{QWidget::}{dropEvent()} event handler behaves
+    slightly differently: We first get hold of the event's MIME
+    data.
+
+    \target drop
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 9
+
+    The QMimeData class provides a container for data that
+    records information about its MIME type. QMimeData objects
+    associate the data that they hold with the corresponding MIME
+    types to ensure that information can be safely transferred between
+    applications, and copied around within the same application.
+
+    We retrieve the data associated with the \c application/x-fridgemagnet
+    MIME type using a data stream in order to create a new \c DragLabel
+    object.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 10
+
+    The QDataStream class provides serialization of binary data to a
+    QIODevice (a data stream is a binary stream of encoded information
+    which is completely independent of the host computer's operating
+    system, CPU or byte order).
+
+    Finally, we create a label and move it to the event's position:
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 11
+
+    If the source of the event is also the widget receiving the
+    drop event, we set the event's drop action to Qt::MoveAction and
+    call the event's \l{QDragMoveEvent::}{accept()}
+    method. Otherwise, we simply accept the proposed action. This
+    means that labels are moved rather than copied in the same
+    window. However, if we drag a label to a second instance of the
+    Fridge Magnets example, the default action is to copy it, leaving
+    the original in the first instance.
+
+    If the event's MIME type is \c text/plain (i.e., if
+    QMimeData::hasText() returns true) we retrieve its text and split
+    it into words. For each word we create a new \c DragLabel action,
+    and show it at the event's position plus an offset depending on
+    the number of words in the text. In the end we accept the proposed
+    action. This lets the user drop selected text from a text editor or
+    Web browser onto the widget to add more fridge magnets.
+
+    \snippet examples/draganddrop/fridgemagnets/dragwidget.cpp 12
+
+    If the event has any other type, we call the event's
+    \l{QDragMoveEvent::}{ignore()} method allowing the event to be
+    propagated further.
+
+    \section1 Summary
+
+    We set our main widget's \l{QWidget::}{acceptDrops} property
+    and reimplemented QWidget's \l{QWidget::}{dragEnterEvent()},
+    \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
+    handlers to support content dropped on our widget.
+
+    In addition, we reimplemented the \l{QWidget::}{mousePressEvent()}
+    function to let the user pick up fridge magnets in the first place.
+
+    Because data is communicated using drag and drop operations and
+    encoded using MIME types, you can run more than one instance of this
+    example, and transfer magnets between them.
+*/