doc/src/examples/tablet.qdoc
changeset 7 f7bc934e204c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/examples/tablet.qdoc	Wed Mar 31 11:06:36 2010 +0300
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** 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 widgets/tablet
+    \title Tablet Example
+
+    This example shows how to use a Wacom tablet in Qt applications.
+
+    \image tabletexample.png
+
+    When you use a tablet with Qt applications, \l{QTabletEvent}s are
+    generated. You need to reimplement the
+    \l{QWidget::}{tabletEvent()} event handler if you want to handle
+    tablet events. Events are generated when the device used for
+    drawing enters and leaves the proximity of the tablet (i.e., when
+    it is close but not pressed down on it), when a device is pushed
+    down and released from it, and when a device is moved on the
+    tablet.
+  
+    The information available in QTabletEvent depends on the device
+    used. The tablet in this example has two different devices for
+    drawing: a stylus and an airbrush. For both devices the event
+    contains the position of the device, pressure on the tablet,
+    vertical tilt, and horizontal tilt (i.e, the angle between the
+    device and the perpendicular of the tablet). The airbrush has a
+    finger wheel; the position of this is also available in the tablet
+    event.
+
+    In this example we implement a drawing program. You can use the
+    stylus to draw on the tablet as you use a pencil on paper. When
+    you draw with the airbrush you get a spray of paint; the finger
+    wheel is used to change the density of the spray. The pressure and
+    tilt can change the alpha and saturation values of the QColor and the
+    width of the QPen used for drawing.
+
+    The example consists of the following:
+
+    \list
+        \o The \c MainWindow class inherits QMainWindow and creates
+           the examples menus and connect their slots and signals.
+	\o The \c TabletCanvas class inherits QWidget and 
+	   receives tablet events. It uses the events to paint on a
+           offscreen pixmap, which it draws onto itself.
+	\o The \c TabletApplication class inherits QApplication. This
+	   class handles tablet events that are not sent to \c tabletEvent(). 
+	   We will look at this later.
+	\o The \c main() function creates a \c MainWindow and shows it
+	   as a top level window.
+    \endlist
+
+
+    \section1 MainWindow Class Definition
+
+    The \c MainWindow creates a \c TabletCanvas and sets it as its 
+    center widget. 
+
+    \snippet examples/widgets/tablet/mainwindow.h 0
+
+    The QActions let the user select if the tablets pressure and
+    tilt should change the pen width, color alpha component and color
+    saturation. \c createActions() creates all actions, and \c
+    createMenus() sets up the menus with the actions. We have one
+    QActionGroup for the actions that alter the alpha channel, color
+    saturation and line width respectively. The action groups are
+    connected to the \c alphaActionTriggered(), \c
+    colorSaturationActiontriggered(), and \c
+    lineWidthActionTriggered() slots, which calls functions in \c
+    myCanvas.
+
+
+    \section1 MainWindow Class Implementation
+
+    We start width a look at the constructor \c MainWindow():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 0
+
+    In the constructor we create the canvas, actions, and menus.
+    We set the canvas as the center widget. We also initialize the
+    canvas to match the state of our menus and start drawing with a
+    red color.
+
+    Here is the implementation of \c brushColorAct():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 1
+
+    We let the user pick a color with a QColorDialog. If it is valid,
+    we set a new drawing color with \c setColor().
+
+    Here is the implementation of \c alphaActionTriggered():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 2
+
+    The \c TabletCanvas class supports two ways by which the alpha 
+    channel of the drawing color can be changed: tablet pressure and
+    tilt. We have one action for each and an action if the alpha
+    channel should not be changed. 
+
+    Here is the implementation of \c lineWidthActionTriggered():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 3
+
+    We check which action is selected in \c lineWidthGroup, and set
+    how the canvas should change the drawing line width.
+
+    Here is the implementation of \c saturationActionTriggered():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 4
+
+    We check which action is selected in \c colorSaturationGroup, and
+    set how the canvas should change the color saturation of the
+    drawing color.
+
+    Here is the implementation of \c saveAct():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 5
+
+    We use the QFileDialog to let the user select a file to save the
+    drawing in. It is the \c TabletCanvas that save the drawing, so we
+    call its \c saveImage() function.
+
+    Here is the implementation of \c loadAct():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 6
+
+    We let the user select the image file to be opened with
+    a QFileDialog; we then ask the canvas to load the image with \c
+    loadImage().
+
+    Here is the implementation of \c aboutAct():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 7
+
+    We show a message box with a short description of the example. 
+
+    \c createActions() creates all actions and action groups of
+    the example. We look at the creation of one action group and its
+    actions. See the \l{Application Example}{application example} if
+    you want a high-level introduction to QActions. 
+
+    Here is the implementation of \c createActions:
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 8
+    \dots
+    \snippet examples/widgets/tablet/mainwindow.cpp 9
+
+    We want the user to be able to choose if the drawing color's
+    alpha component should be changed by the tablet pressure or tilt.
+    We have one action for each choice and an action if the alpha
+    channel is not to be changed, i.e, the color is opaque. We make
+    the actions checkable; the \c alphaChannelGroup will then ensure
+    that only one of the actions are checked at any time. The \c
+    triggered() signal is emitted when an action is checked.
+
+    \dots
+    \snippet examples/widgets/tablet/mainwindow.cpp 10
+
+    Here is the implementation of \c createMenus():
+
+    \snippet examples/widgets/tablet/mainwindow.cpp 11
+
+    We create the menus of the example and add the actions to them.
+
+
+    \section1 TabletCanvas Class Definition
+
+    The \c TabletCanvas class provides a surface on which the
+    user can draw with a tablet. 
+
+    \snippet examples/widgets/tablet/tabletcanvas.h 0
+
+    The canvas can change the alpha channel, color saturation,
+    and line width of the drawing. We have one enum for each of
+    these; their values decide if it is the tablet pressure or tilt
+    that will alter them. We keep a private variable for each, the \c
+    alphaChannelType, \c colorSturationType, and \c penWidthType,
+    which we provide access functions for. 
+
+    We draw on a QPixmap with \c myPen and \c myBrush using \c
+    myColor. The \c saveImage() and \c loadImage() saves and loads
+    the QPixmap to disk. The pixmap is drawn on the widget in \c
+    paintEvent(). The \c pointerType and \c deviceType keeps the type
+    of pointer, which is either a pen or an eraser, and device
+    currently used on the tablet, which is either a stylus or an
+    airbrush.
+
+    The interpretation of events from the tablet is done in \c
+    tabletEvent(); \c paintPixmap(), \c updateBrush(), and \c
+    brushPattern() are helper functions used by \c tabletEvent().
+
+
+    \section1 TabletCanvas Class Implementation
+
+    We start with a look at the constructor:
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 0
+
+    In the constructor we initialize our class variables. We need
+    to draw the background of our pixmap, as the default is gray.
+
+    Here is the implementation of \c saveImage():
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 1
+
+    QPixmap implements functionality to save itself to disk, so we
+    simply call \l{QPixmap::}{save()}.
+
+    Here is the implementation of \c loadImage():
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 2
+
+    We simply call \l{QPixmap::}{load()}, which loads the image in \a
+    file.
+
+    Here is the implementation of \c tabletEvent():
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 3
+
+    We get three kind of events to this function: TabletPress,
+    TabletRelease, and TabletMove, which is generated when a device
+    is pressed down on, leaves, or moves on the tablet. We set the \c
+    deviceDown to true when a device is pressed down on the tablet;
+    we then know when we should draw when we receive move events. We
+    have implemented the \c updateBrush() and \c paintPixmap() helper
+    functions to update \c myBrush and \c myPen after the state of \c
+    alphaChannelType, \c colorSaturationType, and \c lineWidthType.
+
+    Here is the implementation of \c paintEvent():
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 4
+
+    We simply draw the pixmap to the top left of the widget.
+
+    Here is the implementation of \c paintPixmap():
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 5
+
+    In this function we draw on the pixmap based on the movement of the
+    device. If the device used on the tablet is a stylus we want to draw a
+    line between the positions of the stylus recorded in \c polyLine. We
+    also assume that this is a reasonable handling of any unknown device,
+    but update the statusbar with a warning so that the user can see that
+    for his tablet he might have to implement special handling.
+    If it is an airbrush we want to draw a circle of points with a
+    point density based on the tangential pressure, which is the position
+    of the finger wheel on the airbrush. We use the Qt::BrushStyle to
+    draw the points as it has styles that draw points with different
+    density; we select the style based on the tangential pressure in
+    \c brushPattern().
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 6
+
+    We return a brush style with a point density that increases with
+    the tangential pressure.
+
+    In \c updateBrush() we set the pen and brush used for drawing
+    to match \c alphaChannelType, \c lineWidthType, \c
+    colorSaturationType, and \c myColor. We will examine the code to
+    set up \c myBrush and \c myPen for each of these variables:
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 7
+
+    We fetch the current drawingcolor's hue, saturation, value,
+    and alpha values. \c hValue and \c vValue are set to the
+    horizontal and vertical tilt as a number from 0 to 255. The
+    original values are in degrees from -60 to 60, i.e., 0 equals
+    -60, 127 equals 0, and 255 equals 60 degrees. The angle measured
+    is between the device and the perpendicular of the tablet (see
+    QTabletEvent for an illustration).
+         
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 8
+
+    The alpha channel of QColor is given as a number between 0
+    and 255 where 0 is transparent and 255 is opaque.
+    \l{QTabletEvent::}{pressure()} returns the pressure as a qreal
+    between 0.0 and 1.0. By subtracting 127 from the tilt values and
+    taking the absolute value we get the smallest alpha values (i.e.,
+    the color is most transparent) when the pen is perpendicular to
+    the tablet. We select the largest of the vertical and horizontal
+    tilt value. 
+ 
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 9
+
+    The colorsaturation is given as a number between 0 and 255. It is
+    set with \l{QColor::}{setHsv()}. We can set the tilt values
+    directly, but must multiply the pressure to a number between 0 and
+    255.
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 10
+
+    The width of the pen increases with the pressure. When the pen
+    width is controlled with the tilt we let the width increse with
+    the angle between the device and the perpendicular of the tablet.
+
+    \snippet examples/widgets/tablet/tabletcanvas.cpp 11
+   
+    We finally check wether the pointer is the stylus or the eraser.
+    If it is the eraser, we set the color to the background color of
+    the pixmap an let the pressure decide the pen width, else we set
+    the colors we have set up previously in the function.
+
+
+    \section1 TabletApplication Class Definition
+
+    We inherit QApplication in this class because we want to
+    reimplement the \l{QApplication::}{event()} function. 
+
+    \snippet examples/widgets/tablet/tabletapplication.h 0
+
+    We keep a \c TabletCanvas we send the device type of the events we
+    handle in the \c event() function to. The TabletEnterProximity
+    and TabletLeaveProximity events are not sendt to the QApplication
+    object, while other tablet events are sendt to the QWidget's
+    \c event(), which sends them on to \l{QWidget::}{tabletEvent()}.
+    Since we want to handle these events we have implemented \c 
+    TabletApplication.
+
+
+    \section1 TabletApplication Class Implementation
+
+    Here is the implementation of \c event():
+
+    \snippet examples/widgets/tablet/tabletapplication.cpp 0
+
+    We use this function to handle the TabletEnterProximity and
+    TabletLeaveProximity events, which is generated when a device
+    enters and leaves the proximity of the tablet. The intended use of these
+    events is to do work that is dependent on what kind of device is
+    used on the tablet. This way, you don't have to do this work
+    when other events are generated, which is more frequently than the
+    leave and enter proximity events. We call \c setTabletDevice() in 
+    \c TabletCanvas.
+
+    \section1 The \c main() function
+
+    Here is the examples \c main() function:
+
+    \snippet examples/widgets/tablet/main.cpp 0
+
+    In the \c main() function we create a \c MainWinow and display it
+    as a top level window. We use the \c TabletApplication class. We
+    need to set the canvas after the application is created. We cannot
+    use classes that implement event handling before an QApplication
+    object is instantiated.
+*/