diff --git a/.gitignore b/.gitignore
index f140cb47ca629d575e58f819b212b4340d137f7b..3ced6e0c35d69a2cd06ca0cd9369b1f24f75da5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,11 +70,8 @@ src/xml/lib/
 
 # Binaries
 # --------
-bin/Aggregation.dll
-bin/CodeModel.dll
-bin/ExtensionSystem.dll
-bin/QtConcurrent.dll
-bin/Utils.dll
+bin/*.dll
 bin/qtcreator
 bin/qtcreator.exe
+doc/qtcreator.qch
 tests/manual/cplusplus/cplusplus0
diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp
index 04a04abf8f7c4a1f47bd9bab87a290563e6dc644..b88f0772326d0ba1a6cb787dc642c1a5d9a39a14 100644
--- a/bin/gdbmacros/gdbmacros.cpp
+++ b/bin/gdbmacros/gdbmacros.cpp
@@ -1123,8 +1123,8 @@ static void qDumpQHash(QDumper &d)
         while (node != end) {
             d.beginHash();
                 if (simpleKey) {
-                    qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "name");
-                    P(d, "nameisindex", "1");
+                    P(d, "name", "[" << i << "]");
+                    qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "key");
                     if (simpleValue)
                         qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
                     P(d, "type", valueType);
@@ -1310,6 +1310,42 @@ static void qDumpQLocale(QDumper &d)
     d.disarm();
 }
 
+static void qDumpQMapNode(QDumper &d)
+{
+    const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
+    const char *keyType   = d.templateParameters[0];
+    const char *valueType = d.templateParameters[1];
+
+    qCheckAccess(h->backward);
+    qCheckAccess(h->forward[0]);
+
+    P(d, "value", "");
+    P(d, "numchild", 2);
+    if (d.dumpChildren) {
+        //unsigned keySize = d.extraInt[0];
+        //unsigned valueSize = d.extraInt[1];
+        unsigned mapnodesize = d.extraInt[2];
+        unsigned valueOff = d.extraInt[3];
+
+        unsigned keyOffset = 2 * sizeof(void*) - mapnodesize;
+        unsigned valueOffset = 2 * sizeof(void*) - mapnodesize + valueOff;
+
+        d << ",children=[";
+        d.beginHash();
+        P(d, "name", "key");
+        qDumpInnerValue(d, keyType, addOffset(h, keyOffset));
+
+        d.endHash();
+        d.beginHash();
+        P(d, "name", "value");
+        qDumpInnerValue(d, valueType, addOffset(h, valueOffset));
+        d.endHash();
+        d << "]";
+    }
+
+    d.disarm();
+}
+
 static void qDumpQMap(QDumper &d)
 {
     QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
@@ -1355,26 +1391,32 @@ static void qDumpQMap(QDumper &d)
 
         while (node != end) {
             d.beginHash();
+                P(d, "name", "[" << i << "]");
                 if (simpleKey) {
                     P(d, "type", valueType);
-                    qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "name");
-
-                    P(d, "nameisindex", "1");
+                    qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "key");
                     if (simpleValue)
                         qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));
 
                     P(d, "type", valueType);
                     P(d, "addr", addOffset(node, valueOffset));
                 } else {
-                    P(d, "name", "[" << i << "]");
-                    P(d, "type", NS"QMapNode<" << keyType << "," << valueType << " >");
+#if QT_VERSION >= 0x040500
                     // actually, any type (even 'char') will do...
-                    P(d, "exp", "*('"NS"QMapNode<" << keyType << "," << valueType << " >'*)" << node);
+                    P(d, "type", NS"QMapNode<"
+                        << keyType << "," << valueType << " >");
+                    P(d, "exp", "*('"NS"QMapNode<"
+                        << keyType << "," << valueType << " >'*)" << node);
+
                     //P(d, "exp", "*('"NS"QMapData'*)" << (void*)node);
                     //P(d, "exp", "*(char*)" << (void*)node);
-
                     // P(d, "addr", node);  does not work as gdb fails to parse
-                    // e.g. &((*('"NS"QMapNode<QString,Foo>'*)0x616658))
+#else 
+                    P(d, "type", NS"QMapData::Node<"
+                        << keyType << "," << valueType << " >");
+                    P(d, "exp", "*('"NS"QMapData::Node<"
+                        << keyType << "," << valueType << " >'*)" << node);
+#endif
                 }
             d.endHash();
 
@@ -1387,6 +1429,11 @@ static void qDumpQMap(QDumper &d)
     d.disarm();
 }
 
+static void qDumpQMultiMap(QDumper &d)
+{
+    qDumpQMap(d);
+}
+
 static void qDumpQModelIndex(QDumper &d)
 {
     const QModelIndex *mi = reinterpret_cast<const QModelIndex *>(d.data);
@@ -1431,42 +1478,6 @@ static void qDumpQModelIndex(QDumper &d)
     d.disarm();
 }
 
-static void qDumpQMapNode(QDumper &d)
-{
-    const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
-    const char *keyType   = d.templateParameters[0];
-    const char *valueType = d.templateParameters[1];
-
-    qCheckAccess(h->backward);
-    qCheckAccess(h->forward[0]);
-
-    P(d, "value", "");
-    P(d, "numchild", 2);
-    if (d.dumpChildren) {
-        //unsigned keySize = d.extraInt[0];
-        //unsigned valueSize = d.extraInt[1];
-        unsigned mapnodesize = d.extraInt[2];
-        unsigned valueOff = d.extraInt[3];
-
-        unsigned keyOffset = 2 * sizeof(void*) - mapnodesize;
-        unsigned valueOffset = 2 * sizeof(void*) - mapnodesize + valueOff;
-
-        d << ",children=[";
-        d.beginHash();
-        P(d, "name", "key");
-        qDumpInnerValue(d, keyType, addOffset(h, keyOffset));
-
-        d.endHash();
-        d.beginHash();
-        P(d, "name", "value");
-        qDumpInnerValue(d, valueType, addOffset(h, valueOffset));
-        d.endHash();
-        d << "]";
-    }
-
-    d.disarm();
-}
-
 static void qDumpQObject(QDumper &d)
 {
     const QObject *ob = reinterpret_cast<const QObject *>(d.data);
@@ -2355,6 +2366,8 @@ static void handleProtocolVersion2and3(QDumper & d)
                 qDumpQMapNode(d);
             else if (isEqual(type, "QModelIndex"))
                 qDumpQModelIndex(d);
+            else if (isEqual(type, "QMultiMap"))
+                qDumpQMap(d);
             break;
         case 'O':
             if (isEqual(type, "QObject"))
@@ -2457,6 +2470,9 @@ void qDumpObjectData440(
             "\""NS"QMap\","
             "\""NS"QMapNode\","
             "\""NS"QModelIndex\","
+            #if QT_VERSION >= 0x040500
+            "\""NS"QMultiMap\","
+            #endif
             "\""NS"QObject\","
             "\""NS"QObjectMethodList\","   // hack to get nested properties display
             "\""NS"QObjectPropertyList\","
@@ -2483,6 +2499,10 @@ void qDumpObjectData440(
             "\"std::vector\","
             "\"std::wstring\","
             "]";
+        d << ",qtversion=["
+            "\"" << ((QT_VERSION >> 16) & 255) << "\","
+            "\"" << ((QT_VERSION >> 8)  & 255) << "\","
+            "\"" << ((QT_VERSION)       & 255) << "\"]";
         d << ",namespace=\""NS"\"";
         d.disarm();
     }
diff --git a/doc/api/classic.css b/doc/api/classic.css
new file mode 100644
index 0000000000000000000000000000000000000000..400ee71168cdbd017903ab405fc8ed9a7b32360e
--- /dev/null
+++ b/doc/api/classic.css
@@ -0,0 +1,102 @@
+h3.fn,span.fn
+{
+  margin-left: 1cm;
+  text-indent: -1cm;
+}
+
+a:link
+{
+  color: #004faf;
+  text-decoration: none
+}
+
+a:visited
+{
+  color: #672967;
+  text-decoration: none
+}
+
+td.postheader
+{
+  font-family: sans-serif
+}
+
+tr.address
+{
+  font-family: sans-serif
+}
+
+body
+{
+  background: #ffffff;
+  color: black
+}
+
+table tr.odd {
+  background: #f0f0f0;
+  color: black;
+}
+
+table tr.even {
+  background: #e4e4e4;
+  color: black;
+}
+
+table.annotated th {
+  padding: 3px;
+  text-align: left
+}
+
+table.annotated td {
+  padding: 3px;
+}
+
+table tr pre
+{
+  padding-top: none;
+  padding-bottom: none;
+  padding-left: none;
+  padding-right: none;
+  border: none;
+  background: none
+}
+
+tr.qt-style
+{
+  background: #a2c511;
+  color: black
+}
+
+body pre
+{
+  padding: 0.2em;
+  border: #e7e7e7 1px solid;
+  background: #f1f1f1;
+  color: black
+}
+
+span.preprocessor, span.preprocessor a
+{
+  color: darkblue;
+}
+
+span.comment
+{
+  color: darkred;
+  font-style: italic
+}
+
+span.string,span.char
+{
+  color: darkgreen;
+}
+
+.subtitle
+{
+    font-size: 0.8em
+}
+
+.small-subtitle
+{
+    font-size: 0.65em
+}
diff --git a/doc/api/qtcreator-api.qdoc b/doc/api/qtcreator-api.qdoc
new file mode 100644
index 0000000000000000000000000000000000000000..5ac78d98069a404d33006f40cdc8572f50de2687
--- /dev/null
+++ b/doc/api/qtcreator-api.qdoc
@@ -0,0 +1,82 @@
+/*!
+    \page index.html
+    \title Qt Creator
+
+    Qt Creator is Qt Software's crossplatform IDE. The core of Qt Creator is
+    basically only a \l{ExtensionSystem}{plugin loader}.
+
+    \section1 Core Libraries
+
+    There are a few core libraries used by many parts of Qt Creator.
+
+    \table
+    \header
+    \o Library Name
+    \o Description
+
+    \row
+    \o \l{Aggregation}{Aggregation}
+    \o Adds functionality for "glueing" QObjects of different
+    types together, so you can "cast" between them.
+
+    \row
+    \o \l{ExtensionSystem}{ExtensionSystem}
+    \o Implements the plugin loader framework. Provides a base class for plugins and
+    basic mechanisms for plugin interaction like an object pool.
+
+    \endtable
+
+    \section1 Plugins
+
+    As already mentioned, Qt Creator is basically only a plugin loader framework
+    which gets its IDE functionality through plugins. The most important plugin
+    is the Core plugin which provides all the basic functionality needed
+    later to integrate e.g. editors or mode windows.
+
+    \table
+    \header
+    \o Plugin Name
+    \o Description
+
+    \row
+    \o \l{Core} {Core}
+    \o The core plugin. Provides the main window and managers for editors,
+    actions, mode windows and files, just to mention the most important ones.
+
+    \endtable
+*/
+
+/*!
+    \page classes.html
+    \title Qt Creator Classes
+
+    \generatelist classes
+*/
+
+/*!
+    \page namespaces.html
+    \title Qt Creator Namespaces
+
+    \generatelist namespaces
+*/
+
+/*!
+    \page mainclasses.html
+    \title Qt Creator Main Classes
+
+    \generatelist mainclasses
+
+*/
+
+/*!
+    \page functions.html
+    \title Qt Creator Functions
+
+    \generatelist functionindex
+*/
+
+/*!
+    \group qtc
+
+    \title Core Plugin
+*/
diff --git a/doc/workbench.qtdocconf b/doc/api/qtcreator-api.qdocconf
similarity index 56%
rename from doc/workbench.qtdocconf
rename to doc/api/qtcreator-api.qdocconf
index 7a82c2aac6f95eccf38b7155010ea7ae9e740cf4..92c40b8a388aa476ded07a7268420aacafb71862 100644
--- a/doc/workbench.qtdocconf
+++ b/doc/api/qtcreator-api.qdocconf
@@ -1,17 +1,19 @@
-project                 = Workbench
-description             = Workbench SDK Documentation
+project                 = Qt Creator API
+description             = Qt Creator API Documentation
 
 language                = Cpp
 
 headerdirs              = . \
-                          ../src/libs/extensionsystem \
-                          ../src/plugins/core \
-                          ../src/plugins/core/actionmanager
+                          ../../src/libs/aggregation \
+                          ../../src/libs/extensionsystem \
+                          ../../src/plugins/core \
+                          ../../src/plugins/core/actionmanager
 
 sourcedirs              = . \
-                          ../src/libs/extensionsystem \
-                          ../src/plugins/core \
-                          ../src/plugins/core/actionmanager
+                          ../../src/libs/aggregation \
+                          ../../src/libs/extensionsystem \
+                          ../../src/plugins/core \
+                          ../../src/plugins/core/actionmanager
 
 headers.fileextesnions  = "*.h"
 sources.fileextensions  = "*.cpp *.qdoc"
@@ -22,33 +24,70 @@ indexes                 = $QTDIR/doc/html/qt.index
 
 outputdir               = ./html
 base                    = file:./html
-versionsym              = 1.0.0
-defines                 = Q_QDOC \
-                          QT_.*_SUPPORT \
-                          QT_.*_LIB \
-                          QT_COMPAT \
-                          QT_KEYPAD_NAVIGATION \
-                          QT3_SUPPORT \
-                          Q_WS_.* \
-                          Q_OS_.* \
-                          Q_BYTE_ORDER \
-                          __cplusplus
-
+versionsym              = 0.9.2
 codeindent              = 1
-extraimages.HTML        = qt-logo \
-                          trolltech-logo
 
+## compat.qdocconf
+alias.i				= e
+alias.include			= input
+
+macro.0                         = "\\\\0"
+macro.b                         = "\\\\b"
+macro.n                         = "\\\\n"
+macro.r                         = "\\\\r"
+macro.i                         = "\\o"
+macro.i11                       = "\\o{1,1}"
+macro.i12                       = "\\o{1,2}"
+macro.i13                       = "\\o{1,3}"
+macro.i14                       = "\\o{1,4}"
+macro.i15                       = "\\o{1,5}"
+macro.i16                       = "\\o{1,6}"
+macro.i17                       = "\\o{1,7}"
+macro.i18                       = "\\o{1,8}"
+macro.i19                       = "\\o{1,9}"
+macro.i21                       = "\\o{2,1}"
+macro.i31                       = "\\o{3,1}"
+macro.i41                       = "\\o{4,1}"
+macro.i51                       = "\\o{5,1}"
+macro.i61                       = "\\o{6,1}"
+macro.i71                       = "\\o{7,1}"
+macro.i81                       = "\\o{8,1}"
+macro.i91                       = "\\o{9,1}"
+macro.img                       = "\\image"
+macro.endquote                  = "\\endquotation"
+macro.relatesto                 = "\\relates"
+
+spurious			= "Missing comma in .*" \
+				  "Missing pattern .*"
+
+## macros.qdocconf
+macro.aring.HTML        = "&aring;"
+macro.Auml.HTML         = "&Auml;"
+macro.author            = "\\bold{Author:}"
 macro.br.HTML           = "<br />"
-macro.QD                = "\\e{Qt Designer}"
-macro.QA                = "\\e{Qt Assistant}"
+macro.BR.HTML           = "<br />"
+macro.aacute.HTML       = "&aacute;"
 macro.eacute.HTML       = "&eacute;"
-macro.aring.HTML        = "&aring;"
+macro.iacute.HTML       = "&iacute;"
+macro.gui               = "\\bold"
+macro.hr.HTML           = "<hr />"
+macro.key               = "\\bold"
+macro.menu              = "\\bold"
+macro.note              = "\\bold{Note:}"
 macro.oslash.HTML       = "&oslash;"
 macro.ouml.HTML         = "&ouml;"
-macro.Auml.HTML         = "&Auml;"
-macro.uuml.HTML         = "&uuml;"
+macro.QA                = "\\e{Qt Assistant}"
+macro.QD                = "\\e{Qt Designer}"
+macro.QL                = "\\e{Qt Linguist}"
+macro.param             = "\\e"
+macro.raisedaster.HTML  = "<sup>*</sup>"
+macro.reg.HTML          = "<sup>&reg;</sup>"
+macro.return            = "Returns"
 macro.starslash         = "\\c{*/}"
+macro.uuml.HTML         = "&uuml;"
+macro.mdash.HTML        = "&mdash;"
 
+## qt-cpp-ignore.qdocconf
 Cpp.ignoretokens        = QAXFACTORY_EXPORT \
                           QDESIGNER_COMPONENTS_LIBRARY \
                           QDESIGNER_EXTENSION_LIBRARY \
@@ -68,9 +107,11 @@ Cpp.ignoretokens        = QAXFACTORY_EXPORT \
                           QM_EXPORT_WORKSPACE \
                           QM_EXPORT_XML \
                           QT_ASCII_CAST_WARN \
+                          QT_ASCII_CAST_WARN_CONSTRUCTOR \
                           QT_BEGIN_HEADER \
                           QT_DESIGNER_STATIC \
                           QT_END_HEADER \
+                          QT_FASTCALL \
                           QT_WIDGET_PLUGIN_EXPORT \
                           Q_COMPAT_EXPORT \
                           Q_CORE_EXPORT \
@@ -81,6 +122,7 @@ Cpp.ignoretokens        = QAXFACTORY_EXPORT \
                           Q_EXPORT_CODECS_KR \
                           Q_EXPORT_PLUGIN \
                           Q_GFX_INLINE \
+                          Q_AUTOTEST_EXPORT \
                           Q_GUI_EXPORT \
                           Q_GUI_EXPORT_INLINE \
                           Q_GUI_EXPORT_STYLE_CDE \
@@ -93,17 +135,27 @@ Cpp.ignoretokens        = QAXFACTORY_EXPORT \
                           Q_GUI_EXPORT_STYLE_SGI \
                           Q_GUI_EXPORT_STYLE_WINDOWS \
                           Q_GUI_EXPORT_STYLE_WINDOWSXP \
+                          QHELP_EXPORT \
                           Q_INLINE_TEMPLATE \
+                          Q_INTERNAL_WIN_NO_THROW \
                           Q_NETWORK_EXPORT \
                           Q_OPENGL_EXPORT \
                           Q_OUTOFLINE_TEMPLATE \
                           Q_SQL_EXPORT \
                           Q_SVG_EXPORT \
                           Q_SCRIPT_EXPORT \
+                          Q_SCRIPTTOOLS_EXPORT \
                           Q_TESTLIB_EXPORT \
                           Q_TYPENAME \
                           Q_XML_EXPORT \
-                          QDBUS_EXPORT
+                          Q_XMLSTREAM_EXPORT \
+                          Q_XMLPATTERNS_EXPORT \
+                          QDBUS_EXPORT \
+                          QT_BEGIN_NAMESPACE \
+                          QT_BEGIN_INCLUDE_NAMESPACE \
+                          QT_END_NAMESPACE \
+                          QT_END_INCLUDE_NAMESPACE \
+                          PHONON_EXPORT
 Cpp.ignoredirectives    = Q_DECLARE_HANDLE \
                           Q_DECLARE_INTERFACE \
                           Q_DECLARE_METATYPE \
@@ -114,34 +166,66 @@ Cpp.ignoredirectives    = Q_DECLARE_HANDLE \
                           Q_DECLARE_TR_FUNCTIONS \
                           Q_DECLARE_TYPEINFO \
                           Q_DISABLE_COPY \
+                          QT_FORWARD_DECLARE_CLASS \
                           Q_DUMMY_COMPARISON_OPERATOR \
                           Q_ENUMS \
                           Q_FLAGS \
                           Q_INTERFACES \
-                          __attribute__
+                          __attribute__ \
+                          K_DECLARE_PRIVATE \
+                          PHONON_OBJECT \
+                          PHONON_HEIR
 
+## qt-html-templates.qdocconf
 HTML.stylesheets        = classic.css
 HTML.postheader         = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
                           "<tr>\n" \
                           "<td align=\"left\" valign=\"top\" width=\"32\">" \
-                          "<a href=\"http://www.trolltech.com/products/qt\"><img src=\"images/qt-logo.png\" align=\"left\" width=\"32\" height=\"32\" border=\"0\" /></a>" \
+                          "<a href=\"http://www.trolltech.com/products/qt\"><img src=\"images/qt-logo.png\" align=\"left\" border=\"0\" /></a>" \
                           "</td>\n" \
                           "<td width=\"1\">&nbsp;&nbsp;</td>" \
                           "<td class=\"postheader\" valign=\"center\">" \
                           "<a href=\"index.html\">" \
                           "<font color=\"#004faf\">Home</font></a>&nbsp;&middot;" \
+                          " <a href=\"namespaces.html\">" \
+                          "<font color=\"#004faf\">All&nbsp;Namespaces</font></a>&nbsp;&middot;" \
                           " <a href=\"classes.html\">" \
                           "<font color=\"#004faf\">All&nbsp;Classes</font></a>&nbsp;&middot;" \
-                          " <a href=\"interfaces.html\">" \
-                          "<font color=\"#004faf\">All&nbsp;Interfaces</font></a>&nbsp;&middot;" \
+                          " <a href=\"mainclasses.html\">" \
+                          "<font color=\"#004faf\">Main&nbsp;Classes</font></a>&nbsp;&middot;" \
+                          " <a href=\"groups.html\">" \
+                          "<font color=\"#004faf\">Grouped&nbsp;Classes</font></a>&nbsp;&middot;" \
+                          " <a href=\"modules.html\">" \
+                          "<font color=\"#004faf\">Modules</font></a>&nbsp;&middot;" \
                           " <a href=\"functions.html\">" \
                           "<font color=\"#004faf\">Functions</font></a>" \
                           "</td>\n" \
-                          "<td align=\"right\" valign=\"top\" width=\"230\"><a href=\"http://www.trolltech.com\"><img src=\"images/trolltech-logo.png\" align=\"right\" width=\"203\" height=\"32\" border=\"0\" /></a></td></tr></table>"
+                          "<td align=\"right\" valign=\"top\" width=\"230\"></td></tr></table>"
 
 HTML.footer             = "<p /><address><hr /><div align=\"center\">\n" \
                           "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
-                          "<td width=\"30%\">Copyright &copy; \$THISYEAR\$ <a href=\"trolltech.html\">Trolltech</a></td>\n" \
+                          "<td width=\"30%\" align=\"left\">Copyright &copy; %THISYEAR% Nokia Corporation " \
+                          "and/or its subsidiary(-ies)</td>\n" \
                           "<td width=\"40%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
                           "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt \\version</div></td>\n" \
                           "</tr></table></div></address>"
+
+## qt-defines.qdocconf
+defines                 = Q_QDOC \
+                          QT_.*_SUPPORT \
+                          QT_.*_LIB \
+                          QT_COMPAT \
+                          QT_KEYPAD_NAVIGATION \
+                          QT3_SUPPORT \
+                          Q_WS_.* \
+                          Q_OS_.* \
+                          Q_BYTE_ORDER \
+			  QT_DEPRECATED \
+                          Q_NO_USING_KEYWORD \
+                          __cplusplus
+
+# Files not referenced in any qdoc file (last four needed by qtdemo)
+# See also qhp.Qt.extraFiles
+extraimages.HTML        = qt-logo \
+                          trolltech-logo
+                             
diff --git a/doc/doc.pri b/doc/doc.pri
index 5d58a28c3e656a3a2717a0080daf684196efcb68..cb800823ec46b23bf37e1dc1afc23807de1d151a 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -1,16 +1,13 @@
-# Generate docs. Does not work for shadow builds and never will.
-# (adding a "docs" make target).
-
 unix {
-    QDOC = SRCDIR=$$PWD OUTDIR=$$OUT_PWD/html $$(QTDIR)/tools/qdoc3/qdoc3
+    QDOC = SRCDIR=$$PWD OUTDIR=$$OUT_PWD/doc/html $$(QTDIR)/tools/qdoc3/qdoc3
     HELPGENERATOR = qhelpgenerator
 } else {
     QDOC = $$(QTDIR)\tools\qdoc3\release\qdoc3.exe
     HELPGENERATOR = qhelpgenerator
 }
 
-QHP_FILE = $$OUT_PWD/html/qtcreator.qhp
-QCH_FILE = $$OUT_PWD/qtcreator.qch
+QHP_FILE = $$OUT_PWD/doc/html/qtcreator.qhp
+QCH_FILE = $$OUT_PWD/doc/qtcreator.qch
 
 html_docs.commands =$$QDOC $$PWD/qtcreator.qdocconf
 html_docs.depends += $$PWD/qtcreator.qdoc $$PWD/qtcreator.qdocconf
@@ -20,6 +17,14 @@ qch_docs.commands = $$HELPGENERATOR -o $$QCH_FILE $$QHP_FILE
 qch_docs.depends += html_docs
 qch_docs.files = $$QCH_FILE
 
-docs.depends = qch_docs
+macx {
+    cp_docs.commands = $${QMAKE_COPY_DIR} $${OUT_PWD}/doc $${OUT_PWD}/bin/QtCreator.app/Contents/Resources
+    cp_docs.depends += qch_docs
+    docs.depends = cp_docs
+    QMAKE_EXTRA_TARGETS += html_docs qch_docs cp_docs docs
+}
+!macx {
+    docs.depends = qch_docs
+    QMAKE_EXTRA_TARGETS += html_docs qch_docs docs
+}
 
-QMAKE_EXTRA_TARGETS += html_docs qch_docs docs
diff --git a/doc/doc.pro b/doc/doc.pro
deleted file mode 100644
index 8337190b2276b97883826e8158bdc70217f824e6..0000000000000000000000000000000000000000
--- a/doc/doc.pro
+++ /dev/null
@@ -1 +0,0 @@
-include(doc.pri)
diff --git a/doc/qtcreator.qch b/doc/qtcreator.qch
deleted file mode 100644
index 8733e749a0823e5c71ef692a926effabbfeb8106..0000000000000000000000000000000000000000
Binary files a/doc/qtcreator.qch and /dev/null differ
diff --git a/doc/workbench.qdoc b/doc/workbench.qdoc
deleted file mode 100644
index 033b1ae7d4b7dd6379de8284dd70659f5627f1af..0000000000000000000000000000000000000000
--- a/doc/workbench.qdoc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*!
-    \page index.html
-    \title Workbench
-
-    Workbench is Trolltech's crossplatform IDE. The core of Workbench is
-    basically only a \l{Plugin Loader Framework}{plugin loader} comparable to
-    Eclipse. All major functionality is then added via plugins. The plugins
-    necessary for a full IDE will be provided by Trolltech, possible addons or
-    replacements of existing plugins can be provided by anyone. This means that
-    there will be a place where plugins can be shared.
-
-    The main features of Workbench are:
-
-    \list
-    \o Fast since it's written in C++
-    \o Easy and fast to use (the entire IDE can be controlled via short cuts)
-    \o Highly extensible
-    \o Integrated C++ language support, i.e. code completion, class browser, ...
-    \o Integrated debugger framework and outstanding support for gdb
-    \o Integrated Qt Designer
-    \o Qtopia Integration 
-    \endlist
-
-    \section1 Plugins
-
-    As already mentioned, Workbench is basically only a plugin loader framework
-    which gets its IDE functionality through plugins. The most important plugin
-    is the QWorkbench plugin which provides all the basic functionality needed
-    later to integrate e.g. editors or tool windows.
-
-    \table
-    \header
-    \o Plugin Name
-    \o Description
-
-    \row
-    \o \l{QWorkbench Plugin} {QWorkbench}
-    \o The core plugin. Provides the main window and managers for editors,
-    actions, tool windows and files, just to mention the most important ones.
-
-    \endtable
-
-*/
-
-/*!
-    \page classes.html
-    \title Workbench Classes and Namespaces
-
-    \section1 Classes
-
-    \generatelist classes
-
-    \section1 Namespaces
-
-    \generatelist{namespaces}
-*/
-
-/*!
-    \page interfaces.html
-    \title Interfaces
-    \generatelist mainclasses
-
-*/
-
-/*!
-    \page functions.html
-    \title Member Function Index
-    \generatelist functionindex
-*/
-
-/*!
-    \group pluginloader
-
-    \title Plugin Loader Framework
-*/
-
-/*!
-    \group qwb
-
-    \title QWorkbench Plugin
-*/
-
-/*!
-    \namespace Trolltech
-*/
-
-/*!
-    \namespace Trolltech::QWorkbench
-*/
-
-/*!
-    \namespace Trolltech::QWorkbench::Internal
-    \brief Classes that manage and control internal features of the workbench environment.
-*/
-
-/*!
-    \namespace ExtensionSystem
-*/
diff --git a/installer/TODO.txt b/installer/TODO.txt
deleted file mode 100644
index 57aed1443075aacf38dadb0fd96a2db3230abd62..0000000000000000000000000000000000000000
--- a/installer/TODO.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-<all>
-- installdir whitespace check      done.
-- installdir exist/non-empty check
-
-<linux>
-- run '/bin/xdg-desktop-install.sh' if '/usr/bin/xdg-mime exists'
-- desktop shortcut
-
-<windows>
-- create dir '${env(APPDATA)}/Trolltech'
-- start menue shortcuts
-
diff --git a/installer/installer.cpp b/installer/installer.cpp
deleted file mode 100644
index 013d26d2b884170a88a4e1d36a63c54ba927771a..0000000000000000000000000000000000000000
--- a/installer/installer.cpp
+++ /dev/null
@@ -1,433 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact:  Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file.  Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-
-// This file contains the QtCreator-specific part of the installer.
-// It lists the files and features the installer should handle.
-
-#include "qinstaller.h"
-#include "qinstallergui.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QFileInfo>
-#include <QtCore/QObject>
-
-#include <QtGui/QApplication>
-#include <QtGui/QBoxLayout>
-#include <QtGui/QGridLayout>
-#include <QtGui/QLabel>
-#include <QtGui/QMessageBox>
-
-
-// QInstallerGui is base of the Gui part of an installer, i.e.
-// the "main installer wizard". In the simplest case it's just
-// a sequence of "standard" wizard pages. A few commonly used
-// ones are provided already in qinstallergui.h.
-
-
-// A custom target directory selection based due to the no-space
-// restriction...
-
-class TargetDirectoryPage : public QInstallerTargetDirectoryPage
-{
-public:
-    TargetDirectoryPage(QInstaller *installer)
-      : QInstallerTargetDirectoryPage(installer)
-    {
-        m_noSpaceLabel = new QLabel(this);
-        m_noSpaceLabel->setText("The directory name should not contain any space.");
-        m_noSpaceLabel->hide();
-        insertWidget(m_noSpaceLabel, "MessageLabel");
-    }
-
-    bool isComplete() const
-    {
-        bool invalid = targetDir().contains(' ');
-        QPalette palette;
-        // We show the warning only if the user types a space.
-        // No need to scare him if the path is ok for us...
-        if (invalid) {
-            m_noSpaceLabel->show();
-            palette.setColor(QPalette::WindowText, Qt::red);
-        }
-        m_noSpaceLabel->setPalette(palette);
-        return !invalid;
-    }
-    
-    int nextId() const
-    {
-        QFileInfo fi(targetDir());
-    
-        if (isVisible() && fi.isDir()) {
-            QFileInfo fi2(targetDir() + '/' + installer()->uninstallerName());
-            if (fi2.exists()) {
-                QMessageBox::StandardButton bt = QMessageBox::warning(wizard(),
-                    tr("Warning"),
-                    tr("The directory you selected exists already and contains an installaion.\n"
-                       "Do you want to overwrite it?"),
-                        QMessageBox::Yes | QMessageBox::No);
-                if (bt == QMessageBox::No)
-                    return wizard()->currentId();
-            } else {
-                QMessageBox::StandardButton bt = QMessageBox::warning(wizard(),
-                    tr("Warning"),
-                    tr("The directory you selected exists already.\n"
-                       "Do you want to remove it and continue?"),
-                        QMessageBox::Yes | QMessageBox::No);
-                if (bt == QMessageBox::No)
-                    return wizard()->currentId();
-            }
-        }
-        return QInstallerPage::nextId();
-    }
-
-private:
-    QLabel *m_noSpaceLabel;
-};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QtCreatorInstallerGui
-//
-////////////////////////////////////////////////////////////////////
-
-// QtCreatorInstallerGui is the QtCreator specific incarnation
-// of a QInstallerGui.
-
-class QtCreatorInstallerGui : public QInstallerGui
-{
-public:
-    QtCreatorInstallerGui(QInstaller *installer)
-    {
-        // The Gui has access to the installer backend at construction
-        // time. For later access it needs to store the QInstaller *
-        // pointer provided. Not needed in this case here.
-
-        setWindowTitle(tr("%1 Setup").arg(installer->value("ProductName")));
-        installer->connectGui(this);
-
-        // We are happy with the default set of pages.
-        addPage(new QInstallerIntroductionPage(installer));
-        addPage(new QInstallerLicenseAgreementPage(installer));
-        //addPage(new QInstallerTargetDirectoryPage(installer));
-        addPage(new TargetDirectoryPage(installer));
-        if (installer->componentCount() > 1)
-            addPage(new QInstallerComponentSelectionPage(installer));
-        addPage(new QInstallerReadyForInstallationPage(installer));
-        addPage(new QInstallerPerformInstallationPage(installer));
-        addPage(new QInstallerFinishedPage(installer));
-
-        setStartId(installer->value("GuiStartPage").toInt());
-    }
-};
-
-
-// QInstaller is base of the "backend" part of an installer, i.e.
-// the part handling the installer tasks and keeping track of 
-// related data like the directory to install to, the name of
-// the Product, version of the Product etc.
-
-// QtCreatorInstaller is the QtCreator specific incarnation
-// of a QInstaller. It needs to list all tasks that a performed
-// during installation. The tasks themselves specify what to 
-// do at uninstall time.
-
-class QtCreatorInstaller : public QInstaller
-{
-public:
-    QtCreatorInstaller()
-    {
-        // basic product information
-        setValue("ProductName", "Qt Creator");
-        setValue("ProductVersion", "alpha");
-
-        // registration information
-        setValue("Comments", "");
-        setValue("Contact", "");
-        setValue("DisplayVersion", "");
-        setValue("HelpLink", "");
-        setValue("Publisher", "");
-        setValue("UrlAboutInfo", "");
-
-        // information needed at installer generation time
-        setValue("OutputFile", "qtcreator-installer");
-        setValue("RunProgram", "@TargetDir@/bin/qtcreator");
-
-        // default component selection, overridable from command line
-        setValue("UseQtCreator", "true");
-#ifdef Q_OS_WIN
-        //setValue("UseQt", "true");
-        //setValue("UseMinGW", "true");
-#endif
-    }
-    
-private:
-    // tasks related to QtCreator itself. Binary, libraries etc.
-    void appendQtCreatorComponent()
-    {
-        QString sourceDir = value("SourceDir");
-        if (sourceDir.isEmpty() && QFileInfo("../bin/qtcreator").isReadable())
-            sourceDir = QLatin1String("..");
-        if (sourceDir.isEmpty())
-            throw QInstallerError("Missing 'SourceDir=<dir>' on command line.");
-        QInstallerComponent *component = new QInstallerComponent(this);
-        component->setValue("Name", "QtCreator");
-        component->setValue("DisplayName", "Qt Creator");
-        component->setValue("Description", "The Qt Creator IDE");
-        component->setValue("SuggestedState", "AlwaysInstalled");
-#ifdef Q_OS_MAC
-        component->appendDirectoryTasks(sourceDir + "/bin/QtCreator.app", "@TargetDir@");
-#else
-        component->appendDirectoryTasks(sourceDir + "/bin", "@TargetDir@/bin");
-        component->appendDirectoryTasks(sourceDir + "/lib", "@TargetDir@/lib");
-#endif
-
-        QInstallerPatchFileTask *task = new QInstallerPatchFileTask(this);
-        task->setTargetPath("@TargetDir@/lib/Trolltech/" + libraryName("ProjectExplorer", "1.0.0"));
-        task->setNeedle("Clear Session");
-        task->setReplacement("CLEAR SESSION");
-        component->appendTask(task);
-
-        appendComponent(component);
-    }
-
-    void appendMinGWComponent()
-    {
-        QString mingwSourceDir = value("MinGWSourceDir");
-        if (mingwSourceDir.isEmpty())
-            throw QInstallerError("Missing 'MinGWSourceDir=<dir>' on command line.");
-        QInstallerComponent *component = new QInstallerComponent(this);
-        component->setValue("Name", "MinGW");
-        component->setValue("DisplayName", "MinGW");
-        component->setValue("Description",
-            "The MinGW environment including the g++ compiler "
-            "and the gdb debugger.");
-        component->setValue("SuggestedState", "Installed");
-        component->appendDirectoryTasks(mingwSourceDir, "@TargetDir@");
-        appendComponent(component);
-    }
-
-    void appendQtComponent()
-    {
-        QString qtSourceDir = value("QtSourceDir");
-        if (qtSourceDir.isEmpty())
-            throw QInstallerError("Missing 'QtSourceDir=<dir>' on command line.");
-
-        QInstallerComponent *component = new QInstallerComponent(this);
-        component->setValue("Name", "Qt Development Libraries");
-        component->setValue("DisplayName", "Qt");
-        component->setValue("Description",
-            "The Qt library files for development including "
-            "documentation");
-        component->setValue("SuggestedState", "Installed");
-        component->appendDirectoryTasks(qtSourceDir, "@TargetDir@");
-
-#ifdef Q_OS_WIN
-        static const struct
-        {
-            const char *fileName;
-            const char *sourceLocation;
-        } libs[] = {
-            {"/bin/Qt3Support", "/src/qt3support/"},
-            {"/bin/QtCore", "/src/corelib/"},
-            {"/bin/QtGui", "/src/gui/"},
-            {"/bin/QtHelp", "/tools/assistant/lib/"},
-            {"/bin/QtNetwork", "/src/network/"},
-            {"/bin/QtOpenGL", "/src/opengl/"},
-            {"/bin/QtScript", "/src/script/"},
-            {"/bin/QtSql", "/src/sql/"},
-            {"/bin/QtSvg", "/src/svg/"},
-            {"/bin/QtTest", "/src/testlib/"},
-            {"/bin/QtWebKit", "/src/3rdparty/webkit/WebCore/"},
-            {"/bin/QtXml", "/src/xml/"},
-            {"/bin/QtXmlPatterns", "/src/xmlpatterns/"},
-            {"/plugins/accessible/qtaccessiblecompatwidgets",
-                "/src/plugins/accessible/compat/"},
-            {"/plugins/accessible/qtaccessiblewidgets",
-                "/src/plugins/accessible/widgets/"},
-            {"/plugins/codecs/qcncodecs", "/src/plugins/codecs/cn/"},
-            {"/plugins/codecs/qjpcodecs", "/src/plugins/codecs/jp/"},
-            {"/plugins/codecs/qkrcodecs", "/src/plugins/codecs/kr/"},
-            {"/plugins/codecs/qtwcodecs", "/src/plugins/codecs/tw/"},
-            {"/plugins/iconengines/qsvgicon", "/src/plugins/iconengines/svgiconengine/"},
-            {"/plugins/imageformats/qgif", "/src/plugins/imageformats/gif/"},
-            {"/plugins/imageformats/qjpeg", "/src/plugins/imageformats/jpeg/"},
-            {"/plugins/imageformats/qmng", "/src/plugins/imageformats/mng/"},
-            {"/plugins/imageformats/qsvg", "/src/plugins/imageformats/svg/"},
-            {"/plugins/imageformats/qtiff", "/src/plugins/imageformats/tiff/"},
-            {"/plugins/sqldrivers/qsqlite", "/src/plugins/sqldrivers/sqlite/"},
-    //        {"/plugins/sqldrivers/qsqlodbc", "/src/plugins/sqldrivers/odbc/"}
-        };
-        
-        QString debug = QLatin1String("d4.dll");
-
-        for (int i = 0; i != sizeof(libs) / sizeof(libs[0]); ++i) {
-            QInstallerPatchFileTask *task = new QInstallerPatchFileTask(this);
-            task->setTargetPath(QString("@TargetDir@/") + libs[i].fileName + debug);
-            task->setNeedle("f:/depot/qt");
-            task->setReplacement(QByteArray("@TargetDir@/") + libs[i].sourceLocation);
-            component->appendTask(task);
-        }
-#endif
-
-        appendComponent(component);
-    }
-
-    void createTasks()
-    {
-        // set UseXXX=false on command line to prevent inclusion of the 
-        // respective component
-        if (value("UseQtCreator") == "true")
-            appendQtCreatorComponent();
-        if (value("UseMinGW") == "true")
-            appendMinGWComponent();
-        if (value("UseQt") == "true")
-            appendQtComponent();
-    }
-};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QtCreatorUninstallerGui
-//
-////////////////////////////////////////////////////////////////////
-
-class QtCreatorUninstallerGui : public QObject
-{
-public:
-    QtCreatorUninstallerGui(QInstaller *installer)
-      : m_installer(installer)
-    {}
-
-    int exec()
-    {
-        QMessageBox::StandardButton bt = QMessageBox::question(0,
-            tr("Question"),
-            tr("Do you want to deinstall %1 and all of its modules?")
-                .arg(m_installer->value("ProductName")),
-            QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
-        if (bt == QMessageBox::No)
-            return 0;
-        QWizard wizard;
-        wizard.addPage(new QInstallerPerformUninstallationPage(m_installer));
-        wizard.show();  
-        return qApp->exec();
-    }
-
-private:
-    QInstaller *m_installer;
-};
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-// The Main Driver Program
-//
-////////////////////////////////////////////////////////////////////
-
-int main(int argc, char *argv[])
-{
-    QApplication app(argc, argv);
-    QStringList args = app.arguments();
-    qDebug() << "ARGS: " << args;
-
-    QtCreatorInstaller installer;
-    
-    bool helpRequested = false;
-    bool guiRequested = true;
-
-    for (int i = 1; i < args.size(); ++i) {
-        if (args.at(i).contains('=')) {
-            const QString arg = args.at(i);
-            const QString name = arg.section('=', 0, 0);
-            const QString value = arg.section('=', 1, 1);
-            installer.setValue(name, value);
-        } else if (args.at(i) == "--help" || args.at(i) == "-h") {
-            helpRequested = true;
-        } else if (args.at(i) == "--no-gui" || args.at(i) == "NoGui") {
-            qDebug() << "NOGUI";
-            guiRequested = false;
-        } else if (args.at(i) == "--verbose" || args.at(i) == "Verbose") {
-            installer.setVerbose(true);
-        } else {
-            helpRequested = true;
-        }
-    }
-    
-    if (installer.isVerbose())
-        installer.dump(); 
-
-    if (helpRequested) {
-        QString productName = installer.value("ProductName");
-        QString str;
-        if (installer.isCreator())
-            str = QString("  [SourceDir=<dir>]\n"
-                "\n      Creates the %1 installer.\n").arg(productName);
-        else if (installer.isInstaller())
-            str = QString("  [--no-gui] [<name>=<value>...]\n"
-                "\n      Runs the %1 installer\n"
-                "\n      If the '--no-gui' parameter is given, it runs "
-                " installer without GUI\n").arg(productName);
-        else if (installer.isUninstaller())
-            str = QString("  [<name>=<value>...]\n"
-                "\n      Runs the %1 uninstaller.\n").arg(productName);
-        str = "\nUsage: " + installer.installerBinaryPath() + str;
-        qDebug() << qPrintable(str);
-        return 0;
-    }
-
-    if (installer.isInstaller() && guiRequested) {
-        QtCreatorInstallerGui gui(&installer);
-        gui.show();
-        return app.exec();
-    }
-
-#ifdef Q_OS_WIN
-    if (installer.isUninstaller()) {
-        QStringList newArgs = args;
-        newArgs.removeFirst();
-        installer.restartTempUninstaller(newArgs);
-        return 0;
-    }
-#endif
-    if ((installer.isUninstaller() || installer.isTempUninstaller())
-        && guiRequested) {
-        QtCreatorUninstallerGui gui(&installer);
-        //gui.show();
-        return gui.exec();
-    }
-
-    return installer.run() ? 0 : 1;
-}
diff --git a/installer/installer.pro b/installer/installer.pro
deleted file mode 100644
index d9e59651dedb4a577c40dc060a85fdd2eba96a84..0000000000000000000000000000000000000000
--- a/installer/installer.pro
+++ /dev/null
@@ -1,29 +0,0 @@
-TEMPLATE = app
-TARGET = installercreator
-DEPENDPATH += .
-INCLUDEPATH += .
-
-CONFIG -= debug
-CONFIG += release
-
-HEADERS += \
-    qinstaller.h \
-    qinstallergui.h \
-
-SOURCES += \
-    qinstaller.cpp \
-    qinstallergui.cpp \
-    installer.cpp \
-
-RESOURCES += \
-    installer.qrc \
-
-true {
-    OBJECTS_DIR = .tmp/
-    MOC_DIR = .tmp/
-    RCC_DIR = .tmp/
-    UI_DIR = .tmp/
-}
-
-win32:LIBS += ole32.lib
-
diff --git a/installer/installer.qrc b/installer/installer.qrc
deleted file mode 100644
index 5080febcd64e8febe5b77d4ace0e75750b51924e..0000000000000000000000000000000000000000
--- a/installer/installer.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
-    <file>resources/logo.png</file>
-    <file>resources/watermark.png</file>
-    <file>resources/license.txt</file>
-</qresource>
-</RCC>
diff --git a/installer/qinstaller.cpp b/installer/qinstaller.cpp
deleted file mode 100644
index be72b66b2f40d6899f7c2ca3721cf96024f0fbf3..0000000000000000000000000000000000000000
--- a/installer/qinstaller.cpp
+++ /dev/null
@@ -1,1872 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact:  Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file.  Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-
-#include "qinstaller.h"
-
-#include <QtCore/QBuffer>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDateTime>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QDirIterator>
-#include <QtCore/QFile>
-#include <QtCore/QHash>
-#include <QtCore/QProcess>
-#include <QtCore/QSettings>
-
-#ifdef Q_OS_WIN
-#include "qt_windows.h"
-#include <shlobj.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*
- FIXME: Documentation
-
-NAME = "Name";
-DISPLAY_NAME = "DisplayName";
-DESCRIPTION = "Description";
-TASK_COUNT = "TaskCount";
-SIZE = "ComponentSize";
-OUTPUT_FILE = "OutputFile";
-WANTED_STATE = "WantedState";
-SUGGESTED_STATE = "SuggestedState";
-PRODUCT_NAME = "ProductName";
-GUI_START_PAGE = "GuiStartPage";
-RUN_PROGRAM = "RunProgram";
-COMMENTS = "Comments";
-CONTACT = "Contact";
-DISPLAY_VERSION = "DisplayVersion";
-ESTIMATED_SIZE = "EstimatedSize";
-HELP_LINK = "HelpLink";
-INSTALL_DATE = "InstallDate";
-INSTALL_LOCATION = "InstallLocation";
-NO_MODIFY = "NoModify";
-NO_REPAIR = "NoRepair";
-PUBLISHER = "Publisher";
-UNINSTALL_STRING = "UninstallString";
-URL_INFO_ABOUT = "UrlInfoAbout";
-LOGO_PIXMAP
-WATERMARK_PIXMAP
-*/
-
-
-//static qint64 magicInstallerMarker   = (0xdea0d345UL << 32) + 0x12023233UL;
-//static qint64 magicUninstallerMarker = (0xdea0d345UL << 32) + 0x12023234UL;
-static const qint64 magicInstallerMarker      =  0x12023233UL;
-static const qint64 magicUninstallerMarker    =  0x12023234UL;
-static const qint64 magicTempUninstallerMarker =  0x12023235UL;
-
-// Installer Layout:
-//
-//   0000:                            <binary: installer code>
-//     ...
-//   $comptask[0]:                    <int:  $ctc[0]: 1st component task count>
-//     $comptask[0][0]:               <task: first component task data>
-//     ...
-//     $comptask[0][$ctc0-1]:         <task: first component task data>
-//    ...
-//   $comptask[$ncomp-1]:             <int : $cnn: last component task data>
-//     $comptask[$ncomp-1][0]:        <task: last component task data>
-//     ...
-//     $comtaskp[$ncomp-1][$ctc-1]:   <task: last component task data>
-//   $compvars[0]:                    <dict:  $cn0: first component variables>
-//     ...
-//   $compvars[$ncomp-1]:             <dict:  $cnn: last component var data>
-//   $comptaskoffsets:                <int:  $comptask[0]: offset>
-//                                    <int:  $comptask[1]: offset>
-//     ...
-//   $compvarsoffsets:                <int:  $compvars[0]: offset>
-//                                    <int:  $compvars[1]: offset>
-//     ...
-//   $installervars:                  <dict: installer variable data>
-//     ...
-//   end - 7:                         <int:  $comptask[0]: start of comp.tasks>
-//   end - 6:                         <int:  $compvars[0]: start of .vars>
-//   end - 5:                         <int:  $ncomp: number of components>
-//   end - 4:                         <int:  $comptaskoffsets>
-//   end - 3:                         <int:  $compvarsoffsets>
-//   end - 2:                         <int:  $installervars: offset installer vars>
-//   end - 1:                         <int:  magic marker>
-//
-// The stuff after the binary is not present in the "Creator" incarnation
-
-////////////////////////////////////////////////////////////////////
-//
-// Misc helpers
-//
-////////////////////////////////////////////////////////////////////
-
-namespace {
-
-#define ifVerbose(s) if (!installer()->isVerbose()) {} else { qDebug() << s; }
-
-
-QDebug &operator<<(QDebug &os, QInstallerTask *task)
-{
-    task->dump(os);
-    return os;
-}
-
-class Dictionary : public QHash<QString, QString>
-{
-public:
-    typedef QHash<QString, QString> BaseType;
-
-    void setValue(const QString &key, const QString &val)
-    {
-        insert(key, val);
-    }
-
-    void removeTemporaryKeys()
-    {
-        foreach (const QString &key, keys())
-            if (key.startsWith('@'))
-                remove(key);
-    }
-};
-
-//////////////////////////////////////////////////////////////////////
-
-class Error : public QInstallerError
-{
-public:
-    Error(const QString &m)
-        : QInstallerError(m) {}
-    // convenience
-    Error(const char *m, int n)
-        : QInstallerError(QString(QLatin1String(m)).arg(n)) {}
-    Error(const char *m, const QString & n)
-        : QInstallerError(QString(QLatin1String(m)).arg(n)) {}
-private:
-private:
-    QString m_message;
-};
-
-} // anonymous namespace
-
-static void openForWrite(QFile &file)
-{
-    if (!file.open(QIODevice::WriteOnly))
-        throw Error("Cannot open file %1 for writing", file.fileName());
-}
-
-static void openForRead(QFile &file)
-{
-    if (!file.open(QIODevice::ReadOnly))
-        throw Error("Cannot open file %1 for reading", file.fileName());
-}
-
-static void rawWrite(QIODevice *out, const char *buffer, qint64 size)
-{
-    while (size > 0) {
-        qint64 n = out->write(buffer, size);
-        if (n == -1)
-            throw Error("RAW WRITE FAILED: %1", size);
-        size -= n;
-    }
-}
-
-static void rawRead(QIODevice *in, char *buffer, qint64 size)
-{
-    while (size > 0) {
-        qint64 n = in->read(buffer, size);
-        size -= n;
-        buffer += n;
-        if (size != 0)
-            qDebug() << "COULD ONLY READ " << n << "OF" << size + n << "BYTES";
-    }
-}
-
-static inline QByteArray &theBuffer(int size)
-{
-    static QByteArray b;
-    if (size > b.size())
-        b.reserve(size * 3 / 2);
-    return b;
-}
-
-
-#if 0
-// Faster or not?
-static void appendFileData(QIODevice *out, const QString &fileName)
-{
-    QFile file(fileName);
-    openForRead(file);
-    qint64 size = file.size();
-    QInstaller::appendInt(out, size);
-    if (size == 0)
-        return;
-    uchar *data = file.map(0, size);
-    if (!data)
-        throw Error(QInstaller::tr("Cannot map file %1").arg(file.fileName()));
-    rawWrite(out, (const char *)data, size);
-    if (!file.unmap(data))
-        throw Error(QInstaller::tr("Cannot unmap file %1").arg(file.fileName()));
-}
-#endif
-
-static void appendFileData(QIODevice *out, QIODevice *in)
-{
-    QTC_ASSERT(!in->isSequential(), return);
-    qint64 size = in->size();
-    QByteArray &b = theBuffer(size);
-    rawRead(in, b.data(), size);
-    QInstaller::appendInt(out, size);
-    rawWrite(out, b.constData(), size);
-}
-
-static void retrieveFileData(QIODevice *out, QIODevice *in)
-{
-    qint64 size = QInstaller::retrieveInt(in);
-    QByteArray &b = theBuffer(size);
-    rawRead(in, b.data(), size);
-    rawWrite(out, b.constData(), size);
-}
-
-static void appendData(QIODevice *out, QIODevice *in, qint64 size)
-{
-    QByteArray &b = theBuffer(size);
-    rawRead(in, b.data(), size);
-    rawWrite(out, b.constData(), size);
-}
-
-static void appendInt(QIODevice *out, qint64 n)
-{
-    rawWrite(out, (char*)&n, sizeof(n));
-}
-
-static void appendString(QIODevice *out, const QString &str)
-{
-    int n = str.size();
-    appendInt(out, n);
-    rawWrite(out, (char*)str.utf16(), n * sizeof(QChar));
-}
-
-static void appendByteArray(QIODevice *out, const QByteArray &ba)
-{
-    appendInt(out, ba.size());
-    rawWrite(out, ba.constData(), ba.size());
-}
-
-static void appendDictionary(QIODevice *out, const Dictionary &dict)
-{
-    appendInt(out, dict.size());
-    foreach (const QString &key, dict.keys()) {
-        appendString(out, key);
-        appendString(out, dict.value(key));
-    }
-}
-
-static qint64 retrieveInt(QIODevice *in)
-{
-    qint64 n = 0;
-    in->read((char*)&n, sizeof(n));
-    return n;
-}
-
-static QString retrieveString(QIODevice *in)
-{
-    static QByteArray b;
-    qint64 n = retrieveInt(in);
-    if (n * int(sizeof(QChar)) > b.size())
-        b.reserve(n * sizeof(QChar) * 3 / 2);
-    in->read(b.data(), n * sizeof(QChar));
-    QString str((QChar *)b.data(), n);
-    return str;
-}
-
-static QByteArray retrieveByteArray(QIODevice *in)
-{
-    QByteArray ba;
-    qint64 n = retrieveInt(in);
-    ba.resize(n);
-    rawRead(in, ba.data(), n);
-    return ba;
-}
-
-static Dictionary retrieveDictionary(QIODevice *in)
-{
-    Dictionary dict;
-    for (qint64 i = retrieveInt(in); --i >= 0; ) {
-        QString key = retrieveString(in);
-        dict.insert(key, retrieveString(in));
-    }
-    return dict;
-}
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerComponent::Private
-//
-////////////////////////////////////////////////////////////////////
-
-class QInstallerComponent::Private
-{
-public:
-    QInstaller *m_installer;
-    Dictionary m_vars;
-    QList<QInstallerTask *> m_tasks;
-
-    // filled before intaller runs
-    qint64 m_offsetInInstaller;
-};
-
-#if 0
-
-// this is dead slow as QDirIterator::Private::advance needlessly
-// creates tons of QFileInfo objects
-
-static void listDir
-    (const QString &sourcePath0, const QString &targetPath0,
-    QList<QInstallerTask *> *copyTasks,
-    QList<QInstallerTask *> *linkTasks,
-    int sourcePathLength)
-{
-    Q_UNUSED(sourcePathLength);
-    QDirIterator it(sourcePath0, QDir::Files, QDirIterator::Subdirectories);
-    const int pos = sourcePath0.size();
-    while (it.hasNext()) {
-        QString sourcePath = it.next();
-        QFileInfo sourceInfo = it.fileInfo();
-        if (sourceInfo.isSymLink()) {
-            QFileInfo absSourceInfo(sourceInfo.absoluteFilePath());
-            //QString linkTarget = sourceInfo.symLinkTarget();
-            QString absLinkTarget = absSourceInfo.symLinkTarget();
-            //QString relPath = sourceInfo.dir().relativeFilePath(linkTarget);
-            QString absRelPath = absSourceInfo.dir().relativeFilePath(absLinkTarget);
-            if (0) {
-                ifVerbose("\n\nCREATING LINK: "
-                    << "\nSOURCE : " << sourceInfo.filePath()
-                    << "\nSOURCE ABS: " << absSourceInfo.filePath()
-                    //<< "\nLINK : " << linkTarget
-                    << "\nLINK ABS: " << absLinkTarget
-                    //<< "\nREL : " << relPath
-                    << "\nREL ABS: " << absRelPath);
-            }
-            QString targetPath = targetPath0;
-            targetPath += sourcePath.midRef(pos);
-            //qDebug() << "LINK " << absRelPath << targetPath << targetPath0;
-            QInstallerLinkFileTask *task = new QInstallerLinkFileTask(m_installer);
-            task->setLinkTargetPath(absRelPath);
-            task->setTargetPath(targetPath);
-            task->setPermissions(sourceInfo.permissions());
-            linkTasks->append(task);
-        } else {
-            QInstallerCopyFileTask *task = new QInstallerCopyFileTask(m_installer);
-            QString targetPath = targetPath0;
-            targetPath += sourcePath.midRef(pos);
-            //qDebug() << "COPY " << sourcePath << targetPath << targetPath0;
-            task->setSourcePath(sourcePath);
-            task->setTargetPath(targetPath);
-            task->setPermissions(sourceInfo.permissions());
-            copyTasks.append(task);
-        }
-    }
-}
-#else
-
-static void listDir
-    (const QString &sourcePath, const QString &targetPath0,
-    QList<QInstallerTask *> *copyTasks,
-    QList<QInstallerTask *> *linkTasks,
-    QInstaller *installer,
-    int sourcePathLength = -1)
-
-{
-    if (sourcePathLength == -1)
-        sourcePathLength = sourcePath.size();
-    QFileInfo sourceInfo(sourcePath);
-    if (sourceInfo.isDir()) {
-        QDir dir(sourcePath);
-        dir.setSorting(QDir::Unsorted);
-        foreach (const QFileInfo &fi, dir.entryInfoList()) {
-            QString sourceFile = fi.fileName();
-            if (sourceFile == QLatin1String(".")
-                    || sourceFile == QLatin1String(".."))
-                continue;
-            listDir(sourcePath + '/' + sourceFile, targetPath0,
-                copyTasks, linkTasks, installer, sourcePathLength);
-        }
-    } else if (sourceInfo.isSymLink()) {
-        QFileInfo absSourceInfo(sourceInfo.absoluteFilePath());
-        QString absLinkTarget = absSourceInfo.symLinkTarget();
-        QString absRelPath = absSourceInfo.dir().relativeFilePath(absLinkTarget);
-        QString targetPath = targetPath0;
-        targetPath += sourcePath.midRef(sourcePathLength);
-        //qDebug() << "LINK " << absRelPath << targetPath << targetPath0;
-        QInstallerLinkFileTask *task = new QInstallerLinkFileTask(installer);
-        task->setLinkTargetPath(absRelPath);
-        task->setTargetPath(targetPath);
-        task->setPermissions(sourceInfo.permissions());
-        linkTasks->append(task);
-    } else {
-        QInstallerCopyFileTask *task = new QInstallerCopyFileTask(installer);
-        QString targetPath = targetPath0;
-        targetPath += sourcePath.midRef(sourcePathLength);
-        //qDebug() << "COPY " << sourcePath << targetPath << targetPath0;
-        task->setSourcePath(sourcePath);
-        task->setTargetPath(targetPath);
-        task->setPermissions(sourceInfo.permissions());
-        copyTasks->append(task);
-    }
-}
-#endif
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerComponent
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerComponent::QInstallerComponent(QInstaller *installer)
-  : d(new QInstallerComponent::Private)
-{
-    d->m_installer = installer;
-}
-
-
-QInstallerComponent::~QInstallerComponent()
-{
-    qDeleteAll(d->m_tasks);
-    d->m_tasks.clear();
-    delete d;
-}
-
-QString QInstallerComponent::value(const QString &key,
-    const QString &defaultValue) const
-{
-    return d->m_vars.value(key, defaultValue);
-}
-
-void QInstallerComponent::setValue(const QString &key, const QString &value)
-{
-    d->m_vars[key] = value;
-}
-
-void QInstallerComponent::appendDirectoryTasks
-    (const QString &sourcePath0, const QString &targetPath)
-{
-    QList<QInstallerTask *> copyTasks;
-    QList<QInstallerTask *> linkTasks;
-    QString sourcePath = d->m_installer->replaceVariables(sourcePath0);
-    listDir(sourcePath, targetPath, &copyTasks, &linkTasks, d->m_installer);
-    d->m_tasks += copyTasks;
-    d->m_tasks += linkTasks;
-}
-
-void QInstallerComponent::appendSettingsTask
-    (const QString &key, const QString &value)
-{
-    QInstallerWriteSettingsTask *task =
-        new QInstallerWriteSettingsTask(d->m_installer);
-    task->setKey(key);
-    task->setValue(value);
-    appendTask(task);
-}
-
-void QInstallerComponent::appendTask(QInstallerTask *task)
-{
-    d->m_tasks.append(task);
-}
-
-int QInstallerComponent::taskCount() const
-{
-    return d->m_tasks.size();
-}
-
-QInstallerTask *QInstallerComponent::task(int i) const
-{
-    return d->m_tasks.at(i);
-}
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstaller::Private
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerTask *createCopyFileTask(QInstaller *installer)
-{
-    return new QInstallerCopyFileTask(installer);
-}
-
-QInstallerTask *createLinkFileTask(QInstaller *installer)
-{
-    return new QInstallerLinkFileTask(installer);
-}
-
-QInstallerTask *createWriteSettingsTask(QInstaller *installer)
-{
-    return new QInstallerWriteSettingsTask(installer);
-}
-
-QInstallerTask *createPatchFileTask(QInstaller *installer)
-{
-    return new QInstallerPatchFileTask(installer);
-}
-
-QInstallerTask *createMenuShortcutTask(QInstaller *installer)
-{
-    return new QInstallerMenuShortcutTask(installer);
-}
-
-
-
-class QInstaller::Private : public QObject
-{
-    Q_OBJECT;
-
-public:
-    explicit Private(QInstaller *);
-    ~Private();
-
-    void initialize();
-
-    QInstallerTask *createTaskFromCode(int code);
-    void undo(const QList<QInstallerTask *> &tasks);
-    void writeUninstaller(const QList<QInstallerTask *> &tasks);
-    bool statusCanceledOrFailed() const;
-
-    void writeInstaller(QIODevice *out);
-    void writeInstaller();
-    void appendCode(QIODevice *out);
-    void runInstaller();
-    void runUninstaller();
-    void deleteUninstaller();
-    QString uninstallerName() const;
-    QString replaceVariables(const QString &str) const;
-    QByteArray replaceVariables(const QByteArray &str) const;
-    QString registerPath() const;
-    void registerInstaller();
-    void unregisterInstaller();
-    QString installerBinaryPath() const;
-    bool isCreator() const;
-    bool isInstaller() const;
-    bool isUninstaller() const;
-    bool isTempUninstaller() const;
-    QInstaller *installer() const { return q; }
-    bool restartTempUninstaller(const QStringList &args);
-    void setInstallationProgress(qint64 progress); // relative to m_totalProgress
-
-signals:
-    void installationStarted();
-    void installationFinished();
-    void uninstallationStarted();
-    void uninstallationFinished();
-
-public:
-    QInstaller *q;
-
-    Dictionary m_vars;
-    QInstaller::InstallerStatus m_status;
-    bool m_verbose;
-
-    qint64 m_codeSize;
-    qint64 m_tasksStart;
-    qint64 m_variablesStart;
-    qint64 m_componentCount;
-    qint64 m_tasksOffsetsStart;
-    qint64 m_variablesOffsetsStart;
-    qint64 m_variableDataStart;
-    qint64 m_magicMarker;
-    
-    int m_installationProgress;
-    int m_totalProgress;
-    QString m_installationProgressText;
-
-    // Owned. Indexed by component name
-    QList<QInstallerComponent *> m_components;
-    QList<QInstaller::TaskCreator> m_taskCreators;
-};
-
-QInstaller::Private::Private(QInstaller *q_)
-  : q(q_), m_status(QInstaller::InstallerUnfinished), m_verbose(false)
-{
-    connect(this, SIGNAL(installationStarted()),
-        q, SIGNAL(installationStarted()));
-    connect(this, SIGNAL(installationFinished()),
-        q, SIGNAL(installationFinished()));
-    connect(this, SIGNAL(uninstallationStarted()),
-        q, SIGNAL(uninstallationStarted()));
-    connect(this, SIGNAL(uninstallationFinished()),
-        q, SIGNAL(uninstallationFinished()));
-}
-
-QInstaller::Private::~Private()
-{
-    qDeleteAll(m_components);
-    m_components.clear();
-}
-
-
-void QInstaller::Private::initialize()
-{
-    m_installationProgress = 0;
-    m_totalProgress = 100;
-
-    m_vars["ProductName"] = "Unknown Product";
-    m_vars["LogoPixmap"] = ":/resources/logo.png";
-    m_vars["WatermarkPixmap"] = ":/resources/watermark.png";
-
-    QFile in(installerBinaryPath());
-    openForRead(in);
-    m_codeSize = in.size();
-
-    // this reads bogus values for 'creators', but it does not harm
-    in.seek(in.size() - 7 * sizeof(qint64));
-    m_tasksStart = retrieveInt(&in);
-    m_variablesStart = retrieveInt(&in);
-    m_componentCount = retrieveInt(&in);
-    m_tasksOffsetsStart = retrieveInt(&in);
-    m_variablesOffsetsStart = retrieveInt(&in);
-    m_variableDataStart = retrieveInt(&in);
-    m_magicMarker = retrieveInt(&in);
-
-    if (isCreator()) {
-        // valgrind complains otherwise
-        m_tasksStart = 0;
-        m_variablesStart = 0;
-        m_componentCount = 0;
-        m_tasksOffsetsStart = 0;
-        m_variablesOffsetsStart = 0;
-        m_variableDataStart = 0;
-        m_magicMarker = 0;
-    } else {
-        // fix code size
-        m_codeSize = m_tasksStart;
-
-        // merge stored variables
-        in.seek(m_variablesStart);
-
-        for (int i = 0; i != m_componentCount; ++i) {
-            QInstallerComponent *component = new QInstallerComponent(q);
-            component->d->m_vars = retrieveDictionary(&in);
-            qDebug() << "DICT  " << i << component->d->m_vars;
-            m_components.append(component);
-        }
-
-        // read installer variables
-        Dictionary dict = retrieveDictionary(&in);
-        if (m_verbose)
-            qDebug() << "READ VARIABLES FROM INSTALLER:" << dict;
-        foreach (const QString &key, dict.keys()) {
-            if (!m_vars.contains(key))
-                m_vars.insert(key, dict.value(key));
-        }
-        if (m_verbose)
-            qDebug() << "MERGED VARIABLES:" << m_vars;
-    }
-}
-
-void QInstaller::Private::setInstallationProgress(qint64 progress)
-{
-    // from 0 to m_totalProgress
-    int percent = progress * 100 / m_totalProgress;
-    if (percent == m_installationProgress)
-        return;
-    //qDebug() << "setting progress to " << progress
-    //    << " of " << m_totalProgress << " " << percent << "%";
-    m_installationProgress = percent;
-    qApp->processEvents();
-}
-
-QString QInstaller::Private::installerBinaryPath() const
-{
-    return qApp->arguments().at(0);
-}
-
-bool QInstaller::Private::isCreator() const
-{
-    return !isInstaller() && !isUninstaller() && !isTempUninstaller();
-}
-
-bool QInstaller::Private::isInstaller() const
-{
-    return m_magicMarker == magicInstallerMarker;
-}
-
-bool QInstaller::Private::isUninstaller() const
-{
-    return m_magicMarker == magicUninstallerMarker;
-}
-
-bool QInstaller::Private::isTempUninstaller() const
-{
-    return m_magicMarker == magicTempUninstallerMarker;
-}
-
-void QInstaller::Private::writeInstaller()
-{
-    QString fileName = m_vars["OutputFile"];
-#ifdef Q_OS_WIN
-    if (!fileName.endsWith(QLatin1String(".exe")))
-        fileName += QLatin1String(".exe");
-#endif
-    QFile out;
-    out.setFileName(fileName);
-    openForWrite(out);
-    writeInstaller(&out);
-    out.setPermissions(out.permissions() | QFile::WriteUser
-        | QFile::ExeOther | QFile::ExeGroup | QFile::ExeUser);
-}
-
-void QInstaller::Private::writeInstaller(QIODevice *out)
-{
-    appendCode(out);
-
-    QList<qint64> tasksOffsets;
-    QList<qint64> variablesOffsets;
-
-    // write component task data
-    foreach (QInstallerComponent *component, m_components) {
-        qint64 componentStart = out->size();
-        tasksOffsets.append(out->size()); // record start of tasks
-        // pack the component as a whole
-        QBuffer buffer;
-        buffer.open(QIODevice::WriteOnly);
-        foreach (QInstallerTask *task, component->d->m_tasks) {
-            appendInt(&buffer, q->indexOfTaskType(task->creator()));
-            task->writeToInstaller(&buffer);
-        }
-        buffer.close();
-        QByteArray compressed = qCompress(buffer.buffer());
-        int uncompressedSize = buffer.buffer().size();
-        int compressedSize = compressed.size();
-        appendByteArray(out, compressed);
-        qDebug() << "COMPRESS: " << uncompressedSize << compressedSize;
-        component->setValue("TaskCount", QString::number(component->d->m_tasks.size()));
-        component->setValue("ComponentStart", QString::number(componentStart));
-        component->setValue("CompressedSize", QString::number(compressedSize));
-        component->setValue("UncompressedSize", QString::number(uncompressedSize));
-    }
-
-    // write component variables
-    foreach (QInstallerComponent *component, m_components) {
-        variablesOffsets.append(out->size()); // record start of variables
-        appendDictionary(out, component->d->m_vars);
-    }
-
-    // append variables except temporary ones
-    qint64 variableDataStart = out->size();
-    Dictionary dict = m_vars;
-    dict.removeTemporaryKeys();
-    appendDictionary(out, dict);
-
-    // append recorded list of component task offsets
-    qint64 taskOffsetsStart = out->size();
-    foreach (qint64 offset, tasksOffsets)
-        appendInt(out, offset);
-
-    // append recorded list of component varaibles offsets
-    qint64 variablesOffsetsStart = out->size();
-    foreach (qint64 offset, variablesOffsets)
-        appendInt(out, offset);
-
-    // append trailer
-    appendInt(out, tasksOffsets[0]);
-    appendInt(out, variablesOffsets[0]);
-    appendInt(out, m_components.size());
-    appendInt(out, taskOffsetsStart);
-    appendInt(out, variablesOffsetsStart);
-    appendInt(out, variableDataStart);
-    appendInt(out, magicInstallerMarker);
-}
-
-bool QInstaller::Private::statusCanceledOrFailed() const
-{
-    return m_status == QInstaller::InstallerCanceledByUser
-        || m_status == QInstaller::InstallerFailed;
-}
-
-QInstallerTask *QInstaller::Private::createTaskFromCode(int code)
-{
-    if (code >= 0 && code < m_taskCreators.size())
-        return m_taskCreators[code](q);
-    throw Error("NO TASK WITH CODE %1  REGISTERED");
-}
-
-void QInstaller::Private::undo(const QList<QInstallerTask *> &tasks)
-{
-    //qDebug() << "REMOVING" << files.size();
-    // tasks.size() corresponds to m_installationProgress;
-    m_totalProgress = tasks.size() * m_installationProgress / 100 + 1;
-    for (int i = tasks.size(); --i >= 0; ) {
-        QInstallerTask *task = tasks.at(i);
-        setInstallationProgress(i);
-        task->undo();
-    }
-    setInstallationProgress(0);
-}
-
-void QInstaller::Private::appendCode(QIODevice *out)
-{
-    QFile in(installerBinaryPath());
-    openForRead(in);
-    if (m_verbose)
-        qDebug() << "CODE SIZE: " << m_codeSize;
-    appendData(out, &in, m_codeSize);
-    in.close();
-}
-
-QString QInstaller::Private::replaceVariables(const QString &str) const
-{
-    QString res;
-    int pos = 0;
-    while (true) {
-        int pos1 = str.indexOf('@', pos);
-        if (pos1 == -1)
-            break;
-        int pos2 = str.indexOf('@', pos1 + 1);
-        if (pos2 == -1)
-            break;
-        res += str.mid(pos, pos1 - pos);
-        QString name = str.mid(pos1 + 1, pos2 - pos1 - 1);
-        res += m_vars.value(name);
-        pos = pos2 + 1;
-    }
-    res += str.mid(pos);
-    return res;
-}
-
-QByteArray QInstaller::Private::replaceVariables(const QByteArray &ba) const
-{
-    QByteArray res;
-    int pos = 0;
-    while (true) {
-        int pos1 = ba.indexOf('@', pos);
-        if (pos1 == -1)
-            break;
-        int pos2 = ba.indexOf('@', pos1 + 1);
-        if (pos2 == -1)
-            break;
-        res += ba.mid(pos, pos1 - pos);
-        QString name = QString::fromLocal8Bit(ba.mid(pos1 + 1, pos2 - pos1 - 1));
-        res += m_vars.value(name).toLocal8Bit();
-        pos = pos2 + 1;
-    }
-    res += ba.mid(pos);
-    return res;
-}
-
-QString QInstaller::Private::uninstallerName() const
-{
-    QString name = m_vars["TargetDir"];
-    name += "/uninstall";
-#ifdef Q_OS_WIN
-    name += QLatin1String(".exe");
-#endif
-    return name;
-}
-
-void QInstaller::Private::writeUninstaller(const QList<QInstallerTask *> &tasks)
-{
-    QFile out(uninstallerName());
-    try {
-        ifVerbose("CREATING UNINSTALLER " << tasks.size());
-        // Create uninstaller. this is basically a clone of ourselves
-        // with a few changed variables
-        openForWrite(out);
-        appendCode(&out);
-        qint64 tasksStart = out.size();
-        appendInt(&out, tasks.size());
-
-        for (int i = tasks.size(); --i >= 0; ) {
-            QInstallerTask *task = tasks.at(i);
-            appendInt(&out, m_taskCreators.indexOf(task->creator()));
-            task->writeToUninstaller(&out); // might throw
-        }
-
-        // append variables except temporary ones
-        qint64 variableDataStart = out.size();
-        Dictionary dict = m_vars;
-        dict.removeTemporaryKeys();
-        dict.setValue(QLatin1String("UninstallerPath"), uninstallerName());
-        appendDictionary(&out, dict);
-
-        // append trailer
-        appendInt(&out, tasksStart);
-        appendInt(&out, variableDataStart); // variablesStart
-        appendInt(&out, 0); // componentCount
-        appendInt(&out, 0); // tasksOffsetsStart
-        appendInt(&out, 0); // variablesOffsetsStart
-        appendInt(&out, variableDataStart);
-        appendInt(&out, magicUninstallerMarker);
-
-        out.setPermissions(out.permissions() | QFile::WriteUser
-            | QFile::ExeOther | QFile::ExeGroup | QFile::ExeUser);
-    }
-    catch (const QInstallerError &err) {
-        m_status = QInstaller::InstallerFailed;
-        // local roll back
-        qDebug() << "WRITING TO UNINSTALLER FAILED: " << err.message();
-        out.close();
-        out.remove();
-        throw;
-    }
-}
-
-QString QInstaller::Private::registerPath() const
-{
-    QString productName = m_vars["ProductName"];
-    if (productName.isEmpty())
-        throw QInstallerError("ProductName should be set");
-    QString path;
-    if (m_vars["AllUsers"] == "true")
-        path += "HKEY_LOCAL_MACHINE";
-    else
-        path += "HKEY_CURRENT_USER";
-    path += "\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
-    path += productName;
-    return path;
-}
-
-void QInstaller::Private::registerInstaller()
-{
-#ifdef Q_OS_WIN
-    QSettings settings(registerPath(), QSettings::NativeFormat);
-    settings.beginGroup("CurrentVersion");
-    settings.beginGroup("Uninstall");
-    settings.beginGroup(m_vars["ProductName"]);
-    settings.setValue("Comments", m_vars["Comments"]);
-    settings.setValue("Contact", m_vars["Contact"]);
-    settings.setValue("DisplayName", m_vars["ProductName"]);
-    settings.setValue("DisplayVersion", m_vars["DisplayVersion"]);
-    settings.setValue("EstimatedSize", "X4957efb0");
-    settings.setValue("HelpLink", m_vars["HelpLink"]);
-    settings.setValue("InstallDate", QDateTime::currentDateTime().toString());
-    settings.setValue("InstallLocation", m_vars["TargetDir"]);
-    settings.setValue("NoModify", "1");
-    settings.setValue("NoRepair", "1");
-    settings.setValue("Publisher", m_vars["Publisher"]);
-    settings.setValue("UninstallString", uninstallerName());
-    settings.setValue("UrlInfoAbout", m_vars["UrlInfoAbout"]);
-#endif
-}
-
-void QInstaller::Private::unregisterInstaller()
-{
-#ifdef Q_OS_WIN
-    QSettings settings(registerPath(), QSettings::NativeFormat);
-    settings.remove(QString());
-#endif
-}
-
-void QInstaller::Private::runInstaller()
-{
-    QList<QInstallerTask *> tasks;
-
-    try {
-        emit installationStarted();
-        if (!m_vars.contains("TargetDir"))
-            throw QInstallerError(QLatin1String("Variable 'TargetDir' not set."));
-
-        QFile in(installerBinaryPath());
-        openForRead(in);
-
-        m_totalProgress = 0;
-        QList<QInstallerComponent *> componentsToInstall;
-
-        for (int i = 0; i != m_componentCount; ++i) {
-            QInstallerComponent *comp = m_components.at(i);
-            QString wantedState = comp->value("WantedState");
-            ifVerbose("HANDLING COMPONENT" << i << "WANTED: " << wantedState);
-            if (wantedState == "Uninstalled") {
-                qDebug() << "SKIPPING COMPONENT" << comp->value("DisplayName");
-                continue;
-            }
-            componentsToInstall.append(comp);
-            m_totalProgress += comp->value("UncompressedSize").toInt();
-        }
-            
-        qDebug() << "Install size: " << m_totalProgress
-            << "in " << componentsToInstall.size() << "components";
-
-        qint64 lastProgressBase = 0;
-        foreach (QInstallerComponent *comp, componentsToInstall) {
-            int taskCount = comp->value("TaskCount").toInt();
-            quint64 componentStart = comp->value("ComponentStart").toInt();
-            in.seek(componentStart);
-            if (statusCanceledOrFailed())
-                throw Error("Installation canceled by user");
-            m_installationProgressText =
-                tr("Decompressing component %1").arg(comp->value("DisplayName"));
-            qApp->processEvents();
-            QByteArray compressed = retrieveByteArray(&in);
-            QByteArray uncompressed = qUncompress(compressed);
-            if (uncompressed.isEmpty()) {
-                qDebug() << "SIZE: " << compressed.size() << " TASK COUNT: " << taskCount
-                    << uncompressed.size();
-                throw Error("DECOMPRESSION FAILED");
-            }
-            QBuffer buffer(&uncompressed);
-            buffer.open(QIODevice::ReadOnly);
-            for (int j = 0; j != taskCount; ++j) {
-                int code = retrieveInt(&buffer);
-                QInstallerTask *task = createTaskFromCode(code); // might throw
-                task->readAndExecuteFromInstaller(&buffer); // might throw
-                tasks.append(task);
-                if (statusCanceledOrFailed())
-                    throw Error("Installation canceled by user");
-                setInstallationProgress(lastProgressBase + buffer.pos());
-            }
-            comp->setValue("CurrentState", "Installed");
-            lastProgressBase += uncompressed.size();
-        }
-        in.close();
-
-        registerInstaller();
-        writeUninstaller(tasks);
-
-        m_status = InstallerSucceeded;
-        m_installationProgressText = tr("Installation finished!");
-        qApp->processEvents();
-        emit installationFinished();
-    }
-    catch (const QInstallerError &err) {
-        installer()->showWarning(err.message());
-        qDebug() << "INSTALLER FAILED: " << err.message() << "\nROLLING BACK";
-        undo(tasks);
-        m_installationProgressText = tr("Installation aborted");
-        qApp->processEvents();
-        emit installationFinished();
-        throw;
-    }
-}
-
-bool QInstaller::Private::restartTempUninstaller(const QStringList &args)
-{
-#ifdef Q_OS_WIN
-    ifVerbose("Running uninstaller on Windows.");
-    if (isUninstaller()) {
-        QString uninstallerFile = installerBinaryPath();
-        QDir tmpDir = QDir::temp();
-        QString tmpDirName = QLatin1String("qtcreator_uninst");
-        QString tmpAppName = QLatin1String("uninst.exe");
-        if (!tmpDir.exists(tmpDirName)) {
-            tmpDir.mkdir(tmpDirName);
-            if (!tmpDir.exists(tmpDirName)) {
-                ifVerbose("Could not create temporary folder!");
-                return false;
-            }
-            tmpDir.cd(tmpDirName);
-        }
-
-        if (tmpDir.exists(tmpAppName) && !tmpDir.remove(tmpAppName)) {
-            ifVerbose("Could not remove old temporary uninstaller!");
-            return false;
-        }
-
-        QString tmpUninstaller = tmpDir.absoluteFilePath(tmpAppName);
-
-        QFile in(uninstallerFile);
-        if (!in.open(QIODevice::ReadOnly)) {
-            ifVerbose("Cannot open uninstall.exe!");
-            return false;
-        }
-
-        QFile out(tmpUninstaller);
-        if (!out.open(QIODevice::WriteOnly)) {
-            ifVerbose("Cannot open temporary uninstall.exe!");
-            return false;
-        }
-
-        QByteArray ba = in.readAll();
-        QBuffer buf(&ba);
-        buf.open(QIODevice::ReadWrite);
-        buf.seek(buf.size() - sizeof(qint64));
-        appendInt(&buf, magicTempUninstallerMarker);
-        if (in.size() != out.write(buf.data())) {
-            ifVerbose("Could not copy uninstaller!");
-            return false;
-        }
-
-        in.close();
-        out.close();
-
-        MoveFileExW((TCHAR*)tmpUninstaller.utf16(),
-            0, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING);
-
-        STARTUPINFOW sInfo;
-        PROCESS_INFORMATION pInfo;
-        memset(&sInfo, 0, sizeof(sInfo));
-        memset(&pInfo, 0, sizeof(pInfo));
-        sInfo.cb = sizeof(sInfo);
-
-        QString cmd = QString("\"%1\"").arg(tmpUninstaller);
-        foreach (const QString &s, args)
-            cmd.append(QLatin1String(" \"") + s + QLatin1String("\""));
-        if (CreateProcessW(0, (TCHAR*)cmd.utf16(), 0, 0, false, 0, 0, 0, &sInfo, &pInfo)) {
-            CloseHandle(pInfo.hThread);
-            CloseHandle(pInfo.hProcess);
-            ifVerbose("Started temp uninstaller.");
-        } else {
-            ifVerbose("Cannot launch uninstaller!");
-            return false;
-        }
-    }
-#else
-    Q_UNUSED(args);
-#endif
-    return true;
-}
-
-void QInstaller::Private::runUninstaller()
-{
-    QFile uninstaller(installerBinaryPath());
-    openForRead(uninstaller);
-    QByteArray ba = uninstaller.readAll();
-    uninstaller.close();
-
-    emit uninstallationStarted();
-#ifndef Q_OS_WIN
-    // remove uninstaller binary itself. Also necessary for successful
-    // removal of the application directory.
-    uninstaller.remove();
-#else
-    if (m_vars.contains(QLatin1String("UninstallerPath"))) {
-        QFile orgUninstaller(m_vars.value(QLatin1String("UninstallerPath")));
-        orgUninstaller.remove();
-    }
-#endif
-
-    // read file
-    QBuffer in(&ba);
-    in.open(QIODevice::ReadOnly);
-    in.seek(m_tasksStart);
-    qint64 taskCount = retrieveInt(&in);
-    ifVerbose("FOUND " << taskCount << "UNINSTALLER TASKS");
-
-    m_totalProgress = m_variablesStart;
-    for (int i = 0; i != taskCount; ++i) {
-        int code = retrieveInt(&in);
-        QInstallerTask *task = createTaskFromCode(code);
-        task->readAndExecuteFromUninstaller(&in);
-        setInstallationProgress(in.pos());
-    }
-    in.close();
-
-    unregisterInstaller();
-
-    m_installationProgressText = tr("Deinstallation finished");
-    qApp->processEvents();
-    emit uninstallationFinished();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstaller
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::QInstaller()
-{
-    d = new Private(this);
-    d->initialize();
-    registerTaskType(createCopyFileTask);
-    registerTaskType(createLinkFileTask);
-    registerTaskType(createPatchFileTask);
-    registerTaskType(createWriteSettingsTask);
-    registerTaskType(createMenuShortcutTask);
-}
-
-QInstaller::~QInstaller()
-{
-    delete d;
-}
-
-void QInstaller::appendComponent(QInstallerComponent *component)
-{
-    d->m_components.append(component);
-}
-
-int QInstaller::componentCount() const
-{
-    return d->m_components.size();
-}
-
-QInstallerComponent *QInstaller::component(int i) const
-{
-    return d->m_components.at(i);
-}
-
-void QInstaller::registerTaskType(TaskCreator tc)
-{
-    d->m_taskCreators.append(tc);
-}
-
-int QInstaller::indexOfTaskType(TaskCreator tc) const
-{
-    return d->m_taskCreators.indexOf(tc);
-}
-
-QString QInstaller::value(const QString &key, const QString &defaultValue) const
-{
-    return d->m_vars.value(key, defaultValue);
-}
-
-void QInstaller::setValue(const QString &key, const QString &value)
-{
-    d->m_vars[key] = value;
-}
-
-bool QInstaller::containsValue(const QString &key) const
-{
-    return d->m_vars.contains(key);
-}
-
-bool QInstaller::isVerbose() const
-{
-    return d->m_verbose;
-}
-
-void QInstaller::setVerbose(bool on)
-{
-    d->m_verbose = on;
-}
-
-QInstaller::InstallerStatus QInstaller::status() const
-{
-    return d->m_status;
-}
-
-void QInstaller::interrupt()
-{
-    qDebug() << "INTERRUPT INSTALLER";
-    d->m_status = InstallerCanceledByUser;
-}
-
-QString QInstaller::replaceVariables(const QString &str) const
-{
-    return d->replaceVariables(str);
-}
-
-QByteArray QInstaller::replaceVariables(const QByteArray &ba) const
-{
-    return d->replaceVariables(ba);
-}
-
-int QInstaller::installationProgress() const
-{
-    return d->m_installationProgress;
-}
-
-void QInstaller::setInstallationProgressText(const QString &value)
-{
-    d->m_installationProgressText = value;
-}
-
-QString QInstaller::installationProgressText() const
-{
-    return d->m_installationProgressText;
-}
-
-QString QInstaller::installerBinaryPath() const
-{
-    return d->installerBinaryPath();
-}
-
-bool QInstaller::isCreator() const
-{
-    return d->isCreator();
-}
-
-bool QInstaller::isInstaller() const
-{
-    return d->isInstaller();
-}
-
-bool QInstaller::isUninstaller() const
-{
-    return d->isUninstaller();
-}
-
-bool QInstaller::isTempUninstaller() const
-{
-    return d->isTempUninstaller();
-}
-
-bool QInstaller::runInstaller()
-{
-    try { d->runInstaller(); return true; } catch (...) { return false; }
-}
-
-bool QInstaller::runUninstaller()
-{
-    try { d->runUninstaller(); return true; } catch (...) { return false; }
-}
-
-void QInstaller::showWarning(const QString &str)
-{
-    emit warning(str);
-}
-
-void QInstaller::dump() const
-{
-    qDebug() << "COMMAND LINE VARIABLES:" << d->m_vars;
-}
-
-void QInstaller::appendInt(QIODevice *out, qint64 n)
-{
-    QT_PREPEND_NAMESPACE(appendInt)(out, n);
-}
-
-void QInstaller::appendString(QIODevice *out, const QString &str)
-{
-    QT_PREPEND_NAMESPACE(appendString)(out, str);
-}
-
-void QInstaller::appendByteArray(QIODevice *out, const QByteArray &str)
-{
-    QT_PREPEND_NAMESPACE(appendByteArray)(out, str);
-}
-
-qint64 QInstaller::retrieveInt(QIODevice *in)
-{
-    return QT_PREPEND_NAMESPACE(retrieveInt)(in);
-}
-
-QString QInstaller::retrieveString(QIODevice *in)
-{
-    return QT_PREPEND_NAMESPACE(retrieveString)(in);
-}
-
-QByteArray QInstaller::retrieveByteArray(QIODevice *in)
-{
-    return QT_PREPEND_NAMESPACE(retrieveByteArray)(in);
-}
-
-bool QInstaller::run()
-{
-    try {
-        if (isCreator()) {
-            createTasks(); // implemented in derived classes
-            d->writeInstaller();
-        } else if (isInstaller()) {
-            d->runInstaller();
-        } else if (isUninstaller() || isTempUninstaller()) {
-            runUninstaller();
-        }
-        return true;
-    } catch (const QInstallerError &err) {
-        qDebug() << "Caught Installer Error: " << err.message();
-        return false;
-    }
-}
-
-QString QInstaller::uninstallerName() const
-{
-    return d->uninstallerName();
-}
-
-QString QInstaller::libraryName(const QString &baseName, const QString &version)
-{
-#ifdef Q_OS_WIN
-    return baseName + QLatin1String(".dll");
-#elif Q_OS_MAC
-    return QString("lib%1.dylib").arg(baseName);
-#else
-    return QString("lib%1.so.%2").arg(baseName).arg(version);    
-#endif
-}
-
-bool QInstaller::restartTempUninstaller(const QStringList &args)
-{
-    return d->restartTempUninstaller(args);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerTask
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerTask::QInstallerTask(QInstaller *parent)
-  : m_installer(parent)
-{}
-
-QInstaller *QInstallerTask::installer() const
-{
-    return m_installer;
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerCopyFileTask
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::TaskCreator QInstallerCopyFileTask::creator() const
-{
-    return &createCopyFileTask;
-}
-
-void QInstallerCopyFileTask::writeToInstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendInt(out, m_permissions);
-    QFile file(m_sourcePath);
-    openForRead(file);
-    appendFileData(out, &file);
-}
-
-static int createParentDirs(const QString &absFileName)
-{
-    QFileInfo fi(absFileName);
-    if (fi.isDir())
-        return 0;
-    QString dirName = fi.path();
-    int n = createParentDirs(dirName);
-    QDir dir(dirName);
-    dir.mkdir(fi.fileName());
-    return n + 1;
-}
-
-void QInstallerCopyFileTask::readAndExecuteFromInstaller(QIODevice *in)
-{
-    m_targetPath = installer()->replaceVariables(retrieveString(in));
-    m_permissions = retrieveInt(in);
-    ifVerbose("EXECUTE COPY FILE, TARGET " << m_targetPath);
-
-    QString path = QDir::cleanPath(QFileInfo(m_targetPath).absolutePath());
-    m_parentDirCount = createParentDirs(path);
-    QString msg = QInstaller::tr("Copying file %1").arg(m_targetPath);
-    installer()->setInstallationProgressText(msg);
-
-    QFile file(m_targetPath);
-    bool res = file.open(QIODevice::WriteOnly);
-    if (!res) {
-        // try to make it writeable, and try again
-        bool res1 = file.setPermissions(file.permissions()|QFile::WriteOwner);
-        ifVerbose("MAKE WRITABLE: " << res1);
-        res = file.open(QIODevice::WriteOnly);
-    }
-    if (!res) {
-        // try to remove it, and try again
-        bool res1 = file.remove();
-        ifVerbose("REMOVING FILE: " << res1);
-        res = file.open(QIODevice::WriteOnly);
-    }
-
-    if (!res) {
-        QString msg = QInstaller::tr("The file %1 is not writeable.")
-            .arg(m_targetPath);
-        installer()->showWarning(msg);
-        throw Error(msg);
-    }
-    retrieveFileData(&file, in);
-    QFile::Permissions perms(m_permissions | QFile::WriteOwner);
-    file.close();
-    file.setPermissions(perms);
-}
-
-void QInstallerCopyFileTask::writeToUninstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendInt(out, m_parentDirCount);
-}
-
-void QInstallerCopyFileTask::readAndExecuteFromUninstaller(QIODevice *in)
-{
-    m_targetPath = retrieveString(in);
-    m_parentDirCount = retrieveInt(in);
-    undo();
-}
-
-void QInstallerCopyFileTask::undo()
-{
-    ifVerbose("UNLINKING FILE" << m_targetPath << m_parentDirCount);
-    QString msg = QInstaller::tr("Removing %1").arg(m_targetPath);
-    installer()->setInstallationProgressText(msg);
-
-    QFileInfo fi(m_targetPath);
-    QDir dir(fi.path());
-
-    QFile file(m_targetPath);
-    bool res = file.remove();
-    if (!res) {
-        // try to make it writeable, and try again
-        bool res1 = file.setPermissions(file.permissions()|QFile::WriteOwner);
-        ifVerbose("MAKE WRITABLE: " << res1);
-        res = file.remove();
-    }
-    
-    while (res && --m_parentDirCount >= 0) {
-        QString dirName = dir.dirName();
-        dir.cdUp();
-        res = dir.rmdir(dirName);
-        msg = QInstaller::tr("Removing file %1").arg(m_targetPath);
-        installer()->setInstallationProgressText(msg);
-        ifVerbose("REMOVING DIR " << dir.path() << dirName << res);
-    }
-}
-
-void QInstallerCopyFileTask::dump(QDebug & os) const
-{
-    os << "c|" + sourcePath() + '|' + targetPath();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerLinkFileTask
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::TaskCreator QInstallerLinkFileTask::creator() const
-{
-    return &createLinkFileTask;
-}
-
-void QInstallerLinkFileTask::writeToInstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendString(out, m_linkTargetPath);
-    appendInt(out, m_permissions);
-}
-
-void QInstallerLinkFileTask::readAndExecuteFromInstaller(QIODevice *in)
-{
-    m_targetPath = installer()->replaceVariables(retrieveString(in));
-    m_linkTargetPath = installer()->replaceVariables(retrieveString(in));
-    m_permissions = retrieveInt(in);
-
-    ifVerbose("LINK " << m_targetPath << " TARGET " << m_linkTargetPath);
-
-    QFile file(m_linkTargetPath);
-    if (file.link(m_targetPath))
-        return;
-
-    // ok. linking failed. try to remove targetPath and link again
-    bool res1 = QFile::remove(m_targetPath);
-    ifVerbose("TARGET EXITS, REMOVE: " << m_targetPath << res1);
-    if (file.link(m_targetPath))
-        return;
-
-    // nothing helped.
-    throw Error(QInstaller::tr("Cannot link file %1 to %2:\n")
-            .arg(m_linkTargetPath).arg(m_targetPath));
-}
-
-void QInstallerLinkFileTask::writeToUninstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-}
-
-void QInstallerLinkFileTask::readAndExecuteFromUninstaller(QIODevice *in)
-{
-    m_targetPath = retrieveString(in);
-    ifVerbose("UNLINKING LINK" << m_targetPath);
-    undo();
-}
-
-void QInstallerLinkFileTask::undo()
-{
-    QFile file(m_targetPath);
-    file.remove();
-}
-
-void QInstallerLinkFileTask::dump(QDebug & os) const
-{
-     os << "l|" + targetPath() + '|' + linkTargetPath();
-}
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerWriteSettingsTask
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::TaskCreator QInstallerWriteSettingsTask::creator() const
-{
-    return &createWriteSettingsTask;
-}
-
-void QInstallerWriteSettingsTask::writeToInstaller(QIODevice *out) const
-{
-    appendString(out, m_key);
-    appendString(out, m_value);
-}
-
-void QInstallerWriteSettingsTask::readAndExecuteFromInstaller(QIODevice *in)
-{
-    m_key = installer()->replaceVariables(retrieveString(in));
-    m_value = installer()->replaceVariables(retrieveString(in));
-    QSettings settings;
-    settings.setValue(m_key, m_value);
-}
-
-void QInstallerWriteSettingsTask::writeToUninstaller(QIODevice *out) const
-{
-    appendString(out, m_key);
-    appendString(out, m_value);
-}
-
-void QInstallerWriteSettingsTask::readAndExecuteFromUninstaller(QIODevice *in)
-{
-    m_key = installer()->replaceVariables(retrieveString(in));
-    m_value = installer()->replaceVariables(retrieveString(in));
-    undo();
-}
-
-void QInstallerWriteSettingsTask::undo()
-{
-    QSettings settings;
-    settings.setValue(m_key, QString());
-}
-
-void QInstallerWriteSettingsTask::dump(QDebug & os) const
-{
-    os << "s|" + key() + '|' + value();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerPatchFileTask
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::TaskCreator QInstallerPatchFileTask::creator() const
-{
-    return &createPatchFileTask;
-}
-
-void QInstallerPatchFileTask::writeToInstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendByteArray(out, m_needle);
-    appendByteArray(out, m_replacement);
-}
-
-void QInstallerPatchFileTask::readAndExecuteFromInstaller(QIODevice *in)
-{
-    m_targetPath = installer()->replaceVariables(retrieveString(in));
-    m_needle = retrieveByteArray(in);
-    m_replacement = installer()->replaceVariables(retrieveByteArray(in));
-    ifVerbose("PATCHING" << m_replacement << m_needle << m_targetPath);
-
-    QFile file;
-    file.setFileName(m_targetPath);
-    if (!file.open(QIODevice::ReadWrite))
-        throw Error(QInstaller::tr("Cannot open file %1 for reading").arg(file.fileName()));
-
-    uchar *data = file.map(0, file.size());
-    if (!data)
-        throw Error(QInstaller::tr("Cannot map file %1").arg(file.fileName()));
-    QByteArray ba = QByteArray::fromRawData((const char *)data, file.size());
-    int pos = ba.indexOf(m_needle);
-    if (pos != -1) {
-        for (int i = m_replacement.size(); --i >= 0; )
-            data[pos + i] = m_replacement.at(i);
-    }
-    if (!file.unmap(data))
-        throw Error(QInstaller::tr("Cannot unmap file %1").arg(file.fileName()));
-    file.close();
-}
-
-void QInstallerPatchFileTask::dump(QDebug & os) const
-{
-     os << "p|" + targetPath() + '|' + needle() + '|' + replacement();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerMenuShortcutTask
-//
-//
-// Usage:
-//
-// static const struct
-// {
-//     const char *target;
-//     const char *linkTarget;
-// } menuShortcuts[] = {
-//     {"Qt Creator by Nokia\\Run Qt Creator", "bin\\qtcreator.exe"},
-//     {"Qt Creator by Nokia\\Readme", "readme.txt"},
-//     {"Qt Creator by Nokia\\Uninstall", "uninstall.exe"}
-// };
-//
-// for (int i = 0; i != sizeof(menuShortcuts) / sizeof(menuShortcuts[0]); ++i) {
-//     QInstallerMenuShortcutTask *task = new QInstallerMenuShortcutTask(this);
-//     task->setTargetPath(menuShortcuts[i].target);
-//     task->setLinkTargetPath(QLatin1String("@TargetDir@\\") + menuShortcuts[i].linkTarget);
-// }
-//
-////////////////////////////////////////////////////////////////////
-
-QInstaller::TaskCreator QInstallerMenuShortcutTask::creator() const
-{
-    return &createMenuShortcutTask;
-}
-
-void QInstallerMenuShortcutTask::writeToInstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendString(out, m_linkTargetPath);
-}
-
-void QInstallerMenuShortcutTask::readAndExecuteFromInstaller(QIODevice *in)
-{
-    m_targetPath = installer()->replaceVariables(retrieveString(in));
-    m_linkTargetPath = installer()->replaceVariables(retrieveString(in));
-
-#ifdef Q_OS_WIN
-    QString workingDir = installer()->value(QLatin1String("TargetDir"));
-    bool res = false;
-    HRESULT hres;
-    IShellLink *psl;
-    bool neededCoInit = false;
-
-    ifVerbose("CREATE MENU SHORTCUT: " << m_targetPath << " TARGET " << m_linkTargetPath);
-
-    if (installer()->value(QLatin1String("AllUsers")) == "true") {
-        QSettings registry(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows"
-            "\\CurrentVersion\\Explorer\\Shell Folders"), QSettings::NativeFormat);
-        m_startMenuPath = registry.value(QLatin1String("Common Programs"), QString()).toString();
-    } else {
-        QSettings registry(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows"
-            "\\CurrentVersion\\Explorer\\Shell Folders"), QSettings::NativeFormat);
-        m_startMenuPath = registry.value(QLatin1String("Programs"), QString()).toString();
-    }
-    if (m_startMenuPath.isEmpty()) {
-        ifVerbose("CREATE MENU SHORTCUT: Cannot find start menu folder!");
-        return;
-    }
-
-    if (!m_targetPath.isEmpty()) {
-        if (!m_targetPath.endsWith(QLatin1String(".lnk")))
-            m_targetPath.append(QLatin1String(".lnk"));
-        m_targetPath = m_targetPath.replace('/', '\\');
-        int i = m_targetPath.lastIndexOf('\\');
-        if (i > -1) {
-            QDir dir(m_startMenuPath);
-            if (!dir.exists(m_targetPath.left(i)))
-                dir.mkpath(m_targetPath.left(i));
-        }
-
-        if (m_linkTargetPath.isEmpty())
-            return;
-
-        QString trgt = m_linkTargetPath;
-        if (trgt.startsWith('\"')) {
-            trgt = trgt.left(trgt.indexOf('\"', 1) + 1);
-        } else {
-            trgt = trgt.left(trgt.indexOf(' '));
-        }
-        if (trgt.isEmpty())
-            trgt = m_linkTargetPath;
-
-        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
-        if (hres == CO_E_NOTINITIALIZED) {
-            neededCoInit = true;
-            CoInitialize(NULL);
-            hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
-                (void **)&psl);
-        }
-        if (SUCCEEDED(hres)) {
-            hres = psl->SetPath((wchar_t *)trgt.utf16());
-            if (SUCCEEDED(hres)) {
-                hres = psl->SetArguments((wchar_t *)m_linkTargetPath.mid(trgt.length()).utf16());
-                if (SUCCEEDED(hres)) {
-                    hres = psl->SetWorkingDirectory((wchar_t *)workingDir.utf16());
-                    if (SUCCEEDED(hres)) {
-                        IPersistFile *ppf;
-                        hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
-                        if (SUCCEEDED(hres)) {
-                            hres = ppf->Save((TCHAR*)QString(m_startMenuPath
-                                + QDir::separator() + m_targetPath).utf16(), TRUE);
-                            if (SUCCEEDED(hres))
-                                res = true;
-                            ppf->Release();
-                        }
-                    }
-                }
-            }
-            psl->Release();
-        }
-        if (neededCoInit)
-            CoUninitialize();
-    }
-    if (!res) {
-        QString msg = QInstaller::tr("Cannot create menu shortcut %1 to %2:\n")
-            .arg(m_linkTargetPath).arg(m_targetPath);
-        installer()->showWarning(msg);
-        return;
-    }
-#endif
-}
-
-void QInstallerMenuShortcutTask::writeToUninstaller(QIODevice *out) const
-{
-    appendString(out, m_targetPath);
-    appendString(out, m_startMenuPath);
-}
-
-void QInstallerMenuShortcutTask::readAndExecuteFromUninstaller(QIODevice *in)
-{
-    m_targetPath = retrieveString(in);
-    m_startMenuPath = retrieveString(in);
-    ifVerbose("REMOVE MENU SHORTCUT: " << m_targetPath);
-    undo();
-}
-
-void QInstallerMenuShortcutTask::undo()
-{
-#ifdef Q_OS_WIN
-    QFileInfo fi(m_startMenuPath + QDir::separator() + m_targetPath);
-    QString path = fi.absoluteFilePath();
-    if (fi.isFile()) {
-        path = fi.absolutePath();
-        QFile file(fi.absoluteFilePath());
-        file.remove();
-    }
-    QDir dir(m_startMenuPath);
-    dir.rmpath(path);
-#endif
-}
-
-void QInstallerMenuShortcutTask::dump(QDebug & os) const
-{
-     os << "msc|" + targetPath() + '|' + linkTargetPath();
-}
-
-QT_END_NAMESPACE
-
-#include "qinstaller.moc"
diff --git a/installer/qinstaller.h b/installer/qinstaller.h
deleted file mode 100644
index ea3a97f8d517f296c8b81220d9e6992c8a95b5a4..0000000000000000000000000000000000000000
--- a/installer/qinstaller.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact:  Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file.  Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-
-#ifndef QINSTALLER_H
-#define QINSTALLER_H
-
-#include <QtCore/QObject>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QIODevice;
-class QInstallerTask;
-class QInstallerComponent;
-
-class QInstaller : public QObject
-{
-    Q_OBJECT
-
-public:
-    QInstaller();
-    ~QInstaller();
-
-    bool run();
-
-    // parameter handling
-    void setValue(const QString &key, const QString &value);
-    QString value(const QString &key,
-        const QString &defaultValue = QString()) const;
-    bool containsValue(const QString &key) const;
-    QString replaceVariables(const QString &str) const;
-    QByteArray replaceVariables(const QByteArray &str) const;
-    QString installerBinaryPath() const;
-    QString uninstallerName() const;
-
-    // installer-specific task creation
-    virtual void createTasks() {}
-
-    // component handling
-    void appendComponent(QInstallerComponent *components);
-    int componentCount() const;
-    QInstallerComponent *component(int i) const;
-    typedef QInstallerTask *(*TaskCreator)(QInstaller *);
-    void registerTaskType(TaskCreator);
-    int indexOfTaskType(TaskCreator) const;
-
-    // progress handling
-    //void setInstallationProgress(int);
-    int installationProgress() const;
-    void setInstallationProgressText(const QString &);
-    QString installationProgressText() const;
-    
-    // convenience
-    bool isCreator() const; 
-    bool isInstaller() const;
-    bool isUninstaller() const;
-    bool isTempUninstaller() const;
-
-    bool isVerbose() const;
-    void setVerbose(bool on); 
-    void connectGui(QObject *gui);
-    
-    QString libraryName(const QString &baseName, const QString &version);
-    
-    bool restartTempUninstaller(const QStringList &args);
-
-    // status
-    enum InstallerStatus {
-        InstallerUnfinished,
-        InstallerCanceledByUser,
-        InstallerFailed,
-        InstallerSucceeded,
-    };
-    InstallerStatus status() const;
-
-    // I/O helper for authors of classes deriving from QInstallerStep
-    static void appendInt(QIODevice *out, qint64 n);
-    static void appendString(QIODevice *out, const QString &str);
-    static void appendByteArray(QIODevice *out, const QByteArray &str);
-    static qint64 retrieveInt(QIODevice *in);
-    static QString retrieveString(QIODevice *in);
-    static QByteArray retrieveByteArray(QIODevice *in);
-
-    void dump() const;
-    class Private;
-
-public slots:
-    bool runInstaller();
-    bool runUninstaller();
-    void interrupt();
-    void showWarning(const QString &);
-
-signals:
-    void installationStarted();    
-    void installationFinished();
-    void uninstallationStarted();    
-    void uninstallationFinished();
-    void warning(QString);
-
-private:
-    Private *d;
-};
-
-
-class QInstallerComponent 
-{
-public:
-    explicit QInstallerComponent(QInstaller *installer);
-    ~QInstallerComponent();
-
-    void setValue(const QString &key, const QString &value);
-    QString value(const QString &key,
-        const QString &defaultValue = QString()) const;
-
-    void appendTask(QInstallerTask *step);
-    void appendDirectoryTasks(const QString &sourcePath,
-        const QString &targetPath);
-    void appendSettingsTask(const QString &key, const QString &value);
-    void appendUninstallerRegistrationTask();
-    int taskCount() const;
-    QInstallerTask *task(int) const;
-
-    friend class QInstaller;
-    friend class QInstaller::Private;
-private:
-    Q_DISABLE_COPY(QInstallerComponent);
-    class Private;
-    Private *d;
-};
-
-
-class QInstallerTask 
-{
-public:
-    QInstallerTask(QInstaller *parent);
-    virtual ~QInstallerTask() {}
-
-    QInstaller *installer() const;
-
-    virtual void writeToInstaller(QIODevice *out) const = 0;
-    virtual void readAndExecuteFromInstaller(QIODevice *in) = 0;
-
-    virtual void writeToUninstaller(QIODevice *out) const = 0;
-    virtual void readAndExecuteFromUninstaller(QIODevice *in) = 0;
-
-    virtual void undo() = 0;
-    virtual void dump(QDebug &) const {}
-
-    virtual QInstaller::TaskCreator creator() const = 0;
-
-private:
-    QInstaller *m_installer;
-};
-
-
-class QInstallerError
-{
-public:
-    QInstallerError(const QString &m) : m_message(m) {}
-    virtual ~QInstallerError() {}
-    virtual QString message() const { return m_message; }
-private:
-    QString m_message;
-};
-
-/////////////////////////////////////////////////////////////////////
-//
-//  Some useful examples
-//
-/////////////////////////////////////////////////////////////////////
-
-
-class QInstallerCopyFileTask : public QInstallerTask
-{
-public:
-    QInstallerCopyFileTask(QInstaller *parent) : QInstallerTask(parent) {}
-    QInstaller::TaskCreator creator() const;
-
-    void setSourcePath(const QString &sourcePath) { m_sourcePath = sourcePath; }
-    QString sourcePath() const { return m_sourcePath; }
-
-    void setTargetPath(const QString &targetPath) { m_targetPath = targetPath; }
-    QString targetPath() const { return m_targetPath; }
-
-    void setPermissions(qint64 permissions) { m_permissions = permissions; }
-    qint64 permissions() const { return m_permissions; }
-
-    void writeToInstaller(QIODevice *out) const;
-    void readAndExecuteFromInstaller(QIODevice *in);
-
-    void writeToUninstaller(QIODevice *out) const;
-    void readAndExecuteFromUninstaller(QIODevice *in);
-
-    void undo();
-    void dump(QDebug &) const;
-
-private:
-    QString m_sourcePath;
-    QString m_targetPath;
-    qint64 m_permissions;
-    int m_parentDirCount;
-};
-
-
-class QInstallerLinkFileTask : public QInstallerTask
-{
-public:
-    QInstallerLinkFileTask(QInstaller *parent) : QInstallerTask(parent) {}
-    QInstaller::TaskCreator creator() const;
-
-    void setTargetPath(const QString &path) { m_targetPath = path; }
-    QString targetPath() const { return m_targetPath; }
-
-    void setLinkTargetPath(const QString &path) { m_linkTargetPath = path; }
-    QString linkTargetPath() const { return m_linkTargetPath; }
-
-    void setPermissions(qint64 permissions) { m_permissions = permissions; }
-    qint64 permissions() const { return m_permissions; }
-
-    void writeToInstaller(QIODevice *out) const;
-    void readAndExecuteFromInstaller(QIODevice *in);
-
-    void writeToUninstaller(QIODevice *out) const;
-    void readAndExecuteFromUninstaller(QIODevice *in);
-
-    void undo();
-    void dump(QDebug &) const;
-
-public:
-    QString m_targetPath; // location of the link in the target system
-    QString m_linkTargetPath; // linkee
-    qint64 m_permissions;
-};
-
-
-class QInstallerWriteSettingsTask : public QInstallerTask
-{
-public:
-    QInstallerWriteSettingsTask(QInstaller *parent)
-        : QInstallerTask(parent) {}
-    QInstaller::TaskCreator creator() const;
-
-    void setKey(const QString &key) { m_key = key; }
-    QString key() const { return m_key; }
-
-    void setValue(const QString &value) { m_value = value; }
-    QString value() const { return m_value; }
-
-    void writeToInstaller(QIODevice *out) const;
-    void readAndExecuteFromInstaller(QIODevice *in);
-
-    void writeToUninstaller(QIODevice *out) const;
-    void readAndExecuteFromUninstaller(QIODevice *in);
-
-    void undo();
-    void dump(QDebug &) const;
-
-public:
-    QString m_key;
-    QString m_value;
-};
-
-
-class QInstallerPatchFileTask : public QInstallerTask
-{
-public:
-    QInstallerPatchFileTask(QInstaller *parent) : QInstallerTask(parent) {}
-    QInstaller::TaskCreator creator() const;
-
-    void setTargetPath(const QString &path) { m_targetPath = path; }
-    QString targetPath() const { return m_targetPath; }
-
-    void setNeedle(const QByteArray &needle) { m_needle = needle; }
-    QByteArray needle() const { return m_needle; }
-
-    void setReplacement(const QByteArray &repl) { m_replacement = repl; }
-    QByteArray replacement() const { return m_replacement; }
-
-    void writeToInstaller(QIODevice *out) const;
-    void readAndExecuteFromInstaller(QIODevice *in);
-
-    void writeToUninstaller(QIODevice *) const {}
-    void readAndExecuteFromUninstaller(QIODevice *) {}
-
-    void undo() {}
-    void dump(QDebug &) const;
-
-private:
-    QByteArray m_needle;
-    QByteArray m_replacement;
-    QString m_targetPath;
-};
-
-
-class QInstallerMenuShortcutTask : public QInstallerTask
-{
-public:
-    QInstallerMenuShortcutTask(QInstaller *parent) : QInstallerTask(parent) {}
-    QInstaller::TaskCreator creator() const;
-
-    void setTargetPath(const QString &path) { m_targetPath = path; }
-    QString targetPath() const { return m_targetPath; }
-
-    void setLinkTargetPath(const QString &path) { m_linkTargetPath = path; }
-    QString linkTargetPath() const { return m_linkTargetPath; }
-    
-    void writeToInstaller(QIODevice *out) const;
-    void readAndExecuteFromInstaller(QIODevice *in);
-
-    void writeToUninstaller(QIODevice *out) const;
-    void readAndExecuteFromUninstaller(QIODevice *in);
-
-    void undo();
-    void dump(QDebug &) const;
-
-public:
-    QString m_targetPath;
-    QString m_linkTargetPath;
-    QString m_startMenuPath;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QINSTALLER_H
diff --git a/installer/qinstallergui.cpp b/installer/qinstallergui.cpp
deleted file mode 100644
index ca2c6d73c04a1da407e0a37df10d7f959790b8e3..0000000000000000000000000000000000000000
--- a/installer/qinstallergui.cpp
+++ /dev/null
@@ -1,742 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact:  Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file.  Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-
-#include "qinstallergui.h"
-
-#include "qinstaller.h"
-#include "private/qobject_p.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QProcess>
-#include <QtCore/QRegExp>
-#include <QtCore/QTimer>
-
-#include <QtGui/QApplication>
-#include <QtGui/QCheckBox>
-#include <QtGui/QFileDialog>
-#include <QtGui/QGridLayout>
-#include <QtGui/QHBoxLayout>
-#include <QtGui/QHeaderView>
-#include <QtGui/QLabel>
-#include <QtGui/QLineEdit>
-#include <QtGui/QMessageBox>
-#include <QtGui/QProgressBar>
-#include <QtGui/QPushButton>
-#include <QtGui/QRadioButton>
-#include <QtGui/QTextEdit>
-#include <QtGui/QTreeWidget>
-#include <QtGui/QTreeView>
-#include <QtGui/QVBoxLayout>
-
-
-QT_BEGIN_NAMESPACE
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerGui
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerGui::QInstallerGui(QInstaller *installer, QWidget *parent)
-  : QWizard(parent)
-{
-    #ifndef Q_WS_MAC
-    setWizardStyle(QWizard::ModernStyle);
-    #endif
-    setOption(QWizard::IndependentPages);
-    connect(button(QWizard::CancelButton), SIGNAL(clicked()),
-        this, SLOT(cancelButtonClicked()));
-
-    connect(this, SIGNAL(interrupted()),
-        installer, SLOT(interrupt()));
-    connect(installer, SIGNAL(installationFinished()),
-        this, SLOT(showFinishedPage()));
-    connect(installer, SIGNAL(warning(QString)),
-        this, SLOT(showWarning(QString)));
-}
-
-void QInstallerGui::cancelButtonClicked()
-{
-    QInstallerPage *page = qobject_cast<QInstallerPage *>(currentPage());
-    qDebug() << "CANCEL CLICKED" << currentPage() << page;
-    if (page && page->isInterruptible()) {
-        QMessageBox::StandardButton bt = QMessageBox::warning(this,
-            tr("Warning"),
-            tr("Do you want to abort the installation process?"),
-                QMessageBox::Yes | QMessageBox::No);
-        if (bt == QMessageBox::Yes)
-            emit interrupted();
-    } else {
-        QMessageBox::StandardButton bt = QMessageBox::warning(this,
-            tr("Warning"),
-            tr("Do you want to abort the installer application?"),
-                QMessageBox::Yes | QMessageBox::No);
-        if (bt == QMessageBox::Yes)
-            QDialog::reject();
-    }
-}
-
-void QInstallerGui::reject()
-{}
-
-void QInstallerGui::showFinishedPage()
-{
-    qDebug() << "SHOW FINISHED PAGE";
-    next();
-}
-
-void QInstallerGui::showWarning(const QString &msg)
-{
-    QMessageBox::warning(this, tr("Warning"), msg);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerPage::QInstallerPage(QInstaller *installer)
-  : m_installer(installer), m_fresh(true)
-{
-    setSubTitle(QString(" ")); // otherwise the colors will screw up
-
-}
-
-QInstaller *QInstallerPage::installer() const
-{
-    return m_installer;
-}
-
-QPixmap QInstallerPage::watermarkPixmap() const
-{
-    return QPixmap(m_installer->value("WatermarkPixmap"));
-}
-
-QPixmap QInstallerPage::logoPixmap() const
-{
-    return QPixmap(m_installer->value("LogoPixmap"));
-}
-
-QString QInstallerPage::productName() const
-{
-    return m_installer->value("ProductName");
-}
-
-void QInstallerPage::insertWidget(QWidget *widget, const QString &siblingName, int offset)
-{
-    QWidget *sibling = findChild<QWidget *>(siblingName);
-    QWidget *parent = sibling ? sibling->parentWidget() : 0;
-    QLayout *layout = parent ? parent->layout() : 0;
-    QBoxLayout *blayout = qobject_cast<QBoxLayout *>(layout);
-    //qDebug() << "FOUND: " << sibling << parent << layout << blayout;
-    if (blayout) {
-        int index = blayout->indexOf(sibling) + offset;
-        blayout->insertWidget(index, widget);
-    }
-}
-
-QWidget *QInstallerPage::findWidget(const QString &objectName) const
-{
-    return findChild<QWidget *>(objectName);
-}
-
-void QInstallerPage::setVisible(bool visible)
-{   
-    QWizardPage::setVisible(visible);
-    qApp->processEvents();
-    //qDebug() << "VISIBLE: " << visible << objectName() << installer(); 
-    if (m_fresh && !visible) {
-        //qDebug() << "SUPRESSED...";
-        m_fresh = false;
-        return;
-    }
-    if (visible)
-        entering();
-    else
-        leaving();
-}
-
-int QInstallerPage::nextId() const
-{
-    //qDebug() << "NEXTID";
-    return QWizardPage::nextId();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerIntroductionPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerIntroductionPage::QInstallerIntroductionPage(QInstaller *installer)
-  : QInstallerPage(installer)
-{
-    setObjectName("IntroductionPage");
-    setTitle(tr("Setup - %1").arg(productName()));
-    setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
-    setSubTitle(QString());
-
-    QLabel *msgLabel = new QLabel(this);
-    msgLabel->setObjectName("MessageLabel");
-    msgLabel->setWordWrap(true);
-    msgLabel->setText(QInstaller::tr("Welcome to the %1 Setup Wizard.")
-        .arg(productName()));
-
-    QVBoxLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(msgLabel);
-    setLayout(layout);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerLicenseAgreementPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerLicenseAgreementPage::QInstallerLicenseAgreementPage(QInstaller *installer)
-  : QInstallerPage(installer)
-{
-    setObjectName("LicenseAgreementPage");
-    setTitle(tr("License Agreement"));
-    QString msg = tr("Please read the following License Agreement. "
-        "You must accept the terms of this agreement "
-        "before continuing with the installation.");
-    setPixmap(QWizard::LogoPixmap, logoPixmap());
-    setPixmap(QWizard::WatermarkPixmap, QPixmap());
-
-    QTextEdit *textEdit = new QTextEdit(this);
-    textEdit->setObjectName("LicenseText");
-    QFile file(":/resources/license.txt");
-    file.open(QIODevice::ReadOnly);
-    textEdit->setText(file.readAll());
-
-    m_acceptRadioButton = new QRadioButton(tr("I accept the agreement"), this);
-    m_rejectRadioButton = new QRadioButton(tr("I do not accept the agreement"), this);
-
-    QLabel *msgLabel = new QLabel(msg, this);
-    msgLabel->setObjectName("MessageLabel");
-    msgLabel->setWordWrap(true);
-
-    QVBoxLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(msgLabel);
-    layout->addWidget(textEdit);
-        QHBoxLayout *hlayout = new QHBoxLayout;
-        hlayout->addWidget(new QLabel(tr("Do you accept this License?")));
-            QVBoxLayout *vlayout = new QVBoxLayout;
-            vlayout->addWidget(m_acceptRadioButton);
-            vlayout->addWidget(m_rejectRadioButton);
-        hlayout->addLayout(vlayout);
-    layout->addLayout(hlayout);
-    setLayout(layout);
-    connect(m_acceptRadioButton, SIGNAL(toggled(bool)),
-        this, SIGNAL(completeChanged()));
-    connect(m_rejectRadioButton, SIGNAL(toggled(bool)),
-        this, SIGNAL(completeChanged()));
-}
-
-bool QInstallerLicenseAgreementPage::isComplete() const
-{
-    return m_acceptRadioButton->isChecked();
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerComponentSelectionPage
-//
-////////////////////////////////////////////////////////////////////
-
-static QString niceSizeText(const QString &str)
-{
-    qint64 size = str.toInt();
-    QString msg = QInstallerComponentSelectionPage::tr(
-        "This component will occupy approximately %1 %2 on your harddisk.");
-    if (size < 10000)
-        return msg.arg(size).arg("Bytes");
-    if (size < 1024 * 10000)
-        return msg.arg(size / 1024).arg("kBytes");
-    return msg.arg(size / 1024 / 1024).arg("MBytes");
-}
-
-class QInstallerComponentSelectionPage::Private : public QObject
-{
-    Q_OBJECT
-
-public:
-    Private(QInstallerComponentSelectionPage *q_, QInstaller *installer)
-      : q(q_), m_installer(installer)
-    {
-        m_treeView = new QTreeWidget(q);
-        m_treeView->setObjectName("TreeView");
-        m_treeView->setMouseTracking(true);
-        m_treeView->header()->hide();
-
-        for (int i = 0; i != installer->componentCount(); ++i) {
-            QInstallerComponent *component = installer->component(i);
-            QTreeWidgetItem *item = new QTreeWidgetItem(m_treeView);
-            item->setText(0, component->value("Name"));
-            item->setToolTip(0, component->value("Description"));
-            item->setToolTip(1, niceSizeText(component->value("UncompressedSize")));
-            //QString current = component->value("CurrentState");
-            QString suggested = component->value("SuggestedState");
-            if (suggested == "Uninstalled") {
-                item->setCheckState(0, Qt::Unchecked);
-            } else if (suggested == "AlwaysInstalled") {
-                item->setCheckState(0, Qt::PartiallyChecked);
-                item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable);
-            } else { //if (suggested == "Installed")
-                item->setCheckState(0, Qt::Checked);
-            }
-        }
-        
-        m_descriptionLabel = new QLabel(q);
-        m_descriptionLabel->setWordWrap(true);
-
-        m_sizeLabel = new QLabel(q);
-        m_sizeLabel->setWordWrap(true);
-
-        QVBoxLayout *layout = new QVBoxLayout(q);
-        //layout->addWidget(msgLabel);
-            QHBoxLayout *hlayout = new QHBoxLayout;
-            hlayout->addWidget(m_treeView, 3);
-                QVBoxLayout *vlayout = new QVBoxLayout;
-                vlayout->addWidget(m_descriptionLabel);
-                vlayout->addWidget(m_sizeLabel);
-                vlayout->addSpacerItem(new QSpacerItem(1, 1,
-                    QSizePolicy::MinimumExpanding, 
-                    QSizePolicy::MinimumExpanding));
-            hlayout->addLayout(vlayout, 2);
-        layout->addLayout(hlayout);
-        q->setLayout(layout);
-
-        connect(m_treeView,
-            SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
-            this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
-    }
-
-public slots:
-    void currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *)
-    {
-        m_descriptionLabel->setText(item->toolTip(0));
-        m_sizeLabel->setText(item->toolTip(1));
-    }
-
-public:
-    QInstallerComponentSelectionPage *q;
-    QInstaller *m_installer;
-    QTreeWidget *m_treeView;
-    QLabel *m_descriptionLabel;
-    QLabel *m_sizeLabel;
-};
-
- 
-QInstallerComponentSelectionPage::QInstallerComponentSelectionPage
-    (QInstaller *installer)
-  : QInstallerPage(installer), d(new Private(this, installer))
-{
-    setObjectName("ComponentSelectionPage");
-    setTitle(tr("Select Components"));
-    QString msg = tr("Please select the components you want to install.");
-    setSubTitle(msg);
-    setPixmap(QWizard::LogoPixmap, logoPixmap());
-    setPixmap(QWizard::WatermarkPixmap, QPixmap());
-}
-
-QInstallerComponentSelectionPage::~QInstallerComponentSelectionPage()
-{
-    delete d;
-}
-
-void QInstallerComponentSelectionPage::leaving()
-{
-    int n = d->m_treeView->topLevelItemCount();
-    for (int i = 0; i != n; ++i) {
-        QTreeWidgetItem *item = d->m_treeView->topLevelItem(i);
-        QInstallerComponent *component = installer()->component(i);
-        if (item->checkState(0) == Qt::Unchecked)
-            component->setValue("WantedState", "Uninstalled");
-        else 
-            component->setValue("WantedState", "Installed");
-    }
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerTargetDirectoryPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerTargetDirectoryPage::QInstallerTargetDirectoryPage(QInstaller *installer)
-  : QInstallerPage(installer)
-{
-    setObjectName("TargetDirectoryPage");
-    setTitle(tr("Installation Directory"));
-    setPixmap(QWizard::LogoPixmap, logoPixmap());
-    setPixmap(QWizard::WatermarkPixmap, QPixmap());
-
-    QLabel *msgLabel = new QLabel(this);
-    msgLabel->setText(QInstaller::tr("Please specify the directory where %1 "
-        "will be installed.").arg(productName()));
-    msgLabel->setWordWrap(true);
-    msgLabel->setObjectName("MessageLabel");
-
-    m_lineEdit = new QLineEdit(this);
-    m_lineEdit->setObjectName("LineEdit");
-
-    QPushButton *browseButton = new QPushButton(this);
-    browseButton->setObjectName("BrowseButton");
-    browseButton->setText("Browse...");
-    browseButton->setIcon(QIcon(logoPixmap()));
-
-    QVBoxLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(msgLabel);
-        QHBoxLayout *hlayout = new QHBoxLayout;
-        hlayout->addWidget(m_lineEdit);
-        hlayout->addWidget(browseButton);
-    layout->addLayout(hlayout);
-    setLayout(layout);
-
-    QString targetDir = installer->value("TargetDir");
-    //targetDir = QDir::currentPath();
-    if (targetDir.isEmpty())
-        targetDir = QDir::homePath() + QDir::separator() + productName();
-    m_lineEdit->setText(targetDir);
-
-    connect(browseButton, SIGNAL(clicked()),
-        this, SLOT(dirRequested()));
-    connect(m_lineEdit, SIGNAL(textChanged(QString)),
-        this, SIGNAL(completeChanged()));
-}
-
-QString QInstallerTargetDirectoryPage::targetDir() const
-{
-    return m_lineEdit->text();
-}
-
-void QInstallerTargetDirectoryPage::setTargetDir(const QString &dirName)
-{
-    m_lineEdit->setText(dirName);
-}
-
-void QInstallerTargetDirectoryPage::entering()
-{
-    connect(wizard(), SIGNAL(customButtonClicked(int)),
-            this, SLOT(targetDirSelected()));
-}
-
-void QInstallerTargetDirectoryPage::leaving()
-{
-    installer()->setValue("TargetDir", targetDir());
-    disconnect(wizard(), SIGNAL(customButtonClicked(int)),
-               this, SLOT(targetDirSelected()));
-}
-
-void QInstallerTargetDirectoryPage::targetDirSelected()
-{
-    //qDebug() << "TARGET DIRECTORY";
-    QDir dir(targetDir());
-    if (dir.exists() && dir.isReadable()) {
-        QMessageBox::StandardButton bt = QMessageBox::warning(this,
-            tr("Warning"),
-            tr("The directory you slected exists already.\n"
-               "Do you want to continue?"),
-                QMessageBox::Yes | QMessageBox::No);
-        if (bt == QMessageBox::Yes)
-            wizard()->next();
-        return;
-    }
-    dir.cdUp();
-    if (dir.exists() && dir.isReadable()) {
-        wizard()->next();
-        return;
-    }
-    wizard()->next();
-}
-
-void QInstallerTargetDirectoryPage::dirRequested()
-{
-    //qDebug() << "DIR REQUESTED";
-    QString newDirName = QFileDialog::getExistingDirectory(this,
-        tr("Select Installation Directory"), targetDir()
-        /*, Options options = ShowDirsOnly*/);
-    if (newDirName.isEmpty() || newDirName == targetDir())
-        return;
-    m_lineEdit->setText(newDirName);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerReadyForInstallationPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerReadyForInstallationPage::
-    QInstallerReadyForInstallationPage(QInstaller *installer)
-  : QInstallerPage(installer)
-{
-    setObjectName("ReadyForInstallationPage");
-    setTitle(tr("Ready to Install"));
-    setCommitPage(true);
-    setButtonText(QWizard::CommitButton, tr("Install"));
-
-    QLabel *msgLabel = new QLabel(this);
-    msgLabel->setObjectName("MessageLabel");
-    msgLabel->setText(QInstaller::tr("Setup is now ready to begin installing %1 "
-        "on your computer.").arg(productName()));
-
-    QLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(msgLabel);
-    setLayout(layout);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerPerformInstallationPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerPerformInstallationPage::QInstallerPerformInstallationPage(QInstaller *gui)
-  : QInstallerPage(gui)
-{
-    setObjectName("InstallationPage");
-    setTitle(tr("Installing %1").arg(installer()->value("ProductName")));
-    setCommitPage(true);
-
-    m_progressBar = new QProgressBar(this);
-    m_progressBar->setObjectName("ProgressBar");
-    m_progressBar->setRange(1, 100);
-
-    m_progressLabel = new QLabel(this);
-    m_progressLabel->setObjectName("ProgressLabel");
-    
-    m_updateTimer = new QTimer(this);
-    connect(m_updateTimer, SIGNAL(timeout()),
-            this, SLOT(updateProgress()));
-    m_updateTimer->setInterval(50);
-
-    QLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(m_progressBar);
-    layout->addWidget(m_progressLabel);
-    setLayout(layout);
-
-    connect(installer(), SIGNAL(installationStarted()),
-            this, SLOT(installationStarted()));
-    connect(installer(), SIGNAL(installationFinished()),
-            this, SLOT(installationFinished()));
-}
-
-void QInstallerPerformInstallationPage::initializePage()
-{
-    QWizardPage::initializePage();
-    QTimer::singleShot(30, installer(), SLOT(runInstaller()));
-}
-
-// FIXME: remove function
-bool QInstallerPerformInstallationPage::isComplete() const
-{
-    return true;
-}
-
-void QInstallerPerformInstallationPage::installationStarted()
-{
-    qDebug() << "INSTALLATION STARTED";
-    m_updateTimer->start();
-    updateProgress();
-}
-
-void QInstallerPerformInstallationPage::installationFinished()
-{
-    qDebug() << "INSTALLATION FINISHED";
-    m_updateTimer->stop();
-    updateProgress();
-}
-
-void QInstallerPerformInstallationPage::updateProgress()
-{
-    int progress = installer()->installationProgress();
-    if (progress != m_progressBar->value())
-        m_progressBar->setValue(progress);
-    QString progressText = installer()->installationProgressText();
-    if (progressText != m_progressLabel->text())
-        m_progressLabel->setText(progressText);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerPerformUninstallationPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerPerformUninstallationPage::QInstallerPerformUninstallationPage
-        (QInstaller *gui)
-  : QInstallerPage(gui)
-{
-    setObjectName("UninstallationPage");
-    setTitle(tr("Uninstalling %1").arg(installer()->value("ProductName")));
-    setCommitPage(true);
-
-    m_progressBar = new QProgressBar(this);
-    m_progressBar->setObjectName("ProgressBar");
-    m_progressBar->setRange(1, 100);
-
-    m_progressLabel = new QLabel(this);
-    m_progressLabel->setObjectName("ProgressLabel");
-    
-    m_updateTimer = new QTimer(this);
-    connect(m_updateTimer, SIGNAL(timeout()),
-            this, SLOT(updateProgress()));
-    m_updateTimer->setInterval(50);
-
-    QLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(m_progressBar);
-    layout->addWidget(m_progressLabel);
-    setLayout(layout);
-
-    connect(installer(), SIGNAL(uninstallationStarted()),
-            this, SLOT(uninstallationStarted()));
-    connect(installer(), SIGNAL(uninstallationFinished()),
-            this, SLOT(uninstallationFinished()));
-}
-
-void QInstallerPerformUninstallationPage::initializePage()
-{
-    QWizardPage::initializePage();
-    QTimer::singleShot(30, installer(), SLOT(runUninstaller()));
-}
-
-// FIXME: remove function
-bool QInstallerPerformUninstallationPage::isComplete() const
-{
-    return true;
-}
-
-void QInstallerPerformUninstallationPage::uninstallationStarted()
-{
-    m_updateTimer->start();
-    updateProgress();
-}
-
-void QInstallerPerformUninstallationPage::uninstallationFinished()
-{
-    m_updateTimer->stop();
-    updateProgress();
-}
-
-void QInstallerPerformUninstallationPage::updateProgress()
-{
-    int progress = installer()->installationProgress();
-    if (progress != m_progressBar->value())
-        m_progressBar->setValue(progress);
-    QString progressText = installer()->installationProgressText();
-    if (progressText != m_progressLabel->text())
-        m_progressLabel->setText(progressText);
-}
-
-
-////////////////////////////////////////////////////////////////////
-//
-// QInstallerFinishedPage
-//
-////////////////////////////////////////////////////////////////////
-
-QInstallerFinishedPage::QInstallerFinishedPage(QInstaller *installer)
-  : QInstallerPage(installer)
-{
-    setObjectName("FinishedPage");
-    setTitle(tr("Completing the %1 Setup Wizard").arg(productName()));
-    setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
-    setSubTitle(QString());
-
-    QLabel *msgLabel = new QLabel(this);
-    msgLabel->setObjectName("MessageLabel");
-    msgLabel->setWordWrap(true);
-    msgLabel->setText(tr("Click Finish to exit the Setup Wizard"));
-
-    m_runItCheckBox = new QCheckBox(this);
-    m_runItCheckBox->setObjectName("RunItCheckBox");
-    m_runItCheckBox->setChecked(true);
-
-    QVBoxLayout *layout = new QVBoxLayout(this);
-    layout->addWidget(msgLabel);
-    if (m_runItCheckBox)
-        layout->addWidget(m_runItCheckBox);
-    setLayout(layout);
-}
-
-void QInstallerFinishedPage::entering()
-{
-    qDebug() << "FINISHED ENTERING: ";
-    connect(wizard()->button(QWizard::FinishButton), SIGNAL(clicked()),
-        this, SLOT(handleFinishClicked()));
-    if (installer()->status() == QInstaller::InstallerSucceeded) {
-        m_runItCheckBox->show();
-        m_runItCheckBox->setText(tr("Run %1 now.").arg(productName()));
-    } else {
-        setTitle(tr("The %1 Setup Wizard failed").arg(productName()));
-        m_runItCheckBox->hide();
-        m_runItCheckBox->setChecked(false);
-    }
-}
-
-void QInstallerFinishedPage::leaving()
-{
-    disconnect(wizard(), SIGNAL(customButtonClicked(int)),
-        this, SLOT(handleFinishClicked()));
-}
-
-void QInstallerFinishedPage::handleFinishClicked()
-{
-    if (!m_runItCheckBox->isChecked())
-        return;
-    QString program = installer()->value("RunProgram");
-    if (program.isEmpty())
-        return;
-    program = installer()->replaceVariables(program);
-    qDebug() << "STARTING " << program;
-    QProcess *process = new QProcess;
-    process->start(program);
-    process->waitForFinished();
-}
-
-#include "qinstallergui.moc"
-
-QT_END_NAMESPACE
diff --git a/installer/qinstallergui.h b/installer/qinstallergui.h
deleted file mode 100644
index ec7db64677cc342d649914ddfe4a40ac9658a222..0000000000000000000000000000000000000000
--- a/installer/qinstallergui.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact:  Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file.  Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-
-#ifndef QINSTALLERGUI_H
-#define QINSTALLERGUI_H
-
-#include <QtGui/QWizard>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QInstaller;
-
-// FIXME: move to private classes
-class QCheckBox;
-class QLabel;
-class QLineEdit;
-class QProgressBar;
-class QRadioButton;
-class QTreeView;
-class QTreeWidget;
-
-class QInstallerGui : public QWizard
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerGui(QInstaller *installer, QWidget *parent = 0);
-
-signals:
-    void interrupted();
-
-public slots:
-    void cancelButtonClicked();
-    void reject();
-    void showFinishedPage();
-    void showWarning(const QString &msg);
-};
-
-
-class QInstallerPage : public QWizardPage
-{
-    Q_OBJECT
-
-public:
-    QInstallerPage(QInstaller *installer);
-
-    virtual bool isInterruptible() const { return false; }
-    virtual QPixmap watermarkPixmap() const;
-    virtual QPixmap logoPixmap() const;
-    virtual QString productName() const;
-
-protected:
-    QInstaller *installer() const;
-
-    // Inserts widget into the same layout like a sibling identified
-    // by its name. Default position is just behind the sibling.
-    virtual void insertWidget(QWidget *widget, const QString &siblingName,
-        int offset = 1);
-    virtual QWidget *findWidget(const QString &objectName) const;
-
-    virtual void setVisible(bool visible); // reimp
-    virtual int nextId() const; // reimp
-
-    virtual void entering() {} // called on entering
-    virtual void leaving() {}  // called on leaving
-
-    virtual void forward() const {} // called when going forwards
-    //virtual void backward() const {}  // called when going back
-    bool isConstructing() const { return m_fresh; }
-
-private:
-    QInstaller *m_installer;
-    bool m_fresh;
-};
-
-
-class QInstallerIntroductionPage : public QInstallerPage
-{
-public:
-    explicit QInstallerIntroductionPage(QInstaller *installer);
-};
-
-
-class QInstallerLicenseAgreementPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerLicenseAgreementPage(QInstaller *installer);
-    bool isComplete() const;
-
-private:
-    QRadioButton *m_acceptRadioButton;
-    QRadioButton *m_rejectRadioButton;
-};
-
-
-class QInstallerComponentSelectionPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerComponentSelectionPage(QInstaller *installer);
-    ~QInstallerComponentSelectionPage();
-
-protected:
-    //void entering();
-    void leaving();
-
-private:
-    class Private;
-    Private *d;
-};
-
-
-class QInstallerTargetDirectoryPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerTargetDirectoryPage(QInstaller *installer);
-    QString targetDir() const;
-    void setTargetDir(const QString &dirName);
-
-protected:
-    void entering();
-    void leaving();
-
-private slots:
-    void targetDirSelected();
-    void dirRequested();
-
-private:
-    QLineEdit *m_lineEdit;
-};
-
-
-class QInstallerReadyForInstallationPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerReadyForInstallationPage(QInstaller *installer);
-};
-
-
-class QInstallerPerformInstallationPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerPerformInstallationPage(QInstaller *installer);
-
-protected:
-    void initializePage();
-    bool isComplete() const;
-    bool isInterruptible() const { return true; }
-
-signals:
-    void installationRequested();
-
-private slots:
-    void installationStarted();
-    void installationFinished();
-    void updateProgress();
-
-private:
-    QProgressBar *m_progressBar;
-    QLabel *m_progressLabel;
-    QTimer *m_updateTimer;
-};
-
-
-class QInstallerPerformUninstallationPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerPerformUninstallationPage(QInstaller *installer);
-
-protected:
-    void initializePage();
-    bool isComplete() const;
-    bool isInterruptible() const { return true; }
-
-signals:
-    void uninstallationRequested();
-
-private slots:
-    void uninstallationStarted();
-    void uninstallationFinished();
-    void updateProgress();
-
-private:
-    QProgressBar *m_progressBar;
-    QLabel *m_progressLabel;
-    QTimer *m_updateTimer;
-};
-
-
-class QInstallerFinishedPage : public QInstallerPage
-{
-    Q_OBJECT
-
-public:
-    explicit QInstallerFinishedPage(QInstaller *installer);
-
-public slots:
-    void handleFinishClicked();
-
-protected:
-    void entering();
-    void leaving();
-
-private:
-    QCheckBox *m_runItCheckBox;
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QINSTALLERGUI_H
diff --git a/installer/resources/license.txt b/installer/resources/license.txt
deleted file mode 100644
index a55990fe3a0eef7e9e2c882ceb2e68f518b6019f..0000000000000000000000000000000000000000
--- a/installer/resources/license.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-For individuals and/or legal entities resident in the American Continent (including those resident in Canada, South America, and the United States of America), the applicable licensing terms are specified under the heading "Trolltech Technology Preview License
-Agreement: American Continent".
-
-For individuals and/or legal entities not resident in the American Continent, the applicable licensing terms are specified under the heading "Trolltech Technology Preview License Agreement: Norway".
-
-TROLLTECH TECHNOLOGY PREVIEW LICENSE AGREEMENT: AMERICAN CONTINENT Agreement version 2.0
-IMPORTANT-READ CAREFULLY:
-
-1. This Trolltech Technology Preview License Agreement ("Agreement") is a legal agreement between you (either an individual or a legal entity) and Trolltech, Inc. ("Trolltech"), and pertains to the Trolltech software product(s) accompanying this Agreement, which include(s) computer software and may include "online" or electronic documentation, associated media, and printed materials, including the source code, example programs and the documentation ("Licensed Software").
-
-2. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Trolltech retains all rights not expressly granted. No title, property rights or copyright in the Licensed Software or in any modifications to the Licensed Software shall pass to the Licensee under any circumstances. The Licensed Software is licensed, not sold.
-
-3. By installing, copying, or otherwise using the Licensed Software, Licensee agrees to be bound by the terms of this Agreement. If Licensee does not agree to the terms of this Agreement, Licensee should not install, copy, or otherwise use the Licensed Software.
-
-4. Upon Licensee's acceptance of the terms and conditions of this Agreement, Trolltech grants Licensee the right to use the Licensed Software in the manner provided below.
-
-5. Trolltech grants to Licensee as an individual a personal, non-exclusive, non-transferable license to make and use copies of the Licensed Software for the sole purpose of evaluating and testing the Licensed Software and/or providing feedback to Trolltech. Licensee may install copies of the Licensed Software on an unlimited number of computers provided that Licensee is the only individual using the Licensed Software. If Licensee is an entity, Trolltech grants Licensee the right to designate one, and only one, individual within Licensee's organization who shall have the sole right to use the Licensed Software in the manner provided in this Agreement. Licensee may, at any time, but not more frequently than once every six (6) months, designate another individual to replace the current designated user by notifying Trolltech, so long as there is no more than one (1) designated user at any given time
-
-6. Licensee may not loan, rent, lease, or license the Licensed Software or any copy of it. Licensee may not alter or remove any details of ownership, copyright, trademark or other property right connected with the Licensed Software. Licensee may not modify or distribute the Licensed Software. Licensee may not distribute any software statically or dynamically linked with the Licensed Software.
-
-7. This Licensed Software is time-limited. All rights granted to Licensee in this Agreement will be void three (3) months after Licensee received the Licensed Software.
-
-8. The Licensed Software may provide links to third party libraries or code (collectively "Third Party Libraries") to implement various functions. Third Party Libraries do not comprise part of the Licensed Software. In some cases, access to Third Party Libraries may be included along with the Licensed Software delivery as a convenience for development and testing only. Such source code and libraries as are or may be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software, as may be amended from time to time, do not comprise the Licensed Software. Licensee acknowledges (1) that some Third Party Libraries may require additional licensing of copyright and patents from the owners of such, and (2) that distribution of any of the Licensed Software referencing any portion of a Third Party Library may require appropriate licensing from such third parties.
-
-9. Pre-Release Code, Non-Commercial Use: The Licensed Software contains Pre-release Code that is not at the level of performance and compatibility of a final, generally available, product offering. The Licensed Software may not operate correctly and may be substantially modified prior to the first commercial shipment, if any. Trolltech is not obligated to make this or any later version of the Licensed Software commercially available. The License Software is "Not for Commercial Use" and may only be used for the purposes described in Section 5. You may not use the Licensed Software in a live operating environment where it may be relied upon to perform in the same manner as a commercially released product or with data that has not been sufficiently backed up.
-
-10. WARRANTY DISCLAIMER: THE LICENSED SOFTWARE IS LICENSED TO LICENSEE "AS IS". TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, TROLLTECH ON BEHALF OF ITSELF AND ITS SUPPLIERS, DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE.
-
-11. LIMITATION OF LIABILITY: IF, TROLLTECH'S WARRANTY DISCLAIMER NOTWITHSTANDING, TROLLTECH IS HELD LIABLE TO LICENSEE, WHETHER IN CONTRACT, TORT OR ANY OTHER LEGAL THEORY, BASED ON THE LICENSED SOFTWARE, TROLLTECH'S ENTIRE LIABILITY TO LICENSEE AND LICENSEE'S EXCLUSIVE REMEDY SHALL BE, AT TROLLTECH'S OPTION, EITHER (A) RETURN OF THE PRICE LICENSEE PAID FOR THE LICENSED SOFTWARE, OR (B) REPAIR OR REPLACEMENT OF THE LICENSED SOFTWARE, PROVIDED LICENSEE RETURNS TO TROLLTECH ALL COPIES OF THE LICENSED SOFTWARE AS ORIGINALLY DELIVERED TO LICENSEE. TROLLTECH SHALL NOT UNDER ANY CIRCUMSTANCES BE LIABLE TO LICENSEE BASED ON FAILURE OF THE LICENSED SOFTWARE IF THE FAILURE RESULTED FROM ACCIDENT, ABUSE OR MISAPPLICATION, NOR SHALL TROLLTECH UNDER ANY CIRCUMSTANCES BE LIABLE FOR SPECIAL DAMAGES, PUNITIVE OR EXEMPLARY DAMAGES, DAMAGES FOR LOSS OF PROFITS OR INTERRUPTION OF BUSINESS OR FOR LOSS OR CORRUPTION OF DATA. ANY AWARD OF DAMAGES FROM TROLLTECH TO LICENSEE SHALL NOT EXCEED THE TOTAL AMOUNT LICENSEE HAS PAID TO TROLLTECH IN CONNECTION WITH THIS AGREEMENT.
-
-12. Termination: Without prejudice to any other rights, Trolltech may terminate this Agreement if Licensee fails to comply with the terms and conditions of this Agreement. In such event, Licensee must destroy all copies of the Licensed Software and all of its components.
-
-13. Export Restrictions: Licensee agrees not to export or re-export the Licensed Software, any part thereof, or any process or service that is the direct product of the Licensed Software. Licensee may not sell, resell, or otherwise transfer for value, the Licensed Software (the foregoing collectively referred to as the "Restricted Components"), to any country, person, entity or end user subject to U.S. export restrictions. Licensee specifically agrees not to export or re-export any of the Restricted Components (i) to any country to which the U.S. has embargoed or restricted the export of goods or services, which currently include, but are not necessarily limited to Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria, or to any national of any such country, wherever located, who intends to transmit or transport the Restricted Components back to such country; (ii) to any end-user who Licensee knows or has reason to know will utilize the Restricted Components in the design, development or production of nuclear, chemical or biological weapons; or (iii) to any end-user who has been prohibited from participating in U.S. export transactions by any federal agency of the U.S. government. Licensee warrants and represents that neither the U.S. Commerce Department, Bureau of Export Administration nor any other U.S. federal agency has suspended, revoked or denied Licensee's export privileges.
-
-14. Government End Users: A "U.S. Government End User" shall mean any agency or entity of the government of the United States. The following shall apply if Licensee is a U.S. Government End User. The Licensed Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire the Licensed Software with only those rights set forth herein. The Licensed Software (including related documentation) is provided to U.S. Government End Users: (a) only as a commercial end item; and (b) only pursuant to this Agreement.
-
-15. Compliance with local laws: Licensee shall comply with all applicable laws and regulations relating to the Licensed Software in the United States and in other countries in which Licensee uses or modifies the Licensed Software. Without limiting the generality of the foregoing, Licensee shall not export, re-export, disclose or distribute any of the Licensed Software in violation of any applicable laws or regulations, including the export laws and regulations of the United States, and shall comply with all such laws and regulations.
-
-16. Entire Agreement: This Agreement constitutes the complete agreement between the parties and supersedes all prior or contemporaneous discussions, representations, and proposals, written or oral, with respect to the subject matters discussed herein. No modification of this Agreement will be effective unless contained in a writing executed by an authorized representative of each party. No term or condition contained in Licensee's purchase order will apply unless expressly accepted by Trolltech in writing. If any provision of the Agreement is found void or unenforceable, the remainder will remain valid and enforceable according to its terms. If any remedy provided is determined to have failed for its essential purpose, all limitations of liability and exclusions of damages set forth in this Agreement shall remain in effect.
-
-17. Governing law, legal venue: This Agreement shall be construed, interpreted and governed by the laws of the State of California, USA. Any action or proceeding arising from or relating to this Agreement shall be brought in a federal court in the Northern District of California or in the State Court in Santa Clara County, California, and each party irrevocably submits to the personal jurisdiction of any such court in any such action or proceeding. The Agreement gives Licensee specific legal rights; Licensee may have others, which vary from state to state and from country to country. Trolltech reserves all rights not specifically granted in this Agreement.
-
-
-
-
-For legal entities and/or individuals residing in any country other than Canada, the United States of America or South America:
-TROLLTECH TECHNOLOGY PREVIEW LICENSE AGREEMENT: NORWAY
-
-Agreement version 2.0
-IMPORTANT-READ CAREFULLY:
-
-1. This Trolltech Technology Preview License Agreement ("Agreement") is a legal agreement between you (either an individual or a legal entity) and Trolltech ASA ("Trolltech"), and pertains to the Trolltech software product(s) accompanying this Agreement, which include(s) computer software and may include "online" or electronic documentation, associated media, and printed materials, including the source code, example programs and the documentation ("Licensed Software").
-
-2. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Trolltech retains all rights not expressly granted. No title, property rights or copyright in the Licensed Software or in any modifications to the Licensed Software shall pass to the Licensee under any circumstances. The Licensed Software is licensed, not sold.
-
-3. By installing, copying, or otherwise using the Licensed Software, Licensee agrees to be bound by the terms of this Agreement. If Licensee does not agree to the terms of this Agreement, Licensee should not install, copy, or otherwise use the Licensed Software.
-
-4. Upon Licensee's acceptance of the terms and conditions of this Agreement, Trolltech grants Licensee the right to use the Licensed Software in the manner provided below.
-
-5. Trolltech grants to Licensee as an individual a personal, non-exclusive, non-transferable license to make and use copies of the Licensed Software for the sole purpose of evaluating and testing the Licensed Software and/or providing feedback to Trolltech. Licensee may install copies of the Licensed Software on an unlimited number of computers provided that Licensee is the only individual using the Licensed Software. If Licensee is an entity, Trolltech grants Licensee the right to designate one, and only one, individual within Licensee's organization who shall have the sole right to use the Licensed Software in the manner provided in this Agreement. Licensee may, at any time, but not more frequently than once every six (6) months, designate another individual to replace the current designated user by notifying Trolltech, so long as there is no more than one (1) designated user at any given time
-
-6. Licensee may not loan, rent, lease, or license the Licensed Software or any copy of it. Licensee may not alter or remove any details of ownership, copyright, trademark or other property right connected with the Licensed Software. Licensee may not modify or distribute the Licensed Software. Licensee may not distribute any software statically or dynamically linked with the Licensed Software.
-
-7. This Licensed Software is time-limited. All rights granted to Licensee in this Agreement will be void three (3) months after Licensee received the Licensed Software.
-
-8. The Licensed Software may provide links to third party libraries or code (collectively "Third Party Libraries") to implement various functions. Third Party Libraries do not comprise part of the Licensed Software. In some cases, access to Third Party Libraries may be included along with the Licensed Software delivery as a convenience for development and testing only. Such source code and libraries as are or may be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software, as may be amended from time to time, do not comprise the Licensed Software. Licensee acknowledges (1) that some Third Party Libraries may require additional licensing of copyright and patents from the owners of such, and (2) that distribution of any of the Licensed Software referencing any portion of a Third Party Library may require appropriate licensing from such third parties.
-
-9. Pre-Release Code, Non-Commercial Use: The Licensed Software contains Pre-release Code that is not at the level of performance and compatibility of a final, generally available, product offering. The Licensed Software may not operate correctly and may be substantially modified prior to the first commercial shipment, if any. Trolltech is not obligated to make this or any later version of the Licensed Software commercially available. The License Software is "Not for Commercial Use" and may only be used for the purposes described in Section 5. You may not use the Licensed Software in a live operating environment where it may be relied upon to perform in the same manner as a commercially released product or with data that has not been sufficiently backed up.
-
-10. WARRANTY DISCLAIMER: THE LICENSED SOFTWARE IS LICENSED TO LICENSEE "AS IS". TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, TROLLTECH ON BEHALF OF ITSELF AND ITS SUPPLIERS, DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE.
-
-11. LIMITATION OF LIABILITY: IF, TROLLTECH'S WARRANTY DISCLAIMER NOTWITHSTANDING, TROLLTECH IS HELD LIABLE TO LICENSEE, WHETHER IN CONTRACT, TORT OR ANY OTHER LEGAL THEORY, BASED ON THE LICENSED SOFTWARE, TROLLTECH'S ENTIRE LIABILITY TO LICENSEE AND LICENSEE'S EXCLUSIVE REMEDY SHALL BE, AT TROLLTECH'S OPTION, EITHER (A) RETURN OF THE PRICE LICENSEE PAID FOR THE LICENSED SOFTWARE, OR (B) REPAIR OR REPLACEMENT OF THE LICENSED SOFTWARE, PROVIDED LICENSEE RETURNS TO TROLLTECH ALL COPIES OF THE LICENSED SOFTWARE AS ORIGINALLY DELIVERED TO LICENSEE. TROLLTECH SHALL NOT UNDER ANY CIRCUMSTANCES BE LIABLE TO LICENSEE BASED ON FAILURE OF THE LICENSED SOFTWARE IF THE FAILURE RESULTED FROM ACCIDENT, ABUSE OR MISAPPLICATION, NOR SHALL TROLLTECH UNDER ANY CIRCUMSTANCES BE LIABLE FOR SPECIAL DAMAGES, PUNITIVE OR EXEMPLARY DAMAGES, DAMAGES FOR LOSS OF PROFITS OR INTERRUPTION OF BUSINESS OR FOR LOSS OR CORRUPTION OF DATA. ANY AWARD OF DAMAGES FROM TROLLTECH TO LICENSEE SHALL NOT EXCEED THE TOTAL AMOUNT LICENSEE HAS PAID TO TROLLTECH IN CONNECTION WITH THIS AGREEMENT.
-
-12. Termination: Without prejudice to any other rights, Trolltech may terminate this Agreement if Licensee fails to comply with the terms and conditions of this Agreement. In such event, Licensee must destroy all copies of the Licensed Software and all of its components.
-
-13. Export Restrictions: Licensee agrees not to export or re-export the Licensed Software, any part thereof, or any process or service that is the direct product of the Licensed Software. Licensee may not sell, resell, or otherwise transfer for value, the Licensed Software (the foregoing collectively referred to as the "Restricted Components"), to any country, person, entity or end user subject to U.S. export restrictions. Licensee specifically agrees not to export or re-export any of the Restricted Components (i) to any country to which the U.S. has embargoed or restricted the export of goods or services, which currently include, but are not necessarily limited to Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria, or to any national of any such country, wherever located, who intends to transmit or transport the Restricted Components back to such country; (ii) to any end-user who Licensee knows or has reason to know will utilize the Restricted Components in the design, development or production of nuclear, chemical or biological weapons; or (iii) to any end-user who has been prohibited from participating in U.S. export transactions by any federal agency of the U.S. government. Licensee warrants and represents that neither the U.S. Commerce Department, Bureau of Export Administration nor any other U.S. federal agency has suspended, revoked or denied Licensee's export privileges.
-
-14. Government End Users: A "U.S. Government End User" shall mean any agency or entity of the government of the United States. The following shall apply if Licensee is a U.S. Government End User. The Licensed Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire the Licensed Software with only those rights set forth herein. The Licensed Software (including related documentation) is provided to U.S. Government End Users: (a) only as a commercial end item; and (b) only pursuant to this Agreement.
-
-15. Compliance with local laws: Licensee shall comply with all applicable laws and regulations relating to the Licensed Software in the United States and in other countries in which Licensee uses or modifies the Licensed Software. Without limiting the generality of the foregoing, Licensee shall not export, re-export, disclose or distribute any of the Licensed Software in violation of any applicable laws or regulations, including the export laws and regulations of the United States, and shall comply with all such laws and regulations.
-
-16. Entire Agreement: This Agreement constitutes the complete agreement between the parties and supersedes all prior or contemporaneous discussions, representations, and proposals, written or oral, with respect to the subject matters discussed herein. No modification of this Agreement will be effective unless contained in a writing executed by an authorized representative of each party. No term or condition contained in Licensee's purchase order will apply unless expressly accepted by Trolltech in writing. If any provision of the Agreement is found void or unenforceable, the remainder will remain valid and enforceable according to its terms. If any remedy provided is determined to have failed for its essential purpose, all limitations of liability and exclusions of damages set forth in this Agreement shall remain in effect.
-
-17. Governing law, legal venue: This Agreement shall be construed, interpreted and governed by the laws of Norway, the legal venue to be Oslo City Court. Trolltech reserves all rights not specifically granted in this Agreement.
diff --git a/installer/resources/logo.png b/installer/resources/logo.png
deleted file mode 100644
index 8a9562614b23d9508fbca6c57f2dc571b8ae5e53..0000000000000000000000000000000000000000
Binary files a/installer/resources/logo.png and /dev/null differ
diff --git a/installer/resources/watermark.png b/installer/resources/watermark.png
deleted file mode 100644
index b07780d9d049bd5e70b3a67eabb18ef100b1cc02..0000000000000000000000000000000000000000
Binary files a/installer/resources/watermark.png and /dev/null differ
diff --git a/qtcreator.pro b/qtcreator.pro
index 13f0b26fa3ed9c9b5fa4f2c120d0350061b6f45e..9a5e467eb6edfbdb6558d992786fa100655b06b7 100644
--- a/qtcreator.pro
+++ b/qtcreator.pro
@@ -2,3 +2,5 @@ TEMPLATE  = subdirs
 CONFIG   += ordered
 
 SUBDIRS = src
+
+include(doc/doc.pri)
diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp
index dcf32573616057c04731eec0b224f2b9b447fc99..9a8d41fe7a8f61d3eae470cd0186ca3c085d2c2c 100644
--- a/shared/cplusplus/AST.cpp
+++ b/shared/cplusplus/AST.cpp
@@ -408,6 +408,19 @@ unsigned AttributeSpecifierAST::lastToken() const
     return attribute_token + 1;
 }
 
+AttributeSpecifierAST *AttributeSpecifierAST::clone(MemoryPool *pool) const
+{
+    AttributeSpecifierAST *ast = new (pool) AttributeSpecifierAST;
+    ast->attribute_token = attribute_token;
+    ast->first_lparen_token = first_lparen_token;
+    ast->second_lparen_token = second_lparen_token;
+    if (attributes)
+        ast->attributes = attributes->clone(pool);
+    ast->first_rparen_token = first_rparen_token;
+    ast->second_rparen_token = second_rparen_token;
+    return ast;
+}
+
 void AttributeSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -442,6 +455,20 @@ unsigned AttributeAST::lastToken() const
     return identifier_token + 1;
 }
 
+AttributeAST *AttributeAST::clone(MemoryPool *pool) const
+{
+    AttributeAST *ast = new (pool) AttributeAST;
+    ast->identifier_token = identifier_token;
+    ast->lparen_token = lparen_token;
+    ast->tag_token = tag_token;
+    if (expression_list)
+        ast->expression_list = expression_list->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void AttributeAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -450,6 +477,15 @@ void AttributeAST::accept0(ASTVisitor *visitor)
     }
 }
 
+AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
+{
+    AccessDeclarationAST *ast = new (pool) AccessDeclarationAST;
+    ast->access_specifier_token = access_specifier_token;
+    ast->slots_token = slots_token;
+    ast->colon_token = colon_token;
+    return ast;
+}
+
 void AccessDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -470,6 +506,16 @@ unsigned AccessDeclarationAST::lastToken() const
     return access_specifier_token + 1;
 }
 
+ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
+{
+    ArrayAccessAST *ast = new (pool) ArrayAccessAST;
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
 void ArrayAccessAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -491,6 +537,16 @@ unsigned ArrayAccessAST::lastToken() const
     return lbracket_token + 1;
 }
 
+ArrayDeclaratorAST *ArrayDeclaratorAST::clone(MemoryPool *pool) const
+{
+    ArrayDeclaratorAST *ast = new (pool) ArrayDeclaratorAST;
+    ast->lbracket_token = lbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rbracket_token = rbracket_token;
+    return ast;
+}
+
 void ArrayDeclaratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -512,11 +568,20 @@ unsigned ArrayDeclaratorAST::lastToken() const
     return lbracket_token + 1;
 }
 
+ArrayInitializerAST *ArrayInitializerAST::clone(MemoryPool *pool) const
+{
+    ArrayInitializerAST *ast = new (pool) ArrayInitializerAST;
+    ast->lbrace_token = lbrace_token;
+    if (expression_list)
+        ast->expression_list = expression_list->clone(pool);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
 void ArrayInitializerAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
-        for (ExpressionListAST *expr = expression_list;expr;
-                 expr = expr->next)
+        for (ExpressionListAST *expr = expression_list; expr; expr = expr->next)
             accept(expr->expression, visitor);
     }
 }
@@ -539,6 +604,18 @@ unsigned ArrayInitializerAST::lastToken() const
     return lbrace_token + 1;
 }
 
+AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
+{
+    AsmDefinitionAST *ast = new (pool) AsmDefinitionAST;
+    ast->asm_token = asm_token;
+    if (cv_qualifier_seq)
+        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+    ast->lparen_token = lparen_token;
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void AsmDefinitionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -569,6 +646,18 @@ unsigned AsmDefinitionAST::lastToken() const
     return asm_token + 1;
 }
 
+BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const
+{
+    BaseSpecifierAST *ast = new (pool) BaseSpecifierAST;
+    ast->token_virtual = token_virtual;
+    ast->token_access_specifier = token_access_specifier;
+    if (name)
+        ast->name = name->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void BaseSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -611,6 +700,17 @@ unsigned QtMethodAST::lastToken() const
     return method_token + 1;
 }
 
+QtMethodAST *QtMethodAST::clone(MemoryPool *pool) const
+{
+    QtMethodAST *ast = new (pool) QtMethodAST;
+    ast->method_token = method_token;
+    ast->lparen_token = lparen_token;
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void QtMethodAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -618,6 +718,17 @@ void QtMethodAST::accept0(ASTVisitor *visitor)
     }
 }
 
+BinaryExpressionAST *BinaryExpressionAST::clone(MemoryPool *pool) const
+{
+    BinaryExpressionAST *ast = new (pool) BinaryExpressionAST;
+    if (left_expression)
+        ast->left_expression = left_expression->clone(pool);
+    ast->binary_op_token = binary_op_token;
+    if (right_expression)
+        ast->right_expression = right_expression->clone(pool);
+    return ast;
+}
+
 void BinaryExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -640,6 +751,13 @@ unsigned BinaryExpressionAST::lastToken() const
     return left_expression->lastToken();
 }
 
+BoolLiteralAST *BoolLiteralAST::clone(MemoryPool *pool) const
+{
+    BoolLiteralAST *ast = new (pool) BoolLiteralAST;
+    ast->token = token;
+    return ast;
+}
+
 void BoolLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -656,6 +774,14 @@ unsigned BoolLiteralAST::lastToken() const
     return token + 1;
 }
 
+BreakStatementAST *BreakStatementAST::clone(MemoryPool *pool) const
+{
+    BreakStatementAST *ast = new (pool) BreakStatementAST;
+    ast->break_token = break_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void BreakStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -674,6 +800,16 @@ unsigned BreakStatementAST::lastToken() const
     return break_token + 1;
 }
 
+CallAST *CallAST::clone(MemoryPool *pool) const
+{
+    CallAST *ast = new (pool) CallAST;
+    ast->lparen_token = lparen_token;
+    if (expression_list)
+        ast->expression_list = expression_list;
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void CallAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -699,6 +835,18 @@ unsigned CallAST::lastToken() const
     return lparen_token + 1;
 }
 
+CaseStatementAST *CaseStatementAST::clone(MemoryPool *pool) const
+{
+    CaseStatementAST *ast = new (pool) CaseStatementAST;
+    ast->case_token = case_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->colon_token = colon_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
 void CaseStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -721,6 +869,18 @@ unsigned CaseStatementAST::lastToken() const
     return case_token + 1;
 }
 
+CastExpressionAST *CastExpressionAST::clone(MemoryPool *pool) const
+{
+    CastExpressionAST *ast = new (pool) CastExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void CastExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -743,6 +903,21 @@ unsigned CastExpressionAST::lastToken() const
     return lparen_token + 1;
 }
 
+CatchClauseAST *CatchClauseAST::clone(MemoryPool *pool) const
+{
+    CatchClauseAST *ast = new (pool) CatchClauseAST;
+    ast->catch_token = catch_token;
+    ast->lparen_token = lparen_token;
+    if (exception_declaration)
+        ast->exception_declaration = exception_declaration->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void CatchClauseAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -772,6 +947,24 @@ unsigned CatchClauseAST::lastToken() const
     return catch_token + 1;
 }
 
+ClassSpecifierAST *ClassSpecifierAST::clone(MemoryPool *pool) const
+{
+    ClassSpecifierAST *ast = new (pool) ClassSpecifierAST;
+    ast->classkey_token = classkey_token;
+    if (attributes)
+        ast->attributes = attributes->clone(pool);
+    if (name)
+        ast->name = name->clone(pool);
+    ast->colon_token = colon_token;
+    if (base_clause)
+        ast->base_clause = base_clause->clone(pool);
+    ast->lbrace_token = lbrace_token;
+    if (member_specifiers)
+        ast->member_specifiers = member_specifiers->clone(pool);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
 void ClassSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -822,6 +1015,16 @@ unsigned ClassSpecifierAST::lastToken() const
     return classkey_token + 1;
 }
 
+CompoundStatementAST *CompoundStatementAST::clone(MemoryPool *pool) const
+{
+    CompoundStatementAST *ast = new (pool) CompoundStatementAST;
+    ast->lbrace_token = lbrace_token;
+    if (statements)
+        ast->statements = statements->clone(pool);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
 void CompoundStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -848,6 +1051,16 @@ unsigned CompoundStatementAST::lastToken() const
     return lbrace_token + 1;
 }
 
+ConditionAST *ConditionAST::clone(MemoryPool *pool) const
+{
+    ConditionAST *ast = new (pool) ConditionAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
 void ConditionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -879,6 +1092,20 @@ unsigned ConditionAST::lastToken() const
     return 0;
 }
 
+ConditionalExpressionAST *ConditionalExpressionAST::clone(MemoryPool *pool) const
+{
+    ConditionalExpressionAST *ast = new (pool) ConditionalExpressionAST;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->question_token = question_token;
+    if (left_expression)
+        ast->left_expression = left_expression->clone(pool);
+    ast->colon_token = colon_token;
+    if (right_expression)
+        ast->right_expression = right_expression->clone(pool);
+    return ast;
+}
+
 void ConditionalExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -909,6 +1136,14 @@ unsigned ConditionalExpressionAST::lastToken() const
     return 0;
 }
 
+ContinueStatementAST *ContinueStatementAST::clone(MemoryPool *pool) const
+{
+    ContinueStatementAST *ast = new (pool) ContinueStatementAST;
+    ast->continue_token = continue_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void ContinueStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -927,6 +1162,17 @@ unsigned ContinueStatementAST::lastToken() const
     return continue_token + 1;
 }
 
+ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
+{
+    ConversionFunctionIdAST *ast = new (pool) ConversionFunctionIdAST;
+    ast->operator_token = operator_token;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (ptr_operators)
+        ast->ptr_operators = ptr_operators->clone(pool);
+    return ast;
+}
+
 void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -958,6 +1204,21 @@ unsigned ConversionFunctionIdAST::lastToken() const
     return operator_token + 1;
 }
 
+CppCastExpressionAST *CppCastExpressionAST::clone(MemoryPool *pool) const
+{
+    CppCastExpressionAST *ast = new (pool) CppCastExpressionAST;
+    ast->cast_token = cast_token;
+    ast->less_token = less_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    ast->greater_token = greater_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void CppCastExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -988,6 +1249,15 @@ unsigned CppCastExpressionAST::lastToken() const
     return cast_token + 1;
 }
 
+CtorInitializerAST *CtorInitializerAST::clone(MemoryPool *pool) const
+{
+    CtorInitializerAST *ast = new (pool) CtorInitializerAST;
+    ast->colon_token = colon_token;
+    if (member_initializers)
+        ast->member_initializers = member_initializers->clone(pool);
+    return ast;
+}
+
 void CtorInitializerAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1011,6 +1281,22 @@ unsigned CtorInitializerAST::lastToken() const
     return colon_token + 1;
 }
 
+DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const
+{
+    DeclaratorAST *ast = new (pool) DeclaratorAST;
+    if (ptr_operators)
+        ast->ptr_operators = ptr_operators->clone(pool);
+    if (core_declarator)
+        ast->core_declarator = core_declarator->clone(pool);
+    if (postfix_declarators)
+        ast->postfix_declarators = postfix_declarators->clone(pool);
+    if (attributes)
+        ast->attributes = attributes->clone(pool);
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    return ast;
+}
+
 void DeclaratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1069,6 +1355,14 @@ unsigned DeclaratorAST::lastToken() const
     return 0;
 }
 
+DeclarationStatementAST *DeclarationStatementAST::clone(MemoryPool *pool) const
+{
+    DeclarationStatementAST *ast = new (pool) DeclarationStatementAST;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
 void DeclarationStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1086,6 +1380,14 @@ unsigned DeclarationStatementAST::lastToken() const
     return declaration->lastToken();
 }
 
+DeclaratorIdAST *DeclaratorIdAST::clone(MemoryPool *pool) const
+{
+    DeclaratorIdAST *ast = new (pool) DeclaratorIdAST;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
 void DeclaratorIdAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1103,6 +1405,16 @@ unsigned DeclaratorIdAST::lastToken() const
     return name->lastToken();
 }
 
+DeclaratorListAST *DeclaratorListAST::clone(MemoryPool *pool) const
+{
+    DeclaratorListAST *ast = new (pool) DeclaratorListAST;
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void DeclaratorListAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1125,6 +1437,18 @@ unsigned DeclaratorListAST::lastToken() const
     return 0;
 }
 
+DeleteExpressionAST *DeleteExpressionAST::clone(MemoryPool *pool) const
+{
+    DeleteExpressionAST *ast = new (pool) DeleteExpressionAST;
+    ast->scope_token = scope_token;
+    ast->delete_token = delete_token;
+    ast->lbracket_token = lbracket_token;
+    ast->rbracket_token = rbracket_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void DeleteExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1152,6 +1476,14 @@ unsigned DeleteExpressionAST::lastToken() const
     return scope_token + 1;
 }
 
+DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const
+{
+    DestructorNameAST *ast = new (pool) DestructorNameAST;
+    ast->tilde_token = tilde_token;
+    ast->identifier_token = identifier_token;
+    return ast;
+}
+
 void DestructorNameAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1170,6 +1502,21 @@ unsigned DestructorNameAST::lastToken() const
     return tilde_token + 1;
 }
 
+DoStatementAST *DoStatementAST::clone(MemoryPool *pool) const
+{
+    DoStatementAST *ast = new (pool) DoStatementAST;
+    ast->do_token = do_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    ast->while_token = while_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void DoStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1200,6 +1547,15 @@ unsigned DoStatementAST::lastToken() const
     return do_token + 1;
 }
 
+ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+    ElaboratedTypeSpecifierAST *ast = new (pool) ElaboratedTypeSpecifierAST;
+    ast->classkey_token = classkey_token;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
 void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1219,6 +1575,13 @@ unsigned ElaboratedTypeSpecifierAST::lastToken() const
     return classkey_token + 1;
 }
 
+EmptyDeclarationAST *EmptyDeclarationAST::clone(MemoryPool *pool) const
+{
+    EmptyDeclarationAST *ast = new (pool) EmptyDeclarationAST;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void EmptyDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1235,6 +1598,19 @@ unsigned EmptyDeclarationAST::lastToken() const
     return semicolon_token + 1;
 }
 
+EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const
+{
+    EnumSpecifierAST *ast = new (pool) EnumSpecifierAST;
+    ast->enum_token = enum_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->lbrace_token = lbrace_token;
+    if (enumerators)
+        ast->enumerators = enumerators->clone(pool);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
 void EnumSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1268,6 +1644,18 @@ unsigned EnumSpecifierAST::lastToken() const
     return enum_token + 1;
 }
 
+EnumeratorAST *EnumeratorAST::clone(MemoryPool *pool) const
+{
+    EnumeratorAST *ast = new (pool) EnumeratorAST;
+    ast->identifier_token = identifier_token;
+    ast->equal_token = equal_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void EnumeratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1289,6 +1677,17 @@ unsigned EnumeratorAST::lastToken() const
     return identifier_token + 1;
 }
 
+ExceptionDeclarationAST *ExceptionDeclarationAST::clone(MemoryPool *pool) const
+{
+    ExceptionDeclarationAST *ast = new (pool) ExceptionDeclarationAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    return ast;
+}
+
 void ExceptionDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1320,6 +1719,18 @@ unsigned ExceptionDeclarationAST::lastToken() const
     return 0;
 }
 
+ExceptionSpecificationAST *ExceptionSpecificationAST::clone(MemoryPool *pool) const
+{
+    ExceptionSpecificationAST *ast = new (pool) ExceptionSpecificationAST;
+    ast->throw_token = throw_token;
+    ast->lparen_token = lparen_token;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    if (type_ids)
+        ast->type_ids = type_ids->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void ExceptionSpecificationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1352,8 +1763,22 @@ unsigned ExceptionSpecificationAST::lastToken() const
     return throw_token + 1;
 }
 
-void ExpressionListAST::accept0(ASTVisitor *)
-{ assert(0); }
+ExpressionListAST *ExpressionListAST::clone(MemoryPool *pool) const
+{
+    ExpressionListAST *ast = new (pool) ExpressionListAST;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
+void ExpressionListAST::accept0(ASTVisitor *visitor)
+{
+    for (const ExpressionListAST *it = this; it; it = it->next) {
+        accept(it->expression, visitor);
+    }
+}
 
 unsigned ExpressionListAST::firstToken() const
 {
@@ -1369,6 +1794,16 @@ unsigned ExpressionListAST::lastToken() const
     return 0;
 }
 
+ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatementAST::clone(MemoryPool *pool) const
+{
+    ExpressionOrDeclarationStatementAST *ast = new (pool) ExpressionOrDeclarationStatementAST;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
 void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1387,6 +1822,15 @@ unsigned ExpressionOrDeclarationStatementAST::lastToken() const
     return declaration->lastToken();
 }
 
+ExpressionStatementAST *ExpressionStatementAST::clone(MemoryPool *pool) const
+{
+    ExpressionStatementAST *ast = new (pool) ExpressionStatementAST;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void ExpressionStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1411,6 +1855,24 @@ unsigned ExpressionStatementAST::lastToken() const
     return 0;
 }
 
+ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const
+{
+    ForStatementAST *ast = new (pool) ForStatementAST;
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
 void ForStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1446,6 +1908,20 @@ unsigned ForStatementAST::lastToken() const
     return for_token + 1;
 }
 
+FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const
+{
+    FunctionDeclaratorAST *ast = new (pool) FunctionDeclaratorAST;
+    ast->lparen_token = lparen_token;
+    if (parameters)
+        ast->parameters = parameters->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (cv_qualifier_seq)
+        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+    if (exception_specification)
+        ast->exception_specification = exception_specification->clone(pool);
+    return ast;
+}
+
 void FunctionDeclaratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1475,6 +1951,20 @@ unsigned FunctionDeclaratorAST::lastToken() const
     return lparen_token + 1;
 }
 
+FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const
+{
+    FunctionDefinitionAST *ast = new (pool) FunctionDefinitionAST;
+    if (decl_specifier_seq)
+        ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    if (ctor_initializer)
+        ast->ctor_initializer = ctor_initializer->clone(pool);
+    if (function_body)
+        ast->function_body = function_body->clone(pool);
+    return ast;
+}
+
 void FunctionDefinitionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1516,6 +2006,15 @@ unsigned FunctionDefinitionAST::lastToken() const
     return 0;
 }
 
+GotoStatementAST *GotoStatementAST::clone(MemoryPool *pool) const
+{
+    GotoStatementAST *ast = new (pool) GotoStatementAST;
+    ast->goto_token = goto_token;
+    ast->identifier_token = identifier_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void GotoStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1538,6 +2037,22 @@ unsigned GotoStatementAST::lastToken() const
     return 0;
 }
 
+IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const
+{
+    IfStatementAST *ast = new (pool) IfStatementAST;
+    ast->if_token = if_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    ast->else_token = else_token;
+    if (else_statement)
+        ast->else_statement = else_statement->clone(pool);
+    return ast;
+}
+
 void IfStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1569,6 +2084,16 @@ unsigned IfStatementAST::lastToken() const
     return if_token + 1;
 }
 
+LabeledStatementAST *LabeledStatementAST::clone(MemoryPool *pool) const
+{
+    LabeledStatementAST *ast = new (pool) LabeledStatementAST;
+    ast->label_token = label_token;
+    ast->colon_token = colon_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
 void LabeledStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1590,6 +2115,16 @@ unsigned LabeledStatementAST::lastToken() const
     return label_token + 1;
 }
 
+LinkageBodyAST *LinkageBodyAST::clone(MemoryPool *pool) const
+{
+    LinkageBodyAST *ast = new (pool) LinkageBodyAST;
+    ast->lbrace_token = lbrace_token;
+    if (declarations)
+        ast->declarations = declarations->clone(pool);
+    ast->rbrace_token = rbrace_token;
+    return ast;
+}
+
 void LinkageBodyAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1617,6 +2152,16 @@ unsigned LinkageBodyAST::lastToken() const
     return lbrace_token + 1;
 }
 
+LinkageSpecificationAST *LinkageSpecificationAST::clone(MemoryPool *pool) const
+{
+    LinkageSpecificationAST *ast = new (pool) LinkageSpecificationAST;
+    ast->extern_token = extern_token;
+    ast->extern_type = extern_type;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
 void LinkageSpecificationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1638,6 +2183,20 @@ unsigned LinkageSpecificationAST::lastToken() const
     return extern_token + 1;
 }
 
+MemInitializerAST *MemInitializerAST::clone(MemoryPool *pool) const
+{
+    MemInitializerAST *ast = new (pool) MemInitializerAST;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void MemInitializerAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1661,6 +2220,16 @@ unsigned MemInitializerAST::lastToken() const
     return name->lastToken();
 }
 
+MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const
+{
+    MemberAccessAST *ast = new (pool) MemberAccessAST;
+    ast->access_token = access_token;
+    ast->template_token = template_token;
+    if (member_name)
+        ast->member_name = member_name->clone(pool);
+    return ast;
+}
+
 void MemberAccessAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1682,6 +2251,14 @@ unsigned MemberAccessAST::lastToken() const
     return access_token + 1;
 }
 
+NamedTypeSpecifierAST *NamedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+    NamedTypeSpecifierAST *ast = new (pool) NamedTypeSpecifierAST;
+    if (name)
+        ast->name = name->clone(pool);
+    return ast;
+}
+
 void NamedTypeSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1699,6 +2276,18 @@ unsigned NamedTypeSpecifierAST::lastToken() const
     return name->lastToken();
 }
 
+NamespaceAST *NamespaceAST::clone(MemoryPool *pool) const
+{
+    NamespaceAST *ast = new (pool) NamespaceAST;
+    ast->namespace_token = namespace_token;
+    ast->identifier_token = identifier_token;
+    if (attributes)
+        ast->attributes = attributes->clone(pool);
+    if (linkage_body)
+        ast->linkage_body = linkage_body->clone(pool);
+    return ast;
+}
+
 void NamespaceAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1730,6 +2319,18 @@ unsigned NamespaceAST::lastToken() const
     return namespace_token + 1;
 }
 
+NamespaceAliasDefinitionAST *NamespaceAliasDefinitionAST::clone(MemoryPool *pool) const
+{
+    NamespaceAliasDefinitionAST *ast = new (pool) NamespaceAliasDefinitionAST;
+    ast->namespace_token = namespace_token;
+    ast->namespace_name = namespace_name;
+    ast->equal_token = equal_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void NamespaceAliasDefinitionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1755,6 +2356,16 @@ unsigned NamespaceAliasDefinitionAST::lastToken() const
     return namespace_token + 1;
 }
 
+NestedDeclaratorAST *NestedDeclaratorAST::clone(MemoryPool *pool) const
+{
+    NestedDeclaratorAST *ast = new (pool) NestedDeclaratorAST;
+    ast->lparen_token = lparen_token;
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1776,6 +2387,16 @@ unsigned NestedDeclaratorAST::lastToken() const
     return lparen_token + 1;
 }
 
+NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const
+{
+    NestedExpressionAST *ast = new (pool) NestedExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void NestedExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1797,6 +2418,17 @@ unsigned NestedExpressionAST::lastToken() const
     return lparen_token + 1;
 }
 
+NestedNameSpecifierAST *NestedNameSpecifierAST::clone(MemoryPool *pool) const
+{
+    NestedNameSpecifierAST *ast = new (pool) NestedNameSpecifierAST;
+    if (class_or_namespace_name)
+        ast->class_or_namespace_name = class_or_namespace_name->clone(pool);
+    ast->scope_token = scope_token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void NestedNameSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1817,13 +2449,25 @@ unsigned NestedNameSpecifierAST::lastToken() const
     return class_or_namespace_name->lastToken();
 }
 
+NewDeclaratorAST *NewDeclaratorAST::clone(MemoryPool *pool) const
+{
+    NewDeclaratorAST *ast = new (pool) NewDeclaratorAST;
+    if (ptr_operators)
+        ast->ptr_operators = ptr_operators->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
 void NewDeclaratorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op;
-                 ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next))
+                 ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next)) {
             accept(ptr_op, visitor);
-        // ### TODO accept the brackets
+        }
+
+        accept(declarator, visitor);
     }
 }
 
@@ -1834,17 +2478,37 @@ unsigned NewDeclaratorAST::firstToken() const
 
 unsigned NewDeclaratorAST::lastToken() const
 {
-    assert(0 && "review me");
     if (declarator)
         return declarator->lastToken();
-    assert(0); // ### implement me
+
+    for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
     return 0;
 }
 
-void NewExpressionAST::accept0(ASTVisitor *visitor)
+NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const
 {
-    if (visitor->visit(this)) {
-        accept(expression, visitor);
+    NewExpressionAST *ast = new (pool) NewExpressionAST;
+    ast->scope_token = scope_token;
+    ast->new_token = new_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    if (new_type_id)
+        ast->new_type_id = new_type_id->clone(pool);
+    if (new_initializer)
+        ast->new_initializer = new_initializer->clone(pool);
+    return ast;
+}
+
+void NewExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
         accept(type_id, visitor);
         accept(new_type_id, visitor);
         accept(new_initializer, visitor);
@@ -1860,7 +2524,6 @@ unsigned NewExpressionAST::firstToken() const
 
 unsigned NewExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     if (new_initializer)
         return new_initializer->lastToken();
     else if (new_type_id)
@@ -1869,7 +2532,22 @@ unsigned NewExpressionAST::lastToken() const
         return type_id->lastToken();
     else if (expression)
         return expression->lastToken();
-    return new_token + 1;
+    else if (new_token)
+        return new_token + 1;
+    else if (scope_token)
+        return scope_token + 1;
+    // ### assert?
+    return 0;
+}
+
+NewInitializerAST *NewInitializerAST::clone(MemoryPool *pool) const
+{
+    NewInitializerAST *ast = new (pool) NewInitializerAST;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
 }
 
 void NewInitializerAST::accept0(ASTVisitor *visitor)
@@ -1886,8 +2564,33 @@ unsigned NewInitializerAST::firstToken() const
 
 unsigned NewInitializerAST::lastToken() const
 {
-    assert(0 && "review me");
-    return rparen_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    else if (expression)
+        return expression->lastToken();
+    return lparen_token + 1;
+}
+
+TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const
+{
+    TypeIdAST *ast = new (pool) TypeIdAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    return ast;
+}
+
+NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const
+{
+    NewTypeIdAST *ast = new (pool) NewTypeIdAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (new_initializer)
+        ast->new_initializer = new_initializer->clone(pool);
+    if (new_declarator)
+        ast->new_declarator = new_declarator->clone(pool);
+    return ast;
 }
 
 void NewTypeIdAST::accept0(ASTVisitor *visitor)
@@ -1907,7 +2610,6 @@ unsigned NewTypeIdAST::firstToken() const
 
 unsigned NewTypeIdAST::lastToken() const
 {
-    assert(0 && "review me");
     if (new_declarator)
         return new_declarator->lastToken();
     else if (new_initializer)
@@ -1916,9 +2618,18 @@ unsigned NewTypeIdAST::lastToken() const
         if (! it->next)
             return it->lastToken();
     }
+
+    // ### assert?
     return 0;
 }
 
+NumericLiteralAST *NumericLiteralAST::clone(MemoryPool *pool) const
+{
+    NumericLiteralAST *ast = new (pool) NumericLiteralAST;
+    ast->token = token;
+    return ast;
+}
+
 void NumericLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1932,10 +2643,18 @@ unsigned NumericLiteralAST::firstToken() const
 
 unsigned NumericLiteralAST::lastToken() const
 {
-    assert(0 && "review me");
     return token + 1;
 }
 
+OperatorAST *OperatorAST::clone(MemoryPool *pool) const
+{
+    OperatorAST *ast = new (pool) OperatorAST;
+    ast->op_token = op_token;
+    ast->open_token = open_token;
+    ast->close_token = close_token;
+    return ast;
+}
+
 void OperatorAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1949,12 +2668,22 @@ unsigned OperatorAST::firstToken() const
 
 unsigned OperatorAST::lastToken() const
 {
-    assert(0 && "review me");
     if (close_token)
         return close_token + 1;
+    else if (open_token)
+        return open_token + 1;
     return op_token + 1;
 }
 
+OperatorFunctionIdAST *OperatorFunctionIdAST::clone(MemoryPool *pool) const
+{
+    OperatorFunctionIdAST *ast = new (pool) OperatorFunctionIdAST;
+    ast->operator_token = operator_token;
+    if (op)
+        ast->op = op->clone(pool);
+    return ast;
+}
+
 void OperatorFunctionIdAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1969,12 +2698,24 @@ unsigned OperatorFunctionIdAST::firstToken() const
 
 unsigned OperatorFunctionIdAST::lastToken() const
 {
-    assert(0 && "review me");
     if (op)
         return op->lastToken();
     return operator_token + 1;
 }
 
+ParameterDeclarationAST *ParameterDeclarationAST::clone(MemoryPool *pool) const
+{
+    ParameterDeclarationAST *ast = new (pool) ParameterDeclarationAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->equal_token = equal_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void ParameterDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -1992,20 +2733,29 @@ unsigned ParameterDeclarationAST::firstToken() const
 
 unsigned ParameterDeclarationAST::lastToken() const
 {
-    assert(0 && "review me");
     if (expression)
         return expression->lastToken();
     else if (equal_token)
         return equal_token + 1;
     else if (declarator)
         return declarator->lastToken();
-        for (SpecifierAST *it = type_specifier; it; it = it->next) {
+    for (SpecifierAST *it = type_specifier; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
     }
+    // ### assert?
     return 0;
 }
 
+ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *pool) const
+{
+    ParameterDeclarationClauseAST *ast = new (pool) ParameterDeclarationClauseAST;
+    if (parameter_declarations)
+        ast->parameter_declarations = parameter_declarations;
+    ast->dot_dot_dot_token = dot_dot_dot_token;
+    return ast;
+}
+
 void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2024,12 +2774,20 @@ unsigned ParameterDeclarationClauseAST::firstToken() const
 
 unsigned ParameterDeclarationClauseAST::lastToken() const
 {
-    assert(0 && "review me");
     if (dot_dot_dot_token)
         return dot_dot_dot_token + 1;
     return parameter_declarations->lastToken();
 }
 
+PointerAST *PointerAST::clone(MemoryPool *pool) const
+{
+    PointerAST *ast = new (pool) PointerAST;
+    ast->star_token = star_token;
+    if (cv_qualifier_seq)
+        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+    return ast;
+}
+
 void PointerAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2046,7 +2804,6 @@ unsigned PointerAST::firstToken() const
 
 unsigned PointerAST::lastToken() const
 {
-    assert(0 && "review me");
     for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
@@ -2054,6 +2811,18 @@ unsigned PointerAST::lastToken() const
     return star_token + 1;
 }
 
+PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const
+{
+    PointerToMemberAST *ast = new (pool) PointerToMemberAST;
+    ast->global_scope_token = global_scope_token;
+    if (nested_name_specifier)
+        ast->nested_name_specifier = nested_name_specifier->clone(pool);
+    ast->star_token = star_token;
+    if (cv_qualifier_seq)
+        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+    return ast;
+}
+
 void PointerToMemberAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2075,12 +2844,30 @@ unsigned PointerToMemberAST::firstToken() const
 
 unsigned PointerToMemberAST::lastToken() const
 {
-    assert(0 && "review me");
     for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
     }
-    return star_token + 1;
+
+    if (star_token)
+        return star_token + 1;
+
+    for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (global_scope_token)
+        return global_scope_token + 1;
+
+    return 0;
+}
+
+PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
+{
+    PostIncrDecrAST *ast = new (pool) PostIncrDecrAST;
+    ast->incr_decr_token = incr_decr_token;
+    return ast;
 }
 
 void PostIncrDecrAST::accept0(ASTVisitor *visitor)
@@ -2096,10 +2883,19 @@ unsigned PostIncrDecrAST::firstToken() const
 
 unsigned PostIncrDecrAST::lastToken() const
 {
-    assert(0 && "review me");
     return incr_decr_token + 1;
 }
 
+PostfixExpressionAST *PostfixExpressionAST::clone(MemoryPool *pool) const
+{
+    PostfixExpressionAST *ast = new (pool) PostfixExpressionAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
+    if (postfix_expressions)
+        ast->postfix_expressions = postfix_expressions->clone(pool);
+    return ast;
+}
+
 void PostfixExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2116,7 +2912,6 @@ unsigned PostfixExpressionAST::firstToken() const
 
 unsigned PostfixExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     for (PostfixAST *it = postfix_expressions; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
@@ -2124,6 +2919,17 @@ unsigned PostfixExpressionAST::lastToken() const
     return base_expression->lastToken();
 }
 
+QualifiedNameAST *QualifiedNameAST::clone(MemoryPool *pool) const
+{
+    QualifiedNameAST *ast = new (pool) QualifiedNameAST;
+    ast->global_scope_token = global_scope_token;
+    if (nested_name_specifier)
+        ast->nested_name_specifier = nested_name_specifier->clone(pool);
+    if (unqualified_name)
+        ast->unqualified_name = unqualified_name->clone(pool);
+    return ast;
+}
+
 void QualifiedNameAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2143,12 +2949,25 @@ unsigned QualifiedNameAST::firstToken() const
 
 unsigned QualifiedNameAST::lastToken() const
 {
-    assert(0 && "review me");
     if (unqualified_name)
         return unqualified_name->lastToken();
-    else if (nested_name_specifier)
-        return nested_name_specifier->lastToken();
-    return global_scope_token + 1;
+
+    for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (global_scope_token)
+        return global_scope_token + 1;
+
+    return 0;
+}
+
+ReferenceAST *ReferenceAST::clone(MemoryPool *pool) const
+{
+    ReferenceAST *ast = new (pool) ReferenceAST;
+    ast->amp_token = amp_token;
+    return ast;
 }
 
 void ReferenceAST::accept0(ASTVisitor *visitor)
@@ -2164,10 +2983,19 @@ unsigned ReferenceAST::firstToken() const
 
 unsigned ReferenceAST::lastToken() const
 {
-    assert(0 && "review me");
     return amp_token + 1;
 }
 
+ReturnStatementAST *ReturnStatementAST::clone(MemoryPool *pool) const
+{
+    ReturnStatementAST *ast = new (pool) ReturnStatementAST;
+    ast->return_token = return_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void ReturnStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2182,8 +3010,22 @@ unsigned ReturnStatementAST::firstToken() const
 
 unsigned ReturnStatementAST::lastToken() const
 {
-    assert(0 && "review me");
-    return semicolon_token + 1;
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else if (expression)
+        return expression->lastToken();
+    return return_token + 1;
+}
+
+SimpleDeclarationAST *SimpleDeclarationAST::clone(MemoryPool *pool) const
+{
+    SimpleDeclarationAST *ast = new (pool) SimpleDeclarationAST;
+    if (decl_specifier_seq)
+        ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
+    if (declarators)
+        ast->declarators = declarators->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
 }
 
 void SimpleDeclarationAST::accept0(ASTVisitor *visitor)
@@ -2202,26 +3044,34 @@ unsigned SimpleDeclarationAST::firstToken() const
         return decl_specifier_seq->firstToken();
     else if (declarators)
         return declarators->firstToken();
-    else
-        return semicolon_token;
+    return semicolon_token;
 }
 
 unsigned SimpleDeclarationAST::lastToken() const
 {
-    assert(0 && "review me");
     if (semicolon_token)
         return semicolon_token + 1;
+
     for (DeclaratorListAST *it = declarators; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
     }
+
     for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
     }
+
     return 0;
 }
 
+SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
+{
+    SimpleNameAST *ast = new (pool) SimpleNameAST;
+    ast->identifier_token = identifier_token;
+    return ast;
+}
+
 void SimpleNameAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2235,7 +3085,6 @@ unsigned SimpleNameAST::firstToken() const
 
 unsigned SimpleNameAST::lastToken() const
 {
-    assert(0 && "review me");
     return identifier_token + 1;
 }
 
@@ -2245,6 +3094,15 @@ void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
     }
 }
 
+SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
+{
+    SimpleSpecifierAST *ast = new (pool) SimpleSpecifierAST;
+    ast->specifier_token = specifier_token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 unsigned SimpleSpecifierAST::firstToken() const
 {
     return specifier_token;
@@ -2252,10 +3110,20 @@ unsigned SimpleSpecifierAST::firstToken() const
 
 unsigned SimpleSpecifierAST::lastToken() const
 {
-    assert(0 && "review me");
     return specifier_token + 1;
 }
 
+TypeofSpecifierAST *TypeofSpecifierAST::clone(MemoryPool *pool) const
+{
+    TypeofSpecifierAST *ast = new (pool) TypeofSpecifierAST;
+    ast->typeof_token = typeof_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void TypeofSpecifierAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2270,12 +3138,20 @@ unsigned TypeofSpecifierAST::firstToken() const
 
 unsigned TypeofSpecifierAST::lastToken() const
 {
-    assert(0 && "review me");
     if (expression)
         return expression->lastToken();
     return typeof_token + 1;
 }
 
+SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
+{
+    SizeofExpressionAST *ast = new (pool) SizeofExpressionAST;
+    ast->sizeof_token = sizeof_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void SizeofExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2290,12 +3166,20 @@ unsigned SizeofExpressionAST::firstToken() const
 
 unsigned SizeofExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     if (expression)
         return expression->lastToken();
     return sizeof_token + 1;
 }
 
+StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const
+{
+    StringLiteralAST *ast = new (pool) StringLiteralAST;
+    ast->token = token;
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
+}
+
 void StringLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2310,12 +3194,24 @@ unsigned StringLiteralAST::firstToken() const
 
 unsigned StringLiteralAST::lastToken() const
 {
-    assert(0 && "review me");
     if (next)
         return next->lastToken();
     return token + 1;
 }
 
+SwitchStatementAST *SwitchStatementAST::clone(MemoryPool *pool) const
+{
+    SwitchStatementAST *ast = new (pool) SwitchStatementAST;
+    ast->switch_token = switch_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
+}
+
 void SwitchStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2331,10 +3227,25 @@ unsigned SwitchStatementAST::firstToken() const
 
 unsigned SwitchStatementAST::lastToken() const
 {
-    assert(0 && "review me");
     if (statement)
         return statement->lastToken();
-    return rparen_token + 1;
+    else if (rparen_token)
+        return rparen_token + 1;
+    else if (condition)
+        return condition->lastToken();
+    else if (lparen_token)
+        return lparen_token + 1;
+    return switch_token + 1;
+}
+
+TemplateArgumentListAST *TemplateArgumentListAST::clone(MemoryPool *pool) const
+{
+    TemplateArgumentListAST *ast = new (pool) TemplateArgumentListAST;
+    if (template_argument)
+        ast->template_argument = template_argument->clone(pool);
+    if (next)
+        ast->next = next->clone(pool);
+    return ast;
 }
 
 void TemplateArgumentListAST::accept0(ASTVisitor *visitor)
@@ -2352,14 +3263,27 @@ unsigned TemplateArgumentListAST::firstToken() const
 
 unsigned TemplateArgumentListAST::lastToken() const
 {
-    assert(0 && "review me");
     for (const TemplateArgumentListAST *it = this; it; it = it->next) {
-        if (! it->next)
+        if (! it->next && it->template_argument)
             return it->template_argument->lastToken();
     }
     return 0;
 }
 
+TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
+{
+    TemplateDeclarationAST *ast = new (pool) TemplateDeclarationAST;
+    ast->export_token = export_token;
+    ast->template_token = template_token;
+    ast->less_token = less_token;
+    if (template_parameters)
+        ast->template_parameters = template_parameters->clone(pool);
+    ast->greater_token = greater_token;
+    if (declaration)
+        ast->declaration = declaration->clone(pool);
+    return ast;
+}
+
 void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2379,10 +3303,35 @@ unsigned TemplateDeclarationAST::firstToken() const
 
 unsigned TemplateDeclarationAST::lastToken() const
 {
-    assert(0 && "review me");
     if (declaration)
         return declaration->lastToken();
-    return greater_token + 1;
+    else if (greater_token)
+        return greater_token + 1;
+
+    for (DeclarationAST *it = template_parameters; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (less_token)
+        return less_token + 1;
+    else if (template_token)
+        return template_token + 1;
+    else if (export_token)
+        return export_token + 1;
+
+    return 0;
+}
+
+TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const
+{
+    TemplateIdAST *ast = new (pool) TemplateIdAST;
+    ast->identifier_token = identifier_token;
+    ast->less_token = less_token;
+    if (template_arguments)
+        ast->template_arguments = template_arguments->clone(pool);
+    ast->greater_token = greater_token;
+    return ast;
 }
 
 void TemplateIdAST::accept0(ASTVisitor *visitor)
@@ -2401,8 +3350,35 @@ unsigned TemplateIdAST::firstToken() const
 
 unsigned TemplateIdAST::lastToken() const
 {
-    assert(0 && "review me");
-    return greater_token + 1;
+    if (greater_token)
+        return greater_token + 1;
+
+    for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) {
+        if (! it->next && it->template_argument)
+            return it->template_argument->lastToken();
+    }
+
+    if (less_token)
+        return less_token + 1;
+
+    return identifier_token + 1;
+}
+
+TemplateTypeParameterAST *TemplateTypeParameterAST::clone(MemoryPool *pool) const
+{
+    TemplateTypeParameterAST *ast = new (pool) TemplateTypeParameterAST;
+    ast->template_token = template_token;
+    ast->less_token = less_token;
+    if (template_parameters)
+        ast->template_parameters = template_parameters->clone(pool);
+    ast->greater_token = greater_token;
+    ast->class_token = class_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->equal_token = equal_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    return ast;
 }
 
 void TemplateTypeParameterAST::accept0(ASTVisitor *visitor)
@@ -2418,7 +3394,6 @@ unsigned TemplateTypeParameterAST::firstToken() const
 
 unsigned TemplateTypeParameterAST::lastToken() const
 {
-    assert(0 && "review me");
     if (type_id)
         return type_id->lastToken();
     else if (equal_token)
@@ -2427,7 +3402,25 @@ unsigned TemplateTypeParameterAST::lastToken() const
         return name->lastToken();
     else if (class_token)
         return class_token + 1;
-    return greater_token + 1;
+    else if (greater_token)
+        return greater_token + 1;
+
+    for (DeclarationAST *it = template_parameters; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (less_token)
+        return less_token + 1;
+
+    return template_token + 1;
+}
+
+ThisExpressionAST *ThisExpressionAST::clone(MemoryPool *pool) const
+{
+    ThisExpressionAST *ast = new (pool) ThisExpressionAST;
+    ast->this_token = this_token;
+    return ast;
 }
 
 void ThisExpressionAST::accept0(ASTVisitor *visitor)
@@ -2443,10 +3436,18 @@ unsigned ThisExpressionAST::firstToken() const
 
 unsigned ThisExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     return this_token + 1;
 }
 
+ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
+{
+    ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
+    ast->throw_token = throw_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void ThrowExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2461,12 +3462,19 @@ unsigned ThrowExpressionAST::firstToken() const
 
 unsigned ThrowExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     if (expression)
         return expression->lastToken();
     return throw_token + 1;
 }
 
+TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const
+{
+    TranslationUnitAST *ast = new (pool) TranslationUnitAST;
+    if (declarations)
+        ast->declarations = declarations->clone(pool);
+    return ast;
+}
+
 void TranslationUnitAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2483,7 +3491,6 @@ unsigned TranslationUnitAST::firstToken() const
 
 unsigned TranslationUnitAST::lastToken() const
 {
-    assert(0 && "review me");
     for (DeclarationAST *it = declarations; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
@@ -2491,6 +3498,17 @@ unsigned TranslationUnitAST::lastToken() const
     return 0;
 }
 
+TryBlockStatementAST *TryBlockStatementAST::clone(MemoryPool *pool) const
+{
+    TryBlockStatementAST *ast = new (pool) TryBlockStatementAST;
+    ast->try_token = try_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    if (catch_clause_seq)
+        ast->catch_clause_seq = catch_clause_seq->clone(pool);
+    return ast;
+}
+
 void TryBlockStatementAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2506,16 +3524,29 @@ unsigned TryBlockStatementAST::firstToken() const
 
 unsigned TryBlockStatementAST::lastToken() const
 {
-    assert(0 && "review me");
     for (CatchClauseAST *it = catch_clause_seq; it; it = it->next) {
         if (! it->next)
             return it->lastToken();
     }
+
     if (statement)
         return statement->lastToken();
+
     return try_token + 1;
 }
 
+TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const
+{
+    TypeConstructorCallAST *ast = new (pool) TypeConstructorCallAST;
+    if (type_specifier)
+        ast->type_specifier = type_specifier->clone(pool);
+    ast->lparen_token = lparen_token;
+    if (expression_list)
+        ast->expression_list = expression_list;
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 void TypeConstructorCallAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2534,8 +3565,24 @@ unsigned TypeConstructorCallAST::firstToken() const
 
 unsigned TypeConstructorCallAST::lastToken() const
 {
-    assert(0 && "review me");
-    return rparen_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+
+    for (ExpressionListAST *it = expression_list; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (lparen_token)
+        return lparen_token + 1;
+
+
+    for (SpecifierAST *it = type_specifier; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    return 0;
 }
 
 void TypeIdAST::accept0(ASTVisitor *visitor)
@@ -2554,10 +3601,26 @@ unsigned TypeIdAST::firstToken() const
 
 unsigned TypeIdAST::lastToken() const
 {
-    assert(0 && "review me");
     if (declarator)
         return declarator->lastToken();
-    return type_specifier->lastToken();
+
+    for (SpecifierAST *it = type_specifier; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    return 0;
+}
+
+TypeidExpressionAST *TypeidExpressionAST::clone(MemoryPool *pool) const
+{
+    TypeidExpressionAST *ast = new (pool) TypeidExpressionAST;
+    ast->typeid_token = typeid_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
 }
 
 void TypeidExpressionAST::accept0(ASTVisitor *visitor)
@@ -2574,8 +3637,27 @@ unsigned TypeidExpressionAST::firstToken() const
 
 unsigned TypeidExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
-    return rparen_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    else if (expression)
+        return expression->lastToken();
+    else if (lparen_token)
+        return lparen_token + 1;
+
+    return typeid_token + 1;
+}
+
+TypenameCallExpressionAST *TypenameCallExpressionAST::clone(MemoryPool *pool) const
+{
+    TypenameCallExpressionAST *ast = new (pool) TypenameCallExpressionAST;
+    ast->typename_token = typename_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->lparen_token = lparen_token;
+    if (expression_list)
+        ast->expression_list = expression_list;
+    ast->rparen_token = rparen_token;
+    return ast;
 }
 
 void TypenameCallExpressionAST::accept0(ASTVisitor *visitor)
@@ -2595,8 +3677,32 @@ unsigned TypenameCallExpressionAST::firstToken() const
 
 unsigned TypenameCallExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
-    return rparen_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+
+    for (ExpressionListAST *it = expression_list; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (lparen_token)
+        return lparen_token + 1;
+    else if (name)
+        return name->lastToken();
+
+    return typename_token + 1;
+}
+
+TypenameTypeParameterAST *TypenameTypeParameterAST::clone(MemoryPool *pool) const
+{
+    TypenameTypeParameterAST *ast = new (pool) TypenameTypeParameterAST;
+    ast->classkey_token = classkey_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->equal_token = equal_token;
+    if (type_id)
+        ast->type_id = type_id->clone(pool);
+    return ast;
 }
 
 void TypenameTypeParameterAST::accept0(ASTVisitor *visitor)
@@ -2614,7 +3720,6 @@ unsigned TypenameTypeParameterAST::firstToken() const
 
 unsigned TypenameTypeParameterAST::lastToken() const
 {
-    assert(0 && "review me");
     if (type_id)
         return type_id->lastToken();
     else if (equal_token)
@@ -2624,6 +3729,15 @@ unsigned TypenameTypeParameterAST::lastToken() const
     return classkey_token + 1;
 }
 
+UnaryExpressionAST *UnaryExpressionAST::clone(MemoryPool *pool) const
+{
+    UnaryExpressionAST *ast = new (pool) UnaryExpressionAST;
+    ast->unary_op_token = unary_op_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    return ast;
+}
+
 void UnaryExpressionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2638,12 +3752,22 @@ unsigned UnaryExpressionAST::firstToken() const
 
 unsigned UnaryExpressionAST::lastToken() const
 {
-    assert(0 && "review me");
     if (expression)
         return expression->lastToken();
     return unary_op_token + 1;
 }
 
+UsingAST *UsingAST::clone(MemoryPool *pool) const
+{
+    UsingAST *ast = new (pool) UsingAST;
+    ast->using_token = using_token;
+    ast->typename_token = typename_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 void UsingAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
@@ -2658,8 +3782,24 @@ unsigned UsingAST::firstToken() const
 
 unsigned UsingAST::lastToken() const
 {
-    assert(0 && "review me");
-    return semicolon_token + 1;
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else if (name)
+        return name->lastToken();
+    else if (typename_token)
+        return typename_token + 1;
+    return using_token + 1;
+}
+
+UsingDirectiveAST *UsingDirectiveAST::clone(MemoryPool *pool) const
+{
+    UsingDirectiveAST *ast = new (pool) UsingDirectiveAST;
+    ast->using_token = using_token;
+    ast->namespace_token = namespace_token;
+    if (name)
+        ast->name = name->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
 }
 
 void UsingDirectiveAST::accept0(ASTVisitor *visitor)
@@ -2676,8 +3816,26 @@ unsigned UsingDirectiveAST::firstToken() const
 
 unsigned UsingDirectiveAST::lastToken() const
 {
-    assert(0 && "review me");
-    return semicolon_token + 1;
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else if (name)
+        return name->lastToken();
+    else if (namespace_token)
+        return namespace_token + 1;
+    return using_token + 1;
+}
+
+WhileStatementAST *WhileStatementAST::clone(MemoryPool *pool) const
+{
+    WhileStatementAST *ast = new (pool) WhileStatementAST;
+    ast->while_token = while_token;
+    ast->lparen_token = lparen_token;
+    if (condition)
+        ast->condition = condition->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (statement)
+        ast->statement = statement->clone(pool);
+    return ast;
 }
 
 void WhileStatementAST::accept0(ASTVisitor *visitor)
@@ -2695,10 +3853,15 @@ unsigned WhileStatementAST::firstToken() const
 
 unsigned WhileStatementAST::lastToken() const
 {
-    assert(0 && "review me");
     if (statement)
         return statement->lastToken();
-    return rparen_token + 1;
+    else if (rparen_token)
+        return rparen_token + 1;
+    else if (condition)
+        return condition->lastToken();
+    else if (lparen_token)
+        return lparen_token + 1;
+    return while_token + 1;
 }
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h
index be4f26d9f9c1531f0fef9de326aab0db067ebf08..ace137760f1373716a0fc8210a0f6af2454ce3fa 100644
--- a/shared/cplusplus/AST.h
+++ b/shared/cplusplus/AST.h
@@ -183,6 +183,8 @@ public:
     UsingDirectiveAST *asUsingDirective();
     WhileStatementAST *asWhileStatement();
 
+    virtual AST *clone(MemoryPool *pool) const = 0;
+
 protected:
     virtual void accept0(ASTVisitor *visitor) = 0;
 };
@@ -191,6 +193,9 @@ class CPLUSPLUS_EXPORT SpecifierAST: public AST
 {
 public:
     SpecifierAST *next;
+
+public:
+    virtual SpecifierAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT SimpleSpecifierAST: public SpecifierAST
@@ -202,6 +207,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual SimpleSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -220,6 +227,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual AttributeSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -238,6 +247,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual AttributeAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -252,6 +263,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypeofSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -260,28 +273,39 @@ class CPLUSPLUS_EXPORT StatementAST: public AST
 {
 public:
     StatementAST *next;
+
+public:
+    virtual StatementAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT ExpressionAST: public AST
 {
 public:
+    virtual ExpressionAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT DeclarationAST: public AST
 {
 public:
     DeclarationAST *next;
+
+public:
+    virtual DeclarationAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT CoreDeclaratorAST: public AST
 {
 public:
+    virtual CoreDeclaratorAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT PostfixDeclaratorAST: public AST
 {
 public:
     PostfixDeclaratorAST *next;
+
+public:
+    virtual PostfixDeclaratorAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT DeclaratorAST: public AST
@@ -297,6 +321,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DeclaratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -311,6 +337,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ExpressionListAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -326,6 +354,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual SimpleDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -339,6 +369,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual EmptyDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -354,6 +386,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual AccessDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -371,6 +405,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual AsmDefinitionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -387,6 +423,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual BaseSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -403,6 +441,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual QtMethodAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -418,6 +458,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual BinaryExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -434,6 +476,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CastExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -454,6 +498,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ClassSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -470,6 +516,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CaseStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -485,6 +533,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CompoundStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -499,6 +549,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ConditionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -516,6 +568,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ConditionalExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -535,6 +589,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CppCastExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -549,6 +605,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CtorInitializerAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -562,6 +620,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DeclarationStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -575,6 +635,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DeclaratorIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -590,6 +652,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NestedDeclaratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -607,6 +671,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual FunctionDeclaratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -622,6 +688,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ArrayDeclaratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -636,6 +704,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DeclaratorListAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -653,6 +723,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DeleteExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -672,6 +744,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DoStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -685,6 +759,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NamedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -699,6 +775,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ElaboratedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -716,6 +794,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual EnumSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -732,6 +812,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual EnumeratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -747,6 +829,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ExceptionDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -764,6 +848,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ExceptionSpecificationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -778,6 +864,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ExpressionOrDeclarationStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -792,6 +880,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ExpressionStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -808,6 +898,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual FunctionDefinitionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -828,6 +920,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ForStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -847,6 +941,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual IfStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -862,6 +958,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ArrayInitializerAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -877,6 +975,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual LabeledStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -892,6 +992,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual LinkageBodyAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -907,6 +1009,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual LinkageSpecificationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -924,6 +1028,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual MemInitializerAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -931,6 +1037,7 @@ protected:
 class CPLUSPLUS_EXPORT NameAST: public ExpressionAST
 {
 public:
+    virtual NameAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT NestedNameSpecifierAST: public AST
@@ -944,6 +1051,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NestedNameSpecifierAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -959,6 +1068,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual QualifiedNameAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -973,6 +1084,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual OperatorFunctionIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -988,6 +1101,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ConversionFunctionIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1001,6 +1116,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual SimpleNameAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1015,6 +1132,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual DestructorNameAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1031,6 +1150,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TemplateIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1047,6 +1168,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NamespaceAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1064,6 +1187,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NamespaceAliasDefinitionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1078,6 +1203,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NewDeclaratorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1096,6 +1223,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NewExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1111,6 +1240,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NewInitializerAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1126,6 +1257,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NewTypeIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1141,6 +1274,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual OperatorAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1157,6 +1292,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ParameterDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1171,6 +1308,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ParameterDeclarationClauseAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1179,6 +1318,9 @@ class CPLUSPLUS_EXPORT PostfixAST: public AST
 {
 public:
     PostfixAST *next;
+
+public:
+    virtual PostfixAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT CallAST: public PostfixAST
@@ -1192,6 +1334,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CallAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1207,6 +1351,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ArrayAccessAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1220,6 +1366,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual PostIncrDecrAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1235,6 +1383,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual MemberAccessAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1251,6 +1401,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypeidExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1268,6 +1420,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypenameCallExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1284,6 +1438,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypeConstructorCallAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1298,6 +1454,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual PostfixExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1306,6 +1464,9 @@ class CPLUSPLUS_EXPORT PtrOperatorAST: public AST
 {
 public:
     PtrOperatorAST *next;
+
+public:
+    virtual PtrOperatorAST *clone(MemoryPool *pool) const = 0;
 };
 
 class CPLUSPLUS_EXPORT PointerToMemberAST: public PtrOperatorAST
@@ -1320,6 +1481,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual PointerToMemberAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1334,6 +1497,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual PointerAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1347,6 +1512,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ReferenceAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1361,6 +1528,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual BreakStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1375,6 +1544,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ContinueStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1390,6 +1561,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual GotoStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1405,6 +1578,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ReturnStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1419,6 +1594,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual SizeofExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1432,6 +1609,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NumericLiteralAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1445,6 +1624,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual BoolLiteralAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1458,6 +1639,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ThisExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1473,6 +1656,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual NestedExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1487,6 +1672,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual StringLiteralAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1504,6 +1691,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual SwitchStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1518,6 +1707,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TemplateArgumentListAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1536,6 +1727,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TemplateDeclarationAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1550,6 +1743,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual ThrowExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1563,6 +1758,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TranslationUnitAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1578,6 +1775,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TryBlockStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1596,6 +1795,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual CatchClauseAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1610,6 +1811,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypeIdAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1626,6 +1829,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TypenameTypeParameterAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1646,6 +1851,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual TemplateTypeParameterAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1660,6 +1867,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual UnaryExpressionAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1676,6 +1885,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual UsingAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1692,6 +1903,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual UsingDirectiveAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
@@ -1709,6 +1922,8 @@ public:
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
+    virtual WhileStatementAST *clone(MemoryPool *pool) const;
+
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp
index 7664d5b6d40abf991049006e2a6fe770383ae3ea..72338576b6b25665a6154cf6bf4090ede03592d9 100644
--- a/shared/cplusplus/PrettyPrinter.cpp
+++ b/shared/cplusplus/PrettyPrinter.cpp
@@ -33,8 +33,10 @@
 
 #include "PrettyPrinter.h"
 #include "AST.h"
+#include "Token.h"
 #include <iostream>
 #include <string>
+#include <cassert>
 
 CPLUSPLUS_USE_NAMESPACE
 
@@ -144,12 +146,16 @@ bool PrettyPrinter::visit(AttributeAST *ast)
 bool PrettyPrinter::visit(BaseSpecifierAST *ast)
 {
     if (ast->token_virtual && ast->token_access_specifier) {
-        out << "virtual ";
+        out << "virtual";
+        out << ' ';
         out << spell(ast->token_access_specifier);
+        out << ' ';
     } else if (ast->token_virtual) {
         out << "virtual";
+        out << ' ';
     } else if (ast->token_access_specifier) {
         out << spell(ast->token_access_specifier);
+        out << ' ';
     }
     accept(ast->name);
     return false;
@@ -192,7 +198,24 @@ bool PrettyPrinter::visit(CaseStatementAST *ast)
     out << "case ";
     accept(ast->expression);
     out << ':';
-    accept(ast->statement);
+    if (! ast->statement) {
+        newline();
+        return false;
+    }
+
+    if (ast->statement->asCompoundStatement()) {
+        out << ' ';
+        accept(ast->statement);
+    } else if (ast->statement->asCaseStatement() || ast->statement->asLabeledStatement()) {
+        newline();
+        accept(ast->statement);
+    } else {
+        indent();
+        newline();
+        accept(ast->statement);
+        deindent();
+        newline();
+    }
     return false;
 }
 
@@ -233,6 +256,7 @@ bool PrettyPrinter::visit(ClassSpecifierAST *ast)
                 out << ", ";
         }
     }
+    newline();
     out << '{';
     if (ast->member_specifiers) {
         indent();
@@ -365,6 +389,7 @@ bool PrettyPrinter::visit(DeclaratorAST *ast)
             out << ' ';
     }
     if (ast->initializer) {
+        out << ' ';
         out << '=';
         out << ' ';
         accept(ast->initializer);
@@ -451,11 +476,20 @@ bool PrettyPrinter::visit(EnumSpecifierAST *ast)
         out << ' ';
         accept(ast->name);
     }
+    out << ' ';
     out << '{';
-    for (EnumeratorAST *it = ast->enumerators; it; it = it->next) {
-        accept(it);
-        if (it->next)
-            out << ", ";
+    if (ast->enumerators) {
+        indent();
+        newline();
+        for (EnumeratorAST *it = ast->enumerators; it; it = it->next) {
+            accept(it);
+            if (it->next) {
+                out << ", ";
+                newline();
+            }
+        }
+        deindent();
+        newline();
     }
     out << '}';
     return false;
@@ -550,9 +584,8 @@ bool PrettyPrinter::visit(FunctionDeclaratorAST *ast)
     accept(ast->parameters);
     out << ')';
     for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+        out << ' ';
         accept(it);
-        if (it->next)
-            out << ' ';
     }
     if (ast->exception_specification) {
         out << ' ';
@@ -597,9 +630,10 @@ bool PrettyPrinter::visit(IfStatementAST *ast)
     out << '(';
     accept(ast->condition);
     out << ')';
-    if (ast->statement->asCompoundStatement())
+    if (ast->statement->asCompoundStatement()) {
+        out << ' ';
         accept(ast->statement);
-    else {
+    } else {
         indent();
         newline();
         accept(ast->statement);
@@ -797,7 +831,17 @@ bool PrettyPrinter::visit(NewTypeIdAST *ast)
 
 bool PrettyPrinter::visit(NumericLiteralAST *ast)
 {
-    out << spell(ast->token);
+    switch (tokenKind(ast->token)) {
+    case T_CHAR_LITERAL:
+        out << '\'' << spell(ast->token) << '\'';
+        break;
+    case T_WIDE_CHAR_LITERAL:
+        out << "L\'" << spell(ast->token) << '\'';
+        break;
+
+    default:
+        out << spell(ast->token);
+    }
     return false;
 }
 
@@ -962,10 +1006,13 @@ bool PrettyPrinter::visit(SizeofExpressionAST *ast)
 
 bool PrettyPrinter::visit(StringLiteralAST *ast)
 {
-    out << '"' << spell(ast->token) << '"';
-    if (ast->next) {
-        out << ' ';
-        accept(ast->next);
+    for (StringLiteralAST *it = ast; it; it = it->next) {
+        if (tokenKind(ast->token) == T_STRING_LITERAL)
+            out << '"' << spell(ast->token) << '"';
+        else
+            out << "L\"" << spell(ast->token) << '"';
+        if (it->next)
+            out << ' ';
     }
     return false;
 }
@@ -1213,7 +1260,16 @@ bool PrettyPrinter::visit(WhileStatementAST *ast)
     out << '(';
     accept(ast->condition);
     out << ')';
-    accept(ast->statement);
+    out << ' ';
+    if (ast->statement && ast->statement->asCompoundStatement())
+        accept(ast->statement);
+    else {
+        indent();
+        newline();
+        accept(ast->statement);
+        deindent();
+        newline();
+    }
     return false;
 }
 
diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp
index d5a88895cb65e5d2df5521cd1491eac935194a9c..7f029f00185bf252b2ea2e767eaa558df70f0b3d 100644
--- a/shared/proparser/profileevaluator.cpp
+++ b/shared/proparser/profileevaluator.cpp
@@ -770,6 +770,11 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value)
                     removeEach(&m_valuemap, varName, v);
                     removeEach(&m_filevaluemap[currentProFile()], varName, v);
                 }
+            } else if (!m_skipLevel) {
+                // this is a hack for the moment to fix the
+                // CONFIG -= app_bundle problem on Mac (add it to a variable -CONFIG as was done before)
+                insertUnique(&m_valuemap, QString("-%1").arg(varName), v);
+                insertUnique(&m_filevaluemap[currentProFile()], QString("-%1").arg(varName), v);
             } else {
                 // We are stingy with our values, too.
             }
diff --git a/src/app/app.pro b/src/app/app.pro
index a0e120da1c6666a27237d3abc03f30dbe450ecde..bc8376bbddbe6af634f9be962ef14031cd9eb6c3 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -36,13 +36,11 @@ macx {
         SCHEMES.files = $$IDE_SOURCE_TREE/bin/schemes
         GDBDEBUGGER.path = Contents/Resources
         GDBDEBUGGER.files = $$IDE_SOURCE_TREE/bin/gdbmacros
-        DOC.path = Contents/Resources/doc
-        DOC.files = $$IDE_SOURCE_TREE/doc/qtcreator.qch
         LICENSE.path = Contents/Resources
         LICENSE.files = $$IDE_SOURCE_TREE/bin/license.txt
         RUNINTERMINAL.path = Contents/Resources
         RUNINTERMINAL.files = $$IDE_SOURCE_TREE/bin/runInTerminal.command
-        QMAKE_BUNDLE_DATA += SNIPPETS TEMPLATES DESIGNER SCHEMES GDBDEBUGGER DOC LICENSE RUNINTERMINAL
+        QMAKE_BUNDLE_DATA += SNIPPETS TEMPLATES DESIGNER SCHEMES GDBDEBUGGER LICENSE RUNINTERMINAL
         QMAKE_INFO_PLIST = $$PWD/Info.plist
 }
 !macx {
diff --git a/src/libs/aggregation/aggregate.cpp b/src/libs/aggregation/aggregate.cpp
index 6fd7414dfc2d048f2c6a1a9e4017a8acb60893a1..1dd6ce03392427bbf8a7dce9dc5f9e5937c5bbc6 100644
--- a/src/libs/aggregation/aggregate.cpp
+++ b/src/libs/aggregation/aggregate.cpp
@@ -37,12 +37,12 @@
 
 /*!
     \namespace Aggregation
-    \brief Contains support for bundling related components, such that
-           each component exposes the properties and behavior of the
+    \brief The Aggregation namespace contains support for bundling related components,
+           such that each component exposes the properties and behavior of the
            other components to the outside.
 
     Components that are bundled to an Aggregate can be "cast" to each other
-    and have a coupled life cycle. See the documentation of Aggregate for
+    and have a coupled life cycle. See the documentation of Aggregation::Aggregate for
     details and examples.
 */
 
diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp
index 1b75839fa890387ed9ecef7cc99dc1a9372dd82a..0ce65bf5c0ae9f118b54611145e7af64185b181e 100644
--- a/src/libs/extensionsystem/iplugin.cpp
+++ b/src/libs/extensionsystem/iplugin.cpp
@@ -38,6 +38,7 @@
 
 /*!
     \class ExtensionSystem::IPlugin
+    \mainclass
     \brief Base class for all plugins.
 
     The IPlugin class is an abstract class that must be implemented
@@ -304,7 +305,7 @@ void IPlugin::addObject(QObject *obj)
     plugin pool. Usually, registered objects must be removed from
     the object pool and deleted by hand.
     Objects added to the pool via addAutoReleasedObject are automatically
-    removed and deleted in \i reverse order of registration when
+    removed and deleted in reverse order of registration when
     the IPlugin instance is destroyed.
     \sa PluginManager::addObject()
 */
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 0603cd87cab52dca1163efeef2fb7a6586bdcc54..7dc9c4e10af716cad64356b88212697bf3a2f9fb 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -54,7 +54,8 @@ enum { debugLeaks = 0 };
 
 /*!
     \namespace ExtensionSystem
-    \brief Classes that belong to the core plugin system.
+    \brief The ExtensionSystem namespace provides
+    classes that belong to the core plugin system.
 
     The basic extension system contains of the plugin manager and its supporting classes,
     and the IPlugin interface that must be implemented by plugin providers.
@@ -444,11 +445,19 @@ void PluginManager::startTests()
 #endif
 }
 
+/*!
+ * \fn bool PluginManager::runningTests() const
+ * \internal
+ */
 bool PluginManager::runningTests() const
 {
     return !d->testSpecs.isEmpty();
 }
 
+/*!
+ * \fn QString PluginManager::testDataDirectory() const
+ * \internal
+ */
 QString PluginManager::testDataDirectory() const
 {
     QString s = QString::fromLocal8Bit(qgetenv("IDETESTDIR"));
diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp
index 99e83d9fc6407ad19bd5aae93859c53493d2a01b..0e5fa53996ff187b23c443d4dc04e89e56f11333 100644
--- a/src/libs/extensionsystem/pluginspec.cpp
+++ b/src/libs/extensionsystem/pluginspec.cpp
@@ -221,7 +221,7 @@ QList<PluginDependency> PluginSpec::dependencies() const
 }
 
 /*!
-    \fn PluginOptionDescriptions optionDescriptions() const
+    \fn PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const
     Returns a list of descriptions of command line arguments the plugin processes.
 */
 
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index 857dd5be370f5908167db3e9743736b665cdb52c..301cfb6d39af0c7761faea1afe8bf2f455eaaf64 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -52,7 +52,7 @@ namespace Constants {
 
 const char * const IDE_VERSION_LONG      = IDE_VERSION;
 const char * const IDE_AUTHOR            = "Nokia Corporation";
-const char * const IDE_YEAR              = "2008";
+const char * const IDE_YEAR              = "2009";
 
 #ifdef IDE_REVISION
 const char * const IDE_REVISION_STR      = STRINGIFY(IDE_REVISION);
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 729ac7cd845b96ed9c1d2f8082e30ab9e4f34d93..eec20a4a05d3bdcace5797d5982e8a5a3752135d 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -65,6 +65,7 @@ enum MakeWritableResult {
 };
 
 struct EditorManagerPrivate;
+
 namespace Internal {
 class OpenEditorsWindow;
 class EditorSplitter;
@@ -224,7 +225,8 @@ private:
 
 namespace Internal {
 
-class EditorClosingCoreListener : public ICoreListener {
+class EditorClosingCoreListener : public ICoreListener
+{
     Q_OBJECT
 
 public:
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 2a9fff0f4e38a8ef15e65314802fbaf21f5dcfc1..f68c5da7d06772f8684ddcb53f8244774e098153 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -625,6 +625,7 @@ void MainWindow::registerDefaultActions()
     // Toggle Sidebar Action
     m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR),
                                         tr("Toggle Sidebar"), this);
+    m_toggleSideBarAction->setCheckable(true);
     cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, m_globalContext);
 #ifdef Q_OS_MAC
     cmd->setDefaultKeySequence(QKeySequence("Ctrl+0"));
diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index 9bbb4323d21bbb12e18a50f013a474fa2e4bc648..412559a9b0aecd1c2c22d19554776d8de37fe439 100644
--- a/src/plugins/coreplugin/navigationwidget.cpp
+++ b/src/plugins/coreplugin/navigationwidget.cpp
@@ -166,6 +166,7 @@ int NavigationWidget::storedWidth()
 void NavigationWidget::placeHolderChanged(NavigationWidgetPlaceHolder *holder)
 {
     m_toggleSideBarAction->setEnabled(holder);
+    m_toggleSideBarAction->setChecked(holder && isShown());
 }
 
 void NavigationWidget::resizeEvent(QResizeEvent *re)
@@ -281,8 +282,12 @@ void NavigationWidget::setShown(bool b)
     if (m_shown == b)
         return;
     m_shown = b;
-    if (NavigationWidgetPlaceHolder::m_current)
+    if (NavigationWidgetPlaceHolder::m_current) {
         NavigationWidgetPlaceHolder::m_current->setVisible(m_shown && !m_suppressed);
+        m_toggleSideBarAction->setChecked(m_shown);
+    } else {
+        m_toggleSideBarAction->setChecked(false);
+    }
 }
 
 bool NavigationWidget::isShown() const
diff --git a/src/plugins/coreplugin/outputpane.cpp b/src/plugins/coreplugin/outputpane.cpp
index b9cd825e244b1152f4b13b9e19effbde417683ab..6d97c5d3611fd3f64574fb8aab68cae0866e5c86 100644
--- a/src/plugins/coreplugin/outputpane.cpp
+++ b/src/plugins/coreplugin/outputpane.cpp
@@ -488,13 +488,13 @@ OutputPaneToggleButton::OutputPaneToggleButton(int number, const QString &text,
     setFocusPolicy(Qt::NoFocus);
     setCheckable(true);
     setStyleSheet(
-            "QPushButton { border-image: url(:/qworkbench/images/panel_button.png) 2 2 2 19 repeat;"
+            "QPushButton { border-image: url(:/qworkbench/images/panel_button.png) 2 2 2 19;"
                          " border-width: 2px 2px 2px 19px; padding-left: -17; padding-right: 4 } "
-            "QPushButton:checked { border-image: url(:/qworkbench/images/panel_button_checked.png) 2 2 2 19 repeat } "
+            "QPushButton:checked { border-image: url(:/qworkbench/images/panel_button_checked.png) 2 2 2 19 } "
 #ifndef Q_WS_MAC // Mac UI's dont usually do hover
-            "QPushButton:checked:hover { border-image: url(:/qworkbench/images/panel_button_checked_hover.png) 2 2 2 19 repeat } "
-            "QPushButton:pressed:hover { border-image: url(:/qworkbench/images/panel_button_pressed.png) 2 2 2 19 repeat } "
-            "QPushButton:hover { border-image: url(:/qworkbench/images/panel_button_hover.png) 2 2 2 19 repeat } "
+            "QPushButton:checked:hover { border-image: url(:/qworkbench/images/panel_button_checked_hover.png) 2 2 2 19 } "
+            "QPushButton:pressed:hover { border-image: url(:/qworkbench/images/panel_button_pressed.png) 2 2 2 19 } "
+            "QPushButton:hover { border-image: url(:/qworkbench/images/panel_button_hover.png) 2 2 2 19 } "
 #endif
             );
 }
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index ba97e5a212a624c5d2b5ef2ea64c2234aaa03ce9..6ebf51b2a2c0ad8f989e836181dd9c934a2d1654 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -72,10 +72,16 @@ CppHoverHandler::CppHoverHandler(QObject *parent)
     m_modelManager = m_core->pluginManager()->getObject<CppTools::CppModelManagerInterface>();
 
     QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->settings()->fileName());
-    m_helpEngine = new QHelpEngineCore(fi.absolutePath()
+    // FIXME shouldn't the help engine create the directory if it doesn't exist?
+    QDir directory(fi.absolutePath()+"/qtcreator");
+    if (!directory.exists())
+        directory.mkpath(directory.absolutePath());
+
+    m_helpEngine = new QHelpEngineCore(directory.absolutePath()
                                        + QLatin1String("/helpcollection.qhc"), this);
     //m_helpEngine->setAutoSaveFilter(false);
-    m_helpEngine->setupData();
+    if (!m_helpEngine->setupData())
+        qWarning() << "Could not initialize help engine:" << m_helpEngine->error();
     m_helpEngine->setCurrentFilter(tr("Unfiltered"));
     m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0;
 
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index 4195fbee339679d72609e8c9ecae230c8fcccb94..866a3d05c9460e2ced1d283ba86ea0707f470edf 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -163,7 +163,8 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name,
     if (debug)
         qDebug() << Q_FUNC_INFO << dir << name;
 
-    if (project) {
+    QFileInfo fileInSameDir(dir, name);
+    if (project && !fileInSameDir.isFile()) {
         QString pattern = QString(1, QLatin1Char('/'));
         pattern += name;
         const QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles);
@@ -173,7 +174,7 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name,
                 return QFileInfo(*it);
         return QFileInfo();
     }
-    return QFileInfo(dir, name);
+    return fileInSameDir;
 }
 
 // Figure out file type
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 7308fb441c2da8c38ec4cd3d69599896bd44843e..b47e7d5ee02613d1c99f6bdace60c88d68a4ca7a 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -76,7 +76,6 @@ FORMS += attachexternaldialog.ui \
     attachremotedialog.ui \
     breakbyfunction.ui \
     breakcondition.ui \
-    mode.ui \
     gdboptionpage.ui \
     startexternaldialog.ui \
 
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 7c7d3b6d3281caebd4340aced5885b32ac69a8e7..fa6f9ab32508631d983ec65eff7a216d7c94c5ae 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -2944,8 +2944,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
 
     QString outertype = isTemplate ? tmplate : data.type;
     // adjust the data extract
-    if (outertype == "QWidget")
-        outertype = "QObject";
+    if (outertype == m_namespace + "QWidget")
+        outertype = m_namespace + "QObject";
 
     QString extraArgs[4];
     extraArgs[0] = "0";
@@ -2977,10 +2977,17 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
         if (lastOpened != -1 && lastClosed != -1)
             slotNumber = data.iname.mid(lastOpened + 1, lastClosed - lastOpened - 1);
         extraArgs[0] = slotNumber;
-    } else if (outertype == m_namespace + "QMap") {
-        QString nodetype = m_namespace + "QMapNode";
-        nodetype += data.type.mid(m_namespace.size() + 4);
-        //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype;
+    } else if (outertype == m_namespace + "QMap" || outertype == m_namespace + "QMultiMap") {
+        QString nodetype;
+        if (m_qtVersion >= (4 << 16) + (5 << 8) + 0) {
+            nodetype  = m_namespace + "QMapNode";
+            nodetype += data.type.mid(outertype.size());
+        } else {
+            // FIXME: doesn't work for QMultiMap
+            nodetype  = data.type + "::Node"; 
+        }
+        //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
+        //    << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
         extraArgs[2] = sizeofTypeExpression(nodetype);
         extraArgs[3] = "(size_t)&(('" + nodetype + "'*)0)->value";
     } else if (outertype == m_namespace + "QMapNode") {
@@ -3311,6 +3318,16 @@ void GdbEngine::handleQueryDataDumper2(const GdbResultRecord &record)
     GdbMi contents(output.data());
     GdbMi simple = contents.findChild("dumpers");
     m_namespace = contents.findChild("namespace").data();
+    GdbMi qtversion = contents.findChild("qtversion");
+    if (qtversion.children().size() == 3) {
+        m_qtVersion = (qtversion.childAt(0).data().toInt() << 16)
+                    + (qtversion.childAt(1).data().toInt() << 8)
+                    + qtversion.childAt(2).data().toInt();
+        //qDebug() << "FOUND QT VERSION: " << qtversion.toString() << m_qtVersion;
+    } else {
+        m_qtVersion = 0;
+    }
+    
     //qDebug() << "OUTPUT: " << output.toString();
     //qDebug() << "CONTENTS: " << contents.toString();
     //qDebug() << "SIMPLE DUMPERS: " << simple.toString();
@@ -3536,8 +3553,9 @@ void GdbEngine::handleDumpCustomValue2(const GdbResultRecord &record,
                 //    << item.findChild("nameencoded").data()[1];
                 if (item.findChild("nameencoded").data()[0] == '1')
                     data1.name = QByteArray::fromBase64(data1.name.toUtf8());
-                if (item.findChild("nameisindex").data()[0] == '1')
-                    data1.name = '[' + data1.name + ']';
+                QString key = item.findChild("key").data();
+                if (!key.isEmpty())
+                    data1.name += " (" + key + ")";
                 setWatchDataType(data1, item.findChild("type"));
                 setWatchDataExpression(data1, item.findChild("exp"));
                 setWatchDataChildCount(data1, item.findChild("numchild"));
@@ -3951,6 +3969,9 @@ void GdbEngine::tryLoadCustomDumpers()
         sendCommand("sharedlibrary " + dotEscape(lib));
         if (qq->useFastStart())
             sendCommand("set stop-on-solib-events 1");
+    } else {
+        qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+            << lib << QFileInfo(lib).isExecutable();
     }
 #endif
 #if defined(Q_OS_MAC)
@@ -3964,6 +3985,9 @@ void GdbEngine::tryLoadCustomDumpers()
         sendCommand("sharedlibrary " + dotEscape(lib));
         if (qq->useFastStart())
             sendCommand("set stop-on-solib-events 1");
+    } else {
+        qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+            << lib << QFileInfo(lib).isExecutable();
     }
 #endif
 #if defined(Q_OS_WIN)
@@ -3977,6 +4001,9 @@ void GdbEngine::tryLoadCustomDumpers()
         sendCommand("sharedlibrary " + dotEscape(lib));
         if (qq->useFastStart())
             sendCommand("set stop-on-solib-events 1");
+    } else {
+        qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: "
+            << lib << QFileInfo(lib).isExecutable();
     }
 #endif
 
diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h
index c1344f86dda3c76682d2d65458f48c5f53c1e2fd..000c0b84a952d88313066a76e56578c842fd147d 100644
--- a/src/plugins/debugger/gdbengine.h
+++ b/src/plugins/debugger/gdbengine.h
@@ -333,6 +333,7 @@ private:
 
     QStringList m_availableSimpleDumpers;
     QString m_namespace; // namespace used in "namespaced Qt";
+    int m_qtVersion; // Qt version used in the debugged program
     
     DataDumperState m_dataDumperState; // state of qt creator dumpers
     QList<GdbMi> m_currentFunctionArgs;
diff --git a/src/plugins/debugger/mode.ui b/src/plugins/debugger/mode.ui
deleted file mode 100644
index da44cf38b4a7a6916c56471fb99646a5b055a035..0000000000000000000000000000000000000000
--- a/src/plugins/debugger/mode.ui
+++ /dev/null
@@ -1,76 +0,0 @@
-<ui version="4.0" >
- <class>DebugMode</class>
- <widget class="QWidget" name="DebugMode" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>558</width>
-    <height>353</height>
-   </rect>
-  </property>
-  <property name="windowTitle" >
-   <string>Form</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_3" >
-   <property name="spacing" >
-    <number>0</number>
-   </property>
-   <property name="margin" >
-    <number>0</number>
-   </property>
-   <item>
-    <widget class="QSplitter" name="vSplitter" >
-     <property name="orientation" >
-      <enum>Qt::Vertical</enum>
-     </property>
-     <widget class="QWidget" native="1" name="editorHolder" >
-      <property name="sizePolicy" >
-       <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
-        <horstretch>10</horstretch>
-        <verstretch>10</verstretch>
-       </sizepolicy>
-      </property>
-     </widget>
-     <widget class="QWidget" name="layoutWidget" >
-      <layout class="QVBoxLayout" name="verticalLayout" >
-       <property name="spacing" >
-        <number>0</number>
-       </property>
-       <item>
-        <layout class="QVBoxLayout" name="toolbarLayout" >
-         <property name="spacing" >
-          <number>0</number>
-         </property>
-        </layout>
-       </item>
-       <item>
-        <widget class="QSplitter" name="hSplitter" >
-         <property name="orientation" >
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <widget class="QTabWidget" name="bottomTabWidget" >
-          <property name="sizePolicy" >
-           <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="tabPosition" >
-           <enum>QTabWidget::South</enum>
-          </property>
-          <property name="tabShape" >
-           <enum>QTabWidget::Rounded</enum>
-          </property>
-         </widget>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 20b3b082a585d6d28329cb4995638f9cc95614da..97e1cfffea07c2be91a03249a0159dbc7a64a816 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -75,6 +75,7 @@ namespace FakeVim {
 namespace Constants {
 
 const char * const INSTALL_HANDLER        = "FakeVim.InstallHandler";
+const char * const MINI_BUFFER            = "FakeVim.MiniBuffer";
 const char * const INSTALL_KEY            = "Alt+V,Alt+V";
 
 } // namespace Constants
@@ -89,7 +90,7 @@ const char * const INSTALL_KEY            = "Alt+V,Alt+V";
 
 FakeVimPlugin::FakeVimPlugin()
 {
-    m_pm = 0;
+    m_core = 0;
     m_handler = 0;
 }
 
@@ -109,12 +110,10 @@ bool FakeVimPlugin::initialize(const QStringList &arguments, QString *error_mess
 
     m_handler = new FakeVimHandler;
 
-    m_pm = ExtensionSystem::PluginManager::instance();
+    m_core = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>();
+    QTC_ASSERT(m_core, return false);
 
-    ICore *core = m_pm->getObject<Core::ICore>();
-    QTC_ASSERT(core, return false);
-
-    Core::ActionManagerInterface *actionManager = core->actionManager();
+    Core::ActionManagerInterface *actionManager = m_core->actionManager();
     QTC_ASSERT(actionManager, return false);
 
     QList<int> globalcontext;
@@ -143,44 +142,33 @@ void FakeVimPlugin::extensionsInitialized()
 
 void FakeVimPlugin::installHandler()
 {
-    ICore *core = m_pm->getObject<Core::ICore>();
-    if (!core || !core->editorManager())
+    if (!m_core || !m_core->editorManager())
         return;
-    Core::IEditor *editor = core->editorManager()->currentEditor();
+    Core::IEditor *editor = m_core->editorManager()->currentEditor();
     ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
     if (!textEditor)
         return;
 
-    QWidget *widget = textEditor->widget();
-    QPlainTextEdit *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget);
-    if (!plainTextEdit)
-        return;
-    plainTextEdit->removeEventFilter(m_handler);
-    plainTextEdit->installEventFilter(m_handler);
-    QFont font = plainTextEdit->font();
-    //font.setFamily("Monospace");
-    m_savedCursorWidth = plainTextEdit->cursorWidth();
-    plainTextEdit->setCursorWidth(QFontMetrics(font).width(QChar('x')));
-
-    //QMainWindow mw;
     connect(m_handler, SIGNAL(commandBufferChanged(QString)),
         this, SLOT(showCommandBuffer(QString)));
     connect(m_handler, SIGNAL(quitRequested(QWidget *)),
         this, SLOT(removeHandler(QWidget *)));
+
+    m_handler->addWidget(textEditor->widget());
 }
 
 void FakeVimPlugin::removeHandler(QWidget *widget)
 {
-    widget->removeEventFilter(m_handler);
-    QPlainTextEdit *plainTextEdit = qobject_cast<QPlainTextEdit *>(widget);
-    if (!plainTextEdit)
-        return;
-    plainTextEdit->setCursorWidth(m_savedCursorWidth);
+    m_handler->removeWidget(widget);
+    Core::EditorManager::instance()->hideEditorInfoBar(
+        QLatin1String(Constants::MINI_BUFFER));
 }
 
 void FakeVimPlugin::showCommandBuffer(const QString &contents)
 {
-    //qDebug() << "CMD: " << contents;
+    Core::EditorManager::instance()->showEditorInfoBar( 
+        QLatin1String(Constants::MINI_BUFFER), contents,
+        tr("Quit FakeVim"), m_handler, SLOT(quit()));
 }
 
 
diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h
index 6561e871b00dadf8a0da678ad6ab0717007123d9..9025affcec33c6a36a7f8a54c8f44e9002a89d59 100644
--- a/src/plugins/fakevim/fakevimplugin.h
+++ b/src/plugins/fakevim/fakevimplugin.h
@@ -44,8 +44,21 @@ class QCursor;
 class QAbstractItemView;
 QT_END_NAMESPACE
 
-namespace Core { class IEditor; }
-namespace TextEditor { class ITextEditor; }
+
+namespace Core {
+
+class ICore;
+class IEditor;
+
+} // namespace Core
+
+
+namespace TextEditor {
+
+class ITextEditor;
+
+} // namespace TextEditor
+
 
 namespace FakeVim {
 namespace Internal {
@@ -72,9 +85,8 @@ private slots:
 
 private:
     FakeVimHandler *m_handler;
-    ExtensionSystem::PluginManager *m_pm;
     QAction *m_installHandlerAction;
-    int m_savedCursorWidth;
+    Core::ICore *m_core;
 };
 
 } // namespace Internal
diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp
index fd8734f21146bcc8f58f80d30ce21173fd3cbb54..2fba75104263951bf745864d2631d224195d9321 100644
--- a/src/plugins/fakevim/handler.cpp
+++ b/src/plugins/fakevim/handler.cpp
@@ -46,19 +46,21 @@
 #include <QtGui/QScrollBar>
 #include <QtGui/QTextBlock>
 #include <QtGui/QTextCursor>
+#include <QtGui/QTextDocumentFragment>
 #include <QtGui/QTextEdit>
 
 
 using namespace FakeVim::Internal;
 
-#define StartOfLine QTextCursor::StartOfLine
-#define EndOfLine   QTextCursor::EndOfLine
-#define MoveAnchor  QTextCursor::MoveAnchor
-#define KeepAnchor  QTextCursor::KeepAnchor
-#define Up          QTextCursor::Up
-#define Down        QTextCursor::Down
-#define Right       QTextCursor::Right
-#define Left        QTextCursor::Left
+#define StartOfLine    QTextCursor::StartOfLine
+#define EndOfLine      QTextCursor::EndOfLine
+#define MoveAnchor     QTextCursor::MoveAnchor
+#define KeepAnchor     QTextCursor::KeepAnchor
+#define Up             QTextCursor::Up
+#define Down           QTextCursor::Down
+#define Right          QTextCursor::Right
+#define Left           QTextCursor::Left
+#define EndOfDocument  QTextCursor::End
 
 
 ///////////////////////////////////////////////////////////////////////
@@ -68,7 +70,6 @@ using namespace FakeVim::Internal;
 ///////////////////////////////////////////////////////////////////////
 
 #define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s)
-#define THE_EDITOR (m_textedit ? (QWidget*)m_textedit : (QWidget*)m_plaintextedit)
 
 const int ParagraphSeparator = 0x00002029;
 
@@ -78,7 +79,9 @@ enum Mode
 {
     InsertMode,
     CommandMode,
-    ExMode
+    ExMode,
+    SearchForwardMode,
+    SearchBackwardMode,
 };
 
 enum SubMode
@@ -87,7 +90,7 @@ enum SubMode
     RegisterSubMode,
     ChangeSubMode,
     DeleteSubMode,
-    ZSubMode
+    ZSubMode,
 };
 
 enum SubSubMode
@@ -99,16 +102,46 @@ enum SubSubMode
     TickSubSubMode      // used for '
 };
 
+enum VisualMode
+{
+    NoVisualMode,
+    VisualCharMode,
+    VisualLineMode,
+    VisualBlockMode,
+};
+
 static const QString ConfigStartOfLine = "startofline";
 static const QString ConfigOn = "on";
 
+struct EditOperation
+{
+    EditOperation() : m_position(-1), m_itemCount(0) {}
+    int m_position;
+    int m_itemCount; // used to combine several operations
+    QString m_from;
+    QString m_to;
+};
+
+QDebug &operator<<(QDebug &ts, const EditOperation &op)
+{
+    if (op.m_itemCount > 0) {
+        ts << "EDIT BLOCK WITH" << op.m_itemCount << "ITEMS";
+    } else {
+        ts << "EDIT AT " << op.m_position
+           << " FROM " << op.m_from << " TO " << op.m_to;
+    }
+    return ts;
+}
+
 class FakeVimHandler::Private
 {
 public:
     Private(FakeVimHandler *parent);
 
     bool eventFilter(QObject *ob, QEvent *ev);
+    void handleExCommand(const QString &cmd);
 
+private:
     static int shift(int key) { return key + 32; }
     static int control(int key) { return key + 256; }
 
@@ -117,11 +150,9 @@ public:
     void handleInsertMode(int key, const QString &text);
     void handleCommandMode(int key, const QString &text);
     void handleRegisterMode(int key, const QString &text);
-    void handleExMode(int key, const QString &text);
-    void finishMovement();
-    void updateMiniBuffer();
+    void handleMiniBufferModes(int key, const QString &text);
+    void finishMovement(const QString &text = QString());
     void search(const QString &needle, bool forward);
-    void showMessage(const QString &msg);
 
     int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); }
     int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); }
@@ -131,47 +162,57 @@ public:
     bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; }
 
     int lastPositionInDocument() const;
-
-	// all zero-based counting
-	int cursorLineOnScreen() const;
-	int linesOnScreen() const;
-	int columnsOnScreen() const;
-	int cursorLineInDocument() const;
-	int cursorColumnInDocument() const;
+    int positionForLine(int line) const; // 1 based line, 0 based pos
+    int lineForPosition(int pos) const;  // 1 based line, 0 based pos
+
+    // all zero-based counting
+    int cursorLineOnScreen() const;
+    int linesOnScreen() const;
+    int columnsOnScreen() const;
+    int cursorLineInDocument() const;
+    int cursorColumnInDocument() const;
     int linesInDocument() const;
-	void scrollToLineInDocument(int line);
+    void scrollToLineInDocument(int line);
 
     void moveToFirstNonBlankOnLine();
     void moveToNextWord(bool simple);
     void moveToWordBoundary(bool simple, bool forward);
     void handleFfTt(int key);
-    void handleCommand(const QString &cmd);
 
     // helper function for handleCommand. return 1 based line index.
     int readLineCode(QString &cmd);
+    QTextCursor selectRange(int beginLine, int endLine);
 
+public:
+    void enterInsertMode();
+    void enterCommandMode();
+    void showMessage(const QString &msg);
+    void updateMiniBuffer();
+    void updateSelection();
+    void quit();
+
+public:
+    QTextEdit *m_textedit;
+    QPlainTextEdit *m_plaintextedit;
+
+private:
     FakeVimHandler *q;
     Mode m_mode;
     SubMode m_submode;
     SubSubMode m_subsubmode;
     int m_subsubdata;
     QString m_input;
-    QTextEdit *m_textedit;
-    QPlainTextEdit *m_plaintextedit;
     QTextCursor m_tc;
     QHash<int, QString> m_registers;
     int m_register;
     QString m_mvcount;
     QString m_opcount;
 
-    QStack<QString> m_undoStack;
-    QStack<QString> m_redoStack;
-
     bool m_fakeEnd;
 
-    bool isSearchCommand() const
-        { return m_commandCode == '?' || m_commandCode == '/'; }
-    int m_commandCode; // ?, /, : ...
+    QWidget *editor() const;
+    bool isSearchMode() const
+        { return m_mode == SearchForwardMode || m_mode == SearchBackwardMode; }
     int m_gflag;  // whether current command started with 'g'
     
     QString m_commandBuffer;
@@ -181,15 +222,33 @@ public:
     bool m_lastSearchForward;
     QString m_lastInsertion;
 
-    // History for '/'
+    // undo handling
+    void recordInsert(int position, const QString &data);
+    void recordRemove(int position, const QString &data);
+    void recordRemove(int position, int length);
+    void undo();
+    void redo();
+    QStack<EditOperation> m_undoStack;
+    QStack<EditOperation> m_redoStack;
+
+    // extra data for '.'
+    QString m_dotCount;
+    QString m_dotCommand;
+
+    // history for '/'
     QString lastSearchString() const;
     QStringList m_searchHistory;
     int m_searchHistoryIndex;
 
-    // History for ':'
+    // history for ':'
     QStringList m_commandHistory;
     int m_commandHistoryIndex;
 
+    // visual line mode
+    void enterVisualMode(VisualMode visualMode);
+    void leaveVisualMode();
+    VisualMode m_visualMode;
+
     // marks as lines
     QHash<int, int> m_marks;
 
@@ -204,13 +263,13 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent)
     m_mode = CommandMode;
     m_submode = NoSubMode;
     m_subsubmode = NoSubSubMode;
-    m_commandCode = 0;
     m_fakeEnd = false;
     m_lastSearchForward = true;
     m_register = '"';
     m_gflag = false;
     m_textedit = 0;
     m_plaintextedit = 0;
+    m_visualMode = NoVisualMode;
 
     m_config[ConfigStartOfLine] = ConfigOn;
 }
@@ -254,22 +313,30 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev)
 
 void FakeVimHandler::Private::handleKey(int key, const QString &text)
 {
+    //qDebug() << "KEY: " << key << text << "POS: " << m_tc.position();
+    //qDebug() << "\nUNDO: " << m_undoStack << "\nREDO: " << m_redoStack;
     if (m_mode == InsertMode)
         handleInsertMode(key, text);
     else if (m_mode == CommandMode)
         handleCommandMode(key, text);
-    else if (m_mode == ExMode)
-        handleExMode(key, text);
+    else if (m_mode == ExMode || m_mode == SearchForwardMode
+            || m_mode == SearchBackwardMode)
+        handleMiniBufferModes(key, text);
 }
 
-void FakeVimHandler::Private::finishMovement()
+void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
 {
     if (m_submode == ChangeSubMode) {
+        if (!dotCommand.isEmpty())
+            m_dotCommand = "c" + dotCommand;
         m_registers[m_register] = m_tc.selectedText();
         m_tc.removeSelectedText();
         m_mode = InsertMode;
         m_submode = NoSubMode;
     } else if (m_submode == DeleteSubMode) {
+        if (!dotCommand.isEmpty())
+            m_dotCommand = "d" + dotCommand;
+        recordRemove(qMin(m_tc.position(), m_tc.anchor()), m_tc.selectedText());
         m_registers[m_register] = m_tc.selectedText();
         m_tc.removeSelectedText();
         m_submode = NoSubMode;
@@ -281,18 +348,81 @@ void FakeVimHandler::Private::finishMovement()
     m_gflag = false;
     m_register = '"';
     m_tc.clearSelection();
+
+    updateSelection();
     updateMiniBuffer();
 }
 
+void FakeVimHandler::Private::updateSelection()
+{
+    QList<QTextEdit::ExtraSelection> selections;
+    if (m_visualMode != NoVisualMode) {
+        QTextEdit::ExtraSelection sel;
+        sel.cursor = m_tc;
+        sel.format = m_tc.blockCharFormat();
+        sel.format.setFontWeight(QFont::Bold);
+        sel.format.setFontUnderline(true);
+        int cursorPos = m_tc.position();
+        int anchorPos = m_marks['<'];
+        //qDebug() << "POS: " << cursorPos << " ANCHOR: " << anchorPos;
+        if (m_visualMode == VisualCharMode) {
+            sel.cursor.setPosition(anchorPos, KeepAnchor);
+            selections.append(sel);
+        } else if (m_visualMode == VisualLineMode) {
+            sel.cursor.setPosition(qMin(cursorPos, anchorPos), MoveAnchor);
+            sel.cursor.movePosition(StartOfLine, MoveAnchor);
+            sel.cursor.setPosition(qMax(cursorPos, anchorPos), KeepAnchor);
+            sel.cursor.movePosition(EndOfLine, KeepAnchor);
+            selections.append(sel);
+        } else if (m_visualMode == VisualBlockMode) {
+            QTextCursor tc = m_tc;
+            tc.setPosition(anchorPos);
+            tc.movePosition(StartOfLine, MoveAnchor);
+            QTextBlock anchorBlock = tc.block();
+            QTextBlock cursorBlock = m_tc.block();
+            int anchorColumn = anchorPos - anchorBlock.position();
+            int cursorColumn = cursorPos - cursorBlock.position();
+            int startColumn = qMin(anchorColumn, cursorColumn);
+            int endColumn = qMax(anchorColumn, cursorColumn);
+            int endPos = cursorBlock.position();
+            while (tc.position() <= endPos) {
+                if (startColumn < tc.block().length() - 1) {
+                    int last = qMin(tc.block().length() - 1, endColumn);
+                    int len = last - startColumn + 1;
+                    sel.cursor = tc;
+                    sel.cursor.movePosition(Right, MoveAnchor, startColumn);
+                    sel.cursor.movePosition(Right, KeepAnchor, len);
+                    selections.append(sel);
+                }
+                tc.movePosition(Down, MoveAnchor, 1);
+            }
+        }
+    }
+    EDITOR(setExtraSelections(selections));
+}
+
 void FakeVimHandler::Private::updateMiniBuffer()
 {
-    if (m_tc.isNull())
-        return;
     QString msg;
-    if (m_currentMessage.isEmpty()) {
-        msg = QChar(m_commandCode ? m_commandCode : ' ');
-        for (int i = 0; i != m_commandBuffer.size(); ++i) {
-            QChar c = m_commandBuffer.at(i);
+    if (!m_currentMessage.isEmpty()) {
+        msg = m_currentMessage;
+        m_currentMessage.clear();
+    } else if (m_visualMode == VisualCharMode) {
+        msg = "-- VISUAL --";
+    } else if (m_visualMode == VisualLineMode) {
+        msg = "-- VISUAL LINE --";
+    } else if (m_visualMode == VisualBlockMode) {
+        msg = "-- VISUAL BLOCK --";
+    } else if (m_mode == InsertMode) {
+        msg = "-- INSERT --";
+    } else {
+        if (m_mode == SearchForwardMode) 
+            msg += '/';
+        else if (m_mode == SearchBackwardMode) 
+            msg += '?';
+        else if (m_mode == ExMode) 
+            msg += ':';
+        foreach (QChar c, m_commandBuffer) {
             if (c.unicode() < 32) {
                 msg += '^';
                 msg += QChar(c.unicode() + 64);
@@ -300,20 +430,22 @@ void FakeVimHandler::Private::updateMiniBuffer()
                 msg += c;
             }
         }
-    } else {
-        msg = m_currentMessage;
-        m_currentMessage.clear();
     }
+    emit q->commandBufferChanged(msg);
+
+    int linesInDoc = linesInDocument();
     int l = cursorLineInDocument();
-    int w = columnsOnScreen();
-    msg += QString(w, ' ');
-    msg = msg.left(w - 20);
+    QString status;
     QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1);
-    msg += tr("%1").arg(pos, -12);
+    status += tr("%1").arg(pos, -10);
     // FIXME: physical "-" logical
-    msg += tr("%1").arg(l * 100 / (m_tc.document()->blockCount() - 1), 4);
-    msg += '%';
-    emit q->commandBufferChanged(msg);
+    if (linesInDoc != 0) {
+        status += tr("%1").arg(l * 100 / linesInDoc, 4);
+        status += "%";
+    } else {
+        status += "All";
+    }
+    emit q->statusDataChanged(status);
 }
 
 void FakeVimHandler::Private::showMessage(const QString &msg)
@@ -334,16 +466,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         m_tc.movePosition(StartOfLine, MoveAnchor);
         m_tc.movePosition(Down, KeepAnchor, count());
         m_registers[m_register] = m_tc.selectedText();
-        finishMovement();
+        finishMovement("c");
     } else if (m_submode == DeleteSubMode && key == 'd') {
         m_tc.movePosition(StartOfLine, MoveAnchor);
         m_tc.movePosition(Down, KeepAnchor, count());
         m_registers[m_register] = m_tc.selectedText();
-        finishMovement();
+        finishMovement("d");
     } else if (m_submode == ZSubMode) {
         if (key == Key_Return) {
             // cursor line to top of window, cursor on first non-blank
-			scrollToLineInDocument(cursorLineInDocument());
+            scrollToLineInDocument(cursorLineInDocument());
             moveToFirstNonBlankOnLine();
             finishMovement();
         } else {
@@ -353,14 +485,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
     } else if (m_subsubmode == FtSubSubMode) {
         handleFfTt(key);
         m_subsubmode = NoSubSubMode;
-        finishMovement();
+        finishMovement(QString(QChar(m_subsubdata)) + QChar(key));
     } else if (m_subsubmode == MarkSubSubMode) {
         m_marks[key] = m_tc.position();
         m_subsubmode = NoSubSubMode;
     } else if (m_subsubmode == BackTickSubSubMode
             || m_subsubmode == TickSubSubMode) {
         if (m_marks.contains(key)) {
-            m_tc.setPosition(m_marks[key]);
+            m_tc.setPosition(m_marks[key], MoveAnchor);
             if (m_subsubmode == TickSubSubMode)
                 moveToFirstNonBlankOnLine();
             finishMovement();
@@ -375,16 +507,21 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         } else {
             m_mvcount.append(QChar(key));
         }
-    } else if (key == ':' || key == '/' || key == '?') {
-        m_commandCode = key;
+    } else if (key == ':') {
         m_mode = ExMode;
-        if (isSearchCommand()) {
-            m_searchHistory.append(QString());
-            m_searchHistoryIndex = m_searchHistory.size() - 1;
-        } else {
-            m_commandHistory.append(QString());
-            m_commandHistoryIndex = m_commandHistory.size() - 1;
+        m_commandBuffer.clear();
+        if (m_visualMode != NoVisualMode) {
+            m_commandBuffer = "'<,'>";
+            leaveVisualMode();
         }
+        m_commandHistory.append(QString());
+        m_commandHistoryIndex = m_commandHistory.size() - 1;
+        updateMiniBuffer();
+    } else if (key == '/' || key == '?') {
+        m_mode = (key == '/') ? SearchForwardMode : SearchBackwardMode;
+        m_commandBuffer.clear();
+        m_searchHistory.append(QString());
+        m_searchHistoryIndex = m_searchHistory.size() - 1;
         updateMiniBuffer();
     } else if (key == '`') {
         m_subsubmode = BackTickSubSubMode;
@@ -405,14 +542,18 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
     } else if (key == '$' || key == Key_End) {
         m_tc.movePosition(EndOfLine, KeepAnchor);
         finishMovement();
+    } else if (key == '.') {
+        qDebug() << "REPEATING" << m_dotCommand;
+        for (int i = count(); --i >= 0; )
+            foreach (QChar c, m_dotCommand)
+                handleKey(c.unicode(), QString(c));
     } else if (key == 'a') {
         m_mode = InsertMode;
         m_lastInsertion.clear();
-        m_tc.beginEditBlock();
         m_tc.movePosition(Right, MoveAnchor, 1);
+        updateMiniBuffer();
     } else if (key == 'A') {
         m_mode = InsertMode;
-        m_tc.beginEditBlock();
         m_tc.movePosition(EndOfLine, MoveAnchor);
         m_lastInsertion.clear();
     } else if (key == 'b') {
@@ -423,18 +564,22 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         finishMovement();
     } else if (key == 'c') {
         m_submode = ChangeSubMode;
-        m_tc.beginEditBlock();
     } else if (key == 'C') {
         m_submode = ChangeSubMode;
-        m_tc.beginEditBlock();
         m_tc.movePosition(EndOfLine, KeepAnchor);
         finishMovement();
-    } else if (key == 'd') {
+    } else if (key == 'd' && m_visualMode == NoVisualMode) {
         if (atEol())
             m_tc.movePosition(Left, MoveAnchor, 1);
         m_opcount = m_mvcount;
         m_mvcount.clear();
         m_submode = DeleteSubMode;
+    } else if (key == 'd') {
+        leaveVisualMode();
+        int beginLine = lineForPosition(m_marks['<']);
+        int endLine = lineForPosition(m_marks['>']);
+        m_tc = selectRange(beginLine, endLine);
+        m_tc.removeSelectedText();
     } else if (key == 'D') {
         m_submode = DeleteSubMode;
         m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0));
@@ -453,7 +598,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         m_gflag = true;
     } else if (key == 'G') {
         int n = m_mvcount.isEmpty() ? linesInDocument() : count();
-        m_tc.setPosition(m_tc.document()->findBlockByNumber(n - 1).position());
+        m_tc.setPosition(positionForLine(n), MoveAnchor);
         if (m_config.contains(ConfigStartOfLine))
             moveToFirstNonBlankOnLine();
         finishMovement();
@@ -469,23 +614,19 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         moveToFirstNonBlankOnLine();
         finishMovement();
     } else if (key == 'i') {
-        m_mode = InsertMode;
-        m_tc.beginEditBlock();
-        m_lastInsertion.clear();
+        enterInsertMode();
+        updateMiniBuffer();
     } else if (key == 'I') {
-        m_mode = InsertMode;
+        enterInsertMode();
         if (m_gflag)
             m_tc.movePosition(StartOfLine, KeepAnchor);
         else
             moveToFirstNonBlankOnLine();
-        m_tc.clearSelection();
-        m_tc.beginEditBlock();
-        m_lastInsertion.clear();
     } else if (key == 'j' || key == Key_Down) {
         m_tc.movePosition(Down, KeepAnchor, count());
         finishMovement();
     } else if (key == 'J') {
-        m_tc.beginEditBlock();
+        EditOperation op;
         if (m_submode == NoSubMode) {
             for (int i = qMax(count(), 2) - 1; --i >= 0; ) {
                 m_tc.movePosition(EndOfLine);
@@ -496,7 +637,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
             if (!m_gflag)
                 m_tc.movePosition(Left, MoveAnchor, 1);
         }
-        m_tc.endEditBlock();
     } else if (key == 'k' || key == Key_Up) {
         m_tc.movePosition(Up, KeepAnchor, count());
         finishMovement();
@@ -519,15 +659,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
     } else if (key == 'N') {
         search(lastSearchString(), !m_lastSearchForward);
     } else if (key == 'o') {
-        m_mode = InsertMode;
-        m_lastInsertion.clear();
-        //m_tc.beginEditBlock();  // FIXME: unusable due to drawing errors
+        enterInsertMode();
         m_tc.movePosition(EndOfLine, MoveAnchor);
         m_tc.insertText("\n");
     } else if (key == 'O') {
-        m_mode = InsertMode;
-        m_lastInsertion.clear();
-        //m_tc.beginEditBlock();  // FIXME: unusable due to drawing errors
+        enterInsertMode();
         m_tc.movePosition(StartOfLine, MoveAnchor);
         m_tc.movePosition(Left, MoveAnchor, 1);
         m_tc.insertText("\n");
@@ -545,29 +681,33 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
             m_tc.movePosition(Left);
         }
     } else if (key == control('r')) {
-        EDITOR(redo());
+        redo();
     } else if (key == 's') {
         m_submode = ChangeSubMode;
-        m_tc.beginEditBlock();
         m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()));
-        finishMovement();
     } else if (key == 't' || key == 'T') {
         m_subsubmode = FtSubSubMode;
         m_subsubdata = key;
     } else if (key == 'u') {
-        EDITOR(undo());
+        undo();
+    } else if (key == 'v') {
+        enterVisualMode(VisualCharMode);
+    } else if (key == 'V') {
+        enterVisualMode(VisualLineMode);
+    } else if (key == control('v')) {
+        enterVisualMode(VisualBlockMode);
     } else if (key == 'w') {
         moveToNextWord(false);
-        finishMovement();
+        finishMovement("w");
     } else if (key == 'W') {
         moveToNextWord(true);
-        finishMovement();
+        finishMovement("W");
     } else if (key == 'x') { // = "dl"
         if (atEol())
             m_tc.movePosition(Left, MoveAnchor, 1);
         m_submode = DeleteSubMode;
         m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()));
-        finishMovement();
+        finishMovement("l");
     } else if (key == 'X') {
         if (leftDist() > 0) {
             m_tc.movePosition(Left, KeepAnchor, qMin(count(), leftDist()));
@@ -596,7 +736,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
     } else if (key == Key_Delete) {
         m_tc.deleteChar();
     } else if (key == Key_Escape) {
-        // harmless
+        if (m_visualMode != NoVisualMode)
+            leaveVisualMode();
     } else {
         qDebug() << "Ignored" << key << text;
     }    
@@ -605,11 +746,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
 void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
 {
     if (key == Key_Escape) {
-        for (int i = 1; i < count(); ++i)
+        // start with '1', as one instance was already physically inserted
+        // while typing
+        QString data = m_lastInsertion;
+        for (int i = 1; i < count(); ++i) {
             m_tc.insertText(m_lastInsertion);
+            data += m_lastInsertion;
+        }
+        recordInsert(m_tc.position() - m_lastInsertion.size(), data);
         m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist()));
-        m_mode = CommandMode;
-        m_tc.endEditBlock();
+        enterCommandMode();
     } else if (key == Key_Left) {
         m_tc.movePosition(Left, MoveAnchor, 1);
         m_lastInsertion.clear();
@@ -624,7 +770,7 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
         m_lastInsertion.clear();
     } else if (key == Key_Return) {
         m_tc.insertBlock();
-        m_lastInsertion.clear();
+        m_lastInsertion += "\n";
     } else if (key == Key_Backspace) {
         m_tc.deletePreviousChar();
         m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
@@ -644,45 +790,40 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
     } else {
         m_lastInsertion.append(text);
         m_tc.insertText(text);
-    }    
+    }
+    updateMiniBuffer();
 }
 
-void FakeVimHandler::Private::handleExMode(int key, const QString &text)
+void FakeVimHandler::Private::handleMiniBufferModes(int key, const QString &text)
 {
     Q_UNUSED(text)
 
     if (key == Key_Escape) {
         m_commandBuffer.clear();
-        m_commandCode = 0;
-        m_mode = CommandMode;
+        enterCommandMode();
         updateMiniBuffer();
     } else if (key == Key_Backspace) {
         if (m_commandBuffer.isEmpty())
-            m_mode = CommandMode;
+            enterCommandMode();
         else
             m_commandBuffer.chop(1);
         updateMiniBuffer();
-    } else if (key == Key_Return && m_commandCode == ':') {
+    } else if (key == Key_Return && m_mode == ExMode) {
         if (!m_commandBuffer.isEmpty()) {
             m_commandHistory.takeLast();
             m_commandHistory.append(m_commandBuffer);
-            handleCommand(m_commandBuffer);
-            m_commandBuffer.clear();
-            m_commandCode = 0;
+            handleExCommand(m_commandBuffer);
         }
-        m_mode = CommandMode;
-    } else if (key == Key_Return && isSearchCommand()) {
+    } else if (key == Key_Return && isSearchMode()) {
         if (!m_commandBuffer.isEmpty()) {
             m_searchHistory.takeLast();
             m_searchHistory.append(m_commandBuffer);
-            m_lastSearchForward = (m_commandCode == '/');
+            m_lastSearchForward = (m_mode == SearchForwardMode);
             search(lastSearchString(), m_lastSearchForward);
-            m_commandBuffer.clear();
-            m_commandCode = 0;
         }
-        m_mode = CommandMode;
+        enterCommandMode();
         updateMiniBuffer();
-    } else if (key == Key_Up && isSearchCommand()) {
+    } else if (key == Key_Up && isSearchMode()) {
         // FIXME: This and the three cases below are wrong as vim
         // takes only matching entires in the history into account.
         if (m_searchHistoryIndex > 0) {
@@ -690,19 +831,19 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text)
             m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex);
             updateMiniBuffer();
         }
-    } else if (key == Key_Up && m_commandCode == ':') {
+    } else if (key == Key_Up && m_mode == ExMode) {
         if (m_commandHistoryIndex > 0) {
             --m_commandHistoryIndex;
             m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex);
             updateMiniBuffer();
         }
-    } else if (key == Key_Down && isSearchCommand()) {
+    } else if (key == Key_Down && isSearchMode()) {
         if (m_searchHistoryIndex < m_searchHistory.size() - 1) {
             ++m_searchHistoryIndex;
             m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex);
             updateMiniBuffer();
         }
-    } else if (key == Key_Down && m_commandCode == ':') {
+    } else if (key == Key_Down && m_mode == ExMode) {
         if (m_commandHistoryIndex < m_commandHistory.size() - 1) {
             ++m_commandHistoryIndex;
             m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); 
@@ -737,6 +878,16 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
         int n = readLineCode(cmd);
         return cursorLineInDocument() + 1 + (n == -1 ? 1 : n);
     }
+    if (c == '\'' && !cmd.isEmpty()) {
+        int pos = m_marks.value(cmd.at(0).unicode());
+        qDebug() << " MARK: " << cmd.at(0) << pos << lineForPosition(pos);
+        if (!pos) {
+             showMessage(tr("E20: Mark '%1' not set").arg(cmd.at(0)));
+             return -1;
+        }
+        cmd = cmd.mid(1);
+        return lineForPosition(pos);
+    }
     if (c.isDigit()) {
         int n = c.unicode() - '0';
         while (!cmd.isEmpty()) {
@@ -754,14 +905,27 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
     return -1; 
 }
 
-void FakeVimHandler::Private::handleCommand(const QString &cmd0)
+QTextCursor FakeVimHandler::Private::selectRange(int beginLine, int endLine)
+{
+    QTextCursor tc = m_tc;
+    tc.setPosition(positionForLine(beginLine), MoveAnchor);
+    if (endLine == linesInDocument()) {
+        tc.setPosition(positionForLine(endLine), KeepAnchor);
+        tc.movePosition(EndOfLine, KeepAnchor);
+    } else {
+        tc.setPosition(positionForLine(endLine + 1), KeepAnchor);
+    }
+    return tc;
+}
+
+void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
 {
     QString cmd = cmd0;
     if (cmd.startsWith("%"))
         cmd = "1,$" + cmd.mid(1);
 
-    int beginLine = 0;
-    int endLine = linesInDocument();
+    int beginLine = -1;
+    int endLine = -1;
 
     int line = readLineCode(cmd);
     if (line != -1)
@@ -774,44 +938,68 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0)
             endLine = line;
     }
 
-    //qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0;
+    qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0;
 
     static QRegExp reWrite("^w!?( (.*))?$");
+    static QRegExp reDelete("^d( (.*))?$");
 
     if (cmd.isEmpty()) {
-        m_tc.setPosition(m_tc.block().document()
-            ->findBlockByNumber(beginLine - 1).position());
-        showMessage(QString());
-    } else if (cmd == "q!" || cmd == "q") {
-        q->quitRequested(THE_EDITOR);
+        m_tc.setPosition(positionForLine(beginLine));
         showMessage(QString());
-    } else if (reWrite.indexIn(cmd) != -1) {
+    } else if (cmd == "q!" || cmd == "q") { // :q
+        quit();
+    } else if (reDelete.indexIn(cmd) != -1) { // :d
+        if (beginLine == -1)
+            beginLine = cursorLineInDocument();
+        if (endLine == -1)
+            endLine = cursorLineInDocument();
+        QTextCursor tc = selectRange(beginLine, endLine);
+        QString reg = reDelete.cap(2);
+        if (!reg.isEmpty())
+            m_registers[reg.at(0).unicode()] = tc.selection().toPlainText();
+        tc.removeSelectedText();
+    } else if (reWrite.indexIn(cmd) != -1) { // :w
+        enterCommandMode();
+        bool noArgs = (beginLine == -1);
+        if (beginLine == -1)
+            beginLine = 0;
+        if (endLine == -1)
+            endLine = linesInDocument();
+        qDebug() << "LINES: " << beginLine << endLine;
         bool forced = cmd.startsWith("w!");
         QString fileName = reWrite.cap(2);
         if (fileName.isEmpty())
             fileName = m_currentFileName;
         QFile file(fileName);
         bool exists = file.exists();
-        if (exists && !forced) {
-            showMessage("E13: File exists (add ! to override)");
-        } else {
-            file.open(QIODevice::ReadWrite);
-            QTextStream ts(&file);
-            ts << EDITOR(toPlainText());
+        if (exists && !forced && !noArgs) {
+            showMessage(tr("File '%1' exists (add ! to override)").arg(fileName));
+        } else if (file.open(QIODevice::ReadWrite)) {
+            QTextCursor tc = selectRange(beginLine, endLine);
+            qDebug() << "ANCHOR: " << tc.position() << tc.anchor()
+                << tc.selection().toPlainText();
+            { QTextStream ts(&file); ts << tc.selection().toPlainText(); }
             file.close();
-            file.open(QIODevice::ReadWrite);
+            file.open(QIODevice::ReadOnly);
             QByteArray ba = file.readAll();
-            showMessage(tr("\"%1\" %2 %3L, %4C written")
+            m_commandBuffer = QString("\"%1\" %2 %3L, %4C written")
                 .arg(fileName).arg(exists ? " " : " [New] ")
-                .arg(ba.count('\n')).arg(ba.size()));
+                .arg(ba.count('\n')).arg(ba.size());
+            updateMiniBuffer();
+        } else {
+            showMessage(tr("Cannot open file '%1' for reading").arg(fileName));
         }
-    } else if (cmd.startsWith("r ")) {
+    } else if (cmd.startsWith("r ")) { // :r
         m_currentFileName = cmd.mid(2);
         QFile file(m_currentFileName);
         file.open(QIODevice::ReadOnly);
         QTextStream ts(&file);
-        EDITOR(setPlainText(ts.readAll()));
-        showMessage(QString());
+        QString data = ts.readAll();
+        EDITOR(setPlainText(data));
+        m_commandBuffer = QString("\"%1\" %2L, %3C")
+            .arg(m_currentFileName).arg(data.count('\n')).arg(data.size());
+        enterCommandMode();
+        updateMiniBuffer();
     } else {
         showMessage("E492: Not an editor command: " + cmd0);
     }
@@ -961,30 +1149,37 @@ void FakeVimHandler::Private::moveToNextWord(bool simple)
 
 int FakeVimHandler::Private::cursorLineOnScreen() const
 {
-	QRect rect = EDITOR(cursorRect());
-	return rect.y() / rect.height();
+    if (!editor())
+        return 0;
+    QRect rect = EDITOR(cursorRect());
+    return rect.y() / rect.height();
 }
 
 int FakeVimHandler::Private::linesOnScreen() const
 {
-	QRect rect = EDITOR(cursorRect());
-	return EDITOR(height()) / rect.height();
+    if (!editor())
+        return 1;
+    QRect rect = EDITOR(cursorRect());
+    return EDITOR(height()) / rect.height();
 }
 
 int FakeVimHandler::Private::columnsOnScreen() const
 {
-	QRect rect = EDITOR(cursorRect());
-	return EDITOR(width()) / rect.width();
+    if (!editor())
+        return 1;
+    QRect rect = EDITOR(cursorRect());
+    // qDebug() << "WID: " << EDITOR(width()) << "RECT: " << rect;
+    return EDITOR(width()) / rect.width();
 }
 
 int FakeVimHandler::Private::cursorLineInDocument() const
 {
-	return m_tc.block().blockNumber();
+    return m_tc.block().blockNumber();
 }
 
 int FakeVimHandler::Private::cursorColumnInDocument() const
 {
-	return m_tc.position() - m_tc.block().position();
+    return m_tc.position() - m_tc.block().position();
 }
 
 int FakeVimHandler::Private::linesInDocument() const
@@ -994,9 +1189,9 @@ int FakeVimHandler::Private::linesInDocument() const
 
 void FakeVimHandler::Private::scrollToLineInDocument(int line)
 {
-	// FIXME: works only for QPlainTextEdit
-	QScrollBar *scrollBar = EDITOR(verticalScrollBar());
-	scrollBar->setValue(line);
+    // FIXME: works only for QPlainTextEdit
+    QScrollBar *scrollBar = EDITOR(verticalScrollBar());
+    scrollBar->setValue(line);
 }
 
 int FakeVimHandler::Private::lastPositionInDocument() const
@@ -1010,6 +1205,141 @@ QString FakeVimHandler::Private::lastSearchString() const
      return m_searchHistory.empty() ? QString() : m_searchHistory.back();
 }
 
+int FakeVimHandler::Private::positionForLine(int line) const
+{
+    return m_tc.block().document()->findBlockByNumber(line - 1).position();
+}
+
+int FakeVimHandler::Private::lineForPosition(int pos) const
+{
+    QTextCursor tc = m_tc;
+    tc.setPosition(pos);
+    return tc.block().blockNumber() + 1;
+}
+
+void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode)
+{
+    m_visualMode = visualMode;
+    m_marks['<'] = m_tc.position();
+    updateMiniBuffer();
+    updateSelection();
+}
+
+void FakeVimHandler::Private::leaveVisualMode()
+{
+    m_visualMode = NoVisualMode;
+    m_marks['>'] = m_tc.position();
+    updateMiniBuffer();
+    updateSelection();
+}
+
+QWidget *FakeVimHandler::Private::editor() const
+{
+    return m_textedit
+        ? static_cast<QWidget *>(m_textedit)
+        : static_cast<QWidget *>(m_plaintextedit);
+}
+
+void FakeVimHandler::Private::undo()
+{
+#if 0
+    EDITOR(undo());
+#else
+    if (m_undoStack.isEmpty())
+        return;
+    EditOperation op = m_undoStack.pop();
+    //qDebug() << "UNDO " << op;
+    if (op.m_itemCount > 0) {
+        for (int i = op.m_itemCount; --i >= 0; )
+            undo();
+    } else {
+        m_tc.setPosition(op.m_position, MoveAnchor);
+        if (!op.m_to.isEmpty()) {
+            m_tc.setPosition(op.m_position + op.m_to.size(), KeepAnchor);
+            m_tc.deleteChar();
+        }
+        if (!op.m_from.isEmpty())
+            m_tc.insertText(op.m_from);
+        m_tc.setPosition(op.m_position, MoveAnchor);
+    }
+    m_redoStack.push(op);
+#endif
+}
+
+void FakeVimHandler::Private::redo()
+{
+#if 0
+    EDITOR(redo());
+#else
+    if (m_redoStack.isEmpty())
+        return;
+    EditOperation op = m_redoStack.pop();
+    //qDebug() << "REDO " << op;
+    if (op.m_itemCount > 0) {
+        for (int i = op.m_itemCount; --i >= 0; )
+            redo();
+    } else {
+        m_tc.setPosition(op.m_position, MoveAnchor);
+        if (!op.m_from.isEmpty()) {
+            m_tc.setPosition(op.m_position + op.m_from.size(), KeepAnchor);
+            m_tc.deleteChar();
+        }
+        if (!op.m_to.isEmpty())
+            m_tc.insertText(op.m_to);
+        m_tc.setPosition(op.m_position, MoveAnchor);
+    }
+    m_undoStack.push(op);
+#endif
+}
+
+void FakeVimHandler::Private::recordInsert(int position, const QString &data)
+{
+    EditOperation op;
+    op.m_position = position;
+    op.m_to = data;
+    m_undoStack.push(op);
+    m_redoStack.clear();
+}
+
+void FakeVimHandler::Private::recordRemove(int position, int length)
+{
+    QTextCursor tc = m_tc;
+    tc.setPosition(position, MoveAnchor);
+    tc.setPosition(position + length, KeepAnchor);
+    recordRemove(position, tc.selection().toPlainText());
+}
+
+void FakeVimHandler::Private::recordRemove(int position, const QString &data)
+{
+    EditOperation op;
+    op.m_position = position;
+    op.m_from = data;
+    m_undoStack.push(op);
+    m_redoStack.clear();
+}
+
+void FakeVimHandler::Private::enterInsertMode()
+{
+    EDITOR(setOverwriteMode(false));
+    m_mode = InsertMode;
+    m_lastInsertion.clear();
+}
+
+void FakeVimHandler::Private::enterCommandMode()
+{
+    if (editor())
+        EDITOR(setOverwriteMode(true));
+    m_mode = CommandMode;
+}
+
+void FakeVimHandler::Private::quit()
+{
+    showMessage(QString());
+    EDITOR(setOverwriteMode(false));
+    q->quitRequested(editor());
+}
+
+
 ///////////////////////////////////////////////////////////////////////
 //
 // FakeVimHandler
@@ -1035,23 +1365,22 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
 void FakeVimHandler::addWidget(QWidget *widget)
 {
     widget->installEventFilter(this);
-    QFont font = widget->font();
-    //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
-    //font.setFamily("Misc");
-    font.setFamily("Monospace");
-    font.setStretch(QFont::SemiCondensed);
-    widget->setFont(font);
+    d->enterCommandMode();
     if (QTextEdit *ed = qobject_cast<QTextEdit *>(widget)) {
-        ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
+        //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
         ed->setLineWrapMode(QTextEdit::NoWrap);
     } else if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(widget)) {
-        ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
+        //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
         ed->setLineWrapMode(QPlainTextEdit::NoWrap);
     }
+    d->showMessage("vi emulation mode. Hit <Shift+Esc>:q<Return> to quit");
+    d->updateMiniBuffer();
 }
 
 void FakeVimHandler::removeWidget(QWidget *widget)
 {
+    d->showMessage(QString());
+    d->updateMiniBuffer();
     widget->removeEventFilter(this);
 }
 
@@ -1059,6 +1388,11 @@ void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd)
 {
     d->m_textedit = qobject_cast<QTextEdit *>(widget);
     d->m_plaintextedit = qobject_cast<QPlainTextEdit *>(widget);
-    d->handleCommand(cmd);
+    d->handleExCommand(cmd);
 }
 
+
+void FakeVimHandler::quit()
+{
+    d->quit();
+}
diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h
index 1ebf9adb8e47202bcc50d14da7c3a5cb1ce334c8..fccb9f0f84f3abc229f4e567258213f8129f4f16 100644
--- a/src/plugins/fakevim/handler.h
+++ b/src/plugins/fakevim/handler.h
@@ -52,16 +52,20 @@ public:
     FakeVimHandler(QObject *parent = 0);
     ~FakeVimHandler();
 
+public slots:
     // The same handler can be installed on several widgets
+    // FIXME: good idea?
     void addWidget(QWidget *widget);
     void removeWidget(QWidget *widget);
 
     // This executes an "ex" style command taking context
     // information from \p widget;
     void handleCommand(QWidget *widget, const QString &cmd);
+    void quit();
 
 signals:
     void commandBufferChanged(const QString &msg);
+    void statusDataChanged(const QString &msg);
     void quitRequested(QWidget *);
 
 private:
diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp
index 26ed8dd0492b9df38232389a1228d39bce5a6daf..dd25564a4373fee90f1112ebfeb24a8a1cc02fb8 100644
--- a/src/plugins/find/currentdocumentfind.cpp
+++ b/src/plugins/find/currentdocumentfind.cpp
@@ -147,9 +147,11 @@ void CurrentDocumentFind::updateCurrentFindFilter(QWidget *old, QWidget *now)
         if (!impl)
             candidate = candidate->parentWidget();
     }
-    if (!impl)
+    if (!impl || impl == m_currentFind)
         return;
     removeFindSupportConnections();
+    if (m_currentFind)
+        m_currentFind->highlightAll(QString(), 0);
     m_currentWidget = candidate;
     m_currentFind = impl;
     if (m_currentFind) {
diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp
index 8d06c871f96984788c3aa20e5db02faac9359477..3eeee2347b672374d6f5a71a75eeb6d1b4ba7837 100644
--- a/src/plugins/git/branchdialog.cpp
+++ b/src/plugins/git/branchdialog.cpp
@@ -58,8 +58,9 @@ bool BranchDialog::init(GitClient *client, const QString &workingDirectory, QStr
     }
     m_ui->repositoryFieldLabel->setText(m_repoDirectory);
 
-    m_localModel = new BranchModel(client, BranchModel::LocalBranches, this);
-    m_remoteModel = new BranchModel(client, BranchModel::RemoteBranches, this);
+    m_localModel = new LocalBranchModel(client, this);
+    connect(m_localModel, SIGNAL(newBranchCreated(QString)), this, SLOT(slotNewLocalBranchCreated(QString)));
+    m_remoteModel = new RemoteBranchModel(client, this);
     if (!m_localModel->refresh(workingDirectory, errorMessage)
         || !m_remoteModel->refresh(workingDirectory, errorMessage))
         return false;
@@ -93,13 +94,23 @@ void BranchDialog::slotEnableButtons()
     const int selectedLocalRow = selectedLocalBranchIndex();
     const int currentLocalBranch = m_localModel->currentBranch();
 
-    const bool hasSelection = selectedLocalRow != -1;
+    const bool hasSelection = selectedLocalRow != -1 && !m_localModel->isNewBranchRow(selectedLocalRow);
     const bool currentIsNotSelected = hasSelection && selectedLocalRow != currentLocalBranch;
 
     m_checkoutButton->setEnabled(currentIsNotSelected);
     m_deleteButton->setEnabled(currentIsNotSelected);
 }
 
+void BranchDialog::slotNewLocalBranchCreated(const QString &b)
+{
+    // Select the newly created branch
+    const int row = m_localModel->findBranchByName(b);
+    if (row != -1) {
+        const QModelIndex index = m_localModel->index(row);
+        m_ui->localBranchListView->selectionModel()->select(index, QItemSelectionModel::Select);
+    }
+}
+
 bool BranchDialog::ask(const QString &title, const QString &what, bool defaultButton)
 {
     return QMessageBox::question(this, title, what, QMessageBox::Yes|QMessageBox::No,
diff --git a/src/plugins/git/branchdialog.h b/src/plugins/git/branchdialog.h
index 064719b8ff045167b67ceaf2524f105e302a3bd2..c803b57e833a8ad9920a0828a6c6d1c9dc8ac7a1 100644
--- a/src/plugins/git/branchdialog.h
+++ b/src/plugins/git/branchdialog.h
@@ -14,7 +14,8 @@ namespace Git {
         }
 
         class GitClient;
-        class BranchModel;
+        class LocalBranchModel;
+        class RemoteBranchModel;
 
         /* Branch dialog: Display a list of local branches at the top
          * and remote branches below. Offers to checkout/delete local
@@ -39,6 +40,7 @@ namespace Git {
             void slotCheckoutSelectedBranch();
             void slotDeleteSelectedBranch();
             void slotLocalBranchActivated();
+            void slotNewLocalBranchCreated(const QString &);
 
         private:
             bool ask(const QString &title, const QString &what, bool defaultButton);
@@ -51,8 +53,8 @@ namespace Git {
             QPushButton *m_checkoutButton;
             QPushButton *m_deleteButton;
 
-            BranchModel *m_localModel;
-            BranchModel *m_remoteModel;
+            LocalBranchModel *m_localModel;
+            RemoteBranchModel *m_remoteModel;
             QString m_repoDirectory;
         };
     } // namespace Internal
diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp
index b02d58dbd04d6d445bf923dd61ead83a8d26cde0..bb8ccf19510cadcbeec145d826ae08931aadd630 100644
--- a/src/plugins/git/branchmodel.cpp
+++ b/src/plugins/git/branchmodel.cpp
@@ -2,6 +2,8 @@
 #include "gitclient.h"
 
 #include <QtCore/QDebug>
+#include <QtCore/QRegExp>
+#include <QtCore/QTimer>
 
 enum { debug = 0 };
 
@@ -10,7 +12,7 @@ namespace Git {
 
 // Parse a branch line: " *name sha description".  Return  true if it is
 // the current one
-bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
+bool RemoteBranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
 {
     if (debug)
         qDebug() << Q_FUNC_INFO << lineIn;
@@ -28,40 +30,41 @@ bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent)
     return true;
 }
 
-static inline Qt::ItemFlags typeToModelFlags(BranchModel::Type t)
+// ------ RemoteBranchModel
+RemoteBranchModel::RemoteBranchModel(GitClient *client, QObject *parent) :
+    QAbstractListModel(parent),
+    m_flags(Qt::ItemIsSelectable|Qt::ItemIsEnabled),
+    m_client(client)
 {
-    Qt::ItemFlags rc = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
-    if (t == BranchModel::LocalBranches)
-        rc |= Qt::ItemIsUserCheckable;
-    return rc;
 }
 
-// --- BranchModel
-BranchModel::BranchModel(GitClient *client, Type type, QObject *parent) :
-    QAbstractListModel(parent),
-    m_type(type),
-    m_flags(typeToModelFlags(type)),
-    m_client(client),
-    m_currentBranch(-1)
+bool RemoteBranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
 {
+    int currentBranch;
+    return refreshBranches(workingDirectory, true, &currentBranch, errorMessage);
 }
 
-int BranchModel::currentBranch() const
+QString RemoteBranchModel::branchName(int row) const
 {
-    return m_currentBranch;
+    return m_branches.at(row).name;
 }
 
-QString BranchModel::branchName(int row) const
+QString RemoteBranchModel::workingDirectory() const
 {
-    return m_branches.at(row).name;
+    return m_workingDirectory;
 }
 
-int BranchModel::rowCount(const QModelIndex & /* parent */) const
+int RemoteBranchModel::branchCount() const
 {
     return m_branches.size();
 }
 
-QVariant BranchModel::data(const QModelIndex &index, int role) const
+int RemoteBranchModel::rowCount(const QModelIndex & /* parent */) const
+{
+    return branchCount();
+}
+
+QVariant RemoteBranchModel::data(const QModelIndex &index, int role) const
 {
     const int row = index.row();
     switch (role) {
@@ -72,36 +75,52 @@ QVariant BranchModel::data(const QModelIndex &index, int role) const
             m_branches.at(row).toolTip = toolTip(m_branches.at(row).currentSHA);
         return m_branches.at(row).toolTip;
         break;
-        case Qt::CheckStateRole:
-        if (m_type == RemoteBranches)
-            return QVariant();
-        return row == m_currentBranch ? Qt::Checked : Qt::Unchecked;
         default:
         break;
     }
     return QVariant();
 }
 
-Qt::ItemFlags BranchModel::flags(const QModelIndex & /*index */) const
+Qt::ItemFlags RemoteBranchModel::flags(const QModelIndex & /* index */) const
 {
     return m_flags;
 }
 
-bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
+QString RemoteBranchModel::toolTip(const QString &sha) const
+{
+    // Show the sha description excluding diff as toolTip
+    QString output;
+    QString errorMessage;
+    if (!m_client->synchronousShow(m_workingDirectory, sha, &output, &errorMessage))
+        return errorMessage;
+    // Remove 'diff' output
+    const int diffPos = output.indexOf(QLatin1String("\ndiff --"));
+    if (diffPos != -1)
+        output.remove(diffPos, output.size() - diffPos);
+    return output;
+}
+
+bool RemoteBranchModel::runGitBranchCommand(const QString &workingDirectory, const QStringList &additionalArgs, QString *output, QString *errorMessage)
+{
+    return m_client->synchronousBranchCmd(workingDirectory, additionalArgs, output, errorMessage);
+}
+
+bool RemoteBranchModel::refreshBranches(const QString &workingDirectory, bool remoteBranches,
+                                        int *currentBranch, QString *errorMessage)
 {
     // Run branch command with verbose.
     QStringList branchArgs(QLatin1String("-v"));
     QString output;
-    if (m_type == RemoteBranches)
+    *currentBranch = -1;
+    if (remoteBranches)
         branchArgs.push_back(QLatin1String("-r"));
-    if (!m_client->synchronousBranchCmd(workingDirectory, branchArgs, &output, errorMessage))
+    if (!runGitBranchCommand(workingDirectory, branchArgs, &output, errorMessage))
         return false;
     if (debug)
         qDebug() << Q_FUNC_INFO << workingDirectory << output;
     // Parse output
     m_workingDirectory = workingDirectory;
     m_branches.clear();
-    m_currentBranch = -1;
     const QStringList branches = output.split(QLatin1Char('\n'));
     const int branchCount = branches.size();
     bool isCurrent;
@@ -110,25 +129,122 @@ bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage
         if (newBranch.parse(branches.at(b), &isCurrent)) {
             m_branches.push_back(newBranch);
             if (isCurrent)
-                m_currentBranch = b;
+                *currentBranch = b;
         }
     }
     reset();
     return true;
 }
 
-QString BranchModel::toolTip(const QString &sha) const
+int RemoteBranchModel::findBranchByName(const QString &name) const
 {
-    // Show the sha description excluding diff as toolTip
+    const int count = branchCount();
+    for (int i = 0; i < count; i++)
+        if (branchName(i) == name)
+            return i;
+    return -1;
+}
+
+// --- LocalBranchModel
+LocalBranchModel::LocalBranchModel(GitClient *client, QObject *parent) :
+    RemoteBranchModel(client, parent),
+    m_typeHere(tr("<New branch>")),
+    m_typeHereToolTip(tr("Type to create a new branch")),
+    m_currentBranch(-1)
+{
+}
+
+int LocalBranchModel::currentBranch() const
+{
+    return m_currentBranch;
+}
+
+bool LocalBranchModel::isNewBranchRow(int row) const
+{
+    return row >= branchCount();
+}
+
+Qt::ItemFlags LocalBranchModel::flags(const QModelIndex & index) const
+{
+    if (isNewBranchRow(index))
+        return Qt::ItemIsEditable|Qt::ItemIsSelectable|Qt::ItemIsEnabled| Qt::ItemIsUserCheckable;
+    return RemoteBranchModel::flags(index) | Qt::ItemIsUserCheckable;
+}
+
+int LocalBranchModel::rowCount(const QModelIndex & /* parent */) const
+{
+    return branchCount() + 1;
+}
+
+QVariant LocalBranchModel::data(const QModelIndex &index, int role) const
+{
+    if (isNewBranchRow(index)) {
+        switch (role) {
+        case Qt::DisplayRole:
+            return m_typeHere;
+        case Qt::ToolTipRole:
+            return m_typeHereToolTip;
+        case Qt::CheckStateRole:
+            return QVariant(false);
+        }
+        return QVariant();
+    }
+
+    if (role == Qt::CheckStateRole)
+        return index.row() == m_currentBranch ? Qt::Checked : Qt::Unchecked;
+    return RemoteBranchModel::data(index, role);
+}
+
+bool LocalBranchModel::refresh(const QString &workingDirectory, QString *errorMessage)
+{
+    return refreshBranches(workingDirectory, false, &m_currentBranch, errorMessage);
+}
+
+bool LocalBranchModel::checkNewBranchName(const QString &name) const
+{
+    // Syntax
+    const QRegExp pattern(QLatin1String("[a-zA-Z0-9-_]+"));
+    if (!pattern.exactMatch(name))
+        return false;
+    // existing
+    if (findBranchByName(name) != -1)
+        return false;
+    return true;
+}
+
+bool LocalBranchModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    // Verify
+    if (role != Qt::EditRole || index.row() < branchCount())
+        return false;
+    const QString branchName = value.toString();
+    const bool ok = checkNewBranchName(branchName);
+    if (debug)
+        qDebug() << Q_FUNC_INFO << branchName << ok;
+    if (!ok)
+        return false;
+    // Create
     QString output;
     QString errorMessage;
-    if (!m_client->synchronousShow(m_workingDirectory, sha, &output, &errorMessage))
-        return errorMessage;
-    // Remove 'diff' output
-    const int diffPos = output.indexOf(QLatin1String("\ndiff --"));
-    if (diffPos != -1)
-        output.remove(diffPos, output.size() - diffPos);
-    return output;
+    if (!runGitBranchCommand(workingDirectory(), QStringList(branchName), &output, &errorMessage))
+        return false;
+    m_newBranch = branchName;
+    // Start a delayed complete refresh and return true for now.
+    QTimer::singleShot(0, this, SLOT(slotNewBranchDelayedRefresh()));
+    return true;
+}
+
+void LocalBranchModel::slotNewBranchDelayedRefresh()
+{
+    if (debug)
+        qDebug() << Q_FUNC_INFO;
+
+    QString errorMessage;
+    if (!refresh(workingDirectory(), &errorMessage)) {
+        qWarning("%s", qPrintable(errorMessage));
+        return;
+    }
+    emit newBranchCreated(m_newBranch);
 }
 
 }
diff --git a/src/plugins/git/branchmodel.h b/src/plugins/git/branchmodel.h
index 5083a1c377cfe81ddf6bce7f0b25ec03ad11e3ed..91b1ca84dc0e89e8ffcf074dee2b584a2b161ceb 100644
--- a/src/plugins/git/branchmodel.h
+++ b/src/plugins/git/branchmodel.h
@@ -3,27 +3,25 @@
 
 #include <QtCore/QAbstractListModel>
 #include <QtCore/QList>
+#include <QtCore/QVariant>
 
 namespace Git {
     namespace Internal {
 
 class GitClient;
 
-/* A model to list git branches in a simple list of branch names. Local
- * branches will have a read-only checkbox indicating the current one. The
- * [delayed] tooltip describes the latest commit. */
+/* A read-only model to list git remote branches in a simple list of branch names.
+ * The tooltip describes the latest commit (delayed creation).
+ * Provides virtuals to be able to derive a local branch model with the notion
+ * of a "current branch". */
 
-class BranchModel : public QAbstractListModel {
+class RemoteBranchModel : public QAbstractListModel {
+    Q_OBJECT
 public:
-    enum Type { LocalBranches, RemoteBranches };
+    explicit RemoteBranchModel(GitClient *client, QObject *parent = 0);
 
-    explicit BranchModel(GitClient *client,
-                         Type type = LocalBranches,
-                         QObject *parent = 0);
-
-    bool refresh(const QString &workingDirectory, QString *errorMessage);
+    virtual bool refresh(const QString &workingDirectory, QString *errorMessage);
 
-    int currentBranch() const;
     QString branchName(int row) const;
 
     // QAbstractListModel
@@ -31,9 +29,12 @@ public:
     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
     virtual Qt::ItemFlags flags(const QModelIndex &index) const;
 
-private:
-    QString toolTip(const QString &sha) const;
+    int branchCount() const;
 
+    QString workingDirectory() const;
+    int findBranchByName(const QString &name) const;
+
+protected:
     struct Branch {
         bool parse(const QString &line, bool *isCurrent);
 
@@ -43,13 +44,61 @@ private:
     };
     typedef QList<Branch> BranchList;
 
-    const Type m_type;
+    /* Parse git output and populate m_branches. */
+    bool refreshBranches(const QString &workingDirectory, bool remoteBranches,
+                         int *currentBranch, QString *errorMessage);
+    bool runGitBranchCommand(const QString &workingDirectory, const QStringList &additionalArgs, QString *output, QString *errorMessage);
+
+private:
+    QString toolTip(const QString &sha) const;
+
     const Qt::ItemFlags m_flags;
-    GitClient *m_client;
 
+    GitClient *m_client;
     QString m_workingDirectory;
     BranchList m_branches;
+};
+
+/* LocalBranchModel: Extends RemoteBranchModel by a read-only
+ * checkable column indicating the current branch. Provides an
+ * editable "Type here" new-branch-row at the bottom to create
+ * a new branch. */
+
+class LocalBranchModel : public RemoteBranchModel {
+    Q_OBJECT
+public:
+
+    explicit LocalBranchModel(GitClient *client,
+                         QObject *parent = 0);
+
+    virtual bool refresh(const QString &workingDirectory, QString *errorMessage);
+
+    // is this the "type here" row?
+    bool isNewBranchRow(int row) const;
+    bool isNewBranchRow(const QModelIndex & index) const { return isNewBranchRow(index.row()); }
+
+    int currentBranch() const;
+
+    // QAbstractListModel
+    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+signals:
+    void newBranchCreated(const QString &);
+
+private slots:
+    void slotNewBranchDelayedRefresh();
+
+private:
+    bool checkNewBranchName(const QString &name) const;
+
+    const QVariant m_typeHere;
+    const QVariant m_typeHereToolTip;
+
     int m_currentBranch;
+    QString m_newBranch;
 };
 
 }
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index bdc98b66ee124e863bbfccf400c633ac721a135c..5ecb375240dcc4057b06f75f55ddbb7c327ea288 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -83,7 +83,8 @@ void HelpManager::registerDocumentation(const QStringList &fileNames)
     bool needsSetup = false;
     {
         QHelpEngineCore hc(m_helpEngine->collectionFile());
-        hc.setupData();
+        if (!hc.setupData())
+            qWarning() << "Could not initialize help engine:" << hc.error();
         foreach (const QString &fileName, fileNames) {
             if (!QFile::exists(fileName))
                 continue;
@@ -132,7 +133,7 @@ bool HelpPlugin::initialize(const QStringList & /*arguments*/, QString *)
 
     // FIXME shouldn't the help engine create the directory if it doesn't exist?
     QFileInfo fi(m_core->settings()->fileName());
-    QDir directory(fi.absolutePath());
+    QDir directory(fi.absolutePath()+"/qtcreator");
     if (!directory.exists())
         directory.mkpath(directory.absolutePath());
     m_helpEngine = new QHelpEngine(directory.absolutePath()
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 2a7fd0c242cb4a5dcd8306e6205f0b0b5e1eb7de..dd61dbde09980132e0807c50fa5931dffbd14491 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -566,7 +566,6 @@ QStringList Qt4Project::files(FilesMode fileMode) const
         if (fileMode == AllFiles)
             files += m_projectFiles->generatedFiles[i];
     }
-    files += m_projectFiles->proFiles;
     return files;
 }
 
diff --git a/src/plugins/quickopen/quickopentoolwindow.cpp b/src/plugins/quickopen/quickopentoolwindow.cpp
index 415e347a3ac612904ff87f31a7604984fc989821..b3232147f37b724f9f332e3f5fea5fbc99dbacca 100644
--- a/src/plugins/quickopen/quickopentoolwindow.cpp
+++ b/src/plugins/quickopen/quickopentoolwindow.cpp
@@ -451,14 +451,25 @@ void QuickOpenToolWindow::show(const QString &text, int selectionStart, int sele
 
 void QuickOpenToolWindow::filterSelected()
 {
-    const char * const TEXT = "<type here>";
+    QString searchText = "<type here>";
     QAction *action = qobject_cast<QAction*>(sender());
     QTC_ASSERT(action, return);
     IQuickOpenFilter *filter = action->data().value<IQuickOpenFilter*>();
     QTC_ASSERT(filter, return);
-    show(filter->shortcutString() + " " + TEXT,
+    QString currentText = m_fileLineEdit->text().trimmed();
+    // add shortcut string at front or replace existing shortcut string
+    if (!currentText.isEmpty()) {
+        searchText = currentText;
+        foreach (IQuickOpenFilter *otherfilter, m_quickOpenPlugin->filter()) {
+            if (currentText.startsWith(otherfilter->shortcutString() + " ")) {
+                searchText = currentText.mid(otherfilter->shortcutString().length()+1);
+                break;
+            }
+        }
+    }
+    show(filter->shortcutString() + " " + searchText,
          filter->shortcutString().length() + 1,
-         QString(TEXT).length());
+         searchText.length());
     updateCompletionList(m_fileLineEdit->text());
     m_fileLineEdit->setFocus();
 }
diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp
index 2b2f8520e739c2f52e8a1d2fec9ebd66706055da..2c9f6017b7f9773d9630cfab3ee94b82e9755104 100644
--- a/src/plugins/texteditor/completionwidget.cpp
+++ b/src/plugins/texteditor/completionwidget.cpp
@@ -260,9 +260,9 @@ void CompletionWidget::updatePositionAndSize(int startPos)
     const QRect cursorRect = m_editor->cursorRect(startPos);
     const QDesktopWidget *desktop = QApplication::desktop();
 #ifdef Q_OS_MAC
-    const QRect screen = desktop->availableGeometry(desktop->screenNumber(this));
+    const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editorWidget));
 #else
-    const QRect screen = desktop->screenGeometry(desktop->screenNumber(this));
+    const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editorWidget));
 #endif
 
     QPoint pos = cursorRect.bottomLeft();
diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp
index e5a68d4058686f9d273dd1e409719c94061ac2fc..c33bcbbeff7fc8accdb3e923f63e4ed7fb6867cc 100644
--- a/tests/manual/cplusplus/main.cpp
+++ b/tests/manual/cplusplus/main.cpp
@@ -37,13 +37,19 @@
 #include <Scope.h>
 #include <Semantic.h>
 #include <TranslationUnit.h>
+#include <PrettyPrinter.h>
 
-#include <QtCore/QFile>
-#include <QtCore/QList>
+#include <QFile>
+#include <QList>
+#include <QCoreApplication>
+#include <QStringList>
+#include <QFileInfo>
 #include <QtDebug>
 
 #include <cstdio>
 #include <cstdlib>
+#include <iostream>
+#include <sstream>
 
 class Rewrite
 {
@@ -119,6 +125,25 @@ public:
     }
 
 protected:
+    bool isEnumOrTypedefEnum(SpecifierAST *spec) {
+        if (! spec)
+            return false;
+        if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) {
+            if (tokenKind(simpleSpec->specifier_token) == T_TYPEDEF)
+                return isEnumOrTypedefEnum(spec->next);
+        }
+        return spec->asEnumSpecifier() != 0;
+    }
+    virtual bool visit(SimpleDeclarationAST *ast) {
+        if (isEnumOrTypedefEnum(ast->decl_specifier_seq)) {
+            //remove(ast->firstToken(), ast->lastToken());
+            insertTextBefore(ast->firstToken(), "/* #REF# removed ");
+            insertTextAfter(ast->lastToken() - 1, "*/");
+            return true;
+        }
+        return true;
+    }
+
     virtual bool visit(AccessDeclarationAST *ast)
     {
         if (tokenKind(ast->access_specifier_token) == T_PRIVATE) {
@@ -164,12 +189,56 @@ protected:
         if (ast->lbrace_token)
             insertTextAfter(ast->lbrace_token, " Q_OBJECT\n");
 
-        return true;
+        for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) {
+            accept(it);
+        }
+
+        return false;
+    }
+
+    virtual bool visit(CppCastExpressionAST *ast) {
+        // Replace the C++ cast expression (e.g. static_cast<foo>(a)) with
+        // the one generated by the pretty printer.
+        std::ostringstream o;
+        PrettyPrinter pp(control(), o);
+        pp(ast);
+        remove(ast->firstToken(), ast->lastToken());
+        const std::string str = o.str();
+        insertTextBefore(ast->firstToken(), str.c_str());
+        insertTextBefore(ast->firstToken(), "/* #REF# beautiful cast */ ");
+        return false;
     }
 };
 
-int main(int, char *[])
+int main(int argc, char *argv[])
 {
+    QCoreApplication app(argc, argv);
+
+    QStringList args = app.arguments();
+    const QString appName = args.first();
+    args.removeFirst();
+
+    bool test_rewriter = false;
+    bool test_pretty_printer = false;
+
+    foreach (QString arg, args) {
+        if (arg == QLatin1String("--test-rewriter"))
+            test_rewriter = true;
+        else if (arg == QLatin1String("--test-pretty-printer"))
+            test_pretty_printer = true;
+        else if (arg == QLatin1String("--help")) {
+            const QFileInfo appInfo(appName);
+            const QByteArray appFileName = QFile::encodeName(appInfo.fileName());
+
+            printf("Usage: %s [options]\n"
+                   "  --help                    Display this information\n"
+                   "  --test-rewriter           Test the tree rewriter\n"
+                   "  --test-pretty-printer     Test the pretty printer\n",
+                   appFileName.constData());
+            return EXIT_SUCCESS;
+        }
+    }
+
     QFile in;
     if (! in.open(stdin, QFile::ReadOnly))
         return EXIT_FAILURE;
@@ -194,10 +263,14 @@ int main(int, char *[])
     }
 
     // test the rewriter
-    QByteArray out;
-    SimpleRefactor refactor(&control);
-    refactor(&unit, source, &out);
-    printf("%s\n", out.constData());
-
+    if (test_rewriter) {
+        QByteArray out;
+        SimpleRefactor refactor(&control);
+        refactor(&unit, source, &out);
+        printf("%s\n", out.constData());
+    } else if (test_pretty_printer) {
+        PrettyPrinter pp(&control, std::cout);
+        pp(unit.ast());
+    }
     return EXIT_SUCCESS;
 }
diff --git a/tests/manual/cplusplus/test-pretty-printer b/tests/manual/cplusplus/test-pretty-printer
new file mode 100755
index 0000000000000000000000000000000000000000..7403721300eddd0440cf5dc632eb0aefd7b34fbc
--- /dev/null
+++ b/tests/manual/cplusplus/test-pretty-printer
@@ -0,0 +1,3 @@
+#!/bin/sh
+me=$(dirname $0)
+${CPP-gcc} -xc++ -E -include $me/conf.c++ $* | $me/cplusplus0 --test-pretty-printer
diff --git a/tests/manual/cplusplus/test-rewriter b/tests/manual/cplusplus/test-rewriter
new file mode 100755
index 0000000000000000000000000000000000000000..c0494257c8f5a81cb382ac603bb4c84edc3b8055
--- /dev/null
+++ b/tests/manual/cplusplus/test-rewriter
@@ -0,0 +1,3 @@
+#!/bin/sh
+me=$(dirname $0)
+${CPP-gcc} -xc++ -E -include $me/conf.c++ $* | $me/cplusplus0 --test-rewriter
diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c489dd3b072fa8c4f29e2cb6bd1766e40adae565
--- /dev/null
+++ b/tests/manual/cplusplus/tests/t1.cpp
@@ -0,0 +1,56 @@
+
+class Class {
+  int a, b;
+
+  enum zoo { a = 1, b = a + 2 + x::y<10>::value };
+
+  enum {};
+
+  typedef enum { k };
+
+  void foo() {}
+  inline void bar() {}
+
+  void another_foo() {
+    int a = static_cast<int>(1+2/3*4-5%6+(7&8));
+  }
+
+  void test_if() {
+    if (a == 10) return 1;
+    else if (b == 20) return 2;
+    else if (c == 30) { x = 1; }
+  }
+
+  void test_while() {
+    while (int a = 1) {
+      exit();
+    }
+
+    while (x==1) do_something_here();
+
+    while (x==2) if(a==1) c(); else if (a==2) c(); else c3();
+  }
+
+  void test_switch() {
+    switch (int k = 1) {
+    case 'a': case 'b': case '\\':
+      return 1;
+    case 1|2: { return 3; } break;
+    case x: break;
+    case y:
+      foo();
+      break;
+    default:
+      return 2;
+    }
+    s = L"ci\"aa\"ao" L"blah!";
+    s2 = "ciao \"ciao\" ciao";
+  }
+};
+
+class Derived: public Class {
+  operator bool() const volatile throw () { return 1; }
+  Derived &operator++() {}
+};
+
+class Derived2: public Class, public virtual Derived {};
diff --git a/tests/manual/fakevim/fakevim.pro b/tests/manual/fakevim/fakevim.pro
new file mode 100644
index 0000000000000000000000000000000000000000..ed3046b76c9d110aaaa89196878a54adf73d2758
--- /dev/null
+++ b/tests/manual/fakevim/fakevim.pro
@@ -0,0 +1,11 @@
+
+FAKEVIMHOME = ../../../src/plugins/fakevim
+
+SOURCES += \
+	main.cpp \
+	$$FAKEVIMHOME/handler.cpp
+
+HEADERS += \
+	$$FAKEVIMHOME/handler.h
+
+INCLUDEPATH += $$FAKEVIMHOME
diff --git a/tests/manual/fakevim/main.cpp b/tests/manual/fakevim/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8c504a62a81b353fe92683f375e9e909ba4909dd
--- /dev/null
+++ b/tests/manual/fakevim/main.cpp
@@ -0,0 +1,63 @@
+
+#include "handler.h"
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QStatusBar>
+#include <QtGui/QTextEdit>
+
+using namespace FakeVim::Internal;
+
+int main(int argc, char *argv[])
+{
+    QApplication app(argc, argv);
+
+    QStringList args = app.arguments();
+    (void) args.takeFirst();
+
+    QWidget *widget = 0;
+    QString title;
+    bool usePlainTextEdit = args.size() < 2;
+    if (usePlainTextEdit) {
+        widget = new QPlainTextEdit;
+        title = "PlainTextEdit";
+    } else {
+        widget = new QTextEdit;
+        title = "TextEdit";
+    }
+    widget->resize(450, 350);
+    widget->setFocus();
+
+
+    FakeVimHandler fakeVim;
+
+    QMainWindow mw;
+    mw.setWindowTitle("Fakevim (" + title + ")");
+    mw.setCentralWidget(widget);
+    mw.resize(500, 650);
+    mw.move(0, 0);
+    mw.show();
+    
+    QFont font = widget->font();
+    //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
+    //font.setFamily("Misc");
+    font.setFamily("Monospace");
+    //font.setStretch(QFont::SemiCondensed);
+
+    widget->setFont(font);
+    mw.statusBar()->setFont(font);
+
+    QObject::connect(&fakeVim, SIGNAL(commandBufferChanged(QString)),
+        mw.statusBar(), SLOT(showMessage(QString)));
+    QObject::connect(&fakeVim, SIGNAL(quitRequested(QWidget *)),
+        &app, SLOT(quit()));
+
+    fakeVim.addWidget(widget);
+    if (args.size() >= 1)
+        fakeVim.handleCommand(widget, "r " + args.at(0));
+
+    return app.exec();
+}
diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index 3243e9c70e2c3b50d959fe7751b28108d414172b..33c8836029b0fedaf971d85b3aca46d36d1c2191 100644
--- a/tests/manual/gdbdebugger/simple/app.cpp
+++ b/tests/manual/gdbdebugger/simple/app.cpp
@@ -289,6 +289,36 @@ void testQMap()
 #endif
 }
 
+void testQMultiMap()
+{
+    QMultiMap<uint, float> gg0;
+    gg0.insert(11, 11.0);
+    gg0.insert(22, 22.0);
+    gg0.insert(22, 33.0);
+    gg0.insert(22, 34.0);
+    gg0.insert(22, 35.0);
+    gg0.insert(22, 36.0);
+#if 1
+    QMultiMap<QString, float> gg1;
+    gg1.insert("22.0", 22.0);
+
+    QMultiMap<int, QString> gg2;
+    gg2.insert(22, "22.0");
+
+    QMultiMap<QString, Foo> gg3;
+    gg3.insert("22.0", Foo(22));
+    gg3.insert("33.0", Foo(33));
+    gg3.insert("22.0", Foo(22));
+
+    QObject ob;
+    QMultiMap<QString, QPointer<QObject> > map;
+    map.insert("Hallo", QPointer<QObject>(&ob));
+    map.insert("Welt", QPointer<QObject>(&ob));
+    map.insert(".", QPointer<QObject>(&ob));
+    map.insert(".", QPointer<QObject>(&ob));
+#endif
+}
+
 void testQObject(int &argc, char *argv[])
 {
     QApplication app(argc, argv);
@@ -856,6 +886,7 @@ int main(int argc, char *argv[])
     testQHash();
     testQImage();
     testQMap();
+    testQMultiMap();
     testQString();
     testQSet();
     testQStringList();