summaryrefslogtreecommitdiffstats
path: root/doc/src
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2010-05-04 00:09:14 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2010-05-04 00:09:14 (GMT)
commit536d0f141a13474122f99daf98bf6b54e635b474 (patch)
tree7f0219f0625f20b2678c344f6c5e97dff3bc8a59 /doc/src
parente0c8fc977738ca4ac6d31e45bdd2aa1b32828f54 (diff)
parentbec679624c642fb9914c8c43672c249ab0c1ab4c (diff)
downloadQt-536d0f141a13474122f99daf98bf6b54e635b474.zip
Qt-536d0f141a13474122f99daf98bf6b54e635b474.tar.gz
Qt-536d0f141a13474122f99daf98bf6b54e635b474.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt into 4.7
Conflicts: src/declarative/graphicsitems/qdeclarativeitem.cpp
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/classes.qdoc4
-rw-r--r--doc/src/examples/dragdroprobot.qdoc334
-rw-r--r--doc/src/examples/elasticnodes.qdoc391
-rw-r--r--doc/src/getting-started/examples.qdoc4
-rw-r--r--doc/src/getting-started/installation.qdoc203
-rw-r--r--doc/src/platforms/platform-notes.qdoc29
-rw-r--r--doc/src/snippets/code/doc_src_installation.qdoc86
7 files changed, 1028 insertions, 23 deletions
diff --git a/doc/src/classes.qdoc b/doc/src/classes.qdoc
index 6ba31a2..1552f56 100644
--- a/doc/src/classes.qdoc
+++ b/doc/src/classes.qdoc
@@ -59,7 +59,7 @@
/*!
\page classes.html
- \title All Qt Classes (main index)
+ \title All Qt Classes
\ingroup classlists
\brief If you know the name of the class you want, find it here.
@@ -146,7 +146,7 @@
/*!
\page functions.html
- \title All Functions (main index)
+ \title All Functions
\ingroup funclists
\brief All documented Qt functions listed alphabetically with a
diff --git a/doc/src/examples/dragdroprobot.qdoc b/doc/src/examples/dragdroprobot.qdoc
index 413f190..887b254 100644
--- a/doc/src/examples/dragdroprobot.qdoc
+++ b/doc/src/examples/dragdroprobot.qdoc
@@ -43,9 +43,337 @@
\example graphicsview/dragdroprobot
\title Drag and Drop Robot Example
- This GraphicsView example shows how to implement drag and drop in
- a QGraphicsItem subclass, as well as how to animate items using
- QGraphicsItemAnimation and QTimeLine.
+ This GraphicsView example shows how to implement Drag and Drop in a
+ QGraphicsItem subclass, as well as how to animate items using Qt's
+ \l{Animation Framework}.
\image dragdroprobot-example.png
+
+ Graphics View provides the QGraphicsScene class for managing and
+ interacting with a large number of custom-made 2D graphical items derived
+ from the QGraphicsItem class, and a QGraphicsView widget for visualizing
+ the items, with support for zooming and rotation.
+
+ This example consists of a \c Robot class, a \c ColorItem class, and a main
+ function: the \c Robot class describes a simple robot consisting of several
+ \c RobotPart derived limbs, including \c RobotHead and \c RobotLimb, the \c
+ ColorItem class provides a draggable colored ellipse, and the \c main()
+ function provides the main application window.
+
+ We will first review the \c Robot class to see how to assemble the
+ different parts so that they can be individually rotated and animated using
+ QPropertyAnimation, and we will then review the \c ColorItem class to
+ demonstrate how to implement Drag and Drop between items. Finally we will
+ review the main() function to see how we can put all the pieces together,
+ to form the final application.
+
+ \section1 Robot Class Definition
+
+ The robot consists of three main classes: the \c RobotHead, the \c
+ RobotTorso, and the \c RobotLimb, which is used for the upper and lower
+ arms and legs. All parts derive from the \c RobotPart class, which in turn
+ inherits \c QGraphicsObject. The \c Robot class itself has no visual
+ appearance and serves only as a root node for the robot.
+
+ Let's start with the \c RobotPart class declaration.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.h 0
+
+ This base class inherits QGraphicsObject. QGraphicsObject provides signals
+ and slots through inheriting QObject, and it also declares QGraphicsItem's
+ properties using Q_PROPERTY, which makes the properties accessible for
+ QPropertyAnimation.
+
+ RobotPart also implements the three most important event handlers for
+ accepting drop events:
+ \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()},
+ \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()}, and
+ \l{QGraphicsItem::dropEvent()}{dropEvent()}.
+
+ The color is stored as a member variable, along with the \c dragOver
+ variable, which we will use later to indicate visually that the limb can
+ accept colors that are is dragged onto it.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 0
+
+ \c RobotPart's constructor initializes the dragOver member and sets the
+ color to Qt::lightGray. In the constructor body we enable support for
+ accepting drop events by calling
+ \l{QGraphicsItem::setAcceptDrops()}{setAcceptDrops(true)}.
+
+ The rest of this class's implementation is to support Drag and Drop.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 1
+
+ The \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} handler is called
+ when a Drag and Drop element is dragged into the robot part's area.
+
+ The handler implementation determines whether or not this item as a whole
+ can accept the mime data assiciated with the incoming drag object. \c
+ RobotPart provides a base behavior for all parts that accepts color drops.
+ So if the incoming drag object contains a color, the event is accepted, we
+ set \c dragOver to \c true and call update() to help provide positive
+ visual feedback to the user; otherwise the event is ignored, which in turn
+ allows the event to propagate to parent elements.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 2
+
+ The \l{QGraphicsItem::dragLeaveEvent()}{dragLeaveEvent()} handler is called
+ when a Drag and Drop element is dragged away from the robot part's area.
+ Our implementation simply resets \e dragOver to false and calls
+ \l{QGraphicsItem::update()}{update()} to help provide visual feedback that
+ the drag has left this item.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 3
+
+ The \l{QGraphicsItem::dropEvent()}{dropEvent()} handler is called when a
+ Drag and Drop element is dropped onto an item (i.e., when the mouse button
+ is released over the item while dragging).
+
+ We reset \c dragOver to false, assign the item's new color, and call
+ \l{QGraphicsItem::update()}{update()}.
+
+ The declaration and implementation of \c RobotHead, \c RobotTorso, and \c
+ RobotLimb are practically identical. We will review \c RobotHead in detail,
+ as this class has one minor difference, and leave the other classes as an
+ exercise for the reader.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.h 1
+
+ The \c RobotHead class inherits \c RobotPart and provides the necessary
+ implementations of \l{QGraphicsItem::boundingRect()}{boundingRect()} and
+ \l{QGraphicsItem::paint()}{paint()}. It also reimplements
+ \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()} and dropEvent() to
+ provide special handling of image drops.
+
+ The class contains a private pixmap member that we can use to implement
+ support for accepting image drops.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 4
+
+ \c RobotHead has a rather plain constructor that simply forwards to
+ \c RobotPart's constructor.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 5
+
+ The \l{QGraphicsItem::boundingRect()}{boundingRect()} reimplementation
+ returns the extents for the head. Because we want the center of rotation to
+ be the bottom center of the item, we have chosen a bounding rectangle that
+ starts at (-15, -50) and extends to 30 units wide and 50 units tall. When
+ rotating the head, the "neck" will stay still while the top of the head
+ tilts from side to side.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 6
+
+ In \l{QGraphicsItem::paint()}{paint()} we draw the actual head. The
+ implementation is split into two sections; if an image has been dropped
+ onto the head, we draw the image, otherwise we draw a round rectangular
+ robot head with simple vector graphics.
+
+ For performance reasons, depending on the complexity of what is painted, it
+ can often be faster to draw the head as an image rather than using a
+ sequence of vector operations.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 7
+
+ The robot head can accept image drops. In order to support this, its
+ reimplementation of \l{QGraphicsItem::dragEnterEvent()}{dragEnterEvent()}
+ checks if the drag object contains image data, and if it does, then the
+ event is accepted. Otherwise we fall back to the base \c RobotPart
+ implementation.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 8
+
+ To follow up on image support, we must also implement
+ \l{QGraphicsItem::dropEvent()}{dropEvent()}. We check if the drag object
+ contains image data, and if it does, we store this data as a member pixmap
+ and call \l{QGraphicsItem::update()}{update()}. This pixmap is used inside
+ the \l{QGraphicsItem::paint()}{paint()} implementation that we reviewed
+ before.
+
+ \c RobotTorso and \c RobotLimb are similar to \c RobotHead, so let's
+ skip directly to the \c Robot class.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.h 4
+
+ The \c Robot class also inherits \c RobotPart, and like the other parts it
+ also implements \l{QGraphicsItem::boundingRect()}{boundingRect()} and
+ \l{QGraphicsItem::paint()}{paint()}. It provides a rather special
+ implementation, though:
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 9
+
+ Because the \c Robot class is only used as a base node for the rest of the
+ robot, it has no visual representation. Its
+ \l{QGraphicsItem::boundingRect()}{boundingRect()} implementation can
+ therefore return a null QRectF, and its paint() function does nothing.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 10
+
+ The constuctor starts by setting the flag
+ \l{QGraphicsItem::ItemHasNoContents}{ItemHasNoContents}, which is a minor
+ optimization for items that have no visual appearance.
+
+ We then construct all the robot parts (head, torso, and upper/lower arms
+ and legs). The stacking order is very important, and we use the
+ parent-child hierarchy to ensure the elements rotate and move properly. We
+ construct the torso first, as this is the root element. We then construct
+ the head and pass the torso to \c HeadItem's constructor. This will make
+ the head a child of the torso; if you rotate the torso, the head will
+ follow. The same pattern is applied to the rest of the limbs.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 11
+
+ Each robot part is carefully positioned. For example, the upper left arm is
+ moved precisely to the top-left area of the torso, and the upper right arm
+ is moved to the top-right area.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 12
+
+ The next section creates all animation objects. This snippet shows the two
+ animations that operate on the head's scale and rotation. The two
+ QPropertyAnimation instances simply set the object, property, and
+ respective start and end values.
+
+ All animations are controlled by one top-level parallel animation group.
+ The scale and rotation animations are added to this group.
+
+ The rest of the animations are defined in a similar way.
+
+ \snippet examples/graphicsview/dragdroprobot/robot.cpp 13
+
+ Finally we set an easing curve and duration on each animation, ensure the
+ toplevel animation group loops forever, and start the toplevel animation.
+
+ \section1 ColorItem Class Definition
+
+ The \c ColorItem class represents a circular item that can be pressed to
+ drag colors onto robot parts.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.h 0
+
+ This class is very simple. It does not use animations, and has no need for
+ properties nor signals and slots, so to save resources, it's most natural
+ that it inherits QGraphicsItem (as opposed to QGraphicsObject).
+
+ It declares the mandatory \l{QGraphicsItem::boundingRect()}{boundingRect()}
+ and \l{QGraphicsItem::paint()}{paint()} functions, and adds
+ reimplementations of
+ \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()},
+ \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()}, and
+ \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()}. It contains a
+ single private color member.
+
+ Let's take a look at its implementation.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 0
+
+ \c ColorItem's constructor assigns an opaque random color to its color
+ member by making use of qrand(). For improved usability, it assigns a
+ tooltip that provides a useful hint to the user, and it also sets a
+ suitable cursor. This ensures that the cursor will chance to
+ Qt::OpenHandCursor when the mouse pointer hovers over the item.
+
+ Finally, we call
+ \l{QGraphicsItem::setAcceptedMouseButtons()}{setAcceptedMouseButtons()} to
+ ensure that this item can only process Qt::LeftButton. This simplifies the
+ mouse event handlers greatly, as we can always assume that only the left
+ mouse button is pressed and released.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 1
+
+ The item's bounding rect is a fixed 30x30 units centered around the item's
+ origin (0, 0), and adjusted by 0.5 units in all directions to allow a
+ scalable pen to draw its outline. For a final visual touch the bounds
+ also compensate with a few units down and to the right to make room
+ for a simple dropshadow.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 2
+
+ The \l{QGraphicsItem::paint()}{paint()} implementation draws an ellipse
+ with a 1-unit black outline, a plain color fill, and a dark gray
+ dropshadow.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 3
+
+ The \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()} handler is
+ called when you press the mouse button inside the item's area. Our
+ implementation simply sets the cursor to Qt::ClosedHandCursor.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 4
+
+ The \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()} handler is
+ called when you release the mouse button after having pressed it inside an
+ item's area. Our implementation sets the cursor back to Qt::OpenHandCursor.
+ The mouse press and release event handlers together provide useful visual
+ feedback to the user: when you move the mouse pointer over a \c CircleItem,
+ the cursor changes to an open hand. Pressing the item will show a closed
+ hand cursor. Releasing will restore to an open hand cursor again.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 5
+
+ The \l{QGraphicsItem::mouseMoveEvent()}{mouseMoveEvent()} handler is called
+ when you move the mouse around after pressing the mouse button inside the
+ \c ColorItem's area. This implementation provides the most important piece
+ of logic for \c CircleItem: the code that starts and manages drags.
+
+ The implementation starts by checking if the mouse has been dragged far
+ enough to eliminate mouse jitter noise. We only want to start a drag if the
+ mouse has been dragged farther than the application start drag distance.
+
+ Continuing, we create a QDrag object, passing the event
+ \l{QGraphicsSceneEvent::widget()}{widget} (i.e., the QGraphicsView
+ viewport) to its constructor. Qt will ensure that this object is deleted at
+ the right time. We also create a QMimeData instance that can contain our
+ color or image data, and assign this to the drag object.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 6
+
+ This snippet has a somewhat random outcome: once in a while, a special
+ image is assigned to the drag object's mime data. The pixmap is also
+ assiged as the drag object's pixmap. This will ensure that you can see the
+ image that is being dragged as a pixmap under the mouse cursor.
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 7
+
+ Otherwise, and this is the most common outcome, a simple color is assigned
+ to the drag object's mime data. We render this \c ColorItem into a new
+ pixmap to give the user visual feedback that the color is being "dragged".
+
+ \snippet examples/graphicsview/dragdroprobot/coloritem.cpp 8
+
+ Finally we execute the drag. QDrag::exec() will reenter the event loop, and
+ only exit if the drag has either been dropped, or canceled. In any case we
+ reset the cursor to Qt::OpenHandCursor.
+
+ \section1 The main() Function
+
+ Now that the \c Robot and \c ColorItem classes are complete, we can put all
+ the pieces together inside the main() function.
+
+ \snippet examples/graphicsview/dragdroprobot/main.cpp 0
+
+ We start off by constructing QApplication, and initializing the random
+ number generator. This ensures that the color items have different colors
+ every time the application starts.
+
+ \snippet examples/graphicsview/dragdroprobot/main.cpp 1
+
+ We construct a fixed size scene, and create 10 \c ColorItem instances
+ arranged in a circle. Each item is added to the scene.
+
+ In the center of this circle we create one \c Robot instance. The
+ robot is scaled and moved up a few units. It is then added to the scene.
+
+ \snippet examples/graphicsview/dragdroprobot/main.cpp 2
+
+ Finally we create a QGraphicsView window, and assign the scene to it.
+
+ For increased visual quality, we enable antialiasing. We also choose to use
+ bounding rectangle updates to simplify visual update handling.
+ The view is given a fixed sand-colored background, and a window title.
+
+ We then show the view. The animations start immediately after
+ control enters the event loop.
*/
+
diff --git a/doc/src/examples/elasticnodes.qdoc b/doc/src/examples/elasticnodes.qdoc
index f7b1c37..edc62d8 100644
--- a/doc/src/examples/elasticnodes.qdoc
+++ b/doc/src/examples/elasticnodes.qdoc
@@ -43,7 +43,396 @@
\example graphicsview/elasticnodes
\title Elastic Nodes Example
- This GraphicsView example shows how to implement edges between nodes in a graph.
+ This GraphicsView example shows how to implement edges between nodes in a
+ graph, with basic interaction. You can click to drag a node around, and
+ zoom in and out using the mouse wheel or the keyboard. Hitting the space
+ bar will randomize the nodes. The example is also resolution independent;
+ as you zoom in, the graphics remain crisp.
\image elasticnodes-example.png
+
+ Graphics View provides the QGraphicsScene class for managing and
+ interacting with a large number of custom-made 2D graphical items derived
+ from the QGraphicsItem class, and a QGraphicsView widget for visualizing
+ the items, with support for zooming and rotation.
+
+ This example consists of a \c Node class, an \c Edge class, a \c
+ GraphWidget test, and a \c main function: the \c Node class represents
+ draggable yellow nodes in a grid, the \c Edge class represents the lines
+ between the nodes, the \c GraphWidget class represents the application
+ window, and the \c main() function creates and shows this window, and runs
+ the event loop.
+
+ \section1 Node Class Definition
+
+ The \c Node class serves three purposes:
+
+ \list
+ \o Painting a yellow gradient "ball" in two states: sunken and raised.
+ \o Managing connections to other nodes.
+ \o Calculating forces pulling and pushing the nodes in the grid.
+ \endlist
+
+ Let's start by looking at the \c Node class declaration.
+
+ \snippet examples/graphicsview/elasticnodes/node.h 0
+
+ The \c Node class inherits QGraphicsItem, and reimplements the two
+ mandatory functions \l{QGraphicsItem::boundingRect()}{boundingRect()} and
+ \l{QGraphicsItem::paint()}{paint()} to provide its visual appearance. It
+ also reimplements \l{QGraphicsItem::shape()}{shape()} to ensure its hit
+ area has an elliptic shape (as opposed to the default bounding rectangle).
+
+ For edge management purposes the node provides a simple API for adding
+ edges to a node, and for listing all connected edges.
+
+ The \l{QGraphicsItem::advance()}{advance()} reimplementation is called
+ whenever the scene's state advances by one step. The calculateForces()
+ function is called to calculate the forces that push and pull on this node
+ and its neighbors.
+
+ The \c Node class also reimplements
+ \l{QGraphicsItem::itemChange()}{itemChange()} to react to state changes (in
+ this case, position changes), and
+ \l{QGraphicsItem::mousePressEvent()}{mousePressEvent()} and
+ \l{QGraphicsItem::mouseReleaseEvent()}{mouseReleaseEvent()} to update the
+ item's visual appearance.
+
+ We will start reviewing the \c Node implementation by looking at its
+ constructor:
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 0
+
+ In the constructor, we set the
+ \l{QGraphicsItem::ItemIsMovable}{ItemIsMovable} flag to allow the item to
+ move in response to mouse dragging, and
+ \l{QGraphicsItem::ItemSendsGeometryChanges}{ItemSendsGeometryChanges} to
+ enable \l{QGraphicsItem::itemChange()}{itemChange()} notifications for
+ position and transformation changes. We also enable
+ \l{QGraphicsItem::DeviceCoordinateCache}{DeviceCoordinateCache} to speed up
+ rendering performance. To ensure that the nodes are always stacked on top
+ of edges, we finally set the item's Z value to -1.
+
+ \c Node's constructor takes a \c GraphWidget pointer and stores this as a
+ member variable. We will revisit this pointer later on.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 1
+
+ The addEdge() function adds the input edge to a list of attached edges. The
+ edge is then adjusted so that the end points for the edge match the
+ positions of the source and destination nodes.
+
+ The edges() function simply returns the list of attached edges.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 2
+
+ The \e calculateForces() function implements the elastic forces effect that
+ pulls and pushes on nodes in the grid. In addition to this algorithm, the
+ user can move one node around with the mouse. Because we do not want the
+ two to interfere, we start by checking if this \c Node is the current mouse
+ grabber item (i.e., QGraphicsScene::mouseGrabberItem()). Because we need to
+ find all neighboring (but not necessarily connected) nodes, we also make
+ sure the item is part of a scene in the first place.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 3
+
+ The algorithm has two steps: the first is to calculate the forces that push
+ the nodes apart, and the second is to subtract the forces that pull the
+ nodes together. First we need to find all the nodes in the graph. We call
+ QGraphicsScene::items() to find all items in the scene, and then use
+ qgraphicsitem_cast() to look for \c Node instances.
+
+ We make use of \l{QGraphicsItem::mapFromItem()}{mapFromItem()} to create a
+ vector pointing from this node to each other node, in \l{The Graphics View
+ Coordinate System}{local coordinates}. We use the decomposed components of
+ this vector to determine the direction and strength of force that apply to
+ the node. The forces are added up for each node, and weighted so that the
+ closest nodes are given the strongest force. The sum of all forces are
+ stored in \e xvel (X-velocity) and \e yvel (Y-velocity).
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 4
+
+ The edges between the nodes represent the forces that pull the nodes
+ together. By visiting each edge that is connected to this node, we can use
+ a similar approach as above to find the direction and strength of all
+ forces. These forces are subtracted from \e xvel and \e yvel.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 5
+
+ In theory, the sum of pushing and pulling forces should stabilize to
+ precisely 0. In practise, however, they never do. To circumvent errors in
+ numerical precision, we simply force the sum of forces to be 0 when they
+ are less than 0.1.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 6
+
+ The final step of \e calculateForces() determines the node's new position.
+ We add the force to the node's current position. We also make sure the new
+ position stays inside of our defined boundaries. We don't actually move the
+ item in this function; that's done in a separate step, from \e advance().
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 7
+
+ The \e advance() function updates the item's current position. It is called
+ from \e GraphWidget::timerEvent(). If the node's position changed, the
+ function returns true; otherwise false is returned.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 8
+
+ The \e Node's bounding rectangle is a 20x20 sized rectangle centered around
+ its origin (0, 0), adjusted by 2 units in all directions to compensate for
+ the node's outline stroke, and by 3 units down and to the right to make
+ room for a simple drop shadow.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 9
+
+ The shape is a simple ellipse. This ensures that you must click inside the
+ node's elliptic shape in order to drag it around. You can test this effect
+ by running the example, and zooming far enough in so that the nodes become
+ very large. Without reimplementing \l{QGraphicsItem::shape()}{shape()}, the
+ item's hit area would be identical to its bounding rectangle (i.e.,
+ rectangular).
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 10
+
+ This function implements the node's painting. We start by drawing a simple
+ dark gray elliptic drop shadow at (-7, -7), that is, (3, 3) units down and
+ to the right.
+
+ We then draw an ellipse with a radial gradient fill. This fill is either
+ Qt::yellow to Qt::darkYellow when raised, or the opposite when sunken. In
+ sunken state we also shift the center and focal point by (3, 3) to
+ emphasize the impression that something has been pushed down.
+
+ Drawing filled ellipses with gradients can be quite slow, especially when
+ using complex gradients such as QRadialGradient. This is why this example
+ uses \l{QGraphicsItem::DeviceCoordinateCache}{DeviceCoordinateCache}, a
+ simple yet effective measure that prevents unnecessary redrawing.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 11
+
+ We reimplement \l{QGraphicsItem::itemChange()}{itemChange()} to adjust the
+ position of all connected edges, and to notify the scene that an item has
+ moved (i.e., "something has happened"). This will trigger new force
+ calculations.
+
+ This notification is the only reason why the nodes need to keep a pointer
+ back to the \e GraphWidget. Another approach could be to provide such
+ notification using a signal; in such case, \e Node would need to inherit
+ from QGraphicsObject.
+
+ \snippet examples/graphicsview/elasticnodes/node.cpp 12
+
+ Because we have set the \l{QGraphicsItem::ItemIsMovable}{ItemIsMovable}
+ flag, we don't need to implement the logic that moves the node according to
+ mouse input; this is already provided for us. We still need to reimplement
+ the mouse press and release handlers though, to update the nodes' visual
+ appearance (i.e., sunken or raised).
+
+ \section1 Edge Class Definition
+
+ The \e Edge class represents the arrow-lines between the nodes in this
+ example. The class is very simple: it maintains a source- and destination
+ node pointer, and provides an \e adjust() function that makes sure the line
+ starts at the position of the source, and ends at the position of the
+ destination. The edges are the only items that change continuously as
+ forces pull and push on the nodes.
+
+ Let's take a look at the class declaration:
+
+ \snippet examples/graphicsview/elasticnodes/edge.h 0
+
+ \e Edge inherits from QGraphicsItem, as it's a simple class that has no use
+ for signals, slots, and properties (compare to QGraphicsObject).
+
+ The constructor takes two node pointers as input. Both pointers are
+ mandatory in this example. We also provide get-functions for each node.
+
+ The \e adjust() function repositions the edge, and the item also implements
+ \l{QGraphicsItem::boundingRect()}{boundingRect()} and
+ \{QGraphicsItem::paint()}{paint()}.
+
+ We will now review its implementation.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 0
+
+ The \e Edge constructor initializes its arrowSize data member to 10 units;
+ this determines the size of the arrow which is drawn in
+ \l{QGraphicsItem::paint()}{paint()}.
+
+ In the constructor body, we call
+ \l{QGraphicsItem::setAcceptedMouseButtons()}{setAcceptedMouseButtons(0)}.
+ This ensures that the edge items are not considered for mouse input at all
+ (i.e., you cannot click the edges). Then, the source and destination
+ pointers are updated, this edge is registered with each node, and we call
+ \e adjust() to update this edge's start end end position.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 1
+
+ The source and destination get-functions simply return the respective
+ pointers.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 2
+
+ In \e adjust(), we define two points: \e sourcePoint, and \e destPoint,
+ pointing at the source and destination nodes' origins respectively. Each
+ point is calculated using \l{The Graphics View Coordinate System}{local
+ coordinates}.
+
+ We want the tip of the edge's arrows to point to the exact outline of the
+ nodes, as opposed to the center of the nodes. To find this point, we first
+ decompose the vector pointing from the center of the source to the center
+ of the destination node into X and Y, and then normalize the components by
+ dividing by the length of the vector. This gives us an X and Y unit delta
+ that, when multiplied by the radius of the node (which is 10), gives us the
+ offset that must be added to one point of the edge, and subtracted from the
+ other.
+
+ If the length of the vector is less than 20 (i.e., if two nodes overlap),
+ then we fix the source and destination pointer at the center of the source
+ node. In practise this case is very hard to reproduce manually, as the
+ forces between the two nodes is then at its maximum.
+
+ It's important to notice that we call
+ \l{QGraphicsItem::prepareGeometryChange()}{prepareGeometryChange()} in this
+ function. The reason is that the variables \e sourcePoint and \e destPoint
+ are used directly when painting, and they are returned from the
+ \l{QGraphicsItem::boundingRect()}{boundingRect()} reimplementation. We must
+ always call
+ \l{QGraphicsItem::prepareGeometryChange()}{prepareGeometryChange()} before
+ changing what \l{QGraphicsItem::boundingRect()}{boundingRect()} returns,
+ and before these variables can be used by
+ \l{QGraphicsItem::paint()}{paint()}, to keep Graphics View's internal
+ bookkeeping clean. It's safest to call this function once, immediately
+ before any such variable is modified.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 3
+
+ The edge's bounding rectangle is defined as the smallest rectangle that
+ includes both the start and the end point of the edge. Because we draw an
+ arrow on each edge, we also need to compensate by adjusting with half the
+ arrow size and half the pen width in all directions. The pen is used to
+ draw the outline of the arrow, and we can assume that half of the outline
+ can be drawn outside of the arrow's area, and half will be drawn inside.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 4
+
+ We start the reimplementation of \l{QGraphicsItem::paint()}{paint()} by
+ checking a few preconditions. Firstly, if either the source or destination
+ node is not set, then we return immediately; there is nothing to draw.
+
+ At the same time, we check if the length of the edge is approximately 0,
+ and if it is, then we also return.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 5
+
+ We draw the line using a pen that has round joins and caps. If you run the
+ example, zoom in and study the edge in detail, you will see that there are
+ no sharp/square edges.
+
+ \snippet examples/graphicsview/elasticnodes/edge.cpp 6
+
+ We proceed to drawing one arrow at each end of the edge. Each arrow is
+ drawn as a polygon with a black fill. The coordinates for the arrow are
+ determined using simple trigonometry.
+
+ \section1 GraphWidget Class Definition
+
+ \e GraphWidget is a subclass of QGraphicsView, which provides the main
+ window with scrollbars.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.h 0
+
+ It provides a basic constructor that initializes the scene, an \e
+ itemMoved() function to notify changes in the scene's node graph, a few
+ event handlers, a reimplementation of
+ \l{QGraphicsView::drawBackground()}{drawBackground()}, and a helper
+ function for scaling the view by mouse or keyboard.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 0
+
+ \e GraphicsWidget's constructor creates the scene, and because most items
+ move around most of the time, it sets QGraphicsScene::NoIndex. Then the
+ scene gets a fixed \l{QGraphicsScene::sceneRect}{scene rectangle}.
+ The scene is then assigned to the \e GraphWidget view.
+
+ The view enables QGraphicsView::CacheBackground to cache rendering of its
+ static and somewhat complex background. Because the graph renders a close
+ collection of small items that all move around, it's unnecessary for
+ Graphics View to waste time finding accurate update regions, so we set the
+ QGraphicsView::BoundingRectViewportUpdate viewport update mode. The default
+ would work fine, but this mode is noticably faster for this example.
+
+ To improve rendering quality, we set QPainter::Antialiasing.
+
+ The transformation anchor decides how the view should scroll when you
+ transform the view, or in our case, when we zoom in or out. We have chosen
+ QGraphicsView::AnchorUnderMouse, which centers the view on the point under
+ the mouse cursor. This makes it easy to zoom towards a point in the scene
+ by moving the mouse over it, and then rolling the mouse wheel.
+
+ Finally we give the window a minimum size that matches the scene's default
+ size, and set a suitable window title.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 1
+
+ The last part of the constructor creates the grid of nodes and edges, and
+ gives each node an initial position.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 2
+
+ \e GraphWidget is notified of node movement through this \e itemMoved()
+ function. Its job is simply to restart the main timer in case it's not
+ running already. The timer is designed to stop when the graph stabilizes,
+ and start once it's unstable again.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 3
+
+ This is \e GraphWidget's key event handler. The arrow keys move the center
+ node around, the '+' and '-' keys zoom in and out by calling \e
+ scaleView(), and the enter and space keys randomize the positions of the
+ nodes. All other key events (e.g., page up and page down) are handled by
+ QGraphicsView's default implementation.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 4
+
+ The timer event handler's job is to run the whole force calculation
+ machinery as a smooth animation. Each time the timer is triggered, the
+ handler will find all nodes in the scene, and call \e
+ Node::calculateForces() on each node, one at a time. Then, in a final step
+ it will call \e Node::advance() to move all nodes to their new positions.
+ By checking the return value of \e advance(), we can decide if the grid
+ stabilized (i.e., no nodes moved). If so, we can stop the timer.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 5
+
+ In the wheel event handler, we convert the mouse wheel delta to a scale
+ factor, and pass this factor to \e scaleView(). This approach takes into
+ account the speed that the wheel is rolled. The faster you roll the mouse
+ wheel, the faster the view will zoom.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 6
+
+ The view's background is rendered in a reimplementation of
+ QGraphicsView::drawBackground(). We draw a large rectangle filled with a
+ linear gradient, with a drop shadow, and then render text in top. The text
+ is rendered twice to give a similar simple drop-shadow effect.
+
+ This background rendering is quite expensive; this is why the view enables
+ QGraphicsView::CacheBackground.
+
+ \snippet examples/graphicsview/elasticnodes/graphwidget.cpp 7
+
+ The \e scaleView() helper function checks that the scale factor stays
+ within certain limits (i.e., you cannot zoom too far in nor too far out),
+ and then applies this scale.
+
+ \section1 The main() Function
+
+ In contrast to the complexity of the rest of this example, the \e main()
+ function is very simple: We create a QApplication instance, seed the
+ randomizer using qsrand(), and then create and show an instance of \e
+ GraphWidget. Because all nodes in the grid are moved initially, the \e
+ GraphWidget timer will start immediately after control has returned to the
+ event loop.
*/
diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc
index 071a107..542f672 100644
--- a/doc/src/getting-started/examples.qdoc
+++ b/doc/src/getting-started/examples.qdoc
@@ -649,8 +649,8 @@
\list
\o \l{graphicsview/collidingmice}{Colliding Mice}\raisedaster
\o \l{graphicsview/diagramscene}{Diagram Scene}\raisedaster
- \o \l{graphicsview/dragdroprobot}{Drag and Drop Robot}
- \o \l{graphicsview/elasticnodes}{Elastic Nodes}
+ \o \l{graphicsview/dragdroprobot}{Drag and Drop Robot}\raisedaster
+ \o \l{graphicsview/elasticnodes}{Elastic Nodes}\raisedaster
\o \l{graphicsview/portedasteroids}{Ported Asteroids}
\o \l{graphicsview/portedcanvas}{Ported Canvas}
\endlist
diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc
index 3a9d4ea..3ea351e 100644
--- a/doc/src/getting-started/installation.qdoc
+++ b/doc/src/getting-started/installation.qdoc
@@ -697,6 +697,209 @@ If you are using pre-built binaries, follow the instructions given in the
\endlist
*/
+/*! \page install-Symbian-linux.html
+\title Installing Qt on the Symbian platform using Linux (experimental)
+\ingroup installation
+\ingroup qtsymbian
+\brief How to install Qt on the Symbian platform using Linux.
+
+\note Qt for the Symbian platform has some requirements that are given in more detail
+in the \l{Qt for the Symbian platform Requirements} document. TODO list requirements like SDK here.
+
+\note \bold {This document describes how to install and configure Qt for
+the Symbian platform from scratch, using Linux as the build host.
+Qt does not come with a binary package for Linux yet, but if you want to avoid
+the full build of Qt and start developing applications right away, you can
+download drop-in binaries from here: TODO}
+
+\list 1
+
+ \o Setup the development environment
+
+ TODO Make sure your Symbian development environment is correctly installed and
+ patched as explained in the \l{Qt for the Symbian platform Requirements} document.
+
+ \o Install Qt
+
+ Uncompress the \l{http://qt.nokia.com/downloads}{downloaded} source package into the
+ directory you want Qt installed, e.g. \c{/home/user/qt/%VERSION%}.
+
+ \o Environment variables
+
+ In order to build and use Qt, the \c PATH environment variable needs
+ to be extended to fine Qt tools and also to find the Symbian platform tools:
+
+ First you need to set the \c EPOCROOT environment variable to point to the location
+ of your S60 SDK:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 36
+
+ Then you can update the PATH variable;
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 37
+
+ \o Configure Qt
+
+ To configure Qt for the Symbian platform, do:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 38
+ to build the libraries using RVCT or
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 39
+ to build the libraries using GCCE.
+
+ \o Build Qt
+
+ To build Qt for the device, type:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 40
+
+ Congratulations, Qt is now ready to use.
+
+ \o Building Qt packages for the device
+
+ To run any application or demo on a real device, you need to install it
+ on the device. To do this you first have to create a a package for the
+ device, containing the libraries:
+
+ \list A
+ \o Building a Qt package without a certificate
+
+ If you have no certificate, build a self signed Qt:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 41
+
+ The Qt libraries are built with "All -Tcb" capability, so that
+ they can support all types of applications. However, these
+ capabilities are automatically lowered if you make a selfsigned
+ package.
+
+ \o Building a Qt package with a Symbian developer certificate
+
+ If you have a symbian-signed developer certificate, specify the
+ capabilities you can sign for, for example:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 42
+ \endlist
+
+ \o Installing Qt packages to the device.
+
+ It is possible to install packages to a phone in Linux by putting
+ the package on the phone memory card and then installing manually
+ from the phone menu. However, this is tedious and will not work
+ on phones without a memory card, so the method recommended by Qt is
+ to use the App TRK tool.
+
+ \list a
+ \o Obtaining the App TRK package.
+
+ Download the package from the following location.
+
+ \list
+ \o \l{http://tools.ext.nokia.com/trk/}{Application TRK}.
+ Choose the correct installation package based on the
+ S60 version of your device
+ (\c{S60_<S60-version>_app_trk_<TRK-version>.sisx}).
+ \endlist
+
+ This package currently has to be installed by putting the
+ package on the memory card and installing from the phone
+ menu, or using a Windows PC for doing the install. However,
+ the installation only has to be done once.
+
+ \o Configuring App TRK on the phone.
+
+ When App TRK is installed, connect the phone to the PC using
+ the USB cable. Select "PCSuite" as connection type. Then run
+ App TRK on the phone, and make sure that the connection type is
+ USB. This can be changed under
+ the \c Settings menu entry. If necessary, choose \c Connect
+ from the menu.
+
+ \o Configuring the USB serial driver on the Linux system.
+
+ On Linux, phone should appear as the \c /dev/ttyUSB1 device,
+ however if you are running an old kernel, you may need to
+ force the USB module to be loaded correctly before the device
+ will appear:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 43
+
+ Note the identifier on the line where your Symbian device
+ appears. Then execute the following, using the first and
+ second part of the identifier in place of \c XXXX,
+ respectively.
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 44
+
+ The \c rmmod step may fail if the module is not already
+ loaded, but that is harmless.
+
+ \o Building the \c runonphone tool.
+
+ Note that building the \c runonphone tool requires a separate
+ installation of Qt for Linux. If there is a version of Qt
+ installed by your distribution's package mechanism, that that
+ should do fine. Some distributions separate the libraries from
+ the development setup which includes qmake. Make sure you have
+ both installed.
+
+ First make sure that the \c qmake you use is taken from the
+ Linux installation of Qt. The easiest way to make sure of this
+ is to open a new shell and run the following command:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 45
+
+ \c qmake will tell you where it is installed.
+
+ Copy the \c{%QTDIR%/tools/runonphone} folder to a place outside
+ of the Qt tree. Then go to the folder in a shell and build it:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 46
+
+ Copy the resulting executable to a folder which is in your
+ \c PATH environment variable.
+
+ \o Installing the built package onto the phone.
+
+ Return to the root of the Qt tree configured for Symbian. Then
+ install the Qt libraries by running the following:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 47
+
+ \note If the installation fails, please make sure that there is
+ no previously installed version of Qt on the phone.
+
+ Qt requires some dependent packages to be installed on the device,
+ they are shipped in the Symbian SDK and can be installed using the
+ runonphone tool as well.
+ The packages can be found in the EPOCROOT at the following locations;
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 50
+
+ \endlist
+
+ \o Running Qt demos
+
+ We've included a subset of the Qt demos in this package for you
+ to try out. An excellent starting point is the "fluidlauncher"
+ demo.
+
+ Install and run the demo by using the following commands:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 48
+
+ The same command can be used for other applications:
+
+ \snippet doc/src/snippets/code/doc_src_installation.qdoc 49
+
+ For more information about building and running Qt programs on the
+ Symbian platform, see \l{The Symbian platform - Introduction to Qt}.
+
+ We hope you will enjoy using Qt.
+
+\endlist
+
+*/
/*!
\page requirements.html
\title General Qt Requirements
diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc
index 83f2833..8f5b6a5 100644
--- a/doc/src/platforms/platform-notes.qdoc
+++ b/doc/src/platforms/platform-notes.qdoc
@@ -411,7 +411,7 @@
\section1 Source Compatibility
Qt for Symbian provides the same level of source compatibility guarantee as
- given for other platforms.  That is, a program which compiles against a given
+ given for other platforms. That is, a program which compiles against a given
version of Qt for Symbian will also compile against all future versions of the
same major release.
@@ -496,28 +496,31 @@
\section1 Required Capabilities
- Distributions of Qt are typically signed with \c{All -TCB}. What your
- application needs to be signed with in order to function with Qt depends
- on what functionality it uses:
+ The Qt libraries are typically signed with \c{All -TCB} capabilites, but
+ that does not mean your Qt application needs to be signed with the same
+ capabilities to function properly. The capabilities your application needs
+ to function properly depends on which parts of Qt you use, here is an
+ overview:
\table
- \header \o Technology
+ \header \o Module
\o Required Symbian Capability
\row \o QtCore
- \o \c PowerMgmt if applications are terminated using QProcess.
+ \o \c PowerMgmt if QProcess::kill(...) or QProcess::terminate(...) is called.
+ \row \o QtCore
+ \o \c AllFiles when \l{http://developer.symbian.org/wiki/index.php/Capabilities_%28Symbian_Signed%29/AllFiles_Capability}{accessing specific areas.}
\row \o QtNetwork
- \o NetworkServices
+ \o \c NetworkServices is basically always required for this module.
\row \o QtMultiMedia
\o \c UserEnvironment if QAudioInput is used.
\endtable
- Depending on what file paths that are accessed and how AllFiles may be
- required. Similarly, if the network is accessed indirectly through
- components such as QtXmlPatterns, QtWebkit or QtScript, the capabilities
- needs to match accordingly.
+ Note that some modules rely on other modules. If your application uses
+ QtXmlPatterns, QtWebkit or QtScript it may still require \c NetworkServices
+ \o as these modules rely on QtNetwork to go online.
- See individual classes' documentation for specifics. If a class does not
- mention Symbian capabilities, it requires none.
+ For more information see the documentation of the individual Qt classes. If
+ a class does not mention Symbian capabilities, it requires none.
\section1 Multimedia and Phonon Support
diff --git a/doc/src/snippets/code/doc_src_installation.qdoc b/doc/src/snippets/code/doc_src_installation.qdoc
index b3c9903..ac94cf7 100644
--- a/doc/src/snippets/code/doc_src_installation.qdoc
+++ b/doc/src/snippets/code/doc_src_installation.qdoc
@@ -225,10 +225,8 @@ SYMBIANBUILD_DEPENDENCYOFF=1
//! [34]
cd src\s60installs
-patch_capabilities.pl Qt_template.pkg release-armv5
make sis QT_SIS_OPTIONS=-i
cd ..\3rdparty\webkit\WebCore
-patch_capabilities.pl QtWebkit_template.pkg release-armv5
make sis QT_SIS_OPTIONS=-i
//! [34]
@@ -240,3 +238,87 @@ cd ..\3rdparty\webkit\WebCore
patch_capabilities.pl QtWebKit_template.pkg release-armv5 "ALL -Tcb -AllFiles -DRM"
make sis QT_SIS_OPTIONS=-i QT_SIS_CERTIFICATE=<certificate file> QT_SIS_KEY=<certificate key file>
//! [35]
+
+//! [36]
+EPOCROOT=/home/user/s60-sdk/
+export EPOCROOT
+//! [36]
+
+//! [37]
+PATH=/home/user/qt/%VERSION%/bin:$EPOCROOT/epoc32/tools:$PATH
+export PATH
+//! [37]
+
+//! [38]
+cd /home/user/qt/%VERSION%
+./configure -platform linux-g++ -xplatform symbian/linux-armcc -arch symbian
+//! [38]
+
+//! [39]
+cd /home/user/qt/%VERSION%
+./configure -platform linux-g++ -xplatform symbian/linux-gcce -arch symbian -no-webkit
+//! [39]
+
+//! [40]
+make
+//! [40]
+
+//! [41]
+cd src/s60installs
+make sis
+//! [41]
+
+//! [42]
+cd src/s60installs
+patch_capabilities.pl Qt_template.pkg - "ALL -Tcb -AllFiles -DRM"
+make sis QT_SIS_CERTIFICATE=<certificate file> QT_SIS_KEY=<certificate key file>
+cd ../3rdparty/webkit/WebCore
+patch_capabilities.pl QtWebKit_template.pkg - "ALL -Tcb -AllFiles -DRM"
+make sis QT_SIS_CERTIFICATE=<certificate file> QT_SIS_KEY=<certificate key file>
+//! [42]
+
+//! [43]
+lsusb
+//! [43]
+
+//! [44]
+sudo rmmod usbserial
+sudo modprobe usbserial vendor=0x0XXX product=0x0XXX
+//! [44]
+
+//! [45]
+$ qmake -version
+QMake version 2.01a
+Using Qt version 4.6.2 in /usr/lib/qt4
+//! [45]
+
+//! [46]
+cd $HOME/runonphone
+qmake
+make
+//! [46]
+
+//! [47]
+runonphone -s lib/Qt.sis
+//! [47]
+
+//! [48]
+cd demos/embedded/fluidlauncher
+runonphone -s fluidlauncher.sis fluidlauncher.exe
+//! [48]
+
+//! [49]
+cd myapp
+qmake
+make
+make sis
+runonphone -s myapp.sis myapp.exe
+//! [49]
+
+//! [50]
+nokia_plugin/openc/s60opencsis/openc_ssl_s60_1_6_ss.sis
+nokia_plugin/openc/s60opencsis/pips_s60_1_6_ss.sis
+nokia_plugin/opencpp/s60opencppsis/stdcpp_s60_1_6_ss.sis
+//! [50]
+
+