diff options
author | David Boddie <david.boddie@nokia.com> | 2011-05-11 15:35:46 (GMT) |
---|---|---|
committer | David Boddie <david.boddie@nokia.com> | 2011-05-11 15:35:46 (GMT) |
commit | 0d0165e5e2eac13ae298739d9b5baed1a5a24358 (patch) | |
tree | ca529e33887ce121856086625d8f2c91bb764b61 /doc/src/examples | |
parent | 586258bfb520452860d8ff94c2db132d6ffd9e42 (diff) | |
download | Qt-0d0165e5e2eac13ae298739d9b5baed1a5a24358.zip Qt-0d0165e5e2eac13ae298739d9b5baed1a5a24358.tar.gz Qt-0d0165e5e2eac13ae298739d9b5baed1a5a24358.tar.bz2 |
Squashed commit of changes from the 4.8-temp branch.
Diffstat (limited to 'doc/src/examples')
-rw-r--r-- | doc/src/examples/applicationicon.qdoc | 88 | ||||
-rw-r--r-- | doc/src/examples/cube.qdoc | 178 | ||||
-rw-r--r-- | doc/src/examples/elidedlabel.qdoc | 162 | ||||
-rw-r--r-- | doc/src/examples/maemovibration.qdoc | 164 | ||||
-rw-r--r-- | doc/src/examples/orientation.qdoc | 143 | ||||
-rw-r--r-- | doc/src/examples/simplewebplugin.qdoc | 181 | ||||
-rw-r--r-- | doc/src/examples/symbianvibration.qdoc | 192 | ||||
-rw-r--r-- | doc/src/examples/webftpclient.qdoc | 336 | ||||
-rw-r--r-- | doc/src/examples/webplugin.qdoc | 157 |
9 files changed, 1601 insertions, 0 deletions
diff --git a/doc/src/examples/applicationicon.qdoc b/doc/src/examples/applicationicon.qdoc new file mode 100644 index 0000000..d03bf36 --- /dev/null +++ b/doc/src/examples/applicationicon.qdoc @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! \example widgets/applicationicon + \group all-examples + \title Application Icon Example + + The example shows how to add an application icon to a mobile application. + + \image appicon_screenshot.png The icon on a Nokia XPressMusic 5800 + + \section1 Creating an icon for Maemo + + Maemo expects the icon of an application to be a 64x64 PNG image file. The + file name of the icon should be the same as the executable with a \c .png + extension. You also need a \c .desktop file that gives the window manager + hints about the application, such as name, type and icon. + + \quotefile examples/widgets/applicationicon/applicationicon.desktop + + The \c Icon field should also contain the name of the executable. On the + device, application icons are stored in the + \c /usr/share/icons/hicolor/64x64/apps directory + and desktop files in the \c /usr/share/applications/hildon directory. + + \section1 Creating an icon for Symbian + + Symbian uses Scalable Vector Graphics (SVG Tiny 1.1+) to render + application icons in the application menu. Therefore icons could be + created manually with a text editor, since SVG files are plain text with + XML syntax, but usually you would use a vector graphics program that is + able to output SVG files. Popular graphics programs such as Adobe + Illustrator or Inkscape are able to do so. + + For best results, the icon should be created on a 44x44 pixel canvas. + Otherwise the image might be scaled in unexpected ways. + + Once you have created your icon, make sure that it is stored according to + the SVG-Tiny 1.1+ standard. Inkscape, for instance, is not able to save + images that way, but there are tools that can convert general SVG files + into the Tiny format. For instance, the svg2svgt tool that is bundled with + Symbian 3rd and 5th editon SDKs under the folder s60tools can do this + conversion to some extent. Another tool to convert SVG to SVG Tiny is SVG + Pony. + + \section1 Adding the icons to the project + + Edit the .pro file and specify the ICON variable for the symbian target. + For Maemo, we need to add that the \c .desktop and icon file should be + installed. + + \quotefile examples/widgets/applicationicon/applicationicon.pro + + Currently, Qt Creator doesn't include the icon and desktop files in the + application package for Maemo, merely the executable file is included. As a + workaround for this, the files can be added manually in the Projects tab. + In the "Create Package" build step for the Maemo target, the \c .desktop + file and icon can be added to be a part of the package contents. + Unfortunately, these additions are only stored as a part of the + \c .pro.user file. This issue will be resolved in a future release of + Qt Creator. + + \image appicon_packagecontents.png Manual addition of files to the "Create Package" build step +*/ diff --git a/doc/src/examples/cube.qdoc b/doc/src/examples/cube.qdoc new file mode 100644 index 0000000..0603941 --- /dev/null +++ b/doc/src/examples/cube.qdoc @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** 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 opengl/cube + \group all-examples + \title Cube OpenGL ES 2.0 example + + The Cube OpenGL ES 2.0 example shows how to write mouse rotateable + textured 3D cube using OpenGL ES 2.0 with Qt. It shows how to handle + polygon geometries efficiently and how to write simple vertex and + fragment shader for programmable graphics pipeline. In addition it + shows how to use quaternions for representing 3D object orientation. + + This example has been written for OpenGL ES 2.0 but it works also on + desktop OpenGL because this example is simple enough and for the + most parts desktop OpenGL API is same. It compiles also without OpenGL + support but then it just shows a label stating that OpenGL support is + required. + + \image cube.png Screenshot of the Cube example running on N900 + + The example consist of two classes: + + \list + \o \c MainWidget extends QGLWidget and contains OpenGL ES 2.0 + initialization and drawing and mouse and timer event handling + \o \c GeometryEngine handles polygon geometries. Transfers polygon geometry + to vertex buffer objects and draws geometries from vertex buffer objects. + \endlist + + We'll start by initializing OpenGL ES 2.0 in \c MainWidget. + + \tableofcontents + + \section1 Initializing OpenGL ES 2.0 + + Since OpenGL ES 2.0 doesn't support fixed graphics pipeline anymore it has to + be implemented by ourselves. This makes graphics pipeline very flexible but + in the same time it becomes more difficult because user has to implement graphics + pipeline to get even the simplest example running. It also makes graphics pipeline + more efficient because user can decide what kind of pipeline is needed for the + application. + + First we have to implement vertex shader. It gets vertex data and + model-view-projection matrix (MVP) as parameters. It transforms vertex position + using MVP matrix to screen space and passes texture coordinate to + fragment shader. Texture coordinate will be automatically interpolated on polygon + faces. + + \snippet examples/opengl/cube/vshader.glsl 0 + + After that we need to implement second part of the graphics pipeline - fragment + shader. For this exercise we need to implement fragment shader that handles + texturing. It gets interpolated texture coordinate as a parameter and looks up + fragment color from the given texture. + + \snippet examples/opengl/cube/fshader.glsl 0 + + Using \c QGLShaderProgram we can compile, link and bind shader code to + graphics pipeline. This code uses Qt Resource files to access shader source code. + + \snippet examples/opengl/cube/mainwidget.cpp 3 + + The following code enables depth buffering and back face culling. + + \snippet examples/opengl/cube/mainwidget.cpp 2 + + \section1 Loading textures from Qt Resource files + + \c QGLWidget interface implements methods for loading textures from QImage to GL + texture memory. We still need to use OpenGL provided functions for specifying + the GL texture unit and configuring texture filtering options. + + \snippet examples/opengl/cube/mainwidget.cpp 4 + + \section1 Cube Geometry + + There are many ways to render polygons in OpenGL but the most efficient way is + to use only triangle strip primitives and render vertices from graphics hardware + memory. OpenGL has a mechanism to create buffer objects to this memory area and + transfer vertex data to these buffers. In OpenGL terminology these are referred + as Vertex Buffer Objects (VBO). + + \image cube_faces.png Cube faces and vertices + + This is how cube faces break down to triangles. Vertices are ordered this way + to get vertex ordering correct using triangle strips. OpenGL determines triangle + front and back face based on vertex ordering. By default OpenGL uses + counter-clockwise order for front faces. This information is used by back face + culling which improves rendering performance by not rendering back faces of the + triangles. This way graphics pipeline can omit rendering sides of the triangle that + aren't facing towards screen. + + Creating vertex buffer objects and transferring data to them is quite simple using + OpenGL provided functions. + + \snippet examples/opengl/cube/geometryengine.cpp 0 + + \snippet examples/opengl/cube/geometryengine.cpp 1 + + Drawing primitives from VBOs and telling programmable graphics pipeline how to + locate vertex data requires few steps. First we need to bind VBOs to be used. + After that we bind shader program attribute names and configure what + kind of data it has in the bound VBO. Finally we'll draw triangle + strip primitives using indices from the other VBO. + + \snippet examples/opengl/cube/geometryengine.cpp 2 + + \section1 Perspective projection + + Using \c QMatrix4x4 helper methods it's really easy to calculate perpective + projection matrix. This matrix is used to project vertices to screen space. + + \snippet examples/opengl/cube/mainwidget.cpp 5 + + \section1 Orientation of the 3D object + + Quaternions are handy way to represent orientation of the 3D object. Quaternions + involve quite complex mathematics but fortunately all the necessary mathematics + behind quaternions is implemented in \c QQuaternion. That allows us to store + cube orientation in quaternion and rotating cube around given axis is quite + simple. + + The following code calculates rotation axis and angular speed based on mouse events. + + \snippet examples/opengl/cube/mainwidget.cpp 0 + + \c QBasicTimer is used to animate scene and update cube orientation. Rotations + can be concatenated simply by multiplying quaternions. + + \snippet examples/opengl/cube/mainwidget.cpp 1 + + Model-view matrix is calculated using the quaternion and by moving world by Z axis. + This matrix is multiplied with the projection matrix to get MVP matrix for shader + program. + + \snippet examples/opengl/cube/mainwidget.cpp 6 + +*/ diff --git a/doc/src/examples/elidedlabel.qdoc b/doc/src/examples/elidedlabel.qdoc new file mode 100644 index 0000000..4c6e8e8 --- /dev/null +++ b/doc/src/examples/elidedlabel.qdoc @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** 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:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example widgets/elidedlabel + \group all-examples + \title Elided Label Example + + This example creates a widget similar to QLabel, that elides the last + visible line, if the text is too long to fit the widget's geometry. + + \image elidedlabel-example.png Elided Label example on XPressMusic 5800 + + When text of varying length has to be displayed in a uniformly sized + area, for instance within a list or grid view where all list items have the + same size, it can be useful to give the user a visual clue when not all + text is visible. QLabel can elide text that doesn't fit within it, but only + in one line. The \c ElidedLabel widget shown in this example word wraps its + text by its width, and elides the last visible line if some text is left + out. \c TestWidget gives control to the features of \c ElidedWidget and + forms the example application. + + + \section1 ElidedLabel Class Definition + + Like QLabel, \c ElidedLabel inherits from QFrame. Here's the definition of + the \c ElidedLabel class: + + + \snippet examples/widgets/elidedlabel/elidedlabel.h 0 + + The \c isElided property depends the font, text content and geometry of the + widget. Whenever any of these change, the \c elisionChanged() signal might + trigger. We cache the current elision value in \c elided, so that it + doesn't have to be recomputed every time it's asked for. + + + \section1 ElidedLabel Class Implementation + + Except for initializing the member variables, the constructor sets the size + policy to be horizontally expanding, since it's meant to fill the width of + its container and grow vertically. + + \snippet examples/widgets/elidedlabel/elidedlabel.cpp 0 + + Changing the \c content require a repaint of the widget. + + \snippet examples/widgets/elidedlabel/elidedlabel.cpp 1 + + QTextLayout is used in the \c paintEvent() to divide the \c content into + lines, that wrap on word boundaries. Each line, except the last visible + one, is drawn \c lineSpacing pixels below the previous one. The \c draw() + method of QTextLine will draw the line using the coordinate point as the + top left corner. + + \snippet examples/widgets/elidedlabel/elidedlabel.cpp 2 + + Unfortunately, QTextLayout does not elide text, so the last visible line + has to be treated differently. This last line is elided if it is too wide. + The \c drawText() method of QPainter draws the text starting from the base + line, which is \c ascecnt() pixels below the last drawn line. + + Finally, one more line is created to see if everything fit on this line. + + \snippet examples/widgets/elidedlabel/elidedlabel.cpp 3 + + If the text was elided and wasn't before or vice versa, cache it in + \c elided and emit the change. + + \snippet examples/widgets/elidedlabel/elidedlabel.cpp 4 + + + \section1 TestWidget Class Definition + + \c TestWidget is a QWidget and is the main window of the example. It + contains an \c ElidedLabel which can be resized with two QSlider widgets. + + \snippet examples/widgets/elidedlabel/testwidget.h 0 + + \section1 TestWidget Class Implementation + + The constructor initializes the whole widget. Strings of different length + are stored in \c textSamples. The user is able to switch between these. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 0 + + An \c ElidedLabel is created to contain the first of the sample strings. + The frame is made visible to make it easier to see the actual size of the + widget. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 1 + + The buttons and the elision label are created. By connecting the + \c elisionChanged() signal to the \c setVisible() slot of the \c label, + it will act as an indicator to when the text is elided or not. This signal + could, for instance, be used to make a "More" button visible, or similar. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 2 + + The \c widthSlider and \c heightSlider specify the size of the + \c elidedText. Since the y-axis is inverted, the \c heightSlider has to be + inverted to act appropriately. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 3 + + The components are all stored in a QGridLayout, which is made the layout of + the \c TestWidget. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 4 + + On the Maemo platform, windows are stuck in landscape mode by default. With + this attribute set, the window manager is aware that this window can be + rotated. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 5 + + The \c widthSlider and \c heightSlider have the exact same length as the + dimensions of the \c elidedText. The maximum value for both of them is + thus their lengths, and each tick indicates one pixel. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 6 + + The \c switchText() slot simply cycles through all the available sample + texts. + + \snippet examples/widgets/elidedlabel/testwidget.cpp 7 + + These slots set the width and height of the \c elided text, in response to + changes in the sliders. + + \section1 The \c main() Function + + The \c main() function creates an instance of \c TestWidget fullscreen and + enters the message loop. + + \snippet examples/widgets/elidedlabel/main.cpp 0 +*/ + diff --git a/doc/src/examples/maemovibration.qdoc b/doc/src/examples/maemovibration.qdoc new file mode 100644 index 0000000..280dc30 --- /dev/null +++ b/doc/src/examples/maemovibration.qdoc @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** 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:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example widgets/maemovibration + \group all-examples + \title Maemo Vibration Example + + The Maemo Vibration example shows how to tell the Maemo Mode Control Entity + (MCE) to vibrate a maemo device. + + The MCE is a system service on Maemo that, among other things, provides an + D-Bus interface to trigger vibrations. The vibrations are specified as + patterns and are defined in a system configuration file. + + The example program reads the configuration file to look for possible + vibration patterns and display a button for each. Pressing a button will + make the device vibrate accordingly, until the application closes, or + another pattern is started. + + \image maemovibration-example.png Screenshot of the Maemo Vibration Example + + The code makes use of two classes: + + \list + \o \c MceVibrator connects to the MCE service and can start a certain + vibrator pattern. It also is responsible to parse the configuration + file. + + \o \c ButtonWidget provides a button for each pattern. Pressing the button + activates the pattern in question. + \endlist + + + \section1 MceVibrator Class Definition + + \snippet examples/widgets/maemovibration/mcevibrator.h 0 + + The \c MceVibrator class inherits from QObject and provides a specialized + and Qt friendly interface to the MCE vibration facilty. The slot \c vibrate() + can be called to make the device vibrate according to a specific pattern + name. We will connect it to a signal of a \c ButtonWidget object later. The + static method \c ParsePatternNames() can be called to find out which patterns + are available to us. + + \list + \o \c mceInterface is our D-Bus handle to the MCE service. We use it to + invoke methods on the MCE request object. + + \o \c lastPatternName contains the pattern that was activated last time. We + have to keep track of this, because the last pattern has to be + deactivated before activating a new pattern. + \endlist + + + \section1 MceVibrator Class Implementation + + To connect to the service, we initialize the D-Bus interface handle. The + system header \c "mce/dbus-names.h" contains definitions of the D-Bus + service name and request object path and interface. These are passed to the + constructor of the handle, and Qt will automatically establish a connection + to it, if it is possible. + + The MCE expects us to first enable the vibrator before we can use it. This + is done with the call to the \c MCE_ENABLE_VIBRATOR D-Bus method. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 0 + + From now on we can activate vibration patterns. Each time a vibration + pattern is activated, the last pattern has to be deactivated first. In the + vibrate slot we use the MCE interface to call the activation method. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 1 + + The calls to the private method deactivate simply makes sure to deactivate + the last pattern used, if there was one. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 2 + + Calling either the activate or deactivate MCE D-Bus method with invalid + pattern names are ignored. + + Finally, the destructor disables the vibrator. When the destructor of the + MCE interface handle is called, the connection is also closed. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 3 + + The MCE configuration file contains options for many different things. We + are only interested in one line that contains the vibration patterns. It + has the following format: + + + \code + VibratorPatterns=semicolon;separated;list;of;values + \endcode + + The static method \c ParsePatternNames looks for this line and returns a + QStringList containing the values, which are the pattern names we can use. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 4 + + The helper function \c checkError() saves us some code duplication. None of the + called methods return anything of use to us, so we're only interested in + getting error messages for debugging. + + \snippet examples/widgets/maemovibration/mcevibrator.cpp 5 + + + \section1 ButtonWidget Class Definition + + \snippet examples/widgets/maemovibration/buttonwidget.h 0 + + The \c ButtonWidget class inherits from QWidget and provides the main user + interface for the application. It creates a grid of buttons, one for each + string in the stringlist passed to the constructor. Pressing a button emits + the \c clicked() signal, where the string is the text of the button that + was pressed. + + This class is taken from the QSignalMapper documentation. The only change + is the number of columns in the grid from three to two, to make the button + labels fit. + + + \section1 ButtonWidget Class Implementation + + \snippet examples/widgets/maemovibration/buttonwidget.cpp 0 + + + \section1 \c main() Function + + The main function begins with looking up the patterns available to us. + + \snippet examples/widgets/maemovibration/main.cpp 0 + + Then we create one instance of both classes, and connects the + \c ButtonWidget's clicked signal to the \c MceVibrator's \c vibrate() slot. + This works, since the button texts are the same as the pattern names. + + \snippet examples/widgets/maemovibration/main.cpp 1 +*/ diff --git a/doc/src/examples/orientation.qdoc b/doc/src/examples/orientation.qdoc new file mode 100644 index 0000000..cfe1757 --- /dev/null +++ b/doc/src/examples/orientation.qdoc @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** 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:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! \example widgets/orientation + \group all-examples + \title Orientation Example + + The example shows a simple way to use different UIs depending on the screen + orientation of a mobile device. + + \image orientation-landscape.png The UI in landscape mode + \image orientation-portrait.png The UI in portrait mode + + The screen on many mobile devices can be viewed in both portrait and + landscape orientation. The orientation can be swiched with the help of a + hardware or software trigger. Due to the often small physical screen size, + user interfaces has to be very simple and compact to stay usable, and + applications usually occupy the whole screen. Designing a user interface + that works equally well in both landscape and portrait mode is not always + possible, however, so making a different layout for each case usually pays + off. + + The example application makes use of two different UI widgets created with + the Qt Designer, one for portrait and one for landscape orientation. The + application has a widget that contains an image and the user is able to + select one of three images for it to show. In addition to the two UIs, the + application consists of a \c MainWindow class. + + \section1 Landscape UI + + If the screen is in landscape mode, the user probably holds the device with + both hands and is ready to give full attention to the application. The + landscape UI looks like this: + + \image orientation-landscape-ui.png The landscape UI + + To the left is a QWidget called \c choiceWidget, which will show the + current image, and to the right are three QRadioButton instances. The + active radio button specifies the image to show. + + \section1 Portrait UI + + When the device is in portrait mode, it usually means that the user holds + it with one hand, and can comfortably use the thumb for small amounts of + input. The layout is simpler, and is focused on consuming content. The + portrait UI looks like this: + + \image orientation-portrait-ui.png The portrait UI + + Similarly, it contains a QWidget, also called \c choiceWidget, that will + show the current image. In contrast to the landscape UI, this one doesn't + provide any controls to change the image. + + \section1 MainWindow Class Definition + + \c MainWindow inherits from QWidget and acts as the top level widget of the + application. + + \snippet examples/widgets/orientation/mainwindow.h 0 + + The \c resizeEvent() method is re-implemented, and used to check which + UI to show. The \c onRadioButtonClicked() slot is connected to the + landscape UI's radio button group and selects the current image. + + \c landscapeWidget and \c portraitWidget will contain the UI layouts. Only + one of them is visible at a time. + + \section1 MainWindow Class Implementation + + In the constructor, the widgets that will hold the UIs are created and set + up. + + \snippet examples/widgets/orientation/mainwindow.cpp 0 + + Since the exit buttons on the layouts are different from each other, both + of them have to have their \c clicked() signal connected to the \c close() + slot of the main widget. The first image is also made current with the call + to \c onRadioButtonClicked(). + + \snippet examples/widgets/orientation/mainwindow.cpp 1 + + On the Maemo platform, windows are stuck in landscape mode by default. The + application has to explicitly say that rotation is supported. + + \snippet examples/widgets/orientation/mainwindow.cpp 2 + + The \c resizeEvent() is called when the main window is first created, and + also whenever the window has been resized. If the window is shown in + full screen, this is an indication that the orientation of the screen has + changed. + + The dimensions of \c landscapeWidget is the transpose of the dimensions of + \c portraitWidget. When the orientation is known, both are set to the + (possibly transposed) size of the window. Depending on the orientation, one + widget is made visible and the other invisible. + + \snippet examples/widgets/orientation/mainwindow.cpp 3 + + When the user selects one of the radio buttons in the landscape UI, the + current image is changed. The image is displayed by specifying the + background style of the choice widget. Since both \c portrait and + \c landscape have a \c choiceWidget of their own, the change has to be + reflected in both instances. + + \snippet examples/widgets/orientation/mainwindow.cpp 4 + + Synchronizing both UIs like this might become unfeasible when there are + many things that can change. In that case it is better to make use of the + \l{Introduction to Model/View Programming}{Model-View-Controller pattern} + more extensively and share the content between both portrait and landscape + widgets. Then an interface for displaying and manipulating it can be tailor + made for both orientations. + + \section1 The \c main() Function + + The main function creates a \c MainWindow instance and shows it full + screen. + \snippet examples/widgets/orientation/main.cpp 0 +*/ diff --git a/doc/src/examples/simplewebplugin.qdoc b/doc/src/examples/simplewebplugin.qdoc new file mode 100644 index 0000000..9093b9b --- /dev/null +++ b/doc/src/examples/simplewebplugin.qdoc @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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:FDL$ +** 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 Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webkit/simplewebplugin + \title Simple Web Plugin Example + + The Simple Web Plugin example shows how to embed a regular Qt widget into a + Web page displayed using QWebView. + + \image webkit-simplewebplugin.png A table widget embedded in a Web page. + + In this example, we will show how to include Qt widgets in Web-centric user + interfaces. + + \section1 QtWebKit Basics + + QtWebKit provides integration between Qt and WebKit on two different levels. + On a low level, Qt provides widgets for Web pages to be rendered onto; on a + high level, a set of classes are provided that represent all the key + components of a Web browser. + + QWebView is a widget that is used to display Web pages, QWebPage represents + the content in a page, and QWebFrame represents an individual frame in a + Web page. The code to display a Web page is very simple: + + \snippet webkitsnippets/simple/main.cpp Using QWebView + + The widget provides fundamental Web browsing features, such as Cascading + Style Sheet and JavaScript support. Other technologies can be added to + provide a more comprehensive experience. + + \section1 Adding a Widget to a Page + + Since Qt is used to render pages, it is easy to add both standard and + custom widgets to pages. All we need is some markup to indicate where a + widget is expected in a page and a mechanism that lets us know when it + needs to be created. + + The markup used involves the \c <object> element, described in the HTML 4 + specification, which is used to include generic objects in Web pages. When + describing an object to represent a widget, there are typically three + attributes this element can have: a \c data attribute that indicates where + any relevant data can be obtained; \c width and \c height attributes can + be used to set the size of the widget on the page. + + Here's how we might describe such an object: + + \snippet examples/webkit/simplewebplugin/pages/index.html embedded object + + The mechanism used by QtWebKit to insert widgets into pages is a plugin + factory that is registered with a given WebPage instance. Factories are + subclasses of QWebPluginFactory and can be equipped to supply more than one + type of widget. + + \section1 Creating a Widget to Embed + + To demonstrate how the factory is used, we create a simple widget that can + be used to display Comma-Separated Values (CSV) files. The widget class, + \c CSVView, is just a subclass of QTableView with extra functions to set + up an internal data model. Instances of the factory class, \c CSVFactory, + are responsible for creating \c CSVView widgets and requesting data on + their behalf. + + The \c CSVFactory class is defined in the following way: + + \snippet examples/webkit/simplewebplugin/csvfactory.h plugin factory + + The public functions give a good overview of how QtWebKit will use the + factory to create widgets. We begin by looking at the factory's constructor: + + \snippet examples/webkit/simplewebplugin/csvfactory.cpp constructor + + The factory contains a network access manager which we will use to obtain + data for each of the plugin widgets created. + + The \c plugins() function is used to report information + about the kinds of widget plugins it can create; our implementation reports + the MIME type it expects and provides a description of the plugin: + + \snippet examples/webkit/simplewebplugin/csvfactory.cpp plugins + + The \c create() function is where most of the action happens. It is + called with a MIME type that describes the kind of data to be displayed, + a URL that refers to the data, and information about any additional + arguments that were specified in the Web page. We begin by checking the + basic MIME type information passed in the \c mimeType parameter, and only + continue if we recognize it. + + \snippet examples/webkit/simplewebplugin/csvfactory.cpp begin create + + We construct a view widget + using the fully-specified MIME type, which is guaranteed to be in the list of + arguments if a MIME type has been supplied. + + \snippet examples/webkit/simplewebplugin/csvfactory.cpp submit request + + Lastly, we use the network access manager to request the data specified by + the \c url parameter, connecting its \c finished() signal to the view's + \c updateModel() slot so that it can collect the data. The reply object is + intentionally created on the heap; the \c finished() signal is connected to + its \c deleteLater() slot, ensuring that Qt will dispose of it when it is no + longer needed. + + The \c CSVView class provides only minor extensions to the functionality of + QTableView, with a public slot to handle incoming data and a private + variable to record exact MIME type information: + + \snippet examples/webkit/simplewebplugin/csvview.h definition + + The constructor is simply used to record the MIME type of the data: + + \snippet examples/webkit/simplewebplugin/csvview.cpp constructor + + To save space, we will only look at parts of the \c updateModel() function, + which begins by obtaining the QNetworkReply object that caused the slot + to be invoked before checking for errors: + + \snippet examples/webkit/simplewebplugin/csvview.cpp update model begin + + Assuming that the data is correct, we need to determine whether the + CSV file includes a table header, and to find out which character encoding was + used to store the data. Both these pieces of information may be included in + the complete MIME type information, so we parse this before continuing---this + is shown in the online example code. + + \snippet examples/webkit/simplewebplugin/csvview.cpp read data begin + + Since QNetworkReply is a QIODevice subclass, the reply can be read + using a suitably configured text stream, and the data fed into a standard + model. The mechanics of this can be found in the + \l{webkit/simplewebplugin/csvview.cpp}{code listing}. Here, we skip to the + end of the function where we close the reply object and set the model on + the view: + + \snippet examples/webkit/simplewebplugin/csvview.cpp update model + + Once the reply has been read, and the model populated with data, very little + needs to be done by the plugin. Ownership of the view widget is handled + elsewhere, and we have ensured that the model will be destroyed when it is + no longer needed by making it a child object of the view. + + Let's look quickly at the \c MainWindow implementation: + + \snippet examples/webkit/simplewebplugin/mainwindow.cpp constructor + + Apart from creating and setting a factory on the QWebPage object, the + most important task is to enable Web plugins. If this global setting is not + enabled, plugins will not be used and our \c <object> elements will simply + be ignored. + + \section1 Further Reading + + The \l{Web Plugin Example} extends this example by adding a signal-slot + connection between the embedded widget and a JavaScript function in the + page. +*/ diff --git a/doc/src/examples/symbianvibration.qdoc b/doc/src/examples/symbianvibration.qdoc new file mode 100644 index 0000000..a0de236 --- /dev/null +++ b/doc/src/examples/symbianvibration.qdoc @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** 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:FDL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in a +** written agreement between you and Nokia. +** +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! \example widgets/symbianvibration + \group all-examples + \title Symbian Vibration Example + + The Symbian Vibrator example shows how to get fine-grained vibration + control on Symbian devices. + + Native Symbian APIs have to be used to enable vibration, since QtMobility + doesn't provide an interface for it yet. It is, however, planned to be + included in a future release. In anticipation for that, we make use of the + \c XQVibra class that was a part of the Mobile Extensions Technology Preview + API for Qt for Symbian. The pre-compiled libraries are no longer compatible + with Qt 4.6, but we can include the source code itself with the project. + + \image symbianvibration-example.png Screenshot of the Symbian Vibration example + + The example application divides the window into rectangles, which can be + pressed to make the device vibrate. Pressing different rectangles make the + device vibrate with different intensities. Each rectangle has a different + color and its intensity number is drawn on top of it. Moving the cursor + from one rectangle to another changes the vibration intensity to that of + the new one. Vibration stops when the mouse button has been released. It + is also possible to launch a short burst of vibration through the menu. + + The example consists of four classes: + + \list + \o \c XQVibra is the vibration interface class taken from the Mobile + Extensions for Qt for Symbian. + + \o \c XQVibraPrivate is the Symbian specific private implementation of the + vibration implementation. + + \o \c VibrationSurface is a custom widget that uses a XQVibra instance to + vibrate the device depending on where the user presses. + + \o \c MainWindow inherits from QMainWindow and contains a \c VibrationSurface + as its central widget, and also has a menu from which it is possible to + make the phone vibrate. + \endlist + + \section1 XQVibra Class Definition + + The \c XQVibra class uses the pimpl-idiom to hide the platform specific + implementation behind a common interface. Technically it would be possible + to support more target platforms, with only the addition of a private + implementation. The rest of the code would work the same, since only the + common interface is used. + + \snippet examples/widgets/symbianvibration/xqvibra.h 0 + + \c XQVibra provides a very simple interface for us to use. The interesting + part are the three slots \c start(), \c stop() and \c setIntensity(). Calling the start + method initiates vibration for the specified duration. Calling it while the + device is already vibrating causes it to stop the current one and start the + new one, even if the intensities are the same. The \c setIntensity() method + should be called before starting vibration. + + + \section1 VibrationSurface Class Definition + + \c VibrationSurface inherits from QWidget and acts like a controller for a + \c XQVibra object. It responds to mouse events and performs custom painting. + + \snippet examples/widgets/symbianvibration/vibrationsurface.h 0 + + The virtual event methods are reimplemented from QWidget. As can be seen, + there is no public programmable interface beyond what QWidget provides. + + + \section1 VibrationSurface Class Implementation + + Mouse events control the intensity of the vibration. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 0 + \codeline + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 1 + \codeline + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 2 + + Presses starts the vibration, movement changes the intensity and releases + stops the vibration. To set the right amount of vibration, the private + method \c applyIntensity() is used. It sets the vibration intensity according to + which rectangle the mouse currently resides in. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 3 + + We make sure only to change the intensity if it is different than last + time, so that the vibrator isn't stopped and restarted unnecessarily. + + The range of vibration intensity ranges from 0 to XQVibra::MaxIntensity. We + divide this range into a set of levels. The number of levels and the intensity + increase for each level are stored in two constants. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 4 + + Each rectangle has an intensity of one \c IntensityPerLevel more than the + previous one. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 5 + + The rectangles are either put in a row, if the widget's width is greater + than its height (landscape), otherwise they are put in a column (portrait). + Each rectangle's size is thus dependent on the length of the width or the + height of the widget, whichever is longer. The length is then divided by + the number of levels, which gets us either the height or the width of each + rectangle. The dx and dy specify the distance from one rectangle to the + next, which is the same as either the width or height of the rectangle. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 6 + + For each level of intensity, we draw a rectangle with increasing + brightness. On top of the rectangle a text label is drawn, specifying the + intesity of this level. We use the rectangle rect as a template for + drawing, and move it down or right at each iteration. + + The intensity is calculated by dividing the greater of the width and height + into \c NumberOfLevels slices. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 7 + + In case the widget's geometry is too small to fit all the levels, the user + interface will not work. For simplicity, we just return 0. + + When we know the axis along which the rectangles lie, we can find the one + in which the mouse cursor lie. + + \snippet examples/widgets/symbianvibration/vibrationsurface.cpp 8 + + The final clamp of the intensity value at the end is necessary in case the + mouse coordinate lies outside the widget's geometry. + + + \section1 MainWindow Class Definition + + Here's the definition of the \c MainWindow class: + + \snippet examples/widgets/symbianvibration/mainwindow.h 0 + + \c MainWindow is a top level window that uses a \c XQVibra and a + \c VibrationSurface. It also adds a menu option to the menu bar which can + start a short vibration. + + \section1 MainWindow Class Implementation + + In the \c MainWindow constructor the \c XQVibra and the \c VibrationSurface + are created. An action is added to the menu and is connected to the vibrate + slot. + + \snippet examples/widgets/symbianvibration/mainwindow.cpp 0 + + The \c vibrate() slot offers a way to invoke the vibration in case no + mouse is present on the device. + + \snippet examples/widgets/symbianvibration/mainwindow.cpp 1 + + \section1 Symbian Vibration Library + + The \c XQVibra class requires a platform library to be included. It is + included in the \c .pro file for the symbian target. + + \quotefromfile examples/widgets/symbianvibration/symbianvibration.pro + \skipto /^symbian \{/ + \printuntil /^\}/ +*/ diff --git a/doc/src/examples/webftpclient.qdoc b/doc/src/examples/webftpclient.qdoc new file mode 100644 index 0000000..469b645 --- /dev/null +++ b/doc/src/examples/webftpclient.qdoc @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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:FDL$ +** 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 Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webkit/webftpclient + \title Web FTP Client Example + + The Web FTP Client example shows how to add support for a new protocol + to QtWebKit-based applications. + + \image webkit-webftpclient.png An FTP client displaying the contents of the ftp.qt.nokia.com site. + + \section1 Introduction + + The QtWebKit module presents many ways to integrate the worlds of native + desktop and mobile applications and the Web, making it possible for + developers to extend and combine features found in Qt and WebKit to create + new ones. In this article, we examine the use of Qt's network access API + with WebKit and show how to turn QWebView into a simple FTP client. + + In the \l{Web Plugin Example}, we extended Qt's WebKit integration by + showing how to add custom widgets to Web pages. In the article, we used + QNetworkRequest to ask for content for display in a widget, and we obtained + the data returned by the server by reading from the corresponding + QNetworkReply. + + Qt's network access API is a technology that aims to replace much, but not + all, of the functionality provided by the QHttp and QFtp classes. + Although the network access API is a Qt-specific technology, the QtWebKit + module integrates this Qt technology with WebKit to enable customization of + the browser engine by Qt application developers. It also means that we can + control how the browser engine obtains and renders content. + + Since QNetworkRequest and QNetworkReply are designed to provide a reusable + abstraction for network operations, it seems obvious to use these classes + to add FTP support to browsers written using QtWebKit. To do this, we first + need to examine the network access classes before we see how the QtWebKit + module uses them to manage network operations. + + \section1 Network Access + + The central class in Qt's network access API is QNetworkAccessManager. + This class performs the work of dispatching requests to remote servers and + handling incoming replies. Applications typically construct an instance of + this class and use it for all high level network communication. + + Applications create QNetworkRequest objects, each of them specifying a URL + where the request is to be sent and containing meta-data that will be + understood by the server. Each request is dispatched by passing it to a + function in the network manager \mdash there are different functions + corresponding to different kinds of operations, such as + \l{QNetworkAccessManager::}{get()}, \l{QNetworkAccessManager::}{put()} and + \l{QNetworkAccessManager::}{post()}. Each of these functions returns a + QNetworkReply object which is used to obtain the content sent in the reply, + as well as any meta-data that describes it. + + The QtWebKit module provides the QWebPage class which represents the + content displayed in a QWebView widget. Behind the scenes, this class uses + a default network access manager to handle network communication. This + default manager works perfectly well for fetching content over HTTP from + \tt{http://} URLs, but only supports fetching of files over FTP when using + \tt{ftp://} URLs. + + Fortunately, QWebPage provides the \l{QWebPage::}{setNetworkAccessManager()} + function that allows the default manager to be replaced with one with more + features. This lets us add improved support for FTP quite easily if we can + write a new manager that supports \tt{ftp://} URLs. + + The process of replacing the manager and using a new one with an existing + QWebPage object can be broken up into three steps: + + \list 1 + \o Creating a new QNetworkAccessManager subclass. + \o Creating a new QNetworkReply subclass to deal with the FTP protocol. + \o Setting the new manager on the QWebPage. + \endlist + + Additionally, to provide a reasonable user experience, we should also handle + content that the browser engine cannot display. To do this, we create a + custom \c{Downloader} object. We will briefly return to this topic later. + + \section1 Creating a New Network Manager + + Replacing an existing network manager for a QWebPage is conceptually simple: + we subclass QNetworkAccessManager and reimplement its + \l{QNetworkAccessManager::}{createRequest()} function to check for URLs + with the \tt{ftp} scheme. However, we want to ensure that the manager uses + any existing cache and proxy settings that may have been set up for the + existing manager used by the QWebPage. + + To keep the existing proxy and cache, we give our network manager a + constructor that accepts the old manager as an argument. In the constructor, + we reuse the settings from the old manager. + + \snippet examples/webkit/webftpclient/networkaccessmanager.cpp constructor + + The \c{createRequest()} function is used to create and dispatch requests to + remote servers for each of the different kinds of operation that the API + presents to the developer. Since we are only interested in performing simple + fetches of resources using the \tt{ftp} scheme, we filter out other schemes + and other kinds of operation, delegating the task of handling these to the + default implementation. + + \snippet examples/webkit/webftpclient/networkaccessmanager.cpp create request + + Here, we construct and return an instance of the \c FtpReply class. This + class performs most of the work of handling the FTP protocol. + + \section1 Creating a Custom Reply + + The network access API is designed to be simple to use: we set up a request, + dispatch it using the network manager, and obtain a QNetworkReply object. + If we are not interested in the reply's meta-data, we can simply read the + data using its \l{QNetworkReply::}{readAll()} function because QNetworkReply + is a QIODevice subclass. + + In order to keep the API so simple, however, we need to perform some work + behind the scenes. In this case, that means that we must perform a series of + communications with the FTP server. Fortunately, we can use the existing + implementation provided by QFtp to perform the low level work. + + In the \c FtpReply class, we need to reimplement four functions in the + API to ensure that it will work correctly. These functions, + \l{QNetworkReply::}{abort()}, \l{QIODevice::}{bytesAvailable()}, + \l{QIODevice::}{isSequential()}, \l{QIODevice::}{readData()}, + rely on the rest of the implementation to fill a QByteArray with data and + use an integer offset to track how much has been read from the device by + the browser. + + \snippet examples/webkit/webftpclient/ftpreply.h class definition + + The \c{processCommand()}, \c{processListInfo} and \c{processData()} slots + handle interaction with the FTP server. The private \c{setContent()} and + \c{setListContent()} functions are used to add meta-data to the reply and + compose HTML for the browser to display. + + Two of the private variables hold information about the data obtained from + the FTP server: \c items is updated to contain information about each + file found at a given URL, and \c content contains the raw data obtained + from the server. The \c offset variable is used to track how much data has + been read by the browser from the reply. + + In the constructor, we construct a QFtp object and connect the signals and + slots that form the basis of the interaction with the FTP server. The high + level communication is reported by the \l{QFtp::}{commandFinished()} + signal. New data from the server is reported by the + \l{QFtp::}readyRead()} signal. + Individual items in an FTP directory listing are reported by the + \l{QFtp::}{listInfo()} signal. + + \snippet examples/webkit/webftpclient/ftpreply.cpp constructor + + We also initialize the \c offset into the data that represents the number + of bytes that the browser has read from the reply. Additionally, we define + a list of units for use with the \c setListContent() function. + The last two tasks performed in the constructor are to set the URL of the + reply so that the browser can tell where it came from, and to connect to + the FTP server. + + \section2 Fetching Data from the Server + + All communication with the server is handled by the \c processCommand() + slot, which acts on responses from the server and tells us when a command + we have issued has completed. + This slot performs the task of logging in to the server when connection has + occurred (the \l{QFtp::}{ConnectToHost} command has completed), asking for + a list of files when logged in (\l{QFtp::}{Login} has completed), + preparing a page with a listing when all file information has been received + (\l{QFtp::}{List} has completed), and setting the current content for the + reply when data has been fetched from the server + (\l{QFtp::}{Get} has completed). + + \snippet examples/webkit/webftpclient/ftpreply.cpp process command + + The result of the \l{QFtp::}{List} command is handled by looking at the + number of items obtained from the server. + The items themselves are recorded by the \c processListInfo() slot. When a + \l{QFtp::}{List} command is complete, we can count the number of items + received and determine whether or not we should create a file listing, or + try to fetch the file instead by invoking a \l{QFtp::}{Get} command. + + \snippet examples/webkit/webftpclient/ftpreply.cpp process list info + + Since the reply will only be used once, we can simply append items to a list + and never bother to clear it. + + The \c processData() slot simply appends data obtained from the FTP server + to the QByteArray containing the content to be supplied to the browser. + + \snippet examples/webkit/webftpclient/ftpreply.cpp process data + + Data is appended to the \c content array until the connection to the FTP + server is closed, either by the reply or by the server itself. One of the + ways in which this happens is when a \l{QFtp::}{Get} command completes. At + this point, the \c setContent() function is called from within the + \c processCommand() function. + + \snippet examples/webkit/webftpclient/ftpreply.cpp set content + + Here, we prepare the reply for use by the browser by opening it for + unbuffered reading and setting the header that reports the amount of data + held by the reply. We emit signals that indicate that the network operation + has finished and that it has data to be read. Since we are no longer + interested in the FTP server, we close the connection to it. + + \section2 Preparing Content for the Reader + + Another way in which the reply closes the connection to the server is when + the \c setListContent() function is called from the \c processCommand() + function. Most of the implementation of this function involves transforming + the information about the items held in the reply's private \c items + variable to HTML. + + \snippet examples/webkit/webftpclient/ftpreply.cpp set list content + + Once the HTML description of the files has been composed in a QString, we + convert it to a UTF-8 encoded set of bytes which we store in the reply's + private \c content variable. In this case, the QByteArray holds HTML + instead of file data. We set the reply's headers to indicate that it + contains UTF-8 encoded HTML with a certain length, and we emit the + \l{QNetworkReply::}{readyRead()} and \l{QNetworkReply::}{finished()} + signals to let the browser know that it can start reading the content. + + \section2 Supplying Data to the Browser + + We reimplement four QIODevice functions to provide basic read-only behavior, + simply supplying the data held in the \c content array. + + We do not support aborting of the reply, so our \c abort() implementation + is empty. + + \snippet examples/webkit/webftpclient/ftpreply.cpp abort + + Similarly, we do not support random access reading, so \c isSequential() + is reimplemented to always return true. + + \snippet examples/webkit/webftpclient/ftpreply.cpp is sequential + + The \c bytesAvailable() function returns the total number of bytes held by + the reply minus the value of \c offset, which is the number of bytes we + have already supplied to the reader. + + \snippet examples/webkit/webftpclient/ftpreply.cpp bytes available + + \snippet examples/webkit/webftpclient/ftpreply.cpp read data + + The \c readData() reimplementation tries to return as much data to the + reader as it will allow, copying bytes directly to the appropriate location + in memory. The \c offset variable is updated to keep track of how many + bytes have been read. + + \section1 Enabling the Protocol + + Now that we have an FTP-enabled network manager and a reply that can handle + communication with FTP servers, we can now enable the manager for a given + QWebPage. + We derive the \c FtpView class from QWebView and configure its behavior in + its constructor. + + As we mentioned earlier, we pass the original network manager to the + newly-created manager and pass the new manager to the QWebPage belonging to + the browser. This enables our network manager for the content it displays. + + \snippet examples/webkit/webftpclient/ftpview.cpp constructor + + We also go to some effort to handle content that WebKit does not natively + support, using a \c Downloader helper class to manage this and files that + the user downloads via the browser's \gui{Save Link...} context menu entry. + + In the example's \c main() function, we perform the usual steps to + initialize our Qt application. We choose an appropriate starting URL for + the \c FtpView widget to open before running the application's event loop. + + \snippet examples/webkit/webftpclient/main.cpp main + + \section1 Summary + + As we have seen, enabling support for another protocol and URL scheme in + QtWebKit is a fairly simple process involving the creation of a network + manager and custom reply object. The implementation challenges + are mostly related to how the protocol is handled by the custom + QNetworkReply subclass where, in our case, we need to issue the appropriate + commands in the correct order to obtain data from the FTP server. + + We also need to ensure that that the reply emits the appropriate signals to + inform the browser that it has content to be read. Our implementation is + intentionally simple, only notifying the browser with the + \l{QIODevice::}{readyRead()} signal when \e all the content is ready to + read and emitting the \l{QNetworkReply::}{finished()} signal to indicate + that communication is complete; a more sophisticated approach would + interleave the commands sent to the server with the emission of signals, + allowing the browser to read content as data is obtained from the FTP + server. + + The reply also needs to be open for reading. Forgetting to call the + \l{QIODevice::}{open()} function is a common error to make when dealing + with devices, but in this case it is the reply's responsibility to open + itself. + It must indicate how much content it has for the browser to read. As we + have seen, this is done by setting the reply's + \l{QNetworkRequest::}{ContentLengthHeader} header with the appropriate + value. With this information available, the browser can read from the reply + when the content becomes available, displaying a directory listing or + downloading content depending on the type of data supplied. + + We can use the approach described in this article to enable support for + other protocols by writing or extending a network manager to handle URL + schemes such as \tt mailto, \tt sip, \tt news, \tt file and \tt ldap. + Applications that integrate Web content with information from other sources + can also provide custom URL schemes as long as care is taken not to use an + existing public scheme. +*/ diff --git a/doc/src/examples/webplugin.qdoc b/doc/src/examples/webplugin.qdoc new file mode 100644 index 0000000..0410670 --- /dev/null +++ b/doc/src/examples/webplugin.qdoc @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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:FDL$ +** 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 Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of this +** file. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webkit/webplugin + \title Web Plugin Example + + The Web Plugin example shows how to communicate between a Qt widget + embedded in a Web page and the page itself. + + \image webkit-webplugin.png A table widget embedded in a Web page. + + In this example, we will take the widget described in the + \l{Simple Web Plugin Example} and show how to set up communications between + the widget and the Web environment. + + \section1 Setting up Communications + + There are two ways of interacting with the content in a Web page. The first + way involves the use of QWebElement to read and modify the page + content and structure; this is useful for certain types of application, as + demonstrated by the \l{DOM Traversal Example} and the + \l{Simple Selector Example}. + + The second way is to add Qt objects to the page, connecting their signals + to JavaScript functions, and executing the object's slots directly from + JavaScript in the page. We explore this approach in this example. + + To perform this communication, we require an updated \c CSVView widget from + the \l{Simple Web Plugin Example} that can emit a signal whenever a row is + selected, a JavaScript function to modify elements on the page, and some + glue code to make the connection. + + On the page, the plugin is declared like this: + + \snippet examples/webkit/webplugin/pages/index.html embedded object + + As in the previous example, the \c <object> definition includes information + about the data to be displayed, its location, and the dimensions of the + plugin in the page. + + Later in the document, we include a table that we will update with data + from the \c CSVView widget: + + \snippet examples/webkit/webplugin/pages/index.html table + + The \c CSVView widget is similar to the previous version. However, we + wish to obtain and export individual rows of data, so we define the + \c rowSelected() signal and \c exportRow() slot to perform this task. + + \snippet examples/webkit/webplugin/csvview.h definition + + Since we wish to obtain one row of data at a time, the constructor includes + code to restrict how the user can interact with the view: + + \snippet examples/webkit/simplewebplugin/csvview.cpp constructor + + The \c exportRow() slot provides a convenient mechanism for obtaining and + emitting the values found on the current row of the table: + + \snippet examples/webkit/webplugin/csvview.cpp export row + + This slot is connected to a signal belonging to the view's selection model: + \l{QItemSelectionModel::}{currentChanged()}. This can be seen by examining + the \c updateModel() function in the source code. + + \c exportRow() emits the \c rowSelected() signal, passing strings containing + the name, address and quantity in the current table row. To see how this + data is passed to the Web page, we need to look at the \c CSVFactory class. + + \section1 Connecting Components Together + + In the \c CSVFactory class, we reimplement the \l{QWebPluginFactory::}{create()} + function to create instances of the \c CSVView class, as in the previous + example. + + \snippet examples/webkit/webplugin/csvfactory.cpp begin create + + We also expose the view widget to the frame in the page that + contains the elements, and set up a connection between the view and a + JavaScript function defined in the page header: + + \snippet examples/webkit/webplugin/csvfactory.cpp create connection + + The view is added to the Web page as \c view, and the connection code we + evaluate performs a signal-slot connection from the view's \c rowSelected() + signal to a pure JavaScript function: + + \js + view.rowSelected.connect(fillInTable); + \endjs + + \c fillInTable is the name of the JavaScript function to modify the + form's input elements. This function expects three arguments: the name, + address and quantity values for a row of data. + + Whenever the current row changes in the \c view object, the \c exportRow() + slot is called, the data found in the selected row is extracted from the + model and emitted in the \c rowSelected() signal as three strings, and + the above connection ensures that \c fillInTable() will be called with the + current items of data. The appropriate type conversions occur behind the + scenes to ensure that each QString is converted to a JavaScript string + object. + + The rest of the function is the same as in the previous example: + + \snippet examples/webkit/webplugin/csvfactory.cpp submit request + + We now give the JavaScript \c fillInForm() function to show what it does + with the strings it is given. The function itself is defined in the HTML + page header: + + \snippet examples/webkit/webplugin/pages/index.html script + + We obtain the elements in the page that we wish to update by using the HTML + Document Object Model (DOM) API. The values of these elements are updated + with the \c name, \c address and \c quantity strings supplied. + + \section1 Linking Things Together + + Although we have used the widgets to demonstrate the use of signals and + slots for communication between Qt components and JavaScript in the browser, + we do not need to embed widgets in Web pages to be able to do this. By + inserting objects into pages and evaluating JavaScript, Qt applications can + be made to examine and process information found online. + + One additional improvement that can be made to this example is to create + a relation between the embedded widget and the table to be updated. We + could do this by including \c <param> elements within the \c <object> + element that refers to the table cells by their \c id attributes. This + would help us to avoid hard-coding the \c customers_name, + \c customers_address and \c customers_quantity identifiers in the script. +*/ |