summaryrefslogtreecommitdiffstats
path: root/src/sql/kernel
Commit message (Collapse)AuthorAgeFilesLines
* Merge remote-tracking branch 'origin/release' into stableFrederik Gladhorn2014-05-012-11/+10
|\ | | | | | | | | | | This merge adds the opengl rename. Change-Id: I84ea0b6abee9780ebb2cf3f64ab9e3fdf2acab3e
| * QSqlError: Mark deprecated functiond with QT_DEPRECATEDOlivier Goffart2014-04-252-11/+10
| | | | | | | | | | | | | | | | | | | | | | And move the default argument from the deprecated constructor to the new one Also make sure that the error number is consistent across the two constructor Change-Id: I3721266b39ab493f0add35b2d1f892b2f6094992 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
* | [QSqlQuery] misbehavior of seek in special query positionsIsrael Lins Albuquerque2014-04-261-7/+18
|/ | | | | | | | | | | | When QSqlQuery::at() == QSql::BeforeFirstRow and seek(1, true) (seek to next record) is called the expected result is go to first row. When QSqlQuery::at() == QSql::AfterLastRow and seek(-1, true) (seek to previous record) is called the expected result is go to last row. But in all cases the first and last are skipped. Change-Id: I584138b3d397ce1c790bf89688ee92289a99611c Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Fix some documentation errors.Friedemann Kleint2014-03-241-1/+1
| | | | | | | | Correct links and fix typos, remove obsolete documentation, fix some snippets, mark some classes as internal. Change-Id: I9a3266605f060783413d32740057a57a820c8929 Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
* Fix positional binding values order in QSqlQueryTobias Koenig2014-03-201-4/+9
| | | | | | | | | | | | Adapt the stringification code, that is used to produce the keys for QSqlQuery::boundValues() return value, to keep the right order of the binding values. Task-number: QTBUG-12186 Change-Id: Ic11a455bfd9ffd1418b1b021ce5cf78cae9b4504 [ChangeLog][QtSql] Fixed the order of values with positional binding in a QSqlQuery Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* expand tabs and related whitespace fixes in *.{cpp,h,qdoc}Oswald Buddenhagen2014-01-131-1/+1
| | | | | | | | the diff -w for this commit is empty. Started-by: Thiago Macieira <thiago.macieira@intel.com> Change-Id: I77bb84e71c63ce75e0709e5b94bee18e3ce6ab9e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Move struct declaration out of the union to avoid a compiler warning.Marcel Krems2013-12-311-4/+5
| | | | | | | | Clang 3.3+ warns about this being an extension: qsqlerror.h:101: warning: anonymous types declared in an anonymous union are an extension [-Wnested-anon-types] Change-Id: I0350b977ff85558338b3b9db53d3fce7facb7635 Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Remove additional spaces from indentation.Marcel Krems2013-12-311-6/+6
| | | | | Change-Id: I1f76ed4e2eff64dc133a1fd30a8dc5fd5eb4710e Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Merge remote-tracking branch 'origin/stable' into devFrederik Gladhorn2013-12-242-2/+6
|\ | | | | | | Change-Id: I2defae1904154283446b069d151c3ef57302ec7b
| * fix parsing of bound SQL statements for PostgreSQLIsrael Lins Albuquerque2013-12-162-2/+6
| | | | | | | | | | | | | | | | | | PostgreSQL allows bound variables inside square braces. Task-number: QTBUG-34541 Change-Id: I4f069b3f1078d4cdf172fbac9e0d7d23d20d167a Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Enable QSqlError to handle alphanumeric error codes.Marcel Krems2013-12-202-6/+61
| | | | | | | | | | | | | | | | | | | | Some database systems (like PostgreSQL) use alphanumeric error codes. Introduce a new method nativeErrorCode() which replaces number(). If the error code cannot be converted to int, number() will return 0. Task-number: QTBUG-142 Change-Id: Ic7fba841737674b75c0c01c2263f51d2041da497 Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Move QSqlError private members into a pimpl class.Marcel Krems2013-12-202-26/+46
| | | | | | | | | | | | | | This allows us to add new members without breaking BC. Change-Id: I59236cd5eeacdcfc490849a18b3bdf70d7a501bf Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | add mising tag to method documentationMark Brand2013-12-011-1/+1
| | | | | | | | | | Change-Id: Iafd7a268bf3b3be9a06ab1badc23e3db52df9586 Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | QSqlQuery::isNull string overloadTasuku Suzuki2013-12-012-0/+19
| | | | | | | | | | | | | | | | | | | | Introduce isNull overload to take field name as a parameter. This is corresponding to the commit 7e6e1412348fb8d8df844d821ee80d6d3de69517 Change-Id: I122f79707d26eaa09c2f38dc31aeee1dac7de33b Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Merge remote-tracking branch 'origin/stable' into devFrederik Gladhorn2013-11-261-0/+1
|\| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For the conflicts in msvc_nmake.cpp the ifdefs are extended since we need to support windows phone in the target branch while it is not there in the current stable branch (as of Qt 5.2). Conflicts: configure qmake/generators/win32/msvc_nmake.cpp src/3rdparty/angle/src/libEGL/Surface.cpp src/angle/src/common/common.pri src/corelib/global/qglobal.h src/corelib/io/qstandardpaths.cpp src/plugins/platforms/qnx/qqnxintegration.cpp src/plugins/platforms/qnx/qqnxscreeneventhandler.h src/plugins/platforms/xcb/qglxintegration.h src/widgets/kernel/win.pri tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp tools/configure/configureapp.cpp Change-Id: I00b579eefebaf61d26ab9b00046d2b5bd5958812
| * Add QSQLITE_OPEN_URI database connection flagTobias Koenig2013-11-041-0/+1
| | | | | | | | | | | | | | | | | | | | This flag enables the URI mode for database names in the SQLite backend. Without this flag, it's not possible to use URIs like 'file:somedb?mode=memory&cache=shared' to create shared, in-memory databases. Change-Id: I2938184dad1f27c7af454385ca305bd4f6ed1a5e Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Fix a bug in QSqlQuery::isNull documentationTasuku Suzuki2013-10-221-8/+9
|/ | | | | | | | the method returns true if there is not such field. Change-Id: I25db8de4561d3e0604f3e64edc1810140ba4aad2 Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Doc: Adding mark-up to boolean default values.Jerome Pasion2013-10-088-93/+93
| | | | | | | | | | | | | | | | | Default values should have mark-up to denote that they are code. This commit changes: -"property is true" to "property is \c true". -"Returns true" to "Returns \c true". -"property is false" to "property is \c false". -"returns true" to "returns \c true". -"returns false" to "returns \c false". src/3rdparty and non-documentation instances were ignored. Task-number: QTBUG-33360 Change-Id: Ie87eaa57af947caa1230602b61c5c46292a4cf4e Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
* fix off-by-one index checkMark Brand2013-07-011-1/+1
| | | | | Change-Id: I6d6461eec24895e9aa0e77deccd39210958b7e2c Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* QSqlDriver: use Q_DECLARE_PUBLIC/Q_DECLARE_PRIVATEMark Brand2013-04-043-2/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | 406c8ef6e67da introduced deriving the private SQL driver classes from QSqlDriverPrivate. However, the drivers continued to keep their own pointer to the private class, even though QObject provides the same pointer. Worse yet, the private class is allocated too late and not even passed to QSqlDriver. The result is that QSqlDriver allocates a separate instance of QSqlDriverPrivate. This is likely to cause all kinds of chaos. The private class needs to be allocated in time pass it to QSqlDriver which passes it on to QObject. This commit covers the the base class and drivers: ibase mysql odbc psql sqlite tds Fixes for the remaining drivers will follow. Change-Id: Id8e7ec4205b0ca6cd00bd022c9cd24f137089245 Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* QSqlDriverPrivate clean-upMark Brand2013-04-041-15/+10
| | | | | Change-Id: Ia6cbb37330bc0beed7498e43cd18bb2a1afb8e3d Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* Move the dbmstype to QSqlDriverPrivate so it can be used for all driversAndy Shaw2013-04-023-24/+93
| | | | | | | | | By moving it to QSqlDriverPrivate we make it easier to check what database is actually connected which is particularly useful for the autotests. Change-Id: I54d1c2c998919c1d54efb1b6ac9303070ece54aa Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* QSqlTableModel: expose methods for getting primary valuesMark Brand2013-04-022-0/+16
| | | | | | | These methods are very useful in subclasses. Change-Id: Ifdfee9d90cbdad97f349e46b587582f1d9e7cd7a Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* make QSqlResultPrivate::fieldSerial() virtualMark Brand2013-04-022-12/+7
| | | | | | | | | | | | | | | | | | | | | The Qt psql driver has its own implementation of fieldSerial() it uses when it invokes positionalToNamedBinding() to generate a query using its native naming style. Now that QPSQLResultPrivate is derived from QSqlResultPrivate this can be implemented more conventionally using a virtual function instead of pointers to static functions. Note that this change preserves the current behavior of executedQuery() which will continue to return the query with positional syntax that is presented to virtual prepare() by QSqlResult::savePrepare(). Since the driver does not have the NamedPlaceholders feature, QSqlResult::savePrepare() will not use positionaltoNamedBinding() to set executedQuery. Although QPSQLResult::prepare() calls positionaltoNamedBinding(), it does not put the result into executedQuery. Change-Id: I7740f386cbfec9eadd9e4d6a7df3e590294655a5 Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Whitespace cleanup: remove trailing whitespaceAxel Waggershauser2013-03-161-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | Remove all trailing whitespace from the following list of files: *.cpp *.h *.conf *.qdoc *.pro *.pri *.mm *.rc *.pl *.qps *.xpm *.txt *README excluding 3rdparty, test-data and auto generated code. Note A): the only non 3rdparty c++-files that still have trailing whitespace after this change are: * src/corelib/codecs/cp949codetbl_p.h * src/corelib/codecs/qjpunicode.cpp * src/corelib/codecs/qbig5codec.cpp * src/corelib/xml/qxmlstream_p.h * src/tools/qdoc/qmlparser/qqmljsgrammar.cpp * src/tools/uic/ui4.cpp * tests/auto/other/qtokenautomaton/tokenizers/* * tests/benchmarks/corelib/tools/qstring/data.cpp * util/lexgen/tokenizer.cpp Note B): in about 30 files some overlapping 'leading tab' and 'TAB character in non-leading whitespace' issues have been fixed to make the sanity bot happy. Plus some general ws-fixes here and there as asked for during review. Change-Id: Ia713113c34d82442d6ce4d93d8b1cf545075d11d Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
* QSqlResult: private d -> protected d_ptrMark Brand2013-03-062-6/+43
| | | | | | | | | This QObject-style convention will allow the usual private class macros to be used. Change-Id: I992ee2a2d2e7984d57feb4cbe785a267f2fd83ce Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* add QSqlResult constructor suitable for inheritanceMark Brand2013-03-062-0/+12
| | | | | | | | The new constructor accepts reference to the private class provided by a subclass. Change-Id: I568e31727bb90de12ee8bb7bf0ed442737056470 Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* QSqlResultPrivate: private q -> protected q_ptrMark Brand2013-03-062-3/+4
| | | | | | | | This QObject-style convention will allow the usual private class macros to be used. Change-Id: Ib1cee0b3aca949b75511868ad4914e5b8530929b Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* prepare QSqlResultPrivate() to allow subclassingMark Brand2013-03-062-6/+7
| | | | | | | | | | | | Allow the private class to be instantiated before the public class. Public subclasses will need to first instantiate the private subclass and pass the reference to QSqlResult. Add virtual constructor so QSqlResult can delete private class polymorphically. Change-Id: Ide7115dbb4150d6604677b542dbec16e6956a142 Reviewed-by: Andy Shaw <andy.shaw@digia.com>
* Rename the SQL driver header files to _p.h (make private)Thiago Macieira2013-02-261-9/+9
| | | | | | | | | | | | | The drivers were never public API. They were exposed by mistake in public headers. What's more, they have #include'd a private header (qsqlcachedresult_p.h) since at least Qt 4.5.1. That means no one used those headers in Qt 4 (private headers weren't installed then) and it's unlikely anyone did in 5.0. Change-Id: Ie0a47bcf0260ee6bdd3d8494b78fd1eec28a2d6b Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Deprecate QSqlError setters.Marcel Krems2013-02-242-13/+42
| | | | | | | | | The constructor is sufficient, since it has a parameter for each member variable. Even the drivers, which were mentioned in the class description don't use them. Change-Id: Ie8ba0467c7dc1928c539b4b19db8cc2ea0f44ea0 Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Merge remote-tracking branch 'origin/stable' into devFrederik Gladhorn2013-02-182-37/+74
|\ | | | | | | | | | | | | Conflicts: src/widgets/styles/qmacstyle_mac.mm Change-Id: If8326db9e7da3cbf45dbf7475fdff9915c7723b1
| * QSqlResult: fix parsing of bound SQL statementsIsrael Lins2013-02-151-21/+54
| | | | | | | | | | | | | | | | | | | | | | | | Parsing for bound SQL parameters now handles identifier quoting using double quotes (") and square brackets ([]). The following has only 1 bound value but previously 2 were detected: SELECT 1 AS "A?b[?']]]de?ghi", ? Task-number: QTBUG-27159 Change-Id: Icfd02187e1126ff3b5ed11df8d4e599f574e61bf Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * QSqlResultPrivate: parameterize fieldSerial function for parsingMark Brand2013-02-152-3/+8
| | | | | | | | | | | | | | Change-Id: Ibaffadec9bf9e6e0d5609b7327b369d560e8e2ce Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * QSqlResultPrivate: parameterize input query for parsingMark Brand2013-02-152-15/+15
| | | | | | | | | | | | | | Change-Id: If57f4fcea2e00a1910df5a5bd2b556289f4ffb21 Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * move qFieldSerial() to static QSqlResultPrivate::fieldSerial()Mark Brand2013-02-152-6/+5
| | | | | | | | | | | | | | Change-Id: Ic2db719437a11019262cf299929115ffa11d3d34 Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Merge remote-tracking branch 'origin/stable' into devFrederik Gladhorn2013-02-144-103/+150
|\| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: src/concurrent/doc/qtconcurrent.qdocconf src/corelib/doc/qtcore.qdocconf src/corelib/global/qglobal.h src/dbus/doc/qtdbus.qdocconf src/dbus/qdbusmessage.h src/gui/doc/qtgui.qdocconf src/gui/image/qimagereader.cpp src/network/doc/qtnetwork.qdocconf src/opengl/doc/qtopengl.qdocconf src/opengl/qgl.h src/plugins/platforms/windows/qwindowswindow.cpp src/printsupport/doc/qtprintsupport.qdocconf src/sql/doc/qtsql.qdocconf src/testlib/doc/qttestlib.qdocconf src/tools/qdoc/doc/config/qt-cpp-ignore.qdocconf src/widgets/doc/qtwidgets.qdocconf src/xml/doc/qtxml.qdocconf Change-Id: Ie9a1fa2cc44bec22a0b942e817a1095ca3414629
| * move QSqlResultPrivate to private headerMark Brand2013-02-113-68/+140
| | | | | | | | | | | | | | Change-Id: Ice5464989530d521f65703daa080cb2094afef3c Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * QSqlResult::savePrepare() simplify logicMark Brand2013-02-091-6/+5
| | | | | | | | | | | | Change-Id: If0b54a4c17f1c71c2bb33ae4d514ad6a9cc17e4c Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * QSqlResult: consolidate SQL parsing for bindingIsrael Lins2013-02-091-26/+3
| | | | | | | | | | | | | | Consolidated SQL parsing for binding values, removing repeated code. Change-Id: I77aadcfd2673b067f7deb52b826d7b5a2ba2ae2a Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * QSqlResult: note in doc about misnamed methodMark Brand2013-02-091-0/+2
| | | | | | | | | | | | Change-Id: I488a915622445527c529b35db639ec3b6e887d1d Reviewed-by: Israel Lins Albuquerque <israelins85@yahoo.com.br> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
| * remove misleading statement from ~QSqlDatabase()Mark Brand2013-02-051-3/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The presence of the sentence "If this is the last QSqlDatabase object that uses a certain database connection, the database connection is automatically closed" is misleading, whether or not the statement is true. It is about an internal detail of QSqlDatabase's implementation. As such it is not appropriate for user documentation. The user should be focused on how to use addDatabase(), cloneDatabase() and removeDatabase() correctly. Task-number: QTBUG-29481 Change-Id: I0c39584be260e13340834c34098368fcce4a7419 Reviewed-by: Florian Paul Schmidt <mista.tapas@gmx.net> Reviewed-by: Sune Vuorela <sune@vuorela.dk> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* | Merge "Merge remote-tracking branch 'origin/stable' into dev" into ↵Frederik Gladhorn2013-01-291-1/+1
|\| | | | | | | refs/staging/dev
| * Doc: Fix module name formatSze Howe Koh2013-01-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Follow the conventions at http://qt-project.org/wiki/Spelling_Module_Names_in_Qt_Documentation QtCore -> Qt Core QtDBus -> Qt D-Bus QtDesigner -> Qt Designer QtGui -> Qt GUI QtImageFormats -> Qt Image Formats QtNetwork -> Qt Network QtPrintSupport -> Qt Print Support QtScript -> Qt Script QtSql -> Qt SQL QtSvg -> Qt SVG QtTest -> Qt Test QtWebKit -> Qt WebKit QtWidgets -> Qt Widgets QtXml -> Qt XML QtConcurrent -> Qt Concurrent (partial) QtQuick -> Qt Quick (partial) Also, distinguish between "module" and "library" Change-Id: Icb8aa695ae60b0e45920b0c8fce4dc763a12b0cd Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
* | Remove QT_{BEGIN,END}_HEADER macro usageSergio Ahumada2013-01-2910-40/+0
|/ | | | | | | | | | | The macro was made empty in ba3dc5f3b56d1fab6fe37fe7ae08096d7dc68bcb and is no longer necessary or used. Discussed-on: http://lists.qt-project.org/pipermail/development/2013-January/009284.html Change-Id: Id2bb2e2cabde059305d4af5f12593344ba30f001 Reviewed-by: Laszlo Papp <lpapp@kde.org> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
* Update copyright year in Digia's license headersSergio Ahumada2013-01-1823-23/+23
| | | | | Change-Id: Ic804938fc352291d011800d21e549c10acac66fb Reviewed-by: Lars Knoll <lars.knoll@digia.com>
* SQL: Change in QSqlResultPrivate::positionalToNamedBinding()Caroline Chao2012-12-101-2/+0
| | | | | | | | | | | | | | | | | | | | | | | | With the change cff46983a, prepared queries can now store a named paramater to be used more than once. When using ?, thus positional binding, there is no named parameter, thus there is no need to store it. When prepare is called from a query with ?, it currently causes an error when the feature QSqlDriver::NamedPlaceholders is true. Because holders values are called while holders is actually empty. QSqlDriver::NamedPlaceholders is true for QOCI plugin only but the problem is independant of the plugin used. Adding a test case with a test driver to make the test runnable without Oracle installed. Change-Id: I6d7491f7e09a7b62d2d4d216b40fedd67e927e27 Reviewed-by: Matt Newell <newellm@blur.com> Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>
* Docs: Fix some warningsChristian Stenger2012-12-061-0/+1
| | | | | Change-Id: I3898c89e54aa671ff8cb1b25c49cfe3835ab9384 Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
* Doc: Remove obsolete statementChristian Stenger2012-12-061-3/+0
| | | | | Change-Id: Ic7f14dae391684a4870e030ab4549b3a59f1ea5f Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
* create interface QSqlDriver::cancelQuery()Sune Vuorela2012-11-202-1/+27
| | | | | | | | | This is useful for canceling a long running sql query. Note that it needs support from the individual drivers. Change-Id: Ia170a70487ff4ee13c85f12bc13e62fb198617fe Reviewed-by: Andy Shaw <andy.shaw@digia.com> Reviewed-by: Mark Brand <mabrand@mabrand.nl>