diff --git a/.gitignore b/.gitignore index f140cb47ca6..3ced6e0c35d 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 0802d54a70a..2af0e4b2301 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1123,8 +1124,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); @@ -1265,6 +1266,48 @@ static void qDumpQList(QDumper &d) d.disarm(); } +static void qDumpQLinkedList(QDumper &d) +{ + // This uses the knowledge that QLinkedList has only a single member + // of type union { QLinkedListData *d; QLinkedListNode *e; }; + const QLinkedListData *ldata = + reinterpret_cast(deref(d.data)); + int nn = ldata->size; + if (nn < 0) + qCheck(false); + + int n = nn; + P(d, "value", "<" << n << " items>"); + P(d, "valuedisabled", "true"); + P(d, "numchild", n); + P(d, "childtype", d.innertype); + if (d.dumpChildren) { + unsigned innerSize = d.extraInt[0]; + bool innerTypeIsPointer = isPointerType(d.innertype); + QByteArray strippedInnerType = stripPointerType(d.innertype); + const char *stripped = + isPointerType(d.innertype) ? strippedInnerType.data() : 0; + + P(d, "childtype", d.innertype); + if (n > 1000) + n = 1000; + d << ",children=["; + const void *p = deref(ldata); + for (int i = 0; i != n; ++i) { + d.beginHash(); + P(d, "name", "[" << i << "]"); + const void *addr = addOffset(p, 2 * sizeof(void*)); + qDumpInnerValueOrPointer(d, d.innertype, stripped, addr); + p = deref(p); + d.endHash(); + } + if (n < nn) + d.putEllipsis(); + d << "]"; + } + d.disarm(); +} + static void qDumpQLocale(QDumper &d) { const QLocale &locale = *reinterpret_cast(d.data); @@ -1310,6 +1353,42 @@ static void qDumpQLocale(QDumper &d) d.disarm(); } +static void qDumpQMapNode(QDumper &d) +{ + const QMapData *h = reinterpret_cast(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(d.data); @@ -1355,26 +1434,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'*)0x616658)) +#else + P(d, "type", NS"QMapData::Node<" + << keyType << "," << valueType << " >"); + P(d, "exp", "*('"NS"QMapData::Node<" + << keyType << "," << valueType << " >'*)" << node); +#endif } d.endHash(); @@ -1387,6 +1472,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(d.data); @@ -1431,42 +1521,6 @@ static void qDumpQModelIndex(QDumper &d) d.disarm(); } -static void qDumpQMapNode(QDumper &d) -{ - const QMapData *h = reinterpret_cast(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(d.data); @@ -2345,6 +2399,8 @@ static void handleProtocolVersion2and3(QDumper & d) case 'L': if (isEqual(type, "QList")) qDumpQList(d); + else if (isEqual(type, "QLinkedList")) + qDumpQLinkedList(d); else if (isEqual(type, "QLocale")) qDumpQLocale(d); break; @@ -2355,6 +2411,8 @@ static void handleProtocolVersion2and3(QDumper & d) qDumpQMapNode(d); else if (isEqual(type, "QModelIndex")) qDumpQModelIndex(d); + else if (isEqual(type, "QMultiMap")) + qDumpQMultiMap(d); break; case 'O': if (isEqual(type, "QObject")) @@ -2452,10 +2510,15 @@ void qDumpObjectData440( "\""NS"QHash\"," "\""NS"QHashNode\"," "\""NS"QImage\"," + "\""NS"QLinkedList\"," + "\""NS"QList\"," "\""NS"QLocale\"," "\""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\"," @@ -2465,6 +2528,7 @@ void qDumpObjectData440( "\""NS"QObjectSlot\"," "\""NS"QObjectSlotList\"," #endif // PRIVATE_OBJECT_ALLOWED + // << "\""NS"QRegion\"," "\""NS"QSet\"," "\""NS"QString\"," "\""NS"QStringList\"," @@ -2480,8 +2544,11 @@ void qDumpObjectData440( "\"std::string\"," "\"std::vector\"," "\"std::wstring\"," - // << "\""NS"QRegion\"," "]"; + 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 00000000000..400ee71168c --- /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 00000000000..5ac78d98069 --- /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 7a82c2aac6f..92c40b8a388 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 -macro.br.HTML = "
" -macro.QD = "\\e{Qt Designer}" -macro.QA = "\\e{Qt Assistant}" -macro.eacute.HTML = "é" +## 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 = "å" +macro.Auml.HTML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.HTML = "
" +macro.BR.HTML = "
" +macro.aacute.HTML = "á" +macro.eacute.HTML = "é" +macro.iacute.HTML = "í" +macro.gui = "\\bold" +macro.hr.HTML = "
" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" macro.oslash.HTML = "ø" macro.ouml.HTML = "ö" -macro.Auml.HTML = "Ä" -macro.uuml.HTML = "ü" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.param = "\\e" +macro.raisedaster.HTML = "*" +macro.reg.HTML = "®" +macro.return = "Returns" macro.starslash = "\\c{*/}" +macro.uuml.HTML = "ü" +macro.mdash.HTML = "—" +## 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 = "\n" \ "\n" \ "\n" \ "" \ "\n" \ - "
" \ - "" \ + "" \ "  " \ "" \ "Home ·" \ + " " \ + "All Namespaces ·" \ " " \ "All Classes ·" \ - " " \ - "All Interfaces ·" \ + " " \ + "Main Classes ·" \ + " " \ + "Grouped Classes ·" \ + " " \ + "Modules ·" \ " " \ "Functions" \ "
" + "" HTML.footer = "


\n" \ "\n" \ - "\n" \ + "\n" \ "\n" \ "\n" \ "
Copyright © \$THISYEAR\$ TrolltechCopyright © %THISYEAR% Nokia Corporation " \ + "and/or its subsidiary(-ies)Trademarks
Qt \\version
" + +## 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 5d58a28c3e6..cb800823ec4 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 8337190b227..00000000000 --- 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 8733e749a08..00000000000 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 033b1ae7d4b..00000000000 --- 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 57aed144307..00000000000 --- a/installer/TODO.txt +++ /dev/null @@ -1,12 +0,0 @@ - -- installdir whitespace check done. -- installdir exist/non-empty check - - -- run '/bin/xdg-desktop-install.sh' if '/usr/bin/xdg-mime exists' -- desktop shortcut - - -- create dir '${env(APPDATA)}/Trolltech' -- start menue shortcuts - diff --git a/installer/installer.cpp b/installer/installer.cpp deleted file mode 100644 index 013d26d2b88..00000000000 --- 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 -#include -#include - -#include -#include -#include -#include -#include - - -// 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=' 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=' 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=' 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=]\n" - "\n Creates the %1 installer.\n").arg(productName); - else if (installer.isInstaller()) - str = QString(" [--no-gui] [=...]\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(" [=...]\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 d9e59651ded..00000000000 --- 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 5080febcd64..00000000000 --- a/installer/installer.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - resources/logo.png - resources/watermark.png - resources/license.txt - - diff --git a/installer/qinstaller.cpp b/installer/qinstaller.cpp deleted file mode 100644 index be72b66b2f4..00000000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include "qt_windows.h" -#include -#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: -// ... -// $comptask[0]: -// $comptask[0][0]: -// ... -// $comptask[0][$ctc0-1]: -// ... -// $comptask[$ncomp-1]: -// $comptask[$ncomp-1][0]: -// ... -// $comtaskp[$ncomp-1][$ctc-1]: -// $compvars[0]: -// ... -// $compvars[$ncomp-1]: -// $comptaskoffsets: -// -// ... -// $compvarsoffsets: -// -// ... -// $installervars: -// ... -// end - 7: -// end - 6: -// end - 5: -// end - 4: -// end - 3: -// end - 2: -// end - 1: -// -// 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 -{ -public: - typedef QHash 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 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 *copyTasks, - QList *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 *copyTasks, - QList *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 copyTasks; - QList linkTasks; - QString sourcePath = d->m_installer->replaceVariables(sourcePath0); - listDir(sourcePath, targetPath, ©Tasks, &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 &tasks); - void writeUninstaller(const QList &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 m_components; - QList 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 tasksOffsets; - QList 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 &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 &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 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 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 ea3a97f8d51..00000000000 --- 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 - -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 ca2c6d73c04..00000000000 --- 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -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(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(siblingName); - QWidget *parent = sibling ? sibling->parentWidget() : 0; - QLayout *layout = parent ? parent->layout() : 0; - QBoxLayout *blayout = qobject_cast(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(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 ec7db64677c..00000000000 --- 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 - -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 a55990fe3a0..00000000000 --- 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 8a9562614b2..00000000000 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 b07780d9d04..00000000000 Binary files a/installer/resources/watermark.png and /dev/null differ diff --git a/qtcreator.pro b/qtcreator.pro index 6c5d876731c..bde9c816c7c 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -10,3 +10,5 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS = src + +include(doc/doc.pri) diff --git a/scripts/snapshots/cleanup_snapshots.sh b/scripts/snapshots/cleanup_snapshots.sh index f239cc1af0e..db283edd441 100755 --- a/scripts/snapshots/cleanup_snapshots.sh +++ b/scripts/snapshots/cleanup_snapshots.sh @@ -2,8 +2,8 @@ ## Open script-dir-homed subshell ( -ABS_SCRIPT_DIR=`pwd`/`dirname "$0"` -cd "${ABS_SCRIPT_DIR}" +ABS_SCRIPT_DIR=$(cd $(dirname $(which "$0")) && pwd) +cd "${ABS_SCRIPT_DIR}" || exit 1 ## Internal config diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 248ed13a027..d112f9ab537 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -381,15 +381,6 @@ UsingDirectiveAST *AST::asUsingDirective() WhileStatementAST *AST::asWhileStatement() { return dynamic_cast(this); } -void *AST::operator new(size_t size, MemoryPool *pool) -{ return pool->allocate(size); } - -void AST::operator delete(void *) -{ } - -void AST::operator delete(void *, MemoryPool *) -{ } - void AST::accept(ASTVisitor *visitor) { if (visitor->preVisit(this)) @@ -404,14 +395,30 @@ unsigned AttributeSpecifierAST::firstToken() const unsigned AttributeSpecifierAST::lastToken() const { - assert(0 && "review me"); if (second_rparen_token) return second_rparen_token + 1; else if (first_rparen_token) return first_rparen_token + 1; else if (attributes) return attributes->lastToken(); - return second_lparen_token + 1; + else if (second_lparen_token) + return second_lparen_token + 1; + else if (first_lparen_token) + return first_lparen_token + 1; + 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) @@ -429,14 +436,39 @@ unsigned AttributeAST::firstToken() const unsigned AttributeAST::lastToken() const { - assert(0 && "review me"); - if (expression_list) - return expression_list->lastToken(); - else if (tag_token) + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; + it->expression && it->next; it = it->next) { + if (! it->next && it->expression) { + return it->expression->lastToken(); + } + } + + if (tag_token) return tag_token + 1; + + if (lparen_token) + return lparen_token + 1; + 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)) { @@ -445,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)) { @@ -458,8 +499,21 @@ unsigned AccessDeclarationAST::firstToken() const unsigned AccessDeclarationAST::lastToken() const { - assert(0 && "review me"); - return colon_token + 1; + if (colon_token) + return colon_token + 1; + else if (slots_token) + return slots_token + 1; + 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) @@ -476,8 +530,21 @@ unsigned ArrayAccessAST::firstToken() const unsigned ArrayAccessAST::lastToken() const { - assert(0 && "review me"); - return rbracket_token + 1; + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + 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) @@ -494,15 +561,27 @@ unsigned ArrayDeclaratorAST::firstToken() const unsigned ArrayDeclaratorAST::lastToken() const { - assert(0 && "review me"); - return rbracket_token + 1; + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + 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); } } @@ -514,8 +593,27 @@ unsigned ArrayInitializerAST::firstToken() const unsigned ArrayInitializerAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + 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) @@ -534,8 +632,30 @@ unsigned AsmDefinitionAST::firstToken() const unsigned AsmDefinitionAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (lparen_token) + return lparen_token + 1; + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + 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) @@ -554,8 +674,16 @@ unsigned BaseSpecifierAST::firstToken() const unsigned BaseSpecifierAST::lastToken() const { - assert(0 && "review me"); - return name->lastToken(); + if (name) + return name->lastToken(); + else if (token_virtual && token_access_specifier) + return std::min(token_virtual, token_access_specifier) + 1; + else if (token_virtual) + return token_virtual + 1; + else if (token_access_specifier) + return token_access_specifier + 1; + // assert? + return 0; } unsigned QtMethodAST::firstToken() const @@ -563,8 +691,24 @@ unsigned QtMethodAST::firstToken() const unsigned QtMethodAST::lastToken() const { - assert(0 && "review me"); - return rparen_token; + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + else if (lparen_token) + return lparen_token + 1; + 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) @@ -574,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)) { @@ -589,8 +744,18 @@ unsigned BinaryExpressionAST::firstToken() const unsigned BinaryExpressionAST::lastToken() const { - assert(0 && "review me"); - return right_expression->lastToken(); + if (right_expression) + return right_expression->lastToken(); + else if (binary_op_token) + return binary_op_token + 1; + 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) @@ -606,10 +771,17 @@ unsigned BoolLiteralAST::firstToken() const unsigned BoolLiteralAST::lastToken() const { - assert(0 && "review me"); 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)) { @@ -623,8 +795,19 @@ unsigned BreakStatementAST::firstToken() const unsigned BreakStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + 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) @@ -643,8 +826,25 @@ unsigned CallAST::firstToken() const unsigned CallAST::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 && it->expression) + return it->expression->lastToken(); + } + 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) @@ -660,10 +860,25 @@ unsigned CaseStatementAST::firstToken() const unsigned CaseStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + else if (expression) + return expression->lastToken(); + 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) @@ -679,8 +894,28 @@ unsigned CastExpressionAST::firstToken() const unsigned CastExpressionAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + if (expression) + return expression->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (type_id) + return type_id->lastToken(); + 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) @@ -698,10 +933,36 @@ unsigned CatchClauseAST::firstToken() const unsigned CatchClauseAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + for (DeclarationAST *it = exception_declaration; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (lparen_token) + return lparen_token + 1; + + 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) @@ -724,8 +985,44 @@ unsigned ClassSpecifierAST::firstToken() const unsigned ClassSpecifierAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = member_specifiers; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + + for (BaseSpecifierAST *it = base_clause; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (colon_token) + return colon_token + 1; + + if (name) + return name->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + 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) @@ -743,8 +1040,25 @@ unsigned CompoundStatementAST::firstToken() const unsigned CompoundStatementAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (StatementAST *it = statements; it ; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + 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) @@ -760,13 +1074,36 @@ unsigned ConditionAST::firstToken() const { if (type_specifier) return type_specifier->firstToken(); + return declarator->firstToken(); } unsigned ConditionAST::lastToken() const { - assert(0 && "review me"); - return declarator->lastToken(); + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert? + 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) @@ -785,10 +1122,26 @@ unsigned ConditionalExpressionAST::firstToken() const unsigned ConditionalExpressionAST::lastToken() const { - assert(0 && "review me"); if (right_expression) return right_expression->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + else if (left_expression) + return left_expression->lastToken(); + else if (question_token) + return question_token + 1; + else if (condition) + return condition->lastToken(); + // ### assert? + 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) @@ -804,8 +1157,20 @@ unsigned ContinueStatementAST::firstToken() const unsigned ContinueStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + 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) @@ -826,19 +1191,34 @@ unsigned ConversionFunctionIdAST::firstToken() const unsigned ConversionFunctionIdAST::lastToken() const { - assert(0 && "review me"); -#if 0 // ### implement me - for (DeclaratorAST *ptr_op = ptr_operators; ptr_op; - ptr_op = ptr_op->next) { - if (! ptr_op->next) - return ptr_op->lastToken(); + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); } -#endif - if (type_specifier) - return type_specifier->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + 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)) { @@ -854,8 +1234,28 @@ unsigned CppCastExpressionAST::firstToken() const unsigned CppCastExpressionAST::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; + else if (greater_token) + return greater_token + 1; + else if (type_id) + return type_id->lastToken(); + else if (less_token) + return less_token + 1; + 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) @@ -874,14 +1274,29 @@ unsigned CtorInitializerAST::firstToken() const unsigned CtorInitializerAST::lastToken() const { - assert(0 && "review me"); - for (MemInitializerAST *it = member_initializers; it; - it = it->next) + for (MemInitializerAST *it = member_initializers; it; it = it->next) { if (! it->next) return it->lastToken(); + } 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)) { @@ -905,25 +1320,49 @@ unsigned DeclaratorAST::firstToken() const return core_declarator->firstToken(); else if (postfix_declarators) return postfix_declarators->firstToken(); + else if (attributes) + return attributes->firstToken(); + else if (initializer) + return initializer->firstToken(); + // ### assert? return 0; } unsigned DeclaratorAST::lastToken() const { - assert(0 && "review me"); - for (PostfixDeclaratorAST *fx = postfix_declarators; fx; fx = fx->next) { - if (! fx->next) - return fx->lastToken(); + if (initializer) + return initializer->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); } + + for (PostfixDeclaratorAST *it = postfix_declarators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (core_declarator) return core_declarator->lastToken(); - for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; ptr_op = ptr_op->next) { - if (! ptr_op->next) - return ptr_op->lastToken(); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); } + + // ### assert? 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)) { @@ -938,10 +1377,17 @@ unsigned DeclarationStatementAST::firstToken() const unsigned DeclarationStatementAST::lastToken() const { - assert(0 && "review me"); 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)) { @@ -956,10 +1402,19 @@ unsigned DeclaratorIdAST::firstToken() const unsigned DeclaratorIdAST::lastToken() const { - assert(0 && "review me"); 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)) { @@ -975,7 +1430,6 @@ unsigned DeclaratorListAST::firstToken() const unsigned DeclaratorListAST::lastToken() const { - assert(0 && "review me"); for (const DeclaratorListAST *it = this; it; it = it->next) { if (! it->next) return it->lastToken(); @@ -983,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)) { @@ -999,12 +1465,23 @@ unsigned DeleteExpressionAST::firstToken() const unsigned DeleteExpressionAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); else if (rbracket_token) return rbracket_token + 1; - return delete_token + 1; + else if (lbracket_token) + return lbracket_token + 1; + else if (delete_token) + return delete_token + 1; + 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) @@ -1020,8 +1497,24 @@ unsigned DestructorNameAST::firstToken() const unsigned DestructorNameAST::lastToken() const { - assert(0 && "review me"); - return identifier_token + 1; + if (identifier_token) + return identifier_token + 1; + 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) @@ -1039,8 +1532,28 @@ unsigned DoStatementAST::firstToken() const unsigned DoStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else if (while_token) + return while_token + 1; + else if (statement) + return statement->lastToken(); + 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) @@ -1057,12 +1570,18 @@ unsigned ElaboratedTypeSpecifierAST::firstToken() const unsigned ElaboratedTypeSpecifierAST::lastToken() const { - assert(0 && "review me"); if (name) return name->lastToken(); 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)) { @@ -1076,10 +1595,22 @@ unsigned EmptyDeclarationAST::firstToken() const unsigned EmptyDeclarationAST::lastToken() const { - assert(0 && "review me"); 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)) { @@ -1097,8 +1628,32 @@ unsigned EnumSpecifierAST::firstToken() const unsigned EnumSpecifierAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (EnumeratorAST *it = enumerators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + if (name) + return name->lastToken(); + + 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) @@ -1115,14 +1670,24 @@ unsigned EnumeratorAST::firstToken() const unsigned EnumeratorAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); - if (equal_token) + else if (equal_token) return equal_token + 1; 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)) { @@ -1134,23 +1699,38 @@ void ExceptionDeclarationAST::accept0(ASTVisitor *visitor) unsigned ExceptionDeclarationAST::firstToken() const { - return type_specifier->firstToken(); + if (type_specifier) + return type_specifier->firstToken(); + if (declarator) + return declarator->firstToken(); + return dot_dot_dot_token; } unsigned ExceptionDeclarationAST::lastToken() const { - assert(0 && "review me"); if (dot_dot_dot_token) return dot_dot_dot_token + 1; else if (declarator) return declarator->lastToken(); for (SpecifierAST *it = type_specifier; it; it = it->next) { if (! it->next) - return type_specifier->lastToken(); + return it->lastToken(); } 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)) { @@ -1167,12 +1747,38 @@ unsigned ExceptionSpecificationAST::firstToken() const unsigned ExceptionSpecificationAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = type_ids; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + if (dot_dot_dot_token) + return dot_dot_dot_token + 1; + else if (lparen_token) + return lparen_token + 1; + + 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 { @@ -1181,7 +1787,6 @@ unsigned ExpressionListAST::firstToken() const unsigned ExpressionListAST::lastToken() const { - assert(0 && "review me"); for (const ExpressionListAST *it = this; it; it = it->next) { if (! it->next) return it->expression->lastToken(); @@ -1189,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)) { @@ -1199,13 +1814,21 @@ void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor) unsigned ExpressionOrDeclarationStatementAST::firstToken() const { - return expression->firstToken(); + return declaration->firstToken(); } unsigned ExpressionOrDeclarationStatementAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + 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) @@ -1224,8 +1847,30 @@ unsigned ExpressionStatementAST::firstToken() const unsigned ExpressionStatementAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + if (semicolon_token) + return semicolon_token + 1; + else if (expression) + return expression->lastToken(); + // ### assert? + 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) @@ -1245,10 +1890,36 @@ unsigned ForStatementAST::firstToken() const unsigned ForStatementAST::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 (expression) + return expression->lastToken(); + else if (semicolon_token) + return semicolon_token + 1; + else if (condition) + return condition->lastToken(); + else if (initializer) + return initializer->lastToken(); + else if (lparen_token) + return lparen_token + 1; + + 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) @@ -1264,16 +1935,34 @@ unsigned FunctionDeclaratorAST::firstToken() const unsigned FunctionDeclaratorAST::lastToken() const { - assert(0 && "review me"); if (exception_specification) return exception_specification->lastToken(); - else if (cv_qualifier_seq) { - for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { - if (! it->next) - return it->lastToken(); - } + + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); } - return rparen_token + 1; + + if (rparen_token) + return rparen_token + 1; + else if (parameters) + return parameters->lastToken(); + + 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) @@ -1301,12 +1990,29 @@ unsigned FunctionDefinitionAST::firstToken() const unsigned FunctionDefinitionAST::lastToken() const { - assert(0 && "review me"); if (function_body) return function_body->lastToken(); else if (ctor_initializer) return ctor_initializer->lastToken(); - return declarator->lastToken(); + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert + 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) @@ -1322,8 +2028,29 @@ unsigned GotoStatementAST::firstToken() const unsigned GotoStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (identifier_token) + return identifier_token + 1; + else if (goto_token) + return goto_token + 1; + 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) @@ -1342,14 +2069,29 @@ unsigned IfStatementAST::firstToken() const unsigned IfStatementAST::lastToken() const { - assert(0 && "review me"); if (else_statement) return else_statement->lastToken(); else if (else_token) return else_token + 1; else 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 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) @@ -1366,10 +2108,21 @@ unsigned LabeledStatementAST::firstToken() const unsigned LabeledStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + 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) @@ -1388,8 +2141,25 @@ unsigned LinkageBodyAST::firstToken() const unsigned LinkageBodyAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = declarations; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + 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) @@ -1406,7 +2176,6 @@ unsigned LinkageSpecificationAST::firstToken() const unsigned LinkageSpecificationAST::lastToken() const { - assert(0 && "review me"); if (declaration) return declaration->lastToken(); else if (extern_type) @@ -1414,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)) { @@ -1428,8 +2211,23 @@ unsigned MemInitializerAST::firstToken() const unsigned MemInitializerAST::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 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) @@ -1446,12 +2244,21 @@ unsigned MemberAccessAST::firstToken() const unsigned MemberAccessAST::lastToken() const { - assert(0 && "review me"); if (member_name) return member_name->lastToken(); + else if (template_token) + return template_token + 1; 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)) { @@ -1466,10 +2273,21 @@ unsigned NamedTypeSpecifierAST::firstToken() const unsigned NamedTypeSpecifierAST::lastToken() const { - assert(0 && "review me"); 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)) { @@ -1487,14 +2305,32 @@ unsigned NamespaceAST::firstToken() const unsigned NamespaceAST::lastToken() const { - assert(0 && "review me"); if (linkage_body) return linkage_body->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (identifier_token) return identifier_token + 1; + 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)) { @@ -1509,8 +2345,25 @@ unsigned NamespaceAliasDefinitionAST::firstToken() const unsigned NamespaceAliasDefinitionAST::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 (equal_token) + return equal_token + 1; + else if (namespace_name) + return namespace_name + 1; + 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) @@ -1527,8 +2380,21 @@ unsigned NestedDeclaratorAST::firstToken() const unsigned NestedDeclaratorAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + 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) @@ -1545,8 +2411,22 @@ unsigned NestedExpressionAST::firstToken() const unsigned NestedExpressionAST::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; +} + +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) @@ -1564,17 +2444,30 @@ unsigned NestedNameSpecifierAST::firstToken() const unsigned NestedNameSpecifierAST::lastToken() const { - assert(0 && "review me"); - return scope_token + 1; + if (scope_token) + return scope_token + 1; + 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(ptr_op->next)) + ptr_op = static_cast(ptr_op->next)) { accept(ptr_op, visitor); - // ### TODO accept the brackets + } + + accept(declarator, visitor); } } @@ -1585,13 +2478,33 @@ 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; } +NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const +{ + 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)) { @@ -1611,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) @@ -1620,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) @@ -1637,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) @@ -1658,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) @@ -1667,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)) { @@ -1683,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)) { @@ -1700,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)) { @@ -1720,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)) { @@ -1743,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)) { @@ -1775,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)) { @@ -1797,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(); @@ -1805,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)) { @@ -1826,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) @@ -1847,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)) { @@ -1867,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(); @@ -1875,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)) { @@ -1894,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) @@ -1915,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)) { @@ -1933,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) @@ -1949,33 +3040,38 @@ void SimpleDeclarationAST::accept0(ASTVisitor *visitor) unsigned SimpleDeclarationAST::firstToken() const { - for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { - if (! it->next) - return it->firstToken(); - } - for (DeclaratorListAST *it = declarators; it; it = it->next) { - if (! it->next) - return it->firstToken(); - } + if (decl_specifier_seq) + return decl_specifier_seq->firstToken(); + else if (declarators) + return declarators->firstToken(); 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)) { @@ -1989,7 +3085,6 @@ unsigned SimpleNameAST::firstToken() const unsigned SimpleNameAST::lastToken() const { - assert(0 && "review me"); return identifier_token + 1; } @@ -1999,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; @@ -2006,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)) { @@ -2024,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)) { @@ -2044,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)) { @@ -2064,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)) { @@ -2085,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) @@ -2106,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)) { @@ -2133,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) @@ -2155,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) @@ -2172,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) @@ -2181,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) @@ -2197,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)) { @@ -2215,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)) { @@ -2237,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(); @@ -2245,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)) { @@ -2260,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)) { @@ -2288,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) @@ -2308,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) @@ -2328,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) @@ -2349,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) @@ -2368,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) @@ -2378,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)) { @@ -2392,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)) { @@ -2412,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) @@ -2430,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) @@ -2449,10 +3853,82 @@ 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; } +// ObjC++ +unsigned IdentifierListAST::firstToken() const +{ + return identifier_token; +} + +unsigned IdentifierListAST::lastToken() const +{ + for (const IdentifierListAST *it = this; it; it = it->next) { + if (! it->next && it->identifier_token) { + return it->identifier_token + 1; + } + } + // ### assert? + return 0; +} + +IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const +{ + IdentifierListAST *ast = new (pool) IdentifierListAST; + ast->identifier_token = identifier_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void IdentifierListAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ObjCClassDeclarationAST::firstToken() const +{ + return class_token; +} + +unsigned ObjCClassDeclarationAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + + for (IdentifierListAST *it = identifier_list; it; it = it->next) { + if (! it->next && it->identifier_token) + return it->identifier_token + 1; + } + + return class_token + 1; +} + +ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const +{ + ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST; + ast->class_token = class_token; + if (identifier_list) + ast->identifier_list = identifier_list->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h index fd7cec40deb..d03cd3ff82c 100644 --- a/shared/cplusplus/AST.h +++ b/shared/cplusplus/AST.h @@ -55,12 +55,12 @@ #include "CPlusPlusForwardDeclarations.h" #include "ASTfwd.h" -#include +#include "MemoryPool.h" CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE -class CPLUSPLUS_EXPORT AST +class CPLUSPLUS_EXPORT AST: public Managed { AST(const AST &other); void operator =(const AST &other); @@ -74,10 +74,6 @@ public: static void accept(AST *ast, ASTVisitor *visitor) { if (ast) ast->accept(visitor); } - void *operator new(size_t size, MemoryPool *pool); - void operator delete(void *); - void operator delete(void *, MemoryPool *); - virtual unsigned firstToken() const = 0; virtual unsigned lastToken() const = 0; @@ -187,6 +183,8 @@ public: UsingDirectiveAST *asUsingDirective(); WhileStatementAST *asWhileStatement(); + virtual AST *clone(MemoryPool *pool) const = 0; + protected: virtual void accept0(ASTVisitor *visitor) = 0; }; @@ -195,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 @@ -206,6 +207,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual SimpleSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -224,6 +227,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual AttributeSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -242,6 +247,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual AttributeAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -256,6 +263,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypeofSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -264,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 @@ -301,6 +321,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DeclaratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -315,6 +337,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ExpressionListAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -330,6 +354,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual SimpleDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -343,6 +369,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual EmptyDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -358,6 +386,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual AccessDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -375,6 +405,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual AsmDefinitionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -391,6 +423,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual BaseSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -407,6 +441,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual QtMethodAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -414,14 +450,16 @@ protected: class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST { public: - unsigned binary_op_token; ExpressionAST *left_expression; + unsigned binary_op_token; ExpressionAST *right_expression; public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual BinaryExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -438,6 +476,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CastExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -448,6 +488,7 @@ public: unsigned classkey_token; SpecifierAST *attributes; NameAST *name; + unsigned colon_token; BaseSpecifierAST *base_clause; unsigned lbrace_token; DeclarationAST *member_specifiers; @@ -457,6 +498,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ClassSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -473,6 +516,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CaseStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -488,6 +533,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CompoundStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -502,6 +549,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ConditionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -519,6 +568,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ConditionalExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -538,6 +589,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CppCastExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -552,6 +605,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CtorInitializerAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -565,6 +620,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DeclarationStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -578,6 +635,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DeclaratorIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -593,6 +652,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NestedDeclaratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -610,6 +671,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual FunctionDeclaratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -625,6 +688,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ArrayDeclaratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -639,6 +704,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DeclaratorListAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -656,6 +723,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DeleteExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -675,6 +744,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DoStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -688,6 +759,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NamedTypeSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -702,6 +775,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ElaboratedTypeSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -719,6 +794,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual EnumSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -735,6 +812,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual EnumeratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -750,6 +829,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ExceptionDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -767,6 +848,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ExceptionSpecificationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -781,6 +864,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ExpressionOrDeclarationStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -795,6 +880,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ExpressionStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -811,6 +898,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual FunctionDefinitionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -831,6 +920,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ForStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -850,6 +941,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual IfStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -865,6 +958,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ArrayInitializerAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -880,6 +975,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual LabeledStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -895,6 +992,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual LinkageBodyAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -910,6 +1009,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual LinkageSpecificationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -927,6 +1028,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual MemInitializerAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -934,6 +1037,7 @@ protected: class CPLUSPLUS_EXPORT NameAST: public ExpressionAST { public: + virtual NameAST *clone(MemoryPool *pool) const = 0; }; class CPLUSPLUS_EXPORT NestedNameSpecifierAST: public AST @@ -947,6 +1051,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NestedNameSpecifierAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -962,6 +1068,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual QualifiedNameAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -976,6 +1084,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual OperatorFunctionIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -991,6 +1101,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ConversionFunctionIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1004,6 +1116,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual SimpleNameAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1018,6 +1132,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual DestructorNameAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1034,6 +1150,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TemplateIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1050,6 +1168,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NamespaceAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1067,6 +1187,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NamespaceAliasDefinitionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1081,6 +1203,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NewDeclaratorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1099,6 +1223,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NewExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1114,6 +1240,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NewInitializerAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1129,6 +1257,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NewTypeIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1144,6 +1274,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual OperatorAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1160,6 +1292,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ParameterDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1174,6 +1308,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ParameterDeclarationClauseAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1182,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 @@ -1195,6 +1334,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CallAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1210,6 +1351,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ArrayAccessAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1223,6 +1366,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual PostIncrDecrAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1238,6 +1383,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual MemberAccessAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1254,6 +1401,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypeidExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1271,6 +1420,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypenameCallExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1287,6 +1438,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypeConstructorCallAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1301,6 +1454,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual PostfixExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1309,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 @@ -1323,6 +1481,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual PointerToMemberAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1337,6 +1497,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual PointerAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1350,6 +1512,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ReferenceAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1364,6 +1528,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual BreakStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1378,6 +1544,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ContinueStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1393,6 +1561,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual GotoStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1408,6 +1578,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ReturnStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1422,6 +1594,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual SizeofExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1435,6 +1609,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NumericLiteralAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1448,6 +1624,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual BoolLiteralAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1461,6 +1639,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ThisExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1476,6 +1656,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual NestedExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1490,6 +1672,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual StringLiteralAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1507,6 +1691,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual SwitchStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1521,6 +1707,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TemplateArgumentListAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1539,6 +1727,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TemplateDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1553,6 +1743,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual ThrowExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1566,6 +1758,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TranslationUnitAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1581,6 +1775,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TryBlockStatementAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1599,6 +1795,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual CatchClauseAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1613,6 +1811,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypeIdAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1629,6 +1829,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TypenameTypeParameterAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1649,6 +1851,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual TemplateTypeParameterAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1663,6 +1867,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual UnaryExpressionAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1679,6 +1885,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual UsingAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1695,6 +1903,8 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual UsingDirectiveAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; @@ -1712,6 +1922,43 @@ public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; + virtual WhileStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + + +// ObjC++ +class CPLUSPLUS_EXPORT IdentifierListAST: public AST +{ +public: + unsigned identifier_token; + IdentifierListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual IdentifierListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ObjCClassDeclarationAST: public DeclarationAST +{ +public: + unsigned class_token; + IdentifierListAST *identifier_list; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCClassDeclarationAST *clone(MemoryPool *pool) const; + protected: virtual void accept0(ASTVisitor *visitor); }; diff --git a/shared/cplusplus/ASTVisitor.h b/shared/cplusplus/ASTVisitor.h index 4e1ecaefd8f..28097c14f70 100644 --- a/shared/cplusplus/ASTVisitor.h +++ b/shared/cplusplus/ASTVisitor.h @@ -185,6 +185,10 @@ public: virtual bool visit(WhileStatementAST *) { return true; } virtual bool visit(QtMethodAST *) { return true; } + // ObjC++ + virtual bool visit(IdentifierListAST *) { return true; } + virtual bool visit(ObjCClassDeclarationAST *) { return true; } + private: Control *_control; }; diff --git a/shared/cplusplus/ASTfwd.h b/shared/cplusplus/ASTfwd.h index 14beadfdd0a..79f794f629e 100644 --- a/shared/cplusplus/ASTfwd.h +++ b/shared/cplusplus/ASTfwd.h @@ -167,6 +167,10 @@ class UsingDirectiveAST; class WhileStatementAST; class QtMethodAST; +// ObjC++ +class IdentifierListAST; +class ObjCClassDeclarationAST; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/shared/cplusplus/Lexer.cpp b/shared/cplusplus/Lexer.cpp index 56098d39f24..fcc17313b43 100644 --- a/shared/cplusplus/Lexer.cpp +++ b/shared/cplusplus/Lexer.cpp @@ -122,6 +122,12 @@ bool Lexer::qtMocRunEnabled() const void Lexer::setQtMocRunEnabled(bool onoff) { _qtMocRunEnabled = onoff; } +bool Lexer::objcEnabled() const +{ return _objcEnabled; } + +void Lexer::setObjcEnabled(bool onoff) +{ _objcEnabled = onoff; } + bool Lexer::isIncremental() const { return _isIncremental; } @@ -548,8 +554,53 @@ void Lexer::scan_helper(Token *tok) break; default: { + if (_objcEnabled) { + if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') { + const char *yytext = _currentChar; + + do { + yyinp(); + if (! isalnum(_yychar)) + break; + } while (_yychar); + + const int yylen = _currentChar - yytext; + tok->kind = classifyObjCAtKeyword(yytext, yylen); + break; + } else if (ch == '@' && _yychar == '"') { + // objc @string literals + ch = _yychar; + yyinp(); + tok->kind = T_AT_STRING_LITERAL; + + const char *yytext = _currentChar; + + while (_yychar && _yychar != '"') { + if (_yychar != '\\') + yyinp(); + else { + yyinp(); // skip `\\' + + if (_yychar) + yyinp(); + } + } + // assert(_yychar == '"'); + + int yylen = _currentChar - yytext; + + if (_yychar == '"') + yyinp(); + + if (control()) + tok->string = control()->findOrInsertStringLiteral(yytext, yylen); + + break; + } + } + if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) { - // wide char literals + // wide char/string literals ch = _yychar; yyinp(); diff --git a/shared/cplusplus/Lexer.h b/shared/cplusplus/Lexer.h index d9610849ab9..84fa4107363 100644 --- a/shared/cplusplus/Lexer.h +++ b/shared/cplusplus/Lexer.h @@ -80,6 +80,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); + bool objcEnabled() const; + void setObjcEnabled(bool onoff); + void scan(Token *tok); inline void operator()(Token *tok) @@ -112,6 +115,7 @@ private: void scan_helper(Token *tok); void setSource(const char *firstChar, const char *lastChar); static int classify(const char *string, int length, bool q); + static int classifyObjCAtKeyword(const char *s, int n); static int classifyOperator(const char *string, int length); inline void yyinp() @@ -143,6 +147,7 @@ private: unsigned _scanKeywords: 1; unsigned _scanAngleStringLiteralTokens: 1; unsigned _qtMocRunEnabled: 1; + unsigned _objcEnabled: 1; }; }; unsigned _currentLine; diff --git a/shared/cplusplus/MemoryPool.cpp b/shared/cplusplus/MemoryPool.cpp index 639bb2c6164..a7c04691449 100644 --- a/shared/cplusplus/MemoryPool.cpp +++ b/shared/cplusplus/MemoryPool.cpp @@ -112,4 +112,19 @@ void *MemoryPool::allocate_helper(size_t size) return addr; } +Managed::Managed() +{ } + +Managed::~Managed() +{ } + +void *Managed::operator new(size_t size, MemoryPool *pool) +{ return pool->allocate(size); } + +void Managed::operator delete(void *) +{ } + +void Managed::operator delete(void *, MemoryPool *) +{ } + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/MemoryPool.h b/shared/cplusplus/MemoryPool.h index 8d1f09b54e8..9647b673a6e 100644 --- a/shared/cplusplus/MemoryPool.h +++ b/shared/cplusplus/MemoryPool.h @@ -55,6 +55,7 @@ #include "CPlusPlusForwardDeclarations.h" #include +#include CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE @@ -99,6 +100,20 @@ private: }; }; +class CPLUSPLUS_EXPORT Managed +{ + Managed(const Managed &other); + void operator = (const Managed &other); + +public: + Managed(); + virtual ~Managed(); + + void *operator new(size_t size, MemoryPool *pool); + void operator delete(void *); + void operator delete(void *, MemoryPool *); +}; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/shared/cplusplus/ObjectiveCAtKeywords.cpp b/shared/cplusplus/ObjectiveCAtKeywords.cpp new file mode 100644 index 00000000000..3f8fc7c396f --- /dev/null +++ b/shared/cplusplus/ObjectiveCAtKeywords.cpp @@ -0,0 +1,464 @@ +#include "Lexer.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +static inline int classify3(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'd') { + return T_AT_END; + } + } + } + else if (s[0] == 't') { + if (s[1] == 'r') { + if (s[2] == 'y') { + return T_AT_TRY; + } + } + } + return T_ERROR; +} + +static inline int classify4(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'e') { + if (s[2] == 'f') { + if (s[3] == 's') { + return T_AT_DEFS; + } + } + } + } + return T_ERROR; +} + +static inline int classify5(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'a') { + if (s[2] == 't') { + if (s[3] == 'c') { + if (s[4] == 'h') { + return T_AT_CATCH; + } + } + } + } + else if (s[1] == 'l') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 's') { + return T_AT_CLASS; + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'h') { + if (s[2] == 'r') { + if (s[3] == 'o') { + if (s[4] == 'w') { + return T_AT_THROW; + } + } + } + } + } + return T_ERROR; +} + +static inline int classify6(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'c') { + if (s[3] == 'o') { + if (s[4] == 'd') { + if (s[5] == 'e') { + return T_AT_ENCODE; + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'u') { + if (s[2] == 'b') { + if (s[3] == 'l') { + if (s[4] == 'i') { + if (s[5] == 'c') { + return T_AT_PUBLIC; + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify7(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'm') { + if (s[5] == 'i') { + if (s[6] == 'c') { + return T_AT_DYNAMIC; + } + } + } + } + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'i') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'l') { + if (s[5] == 'l') { + if (s[6] == 'y') { + return T_AT_FINALLY; + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'a') { + if (s[2] == 'c') { + if (s[3] == 'k') { + if (s[4] == 'a') { + if (s[5] == 'g') { + if (s[6] == 'e') { + return T_AT_PACKAGE; + } + } + } + } + } + } + else if (s[1] == 'r') { + if (s[2] == 'i') { + if (s[3] == 'v') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'e') { + return T_AT_PRIVATE; + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify8(const char *s) { + if (s[0] == 'o') { + if (s[1] == 'p') { + if (s[2] == 't') { + if (s[3] == 'i') { + if (s[4] == 'o') { + if (s[5] == 'n') { + if (s[6] == 'a') { + if (s[7] == 'l') { + return T_AT_OPTIONAL; + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 'p') { + if (s[4] == 'e') { + if (s[5] == 'r') { + if (s[6] == 't') { + if (s[7] == 'y') { + return T_AT_PROPERTY; + } + } + } + } + } + else if (s[3] == 't') { + if (s[4] == 'o') { + if (s[5] == 'c') { + if (s[6] == 'o') { + if (s[7] == 'l') { + return T_AT_PROTOCOL; + } + } + } + } + } + } + } + } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'q') { + if (s[3] == 'u') { + if (s[4] == 'i') { + if (s[5] == 'r') { + if (s[6] == 'e') { + if (s[7] == 'd') { + return T_AT_REQUIRED; + } + } + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'e') { + if (s[2] == 'l') { + if (s[3] == 'e') { + if (s[4] == 'c') { + if (s[5] == 't') { + if (s[6] == 'o') { + if (s[7] == 'r') { + return T_AT_SELECTOR; + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify9(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'n') { + if (s[2] == 't') { + if (s[3] == 'e') { + if (s[4] == 'r') { + if (s[5] == 'f') { + if (s[6] == 'a') { + if (s[7] == 'c') { + if (s[8] == 'e') { + return T_AT_INTERFACE; + } + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'c') { + if (s[6] == 't') { + if (s[7] == 'e') { + if (s[8] == 'd') { + return T_AT_PROTECTED; + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify10(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 't') { + if (s[4] == 'h') { + if (s[5] == 'e') { + if (s[6] == 's') { + if (s[7] == 'i') { + if (s[8] == 'z') { + if (s[9] == 'e') { + return T_AT_SYNTHESIZE; + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify11(const char *s) { + if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 't') { + if (s[3] == '_') { + if (s[4] == 'k') { + if (s[5] == 'e') { + if (s[6] == 'y') { + if (s[7] == 'w') { + if (s[8] == 'o') { + if (s[9] == 'r') { + if (s[10] == 'd') { + return T_AT_NOT_KEYWORD; + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify12(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'c') { + if (s[4] == 'h') { + if (s[5] == 'r') { + if (s[6] == 'o') { + if (s[7] == 'n') { + if (s[8] == 'i') { + if (s[9] == 'z') { + if (s[10] == 'e') { + if (s[11] == 'd') { + return T_AT_SYNCHRONIZED; + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify14(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'm') { + if (s[2] == 'p') { + if (s[3] == 'l') { + if (s[4] == 'e') { + if (s[5] == 'm') { + if (s[6] == 'e') { + if (s[7] == 'n') { + if (s[8] == 't') { + if (s[9] == 'a') { + if (s[10] == 't') { + if (s[11] == 'i') { + if (s[12] == 'o') { + if (s[13] == 'n') { + return T_AT_IMPLEMENTATION; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify19(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'm') { + if (s[3] == 'p') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'i') { + if (s[7] == 'b') { + if (s[8] == 'i') { + if (s[9] == 'l') { + if (s[10] == 'i') { + if (s[11] == 't') { + if (s[12] == 'y') { + if (s[13] == '_') { + if (s[14] == 'a') { + if (s[15] == 'l') { + if (s[16] == 'i') { + if (s[17] == 'a') { + if (s[18] == 's') { + return T_AT_COMPATIBILITY_ALIAS; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +int Lexer::classifyObjCAtKeyword(const char *s, int n) { + switch (n) { + case 3: return classify3(s); + case 4: return classify4(s); + case 5: return classify5(s); + case 6: return classify6(s); + case 7: return classify7(s); + case 8: return classify8(s); + case 9: return classify9(s); + case 10: return classify10(s); + case 11: return classify11(s); + case 12: return classify12(s); + case 14: return classify14(s); + case 19: return classify19(s); + default: return T_ERROR; + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/Parser.cpp b/shared/cplusplus/Parser.cpp index 549a74ce111..2b312b08add 100644 --- a/shared/cplusplus/Parser.cpp +++ b/shared/cplusplus/Parser.cpp @@ -395,6 +395,28 @@ bool Parser::parseDeclaration(DeclarationAST *&node) case T_EXPORT: return parseTemplateDeclaration(node); + // objc++ + case T_AT_CLASS: + return parseObjCClassDeclaration(node); + + case T_AT_INTERFACE: + return parseObjCInterfaceDeclaration(node); + + case T_AT_PROTOCOL: + return parseObjCProtocolDeclaration(node); + +// case T_AT_END: +// return parseObjCEndDeclaration(node); + + case T_AT_COMPATIBILITY_ALIAS: + return parseObjCAliasDeclaration(node); + + case T_AT_SYNTHESIZE: + return parseObjCPropertySynthesize(node); + + case T_AT_DYNAMIC: + return parseObjCPropertyDynamic(node); + default: if (LA() == T_EXTERN && LA(2) == T_TEMPLATE) return parseTemplateDeclaration(node); @@ -1196,9 +1218,12 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node) const bool previousInFunctionBody = _inFunctionBody; _inFunctionBody = false; + unsigned colon_token = 0; + if (LA() == T_COLON || LA() == T_LBRACE) { BaseSpecifierAST *base_clause = 0; if (LA() == T_COLON) { + colon_token = cursor(); parseBaseClause(base_clause); if (LA() != T_LBRACE) { _translationUnit->error(cursor(), "expected `{' before `%s'", tok().spell()); @@ -1216,6 +1241,7 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node) ast->classkey_token = classkey_token; ast->attributes = attributes; ast->name = name; + ast->colon_token = colon_token; ast->base_clause = base_clause; if (LA() == T_LBRACE) @@ -3257,4 +3283,170 @@ bool Parser::parseThrowExpression(ExpressionAST *&node) return false; } +bool Parser::parseObjCClassDeclaration(DeclarationAST *&node) +{ + if (LA() != T_AT_CLASS) + return false; + + ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; + ast->class_token = consumeToken(); + parseObjCIdentifierList(ast->identifier_list); + match(T_SEMICOLON, &ast->semicolon_token); + node = ast; + return true; +} + +bool Parser::parseObjCInterfaceDeclaration(DeclarationAST *&node) +{ + if (LA() != T_AT_INTERFACE) + return false; + + unsigned interface_token = consumeToken(); + unsigned interface_name_token = 0; + match(T_IDENTIFIER, &interface_name_token); + if (LA() == T_LPAREN) { + // category interface + unsigned lparen_token = consumeToken(); + unsigned catagory_name_token = 0; + if (LA() == T_IDENTIFIER) + catagory_name_token = consumeToken(); + unsigned rparen_token = 0; + match(T_RPAREN, &rparen_token); + parseObjCProtocolRefs(); + parseObjCClassInstanceVariables(); + parseObjCInterfaceDeclList(); + unsigned end_token = 0; + match(T_AT_END, &end_token); + return true; + } else { + // class interface + unsigned colon_token = 0; + unsigned super_class_token = 0; + if (LA() == T_COLON) { + colon_token = consumeToken(); + match(T_IDENTIFIER, &super_class_token); + } + parseObjCProtocolRefs(); + parseObjCInterfaceDeclList(); + unsigned end_token = 0; + match(T_AT_END, &end_token); + return true; + } + return false; +} + +bool Parser::parseObjCProtocolDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCEndDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCAliasDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCPropertySynthesize(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCPropertyDynamic(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCIdentifierList(IdentifierListAST *&node) +{ + if (LA() == T_IDENTIFIER) { + IdentifierListAST **it = &node; + IdentifierListAST *id = new (_pool) IdentifierListAST; + id->identifier_token = consumeToken(); + *it = id; + while (LA() == T_COMMA) { + consumeToken(); + if (LA() == T_IDENTIFIER) { + it = &(*it)->next; + IdentifierListAST *id = new (_pool) IdentifierListAST; + id->identifier_token = consumeToken(); + *it = id; + } + } + } + return false; +} + +bool Parser::parseObjCProtocolRefs() +{ + return false; +} + +bool Parser::parseObjCClassInstanceVariables() +{ + return false; +} + +bool Parser::parseObjCInterfaceDeclList() +{ + unsigned saved = cursor(); + while (LA() != T_AT_END && parseObjCInterfaceMemberDeclaration()) { + if (saved == cursor()) + consumeToken(); // skip a token + } + return true; +} + +bool Parser::parseObjCInterfaceMemberDeclaration() +{ + switch (LA()) { + case T_SEMICOLON: + consumeToken(); + return true; + + case T_AT_REQUIRED: + case T_AT_OPTIONAL: + consumeToken(); + return true; + + case T_PLUS: + case T_MINUS: + return parseObjCMethodPrototype(); + + default: { + DeclarationAST *declaration = 0; + parseDeclaration(declaration); + } // default + + } // switch + + return true; +} + +bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&ast) +{ + return false; +} + +bool Parser::parseObjCMethodPrototype() +{ + if (LA() != T_PLUS && LA() != T_MINUS) + return false; + + // instance or class method? + unsigned method_type_token = consumeToken(); + + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + return false; +} + + + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/Parser.h b/shared/cplusplus/Parser.h index 6059aa68375..1eac8ce7652 100644 --- a/shared/cplusplus/Parser.h +++ b/shared/cplusplus/Parser.h @@ -203,6 +203,24 @@ public: bool parseUsingDirective(DeclarationAST *&node); bool parseWhileStatement(StatementAST *&node); + // ObjC++ + bool parseObjCClassDeclaration(DeclarationAST *&node); + bool parseObjCInterfaceDeclaration(DeclarationAST *&node); + bool parseObjCProtocolDeclaration(DeclarationAST *&node); + bool parseObjCEndDeclaration(DeclarationAST *&node); + bool parseObjCAliasDeclaration(DeclarationAST *&node); + bool parseObjCPropertySynthesize(DeclarationAST *&node); + bool parseObjCPropertyDynamic(DeclarationAST *&node); + + bool parseObjCIdentifierList(IdentifierListAST *&node); + + bool parseObjCPropertyDeclaration(DeclarationAST *&ast); + bool parseObjCProtocolRefs(); + bool parseObjCClassInstanceVariables(); + bool parseObjCInterfaceMemberDeclaration(); + bool parseObjCInterfaceDeclList(); + bool parseObjCMethodPrototype(); + // Qt MOC run bool parseQtMethod(ExpressionAST *&node); diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp new file mode 100644 index 00000000000..72338576b6b --- /dev/null +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -0,0 +1,1283 @@ +/*************************************************************************** +** +** 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 "PrettyPrinter.h" +#include "AST.h" +#include "Token.h" +#include +#include +#include + +CPLUSPLUS_USE_NAMESPACE + +PrettyPrinter::PrettyPrinter(Control *control, std::ostream &out) + : ASTVisitor(control), + out(out), + depth(0) +{ } + +void PrettyPrinter::operator()(AST *ast) +{ accept(ast); } + +void PrettyPrinter::indent() +{ ++depth; } + +void PrettyPrinter::deindent() +{ --depth; } + +void PrettyPrinter::newline() +{ out << '\n' << std::string(depth * 4, ' '); } + +bool PrettyPrinter::visit(AccessDeclarationAST *ast) +{ + deindent(); + newline(); + out << spell(ast->access_specifier_token); + if (ast->slots_token) + out << ' ' << spell(ast->slots_token); + out << ':' << std::endl; + indent(); + return false; +} + +bool PrettyPrinter::visit(ArrayAccessAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayDeclaratorAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayInitializerAST *ast) +{ + out << '{'; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(AsmDefinitionAST *ast) +{ + out << spell(ast->asm_token); + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; + accept(it); + } + out << '('; + out << "/* ### implement me */"; + out << ");"; + return false; +} + +bool PrettyPrinter::visit(AttributeSpecifierAST *ast) +{ + out << "attribute(("; + for (AttributeAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << "))"; + return false; +} + +bool PrettyPrinter::visit(AttributeAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->lparen_token) { + out << '('; + out << spell(ast->tag_token); + if (ast->expression_list) { + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + } + out << ')'; + } + return false; +} + +bool PrettyPrinter::visit(BaseSpecifierAST *ast) +{ + if (ast->token_virtual && ast->token_access_specifier) { + 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; +} + +bool PrettyPrinter::visit(BinaryExpressionAST *ast) +{ + accept(ast->left_expression); + out << ' ' << spell(ast->binary_op_token) << ' '; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(BoolLiteralAST *ast) +{ + out << spell(ast->token); + return false; +} + +bool PrettyPrinter::visit(BreakStatementAST *) +{ + out << "break;"; + return false; +} + +bool PrettyPrinter::visit(CallAST *ast) +{ + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CaseStatementAST *ast) +{ + out << "case "; + accept(ast->expression); + out << ':'; + 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; +} + +bool PrettyPrinter::visit(CastExpressionAST *ast) +{ + out << '('; + accept(ast->type_id); + out << ')'; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(CatchClauseAST *ast) +{ + out << "catch"; + out << '('; + accept(ast->exception_declaration); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(ClassSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + out << ' '; + if (ast->attributes) { + accept(ast->attributes); + out << ' '; + } + accept(ast->name); + if (ast->colon_token) { + out << ':'; + out << ' '; + for (BaseSpecifierAST *it = ast->base_clause; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + } + newline(); + out << '{'; + if (ast->member_specifiers) { + indent(); + newline(); + if (ast->member_specifiers) { + for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(CompoundStatementAST *ast) +{ + out << '{'; + if (ast->statements) { + indent(); + newline(); + for (StatementAST *it = ast->statements; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(ConditionAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(ConditionalExpressionAST *ast) +{ + accept(ast->condition); + out << '?'; + accept(ast->left_expression); + out << ':'; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(ContinueStatementAST *) +{ + out << "continue"; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ConversionFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(CppCastExpressionAST *ast) +{ + out << spell(ast->cast_token); + out << '<'; + out << ' '; + accept(ast->type_id); + out << ' '; + out << '>'; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CtorInitializerAST *ast) +{ + out << ':'; + out << ' '; + for (MemInitializerAST *it = ast->member_initializers; it; it = it->next) { + accept(it->name); + out << '('; + accept(it->expression); + out << ')'; + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(DeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + if (ast->core_declarator) { + if (ast->ptr_operators) + out << ' '; + accept(ast->core_declarator); + } + for (PostfixDeclaratorAST *it = ast->postfix_declarators; it; it = it->next) { + accept(it); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->initializer) { + out << ' '; + out << '='; + out << ' '; + accept(ast->initializer); + } + return false; +} + +bool PrettyPrinter::visit(DeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(DeclaratorIdAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(DeclaratorListAST *ast) +{ + for (DeclaratorListAST *it = ast; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(DeleteExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "delete"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(DestructorNameAST *ast) +{ + out << '~'; + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(DoStatementAST *ast) +{ + out << "do"; + if (ast->statement) { + out << ' '; + accept(ast->statement); + } + out << "while"; + out << '('; + accept(ast->expression); + out << ')'; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ElaboratedTypeSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + return false; +} + +bool PrettyPrinter::visit(EmptyDeclarationAST *) +{ + out << ';'; + return false; +} + +bool PrettyPrinter::visit(EnumSpecifierAST *ast) +{ + out << "enum"; + if (ast->name) { + out << ' '; + accept(ast->name); + } + out << ' '; + 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; +} + +bool PrettyPrinter::visit(EnumeratorAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(ExceptionDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + accept(ast->declarator); + } + if (ast->dot_dot_dot_token) + out << "..."; + return false; +} + +bool PrettyPrinter::visit(ExceptionSpecificationAST *ast) +{ + out << "throw"; + out << '('; + if (ast->dot_dot_dot_token) + out << "..."; + else { + for (ExpressionListAST *it = ast->type_ids; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(ExpressionListAST *ast) +{ + for (ExpressionListAST *it = ast; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(ExpressionOrDeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(ExpressionStatementAST *ast) +{ + accept(ast->expression); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ForStatementAST *ast) +{ + out << "for"; + out << ' '; + out << '('; + accept(ast->initializer); + accept(ast->condition); + out << ';'; + accept(ast->expression); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(FunctionDeclaratorAST *ast) +{ + out << '('; + accept(ast->parameters); + out << ')'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; + accept(it); + } + if (ast->exception_specification) { + out << ' '; + accept(ast->exception_specification); + } + return false; +} + +bool PrettyPrinter::visit(FunctionDefinitionAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->decl_specifier_seq) + out << ' '; + accept(ast->declarator); + } + accept(ast->ctor_initializer); + newline(); + accept(ast->function_body); + if (ast->next) + newline(); // one extra line after the function definiton. + return false; +} + +bool PrettyPrinter::visit(GotoStatementAST *ast) +{ + out << "goto"; + out << ' '; + out << spell(ast->identifier_token); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(IfStatementAST *ast) +{ + out << "if"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + if (ast->statement->asCompoundStatement()) { + out << ' '; + accept(ast->statement); + } else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + if (ast->else_token) { + out << "else"; + out << ' '; + accept(ast->else_statement); + } + return false; +} + +bool PrettyPrinter::visit(LabeledStatementAST *ast) +{ + out << spell(ast->label_token); + out << ':'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(LinkageBodyAST *ast) +{ + out << '{'; + if (ast->declarations) { + indent(); + newline(); + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(LinkageSpecificationAST *ast) +{ + out << "extern"; + out << ' '; + if (ast->extern_type) { + out << '"' << spell(ast->extern_type) << '"'; + out << ' '; + } + + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(MemInitializerAST *ast) +{ + accept(ast->name); + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(MemberAccessAST *ast) +{ + out << spell(ast->access_token); + if (ast->template_token) { + out << "template"; + out << ' '; + } + accept(ast->member_name); + return false; +} + +bool PrettyPrinter::visit(NamedTypeSpecifierAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(NamespaceAST *ast) +{ + out << "namespace"; + if (ast->identifier_token) { + out << ' '; + out << spell(ast->identifier_token); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + out << ' '; + accept(it); + } + out << ' '; + accept(ast->linkage_body); + return false; +} + +bool PrettyPrinter::visit(NamespaceAliasDefinitionAST *ast) +{ + out << "namespace"; + out << ' '; + out << spell(ast->namespace_name); + out << ' '; + out << '='; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(NestedDeclaratorAST *ast) +{ + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedExpressionAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedNameSpecifierAST *ast) +{ + accept(ast->class_or_namespace_name); + if (ast->scope_token) + out << "::"; + return false; +} + +bool PrettyPrinter::visit(NewDeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) + accept(ast->declarator); + return false; +} + +bool PrettyPrinter::visit(NewExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "new"; + out << ' '; + if (ast->expression) { + accept(ast->expression); + if (ast->type_id) + out << ' '; + } + if (ast->type_id) { + accept(ast->type_id); + if (ast->new_type_id) + out << ' '; + } + if (ast->new_type_id) { + accept(ast->new_type_id); + if (ast->new_initializer) + out << ' '; + } + accept(ast->new_initializer); + return false; +} + +bool PrettyPrinter::visit(NewInitializerAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NewTypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier) + out << ' '; + if (ast->new_initializer) { + accept(ast->new_initializer); + if (ast->new_declarator) + out << ' '; + } + accept(ast->new_declarator); + return false; +} + +bool PrettyPrinter::visit(NumericLiteralAST *ast) +{ + 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; +} + +bool PrettyPrinter::visit(OperatorAST *ast) +{ + out << spell(ast->op_token); + if (ast->open_token) { + out << spell(ast->open_token); + out << spell(ast->close_token); + } + return false; +} + +bool PrettyPrinter::visit(OperatorFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + accept(ast->op); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + out << ' '; + accept(ast->declarator); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + } + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationClauseAST *ast) +{ + for (DeclarationAST *it = ast->parameter_declarations; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(PointerAST *ast) +{ + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PointerToMemberAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PostIncrDecrAST *ast) +{ + out << spell(ast->incr_decr_token); + return false; +} + +bool PrettyPrinter::visit(PostfixExpressionAST *ast) +{ + accept(ast->base_expression); + for (PostfixAST *it = ast->postfix_expressions; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(QualifiedNameAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + accept(ast->unqualified_name); + return false; +} + +bool PrettyPrinter::visit(ReferenceAST *) +{ + out << '&'; + return false; +} + +bool PrettyPrinter::visit(ReturnStatementAST *ast) +{ + out << "return"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarators) { + if (ast->decl_specifier_seq) + out << ' '; + + for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleNameAST *ast) +{ + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(SimpleSpecifierAST *ast) +{ + out << spell(ast->specifier_token); + return false; +} + +bool PrettyPrinter::visit(SizeofExpressionAST *ast) +{ + out << "sizeof"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(StringLiteralAST *ast) +{ + 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; +} + +bool PrettyPrinter::visit(SwitchStatementAST *ast) +{ + out << "switch"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(TemplateArgumentListAST *ast) +{ + for (TemplateArgumentListAST *it = ast; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(TemplateDeclarationAST *ast) +{ + if (ast->export_token) { + out << "export"; + out << ' '; + } + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + newline(); + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(TemplateIdAST *ast) +{ + out << spell(ast->identifier_token); + out << '<'; + if (ast->template_arguments) { + out << ' '; + for (TemplateArgumentListAST *it = ast->template_arguments; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + return false; +} + +bool PrettyPrinter::visit(TemplateTypeParameterAST *ast) +{ + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + out << ' '; + out << "class"; + out << ' '; + accept(ast->name); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(ThisExpressionAST *) +{ + out << "this"; + return false; +} + +bool PrettyPrinter::visit(ThrowExpressionAST *ast) +{ + out << "throw"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(TranslationUnitAST *ast) +{ + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + return false; +} + +bool PrettyPrinter::visit(TryBlockStatementAST *ast) +{ + out << "try"; + out << ' '; + accept(ast->statement); + for (CatchClauseAST *it = ast->catch_clause_seq; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(TypeConstructorCallAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier && ast->declarator) { + out << ' '; + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(TypeidExpressionAST *ast) +{ + out << "typeid"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeofSpecifierAST *ast) +{ + out << "typeof"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameCallExpressionAST *ast) +{ + out << "typename"; + out << ' '; + accept(ast->name); + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameTypeParameterAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(UnaryExpressionAST *ast) +{ + out << spell(ast->unary_op_token); + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(UsingAST *ast) +{ + out << "using"; + out << ' '; + if (ast->typename_token) { + out << "typename"; + out << ' '; + } + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(UsingDirectiveAST *ast) +{ + out << "using"; + out << ' '; + out << "namespace"; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(WhileStatementAST *ast) +{ + out << "while"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + out << ' '; + if (ast->statement && ast->statement->asCompoundStatement()) + accept(ast->statement); + else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + return false; +} + +bool PrettyPrinter::visit(QtMethodAST *ast) +{ + out << ast->method_token; + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} diff --git a/shared/cplusplus/PrettyPrinter.h b/shared/cplusplus/PrettyPrinter.h new file mode 100644 index 00000000000..966ebacd0e6 --- /dev/null +++ b/shared/cplusplus/PrettyPrinter.h @@ -0,0 +1,162 @@ +/*************************************************************************** +** +** 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 CPLUSPLUS_PRETTYPRINTER_H +#define CPLUSPLUS_PRETTYPRINTER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTVisitor.h" + +#include + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class PrettyPrinter: protected ASTVisitor +{ +public: + PrettyPrinter(Control *control, std::ostream &out); + + void operator()(AST *ast); + +protected: + virtual bool visit(AccessDeclarationAST *ast); + virtual bool visit(ArrayAccessAST *ast); + virtual bool visit(ArrayDeclaratorAST *ast); + virtual bool visit(ArrayInitializerAST *ast); + virtual bool visit(AsmDefinitionAST *ast); + virtual bool visit(AttributeSpecifierAST *ast); + virtual bool visit(AttributeAST *ast); + virtual bool visit(BaseSpecifierAST *ast); + virtual bool visit(BinaryExpressionAST *ast); + virtual bool visit(BoolLiteralAST *ast); + virtual bool visit(BreakStatementAST *ast); + virtual bool visit(CallAST *ast); + virtual bool visit(CaseStatementAST *ast); + virtual bool visit(CastExpressionAST *ast); + virtual bool visit(CatchClauseAST *ast); + virtual bool visit(ClassSpecifierAST *ast); + virtual bool visit(CompoundStatementAST *ast); + virtual bool visit(ConditionAST *ast); + virtual bool visit(ConditionalExpressionAST *ast); + virtual bool visit(ContinueStatementAST *ast); + virtual bool visit(ConversionFunctionIdAST *ast); + virtual bool visit(CppCastExpressionAST *ast); + virtual bool visit(CtorInitializerAST *ast); + virtual bool visit(DeclaratorAST *ast); + virtual bool visit(DeclarationStatementAST *ast); + virtual bool visit(DeclaratorIdAST *ast); + virtual bool visit(DeclaratorListAST *ast); + virtual bool visit(DeleteExpressionAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(DoStatementAST *ast); + virtual bool visit(ElaboratedTypeSpecifierAST *ast); + virtual bool visit(EmptyDeclarationAST *ast); + virtual bool visit(EnumSpecifierAST *ast); + virtual bool visit(EnumeratorAST *ast); + virtual bool visit(ExceptionDeclarationAST *ast); + virtual bool visit(ExceptionSpecificationAST *ast); + virtual bool visit(ExpressionListAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(ExpressionStatementAST *ast); + virtual bool visit(ForStatementAST *ast); + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(FunctionDefinitionAST *ast); + virtual bool visit(GotoStatementAST *ast); + virtual bool visit(IfStatementAST *ast); + virtual bool visit(LabeledStatementAST *ast); + virtual bool visit(LinkageBodyAST *ast); + virtual bool visit(LinkageSpecificationAST *ast); + virtual bool visit(MemInitializerAST *ast); + virtual bool visit(MemberAccessAST *ast); + virtual bool visit(NamedTypeSpecifierAST *ast); + virtual bool visit(NamespaceAST *ast); + virtual bool visit(NamespaceAliasDefinitionAST *ast); + virtual bool visit(NestedDeclaratorAST *ast); + virtual bool visit(NestedExpressionAST *ast); + virtual bool visit(NestedNameSpecifierAST *ast); + virtual bool visit(NewDeclaratorAST *ast); + virtual bool visit(NewExpressionAST *ast); + virtual bool visit(NewInitializerAST *ast); + virtual bool visit(NewTypeIdAST *ast); + virtual bool visit(NumericLiteralAST *ast); + virtual bool visit(OperatorAST *ast); + virtual bool visit(OperatorFunctionIdAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(ParameterDeclarationClauseAST *ast); + virtual bool visit(PointerAST *ast); + virtual bool visit(PointerToMemberAST *ast); + virtual bool visit(PostIncrDecrAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(ReferenceAST *ast); + virtual bool visit(ReturnStatementAST *ast); + virtual bool visit(SimpleDeclarationAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(SimpleSpecifierAST *ast); + virtual bool visit(SizeofExpressionAST *ast); + virtual bool visit(StringLiteralAST *ast); + virtual bool visit(SwitchStatementAST *ast); + virtual bool visit(TemplateArgumentListAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual bool visit(TemplateIdAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + virtual bool visit(ThisExpressionAST *ast); + virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(TranslationUnitAST *ast); + virtual bool visit(TryBlockStatementAST *ast); + virtual bool visit(TypeConstructorCallAST *ast); + virtual bool visit(TypeIdAST *ast); + virtual bool visit(TypeidExpressionAST *ast); + virtual bool visit(TypeofSpecifierAST *ast); + virtual bool visit(TypenameCallExpressionAST *ast); + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(UnaryExpressionAST *ast); + virtual bool visit(UsingAST *ast); + virtual bool visit(UsingDirectiveAST *ast); + virtual bool visit(WhileStatementAST *ast); + virtual bool visit(QtMethodAST *ast); + + void indent(); + void deindent(); + void newline(); + +private: + std::ostream &out; + unsigned depth; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_PRETTYPRINTER_H diff --git a/shared/cplusplus/Token.cpp b/shared/cplusplus/Token.cpp index c21c7b4681e..5ebd873dce2 100644 --- a/shared/cplusplus/Token.cpp +++ b/shared/cplusplus/Token.cpp @@ -62,7 +62,7 @@ static const char *token_names[] = { (""), (""), (""), (""), (""), (""), (""), - (""), + ("<@string literal>"), (""), ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"), (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"), @@ -84,8 +84,16 @@ static const char *token_names[] = { ("union"), ("unsigned"), ("using"), ("virtual"), ("void"), ("volatile"), ("wchar_t"), ("while"), + // gnu ("__attribute__"), ("__typeof__"), + // objc @keywords + ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"), + ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"), + ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"), + ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), + ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), + ("SIGNAL"), ("SLOT"), ("Q_SIGNALS"), ("Q_SLOTS") }; @@ -118,6 +126,7 @@ const char *Token::spell() const case T_FLOAT_LITERAL: case T_CHAR_LITERAL: case T_STRING_LITERAL: + case T_AT_STRING_LITERAL: case T_ANGLE_STRING_LITERAL: case T_WIDE_CHAR_LITERAL: case T_WIDE_STRING_LITERAL: diff --git a/shared/cplusplus/Token.h b/shared/cplusplus/Token.h index 826f724d2c8..d5b6f1a1c0e 100644 --- a/shared/cplusplus/Token.h +++ b/shared/cplusplus/Token.h @@ -73,6 +73,7 @@ enum Kind { T_WIDE_CHAR_LITERAL, T_STRING_LITERAL, T_WIDE_STRING_LITERAL, + T_AT_STRING_LITERAL, T_ANGLE_STRING_LITERAL, T_LAST_LITERAL = T_ANGLE_STRING_LITERAL, @@ -199,6 +200,34 @@ enum Kind { T___ATTRIBUTE__, T___TYPEOF__, + // obj c++ @ keywords + T_FIRST_OBJC_KEYWORD, + + T_AT_CATCH = T_FIRST_OBJC_KEYWORD, + T_AT_CLASS, + T_AT_COMPATIBILITY_ALIAS, + T_AT_DEFS, + T_AT_DYNAMIC, + T_AT_ENCODE, + T_AT_END, + T_AT_FINALLY, + T_AT_IMPLEMENTATION, + T_AT_INTERFACE, + T_AT_NOT_KEYWORD, + T_AT_OPTIONAL, + T_AT_PACKAGE, + T_AT_PRIVATE, + T_AT_PROPERTY, + T_AT_PROTECTED, + T_AT_PROTOCOL, + T_AT_PUBLIC, + T_AT_REQUIRED, + T_AT_SELECTOR, + T_AT_SYNCHRONIZED, + T_AT_SYNTHESIZE, + T_AT_THROW, + T_AT_TRY, + T_FIRST_QT_KEYWORD, // Qt keywords diff --git a/shared/cplusplus/cplusplus.pri b/shared/cplusplus/cplusplus.pri index 2b3bb6804d2..041aff67be2 100644 --- a/shared/cplusplus/cplusplus.pri +++ b/shared/cplusplus/cplusplus.pri @@ -35,7 +35,9 @@ HEADERS += \ $$PWD/Token.h \ $$PWD/TranslationUnit.h \ $$PWD/Type.h \ - $$PWD/TypeVisitor.h + $$PWD/TypeVisitor.h \ + $$PWD/PrettyPrinter.h + SOURCES += \ $$PWD/AST.cpp \ @@ -52,6 +54,7 @@ SOURCES += \ $$PWD/DiagnosticClient.cpp \ $$PWD/FullySpecifiedType.cpp \ $$PWD/Keywords.cpp \ + $$PWD/ObjectiveCAtKeywords.cpp \ $$PWD/Lexer.cpp \ $$PWD/LiteralTable.cpp \ $$PWD/Literals.cpp \ @@ -69,5 +72,6 @@ SOURCES += \ $$PWD/Token.cpp \ $$PWD/TranslationUnit.cpp \ $$PWD/Type.cpp \ - $$PWD/TypeVisitor.cpp + $$PWD/TypeVisitor.cpp \ + $$PWD/PrettyPrinter.cpp diff --git a/shared/designerintegrationv2/formresizer.cpp b/shared/designerintegrationv2/formresizer.cpp index 3b9644fbcaf..9e1816a9668 100644 --- a/shared/designerintegrationv2/formresizer.cpp +++ b/shared/designerintegrationv2/formresizer.cpp @@ -35,7 +35,7 @@ #include "sizehandlerect.h" #include "widgethostconstants.h" -#include +#include #include @@ -143,7 +143,7 @@ void FormResizer::setFormWindow(QDesignerFormWindowInterface *fw) if (debugFormResizer) qDebug() << "FormResizer::setFormWindow " << fw; QVBoxLayout *layout = qobject_cast(m_frame->layout()); - QTC_ASSERT(layout, return); + Q_ASSERT(layout); if (layout->count()) delete layout->takeAt(0); m_formWindow = fw; diff --git a/shared/indenter/constants.cpp b/shared/indenter/constants.cpp index 76f2f3f1d9f..9c66b8d2606 100644 --- a/shared/indenter/constants.cpp +++ b/shared/indenter/constants.cpp @@ -33,8 +33,6 @@ #include "indenter.h" -#include - using namespace SharedTools::IndenterInternal; // --- Constants @@ -59,10 +57,10 @@ Constants::Constants() : { m_literal.setMinimal(true); m_inlineCComment.setMinimal(true); - QTC_ASSERT(m_literal.isValid(), return); - QTC_ASSERT(m_label.isValid(), return); - QTC_ASSERT(m_inlineCComment.isValid(), return); - QTC_ASSERT(m_braceX.isValid(), return); - QTC_ASSERT(m_iflikeKeyword.isValid(), return); - QTC_ASSERT(m_caseLabel.isValid(), return); + Q_ASSERT(m_literal.isValid()); + Q_ASSERT(m_label.isValid()); + Q_ASSERT(m_inlineCComment.isValid()); + Q_ASSERT(m_braceX.isValid()); + Q_ASSERT(m_iflikeKeyword.isValid()); + Q_ASSERT(m_caseLabel.isValid()); } diff --git a/shared/proparser/procommandmanager.cpp b/shared/proparser/procommandmanager.cpp index b5ae09e0369..fa0df436983 100644 --- a/shared/proparser/procommandmanager.cpp +++ b/shared/proparser/procommandmanager.cpp @@ -33,8 +33,6 @@ #include "procommandmanager.h" -#include - using namespace Qt4ProjectManager::Internal; ProCommandGroup::ProCommandGroup(const QString &name) @@ -78,7 +76,7 @@ ProCommandManager::~ProCommandManager() void ProCommandManager::beginGroup(const QString &name) { - QTC_ASSERT(!m_group, return); + Q_ASSERT(!m_group); if (m_pos != m_groups.count()) { int removecount = m_groups.count() - m_pos; @@ -97,7 +95,7 @@ bool ProCommandManager::hasGroup() const void ProCommandManager::endGroup() { - QTC_ASSERT(m_group, return); + Q_ASSERT(m_group); m_groups.append(m_group); m_pos = m_groups.count(); @@ -108,7 +106,7 @@ void ProCommandManager::endGroup() bool ProCommandManager::command(ProCommand *cmd) { - QTC_ASSERT(m_group, return false); + Q_ASSERT(m_group); if (cmd->redo()) { m_group->appendCommand(cmd); diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index b7c296420af..7f029f00185 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -35,8 +35,6 @@ #include "proparserutils.h" #include "proitems.h" -#include - #include #include #include @@ -188,7 +186,7 @@ public: QString format(const char *format) const; QString currentFileName() const; - QString getcwd() const; + QString currentDirectory() const; ProFile *currentProFile() const; bool evaluateConditionalFunction(const QString &function, const QString &arguments, bool *result); @@ -530,11 +528,15 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) if (!m_skipLevel) { m_prevCondition = m_condition; m_condition = ConditionFalse; + } else { + Q_ASSERT(m_condition != ConditionTrue); } } else if (block->blockKind() & ProBlock::ScopeContentsKind) { m_updateCondition = false; if (m_condition != ConditionTrue) ++m_skipLevel; + else + Q_ASSERT(!m_skipLevel); } return true; } @@ -542,8 +544,14 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) bool ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) { if (block->blockKind() & ProBlock::ScopeContentsKind) { - if (m_skipLevel) + if (m_skipLevel) { + Q_ASSERT(m_condition != ConditionTrue); --m_skipLevel; + } else { + // Conditionals contained inside this block may have changed the state. + // So we reset it here to make an else following us do the right thing. + m_condition = ConditionTrue; + } } return true; } @@ -572,8 +580,12 @@ bool ProFileEvaluator::Private::visitProCondition(ProCondition *cond) { if (!m_skipLevel) { if (cond->text().toLower() == QLatin1String("else")) { + // The state ConditionElse makes sure that subsequential elses are ignored. + // That's braindead, but qmake is like that. if (m_prevCondition == ConditionTrue) m_condition = ConditionElse; + else if (m_prevCondition == ConditionFalse) + m_condition = ConditionTrue; } else if (m_condition == ConditionFalse) { if (isActiveConfig(cond->text(), true) ^ m_invertNext) m_condition = ConditionTrue; @@ -611,8 +623,7 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) m_cumulative = cumulative; } - QString fn = pro->fileName(); - ok = QDir::setCurrent(QFileInfo(fn).absolutePath()); + ok = QDir::setCurrent(pro->directoryName()); } return ok; @@ -759,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. } @@ -807,18 +823,20 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) { - if (!m_skipLevel && (!m_updateCondition || m_condition == ConditionFalse)) { + if (!m_updateCondition || m_condition == ConditionFalse) { QString text = func->text(); int lparen = text.indexOf(QLatin1Char('(')); int rparen = text.lastIndexOf(QLatin1Char(')')); - QTC_ASSERT(lparen < rparen, return false); + Q_ASSERT(lparen < rparen); QString arguments = text.mid(lparen + 1, rparen - lparen - 1); QString funcName = text.left(lparen); m_lineNo = func->lineNumber(); - bool result = false; - if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) + bool result; + if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) { + m_invertNext = false; return false; - if (result ^ m_invertNext) + } + if (!m_skipLevel && (result ^ m_invertNext)) m_condition = ConditionTrue; } m_invertNext = false; @@ -942,11 +960,10 @@ QString ProFileEvaluator::Private::currentFileName() const return QString(); } -QString ProFileEvaluator::Private::getcwd() const +QString ProFileEvaluator::Private::currentDirectory() const { ProFile *cur = m_profileStack.top(); - QFileInfo fi(cur->fileName()); - return fi.absolutePath(); + return cur->directoryName(); } QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str) @@ -1556,7 +1573,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } break; case 0: - q->logMessage(format("'%1' is not a function").arg(func)); + q->logMessage(format("'%1' is not a recognized replace function").arg(func)); break; default: q->logMessage(format("Function '%1' is not implemented").arg(func)); @@ -1577,26 +1594,67 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct for (int i = 0; i < argumentsList.count(); ++i) args += expandVariableReferences(argumentsList[i]).join(sep); - enum ConditionFunc { CF_CONFIG = 1, CF_CONTAINS, CF_COUNT, CF_EXISTS, CF_INCLUDE, - CF_LOAD, CF_ISEMPTY, CF_SYSTEM, CF_MESSAGE}; + enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, + T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, + T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF }; static QHash *functions = 0; if (!functions) { functions = new QHash; - functions->insert(QLatin1String("load"), CF_LOAD); //v - functions->insert(QLatin1String("include"), CF_INCLUDE); //v - functions->insert(QLatin1String("message"), CF_MESSAGE); //v - functions->insert(QLatin1String("warning"), CF_MESSAGE); //v - functions->insert(QLatin1String("error"), CF_MESSAGE); //v + functions->insert(QLatin1String("requires"), T_REQUIRES); + functions->insert(QLatin1String("greaterThan"), T_GREATERTHAN); + functions->insert(QLatin1String("lessThan"), T_LESSTHAN); + functions->insert(QLatin1String("equals"), T_EQUALS); + functions->insert(QLatin1String("isEqual"), T_EQUALS); + functions->insert(QLatin1String("exists"), T_EXISTS); + functions->insert(QLatin1String("export"), T_EXPORT); + functions->insert(QLatin1String("clear"), T_CLEAR); + functions->insert(QLatin1String("unset"), T_UNSET); + functions->insert(QLatin1String("eval"), T_EVAL); + functions->insert(QLatin1String("CONFIG"), T_CONFIG); + functions->insert(QLatin1String("if"), T_IF); + functions->insert(QLatin1String("isActiveConfig"), T_CONFIG); + functions->insert(QLatin1String("system"), T_SYSTEM); + functions->insert(QLatin1String("return"), T_RETURN); + functions->insert(QLatin1String("break"), T_BREAK); + functions->insert(QLatin1String("next"), T_NEXT); + functions->insert(QLatin1String("defined"), T_DEFINED); + functions->insert(QLatin1String("contains"), T_CONTAINS); + functions->insert(QLatin1String("infile"), T_INFILE); + functions->insert(QLatin1String("count"), T_COUNT); + functions->insert(QLatin1String("isEmpty"), T_ISEMPTY); + functions->insert(QLatin1String("load"), T_LOAD); //v + functions->insert(QLatin1String("include"), T_INCLUDE); //v + functions->insert(QLatin1String("debug"), T_DEBUG); + functions->insert(QLatin1String("message"), T_MESSAGE); //v + functions->insert(QLatin1String("warning"), T_MESSAGE); //v + functions->insert(QLatin1String("error"), T_MESSAGE); //v } bool cond = false; bool ok = true; - ConditionFunc func_t = (ConditionFunc)functions->value(function); + TestFunc func_t = (TestFunc)functions->value(function); switch (func_t) { - case CF_CONFIG: { +#if 0 + case T_INFILE: + case T_REQUIRES: + case T_GREATERTHAN: + case T_LESSTHAN: + case T_EQUALS: + case T_EXPORT: + case T_CLEAR: + case T_UNSET: + case T_EVAL: + case T_IF: + case T_RETURN: + case T_BREAK: + case T_NEXT: + case T_DEFINED: +#endif + case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { q->logMessage(format("CONFIG(config) requires one or two arguments.")); ok = false; @@ -1618,7 +1676,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_CONTAINS: { + case T_CONTAINS: { if (args.count() < 2 || args.count() > 3) { q->logMessage(format("contains(var, val) requires two or three arguments.")); ok = false; @@ -1650,9 +1708,9 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } - case CF_COUNT: { + case T_COUNT: { if (args.count() != 2 && args.count() != 3) { - q->logMessage(format("count(var, count) requires two or three arguments.")); + q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); ok = false; break; } @@ -1677,7 +1735,9 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct cond = values(args.first()).count() == args[1].toInt(); break; } - case CF_INCLUDE: { + case T_INCLUDE: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; if (args.count() == 2) { parseInto = args[1]; @@ -1688,12 +1748,14 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } QString fileName = args.first(); // ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style. - QDir currentProPath(getcwd()); + QDir currentProPath(currentDirectory()); fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName)); ok = evaluateFile(fileName, &ok); break; } - case CF_LOAD: { + case T_LOAD: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; bool ignore_error = false; if (args.count() == 2) { @@ -1707,13 +1769,16 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = evaluateFeatureFile( args.first(), &cond); break; } - case CF_MESSAGE: { + case T_DEBUG: + // Yup - do nothing. Nothing is going to enable debug output anyway. + break; + case T_MESSAGE: { if (args.count() != 1) { q->logMessage(format("%1(message) requires one argument.").arg(function)); ok = false; break; } - QString msg = args.first(); + QString msg = fixEnvVariables(args.first()); if (function == QLatin1String("error")) { QStringList parents; foreach (ProFile *proFile, m_profileStack) @@ -1730,7 +1795,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_SYSTEM: { +#if 0 // Way too dangerous to enable. + case T_SYSTEM: { if (args.count() != 1) { q->logMessage(format("system(exec) requires one argument.")); ok = false; @@ -1739,7 +1805,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = system(args.first().toLatin1().constData()) == 0; break; } - case CF_ISEMPTY: { +#endif + case T_ISEMPTY: { if (args.count() != 1) { q->logMessage(format("isEmpty(var) requires one argument.")); ok = false; @@ -1754,7 +1821,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_EXISTS: { + case T_EXISTS: { if (args.count() != 1) { q->logMessage(format("exists(file) requires one argument.")); ok = false; @@ -1768,7 +1835,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } //regular expression I guess - QString dirstr = getcwd(); + QString dirstr = currentDirectory(); int slsh = file.lastIndexOf(Option::dir_sep); if (slsh != -1) { dirstr = file.left(slsh+1); @@ -1778,6 +1845,13 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } + case 0: + // This is too chatty currently (missing defineTest and defineReplace) + //q->logMessage(format("'%1' is not a recognized test function").arg(function)); + break; + default: + q->logMessage(format("Function '%1' is not implemented").arg(function)); + break; } if (result) @@ -1800,7 +1874,7 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, return QStringList(m_outputDir); if (variableName == QLatin1String("PWD") || //current working dir (of _FILE_) variableName == QLatin1String("IN_PWD")) - return QStringList(getcwd()); + return QStringList(currentDirectory()); if (variableName == QLatin1String("DIR_SEPARATOR")) return QStringList(Option::dir_sep); if (variableName == QLatin1String("DIRLIST_SEPARATOR")) @@ -1975,7 +2049,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo break; } } - return fn.isEmpty() ? false : evaluateFile(fn, result); + if (fn.isEmpty()) + return false; + bool cumulative = m_cumulative; + m_cumulative = false; + bool ok = evaluateFile(fn, result); + m_cumulative = cumulative; + return ok; } void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, @@ -2085,14 +2165,23 @@ bool ProFileEvaluator::contains(const QString &variableName) const return d->m_valuemap.contains(variableName); } +inline QStringList fixEnvVariables(const QStringList &x) +{ + QStringList ret; + foreach (const QString &str, x) + ret << Option::fixString(str, Option::FixEnvVars); + return ret; +} + + QStringList ProFileEvaluator::values(const QString &variableName) const { - return d->values(variableName); + return fixEnvVariables(d->values(variableName)); } QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const { - return d->values(variableName, pro); + return fixEnvVariables(d->values(variableName, pro)); } ProFileEvaluator::TemplateType ProFileEvaluator::templateType() @@ -2166,20 +2255,6 @@ void ProFileEvaluator::errorMessage(const QString &message) qWarning("%s", qPrintable(message)); } -// This function is unneeded and still retained. See log message for reason. -QStringList ProFileEvaluator::absFileNames(const QString &variableName) -{ - QStringList sources_out; - QFileInfo fi(d->m_origfile); - QDir dir(fi.absoluteDir()); - foreach (const QString &fn, values(variableName)) { - const QString absName = QDir::cleanPath(dir.absoluteFilePath(fn)); - d->expandPatternHelper(fn, absName, sources_out); - } - - return sources_out; -} - void ProFileEvaluator::setVerbose(bool on) { d->m_verbose = on; diff --git a/shared/proparser/profileevaluator.h b/shared/proparser/profileevaluator.h index 14805421603..9b7b77fb0c7 100644 --- a/shared/proparser/profileevaluator.h +++ b/shared/proparser/profileevaluator.h @@ -66,8 +66,6 @@ public: ProFileEvaluator::TemplateType templateType(); virtual bool contains(const QString &variableName) const; - QStringList absFileNames(const QString &variableName); - QStringList absFileName(const QString &name); void setVerbose(bool on); // Default is false void setCumulative(bool on); // Default is true! void setOutputDir(const QString &dir); // Default is empty diff --git a/shared/proparser/proitems.cpp b/shared/proparser/proitems.cpp index 346517c0f0f..1e686c5578b 100644 --- a/shared/proparser/proitems.cpp +++ b/shared/proparser/proitems.cpp @@ -275,6 +275,7 @@ ProFile::ProFile(const QString &fileName) QFileInfo fi(fileName); m_displayFileName = fi.fileName(); + m_directoryName = fi.absolutePath(); } ProFile::~ProFile() @@ -291,6 +292,11 @@ QString ProFile::fileName() const return m_fileName; } +QString ProFile::directoryName() const +{ + return m_directoryName; +} + void ProFile::setModified(bool modified) { m_modified = modified; diff --git a/shared/proparser/proitems.h b/shared/proparser/proitems.h index a3736086e70..01ecf0f0f2d 100644 --- a/shared/proparser/proitems.h +++ b/shared/proparser/proitems.h @@ -209,6 +209,7 @@ public: QString displayFileName() const; QString fileName() const; + QString directoryName() const; void setModified(bool modified); bool isModified() const; @@ -218,6 +219,7 @@ public: private: QString m_fileName; QString m_displayFileName; + QString m_directoryName; bool m_modified; }; diff --git a/shared/proparser/proparserutils.h b/shared/proparser/proparserutils.h index daab115a447..6705ffad39f 100644 --- a/shared/proparser/proparserutils.h +++ b/shared/proparser/proparserutils.h @@ -173,7 +173,12 @@ static QStringList replaceInList(const QStringList &varList, const QRegExp ®e } */ -inline QStringList splitPathList(const QString paths) +inline QString fixEnvVariables(const QString &x) +{ + return Option::fixString(x, Option::FixEnvVars); +} + +inline QStringList splitPathList(const QString &paths) { return paths.split(Option::dirlist_sep); } diff --git a/shared/qrceditor/resourcefile.cpp b/shared/qrceditor/resourcefile.cpp index 141e9e6d4b2..a0b7117c2cf 100644 --- a/shared/qrceditor/resourcefile.cpp +++ b/shared/qrceditor/resourcefile.cpp @@ -33,8 +33,6 @@ #include "resourcefile_p.h" -#include - #include #include #include @@ -119,7 +117,7 @@ bool ResourceFile::load() } else { p = m_prefix_list[idx]; } - QTC_ASSERT(p, return false); + Q_ASSERT(p); QDomElement felt = relt.firstChildElement(QLatin1String("file")); for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) { @@ -251,7 +249,7 @@ bool ResourceFile::isEmpty() const QStringList ResourceFile::fileList(int pref_idx) const { QStringList result; - QTC_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count(), return result); + Q_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count()); const FileList &abs_file_list = m_prefix_list.at(pref_idx)->file_list; foreach (const File *abs_file, abs_file_list) result.append(relativePath(abs_file->name)); @@ -261,9 +259,9 @@ QStringList ResourceFile::fileList(int pref_idx) const void ResourceFile::addFile(int prefix_idx, const QString &file, int file_idx) { Prefix * const p = m_prefix_list[prefix_idx]; - QTC_ASSERT(p, return); + Q_ASSERT(p); FileList &files = p->file_list; - QTC_ASSERT(file_idx >= -1 && file_idx <= files.size(), return); + Q_ASSERT(file_idx >= -1 && file_idx <= files.size()); if (file_idx == -1) file_idx = files.size(); files.insert(file_idx, new File(p, absolutePath(file))); @@ -275,7 +273,7 @@ void ResourceFile::addPrefix(const QString &prefix, int prefix_idx) if (indexOfPrefix(fixed_prefix) != -1) return; - QTC_ASSERT(prefix_idx >= -1 && prefix_idx <= m_prefix_list.size(), return); + Q_ASSERT(prefix_idx >= -1 && prefix_idx <= m_prefix_list.size()); if (prefix_idx == -1) prefix_idx = m_prefix_list.size(); m_prefix_list.insert(prefix_idx, new Prefix(fixed_prefix)); @@ -283,7 +281,7 @@ void ResourceFile::addPrefix(const QString &prefix, int prefix_idx) void ResourceFile::removePrefix(int prefix_idx) { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); Prefix * const p = m_prefix_list.at(prefix_idx); delete p; m_prefix_list.removeAt(prefix_idx); @@ -291,39 +289,39 @@ void ResourceFile::removePrefix(int prefix_idx) void ResourceFile::removeFile(int prefix_idx, int file_idx) { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); FileList &fileList = m_prefix_list[prefix_idx]->file_list; - QTC_ASSERT(file_idx >= 0 && file_idx < fileList.count(), return); + Q_ASSERT(file_idx >= 0 && file_idx < fileList.count()); delete fileList.at(file_idx); fileList.removeAt(file_idx); } void ResourceFile::replacePrefix(int prefix_idx, const QString &prefix) { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); m_prefix_list[prefix_idx]->name = fixPrefix(prefix); } void ResourceFile::replaceLang(int prefix_idx, const QString &lang) { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); m_prefix_list[prefix_idx]->lang = lang; } void ResourceFile::replaceAlias(int prefix_idx, int file_idx, const QString &alias) { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); FileList &fileList = m_prefix_list.at(prefix_idx)->file_list; - QTC_ASSERT(file_idx >= 0 && file_idx < fileList.count(), return); + Q_ASSERT(file_idx >= 0 && file_idx < fileList.count()); fileList[file_idx]->alias = alias; } void ResourceFile::replaceFile(int pref_idx, int file_idx, const QString &file) { - QTC_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count(), return); + Q_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count()); FileList &fileList = m_prefix_list.at(pref_idx)->file_list; - QTC_ASSERT(file_idx >= 0 && file_idx < fileList.count(), return); + Q_ASSERT(file_idx >= 0 && file_idx < fileList.count()); fileList[file_idx]->name = file; } @@ -339,7 +337,7 @@ int ResourceFile::indexOfPrefix(const QString &prefix) const int ResourceFile::indexOfFile(int pref_idx, const QString &file) const { - QTC_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count(), return -1); + Q_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count()); Prefix * const p = m_prefix_list.at(pref_idx); File equalFile(p, absolutePath(file)); return p->file_list.indexOf(&equalFile); @@ -373,16 +371,16 @@ bool ResourceFile::contains(const QString &prefix, const QString &file) const return false; if (file.isEmpty()) return true; - QTC_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count(), return false); + Q_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count()); Prefix * const p = m_prefix_list.at(pref_idx); - QTC_ASSERT(p, return false); + Q_ASSERT(p); File equalFile(p, absolutePath(file)); return p->file_list.contains(&equalFile); } bool ResourceFile::contains(int pref_idx, const QString &file) const { - QTC_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count(), return false); + Q_ASSERT(pref_idx >= 0 && pref_idx < m_prefix_list.count()); Prefix * const p = m_prefix_list.at(pref_idx); File equalFile(p, absolutePath(file)); return p->file_list.contains(&equalFile); @@ -412,49 +410,49 @@ int ResourceFile::prefixCount() const QString ResourceFile::prefix(int idx) const { - QTC_ASSERT((idx >= 0) && (idx < m_prefix_list.count()), return QString()); + Q_ASSERT((idx >= 0) && (idx < m_prefix_list.count())); return m_prefix_list.at(idx)->name; } QString ResourceFile::lang(int idx) const { - QTC_ASSERT(idx >= 0 && idx < m_prefix_list.count(), return QString()); + Q_ASSERT(idx >= 0 && idx < m_prefix_list.count()); return m_prefix_list.at(idx)->lang; } int ResourceFile::fileCount(int prefix_idx) const { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return 0); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); return m_prefix_list.at(prefix_idx)->file_list.size(); } QString ResourceFile::file(int prefix_idx, int file_idx) const { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return QString()); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); FileList &fileList = m_prefix_list.at(prefix_idx)->file_list; - QTC_ASSERT(file_idx >= 0 && file_idx < fileList.count(), return QString()); + Q_ASSERT(file_idx >= 0 && file_idx < fileList.count()); return fileList.at(file_idx)->name; } QString ResourceFile::alias(int prefix_idx, int file_idx) const { - QTC_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count(), return QString()); + Q_ASSERT(prefix_idx >= 0 && prefix_idx < m_prefix_list.count()); FileList &fileList = m_prefix_list.at(prefix_idx)->file_list; - QTC_ASSERT(file_idx >= 0 && file_idx < fileList.count(), return QString()); + Q_ASSERT(file_idx >= 0 && file_idx < fileList.count()); return fileList.at(file_idx)->alias; } void * ResourceFile::prefixPointer(int prefixIndex) const { - QTC_ASSERT(prefixIndex >= 0 && prefixIndex < m_prefix_list.count(), return 0); + Q_ASSERT(prefixIndex >= 0 && prefixIndex < m_prefix_list.count()); return m_prefix_list.at(prefixIndex); } void * ResourceFile::filePointer(int prefixIndex, int fileIndex) const { - QTC_ASSERT(prefixIndex >= 0 && prefixIndex < m_prefix_list.count(), return 0); + Q_ASSERT(prefixIndex >= 0 && prefixIndex < m_prefix_list.count()); FileList &fileList = m_prefix_list.at(prefixIndex)->file_list; - QTC_ASSERT(fileIndex >= 0 && fileIndex < fileList.count(), return 0); + Q_ASSERT(fileIndex >= 0 && fileIndex < fileList.count()); return fileList.at(fileIndex); } @@ -509,7 +507,7 @@ QModelIndex ResourceModel::index(int row, int column, const QModelIndex &parent) // File node Node * const node = reinterpret_cast(pip); Prefix * const prefix = node->prefix(); - QTC_ASSERT(prefix, return QModelIndex()); + Q_ASSERT(prefix); if (row < 0 || row >= prefix->file_list.count()) return QModelIndex(); const int prefixIndex = m_resource_file.prefixPointerIndex(prefix); @@ -521,7 +519,7 @@ QModelIndex ResourceModel::index(int row, int column, const QModelIndex &parent) return QModelIndex(); internalPointer = m_resource_file.prefixPointer(row); } - QTC_ASSERT(internalPointer, return QModelIndex()); + Q_ASSERT(internalPointer); return createIndex(row, 0, internalPointer); } @@ -535,12 +533,12 @@ QModelIndex ResourceModel::parent(const QModelIndex &index) const return QModelIndex(); Node * const node = reinterpret_cast(internalPointer); Prefix * const prefix = node->prefix(); - QTC_ASSERT(prefix, return QModelIndex()); + Q_ASSERT(prefix); bool const isFileNode = (prefix != node); if (isFileNode) { const int row = m_resource_file.prefixPointerIndex(prefix); - QTC_ASSERT(row >= 0, return QModelIndex()); + Q_ASSERT(row >= 0); return createIndex(row, 0, prefix); } else { return QModelIndex(); @@ -553,7 +551,7 @@ int ResourceModel::rowCount(const QModelIndex &parent) const void * const internalPointer = parent.internalPointer(); Node * const node = reinterpret_cast(internalPointer); Prefix * const prefix = node->prefix(); - QTC_ASSERT(prefix, return 0); + Q_ASSERT(prefix); bool const isFileNode = (prefix != node); if (isFileNode) { @@ -612,7 +610,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const Node * const node = reinterpret_cast(internalPointer); Prefix const * const prefix = node->prefix(); File const * const file = node->file(); - QTC_ASSERT(prefix, return QVariant()); + Q_ASSERT(prefix); bool const isFileNode = (prefix != node); QVariant result; @@ -629,7 +627,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const appendParenthesized(lang, stringRes); } else { // File node - QTC_ASSERT(file, return result); + Q_ASSERT(file); stringRes = QFileInfo(file->name).fileName(); const QString alias = file->alias; if (!alias.isEmpty()) @@ -641,7 +639,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const case Qt::DecorationRole: if (isFileNode) { // File node - QTC_ASSERT(file, return result); + Q_ASSERT(file); const QString path = m_resource_file.absolutePath(file->name); if (iconFileExtension(path)) { const QIcon icon(path); @@ -653,7 +651,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const case Qt::ToolTipRole: if (isFileNode) { // File node - QTC_ASSERT(file, return result); + Q_ASSERT(file); QString conv_file = m_resource_file.relativePath(file->name); QString stringRes = conv_file.replace(QDir::separator(), QLatin1Char('/')); const QString &alias_file = file->alias; @@ -682,12 +680,12 @@ void ResourceModel::getItem(const QModelIndex &index, QString &prefix, QString & void * const internalPointer = index.internalPointer(); Node * const node = reinterpret_cast(internalPointer); Prefix * const p = node->prefix(); - QTC_ASSERT(p, return); + Q_ASSERT(p); bool const isFileNode = (p != node); if (isFileNode) { File *const f = node->file(); - QTC_ASSERT(f, return); + Q_ASSERT(f); if (!f->alias.isEmpty()) file = f->alias; else diff --git a/shared/qrceditor/resourcefile_p.h b/shared/qrceditor/resourcefile_p.h index d5046e1ed85..28c01745416 100644 --- a/shared/qrceditor/resourcefile_p.h +++ b/shared/qrceditor/resourcefile_p.h @@ -36,8 +36,6 @@ #include "namespace_global.h" -#include - #include #include #include @@ -68,7 +66,7 @@ class Node protected: Node(File *file, Prefix *prefix) : m_file(file), m_prefix(prefix) { - QTC_ASSERT(m_prefix, return); + Q_ASSERT(m_prefix); } public: File *file() { return m_file; } diff --git a/shared/qrceditor/resourceview.cpp b/shared/qrceditor/resourceview.cpp index 8af6a7a9e2d..95caef48201 100644 --- a/shared/qrceditor/resourceview.cpp +++ b/shared/qrceditor/resourceview.cpp @@ -35,8 +35,6 @@ #include "undocommands_p.h" -#include - #include #include @@ -312,14 +310,14 @@ void ResourceView::findSamePlacePostDeletionModelIndex(int &row, QModelIndex &pa EntryBackup * ResourceView::removeEntry(const QModelIndex &index) { - QTC_ASSERT(m_qrcModel, return 0); + Q_ASSERT(m_qrcModel); return m_qrcModel->removeEntry(index); } void ResourceView::addFiles(int prefixIndex, const QStringList &fileNames, int cursorFile, int &firstFile, int &lastFile) { - QTC_ASSERT(m_qrcModel, return); + Q_ASSERT(m_qrcModel); m_qrcModel->addFiles(prefixIndex, fileNames, cursorFile, firstFile, lastFile); // Expand prefix node @@ -331,11 +329,11 @@ void ResourceView::addFiles(int prefixIndex, const QStringList &fileNames, int c void ResourceView::removeFiles(int prefixIndex, int firstFileIndex, int lastFileIndex) { - QTC_ASSERT(prefixIndex >= 0 && prefixIndex < m_qrcModel->rowCount(QModelIndex()), return); + Q_ASSERT(prefixIndex >= 0 && prefixIndex < m_qrcModel->rowCount(QModelIndex())); const QModelIndex prefixModelIndex = m_qrcModel->index(prefixIndex, 0, QModelIndex()); - QTC_ASSERT(prefixModelIndex != QModelIndex(), return); - QTC_ASSERT(firstFileIndex >= 0 && firstFileIndex < m_qrcModel->rowCount(prefixModelIndex), return); - QTC_ASSERT(lastFileIndex >= 0 && lastFileIndex < m_qrcModel->rowCount(prefixModelIndex), return); + Q_ASSERT(prefixModelIndex != QModelIndex()); + Q_ASSERT(firstFileIndex >= 0 && firstFileIndex < m_qrcModel->rowCount(prefixModelIndex)); + Q_ASSERT(lastFileIndex >= 0 && lastFileIndex < m_qrcModel->rowCount(prefixModelIndex)); for (int i = lastFileIndex; i >= firstFileIndex; i--) { const QModelIndex index = m_qrcModel->index(i, 0, prefixModelIndex); @@ -572,7 +570,7 @@ QString ResourceView::getCurrentValue(NodeProperty property) const case AliasProperty: return currentAlias(); case PrefixProperty: return currentPrefix(); case LanguageProperty: return currentLanguage(); - default: QTC_ASSERT(false, /**/); return QString(); // Kill warning + default: Q_ASSERT(false); return QString(); // Kill warning } } @@ -583,7 +581,7 @@ void ResourceView::changeValue(const QModelIndex &nodeIndex, NodeProperty proper case AliasProperty: m_qrcModel->changeAlias(nodeIndex, value); return; case PrefixProperty: m_qrcModel->changePrefix(nodeIndex, value); return; case LanguageProperty: m_qrcModel->changeLang(nodeIndex, value); return; - default: QTC_ASSERT(false, /**/); + default: Q_ASSERT(false); } } diff --git a/shared/qrceditor/undocommands.cpp b/shared/qrceditor/undocommands.cpp index fb9d581d238..a6d23a21287 100644 --- a/shared/qrceditor/undocommands.cpp +++ b/shared/qrceditor/undocommands.cpp @@ -101,7 +101,7 @@ bool ModifyPropertyCommand::mergeWith(const QUndoCommand * command) void ModifyPropertyCommand::undo() { - QTC_ASSERT(m_view, return); + Q_ASSERT(m_view); // Save current text in m_after for redo() m_after = m_view->getCurrentValue(m_property); @@ -117,7 +117,7 @@ void ModifyPropertyCommand::redo() return; // Bring back text before undo - QTC_ASSERT(m_view, return); + Q_ASSERT(m_view); m_view->changeValue(makeIndex(), m_property, m_after); } @@ -144,7 +144,7 @@ void RemoveEntryCommand::undo() { if (m_entry == 0) { m_entry->restore(); - QTC_ASSERT(m_view != 0, return); + Q_ASSERT(m_view != 0); const QModelIndex index = makeIndex(); m_view->setExpanded(index, m_isExpanded); m_view->setCurrentIndex(index); diff --git a/shared/scriptwrapper/wrap_helpers.h b/shared/scriptwrapper/wrap_helpers.h index cb697b1f23f..961b1fef6d0 100644 --- a/shared/scriptwrapper/wrap_helpers.h +++ b/shared/scriptwrapper/wrap_helpers.h @@ -34,8 +34,6 @@ #ifndef WRAP_HELPERS_H #define WRAP_HELPERS_H -#include - #include #include #include @@ -89,7 +87,7 @@ template Wrapped * (Wrapper::*wrappedAccessor) () const) { Wrapped *wrapped = wrappedFromScriptValue(context->thisObject(), wrappedAccessor); - QTC_ASSERT(wrapped, return 0); + Q_ASSERT(wrapped); return wrapped; } @@ -316,7 +314,7 @@ static void scriptValueToQObject(const QScriptValue &sv, SomeQObject * &p) { QObject *qObject = sv.toQObject(); p = qobject_cast(qObject); - QTC_ASSERT(p, return); + Q_ASSERT(p); } // Register a QObject-derived class which has Q_DECLARE_METATYPE(Ptr*) diff --git a/src/app/Info.plist b/src/app/Info.plist index dbd50d35ee1..43dd8e772f5 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -182,8 +182,8 @@ CFBundleIdentifier com.nokia.qtcreator CFBundleVersion - 0.9.1 + 0.9.2 CFBundleShortVersionString - 0.9.1 + 0.9.2 diff --git a/src/app/app.pro b/src/app/app.pro index a0e120da1c6..bc8376bbddb 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/app/main.cpp b/src/app/main.cpp index f11e81764d1..2efc04f1451 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -98,12 +98,12 @@ static void displayError(const QString &t) // No console on Windows. static void displayHelpText(const QString &t) { - qWarning(t.toUtf8().constData()); + qWarning("%s", qPrintable(t)); } static void displayError(const QString &t) { - qCritical(t.toUtf8().constData()); + qCritical("%s", qPrintable(t)); } #endif diff --git a/src/libs/aggregation/aggregate.cpp b/src/libs/aggregation/aggregate.cpp index 6fd7414dfc2..1dd6ce03392 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/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 98b5ed1a2ad..d872dd3a1af 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -35,8 +35,7 @@ #define CPPDOCUMENT_H #include - -#include "pp-macro.h" +#include "Macro.h" #include #include diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index cbf6b1ef660..bf5df8b499b 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -32,23 +32,21 @@ ***************************************************************************/ #include "LookupContext.h" +#include "ResolveExpression.h" +#include "Overview.h" + #include #include #include #include #include #include -#include -#include #include using namespace CPlusPlus; -///////////////////////////////////////////////////////////////////// -// LookupUtils -///////////////////////////////////////////////////////////////////// -bool LookupUtils::isNameCompatibleWithIdentifier(Name *name, Identifier *id) +bool LookupContext::isNameCompatibleWithIdentifier(Name *name, Identifier *id) { if (! name) { return false; @@ -274,129 +272,151 @@ void LookupContext::expand(const QList &scopes, QList *expande } } +void LookupContext::expandNamespace(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Namespace *ns = scope->owner()->asNamespace(); + if (! ns) + return; + + if (Name *nsName = ns->name()) { + const QList namespaceList = resolveNamespace(nsName, visibleScopes); + foreach (Symbol *otherNs, namespaceList) { + if (otherNs == ns) + continue; + expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes); + } + } + + for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast + Symbol *symbol = scope->symbolAt(i); + if (Namespace *ns = symbol->asNamespace()) { + if (! ns->name()) { + expand(ns->members(), visibleScopes, expandedScopes); + } + } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { + const QList candidates = resolveNamespace(u->name(), visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asNamespace()->members(), + visibleScopes, expandedScopes); + } + } else if (Enum *e = symbol->asEnum()) { + expand(e->members(), visibleScopes, expandedScopes); + } + } +} + +void LookupContext::expandClass(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Class *klass = scope->owner()->asClass(); + if (! klass) + return; + + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *symbol = scope->symbolAt(i); + if (Class *nestedClass = symbol->asClass()) { + if (! nestedClass->name()) { + expand(nestedClass->members(), visibleScopes, expandedScopes); + } + } else if (Enum *e = symbol->asEnum()) { + expand(e->members(), visibleScopes, expandedScopes); + } + } + + if (klass->baseClassCount()) { + QList classVisibleScopes = visibleScopes; + for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) { + if (scope->isNamespaceScope()) { + Namespace *enclosingNamespace = scope->owner()->asNamespace(); + if (enclosingNamespace->name()) { + const QList nsList = resolveNamespace(enclosingNamespace->name(), + visibleScopes); + foreach (Symbol *ns, nsList) { + expand(ns->asNamespace()->members(), classVisibleScopes, + &classVisibleScopes); + } + } + } + } + + for (unsigned i = 0; i < klass->baseClassCount(); ++i) { + BaseClass *baseClass = klass->baseClassAt(i); + Name *baseClassName = baseClass->name(); + const QList baseClassCandidates = resolveClass(baseClassName, + classVisibleScopes); + if (baseClassCandidates.isEmpty()) { + Overview overview; + qDebug() << "unresolved base class:" << overview.prettyName(baseClassName); + } + + for (int j = 0; j < baseClassCandidates.size(); ++j) { + Class *baseClassSymbol = baseClassCandidates.at(j)->asClass(); + expand(baseClassSymbol->members(), visibleScopes, expandedScopes); + } + } + } +} + +void LookupContext::expandBlock(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *symbol = scope->symbolAt(i); + if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { + const QList candidates = resolveNamespace(u->name(), + visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asNamespace()->members(), + visibleScopes, expandedScopes); + } + } + + } +} + +void LookupContext::expandFunction(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Function *function = scope->owner()->asFunction(); + if (! expandedScopes->contains(function->arguments())) + expandedScopes->append(function->arguments()); + if (QualifiedNameId *q = function->name()->asQualifiedNameId()) { + Name *nestedNameSpec = 0; + if (q->nameCount() == 1 && q->isGlobal()) + nestedNameSpec = q->nameAt(0); + else + nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1, + q->isGlobal()); + const QList candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asScopedSymbol()->members(), + visibleScopes, expandedScopes); + } + } +} + void LookupContext::expand(Scope *scope, const QList &visibleScopes, QList *expandedScopes) const { - Overview overview; - - if (expandedScopes->contains(scope)) { - //qDebug() << "skipped:" << overview.prettyName(scope->owner()->name()); + if (expandedScopes->contains(scope)) return; - } expandedScopes->append(scope); if (scope->isNamespaceScope()) { - Namespace *ns = scope->owner()->asNamespace(); - Name *nsName = ns->name(); - if (nsName) { - QList namespaceList = resolveNamespace(nsName, visibleScopes); - foreach (Symbol *otherNs, namespaceList) { - if (otherNs == ns) - continue; - expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes); - } - //qDebug() << "*** found:" << namespaceList.count() << "namespace aliases"; - } - //qDebug() << "namespace scope" << overview.prettyName(ns->name()) - //<< ns->fileName() << ns->line(); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast - Symbol *symbol = scope->symbolAt(i); - if (Namespace *ns = symbol->asNamespace()) { - if (! ns->name()) { - expand(ns->members(), visibleScopes, expandedScopes); - } - } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { - QList candidates = resolveNamespace(u->name(), visibleScopes); - //qDebug() << "found:" << candidates.count() << "namespaces to import for:" - //<< overview.prettyName(u->name()); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asNamespace()->members(), - visibleScopes, expandedScopes); - } - } else if (Enum *e = symbol->asEnum()) { - expand(e->members(), visibleScopes, expandedScopes); - } - } + expandNamespace(scope, visibleScopes, expandedScopes); } else if (scope->isClassScope()) { - Class *klass = scope->owner()->asClass(); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - Symbol *symbol = scope->symbolAt(i); - if (Class *nestedClass = symbol->asClass()) { - if (! nestedClass->name()) { - expand(nestedClass->members(), visibleScopes, expandedScopes); - } - } else if (Enum *e = symbol->asEnum()) { - expand(e->members(), visibleScopes, expandedScopes); - } - } - - if (klass->baseClassCount()) { - QList classVisibleScopes = visibleScopes; - for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) { - if (scope->isNamespaceScope()) { - Namespace *enclosingNamespace = scope->owner()->asNamespace(); - if (enclosingNamespace->name()) { - QList nsList = resolveNamespace(enclosingNamespace->name(), - visibleScopes); - foreach (Symbol *ns, nsList) { - expand(ns->asNamespace()->members(), classVisibleScopes, &classVisibleScopes); - } - } - } - } - - for (unsigned i = 0; i < klass->baseClassCount(); ++i) { - BaseClass *baseClass = klass->baseClassAt(i); - Name *baseClassName = baseClass->name(); - QList baseClassCandidates = resolveClass(baseClassName, classVisibleScopes); - if (baseClassCandidates.isEmpty()) { - Overview overview; - qDebug() << "unresolved base class:" << overview.prettyName(baseClassName); - } - for (int j = 0; j < baseClassCandidates.size(); ++j) { - Class *baseClassSymbol = baseClassCandidates.at(j)->asClass(); - expand(baseClassSymbol->members(), visibleScopes, expandedScopes); - } - } - } + expandClass(scope, visibleScopes, expandedScopes); } else if (scope->isBlockScope()) { - //qDebug() << "block scope" << overview.prettyName(scope->owner()->name()); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - Symbol *symbol = scope->symbolAt(i); - if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { - QList candidates = resolveNamespace(u->name(), visibleScopes); - //qDebug() << "found:" << candidates.count() << "namespaces to import for:" - //<< overview.prettyName(u->name()); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asNamespace()->members(), - visibleScopes, expandedScopes); - } - } - - } + expandBlock(scope, visibleScopes, expandedScopes); } else if (scope->isFunctionScope()) { - Function *function = scope->owner()->asFunction(); - //qDebug() << "function scope" << overview.prettyName(function->name()); - if (! expandedScopes->contains(function->arguments())) - expandedScopes->append(function->arguments()); - if (QualifiedNameId *q = function->name()->asQualifiedNameId()) { - //qDebug() << "**** here:" << overview.prettyName(function->name()); - Name *nestedNameSpec = 0; - if (q->nameCount() == 1 && q->isGlobal()) - nestedNameSpec = q->nameAt(0); - else - nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1, - q->isGlobal()); - QList candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes); - //qDebug() << "**** found:" << candidates.count() << "class or namespace for:" - //<< overview.prettyName(nestedNameSpec); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asScopedSymbol()->members(), - visibleScopes, expandedScopes); - } - } + expandFunction(scope, visibleScopes, expandedScopes); } else if (scope->isPrototypeScope()) { //qDebug() << "prototype scope" << overview.prettyName(scope->owner()->name()); } diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index e1aec69d122..8759a79210e 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -34,22 +34,12 @@ #ifndef CPLUSPLUS_LOOKUPCONTEXT_H #define CPLUSPLUS_LOOKUPCONTEXT_H -#include #include - -#include -#include -#include +#include namespace CPlusPlus { -class CPLUSPLUS_EXPORT LookupUtils -{ -public: - static bool isNameCompatibleWithIdentifier(Name *name, Identifier *id); -}; - -class CPLUSPLUS_EXPORT LookupContext: LookupUtils +class CPLUSPLUS_EXPORT LookupContext { public: LookupContext(Control *control = 0); @@ -124,8 +114,25 @@ public: void expand(Scope *scope, const QList &visibleScopes, QList *expandedScopes) const; + void expandNamespace(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandClass(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandBlock(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandFunction(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + private: QList buildVisibleScopes(); + static bool isNameCompatibleWithIdentifier(Name *name, Identifier *id); private: Control *_control; diff --git a/src/libs/cplusplus/pp-internal.h b/src/libs/cplusplus/Macro.cpp similarity index 71% rename from src/libs/cplusplus/pp-internal.h rename to src/libs/cplusplus/Macro.cpp index f3b8aef835e..d5492b983b7 100644 --- a/src/libs/cplusplus/pp-internal.h +++ b/src/libs/cplusplus/Macro.cpp @@ -50,29 +50,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_INTERNAL_H -#define PP_INTERNAL_H +#include "Macro.h" -#include +using namespace CPlusPlus; -namespace CPlusPlus { -namespace _PP_internal { +Macro::Macro() + : _next(0), + _hashcode(0), + _line(0), + _state(0) +{ } -inline bool comment_p (const char *__first, const char *__last) +QString Macro::toString() const { - if (__first == __last) - return false; - - if (*__first != '/') - return false; - - if (++__first == __last) - return false; - - return (*__first == '/' || *__first == '*'); + QString text; + if (_hidden) + text += QLatin1String("#undef "); + else + text += QLatin1String("#define "); + text += QString::fromUtf8(_name.constData(), _name.size()); + if (_functionLike) { + text += QLatin1Char('('); + bool first = true; + foreach (const QByteArray formal, _formals) { + if (! first) + text += QLatin1String(", "); + else + first = false; + text += QString::fromUtf8(formal.constData(), formal.size()); + } + if (_variadic) + text += QLatin1String("..."); + text += QLatin1Char(')'); + } + text += QLatin1Char(' '); + text += QString::fromUtf8(_definition.constData(), _definition.size()); + return text; } - -} // _PP_internal -} // namespace CPlusPlus - -#endif // PP_INTERNAL_H diff --git a/src/libs/cplusplus/pp-macro.h b/src/libs/cplusplus/Macro.h similarity index 64% rename from src/libs/cplusplus/pp-macro.h rename to src/libs/cplusplus/Macro.h index 9f5e32752c5..3957f13fab6 100644 --- a/src/libs/cplusplus/pp-macro.h +++ b/src/libs/cplusplus/Macro.h @@ -64,59 +64,80 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT Macro { public: - QByteArray name; - QByteArray definition; - QVector formals; - QByteArray fileName; - int line; - Macro *next; - unsigned hashcode; + Macro(); + + QByteArray name() const + { return _name; } + + void setName(const QByteArray &name) + { _name = name; } + + QByteArray definition() const + { return _definition; } + + void setDefinition(const QByteArray &definition) + { _definition = definition; } + + QVector formals() const + { return _formals; } + + void addFormal(const QByteArray &formal) + { _formals.append(formal); } + + QByteArray fileName() const + { return _fileName; } + + void setFileName(const QByteArray &fileName) + { _fileName = fileName; } + + unsigned line() const + { return _line; } + + void setLine(unsigned line) + { _line = line; } + + bool isHidden() const + { return _hidden; } + + void setHidden(bool isHidden) + { _hidden = isHidden; } + + bool isFunctionLike() const + { return _functionLike; } + + void setFunctionLike(bool isFunctionLike) + { _functionLike = isFunctionLike; } + + bool isVariadic() const + { return _variadic; } + + void setVariadic(bool isVariadic) + { _variadic = isVariadic; } + + QString toString() const; + +// ### private + Macro *_next; + unsigned _hashcode; + +private: + QByteArray _name; + QByteArray _definition; + QVector _formals; + QByteArray _fileName; + unsigned _line; union { - unsigned state; + unsigned _state; struct { - unsigned hidden: 1; - unsigned function_like: 1; - unsigned variadics: 1; + unsigned _hidden: 1; + unsigned _functionLike: 1; + unsigned _variadic: 1; }; }; - - inline Macro(): - line(0), - next(0), - hashcode(0), - state(0) - { } - - QString toString() const - { - QString text; - if (hidden) - text += QLatin1String("#undef "); - else - text += QLatin1String("#define "); - text += QString::fromUtf8(name.constData(), name.size()); - if (function_like) { - text += QLatin1Char('('); - bool first = true; - foreach (const QByteArray formal, formals) { - if (! first) - text += QLatin1String(", "); - else - first = false; - text += QString::fromUtf8(formal.constData(), formal.size()); - } - if (variadics) - text += QLatin1String("..."); - text += QLatin1Char(')'); - } - text += QLatin1Char(' '); - text += QString::fromUtf8(definition.constData(), definition.size()); - return text; - } }; } // namespace CPlusPlus diff --git a/src/libs/cplusplus/PreprocessorClient.cpp b/src/libs/cplusplus/PreprocessorClient.cpp new file mode 100644 index 00000000000..2eb5656446e --- /dev/null +++ b/src/libs/cplusplus/PreprocessorClient.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** +** +** 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 "PreprocessorClient.h" + +using namespace CPlusPlus; + +Client::Client() +{ } + +Client::~Client() +{ } diff --git a/src/libs/cplusplus/pp-client.h b/src/libs/cplusplus/PreprocessorClient.h similarity index 91% rename from src/libs/cplusplus/pp-client.h rename to src/libs/cplusplus/PreprocessorClient.h index e866be4aa89..2d37dac3e6d 100644 --- a/src/libs/cplusplus/pp-client.h +++ b/src/libs/cplusplus/PreprocessorClient.h @@ -31,14 +31,16 @@ ** ***************************************************************************/ -#ifndef PP_CLIENT_H -#define PP_CLIENT_H +#ifndef CPLUSPLUS_PP_CLIENT_H +#define CPLUSPLUS_PP_CLIENT_H #include +#include -#include -#include -#include +QT_BEGIN_NAMESPACE +class QByteArray; +class QString; +QT_END_NAMESPACE namespace CPlusPlus { @@ -56,11 +58,8 @@ public: }; public: - Client() - { } - - virtual ~Client() - { } + Client(); + virtual ~Client(); virtual void macroAdded(const Macro ¯o) = 0; virtual void sourceNeeded(QString &fileName, IncludeType mode, @@ -79,4 +78,4 @@ public: } // namespace CPlusPlus -#endif // PP_CLIENT_H +#endif // CPLUSPLUS_PP_CLIENT_H diff --git a/src/libs/cplusplus/pp-environment.cpp b/src/libs/cplusplus/PreprocessorEnvironment.cpp similarity index 89% rename from src/libs/cplusplus/pp-environment.cpp rename to src/libs/cplusplus/PreprocessorEnvironment.cpp index 60827d4b9b2..693fe6160ea 100644 --- a/src/libs/cplusplus/pp-environment.cpp +++ b/src/libs/cplusplus/PreprocessorEnvironment.cpp @@ -50,16 +50,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pp-environment.h" -#include "pp.h" - +#include "PreprocessorEnvironment.h" +#include "Macro.h" #include using namespace CPlusPlus; Environment::Environment() : currentLine(0), - hide_next(false), + hideNext(false), _macros(0), _allocated_macros(0), _macro_count(-1), @@ -91,10 +90,10 @@ Macro *Environment::macroAt(unsigned index) const Macro *Environment::bind(const Macro &__macro) { - Q_ASSERT(! __macro.name.isEmpty()); + Q_ASSERT(! __macro.name().isEmpty()); Macro *m = new Macro (__macro); - m->hashcode = hash_code(m->name); + m->_hashcode = hashCode(m->name()); if (++_macro_count == _allocated_macros) { if (! _allocated_macros) @@ -110,8 +109,8 @@ Macro *Environment::bind(const Macro &__macro) if (! _hash || _macro_count > (_hash_count >> 1)) { rehash(); } else { - const unsigned h = m->hashcode % _hash_count; - m->next = _hash[h]; + const unsigned h = m->_hashcode % _hash_count; + m->_next = _hash[h]; _hash[h] = m; } @@ -121,10 +120,10 @@ Macro *Environment::bind(const Macro &__macro) Macro *Environment::remove(const QByteArray &name) { Macro macro; - macro.name = name; - macro.hidden = true; - macro.fileName = currentFile; - macro.line = currentLine; + macro.setName(name); + macro.setHidden(true); + macro.setFileName(currentFile); + macro.setLine(currentLine); return bind(macro); } @@ -192,23 +191,23 @@ bool Environment::isBuiltinMacro(const QByteArray &s) const return false; } -Macro *Environment::resolve (const QByteArray &name) const +Macro *Environment::resolve(const QByteArray &name) const { if (! _macros) return 0; - Macro *it = _hash[hash_code (name) % _hash_count]; - for (; it; it = it->next) { - if (it->name != name) + Macro *it = _hash[hashCode(name) % _hash_count]; + for (; it; it = it->_next) { + if (it->name() != name) continue; - else if (it->hidden) + else if (it->isHidden()) return 0; else break; } return it; } -unsigned Environment::hash_code (const QByteArray &s) +unsigned Environment::hashCode(const QByteArray &s) { unsigned hash_value = 0; @@ -229,8 +228,8 @@ void Environment::rehash() for (Macro **it = firstMacro(); it != lastMacro(); ++it) { Macro *m= *it; - const unsigned h = m->hashcode % _hash_count; - m->next = _hash[h]; + const unsigned h = m->_hashcode % _hash_count; + m->_next = _hash[h]; _hash[h] = m; } } diff --git a/src/libs/cplusplus/pp-environment.h b/src/libs/cplusplus/PreprocessorEnvironment.h similarity index 94% rename from src/libs/cplusplus/pp-environment.h rename to src/libs/cplusplus/PreprocessorEnvironment.h index 4ba6b9353c4..48ee5b2715a 100644 --- a/src/libs/cplusplus/pp-environment.h +++ b/src/libs/cplusplus/PreprocessorEnvironment.h @@ -50,8 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_ENVIRONMENT_H -#define PP_ENVIRONMENT_H +#ifndef CPLUSPLUS_PP_ENVIRONMENT_H +#define CPLUSPLUS_PP_ENVIRONMENT_H #include "CPlusPlusForwardDeclarations.h" @@ -90,13 +90,13 @@ public: { return _macros + _macro_count + 1; } private: - static unsigned hash_code (const QByteArray &s); + static unsigned hashCode(const QByteArray &s); void rehash(); public: QByteArray currentFile; unsigned currentLine; - bool hide_next; + bool hideNext; private: Macro **_macros; @@ -108,4 +108,4 @@ private: } // namespace CPlusPlus -#endif // PP_ENVIRONMENT_H +#endif // CPLUSPLUS_PP_ENVIRONMENT_H diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 7ce0e42c69d..6f8ae2ba9b9 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -427,6 +427,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast) bool ResolveExpression::visit(QualifiedNameAST *ast) { + ResolveClass resolveClass; Scope dummy; Name *name = sem.check(ast, &dummy); @@ -435,7 +436,9 @@ bool ResolveExpression::visit(QualifiedNameAST *ast) if (symbol->isTypedef()) { if (NamedType *namedTy = symbol->type()->asNamedType()) { LookupContext symbolContext(symbol, _context); - QList resolvedClasses = symbolContext.resolveClass(namedTy->name()); + const Result r(namedTy, symbol); + const QList resolvedClasses = + resolveClass(r, _context); if (resolvedClasses.count()) { foreach (Symbol *s, resolvedClasses) { addResult(s->type(), s); @@ -535,6 +538,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) _results.clear(); const QList indexResults = operator()(ast->expression); + ResolveClass symbolsForDotAcccess; foreach (Result p, baseResults) { FullySpecifiedType ty = p.first; @@ -548,13 +552,12 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) } else if (ArrayType *arrTy = ty->asArrayType()) { addResult(arrTy->elementType(), contextSymbol); } else if (NamedType *namedTy = ty->asNamedType()) { - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); + const QList classObjectCandidates = + symbolsForDotAcccess(p, _context); foreach (Symbol *classObject, classObjectCandidates) { - const QList overloads = resolveArrayOperator(p, namedTy, - classObject->asClass()); + const QList overloads = + resolveArrayOperator(p, namedTy, classObject->asClass()); foreach (Result r, overloads) { FullySpecifiedType ty = r.first; Function *funTy = ty->asFunction(); @@ -593,6 +596,7 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, unsigned accessOp, Name *memberName) const { + ResolveClass resolveClass; QList results; if (accessOp == T_ARROW) { @@ -603,9 +607,8 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, ty = refTy->elementType(); if (NamedType *namedTy = ty->asNamedType()) { - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); + const QList classObjectCandidates = + resolveClass(namedTy, p, _context); foreach (Symbol *classObject, classObjectCandidates) { const QList overloads = resolveArrowOperator(p, namedTy, @@ -665,12 +668,15 @@ ResolveExpression::resolveMember(const Result &p, Name *memberName, NamedType *namedTy) const { + ResolveClass resolveClass; + + const QList classObjectCandidates = + resolveClass(namedTy, p, _context); + QList results; - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, namedTy, classObject->asClass()); + results += resolveMember(p, memberName, namedTy, + classObject->asClass()); } return results; } @@ -792,3 +798,91 @@ bool ResolveExpression::visit(PostIncrDecrAST *) { return false; } + +//////////////////////////////////////////////////////////////////////////////// +ResolveClass::ResolveClass() +{ } + +QList ResolveClass::operator()(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context) +{ + const QList previousBlackList = _blackList; + const QList symbols = resolveClass(namedTy, p, context); + _blackList = previousBlackList; + return symbols; +} + +QList ResolveClass::operator()(ResolveExpression::Result p, + const LookupContext &context) +{ + const QList previousBlackList = _blackList; + const QList symbols = resolveClass(p, context); + _blackList = previousBlackList; + return symbols; +} + +QList ResolveClass::resolveClass(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context) +{ + QList resolvedSymbols; + + if (_blackList.contains(p)) + return resolvedSymbols; + + _blackList.append(p); + + const QList candidates = + context.resolve(namedTy->name(), context.visibleScopes(p)); + + foreach (Symbol *candidate, candidates) { + if (Class *klass = candidate->asClass()) { + if (resolvedSymbols.contains(klass)) + continue; // we already know about `klass' + resolvedSymbols.append(klass); + } else if (candidate->isTypedef()) { + if (Declaration *decl = candidate->asDeclaration()) { + if (Class *asClass = decl->type()->asClass()) { + // typedef struct { } Point; + // Point pt; + // pt. + resolvedSymbols.append(asClass); + } else { + // typedef Point Boh; + // Boh b; + // b. + const ResolveExpression::Result r(decl->type(), decl); + resolvedSymbols += resolveClass(r, context); + } + } + } else if (Declaration *decl = candidate->asDeclaration()) { + if (Function *funTy = decl->type()->asFunction()) { + // QString foo("ciao"); + // foo. + if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) { + const ResolveExpression::Result r(funTy->returnType(), decl); + resolvedSymbols += resolveClass(r, context); + } + } + } + } + + return resolvedSymbols; +} + +QList ResolveClass::resolveClass(ResolveExpression::Result p, + const LookupContext &context) +{ + FullySpecifiedType ty = p.first; + + if (NamedType *namedTy = ty->asNamedType()) { + return resolveClass(namedTy, p, context); + } else if (ReferenceType *refTy = ty->asReferenceType()) { + const ResolveExpression::Result e(refTy->elementType(), p.second); + return resolveClass(e, context); + } + + return QList(); +} + diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index ac4a675b459..e7cf1c0a3af 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -128,6 +128,31 @@ private: QList _results; }; +class CPLUSPLUS_EXPORT ResolveClass +{ +public: + ResolveClass(); + + QList operator()(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context); + + QList operator()(ResolveExpression::Result p, + const LookupContext &context); + +private: + QList resolveClass(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context); + + QList resolveClass(ResolveExpression::Result p, + const LookupContext &context); + +private: + QList _blackList; +}; + + } // end of namespace CPlusPlus #endif // CPLUSPLUS_RESOLVEEXPRESSION_H diff --git a/src/libs/cplusplus/SimpleLexer.cpp b/src/libs/cplusplus/SimpleLexer.cpp index 4c2a7830363..583f45da389 100644 --- a/src/libs/cplusplus/SimpleLexer.cpp +++ b/src/libs/cplusplus/SimpleLexer.cpp @@ -57,7 +57,8 @@ bool SimpleToken::isKeyword() const SimpleLexer::SimpleLexer() : _lastState(0), _skipComments(false), - _qtMocRunEnabled(true) + _qtMocRunEnabled(true), + _objcEnabled(false) { } SimpleLexer::~SimpleLexer() @@ -73,6 +74,17 @@ void SimpleLexer::setQtMocRunEnabled(bool enabled) _qtMocRunEnabled = enabled; } + +bool SimpleLexer::objcEnabled() const +{ + return _objcEnabled; +} + +void SimpleLexer::setObjcEnabled(bool onoff) +{ + _objcEnabled = onoff; +} + bool SimpleLexer::skipComments() const { return _skipComments; @@ -93,6 +105,7 @@ QList SimpleLexer::operator()(const QString &text, int state) Lexer lex(firstChar, lastChar); lex.setQtMocRunEnabled(_qtMocRunEnabled); + lex.setObjcEnabled(_objcEnabled); if (! _skipComments) lex.setScanCommentTokens(true); diff --git a/src/libs/cplusplus/SimpleLexer.h b/src/libs/cplusplus/SimpleLexer.h index b4889fc92ea..fb64a66c033 100644 --- a/src/libs/cplusplus/SimpleLexer.h +++ b/src/libs/cplusplus/SimpleLexer.h @@ -91,6 +91,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool enabled); + bool objcEnabled() const; + void setObjcEnabled(bool onoff); + QList operator()(const QString &text, int state = 0); int state() const @@ -100,6 +103,7 @@ private: int _lastState; bool _skipComments: 1; bool _qtMocRunEnabled: 1; + bool _objcEnabled: 1; }; } // end of namespace CPlusPlus diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 46c2042d0f3..7f08d5874d8 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -38,6 +38,7 @@ #include #include #include +#include using namespace CPlusPlus; @@ -136,7 +137,7 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression, processEnvironment(documents, thisDocument, &env, &processed); const QByteArray code = expression.toUtf8(); - pp preproc(0, env); + Preprocessor preproc(0, env); QByteArray preprocessedCode; preproc("", code, &preprocessedCode); return QString::fromUtf8(preprocessedCode); diff --git a/src/libs/cplusplus/cplusplus.pro b/src/libs/cplusplus/cplusplus.pro index 35ec8a070b3..f89d4d3f862 100644 --- a/src/libs/cplusplus/cplusplus.pro +++ b/src/libs/cplusplus/cplusplus.pro @@ -22,14 +22,14 @@ HEADERS += \ TypePrettyPrinter.h \ ResolveExpression.h \ LookupContext.h \ + PreprocessorClient.h \ + PreprocessorEnvironment.h \ + Macro.h \ + pp.h \ pp-cctype.h \ pp-engine.h \ pp-macro-expander.h \ - pp-scanner.h \ - pp-client.h \ - pp-environment.h \ - pp-internal.h \ - pp-macro.h + pp-scanner.h SOURCES += \ SimpleLexer.cpp \ @@ -44,8 +44,11 @@ SOURCES += \ TypePrettyPrinter.cpp \ ResolveExpression.cpp \ LookupContext.cpp \ + PreprocessorClient.cpp \ + PreprocessorEnvironment.cpp \ + Macro.cpp \ pp-engine.cpp \ - pp-environment.cpp \ - pp-macro-expander.cpp + pp-macro-expander.cpp \ + pp-scanner.cpp RESOURCES += cplusplus.qrc diff --git a/src/libs/cplusplus/pp-cctype.h b/src/libs/cplusplus/pp-cctype.h index 532f56a7e1d..d55d6c2e4e9 100644 --- a/src/libs/cplusplus/pp-cctype.h +++ b/src/libs/cplusplus/pp-cctype.h @@ -50,8 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_CCTYPE_H -#define PP_CCTYPE_H +#ifndef CPLUSPLUS_PP_CCTYPE_H +#define CPLUSPLUS_PP_CCTYPE_H #include @@ -73,4 +73,4 @@ inline bool CPLUSPLUS_EXPORT pp_isspace (int __ch) } // namespace CPlusPlus -#endif // PP_CCTYPE_H +#endif // CPLUSPLUS_PP_CCTYPE_H diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 0ed09f224de..6c5930de182 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -451,7 +451,7 @@ private: } // end of anonymous namespace -pp::pp (Client *client, Environment &env) +Preprocessor::Preprocessor(Client *client, Environment &env) : client(client), env(env), expand(env) @@ -459,7 +459,7 @@ pp::pp (Client *client, Environment &env) resetIfLevel (); } -void pp::pushState(const State &s) +void Preprocessor::pushState(const State &s) { _savedStates.append(state()); _source = s.source; @@ -467,7 +467,7 @@ void pp::pushState(const State &s) _dot = s.dot; } -pp::State pp::state() const +Preprocessor::State Preprocessor::state() const { State state; state.source = _source; @@ -476,7 +476,7 @@ pp::State pp::state() const return state; } -void pp::popState() +void Preprocessor::popState() { const State &state = _savedStates.last(); _source = state.source; @@ -485,7 +485,7 @@ void pp::popState() _savedStates.removeLast(); } -void pp::operator () (const QByteArray &filename, +void Preprocessor::operator () (const QByteArray &filename, const QByteArray &source, QByteArray *result) { @@ -497,7 +497,7 @@ void pp::operator () (const QByteArray &filename, env.currentFile = previousFile; } -pp::State pp::createStateFromSource(const QByteArray &source) const +Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source) const { State state; state.source = source; @@ -512,7 +512,7 @@ pp::State pp::createStateFromSource(const QByteArray &source) const return state; } -void pp::operator()(const QByteArray &source, QByteArray *result) +void Preprocessor::operator()(const QByteArray &source, QByteArray *result) { pushState(createStateFromSource(source)); @@ -600,19 +600,15 @@ void pp::operator()(const QByteArray &source, QByteArray *result) if (! m) { result->append(spell); } else { - if (! m->function_like) { + if (! m->isFunctionLike()) { if (_dot->isNot(T_LPAREN)) { if (client) client->startExpandingMacro(identifierToken->offset, *m, spell); - m->hidden = true; - - expand(m->definition.constBegin(), - m->definition.constEnd(), - result); - - m->hidden = false; + m->setHidden(true); + expand(m->definition(), result); + m->setHidden(false); if (client) client->stopExpandingMacro(_dot->offset, *m); @@ -624,13 +620,9 @@ void pp::operator()(const QByteArray &source, QByteArray *result) if (client) client->startExpandingMacro(identifierToken->offset, *m, spell); - m->hidden = true; - - expand(m->definition.constBegin(), - m->definition.constEnd(), - &tmp); - - m->hidden = false; + m->setHidden(true); + expand(m->definition(), &tmp); + m->setHidden(false); if (client) client->stopExpandingMacro(_dot->offset, *m); @@ -641,7 +633,7 @@ void pp::operator()(const QByteArray &source, QByteArray *result) if (_dot->is(T_IDENTIFIER)) { const QByteArray id = tokenSpell(*_dot); Macro *macro = env.resolve(id); - if (macro && macro->function_like) + if (macro && macro->isFunctionLike()) m = macro; } popState(); @@ -656,7 +648,7 @@ void pp::operator()(const QByteArray &source, QByteArray *result) // collect the actual arguments if (_dot->isNot(T_LPAREN)) { // ### warnng expected T_LPAREN - result->append(m->name); + result->append(m->name()); continue; } @@ -700,27 +692,27 @@ void pp::operator()(const QByteArray &source, QByteArray *result) env.currentLine = previousCurrentLine; } -const char *pp::startOfToken(const Token &token) const +const char *Preprocessor::startOfToken(const Token &token) const { return _source.constBegin() + token.begin(); } -const char *pp::endOfToken(const Token &token) const +const char *Preprocessor::endOfToken(const Token &token) const { return _source.constBegin() + token.end(); } -QByteArray pp::tokenSpell(const Token &token) const +QByteArray Preprocessor::tokenSpell(const Token &token) const { const QByteArray text = QByteArray::fromRawData(_source.constBegin() + token.offset, token.length); return text; } -QByteArray pp::tokenText(const Token &token) const +QByteArray Preprocessor::tokenText(const Token &token) const { const QByteArray text(_source.constBegin() + token.offset, token.length); return text; } -void pp::processDirective(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processDirective(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); ++tk; // skip T_POUND @@ -771,7 +763,7 @@ void pp::processDirective(TokenIterator firstToken, TokenIterator lastToken) } } -QVector pp::tokenize(const QByteArray &text) const +QVector Preprocessor::tokenize(const QByteArray &text) const { QVector tokens; Lexer lex(text.constBegin(), text.constEnd()); @@ -784,7 +776,7 @@ QVector pp::tokenize(const QByteArray &text) const return tokens; } -void pp::processInclude(bool skipCurentPath, +void Preprocessor::processInclude(bool skipCurentPath, TokenIterator firstToken, TokenIterator lastToken, bool acceptMacros) { @@ -836,7 +828,7 @@ void pp::processInclude(bool skipCurentPath, } } -void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -852,30 +844,30 @@ void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) } Macro macro; - macro.fileName = env.currentFile; - macro.line = env.currentLine; - macro.name = tokenText(*tk); + macro.setFileName(env.currentFile); + macro.setLine(env.currentLine); + macro.setName(tokenText(*tk)); ++tk; // skip T_IDENTIFIER if (tk->is(T_LPAREN) && ! tk->whitespace) { // a function-like macro definition - macro.function_like = true; + macro.setFunctionLike(true); ++tk; // skip T_LPAREN if (tk->is(T_IDENTIFIER)) { - macro.formals.append(tokenText(*tk)); + macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER while (tk->is(T_COMMA)) { ++tk;// skip T_COMMA if (tk->isNot(T_IDENTIFIER)) break; - macro.formals.append(tokenText(*tk)); + macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER } } if (tk->is(T_DOT_DOT_DOT)) { - macro.variadics = true; + macro.setVariadic(true); ++tk; // skip T_DOT_DOT_DOT } @@ -887,32 +879,31 @@ void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) ++tk; // skip T_RPAREN } - QByteArray macroId = macro.name; - const bool isQtWord = isQtReservedWord(macroId); + if (isQtReservedWord(macro.name())) { + QByteArray macroId = macro.name(); - if (macro.function_like) { - macroId += '('; - for (int i = 0; i < macro.formals.size(); ++i) { - if (i != 0) - macroId += ", "; - - const QByteArray formal = macro.formals.at(i); - macroId += formal; + if (macro.isFunctionLike()) { + macroId += '('; + bool fst = true; + foreach (const QByteArray formal, macro.formals()) { + if (! fst) + macroId += ", "; + fst = false; + macroId += formal; + } + macroId += ')'; } - macroId += ')'; - } - if (isQtWord) - macro.definition = macroId; - else { + macro.setDefinition(macroId); + } else { // ### make me fast! const char *startOfDefinition = startOfToken(*tk); const char *endOfDefinition = startOfToken(*lastToken); - macro.definition.append(startOfDefinition, - endOfDefinition - startOfDefinition); - macro.definition.replace("\\\n", " "); - macro.definition.replace('\n', ' '); - macro.definition = macro.definition.trimmed(); + QByteArray definition(startOfDefinition, + endOfDefinition - startOfDefinition); + definition.replace("\\\n", " "); + definition.replace('\n', ' '); + macro.setDefinition(definition.trimmed()); } env.bind(macro); @@ -921,7 +912,7 @@ void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) client->macroAdded(macro); } -void pp::processIf(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processIf(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -948,7 +939,7 @@ void pp::processIf(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processElse(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processElse(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -961,7 +952,7 @@ void pp::processElse(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processElif(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processElif(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); ++tk; // skip T_POUND @@ -980,7 +971,7 @@ void pp::processElif(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processEndif(TokenIterator, TokenIterator) +void Preprocessor::processEndif(TokenIterator, TokenIterator) { if (iflevel == 0 && !skipping()) { // std::cerr << "*** WARNING #endif without #if" << std::endl; @@ -992,7 +983,7 @@ void pp::processEndif(TokenIterator, TokenIterator) } } -void pp::processIfdef(bool checkUndefined, +void Preprocessor::processIfdef(bool checkUndefined, TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -1013,7 +1004,7 @@ void pp::processIfdef(bool checkUndefined, } } -void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processUndef(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -1029,14 +1020,14 @@ void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::resetIfLevel () +void Preprocessor::resetIfLevel () { iflevel = 0; _skipping[iflevel] = false; _true_test[iflevel] = false; } -pp::PP_DIRECTIVE_TYPE pp::classifyDirective (const QByteArray &__directive) const +Preprocessor::PP_DIRECTIVE_TYPE Preprocessor::classifyDirective (const QByteArray &__directive) const { switch (__directive.size()) { @@ -1085,7 +1076,7 @@ pp::PP_DIRECTIVE_TYPE pp::classifyDirective (const QByteArray &__directive) cons return PP_UNKNOWN_DIRECTIVE; } -bool pp::testIfLevel() +bool Preprocessor::testIfLevel() { const bool result = !_skipping[iflevel++]; _skipping[iflevel] = _skipping[iflevel - 1]; @@ -1093,10 +1084,10 @@ bool pp::testIfLevel() return result; } -int pp::skipping() const +int Preprocessor::skipping() const { return _skipping[iflevel]; } -Value pp::evalExpression(TokenIterator firstToken, TokenIterator lastToken, +Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken, const QByteArray &source) const { ExpressionEvaluator eval(&env); @@ -1104,7 +1095,7 @@ Value pp::evalExpression(TokenIterator firstToken, TokenIterator lastToken, return result; } -bool pp::isQtReservedWord (const QByteArray ¯oId) const +bool Preprocessor::isQtReservedWord (const QByteArray ¯oId) const { const int size = macroId.size(); if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS") diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index e7c0af68fb1..d0a573aed9c 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -50,10 +50,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_ENGINE_H -#define PP_ENGINE_H +#ifndef CPLUSPLUS_PP_ENGINE_H +#define CPLUSPLUS_PP_ENGINE_H -#include "pp-client.h" +#include "PreprocessorClient.h" #include #include @@ -134,7 +134,7 @@ namespace CPlusPlus { #undef PP_DEFINE_BIN_OP }; - class CPLUSPLUS_EXPORT pp + class CPLUSPLUS_EXPORT Preprocessor { Client *client; Environment &env; @@ -182,7 +182,7 @@ namespace CPlusPlus { State createStateFromSource(const QByteArray &source) const; public: - pp(Client *client, Environment &env); + Preprocessor(Client *client, Environment &env); void operator()(const QByteArray &filename, const QByteArray &source, @@ -228,4 +228,4 @@ namespace CPlusPlus { } // namespace CPlusPlus -#endif // PP_ENGINE_H +#endif // CPLUSPLUS_PP_ENGINE_H diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 21148d24461..40bbc8090b6 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -32,11 +32,26 @@ ***************************************************************************/ #include "pp.h" +#include "pp-cctype.h" #include "pp-macro-expander.h" #include using namespace CPlusPlus; +inline static bool comment_p (const char *__first, const char *__last) +{ + if (__first == __last) + return false; + + if (*__first != '/') + return false; + + if (++__first == __last) + return false; + + return (*__first == '/' || *__first == '*'); +} + MacroExpander::MacroExpander (Environment &env, pp_frame *frame) : env(env), frame(frame), lines(0), generated_lines(0) @@ -47,7 +62,7 @@ const QByteArray *MacroExpander::resolve_formal(const QByteArray &__name) if (! (frame && frame->expanding_macro)) return 0; - const QVector &formals = frame->expanding_macro->formals; + const QVector formals = frame->expanding_macro->formals(); for (int index = 0; index < formals.size(); ++index) { const QByteArray formal = formals.at(index); @@ -137,7 +152,7 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, __result->append(__first, next_pos - __first); __first = next_pos; } - else if (_PP_internal::comment_p (__first, __last)) + else if (comment_p (__first, __last)) { __first = skip_comment_or_divop (__first, __last); int n = skip_comment_or_divop.lines; @@ -198,12 +213,12 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, } Macro *macro = env.resolve (fast_name); - if (! macro || macro->hidden || env.hide_next) + if (! macro || macro->isHidden() || env.hideNext) { if (fast_name.size () == 7 && fast_name [0] == 'd' && fast_name == "defined") - env.hide_next = true; + env.hideNext = true; else - env.hide_next = false; + env.hideNext = false; if (fast_name.size () == 8 && fast_name [0] == '_' && fast_name [1] == '_') { @@ -245,19 +260,19 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, continue; } - if (! macro->function_like) + if (! macro->isFunctionLike()) { Macro *m = 0; - if (! macro->definition.isEmpty()) + if (! macro->definition().isEmpty()) { - macro->hidden = true; + macro->setHidden(true); QByteArray __tmp; __tmp.reserve (256); MacroExpander expand_macro (env); - expand_macro (macro->definition.constBegin (), macro->definition.constEnd (), &__tmp); + expand_macro (macro->definition(), &__tmp); generated_lines += expand_macro.lines; if (! __tmp.isEmpty ()) @@ -277,7 +292,7 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, *__result += __tmp; } - macro->hidden = false; + macro->setHidden(false); } if (! m) @@ -333,9 +348,9 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, pp_frame frame (macro, actuals); MacroExpander expand_macro (env, &frame); - macro->hidden = true; - expand_macro (macro->definition.constBegin (), macro->definition.constEnd (), __result); - macro->hidden = false; + macro->setHidden(true); + expand_macro (macro->definition(), __result); + macro->setHidden(false); generated_lines += expand_macro.lines; } else @@ -351,8 +366,8 @@ const char *MacroExpander::skip_argument_variadics (QVector const &_ { const char *arg_end = skip_argument (__first, __last); - while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ',' - && (__actuals.size () + 1) == __macro->formals.size ()) + while (__macro->isVariadic() && __first != arg_end && arg_end != __last && *arg_end == ',' + && (__actuals.size () + 1) == __macro->formals().size ()) { arg_end = skip_argument (++arg_end, __last); } diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h index 2959977bb15..3e6217476fa 100644 --- a/src/libs/cplusplus/pp-macro-expander.h +++ b/src/libs/cplusplus/pp-macro-expander.h @@ -88,6 +88,10 @@ namespace CPlusPlus { const char *operator () (const char *first, const char *last, QByteArray *result); + const char *operator () (const QByteArray &source, + QByteArray *result) + { return operator()(source.constBegin(), source.constEnd(), result); } + const char *skip_argument_variadics (const QVector &actuals, Macro *macro, const char *first, const char *last); diff --git a/src/libs/cplusplus/pp-scanner.cpp b/src/libs/cplusplus/pp-scanner.cpp new file mode 100644 index 00000000000..8f0f9bf9ae8 --- /dev/null +++ b/src/libs/cplusplus/pp-scanner.cpp @@ -0,0 +1,296 @@ +/*************************************************************************** +** +** 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. +** +***************************************************************************/ +/* + Copyright 2005 Roberto Raggi + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "pp-scanner.h" +#include "pp-cctype.h" + +using namespace CPlusPlus; + +const char *pp_skip_blanks::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (*__first == '\\') { + const char *__begin = __first; + ++__begin; + + if (__begin != __last && *__begin == '\n') + ++__first; + else + break; + } else if (*__first == '\n' || !pp_isspace (*__first)) + break; + } + + return __first; +} + +const char *pp_skip_whitespaces::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isspace (*__first)) + break; + } + + return __first; +} + +const char *pp_skip_comment_or_divop::operator () (const char *__first, const char *__last) +{ + enum { + MAYBE_BEGIN, + BEGIN, + MAYBE_END, + END, + IN_COMMENT, + IN_CXX_COMMENT + } state (MAYBE_BEGIN); + + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) { + default: + break; + + case MAYBE_BEGIN: + if (*__first != '/') + return __first; + + state = BEGIN; + break; + + case BEGIN: + if (*__first == '*') + state = IN_COMMENT; + else if (*__first == '/') + state = IN_CXX_COMMENT; + else + return __first; + break; + + case IN_COMMENT: + if (*__first == '*') + state = MAYBE_END; + break; + + case IN_CXX_COMMENT: + if (*__first == '\n') + return __first; + break; + + case MAYBE_END: + if (*__first == '/') + state = END; + else if (*__first != '*') + state = IN_COMMENT; + break; + + case END: + return __first; + } + } + + return __first; +} + +const char *pp_skip_identifier::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isalnum (*__first) && *__first != '_') + break; + } + + return __first; +} + +const char *pp_skip_number::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isalnum (*__first) && *__first != '.') + break; + } + + return __first; +} + +const char *pp_skip_string_literal::operator () (const char *__first, const char *__last) +{ + enum { + BEGIN, + IN_STRING, + QUOTE, + END + } state (BEGIN); + + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) + { + default: + break; + + case BEGIN: + if (*__first != '\"') + return __first; + state = IN_STRING; + break; + + case IN_STRING: + if (! (*__first != '\n')) + return __last; + + if (*__first == '\"') + state = END; + else if (*__first == '\\') + state = QUOTE; + break; + + case QUOTE: + state = IN_STRING; + break; + + case END: + return __first; + } + } + + return __first; +} + +const char *pp_skip_char_literal::operator () (const char *__first, const char *__last) +{ + enum { + BEGIN, + IN_STRING, + QUOTE, + END + } state (BEGIN); + + lines = 0; + + for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) + { + default: + break; + + case BEGIN: + if (*__first != '\'') + return __first; + state = IN_STRING; + break; + + case IN_STRING: + if (! (*__first != '\n')) + return __last; + + if (*__first == '\'') + state = END; + else if (*__first == '\\') + state = QUOTE; + break; + + case QUOTE: + state = IN_STRING; + break; + } + } + + return __first; +} + +const char *pp_skip_argument::operator () (const char *__first, const char *__last) +{ + int depth = 0; + lines = 0; + + while (__first != __last) { + if (!depth && (*__first == ')' || *__first == ',')) + break; + else if (*__first == '(') + ++depth, ++__first; + else if (*__first == ')') + --depth, ++__first; + else if (*__first == '\"') { + __first = skip_string_literal (__first, __last); + lines += skip_string_literal.lines; + } else if (*__first == '\'') { + __first = skip_char_literal (__first, __last); + lines += skip_char_literal.lines; + } else if (*__first == '/') { + __first = skip_comment_or_divop (__first, __last); + lines += skip_comment_or_divop.lines; + } else if (pp_isalpha (*__first) || *__first == '_') { + __first = skip_identifier (__first, __last); + lines += skip_identifier.lines; + } else if (pp_isdigit (*__first)) { + __first = skip_number (__first, __last); + lines += skip_number.lines; + } else if (*__first == '\n') { + ++__first; + ++lines; + } else + ++__first; + } + + return __first; +} + diff --git a/src/libs/cplusplus/pp-scanner.h b/src/libs/cplusplus/pp-scanner.h index c2e768912fa..71bd04476ba 100644 --- a/src/libs/cplusplus/pp-scanner.h +++ b/src/libs/cplusplus/pp-scanner.h @@ -50,266 +50,57 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_SCANNER_H -#define PP_SCANNER_H +#ifndef CPLUSPLUS_PP_SCANNER_H +#define CPLUSPLUS_PP_SCANNER_H namespace CPlusPlus { struct pp_skip_blanks { int lines; - - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (*__first == '\\') - { - const char *__begin = __first; - ++__begin; - - if (__begin != __last && *__begin == '\n') - ++__first; - else - break; - } - else if (*__first == '\n' || !pp_isspace (*__first)) - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_whitespaces { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isspace (*__first)) - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_comment_or_divop { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - MAYBE_BEGIN, - BEGIN, - MAYBE_END, - END, - IN_COMMENT, - IN_CXX_COMMENT - } state (MAYBE_BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case MAYBE_BEGIN: - if (*__first != '/') - return __first; - - state = BEGIN; - break; - - case BEGIN: - if (*__first == '*') - state = IN_COMMENT; - else if (*__first == '/') - state = IN_CXX_COMMENT; - else - return __first; - break; - - case IN_COMMENT: - if (*__first == '*') - state = MAYBE_END; - break; - - case IN_CXX_COMMENT: - if (*__first == '\n') - return __first; - break; - - case MAYBE_END: - if (*__first == '/') - state = END; - else if (*__first != '*') - state = IN_COMMENT; - break; - - case END: - return __first; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_identifier { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isalnum (*__first) && *__first != '_') - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_number { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isalnum (*__first) && *__first != '.') - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_string_literal { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state (BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case BEGIN: - if (*__first != '\"') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - if (! (*__first != '\n')) - return __last; - - if (*__first == '\"') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - - case END: - return __first; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_char_literal { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state (BEGIN); - - lines = 0; - - for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case BEGIN: - if (*__first != '\'') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - if (! (*__first != '\n')) - return __last; - - if (*__first == '\'') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_argument @@ -321,60 +112,9 @@ struct pp_skip_argument pp_skip_comment_or_divop skip_comment_or_divop; int lines; - - const char *operator () (const char *__first, const char *__last) - { - int depth = 0; - lines = 0; - - while (__first != __last) - { - if (!depth && (*__first == ')' || *__first == ',')) - break; - else if (*__first == '(') - ++depth, ++__first; - else if (*__first == ')') - --depth, ++__first; - else if (*__first == '\"') - { - __first = skip_string_literal (__first, __last); - lines += skip_string_literal.lines; - } - else if (*__first == '\'') - { - __first = skip_char_literal (__first, __last); - lines += skip_char_literal.lines; - } - else if (*__first == '/') - { - __first = skip_comment_or_divop (__first, __last); - lines += skip_comment_or_divop.lines; - } - else if (pp_isalpha (*__first) || *__first == '_') - { - __first = skip_identifier (__first, __last); - lines += skip_identifier.lines; - } - else if (pp_isdigit (*__first)) - { - __first = skip_number (__first, __last); - lines += skip_number.lines; - } - else if (*__first == '\n') - { - ++__first; - ++lines; - } - else - ++__first; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; } // namespace CPlusPlus -#endif // PP_SCANNER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; +#endif // CPLUSPLUS_PP_SCANNER_H diff --git a/src/libs/cplusplus/pp.h b/src/libs/cplusplus/pp.h index 2dee3e87f1d..96c81867163 100644 --- a/src/libs/cplusplus/pp.h +++ b/src/libs/cplusplus/pp.h @@ -50,20 +50,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_H -#define PP_H +#ifndef CPLUSPLUS_PREPROCESSOR_H +#define CPLUSPLUS_PREPROCESSOR_H -#include -#include -#include - -#include "pp-cctype.h" -#include "pp-internal.h" -#include "pp-macro.h" -#include "pp-environment.h" +#include "Macro.h" +#include "PreprocessorClient.h" +#include "PreprocessorEnvironment.h" #include "pp-scanner.h" #include "pp-macro-expander.h" #include "pp-engine.h" -#include "pp-client.h" -#endif // PP_H +#endif // CPLUSPLUS_PREPROCESSOR_H diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 1b75839fa89..0ce65bf5c0a 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 0603cd87cab..7dc9c4e10af 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 99e83d9fc64..0e5fa53996f 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -221,7 +221,7 @@ QList 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/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index d3743509709..91504b496c9 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -90,6 +90,7 @@ struct PathChooserPrivate PathValidatingLineEdit *m_lineEdit; PathChooser::Kind m_acceptingKind; QString m_dialogTitleOverride; + QString m_initialBrowsePathOverride; }; PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) : @@ -138,15 +139,20 @@ QString PathChooser::path() const void PathChooser::setPath(const QString &path) { - const QString defaultPath = path.isEmpty() ? homePath() : path; - m_d->m_lineEdit->setText(QDir::toNativeSeparators(defaultPath)); + m_d->m_lineEdit->setText(QDir::toNativeSeparators(path)); } void PathChooser::slotBrowse() { + emit beforeBrowsing(); + QString predefined = path(); - if (!predefined.isEmpty() && !QFileInfo(predefined).isDir()) - predefined.clear(); + if ((predefined.isEmpty() || !QFileInfo(predefined).isDir()) + && !m_d->m_initialBrowsePathOverride.isNull()) { + predefined = m_d->m_initialBrowsePathOverride; + if (!QFileInfo(predefined).isDir()) + predefined.clear(); + } // Prompt for a file/dir QString dialogTitle; @@ -167,13 +173,15 @@ void PathChooser::slotBrowse() ; } - // TODO make cross-platform - // Delete trailing slashes unless it is "/", only + // Delete trailing slashes unless it is "/"|"\\", only if (!newPath.isEmpty()) { + newPath = QDir::toNativeSeparators(newPath); if (newPath.size() > 1 && newPath.endsWith(QDir::separator())) newPath.truncate(newPath.size() - 1); setPath(newPath); } + + emit browsingFinished(); } bool PathChooser::isValid() const @@ -270,6 +278,11 @@ void PathChooser::setPromptDialogTitle(const QString &title) m_d->m_dialogTitleOverride = title; } +void PathChooser::setInitialBrowsePathBackup(const QString &path) +{ + m_d->m_initialBrowsePathOverride = path; +} + QString PathChooser::makeDialogTitle(const QString &title) { if (m_d->m_dialogTitleOverride.isNull()) diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index b3898465531..5fcc8ee228c 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -71,6 +71,8 @@ public: void setPromptDialogTitle(const QString &title); + void setInitialBrowsePathBackup(const QString &path); + bool isValid() const; QString errorMessage() const; @@ -91,6 +93,8 @@ private: signals: void validChanged(); void changed(); + void beforeBrowsing(); + void browsingFinished(); void returnPressed(); public slots: diff --git a/src/plugins/bineditor/BinEditor.pluginspec b/src/plugins/bineditor/BinEditor.pluginspec index 4c79a18f251..499dc23e10b 100644 --- a/src/plugins/bineditor/BinEditor.pluginspec +++ b/src/plugins/bineditor/BinEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Binary editor component. http://www.trolltech.com/ - - + + diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec b/src/plugins/bookmarks/Bookmarks.pluginspec index e6ef924e483..35f196fb9cb 100644 --- a/src/plugins/bookmarks/Bookmarks.pluginspec +++ b/src/plugins/bookmarks/Bookmarks.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Bookmarks in text editors. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec index 84eefae0ee8..567839e781b 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation ### TODO CMake support http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp index 88572968040..13963273287 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp @@ -99,7 +99,7 @@ QString CMakeBuildStepConfigWidget::displayName() const return "CMake"; } -void CMakeBuildStepConfigWidget::init(const QString &buildConfiguration) +void CMakeBuildStepConfigWidget::init(const QString & /*buildConfiguration */) { // TODO } @@ -121,12 +121,12 @@ ProjectExplorer::BuildStep *CMakeBuildStepFactory::create(ProjectExplorer::Proje return new CMakeStep(pro); } -QStringList CMakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const +QStringList CMakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project * /* pro */) const { return QStringList(); } -QString CMakeBuildStepFactory::displayNameForName(const QString &name) const +QString CMakeBuildStepFactory::displayNameForName(const QString & /* name */) const { return "CMake"; } diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 1c7e7f055f5..abd77cd10aa 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -93,7 +93,7 @@ QString MakeBuildStepConfigWidget::displayName() const return "Make"; } -void MakeBuildStepConfigWidget::init(const QString &buildConfiguration) +void MakeBuildStepConfigWidget::init(const QString & /* buildConfiguration */) { // TODO } @@ -115,12 +115,12 @@ ProjectExplorer::BuildStep *MakeBuildStepFactory::create(ProjectExplorer::Projec return new MakeStep(pro); } -QStringList MakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const +QStringList MakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project * /* pro */) const { return QStringList(); } -QString MakeBuildStepFactory::displayNameForName(const QString &name) const +QString MakeBuildStepFactory::displayNameForName(const QString & /* name */) const { return "Make"; } diff --git a/src/plugins/coreplugin/Core.pluginspec b/src/plugins/coreplugin/Core.pluginspec index ef7a7e38f0a..e771f21ec2f 100644 --- a/src/plugins/coreplugin/Core.pluginspec +++ b/src/plugins/coreplugin/Core.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 41e00202e53..301cfb6d39a 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -41,7 +41,7 @@ namespace Constants { #define IDE_VERSION_MAJOR 0 #define IDE_VERSION_MINOR 9 -#define IDE_VERSION_RELEASE 1 +#define IDE_VERSION_RELEASE 2 #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) @@ -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/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp index b4a8c2b8ea6..e2865bf1830 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -47,6 +47,8 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory, setupUi(this); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); + splitter->setCollapsible(1, false); pageTree->header()->setVisible(false); @@ -135,3 +137,9 @@ void SettingsDialog::reject() page->finished(false); done(QDialog::Rejected); } + +void SettingsDialog::apply() +{ + foreach (IOptionsPage *page, m_pages) + page->finished(true); +} diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.h b/src/plugins/coreplugin/dialogs/settingsdialog.h index c277c852671..6dd8a2a37da 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.h +++ b/src/plugins/coreplugin/dialogs/settingsdialog.h @@ -57,6 +57,7 @@ private slots: void pageSelected(QTreeWidgetItem *cat); void accept(); void reject(); + void apply(); private: QList m_pages; diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.ui b/src/plugins/coreplugin/dialogs/settingsdialog.ui index 9d2475536c0..aad114f848c 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.ui +++ b/src/plugins/coreplugin/dialogs/settingsdialog.ui @@ -1,7 +1,8 @@ - + + SettingsDialog - - + + 0 0 @@ -9,50 +10,48 @@ 476 - + Options - - - 9 - - + + 6 + + 9 + - - + + Qt::Horizontal - - - - 7 - 7 + + + 0 0 - + 1 - + 0 - - - - 0 - - + + + 6 + + 0 + - - + + 350 250 @@ -61,8 +60,8 @@ - - + + Qt::Horizontal @@ -72,12 +71,12 @@ - - + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -91,11 +90,11 @@ SettingsDialog accept() - + 297 361 - + 297 193 @@ -107,11 +106,11 @@ SettingsDialog reject() - + 297 361 - + 297 193 diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index cb911b1fd20..1eb3abb133d 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -319,6 +319,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) : IActionContainer *advancedMenu = am->createMenu(Constants::M_EDIT_ADVANCED); medit->addMenu(advancedMenu, Constants::G_EDIT_FORMAT); advancedMenu->menu()->setTitle(tr("&Advanced")); + cmd = am->registerAction(m_d->m_openInExternalEditorAction, Constants::OPEN_IN_EXTERNAL_EDITOR, editManagerContext); cmd->setDefaultKeySequence(QKeySequence(tr("Alt+V,Alt+I"))); advancedMenu->addAction(cmd); diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 729ac7cd845..eec20a4a05d 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/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp index c24e551c77e..ccf9c92322c 100644 --- a/src/plugins/coreplugin/fancytabwidget.cpp +++ b/src/plugins/coreplugin/fancytabwidget.cpp @@ -323,6 +323,7 @@ void FancyTabWidget::paintEvent(QPaintEvent *event) QPainter p(this); QRect rect = m_selectionWidget->rect().adjusted(0, 0, 1, 0); + rect = style()->visualRect(layoutDirection(), geometry(), rect); StyleHelper::verticalGradient(&p, rect, rect); p.setPen(StyleHelper::borderColor()); p.drawLine(rect.topRight(), rect.bottomRight()); diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui index 316637e6a06..f3b50c5e4b3 100644 --- a/src/plugins/coreplugin/generalsettings.ui +++ b/src/plugins/coreplugin/generalsettings.ui @@ -73,7 +73,7 @@ Reset to default - ... + R @@ -114,7 +114,7 @@ Reset to default - ... + R diff --git a/src/plugins/coreplugin/inavigationwidgetfactory.cpp b/src/plugins/coreplugin/inavigationwidgetfactory.cpp index 885277434d7..f2ac6d8d539 100644 --- a/src/plugins/coreplugin/inavigationwidgetfactory.cpp +++ b/src/plugins/coreplugin/inavigationwidgetfactory.cpp @@ -49,12 +49,12 @@ QKeySequence INavigationWidgetFactory::activationSequence() } -void INavigationWidgetFactory::saveSettings(int position, QWidget *widget) +void INavigationWidgetFactory::saveSettings(int /* position */, QWidget * /* widget */) { } -void INavigationWidgetFactory::restoreSettings(int position, QWidget *widget) +void INavigationWidgetFactory::restoreSettings(int /* position */, QWidget * /* widget */) { } diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 2a9fff0f4e3..f68c5da7d06 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/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 4f41be3fc81..5b72c891cd6 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -822,10 +822,12 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti } State mflags = bflags; - if (toolbutton->activeSubControls & SC_ToolButton) - bflags |= State_Sunken; - if (toolbutton->activeSubControls & SC_ToolButtonMenu) - mflags |= State_Sunken; + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + mflags |= State_Sunken; + } QStyleOption tool(0); tool.palette = toolbutton->palette; @@ -894,11 +896,12 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti tool.rect = tool.rect.adjusted(2, 2, -2, -2); drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { - int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); + int arrowSize = 6; QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1); QStyleOptionToolButton newBtn = *toolbutton; newBtn.palette = panelPalette(option->palette); - newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6); + newBtn.rect = QRect(ir.right() - arrowSize - 1, + ir.height() - arrowSize - 2, arrowSize, arrowSize); QWindowsStyle::drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); } } diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp index 9bbb4323d21..412559a9b0a 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 b9cd825e244..6d97c5d3611 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/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec index 7f3e1261af8..4d03eff8e3e 100644 --- a/src/plugins/cpaster/CodePaster.pluginspec +++ b/src/plugins/cpaster/CodePaster.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Codepaster plugin for pushing/fetching diff from server http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cppeditor/CppEditor.pluginspec b/src/plugins/cppeditor/CppEditor.pluginspec index 992f655d95b..c7fcd714e4f 100644 --- a/src/plugins/cppeditor/CppEditor.pluginspec +++ b/src/plugins/cppeditor/CppEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License C/C++ editor component. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index bfc9f3fd5c1..1eb298aa378 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -543,8 +543,8 @@ void CPPEditor::jumpToDefinition() foreach (const Document::MacroUse use, doc->macroUses()) { if (use.contains(endOfName - 1)) { const Macro ¯o = use.macro(); - const QString fileName = QString::fromUtf8(macro.fileName); - if (openCppEditorAt(fileName, macro.line, 0)) + const QString fileName = QString::fromUtf8(macro.fileName()); + if (openCppEditorAt(fileName, macro.line(), 0)) return; // done } } diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index f4060d0b60f..6ebf51b2a2c 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(); QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject()->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; @@ -271,8 +277,9 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in if (m_toolTip.isEmpty()) { foreach (const Document::MacroUse &use, doc->macroUses()) { if (use.contains(pos)) { - m_toolTip = use.macro().toString(); - m_helpId = use.macro().name; + const Macro m = use.macro(); + m_toolTip = m.toString(); + m_helpId = m.name(); break; } } diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec index 08690446e25..1ddf6664544 100644 --- a/src/plugins/cpptools/CppTools.pluginspec +++ b/src/plugins/cpptools/CppTools.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Tools for analyzing C/C++ code. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 1e54a2ae092..b1184420bf6 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -180,8 +180,6 @@ protected: } // namespace Internal } // namespace CppTools - - using namespace CppTools::Internal; FunctionArgumentWidget::FunctionArgumentWidget(Core::ICore *core) @@ -515,9 +513,9 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) { return m_startPosition; } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && - completeMember(exprTy, resolvedTypes, context)) { + completeMember(resolvedTypes, context)) { return m_startPosition; - } else if (m_completionOperator == T_COLON_COLON && completeScope(exprTy, resolvedTypes, context)) { + } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) { return m_startPosition; } else if (m_completionOperator == T_SIGNAL && completeSignal(exprTy, resolvedTypes, context)) { return m_startPosition; @@ -577,32 +575,42 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, return ! m_completions.isEmpty(); } -bool CppCodeCompletion::completeMember(FullySpecifiedType, - const QList &results, +bool CppCodeCompletion::completeMember(const QList &results, const LookupContext &context) { - QTC_ASSERT(!results.isEmpty(), return false); + if (results.isEmpty()) + return false; + TypeOfExpression::Result result = results.first(); QList classObjectCandidates; - TypeOfExpression::Result p = results.first(); - if (m_completionOperator == T_ARROW) { - FullySpecifiedType ty = p.first; + FullySpecifiedType ty = result.first; if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); + if (NamedType *namedTy = ty->asNamedType()) { + // ### This code is pretty slow. + const QList candidates = context.resolve(namedTy->name()); + foreach (Symbol *candidate, candidates) { + if (candidate->isTypedef()) { + ty = candidate->type(); + const ResolveExpression::Result r(ty, candidate); + result = r; + break; + } + } + } + if (NamedType *namedTy = ty->asNamedType()) { ResolveExpression resolveExpression(context); + ResolveClass resolveClass; - Name *className = namedTy->name(); - const QList candidates = - context.resolveClass(className, context.visibleScopes(p)); - + const QList candidates = resolveClass(result, context); foreach (Symbol *classObject, candidates) { const QList overloads = - resolveExpression.resolveArrowOperator(p, namedTy, + resolveExpression.resolveArrowOperator(result, namedTy, classObject->asClass()); foreach (TypeOfExpression::Result r, overloads) { @@ -619,8 +627,7 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); + resolveClass(namedTy, result, context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) @@ -632,29 +639,53 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, } } else if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { - const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); + ResolveClass resolveClass; + + const QList classes = resolveClass(namedTy, result, + context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) classObjectCandidates.append(c); } + } else if (Class *classTy = ptrTy->elementType()->asClass()) { + // typedef struct { int x } *Ptr; + // Ptr p; + // p-> + classObjectCandidates.append(classTy); } } } else if (m_completionOperator == T_DOT) { - FullySpecifiedType ty = p.first; + FullySpecifiedType ty = result.first; if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); NamedType *namedTy = 0; + + if (ArrayType *arrayTy = ty->asArrayType()) { + // Replace . with [0]. when `ty' is an array type. + FullySpecifiedType elementTy = arrayTy->elementType(); + + if (ReferenceType *refTy = elementTy->asReferenceType()) + elementTy = refTy->elementType(); + + if (elementTy->isNamedType() || elementTy->isPointerType()) { + ty = elementTy; + + const int length = m_editor->position() - m_startPosition + 1; + m_editor->setCurPos(m_startPosition - 1); + m_editor->replace(length, QLatin1String("[0].")); + m_startPosition += 3; + } + } + if (PointerType *ptrTy = ty->asPointerType()) { // Replace . with -> int length = m_editor->position() - m_startPosition + 1; m_editor->setCurPos(m_startPosition - 1); m_editor->replace(length, QLatin1String("->")); - m_startPosition++; + ++m_startPosition; namedTy = ptrTy->elementType()->asNamedType(); } else { namedTy = ty->asNamedType(); @@ -666,13 +697,14 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, } if (namedTy) { - const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); - - foreach (Symbol *c, classes) { - if (! classObjectCandidates.contains(c)) - classObjectCandidates.append(c); + ResolveClass resolveClass; + const QList symbols = resolveClass(namedTy, result, + context); + foreach (Symbol *symbol, symbols) { + if (classObjectCandidates.contains(symbol)) + continue; + if (Class *klass = symbol->asClass()) + classObjectCandidates.append(klass); } } } @@ -684,32 +716,45 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, return false; } -bool CppCodeCompletion::completeScope(FullySpecifiedType exprTy, - const QList &resolvedTypes, +bool CppCodeCompletion::completeScope(const QList &results, const LookupContext &context) { + if (results.isEmpty()) + return false; // nothing to do. + // Search for a class or a namespace. - foreach (TypeOfExpression::Result p, resolvedTypes) { - if (p.first->isClass() || p.first->isNamespace()) { - exprTy = p.first; + TypeOfExpression::Result result(FullySpecifiedType(), 0); + foreach (result, results) { + FullySpecifiedType ty = result.first; + + if (ty->isClass() || ty->isNamespace()) break; - } } - if (exprTy->asNamespace()) { + FullySpecifiedType exprTy = result.first; + if (! exprTy) { + return false; + } else if (exprTy->asNamespace()) { QList candidates; - foreach (TypeOfExpression::Result p, resolvedTypes) { + foreach (TypeOfExpression::Result p, results) { if (Namespace *ns = p.first->asNamespace()) candidates.append(ns); } completeNamespace(candidates, context); } else if (exprTy->isClass()) { QList candidates; - foreach (TypeOfExpression::Result p, resolvedTypes) { + foreach (TypeOfExpression::Result p, results) { if (Class *k = p.first->asClass()) candidates.append(k); } completeClass(candidates, context); + } else if (Symbol *symbol = result.second) { + if (symbol->isTypedef()) { + ResolveClass resolveClass; + const QList candidates = resolveClass(result, + context); + completeClass(candidates, context); + } } return ! m_completions.isEmpty(); @@ -741,7 +786,7 @@ void CppCodeCompletion::addMacros(const LookupContext &context) processed.insert(fn); if (Document::Ptr doc = context.document(fn)) { foreach (const Macro ¯o, doc->definedMacros()) { - macroNames.insert(macro.name); + macroNames.insert(macro.name()); } todo += doc->includedFiles(); } @@ -749,7 +794,7 @@ void CppCodeCompletion::addMacros(const LookupContext &context) foreach (const QByteArray ¯oName, macroNames) { TextEditor::CompletionItem item(this); - item.m_text = QString::fromLatin1(macroName.constData(), macroName.length()); + item.m_text = QString::fromUtf8(macroName.constData(), macroName.length()); item.m_icon = m_icons.macroIcon(); m_completions.append(item); } @@ -819,6 +864,8 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, if (results.isEmpty()) return false; + ResolveClass resolveClass; + ConvertToCompletionItem toCompletionItem(this); Overview o; o.setShowReturnTypes(false); @@ -839,10 +886,8 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, if (! namedTy) // not a class name. continue; - const QList visibleScopes = context.visibleScopes(p); - const QList classObjects = - context.resolveClass(namedTy->name(), visibleScopes); + resolveClass(namedTy, p, context); if (classObjects.isEmpty()) continue; @@ -850,6 +895,7 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, Class *klass = classObjects.first()->asClass(); QList todo; + const QList visibleScopes = context.visibleScopes(p); context.expand(klass->members(), visibleScopes, &todo); foreach (Scope *scope, todo) { diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index baf278e71d0..5720adbbc51 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -96,12 +96,10 @@ private: const QList &, const CPlusPlus::LookupContext &context); - bool completeMember(CPlusPlus::FullySpecifiedType exprTy, - const QList &, + bool completeMember(const QList &, const CPlusPlus::LookupContext &context); - bool completeScope(CPlusPlus::FullySpecifiedType exprTy, - const QList &, + bool completeScope(const QList &, const CPlusPlus::LookupContext &context); void completeNamespace(const QList &candidates, diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6dad51a6434..df611294751 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -144,7 +144,7 @@ private: QPointer m_modelManager; Snapshot m_snapshot; Environment env; - pp m_proc; + Preprocessor m_proc; QStringList m_includePaths; QStringList m_systemIncludePaths; QMap m_workingCopy; diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 4195fbee339..866a3d05c94 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.pluginspec b/src/plugins/debugger/Debugger.pluginspec index 399ac3c231a..b646c0bca20 100644 --- a/src/plugins/debugger/Debugger.pluginspec +++ b/src/plugins/debugger/Debugger.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Debugger integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/debugger/attachexternaldialog.cpp b/src/plugins/debugger/attachexternaldialog.cpp index c60130e6569..7ca50470fb5 100644 --- a/src/plugins/debugger/attachexternaldialog.cpp +++ b/src/plugins/debugger/attachexternaldialog.cpp @@ -49,12 +49,11 @@ using namespace Debugger::Internal; -AttachExternalDialog::AttachExternalDialog(QWidget *parent, const QString &pid) +AttachExternalDialog::AttachExternalDialog(QWidget *parent) : QDialog(parent) { setupUi(this); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - m_defaultPID = pid; m_model = new QStandardItemModel(this); procView->setSortingEnabled(true); @@ -65,8 +64,6 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent, const QString &pid) connect(procView, SIGNAL(activated(const QModelIndex &)), this, SLOT(procSelected(const QModelIndex &))); - - pidLineEdit->setText(m_defaultPID); rebuildProcessList(); } @@ -91,7 +88,7 @@ static void insertItem(QStandardItem *root, const QString &pid, //qDebug() << "HANDLING " << pid; QStandardItem *parent = 0; const ProcData &proc = procs[pid]; - if (1 || pid == "0") { + if (1 || pid == "0") { // FIXME: a real tree is not-so-nice to search parent = root; } else { if (!known.contains(proc.ppid)) @@ -148,189 +145,9 @@ void AttachExternalDialog::rebuildProcessList() procView->expandAll(); procView->resizeColumnToContents(0); procView->resizeColumnToContents(1); + procView->sortByColumn(1, Qt::AscendingOrder); } -#ifdef Q_OS_WINDOWS - -BOOL GetProcessList(); -BOOL ListProcessModules(DWORD dwPID); -BOOL ListProcessThreads(DWORD dwOwnerPID); -void printError(TCHAR *msg); - -BOOL GetProcessList() -{ - HANDLE hProcessSnap; - HANDLE hProcess; - PROCESSENTRY32 pe32; - DWORD dwPriorityClass; - - // Take a snapshot of all processes in the system. - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); - if (hProcessSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of processes)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if (!Process32First( hProcessSnap, &pe32 )) - { - printError( TEXT("Process32First") ); // show cause of failure - CloseHandle( hProcessSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - printf( "\n\n=====================================================" ); - _tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile ); - printf( "\n-----------------------------------------------------" ); - - // Retrieve the priority class. - dwPriorityClass = 0; - hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); - if (hProcess == NULL) - printError( TEXT("OpenProcess") ); - else - { - dwPriorityClass = GetPriorityClass( hProcess ); - if (!dwPriorityClass) - printError( TEXT("GetPriorityClass") ); - CloseHandle( hProcess ); - } - - printf( "\n Process ID = 0x%08X", pe32.th32ProcessID ); - printf( "\n Thread count = %d", pe32.cntThreads ); - printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID ); - printf( "\n Priority base = %d", pe32.pcPriClassBase ); - if (dwPriorityClass) - printf( "\n Priority class = %d", dwPriorityClass ); - - // List the modules and threads associated with this process - ListProcessModules( pe32.th32ProcessID ); - ListProcessThreads( pe32.th32ProcessID ); - - } while (Process32Next(hProcessSnap, &pe32)); - - CloseHandle(hProcessSnap); - return TRUE; -} - - -BOOL ListProcessModules(DWORD dwPID) -{ - HANDLE hModuleSnap = INVALID_HANDLE_VALUE; - MODULEENTRY32 me32; - - // Take a snapshot of all modules in the specified process. - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); - if (hModuleSnap == INVALID_HANDLE_VALUE) { - printError(TEXT("CreateToolhelp32Snapshot (of modules)")); - return FALSE; - } - - // Set the size of the structure before using it. - me32.dwSize = sizeof( MODULEENTRY32 ); - - // Retrieve information about the first module, - // and exit if unsuccessful - if (!Module32First( hModuleSnap, &me32)) - { - printError( TEXT("Module32First") ); // show cause of failure - CloseHandle( hModuleSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the module list of the process, - // and display information about each module - do - { - _tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule ); - _tprintf( TEXT("\n Executable = %s"), me32.szExePath ); - printf( "\n Process ID = 0x%08X", me32.th32ProcessID ); - printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage ); - printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage ); - printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr ); - printf( "\n Base size = %d", me32.modBaseSize ); - - } while (Module32Next(hModuleSnap, &me32)); - - CloseHandle(hModuleSnap); - return TRUE; -} - -BOOL ListProcessThreads( DWORD dwOwnerPID ) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First( hThreadSnap, &te32 )) - { - printError( TEXT("Thread32First") ); // show cause of failure - CloseHandle( hThreadSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID ); - printf( "\n Base priority = %d", te32.tpBasePri ); - printf( "\n Delta priority = %d", te32.tpDeltaPri ); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -void printError( TCHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while (*p > 31 || *p == 9 ) - ++p; - - do { - *p-- = 0; - } while( p >= sysMsg && (*p == '.' || *p < 33)); - - // Display the message - _tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg ); -} - -#endif - void AttachExternalDialog::procSelected(const QModelIndex &index0) { QModelIndex index = index0.sibling(index0.row(), 0); diff --git a/src/plugins/debugger/attachexternaldialog.h b/src/plugins/debugger/attachexternaldialog.h index 4970fa79258..d04d1bd61b5 100644 --- a/src/plugins/debugger/attachexternaldialog.h +++ b/src/plugins/debugger/attachexternaldialog.h @@ -48,7 +48,7 @@ class AttachExternalDialog : public QDialog, Ui::AttachExternalDialog Q_OBJECT public: - explicit AttachExternalDialog(QWidget *parent, const QString &pid); + explicit AttachExternalDialog(QWidget *parent); int attachPID() const; private slots: @@ -56,7 +56,6 @@ private slots: void procSelected(const QModelIndex &); private: - QString m_defaultPID; QStandardItemModel *m_model; }; diff --git a/src/plugins/debugger/attachremotedialog.cpp b/src/plugins/debugger/attachremotedialog.cpp index ffe21174239..e13d7b6ebc2 100644 --- a/src/plugins/debugger/attachremotedialog.cpp +++ b/src/plugins/debugger/attachremotedialog.cpp @@ -142,193 +142,6 @@ void AttachRemoteDialog::rebuildProcessList() procView->resizeColumnToContents(1); } -#ifdef Q_OS_WINDOWS - -#include -#include -#include -#include - -// Forward declarations: -BOOL GetProcessList(); -BOOL ListProcessModules(DWORD dwPID); -BOOL ListProcessThreads(DWORD dwOwnerPID); -void printError(TCHAR* msg); - -BOOL GetProcessList( ) -{ - HANDLE hProcessSnap; - HANDLE hProcess; - PROCESSENTRY32 pe32; - DWORD dwPriorityClass; - - // Take a snapshot of all processes in the system. - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); - if (hProcessSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of processes)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if (!Process32First( hProcessSnap, &pe32 )) - { - printError( TEXT("Process32First") ); // show cause of failure - CloseHandle( hProcessSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - printf( "\n\n=====================================================" ); - _tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile ); - printf( "\n-----------------------------------------------------" ); - - // Retrieve the priority class. - dwPriorityClass = 0; - hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); - if (hProcess == NULL) - printError( TEXT("OpenProcess") ); - else - { - dwPriorityClass = GetPriorityClass( hProcess ); - if (!dwPriorityClass) - printError( TEXT("GetPriorityClass") ); - CloseHandle( hProcess ); - } - - printf( "\n Process ID = 0x%08X", pe32.th32ProcessID ); - printf( "\n Thread count = %d", pe32.cntThreads ); - printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID ); - printf( "\n Priority base = %d", pe32.pcPriClassBase ); - if (dwPriorityClass) - printf( "\n Priority class = %d", dwPriorityClass ); - - // List the modules and threads associated with this process - ListProcessModules( pe32.th32ProcessID ); - ListProcessThreads( pe32.th32ProcessID ); - - } while( Process32Next( hProcessSnap, &pe32 ) ); - - CloseHandle( hProcessSnap ); - return( TRUE ); -} - - -BOOL ListProcessModules( DWORD dwPID ) -{ - HANDLE hModuleSnap = INVALID_HANDLE_VALUE; - MODULEENTRY32 me32; - - // Take a snapshot of all modules in the specified process. - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); - if (hModuleSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of modules)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - me32.dwSize = sizeof( MODULEENTRY32 ); - - // Retrieve information about the first module, - // and exit if unsuccessful - if (!Module32First( hModuleSnap, &me32 )) - { - printError( TEXT("Module32First") ); // show cause of failure - CloseHandle( hModuleSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the module list of the process, - // and display information about each module - do - { - _tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule ); - _tprintf( TEXT("\n Executable = %s"), me32.szExePath ); - printf( "\n Process ID = 0x%08X", me32.th32ProcessID ); - printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage ); - printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage ); - printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr ); - printf( "\n Base size = %d", me32.modBaseSize ); - - } while( Module32Next( hModuleSnap, &me32 ) ); - - CloseHandle( hModuleSnap ); - return( TRUE ); -} - -BOOL ListProcessThreads( DWORD dwOwnerPID ) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First( hThreadSnap, &te32 )) - { - printError( TEXT("Thread32First") ); // show cause of failure - CloseHandle( hThreadSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID ); - printf( "\n Base priority = %d", te32.tpBasePri ); - printf( "\n Delta priority = %d", te32.tpDeltaPri ); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -void printError( TCHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - _tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg ); -} - -#endif - - void AttachRemoteDialog::procSelected(const QModelIndex &index0) { QModelIndex index = index0.sibling(index0.row(), 0); diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 7308fb441c2..b47e7d5ee02 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/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 119868ab09c..2d6def04da4 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -804,8 +804,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_workingDir = QString(); m_attachedPID = -1; } else if (startMode() == attachExternal) { - QString pid; - AttachExternalDialog dlg(mainWindow(), pid); + AttachExternalDialog dlg(mainWindow()); if (dlg.exec() != QDialog::Accepted) return false; m_executable = QString(); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 0f50ea461a5..d65f9ac9acd 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -63,10 +63,10 @@ #include #include -#include #include #include #include +#include #include #include diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 957a223db47..fa6f9ab3250 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -650,7 +650,7 @@ void GdbEngine::interruptInferior() if (m_gdbProc.state() == QProcess::NotRunning) return; - if (q->m_attachedPID) { + if (q->m_attachedPID > 0) { if (interruptProcess(q->m_attachedPID)) qq->notifyInferiorStopped(); return; @@ -660,6 +660,7 @@ void GdbEngine::interruptInferior() sendCommand("-exec-interrupt", GdbExecInterrupt); qq->notifyInferiorStopped(); #else + qDebug() << "CANNOT STOP INFERIOR" << m_gdbProc.pid(); if (interruptChildProcess(m_gdbProc.pid())) qq->notifyInferiorStopped(); #endif @@ -672,9 +673,9 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) qDebug() << "Cannot parse PID from " << pid0; return; } - if (pid == m_inferiorPid) + if (pid == q->m_attachedPID) return; - m_inferiorPid = pid; + q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } @@ -1514,7 +1515,6 @@ int GdbEngine::currentFrame() const bool GdbEngine::startDebugger() { - m_inferiorPid = 0; QStringList gdbArgs; QFileInfo fi(q->m_executable); @@ -1616,7 +1616,7 @@ bool GdbEngine::startDebugger() sendCommand("attach " + QString::number(q->m_attachedPID)); } - if (q->startMode() == q->startInternal) { + if (q->startMode() == q->startInternal || q->startMode() == q->startExternal) { sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); #ifdef Q_OS_MAC sendCommand("sharedlibrary apply-load-rules all"); @@ -2401,7 +2401,7 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record) if (usable) q->gotoLocation(frame.file, frame.line, true); else - qDebug() << "FULL NAME NOT USABLE 0: " << frame.file; + qDebug() << "FULL NAME NOT USABLE 0: " << frame.file << topFrame; } #endif } @@ -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"; @@ -2961,11 +2961,11 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) // in rare cases we need more or less: if (outertype == m_namespace + "QObject") { - extraArgs[extraArgCount++] = "(char*)&((('" + extraArgs[0] = "(char*)&((('" + m_namespace + "QObjectPrivate'*)&" + data.exp + ")->children)-(char*)&" + data.exp; } else if (outertype == m_namespace + "QVector") { - extraArgs[extraArgCount++] = "(char*)&((" + extraArgs[1] = "(char*)&((" + data.exp + ").d->array)-(char*)" + data.exp + ".d"; } else if (outertype == m_namespace + "QObjectSlot" || outertype == m_namespace + "QObjectSignal") { @@ -2976,16 +2976,23 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) QString slotNumber = "-1"; if (lastOpened != -1 && lastClosed != -1) slotNumber = data.iname.mid(lastOpened + 1, lastClosed - lastOpened - 1); - extraArgs[extraArgCount++] = 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; - extraArgs[extraArgCount++] = sizeofTypeExpression(nodetype); - extraArgs[extraArgCount++] = "(size_t)&(('" + nodetype + "'*)0)->value"; + extraArgs[0] = slotNumber; + } 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") { - extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); - extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; + extraArgs[2] = sizeofTypeExpression(data.type); + extraArgs[3] = "(size_t)&(('" + data.type + "'*)0)->value"; } else if (outertype == "std::vector") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "bool") { @@ -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")); @@ -3945,10 +3963,15 @@ void GdbEngine::tryLoadCustomDumpers() if (qq->useFastStart()) sendCommand("set stop-on-solib-events 0"); QString flag = QString::number(RTLD_NOW); - sendCommand("call dlopen(\"" + lib + "\", " + flag + ")"); + sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")"); + // some older systems like CentOS 4.6 prefer this: + sendCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")"); 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) @@ -3962,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) @@ -3975,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 434a110a454..000c0b84a95 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -330,10 +330,10 @@ private: QString m_editedData; int m_pendingRequests; - int m_inferiorPid; 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 m_currentFunctionArgs; diff --git a/src/plugins/debugger/mode.ui b/src/plugins/debugger/mode.ui deleted file mode 100644 index da44cf38b4a..00000000000 --- a/src/plugins/debugger/mode.ui +++ /dev/null @@ -1,76 +0,0 @@ - - DebugMode - - - - 0 - 0 - 558 - 353 - - - - Form - - - - 0 - - - 0 - - - - - Qt::Vertical - - - - - 10 - 10 - - - - - - - 0 - - - - - 0 - - - - - - - Qt::Horizontal - - - - - 0 - 0 - - - - QTabWidget::South - - - QTabWidget::Rounded - - - - - - - - - - - - - diff --git a/src/plugins/debugger/startexternaldialog.cpp b/src/plugins/debugger/startexternaldialog.cpp index b8a5a59691f..ba88f5f74c2 100644 --- a/src/plugins/debugger/startexternaldialog.cpp +++ b/src/plugins/debugger/startexternaldialog.cpp @@ -42,6 +42,8 @@ StartExternalDialog::StartExternalDialog(QWidget *parent) : QDialog(parent) { setupUi(this); + execFile->setExpectedKind(Core::Utils::PathChooser::File); + execFile->setPromptDialogTitle(tr("Select Executable")); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); //execLabel->setHidden(false); @@ -53,14 +55,11 @@ StartExternalDialog::StartExternalDialog(QWidget *parent) connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - connect(browseButton, SIGNAL(clicked()), - this, SLOT(onBrowseButton())); } void StartExternalDialog::setExecutableFile(const QString &str) { - execEdit->setText(str); + execFile->setPath(str); } void StartExternalDialog::setExecutableArguments(const QString &str) @@ -70,7 +69,7 @@ void StartExternalDialog::setExecutableArguments(const QString &str) QString StartExternalDialog::executableFile() const { - return execEdit->text(); + return execFile->path(); } QString StartExternalDialog::executableArguments() const @@ -116,10 +115,3 @@ QString StartExternalDialog::executableArguments() const return result; */ } - -void StartExternalDialog::onBrowseButton() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Select Executable"), - execEdit->text()); - execEdit->setText(fileName); -} diff --git a/src/plugins/debugger/startexternaldialog.h b/src/plugins/debugger/startexternaldialog.h index 3cfe4c54206..0707252774d 100644 --- a/src/plugins/debugger/startexternaldialog.h +++ b/src/plugins/debugger/startexternaldialog.h @@ -53,9 +53,6 @@ public: QString executableFile() const; QString executableArguments() const; - -private slots: - void onBrowseButton(); }; } // namespace Debugger diff --git a/src/plugins/debugger/startexternaldialog.ui b/src/plugins/debugger/startexternaldialog.ui index 7888db2a3e6..1b93356584c 100644 --- a/src/plugins/debugger/startexternaldialog.ui +++ b/src/plugins/debugger/startexternaldialog.ui @@ -1,7 +1,8 @@ - + + StartExternalDialog - - + + 0 0 @@ -9,59 +10,52 @@ 127 - + Start Debugger - - + + 6 - + 9 - - + + 0 - + 6 - - - - - - - - - + + + Executable: - - - - ... - - - - - - + + + Arguments: + + + + + + - + Qt::Vertical - + 407 16 @@ -70,24 +64,32 @@ - - + + Qt::Horizontal - - + + Qt::Horizontal - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index a370802b813..25fa770823d 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1204,13 +1204,13 @@ void WatchHandler::loadWatchers() QVariant value; sessionValueRequested("Watchers", &value); m_watchers = value.toStringList(); - qDebug() << "LOAD WATCHERS: " << m_watchers; + //qDebug() << "LOAD WATCHERS: " << m_watchers; reinitializeWatchersHelper(); } void WatchHandler::saveWatchers() { - qDebug() << "SAVE WATCHERS: " << m_watchers; + //qDebug() << "SAVE WATCHERS: " << m_watchers; setSessionValueRequested("Watchers", m_watchers); } diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index dfcc98250de..97d27d5f016 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -55,7 +55,8 @@ enum { INameRole = Qt::UserRole, VisualRole, ExpandedRole }; ///////////////////////////////////////////////////////////////////// WatchWindow::WatchWindow(Type type, QWidget *parent) - : QTreeView(parent), m_type(type) + : QTreeView(parent), m_type(type) + , m_alwaysResizeColumnsToContents(true) { setWindowTitle(tr("Locals and Watchers")); setAlternatingRowColors(true); diff --git a/src/plugins/designer/Designer.pluginspec b/src/plugins/designer/Designer.pluginspec index bc57324c4fb..7428e6df660 100644 --- a/src/plugins/designer/Designer.pluginspec +++ b/src/plugins/designer/Designer.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Qt Designer integration. http://www.trolltech.com/ - + - + diff --git a/src/plugins/designer/cpp/formclasswizardparameters.cpp b/src/plugins/designer/cpp/formclasswizardparameters.cpp index 19fdd7f3527..2441cddc3a0 100644 --- a/src/plugins/designer/cpp/formclasswizardparameters.cpp +++ b/src/plugins/designer/cpp/formclasswizardparameters.cpp @@ -62,8 +62,15 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in return false; } + // Build the ui class (Ui::Foo) name relative to the namespace (which is the same): + const QString colonColon = QLatin1String("::"); + const int lastSeparator = uiClassName.lastIndexOf(colonColon); + if (lastSeparator != -1) + uiClassName.remove(0, lastSeparator + colonColon.size()); + uiClassName.insert(0, QLatin1String(uiNamespaceC) + colonColon); + // Do we have namespaces? - QStringList namespaceList = className.split(QLatin1String("::")); + QStringList namespaceList = className.split(colonColon); if (namespaceList.empty()) // Paranoia! return false; @@ -94,18 +101,21 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in } } + const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr); + // Forward-declare the UI class if (embedding == PointerAggregatedUiClass) { - headerStr << "\nnamespace " << uiNamespaceC << " {\n" - << indent << "class " << uiClassName << ";\n}\n"; + headerStr << '\n' + << namespaceIndent << "namespace " << uiNamespaceC << " {\n" + << namespaceIndent << indent << "class " << FormTemplateWizardPagePage::stripNamespaces(uiClassName) << ";\n" + << namespaceIndent << "}\n"; } - const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr); // Class declaration headerStr << '\n' << namespaceIndent << "class " << unqualifiedClassName << " : public " << formBaseClass; if (embedding == InheritedUiClass) { - headerStr << ", private " << uiNamespaceC << "::" << uiClassName; + headerStr << ", private " << uiClassName; } headerStr << " {\n" << namespaceIndent << indent << "Q_OBJECT\n" << namespaceIndent << indent << "Q_DISABLE_COPY(" << unqualifiedClassName << ")\n" @@ -120,7 +130,7 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in // Member variable if (embedding != InheritedUiClass) { headerStr << '\n' << namespaceIndent << "private:\n" - << namespaceIndent << indent << uiNamespaceC << "::" << uiClassName << ' '; + << namespaceIndent << indent << uiClassName << ' '; if (embedding == PointerAggregatedUiClass) headerStr << '*'; headerStr << uiMemberC << ";\n"; @@ -140,7 +150,7 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName << "(QWidget *parent) :\n" << namespaceIndent << indent << formBaseClass << "(parent)"; if (embedding == PointerAggregatedUiClass) - sourceStr << ",\n" << namespaceIndent << indent << uiMemberC << "(new " << uiNamespaceC << "::" << uiClassName << ")\n"; + sourceStr << ",\n" << namespaceIndent << indent << uiMemberC << "(new " << uiClassName << ")\n"; sourceStr << namespaceIndent << "{\n" << namespaceIndent << indent; if (embedding != InheritedUiClass) sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : "."); diff --git a/src/plugins/designer/workbenchintegration.cpp b/src/plugins/designer/workbenchintegration.cpp index 8483c2f1d9a..0291bd21058 100644 --- a/src/plugins/designer/workbenchintegration.cpp +++ b/src/plugins/designer/workbenchintegration.cpp @@ -59,6 +59,7 @@ #include enum { debugSlotNavigation = 0 }; +enum { indentation = 4 }; using namespace Designer::Internal; using namespace CPlusPlus; @@ -75,6 +76,12 @@ static QString msgClassNotFound(const QString &uiClassName, const QListgetObject(); + return core->pluginManager()->getObject(); +} + WorkbenchIntegration::WorkbenchIntegration(QDesignerFormEditorInterface *core, FormEditorW *parent) : qdesigner_internal::QDesignerIntegration(core, ::qobject_cast(parent)), m_few(parent) @@ -101,18 +108,13 @@ QWidget *WorkbenchIntegration::containerWindow(QWidget * /*widget*/) const return fw->integrationContainer(); } -static QList findDocumentsIncluding(const QString &fileName, bool checkFileNameOnly) +static QList findDocumentsIncluding(const CPlusPlus::Snapshot &docTable, + const QString &fileName, bool checkFileNameOnly) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); - QList docList; - // take all docs - CPlusPlus::Snapshot docTable = cppModelManager->snapshot(); - foreach (Document::Ptr doc, docTable) { // we go through all documents - QStringList includes = doc->includedFiles(); - foreach (QString include, includes) { + foreach (const Document::Ptr &doc, docTable) { // we go through all documents + const QStringList includes = doc->includedFiles(); + foreach (const QString &include, includes) { if (checkFileNameOnly) { const QFileInfo fi(include); if (fi.fileName() == fileName) { // we are only interested in docs which includes fileName only @@ -127,78 +129,79 @@ static QList findDocumentsIncluding(const QString &fileName, bool return docList; } -static Class *findClass(Namespace *parentNameSpace, const QString &uiClassName, QString *namespaceName) +// Check for a class name where haystack is a member class of an object. +// So, haystack can be shorter (can have some namespaces omitted because of a +// "using namespace" declaration, for example, comparing +// "foo::Ui::form", against "using namespace foo; Ui::form". + +static bool matchMemberClassName(const QString &needle, const QString &hayStack) { - // construct proper ui class name, take into account namespaced ui class name - QString className1; - QString className2; - int indexOfScope = uiClassName.lastIndexOf(QLatin1String("::")); - if (indexOfScope < 0) { - className1 = QLatin1String("Ui::") + uiClassName; - className2 = QLatin1String("Ui_") + uiClassName; - } else { - className1 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui::") + uiClassName.mid(indexOfScope + 2); - className2 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui_") + uiClassName.mid(indexOfScope + 2); - } + if (needle == hayStack) + return true; + if (!needle.endsWith(hayStack)) + return false; + // Check if there really is a separator "::" + const int separatorPos = needle.size() - hayStack.size() - 1; + return separatorPos > 1 && needle.at(separatorPos) == QLatin1Char(':'); +} - for (unsigned i = 0; i < parentNameSpace->memberCount(); i++) { // we go through all namespace members - if (Class *cl = parentNameSpace->memberAt(i)->asClass()) { // we have found a class - we are interested in classes only - Overview o; - QString className = o.prettyName(cl->name()); - for (unsigned j = 0; j < cl->memberCount(); j++) { // we go through class members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to know if the class contains a member (so we look into a declaration) of uiClassName type - NamedType *nt = decl->type()->asNamedType(); +// Find class definition in namespace +static const Class *findClass(const Namespace *parentNameSpace, const QString &className, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << className; + const Overview o; + const unsigned namespaceMemberCount = parentNameSpace->memberCount(); + for (unsigned i = 0; i < namespaceMemberCount; i++) { // we go through all namespace members + const Symbol *sym = parentNameSpace->memberAt(i); + // we have found a class - we are interested in classes only + if (const Class *cl = sym->asClass()) { + const unsigned classMemberCount = cl->memberCount(); + for (unsigned j = 0; j < classMemberCount; j++) // we go through class members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) { + // we want to know if the class contains a member (so we look into + // a declaration) of uiClassName type + const NamedType *nt = decl->type()->asNamedType(); // handle pointers to member variables if (PointerType *pt = decl->type()->asPointerType()) nt = pt->elementType()->asNamedType(); - if (nt) { - Overview typeOverview; - const QString memberClass = typeOverview.prettyName(nt->name()); - if (memberClass == className1 || memberClass == className2) // names match + if (nt && matchMemberClassName(className, o.prettyName(nt->name()))) return cl; - // memberClass can be shorter (can have some namespaces cut because of e.g. "using namespace" declaration) - if (memberClass == className1.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className1.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - // the same as above but for className2 - if (memberClass == className2.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className2.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - } + } // decl + } else { + // Check namespaces + if (const Namespace *ns = sym->asNamespace()) { + QString tempNS = *namespaceName; + tempNS += o.prettyName(ns->name()); + tempNS += QLatin1String("::"); + if (const Class *cl = findClass(ns, className, &tempNS)) { + *namespaceName = tempNS; + return cl; } - } - } else if (Namespace *ns = parentNameSpace->memberAt(i)->asNamespace()) { - Overview o; - QString tempNS = *namespaceName + o.prettyName(ns->name()) + QLatin1String("::"); - Class *cl = findClass(ns, uiClassName, &tempNS); - if (cl) { - *namespaceName = tempNS; - return cl; - } - } - } + } // member is namespave + } // member is no class + } // for members return 0; } -static Function *findDeclaration(Class *cl, const QString &functionName) +static const Function *findDeclaration(const Class *cl, const QString &functionName) { const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8())); - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we are interested only in declarations (can be decl of method or of a field) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods - Overview overview; - QString memberFunction = overview.prettyName(fun->name()) + QLatin1Char('('); - for (uint i = 0; i < fun->argumentCount(); i++) { // we build argument types string - Argument *arg = fun->argumentAt(i)->asArgument(); + const unsigned mCount = cl->memberCount(); + // we are interested only in declarations (can be decl of method or of a field) + // we are only interested in declarations of methods + const Overview overview; + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // Format signature + QString memberFunction = overview.prettyName(fun->name()); + memberFunction += QLatin1Char('('); + const uint aCount = fun->argumentCount(); + for (uint i = 0; i < aCount; i++) { // we build argument types string + const Argument *arg = fun->argumentAt(i)->asArgument(); if (i > 0) memberFunction += QLatin1Char(','); memberFunction += overview.prettyType(arg->type()); @@ -209,19 +212,18 @@ static Function *findDeclaration(Class *cl, const QString &functionName) if (memberFunction == funName) // we match function names and argument lists return fun; } - } } return 0; } // TODO: remove me, see below -static bool isCompatible(Name *name, Name *otherName) +static bool isCompatible(const Name *name, const Name *otherName) { - if (NameId *nameId = name->asNameId()) { - if (TemplateNameId *otherTemplId = otherName->asTemplateNameId()) + if (const NameId *nameId = name->asNameId()) { + if (const TemplateNameId *otherTemplId = otherName->asTemplateNameId()) return nameId->identifier()->isEqualTo(otherTemplId->identifier()); - } else if (TemplateNameId *templId = name->asTemplateNameId()) { - if (NameId *otherNameId = otherName->asNameId()) + } else if (const TemplateNameId *templId = name->asTemplateNameId()) { + if (const NameId *otherNameId = otherName->asNameId()) return templId->identifier()->isEqualTo(otherNameId->identifier()); } @@ -229,7 +231,7 @@ static bool isCompatible(Name *name, Name *otherName) } // TODO: remove me, see below -static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNameId *declarationName) +static bool isCompatible(const Function *definition, const Symbol *declaration, const QualifiedNameId *declarationName) { Function *declTy = declaration->type()->asFunction(); if (! declTy) @@ -269,11 +271,9 @@ static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNam } // TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method -static Document::Ptr findDefinition(Function *functionDeclaration, int *line) +static Document::Ptr findDefinition(const Function *functionDeclaration, int *line) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); + CppTools::CppModelManagerInterface *cppModelManager = cppModelManagerInstance(); if (!cppModelManager) return Document::Ptr(); @@ -286,7 +286,8 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) if (QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { for (unsigned i = 0; i < q->nameCount(); ++i) { qualifiedName.prepend(q->nameAt(i)); - } + +} } else { qualifiedName.prepend(scopeOwnerName); } @@ -299,7 +300,6 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) Control control; QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); LookupContext context(&control); - const Snapshot documents = cppModelManager->snapshot(); foreach (Document::Ptr doc, documents) { QList visibleScopes; @@ -368,71 +368,80 @@ static int findClassEndPosition(const QString &headerContents, int classStartPos return -1; } -static void addDeclaration(const QString &docFileName, Class *cl, const QString &functionName) +static inline ITextEditable *editableAt(const QString &fileName, int line, int column) { - // functionName comes already with argument names (if designer managed to do that) - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to find any method which is a private slot (then we don't need to add "private slots:" statement) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods + return qobject_cast(TextEditor::BaseTextEditor::openEditorAt(fileName, line, column)); +} + +static void addDeclaration(const QString &docFileName, const Class *cl, const QString &functionName) +{ + QString declaration = QLatin1String("void "); + declaration += functionName; + declaration += QLatin1String(";\n"); + + // functionName comes already with argument names (if designer managed to + // do that). First, let's try to find any method which is a private slot + // (then we don't need to add "private slots:" statement) + const unsigned mCount = cl->memberCount(); + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // we are only interested in declarations of methods. + // fun->column() returns always 0, what can cause trouble in case in one + // line if there is: "private slots: void foo();" if (fun->isSlot() && fun->isPrivate()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, fun->line(), fun->column())); - // fun->column() raturns always 0, what can cause trouble in case in one - // line there is: "private slots: void foo();" - if (editable) { - editable->insert(QLatin1String("void ") + functionName + QLatin1String(";\n ")); - } + if (ITextEditable *editable = editableAt(docFileName, fun->line(), fun->column())) + editable->insert(declaration + QLatin1String(" ")); return; } } - } } // We didn't find any method under "private slots:", let's add "private slots:". Below code // adds "private slots:" by the end of the class definition. - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, cl->line(), cl->column())); - if (editable) { + if (ITextEditable *editable = editableAt(docFileName, cl->line(), cl->column())) { int classEndPosition = findClassEndPosition(editable->contents(), editable->position()); if (classEndPosition >= 0) { int line, column; editable->convertPosition(classEndPosition, &line, &column); // converts back position into a line and column editable->gotoLine(line, column); // go to position (we should be just before closing } of the class) - editable->insert(QLatin1String("\nprivate slots:\n ") - + QLatin1String("void ") + functionName + QLatin1String(";\n")); + editable->insert(QLatin1String("\nprivate slots:\n ") + declaration); } } } -static Document::Ptr addDefinition(const QString &headerFileName, const QString &className, - const QString &functionName, int *line) +static Document::Ptr addDefinition(const CPlusPlus::Snapshot &docTable, + const QString &headerFileName, const QString &className, + const QString &functionName, int *line) { + QString definition = QLatin1String("\nvoid "); + definition += className; + definition += QLatin1String("::"); + definition += functionName; + definition += QLatin1String("\n{\n"); + definition += QString(indentation, QLatin1Char(' ')); + definition += QLatin1String("\n}\n"); + // we find all documents which include headerFileName - QList docList = findDocumentsIncluding(headerFileName, false); + const QList docList = findDocumentsIncluding(docTable, headerFileName, false); if (docList.isEmpty()) return Document::Ptr(); QFileInfo headerFI(headerFileName); const QString headerBaseName = headerFI.baseName(); const QString headerAbsolutePath = headerFI.absolutePath(); - foreach (Document::Ptr doc, docList) { - QFileInfo sourceFI(doc->fileName()); + foreach (const Document::Ptr &doc, docList) { + const QFileInfo sourceFI(doc->fileName()); // we take only those documents which has the same filename and path (maybe we don't need to compare the path???) if (headerBaseName == sourceFI.baseName() && headerAbsolutePath == sourceFI.absolutePath()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(doc->fileName(), 0)); - if (editable) { + if (ITextEditable *editable = editableAt(doc->fileName(), 0, 0)) { const QString contents = editable->contents(); int column; editable->convertPosition(contents.length(), line, &column); editable->gotoLine(*line, column); - editable->insert(QLatin1String("\nvoid ") + className + QLatin1String("::") + - functionName + QLatin1String("\n {\n\n }\n")); + editable->insert(definition); *line += 1; - } return doc; } @@ -440,33 +449,84 @@ static Document::Ptr addDefinition(const QString &headerFileName, const QString return Document::Ptr(); } +// Insert the parameter names into a signature, "void foo(bool)" -> +// "void foo(bool checked)" static QString addParameterNames(const QString &functionSignature, const QStringList ¶meterNames) { - QString functionName = functionSignature.left(functionSignature.indexOf(QLatin1Char('(')) + 1); - QString argumentsString = functionSignature.mid(functionSignature.indexOf(QLatin1Char('(')) + 1); - argumentsString = argumentsString.left(argumentsString.indexOf(QLatin1Char(')'))); + const int firstParen = functionSignature.indexOf(QLatin1Char('(')); + QString functionName = functionSignature.left(firstParen + 1); + QString argumentsString = functionSignature.mid(firstParen + 1); + const int lastParen = argumentsString.lastIndexOf(QLatin1Char(')')); + if (lastParen != -1) + argumentsString.truncate(lastParen); const QStringList arguments = argumentsString.split(QLatin1Char(','), QString::SkipEmptyParts); - for (int i = 0; i < arguments.count(); ++i) { + const int pCount = parameterNames.count(); + const int aCount = arguments.count(); + for (int i = 0; i < aCount; ++i) { if (i > 0) functionName += QLatin1String(", "); functionName += arguments.at(i); - if (i < parameterNames.count()) - functionName += QLatin1Char(' ') + parameterNames.at(i); + if (i < pCount) { + functionName += QLatin1Char(' '); + functionName += parameterNames.at(i); + } } functionName += QLatin1Char(')'); return functionName; } +// Recursively find a class definition in the document passed on or in its +// included files (going down [maxIncludeDepth] includes) and return a pair +// of . + +typedef QPair ClassDocumentPtrPair; + +static ClassDocumentPtrPair + findClassRecursively(const CPlusPlus::Snapshot &docTable, + const Document::Ptr &doc, const QString &className, + unsigned maxIncludeDepth, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << doc->fileName() << maxIncludeDepth; + // Check document + if (const Class *cl = findClass(doc->globalNamespace(), className, namespaceName)) + return ClassDocumentPtrPair(cl, doc); + if (maxIncludeDepth) { + // Check the includes + const unsigned recursionMaxIncludeDepth = maxIncludeDepth - 1u; + foreach (const QString &include, doc->includedFiles()) { + const CPlusPlus::Snapshot::const_iterator it = docTable.constFind(include); + if (it != docTable.constEnd()) { + const Document::Ptr includeDoc = it.value(); + const ClassDocumentPtrPair irc = findClassRecursively(docTable, it.value(), className, recursionMaxIncludeDepth, namespaceName); + if (irc.first) + return irc; + } + } + } + return ClassDocumentPtrPair(0, Document::Ptr()); +} void WorkbenchIntegration::slotNavigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames) { QString errorMessage; if (!navigateToSlot(objectName, signalSignature, parameterNames, &errorMessage) && !errorMessage.isEmpty()) { - QMessageBox::critical(m_few->designerEditor()->topLevel(), tr("Error finding source file"), errorMessage); + QMessageBox::warning(m_few->designerEditor()->topLevel(), tr("Error finding/adding a slot."), errorMessage); } } +// Build name of the class as generated by uic, insert Ui namespace +// "foo::bar::form" -> "foo::bar::Ui::form" + +static inline QString uiClassName(QString formObjectName) +{ + const int indexOfScope = formObjectName.lastIndexOf(QLatin1String("::")); + const int uiNameSpaceInsertionPos = indexOfScope >= 0 ? indexOfScope : 0; + formObjectName.insert(uiNameSpaceInsertionPos, QLatin1String("Ui::")); + return formObjectName; +} + bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames, @@ -482,7 +542,10 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QFileInfo fi(currentUiFile); const QString uicedName = QLatin1String("ui_") + fi.baseName() + QLatin1String(".h"); - QList docList = findDocumentsIncluding(uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file + // take all docs + + const CPlusPlus::Snapshot docTable = cppModelManagerInstance()->snapshot(); + QList docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file if (debugSlotNavigation) qDebug() << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size(); @@ -493,44 +556,63 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, QDesignerFormWindowInterface *fwi = m_few->activeFormWindow()->formWindow(); - const QString uiClassName = fwi->mainContainer()->objectName(); + const QString uiClass = uiClassName(fwi->mainContainer()->objectName()); if (debugSlotNavigation) - qDebug() << "Checking docs for " << uiClassName; + qDebug() << "Checking docs for " << uiClass; - foreach (const Document::Ptr &doc, docList) { - QString namespaceName; // namespace of the class found - Class *cl = findClass(doc->globalNamespace(), uiClassName, &namespaceName); - if (cl) { - Overview o; - const QString className = namespaceName + o.prettyName(cl->name()); + // Find the class definition in the file itself or in the directly + // included files (order 1). + QString namespaceName; + const Class *cl; + Document::Ptr doc; - QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; - QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); - Function *fun = findDeclaration(cl, functionName); - int line = 0; - Document::Ptr sourceDoc; - if (!fun) { - // add function declaration to cl - addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); - - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } else { - sourceDoc = findDefinition(fun, &line); - if (!sourceDoc) { - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } - } - if (sourceDoc) { - // jump to function definition - TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line); - } - return true; + foreach (const Document::Ptr &d, docList) { + const ClassDocumentPtrPair cd = findClassRecursively(docTable, d, uiClass, 1u , &namespaceName); + if (cd.first) { + cl = cd.first; + doc = cd.second; + break; } } - *errorMessage = msgClassNotFound(uiClassName, docList); - return false; -} + if (!cl) { + *errorMessage = msgClassNotFound(uiClass, docList); + return false; + } + Overview o; + const QString className = namespaceName + o.prettyName(cl->name()); + + const QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; + const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); + + if (debugSlotNavigation) + qDebug() << "Found " << uiClass << doc->fileName() << " checking " << functionName << functionNameWithParameterNames; + + int line = 0; + Document::Ptr sourceDoc; + + if (const Function *fun = findDeclaration(cl, functionName)) { + sourceDoc = findDefinition(fun, &line); + if (!sourceDoc) { + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + } else { + // add function declaration to cl + addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); + + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + + if (!sourceDoc) { + *errorMessage = tr("Unable to add the method definition."); + return false; + } + + // jump to function definition, position within code + TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line + 2, indentation); + + return true; +} diff --git a/src/plugins/fakevim/FakeVim.pluginspec b/src/plugins/fakevim/FakeVim.pluginspec new file mode 100644 index 00000000000..66a091e283d --- /dev/null +++ b/src/plugins/fakevim/FakeVim.pluginspec @@ -0,0 +1,12 @@ + + Nokia Corporation + (C) 2008 Nokia Corporation + Nokia Beta Version License + VI-style keyboard navigation. + http://www.trolltech.com/ + + + + + + diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro new file mode 100644 index 00000000000..6a160774e6a --- /dev/null +++ b/src/plugins/fakevim/fakevim.pro @@ -0,0 +1,19 @@ +TEMPLATE = lib +TARGET = FakeVim + +# CONFIG += single +include(../../qworkbenchplugin.pri) +include(../../plugins/projectexplorer/projectexplorer.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/texteditor/texteditor.pri) + +# DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII +QT += gui + +SOURCES += \ + handler.cpp \ + fakevimplugin.cpp + +HEADERS += \ + handler.h \ + fakevimplugin.h diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp new file mode 100644 index 00000000000..97e1cfffea0 --- /dev/null +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -0,0 +1,177 @@ +/*************************************************************************** +** +** 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 "fakevimplugin.h" + +#include "handler.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +using namespace FakeVim::Internal; +//using namespace FakeVim::Constants; +using namespace TextEditor; +using namespace Core; +using namespace ProjectExplorer; + + +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 +} // namespace FakeVim + + +/////////////////////////////////////////////////////////////////////// +// +// FakeVimPlugin +// +/////////////////////////////////////////////////////////////////////// + +FakeVimPlugin::FakeVimPlugin() +{ + m_core = 0; + m_handler = 0; +} + +FakeVimPlugin::~FakeVimPlugin() +{} + +void FakeVimPlugin::shutdown() +{ + delete m_handler; + m_handler = 0; +} + +bool FakeVimPlugin::initialize(const QStringList &arguments, QString *error_message) +{ + Q_UNUSED(arguments); + Q_UNUSED(error_message); + + m_handler = new FakeVimHandler; + + m_core = ExtensionSystem::PluginManager::instance()->getObject(); + QTC_ASSERT(m_core, return false); + + Core::ActionManagerInterface *actionManager = m_core->actionManager(); + QTC_ASSERT(actionManager, return false); + + QList globalcontext; + globalcontext << Core::Constants::C_GLOBAL_ID; + + m_installHandlerAction = new QAction(this); + m_installHandlerAction->setText(tr("Set vi-Style Keyboard Action Handler")); + + Core::ICommand *cmd = 0; + cmd = actionManager->registerAction(m_installHandlerAction, + Constants::INSTALL_HANDLER, globalcontext); + cmd->setDefaultKeySequence(QKeySequence(Constants::INSTALL_KEY)); + + IActionContainer *advancedMenu = + actionManager->actionContainer(Core::Constants::M_EDIT_ADVANCED); + advancedMenu->addAction(cmd); + + connect(m_installHandlerAction, SIGNAL(triggered()), + this, SLOT(installHandler())); + return true; +} + +void FakeVimPlugin::extensionsInitialized() +{ +} + +void FakeVimPlugin::installHandler() +{ + if (!m_core || !m_core->editorManager()) + return; + Core::IEditor *editor = m_core->editorManager()->currentEditor(); + ITextEditor *textEditor = qobject_cast(editor); + if (!textEditor) + return; + + 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) +{ + m_handler->removeWidget(widget); + Core::EditorManager::instance()->hideEditorInfoBar( + QLatin1String(Constants::MINI_BUFFER)); +} + +void FakeVimPlugin::showCommandBuffer(const QString &contents) +{ + Core::EditorManager::instance()->showEditorInfoBar( + QLatin1String(Constants::MINI_BUFFER), contents, + tr("Quit FakeVim"), m_handler, SLOT(quit())); +} + + +//#include "fakevimplugin.moc" + +Q_EXPORT_PLUGIN(FakeVimPlugin) diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h new file mode 100644 index 00000000000..9025affcec3 --- /dev/null +++ b/src/plugins/fakevim/fakevimplugin.h @@ -0,0 +1,95 @@ +/*************************************************************************** +** +** 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 FAKEVIMPLUGIN_H +#define FAKEVIMPLUGIN_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QCursor; +class QAbstractItemView; +QT_END_NAMESPACE + + +namespace Core { + +class ICore; +class IEditor; + +} // namespace Core + + +namespace TextEditor { + +class ITextEditor; + +} // namespace TextEditor + + +namespace FakeVim { +namespace Internal { + +class FakeVimHandler; + +class FakeVimPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + FakeVimPlugin(); + ~FakeVimPlugin(); + +private: + bool initialize(const QStringList &arguments, QString *error_message); + void shutdown(); + void extensionsInitialized(); + +private slots: + void installHandler(); + void removeHandler(QWidget *widget); + void showCommandBuffer(const QString &contents); + +private: + FakeVimHandler *m_handler; + QAction *m_installHandlerAction; + Core::ICore *m_core; +}; + +} // namespace Internal +} // namespace FakeVim + +#endif // FAKEVIMPLUGIN_H diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp new file mode 100644 index 00000000000..08063dc5a35 --- /dev/null +++ b/src/plugins/fakevim/handler.cpp @@ -0,0 +1,1409 @@ +/*************************************************************************** +** +** 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 "handler.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +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 EndOfDocument QTextCursor::End + + +/////////////////////////////////////////////////////////////////////// +// +// FakeVimHandler +// +/////////////////////////////////////////////////////////////////////// + +#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) + +const int ParagraphSeparator = 0x00002029; + +using namespace Qt; + +enum Mode +{ + InsertMode, + CommandMode, + ExMode, + SearchForwardMode, + SearchBackwardMode, +}; + +enum SubMode +{ + NoSubMode, + RegisterSubMode, + ChangeSubMode, + DeleteSubMode, + ZSubMode, +}; + +enum SubSubMode +{ + NoSubSubMode, + FtSubSubMode, // used for f, F, t, T + MarkSubSubMode, // used for m + BackTickSubSubMode, // used for ` + 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; } + + void init(); + void handleKey(int key, const QString &text); + void handleInsertMode(int key, const QString &text); + void handleCommandMode(int key, const QString &text); + void handleRegisterMode(int key, const QString &text); + void handleMiniBufferModes(int key, const QString &text); + void finishMovement(const QString &text = QString()); + void search(const QString &needle, bool forward); + + int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); } + int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); } + int count() const { return mvCount() * opCount(); } + int leftDist() const { return m_tc.position() - m_tc.block().position(); } + int rightDist() const { return m_tc.block().length() - leftDist() - 1; } + bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + + int lastPositionInDocument() 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 moveToFirstNonBlankOnLine(); + void moveToNextWord(bool simple); + void moveToWordBoundary(bool simple, bool forward); + void handleFfTt(int key); + + // 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; + QTextCursor m_tc; + QHash m_registers; + int m_register; + QString m_mvcount; + QString m_opcount; + + bool m_fakeEnd; + + 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; + QString m_currentFileName; + QString m_currentMessage; + + bool m_lastSearchForward; + QString m_lastInsertion; + + // undo handling + void recordInsert(int position, const QString &data); + void recordRemove(int position, const QString &data); + void recordRemove(int position, int length); + void recordMove(int position, int nestedCount); + void undo(); + void redo(); + QStack m_undoStack; + QStack m_redoStack; + + // extra data for '.' + QString m_dotCount; + QString m_dotCommand; + + // history for '/' + QString lastSearchString() const; + QStringList m_searchHistory; + int m_searchHistoryIndex; + + // history for ':' + QStringList m_commandHistory; + int m_commandHistoryIndex; + + // visual line mode + void enterVisualMode(VisualMode visualMode); + void leaveVisualMode(); + VisualMode m_visualMode; + + // marks as lines + QHash m_marks; + + // vi style configuration + QHash m_config; +}; + +FakeVimHandler::Private::Private(FakeVimHandler *parent) +{ + q = parent; + + m_mode = CommandMode; + m_submode = NoSubMode; + m_subsubmode = NoSubSubMode; + m_fakeEnd = false; + m_lastSearchForward = true; + m_register = '"'; + m_gflag = false; + m_textedit = 0; + m_plaintextedit = 0; + m_visualMode = NoVisualMode; + + m_config[ConfigStartOfLine] = ConfigOn; +} + +bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) +{ + QKeyEvent *keyEvent = static_cast(ev); + int key = keyEvent->key(); + if (key == Key_Shift || key == Key_Alt || key == Key_Control + || key == Key_Alt || key == Key_AltGr || key == Key_Meta) + return false; + + // Fake "End of line" + m_textedit = qobject_cast(ob); + m_plaintextedit = qobject_cast(ob); + if (!m_textedit && !m_plaintextedit) + return false; + + m_tc = EDITOR(textCursor()); + + if (m_fakeEnd) + m_tc.movePosition(Right, MoveAnchor, 1); + + if (key >= Key_A && key <= Key_Z + && (keyEvent->modifiers() & Qt::ShiftModifier) == 0) + key += 32; + if ((keyEvent->modifiers() & Qt::ControlModifier) != 0) + key += 256; + handleKey(key, keyEvent->text()); + + // We fake vi-style end-of-line behaviour + m_fakeEnd = (atEol() && m_mode == CommandMode); + + if (m_fakeEnd) + m_tc.movePosition(Left, MoveAnchor, 1); + + EDITOR(setTextCursor(m_tc)); + EDITOR(ensureCursorVisible()); + return true; +} + +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 || m_mode == SearchForwardMode + || m_mode == SearchBackwardMode) + handleMiniBufferModes(key, text); +} + +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; + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + } + m_mvcount.clear(); + m_opcount.clear(); + m_gflag = false; + m_register = '"'; + m_tc.clearSelection(); + + updateSelection(); + updateMiniBuffer(); +} + +void FakeVimHandler::Private::updateSelection() +{ + QList 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() +{ + QString msg; + 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); + } else { + msg += c; + } + } + } + emit q->commandBufferChanged(msg); + + int linesInDoc = linesInDocument(); + int l = cursorLineInDocument(); + QString status; + QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1); + status += tr("%1").arg(pos, -10); + // FIXME: physical "-" logical + 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) +{ + //qDebug() << "MSG: " << msg; + m_currentMessage = msg; + updateMiniBuffer(); +} + +void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) +{ + Q_UNUSED(text) + + if (m_submode == RegisterSubMode) { + m_register = key; + m_submode = NoSubMode; + } else if (m_submode == ChangeSubMode && key == 'c') { + m_tc.movePosition(StartOfLine, MoveAnchor); + m_tc.movePosition(Down, KeepAnchor, count()); + m_registers[m_register] = m_tc.selectedText(); + 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("d"); + } else if (m_submode == ZSubMode) { + if (key == Key_Return) { + // cursor line to top of window, cursor on first non-blank + scrollToLineInDocument(cursorLineInDocument()); + moveToFirstNonBlankOnLine(); + finishMovement(); + } else { + qDebug() << "Ignored z + " << key << text; + } + m_submode = NoSubMode; + } else if (m_subsubmode == FtSubSubMode) { + handleFfTt(key); + m_subsubmode = NoSubSubMode; + 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], MoveAnchor); + if (m_subsubmode == TickSubSubMode) + moveToFirstNonBlankOnLine(); + finishMovement(); + } else { + showMessage(tr("E20: Mark '%1' not set").arg(text)); + } + m_subsubmode = NoSubSubMode; + } else if (key >= '0' && key <= '9') { + if (key == '0' && m_mvcount.isEmpty()) { + moveToFirstNonBlankOnLine(); + finishMovement(); + } else { + m_mvcount.append(QChar(key)); + } + } else if (key == ':') { + m_mode = ExMode; + 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; + } else if (key == '\'') { + m_subsubmode = TickSubSubMode; + } else if (key == '|') { + m_tc.movePosition(StartOfLine, KeepAnchor); + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()) - 1); + finishMovement(); + } else if (key == '"') { + m_submode = RegisterSubMode; + } else if (key == Key_Return) { + m_tc.movePosition(StartOfLine); + m_tc.movePosition(Down); + } else if (key == Key_Home) { + m_tc.movePosition(StartOfLine, KeepAnchor); + finishMovement(); + } 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.movePosition(Right, MoveAnchor, 1); + updateMiniBuffer(); + } else if (key == 'A') { + m_mode = InsertMode; + m_tc.movePosition(EndOfLine, MoveAnchor); + m_lastInsertion.clear(); + } else if (key == 'b') { + moveToWordBoundary(false, false); + finishMovement(); + } else if (key == 'B') { + moveToWordBoundary(true, false); + finishMovement(); + } else if (key == 'c') { + m_submode = ChangeSubMode; + } else if (key == 'C') { + m_submode = ChangeSubMode; + m_tc.movePosition(EndOfLine, KeepAnchor); + finishMovement(); + } 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)); + m_tc.movePosition(Right, KeepAnchor, rightDist()); + finishMovement(); + } else if (key == 'e') { + moveToWordBoundary(false, true); + finishMovement(); + } else if (key == 'E') { + moveToWordBoundary(true, true); + finishMovement(); + } else if (key == 'f' || key == 'F') { + m_subsubmode = FtSubSubMode; + m_subsubdata = key; + } else if (key == 'g') { + m_gflag = true; + } else if (key == 'G') { + int n = m_mvcount.isEmpty() ? linesInDocument() : count(); + m_tc.setPosition(positionForLine(n), MoveAnchor); + if (m_config.contains(ConfigStartOfLine)) + moveToFirstNonBlankOnLine(); + finishMovement(); + } else if (key == 'h' || key == Key_Left) { + int n = qMin(count(), leftDist()); + if (m_fakeEnd && m_tc.block().length() > 1) + ++n; + m_tc.movePosition(Left, KeepAnchor, n); + finishMovement(); + } else if (key == 'H') { + m_tc = EDITOR(cursorForPosition(QPoint(0, 0))); + m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); + moveToFirstNonBlankOnLine(); + finishMovement(); + } else if (key == 'i') { + enterInsertMode(); + updateMiniBuffer(); + } else if (key == 'I') { + enterInsertMode(); + if (m_gflag) + m_tc.movePosition(StartOfLine, KeepAnchor); + else + moveToFirstNonBlankOnLine(); + } else if (key == 'j' || key == Key_Down) { + m_tc.movePosition(Down, KeepAnchor, count()); + finishMovement(); + } else if (key == 'J') { + EditOperation op; + if (m_submode == NoSubMode) { + for (int i = qMax(count(), 2) - 1; --i >= 0; ) { + m_tc.movePosition(EndOfLine); + m_tc.deleteChar(); + if (!m_gflag) + m_tc.insertText(" "); + } + if (!m_gflag) + m_tc.movePosition(Left, MoveAnchor, 1); + } + } else if (key == 'k' || key == Key_Up) { + m_tc.movePosition(Up, KeepAnchor, count()); + finishMovement(); + } else if (key == 'l' || key == Key_Right) { + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + finishMovement(); + } else if (key == 'L') { + m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height())))); + m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); + moveToFirstNonBlankOnLine(); + finishMovement(); + } else if (key == 'm') { + m_subsubmode = MarkSubSubMode; + } else if (key == 'M') { + m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); + moveToFirstNonBlankOnLine(); + finishMovement(); + } else if (key == 'n') { + search(lastSearchString(), m_lastSearchForward); + } else if (key == 'N') { + search(lastSearchString(), !m_lastSearchForward); + } else if (key == 'o') { + enterInsertMode(); + m_tc.movePosition(EndOfLine, MoveAnchor); + m_tc.insertText("\n"); + } else if (key == 'O') { + enterInsertMode(); + m_tc.movePosition(StartOfLine, MoveAnchor); + m_tc.movePosition(Left, MoveAnchor, 1); + m_tc.insertText("\n"); + } else if (key == 'p') { + QString text = m_registers[m_register]; + int n = text.count(QChar(ParagraphSeparator)); + if (n > 0) { + m_tc.movePosition(StartOfLine); + m_tc.movePosition(Down); + m_tc.insertText(text); + m_tc.movePosition(Up, MoveAnchor, n); + } else { + m_tc.movePosition(Right); + m_tc.insertText(text); + m_tc.movePosition(Left); + } + m_dotCommand = "p"; + } else if (key == control('r')) { + redo(); + } else if (key == 's') { + m_submode = ChangeSubMode; + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + } else if (key == 't' || key == 'T') { + m_subsubmode = FtSubSubMode; + m_subsubdata = key; + } else if (key == 'u') { + 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("w"); + } else if (key == 'W') { + moveToNextWord(true); + 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("l"); + } else if (key == 'X') { + if (leftDist() > 0) { + m_tc.movePosition(Left, KeepAnchor, qMin(count(), leftDist())); + m_tc.deleteChar(); + } + finishMovement(); + } else if (key == 'z') { + m_submode = ZSubMode; + } else if (key == '~' && !atEol()) { + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + QString str = m_tc.selectedText(); + for (int i = str.size(); --i >= 0; ) { + QChar c = str.at(i); + str[i] = c.isUpper() ? c.toLower() : c.toUpper(); + } + m_tc.deleteChar(); + m_tc.insertText(str); + } else if (key == Key_PageDown || key == control('f')) { + m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); + } else if (key == Key_PageUp || key == control('b')) { + m_tc.movePosition(Up, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); + } else if (key == Key_Backspace) { + m_tc.deletePreviousChar(); + } else if (key == Key_Delete) { + m_tc.deleteChar(); + } else if (key == Key_Escape) { + if (m_visualMode != NoVisualMode) + leaveVisualMode(); + } else { + qDebug() << "Ignored" << key << text; + } +} + +void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) +{ + if (key == Key_Escape) { + // 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())); + enterCommandMode(); + } else if (key == Key_Left) { + m_tc.movePosition(Left, MoveAnchor, 1); + m_lastInsertion.clear(); + } else if (key == Key_Down) { + m_tc.movePosition(Down, MoveAnchor, 1); + m_lastInsertion.clear(); + } else if (key == Key_Up) { + m_tc.movePosition(Up, MoveAnchor, 1); + m_lastInsertion.clear(); + } else if (key == Key_Right) { + m_tc.movePosition(Right, MoveAnchor, 1); + m_lastInsertion.clear(); + } else if (key == Key_Return) { + m_tc.insertBlock(); + m_lastInsertion += "\n"; + } else if (key == Key_Backspace) { + m_tc.deletePreviousChar(); + m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1); + } else if (key == Key_Delete) { + m_tc.deleteChar(); + m_lastInsertion.clear(); + } else if (key == Key_PageDown || key == control('f')) { + m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); + m_lastInsertion.clear(); + } else if (key == Key_Backspace) { + finishMovement(); + } else if (key == Key_PageUp || key == control('b')) { + m_tc.movePosition(Up, KeepAnchor, count() * (linesOnScreen() - 2)); + m_lastInsertion.clear(); + } else if (key == Key_Backspace) { + finishMovement(); + } else { + m_lastInsertion.append(text); + m_tc.insertText(text); + } + updateMiniBuffer(); +} + +void FakeVimHandler::Private::handleMiniBufferModes(int key, const QString &text) +{ + Q_UNUSED(text) + + if (key == Key_Escape) { + m_commandBuffer.clear(); + enterCommandMode(); + updateMiniBuffer(); + } else if (key == Key_Backspace) { + if (m_commandBuffer.isEmpty()) + enterCommandMode(); + else + m_commandBuffer.chop(1); + updateMiniBuffer(); + } else if (key == Key_Return && m_mode == ExMode) { + if (!m_commandBuffer.isEmpty()) { + m_commandHistory.takeLast(); + m_commandHistory.append(m_commandBuffer); + handleExCommand(m_commandBuffer); + } + } else if (key == Key_Return && isSearchMode()) { + if (!m_commandBuffer.isEmpty()) { + m_searchHistory.takeLast(); + m_searchHistory.append(m_commandBuffer); + m_lastSearchForward = (m_mode == SearchForwardMode); + search(lastSearchString(), m_lastSearchForward); + } + enterCommandMode(); + updateMiniBuffer(); + } 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) { + --m_searchHistoryIndex; + m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + updateMiniBuffer(); + } + } 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 && isSearchMode()) { + if (m_searchHistoryIndex < m_searchHistory.size() - 1) { + ++m_searchHistoryIndex; + m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + updateMiniBuffer(); + } + } else if (key == Key_Down && m_mode == ExMode) { + if (m_commandHistoryIndex < m_commandHistory.size() - 1) { + ++m_commandHistoryIndex; + m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); + updateMiniBuffer(); + } + } else if (key == Key_Tab) { + m_commandBuffer += QChar(9); + updateMiniBuffer(); + } else { + m_commandBuffer += QChar(key); + updateMiniBuffer(); + } +} + +// 1 based. +int FakeVimHandler::Private::readLineCode(QString &cmd) +{ + //qDebug() << "CMD: " << cmd; + if (cmd.isEmpty()) + return -1; + QChar c = cmd.at(0); + cmd = cmd.mid(1); + if (c == '.') + return cursorLineInDocument() + 1; + if (c == '$') + return linesInDocument(); + if (c == '-') { + int n = readLineCode(cmd); + return cursorLineInDocument() + 1 - (n == -1 ? 1 : n); + } + if (c == '+') { + 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()) { + c = cmd.at(0); + if (!c.isDigit()) + break; + cmd = cmd.mid(1); + n = n * 10 + (c.unicode() - '0'); + } + //qDebug() << "N: " << n; + return n; + } + // not parsed + cmd = c + cmd; + return -1; +} + +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 = -1; + int endLine = -1; + + int line = readLineCode(cmd); + if (line != -1) + beginLine = line; + + if (cmd.startsWith(',')) { + cmd = cmd.mid(1); + line = readLineCode(cmd); + if (line != -1) + endLine = line; + } + + qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0; + + static QRegExp reWrite("^w!?( (.*))?$"); + static QRegExp reDelete("^d( (.*))?$"); + + if (cmd.isEmpty()) { + m_tc.setPosition(positionForLine(beginLine)); + showMessage(QString()); + } 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 && !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::ReadOnly); + QByteArray ba = file.readAll(); + m_commandBuffer = QString("\"%1\" %2 %3L, %4C written") + .arg(fileName).arg(exists ? " " : " [New] ") + .arg(ba.count('\n')).arg(ba.size()); + updateMiniBuffer(); + } else { + showMessage(tr("Cannot open file '%1' for reading").arg(fileName)); + } + } else if (cmd.startsWith("r ")) { // :r + m_currentFileName = cmd.mid(2); + QFile file(m_currentFileName); + file.open(QIODevice::ReadOnly); + QTextStream ts(&file); + 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); + } +} + +void FakeVimHandler::Private::search(const QString &needle, bool forward) +{ + //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; + QTextCursor orig = m_tc; + QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively; + if (!forward) + flags = QTextDocument::FindBackward; + + if (forward) + m_tc.movePosition(Right, MoveAnchor, 1); + + EDITOR(setTextCursor(m_tc)); + if (EDITOR(find(needle, flags))) { + m_tc = EDITOR(textCursor()); + // the qMax seems to be needed for QPlainTextEdit only + m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); + return; + } + + m_tc.setPosition(forward ? 0 : lastPositionInDocument() - 1); + EDITOR(setTextCursor(m_tc)); + if (EDITOR(find(needle, flags))) { + m_tc = EDITOR(textCursor()); + // the qMax seems to be needed for QPlainTextEdit only + m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); + if (forward) + showMessage("search hit BOTTOM, continuing at TOP"); + else + showMessage("search hit TOP, continuing at BOTTOM"); + return; + } + + m_tc = orig; +} + +void FakeVimHandler::Private::moveToFirstNonBlankOnLine() +{ + QTextBlock block = m_tc.block(); + QTextDocument *doc = m_tc.document(); + m_tc.movePosition(StartOfLine); + int firstPos = m_tc.position(); + for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) { + if (!doc->characterAt(i).isSpace()) { + m_tc.setPosition(i, KeepAnchor); + return; + } + } +} + +static int charClass(QChar c, bool simple) +{ + if (simple) + return c.isSpace() ? 0 : 1; + if (c.isLetterOrNumber() || c.unicode() == '_') + return 2; + return c.isSpace() ? 0 : 1; +} + +void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward) +{ + int repeat = count(); + QTextDocument *doc = m_tc.document(); + int n = forward ? lastPositionInDocument() - 1 : 0; + int lastClass = 0; + while (true) { + m_tc.movePosition(forward ? Right : Left, KeepAnchor, 1); + QChar c = doc->characterAt(m_tc.position()); + int thisClass = charClass(c, simple); + if (thisClass != lastClass && lastClass != 0) + --repeat; + if (repeat == -1) { + m_tc.movePosition(forward ? Left : Right, KeepAnchor, 1); + break; + } + lastClass = thisClass; + if (m_tc.position() == n) + break; + } +} + +void FakeVimHandler::Private::handleFfTt(int key) +{ + // m_subsubmode \in { 'f', 'F', 't', 'T' } + bool forward = m_subsubdata == 'f' || m_subsubdata == 't'; + int repeat = count(); + QTextDocument *doc = m_tc.document(); + QTextBlock block = m_tc.block(); + int n = block.position(); + if (forward) + n += block.length(); + int pos = m_tc.position(); + while (true) { + pos += forward ? 1 : -1; + if (pos == n) + break; + int uc = doc->characterAt(pos).unicode(); + if (uc == ParagraphSeparator) + break; + if (uc == key) + --repeat; + if (repeat == 0) { + if (m_subsubdata == 't') + --pos; + else if (m_subsubdata == 'T') + ++pos; + // FIXME: strange correction... + if (m_submode == DeleteSubMode && m_subsubdata == 'f') + ++pos; + if (m_submode == DeleteSubMode && m_subsubdata == 't') + ++pos; + + if (forward) + m_tc.movePosition(Right, KeepAnchor, pos - m_tc.position()); + else + m_tc.movePosition(Left, KeepAnchor, m_tc.position() - pos); + break; + } + } +} + +void FakeVimHandler::Private::moveToNextWord(bool simple) +{ + // FIXME: 'w' should stop on empty lines, too + int repeat = count(); + QTextDocument *doc = m_tc.document(); + int n = lastPositionInDocument() - 1; + QChar c = doc->characterAt(m_tc.position()); + int lastClass = charClass(c, simple); + while (true) { + c = doc->characterAt(m_tc.position()); + int thisClass = charClass(c, simple); + if (thisClass != lastClass && thisClass != 0) + --repeat; + if (repeat == 0) + break; + lastClass = thisClass; + m_tc.movePosition(Right, KeepAnchor, 1); + if (m_tc.position() == n) + break; + } +} + +int FakeVimHandler::Private::cursorLineOnScreen() const +{ + if (!editor()) + return 0; + QRect rect = EDITOR(cursorRect()); + return rect.y() / rect.height(); +} + +int FakeVimHandler::Private::linesOnScreen() const +{ + if (!editor()) + return 1; + QRect rect = EDITOR(cursorRect()); + return EDITOR(height()) / rect.height(); +} + +int FakeVimHandler::Private::columnsOnScreen() const +{ + 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(); +} + +int FakeVimHandler::Private::cursorColumnInDocument() const +{ + return m_tc.position() - m_tc.block().position(); +} + +int FakeVimHandler::Private::linesInDocument() const +{ + return m_tc.isNull() ? 0 : m_tc.document()->blockCount(); +} + +void FakeVimHandler::Private::scrollToLineInDocument(int line) +{ + // FIXME: works only for QPlainTextEdit + QScrollBar *scrollBar = EDITOR(verticalScrollBar()); + scrollBar->setValue(line); +} + +int FakeVimHandler::Private::lastPositionInDocument() const +{ + QTextBlock block = m_tc.block().document()->lastBlock(); + return block.position() + block.length(); +} + +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(m_textedit) + : static_cast(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::recordMove(int position, int nestedCount) +{ + EditOperation op; + op.m_position = position; + op.m_itemCount = nestedCount; + m_undoStack.push(op); + m_redoStack.clear(); +} + +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 +// +/////////////////////////////////////////////////////////////////////// + +FakeVimHandler::FakeVimHandler(QObject *parent) + : QObject(parent), d(new Private(this)) +{} + +FakeVimHandler::~FakeVimHandler() +{ + delete d; +} + +bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) +{ + if (ev->type() != QEvent::KeyPress) + return QObject::eventFilter(ob, ev); + return d->eventFilter(ob, ev); +} + +void FakeVimHandler::addWidget(QWidget *widget) +{ + widget->installEventFilter(this); + d->enterCommandMode(); + if (QTextEdit *ed = qobject_cast(widget)) { + //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + ed->setLineWrapMode(QTextEdit::NoWrap); + } else if (QPlainTextEdit *ed = qobject_cast(widget)) { + //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + ed->setLineWrapMode(QPlainTextEdit::NoWrap); + } + d->showMessage("vi emulation mode. Hit :q to quit"); + d->updateMiniBuffer(); +} + +void FakeVimHandler::removeWidget(QWidget *widget) +{ + d->showMessage(QString()); + d->updateMiniBuffer(); + widget->removeEventFilter(this); +} + +void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd) +{ + d->m_textedit = qobject_cast(widget); + d->m_plaintextedit = qobject_cast(widget); + d->handleExCommand(cmd); +} + + +void FakeVimHandler::quit() +{ + d->quit(); +} diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h new file mode 100644 index 00000000000..fccb9f0f84f --- /dev/null +++ b/src/plugins/fakevim/handler.h @@ -0,0 +1,82 @@ +/*************************************************************************** +** +** 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 FAKEVIM_HANDLER_H +#define FAKEVIM_HANDLER_H + +#include + +QT_BEGIN_NAMESPACE +class QString; +class QEvent; +QT_END_NAMESPACE + +namespace FakeVim { +namespace Internal { + +class FakeVimHandler : public QObject +{ + Q_OBJECT + +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: + bool eventFilter(QObject *ob, QEvent *ev); + + class Private; + friend class Private; + Private *d; +}; + +} // namespace Internal +} // namespace FakeVim + +#endif // FAKEVIM_H diff --git a/src/plugins/find/Find.pluginspec b/src/plugins/find/Find.pluginspec index 2dd9dba1a8c..f0e00617e10 100644 --- a/src/plugins/find/Find.pluginspec +++ b/src/plugins/find/Find.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the find widget and the hooks for find implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp index 26ed8dd0492..dd25564a437 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/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec index 53f6184b80c..21c0c39ab60 100644 --- a/src/plugins/git/ScmGit.pluginspec +++ b/src/plugins/git/ScmGit.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Git integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp new file mode 100644 index 00000000000..3eeee2347b6 --- /dev/null +++ b/src/plugins/git/branchdialog.cpp @@ -0,0 +1,188 @@ +#include "branchdialog.h" +#include "branchmodel.h" +#include "gitclient.h" +#include "ui_branchdialog.h" + +#include +#include +#include + +// Single selection helper +static inline int selectedRow(const QAbstractItemView *listView) +{ + const QModelIndexList indexList = listView->selectionModel()->selectedIndexes(); + if (indexList.size() == 1) + return indexList.front().row(); + return -1; +} + +namespace Git { + namespace Internal { + +BranchDialog::BranchDialog(QWidget *parent) : + QDialog(parent), + m_client(0), + m_ui(new Ui::BranchDialog), + m_checkoutButton(0), + m_deleteButton(0), + m_localModel(0), + m_remoteModel(0) +{ + setModal(true); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + m_ui->setupUi(this); + m_checkoutButton = m_ui->buttonBox->addButton(tr("Checkout"), QDialogButtonBox::AcceptRole); + connect(m_checkoutButton, SIGNAL(clicked()), this, SLOT(slotCheckoutSelectedBranch())); + + m_deleteButton = m_ui->buttonBox->addButton(tr("Delete"), QDialogButtonBox::ActionRole); + connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotDeleteSelectedBranch())); + + connect(m_ui->localBranchListView, SIGNAL(doubleClicked(QModelIndex)), this, + SLOT(slotLocalBranchActivated())); +} + +BranchDialog::~BranchDialog() +{ + delete m_ui; +} + +bool BranchDialog::init(GitClient *client, const QString &workingDirectory, QString *errorMessage) +{ + // Find repository and populate models. + m_client = client; + m_repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory); + if (m_repoDirectory.isEmpty()) { + *errorMessage = tr("Unable to find the repository directory for '%1'.").arg(workingDirectory); + return false; + } + m_ui->repositoryFieldLabel->setText(m_repoDirectory); + + 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; + + m_ui->localBranchListView->setModel(m_localModel); + m_ui->remoteBranchListView->setModel(m_remoteModel); + // Selection model comes into existence only now + connect(m_ui->localBranchListView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotEnableButtons())); + connect(m_ui->remoteBranchListView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotEnableButtons())); + slotEnableButtons(); + return true; +} + +int BranchDialog::selectedLocalBranchIndex() const +{ + return selectedRow(m_ui->localBranchListView); +} + +int BranchDialog::selectedRemoteBranchIndex() const +{ + return selectedRow(m_ui->remoteBranchListView); +} + +void BranchDialog::slotEnableButtons() +{ + // We can switch to or delete branches that are not current. + const int selectedLocalRow = selectedLocalBranchIndex(); + const int currentLocalBranch = m_localModel->currentBranch(); + + 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, + defaultButton ? QMessageBox::Yes : QMessageBox::No) == QMessageBox::Yes; +} + +/* Prompt to delete a local branch and do so. */ +void BranchDialog::slotDeleteSelectedBranch() +{ + const int idx = selectedLocalBranchIndex(); + if (idx == -1) + return; + const QString name = m_localModel->branchName(idx); + if (!ask(tr("Delete Branch"), tr("Would you like to delete the branch '%1'?").arg(name), true)) + return; + QString errorMessage; + bool ok = false; + do { + QString output; + QStringList args(QLatin1String("-D")); + args << name; + if (!m_client->synchronousBranchCmd(m_repoDirectory, args, &output, &errorMessage)) + break; + if (!m_localModel->refresh(m_repoDirectory, &errorMessage)) + break; + ok = true; + } while (false); + slotEnableButtons(); + if (!ok) + QMessageBox::warning(this, tr("Failed to delete branch"), errorMessage); +} + +void BranchDialog::slotLocalBranchActivated() +{ + if (m_checkoutButton->isEnabled()) + m_checkoutButton->animateClick(); +} + +/* Ask to stash away changes and then close dialog and do an asynchronous + * checkout. */ +void BranchDialog::slotCheckoutSelectedBranch() +{ + const int idx = selectedLocalBranchIndex(); + if (idx == -1) + return; + const QString name = m_localModel->branchName(idx); + QString errorMessage; + switch (m_client->ensureStash(m_repoDirectory, &errorMessage)) { + case GitClient::StashUnchanged: + case GitClient::Stashed: + case GitClient::NotStashed: + break; + case GitClient::StashCanceled: + return; + case GitClient::StashFailed: + QMessageBox::warning(this, tr("Failed to stash"), errorMessage); + return; + } + accept(); + m_client->checkoutBranch(m_repoDirectory, name); +} + +void BranchDialog::changeEvent(QEvent *e) +{ + switch (e->type()) { + case QEvent::LanguageChange: + m_ui->retranslateUi(this); + break; + default: + break; + } +} + +} // namespace Internal +} // namespace Git diff --git a/src/plugins/git/branchdialog.h b/src/plugins/git/branchdialog.h new file mode 100644 index 00000000000..c803b57e833 --- /dev/null +++ b/src/plugins/git/branchdialog.h @@ -0,0 +1,62 @@ +#ifndef BRANCHDIALOG_H +#define BRANCHDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QPushButton; +QT_END_NAMESPACE + +namespace Git { + namespace Internal { + namespace Ui { + class BranchDialog; + } + + class GitClient; + class LocalBranchModel; + class RemoteBranchModel; + + /* Branch dialog: Display a list of local branches at the top + * and remote branches below. Offers to checkout/delete local + * branches. + * TODO: Add new branch (optionally tracking a remote one). + * How to find out that a local branch is a tracking one? */ + class BranchDialog : public QDialog { + Q_OBJECT + Q_DISABLE_COPY(BranchDialog) + public: + explicit BranchDialog(QWidget *parent = 0); + + bool init(GitClient *client, const QString &workingDirectory, QString *errorMessage); + + virtual ~BranchDialog(); + + protected: + virtual void changeEvent(QEvent *e); + + private slots: + void slotEnableButtons(); + void slotCheckoutSelectedBranch(); + void slotDeleteSelectedBranch(); + void slotLocalBranchActivated(); + void slotNewLocalBranchCreated(const QString &); + + private: + bool ask(const QString &title, const QString &what, bool defaultButton); + + int selectedLocalBranchIndex() const; + int selectedRemoteBranchIndex() const; + + GitClient *m_client; + Ui::BranchDialog *m_ui; + QPushButton *m_checkoutButton; + QPushButton *m_deleteButton; + + LocalBranchModel *m_localModel; + RemoteBranchModel *m_remoteModel; + QString m_repoDirectory; + }; + } // namespace Internal +} // namespace Git +#endif // BRANCHDIALOG_H diff --git a/src/plugins/git/branchdialog.ui b/src/plugins/git/branchdialog.ui new file mode 100644 index 00000000000..07f7ff656b1 --- /dev/null +++ b/src/plugins/git/branchdialog.ui @@ -0,0 +1,95 @@ + + + Git::Internal::BranchDialog + + + + 0 + 0 + 544 + 631 + + + + Branches + + + + + + General information + + + + + + Repository: + + + + + + + TextLabel + + + + + + + + + + Branches + + + + + + + + + + + + Remote branches + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + rejected() + Git::Internal::BranchDialog + reject() + + + 466 + 614 + + + 544 + 23 + + + + + diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp new file mode 100644 index 00000000000..bb8ccf19510 --- /dev/null +++ b/src/plugins/git/branchmodel.cpp @@ -0,0 +1,252 @@ +#include "branchmodel.h" +#include "gitclient.h" + +#include +#include +#include + +enum { debug = 0 }; + +namespace Git { + namespace Internal { + +// Parse a branch line: " *name sha description". Return true if it is +// the current one +bool RemoteBranchModel::Branch::parse(const QString &lineIn, bool *isCurrent) +{ + if (debug) + qDebug() << Q_FUNC_INFO << lineIn; + + *isCurrent = lineIn.startsWith(QLatin1String("* ")); + if (lineIn.size() < 3) + return false; + + const QStringList tokens =lineIn.mid(2).split(QLatin1Char(' '), QString::SkipEmptyParts); + if (tokens.size() < 2) + return false; + name = tokens.at(0); + currentSHA= tokens.at(1); + toolTip.clear(); + return true; +} + +// ------ RemoteBranchModel +RemoteBranchModel::RemoteBranchModel(GitClient *client, QObject *parent) : + QAbstractListModel(parent), + m_flags(Qt::ItemIsSelectable|Qt::ItemIsEnabled), + m_client(client) +{ +} + +bool RemoteBranchModel::refresh(const QString &workingDirectory, QString *errorMessage) +{ + int currentBranch; + return refreshBranches(workingDirectory, true, ¤tBranch, errorMessage); +} + +QString RemoteBranchModel::branchName(int row) const +{ + return m_branches.at(row).name; +} + +QString RemoteBranchModel::workingDirectory() const +{ + return m_workingDirectory; +} + +int RemoteBranchModel::branchCount() const +{ + return m_branches.size(); +} + +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) { + case Qt::DisplayRole: + return branchName(row); + case Qt::ToolTipRole: + if (m_branches.at(row).toolTip.isEmpty()) + m_branches.at(row).toolTip = toolTip(m_branches.at(row).currentSHA); + return m_branches.at(row).toolTip; + break; + default: + break; + } + return QVariant(); +} + +Qt::ItemFlags RemoteBranchModel::flags(const QModelIndex & /* index */) const +{ + return m_flags; +} + +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; + *currentBranch = -1; + if (remoteBranches) + branchArgs.push_back(QLatin1String("-r")); + if (!runGitBranchCommand(workingDirectory, branchArgs, &output, errorMessage)) + return false; + if (debug) + qDebug() << Q_FUNC_INFO << workingDirectory << output; + // Parse output + m_workingDirectory = workingDirectory; + m_branches.clear(); + const QStringList branches = output.split(QLatin1Char('\n')); + const int branchCount = branches.size(); + bool isCurrent; + for (int b = 0; b < branchCount; b++) { + Branch newBranch; + if (newBranch.parse(branches.at(b), &isCurrent)) { + m_branches.push_back(newBranch); + if (isCurrent) + *currentBranch = b; + } + } + reset(); + return true; +} + +int RemoteBranchModel::findBranchByName(const QString &name) const +{ + 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("")), + 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 (!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 new file mode 100644 index 00000000000..91b1ca84dc0 --- /dev/null +++ b/src/plugins/git/branchmodel.h @@ -0,0 +1,107 @@ +#ifndef BRANCHMODEL_H +#define BRANCHMODEL_H + +#include +#include +#include + +namespace Git { + namespace Internal { + +class GitClient; + +/* 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 RemoteBranchModel : public QAbstractListModel { + Q_OBJECT +public: + explicit RemoteBranchModel(GitClient *client, QObject *parent = 0); + + virtual bool refresh(const QString &workingDirectory, QString *errorMessage); + + QString branchName(int row) const; + + // QAbstractListModel + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + + int branchCount() const; + + QString workingDirectory() const; + int findBranchByName(const QString &name) const; + +protected: + struct Branch { + bool parse(const QString &line, bool *isCurrent); + + QString name; + QString currentSHA; + mutable QString toolTip; + }; + typedef QList BranchList; + + /* 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; + 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; +}; + +} +} + +#endif // BRANCHMODEL_H diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro index 3c4ca176cb5..7f4ed2fc0cc 100644 --- a/src/plugins/git/git.pro +++ b/src/plugins/git/git.pro @@ -6,7 +6,6 @@ include(../../plugins/texteditor/texteditor.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/vcsbase/vcsbase.pri) include(../../libs/utils/utils.pri) - HEADERS += gitplugin.h \ gitconstants.h \ gitoutputwindow.h \ @@ -19,8 +18,9 @@ HEADERS += gitplugin.h \ gitsubmiteditorwidget.h \ gitsubmiteditor.h \ gitversioncontrol.h \ - gitsettings.h - + gitsettings.h \ + branchdialog.h \ + branchmodel.h SOURCES += gitplugin.cpp \ gitoutputwindow.cpp \ gitclient.cpp \ @@ -32,8 +32,10 @@ SOURCES += gitplugin.cpp \ gitsubmiteditorwidget.cpp \ gitsubmiteditor.cpp \ gitversioncontrol.cpp \ - gitsettings.cpp - + gitsettings.cpp \ + branchdialog.cpp \ + branchmodel.cpp FORMS += changeselectiondialog.ui \ settingspage.ui \ - gitsubmitpanel.ui + gitsubmitpanel.ui \ + branchdialog.ui diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 3113ebf3f86..f3d507171d2 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -276,6 +276,13 @@ void GitClient::blame(const QString &workingDirectory, const QString &fileName) executeGit(workingDirectory, arguments, editor); } +void GitClient::checkoutBranch(const QString &workingDirectory, const QString &branch) +{ + QStringList arguments(QLatin1String("checkout")); + arguments << branch; + executeGit(workingDirectory, arguments, 0, true); +} + void GitClient::checkout(const QString &workingDirectory, const QString &fileName) { // Passing an empty argument as the file name is very dangereous, since this makes @@ -379,6 +386,58 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory, return true; } +bool GitClient::synchronousStash(const QString &workingDirectory, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory; + QByteArray outputText; + QByteArray errorText; + QStringList arguments; + arguments << QLatin1String("stash"); + const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable stash in %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + return true; +} + +bool GitClient::synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, + QString *output, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory << branchArgs; + branchArgs.push_front(QLatin1String("branch")); + QByteArray outputText; + QByteArray errorText; + const bool rc = synchronousGit(workingDirectory, branchArgs, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable to run branch command: %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + *output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r')); + return true; +} + +bool GitClient::synchronousShow(const QString &workingDirectory, const QString &id, + QString *output, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory << id; + QStringList args(QLatin1String("show")); + args << id; + QByteArray outputText; + QByteArray errorText; + const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable to run show: %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + *output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r')); + return true; +} + + void GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments, VCSBase::VCSBaseEditor* editor, bool outputToWindow) @@ -467,6 +526,60 @@ bool GitClient::synchronousGit(const QString &workingDirectory, return process.exitCode() == 0; } +static inline int + askWithDetailedText(QWidget *parent, + const QString &title, const QString &msg, + const QString &inf, + QMessageBox::StandardButton defaultButton, + QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No) +{ + QMessageBox msgBox(QMessageBox::Question, title, msg, buttons, parent); + msgBox.setDetailedText(inf); + msgBox.setDefaultButton(defaultButton); + return msgBox.exec(); +} + +// Convenience that pops up an msg box. +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory) +{ + QString errorMessage; + const StashResult sr = ensureStash(workingDirectory, &errorMessage); + if (sr == StashFailed) { + m_plugin->outputWindow()->append(errorMessage); + m_plugin->outputWindow()->popup(); + } + return sr; +} + +// Ensure that changed files are stashed before a pull or similar +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, QString *errorMessage) +{ + QString statusOutput; + switch (gitStatus(workingDirectory, false, &statusOutput, errorMessage)) { + case StatusChanged: + break; + case StatusUnchanged: + return StashUnchanged; + case StatusFailed: + return StashFailed; + } + + const int answer = askWithDetailedText(m_core->mainWindow(), tr("Changes"), + tr("You have modified files. Would you like to stash your changes?"), + statusOutput, QMessageBox::Yes, QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); + switch (answer) { + case QMessageBox::Cancel: + return StashCanceled; + case QMessageBox::Yes: + if (!synchronousStash(workingDirectory, errorMessage)) + return StashFailed; + break; + case QMessageBox::No: // At your own risk, so. + return NotStashed; + } + + return Stashed; + } // Trim a git status file spec: "modified: foo .cpp" -> "modified: foo .cpp" static inline QString trimFileSpecification(QString fileSpec) @@ -476,7 +589,7 @@ static inline QString trimFileSpecification(QString fileSpec) // Collapse the sequence of spaces const int filePos = colonIndex + 2; int nonBlankPos = filePos; - for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++); + for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++) ; if (nonBlankPos > filePos) fileSpec.remove(filePos, nonBlankPos - filePos); } @@ -703,18 +816,6 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory, return rc; } -static inline bool askWithInformativeText(QWidget *parent, - const QString &title, - const QString &msg, - const QString &inf, - bool defaultValue) -{ - QMessageBox msgBox(QMessageBox::Question, title, msg, QMessageBox::Yes|QMessageBox::No, parent); - msgBox.setInformativeText(inf); - msgBox.setDefaultButton(defaultValue ? QMessageBox::Yes : QMessageBox::No); - return msgBox.exec() == QMessageBox::Yes; -} - /* Revert: This function can be called with a file list (to revert single * files) or a single directory (revert all). Qt Creator currently has only * 'revert single' in its VCS menus, but the code is prepared to deal with diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 2ae6c3f583a..f09daa00ab8 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -86,12 +86,19 @@ public: void blame(const QString &workingDirectory, const QString &fileName); void showCommit(const QString &workingDirectory, const QString &commit); void checkout(const QString &workingDirectory, const QString &file); + void checkoutBranch(const QString &workingDirectory, const QString &branch); void hardReset(const QString &workingDirectory, const QString &commit); void addFile(const QString &workingDirectory, const QString &fileName); bool synchronousAdd(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); + bool synchronousStash(const QString &workingDirectory, QString *errorMessage); + bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, + QString *output, QString *errorMessage); + bool synchronousShow(const QString &workingDirectory, const QString &id, + QString *output, QString *errorMessage); + void pull(const QString &workingDirectory); void push(const QString &workingDirectory); @@ -105,6 +112,11 @@ public: QString readConfigValue(const QString &workingDirectory, const QString &configVar); + enum StashResult { StashUnchanged, StashCanceled, StashFailed, + Stashed, NotStashed /* User did not want it */ }; + StashResult ensureStash(const QString &workingDirectory, QString *errorMessage); + StashResult ensureStash(const QString &workingDirectory); + bool getCommitData(const QString &workingDirectory, QString *commitTemplate, CommitData *d, @@ -118,7 +130,7 @@ public: enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed }; StatusResult gitStatus(const QString &workingDirectory, - bool untracked, + bool untracked = false, QString *output = 0, QString *errorMessage = 0); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index dc18fe088ed..fe2d93adbff 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -40,6 +40,7 @@ #include "giteditor.h" #include "gitsubmiteditor.h" #include "gitversioncontrol.h" +#include "branchdialog.h" #include #include @@ -401,7 +402,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message) gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Branch"), this)); - m_branchListAction = new QAction(tr("List branches"), this); + m_branchListAction = new QAction(tr("Branches..."), this); command = actionManager->registerAction(m_branchListAction, "Git.BranchList", globalcontext); command->setAttribute(Core::ICommand::CA_UpdateText); connect(m_branchListAction, SIGNAL(triggered()), this, SLOT(branchList())); @@ -494,7 +495,6 @@ QString GitPlugin::getWorkingDirectory() qDebug() << Q_FUNC_INFO << "file" << workingDirectory; if (workingDirectory.isEmpty()) { - m_outputWindow->clearContents(); m_outputWindow->append(tr("Could not find working directory")); m_outputWindow->popup(false); return QString(); @@ -703,8 +703,17 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor) void GitPlugin::pull() { const QString workingDirectory = getWorkingDirectory(); - if (!workingDirectory.isEmpty()) - m_gitClient->pull(workingDirectory); + if (workingDirectory.isEmpty()) + return; + + switch (m_gitClient->ensureStash(workingDirectory)) { + case GitClient::StashUnchanged: + case GitClient::Stashed: + case GitClient::NotStashed: + m_gitClient->pull(workingDirectory); + default: + break; + } } void GitPlugin::push() @@ -731,8 +740,21 @@ void GitPlugin::stashPop() void GitPlugin::branchList() { const QString workingDirectory = getWorkingDirectory(); - if (!workingDirectory.isEmpty()) - m_gitClient->branchList(workingDirectory); + if (workingDirectory.isEmpty()) + return; +#ifndef USE_BRANCHDIALOG + QString errorMessage; + BranchDialog dialog(m_core->mainWindow()); + + if (!dialog.init(m_gitClient, workingDirectory, &errorMessage)) { + m_outputWindow->append(errorMessage); + m_outputWindow->popup(false); + return; + } + dialog.exec(); +#else + m_gitClient->branchList(workingDirectory); +#endif } void GitPlugin::stashList() diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 5e15a52a87a..39287e1939a 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -97,6 +97,7 @@ public: GitOutputWindow *outputWindow() const; + GitSettings settings() const; void setSettings(const GitSettings &s); diff --git a/src/plugins/helloworld/HelloWorld.pluginspec b/src/plugins/helloworld/HelloWorld.pluginspec index dab4cbfd3c8..54743ced9a3 100644 --- a/src/plugins/helloworld/HelloWorld.pluginspec +++ b/src/plugins/helloworld/HelloWorld.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Hello World sample plugin. http://www.trolltech.com/ - + diff --git a/src/plugins/helloworld/helloworldplugin.cpp b/src/plugins/helloworld/helloworldplugin.cpp index 296c00454ee..a8eb79c0519 100644 --- a/src/plugins/helloworld/helloworldplugin.cpp +++ b/src/plugins/helloworld/helloworldplugin.cpp @@ -33,26 +33,21 @@ #include "helloworldplugin.h" -#include "helloworldwindow.h" - -#include #include -#include -#include +#include #include +#include +#include #include +#include #include -#include +#include #include #include #include #include -#include - -#include "helloworldplugin.h" - using namespace HelloWorld::Internal; /*! Constructs the Hello World plugin. Normally plugins don't do anything in @@ -77,30 +72,20 @@ HelloWorldPlugin::~HelloWorldPlugin() \a error_message can be used to pass an error message to the plugin system, if there was any. */ -bool HelloWorldPlugin::initialize(const QStringList & /*arguments*/, QString *error_message) +bool HelloWorldPlugin::initialize(const QStringList &arguments, QString *error_message) { + Q_UNUSED(arguments) Q_UNUSED(error_message) // Get the primary access point to the workbench. Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - // Create our own widget that we want to show in a view in the IDE. - HelloWorldWindow *window = new HelloWorldWindow; - // Create a unique context id for our own view, that will be used for the // menu entry later. QList context = QList() << core->uniqueIDManager()->uniqueIdentifier( QLatin1String("HelloWorld.MainView")); - // Create a new view that contains our widget and register it with the - // plugin manager. The view will have the id "HelloWorld.HelloWorldWindow", - // and if it has focus it provides 'context' to the context list in - // Qt Creator. It will be put into the right dock widget area. - addAutoReleasedObject(new Core::BaseView("HelloWorld.HelloWorldWindow", - window, context, - Qt::RightDockWidgetArea)); - // Create an action to be triggered by a menu entry QAction *helloWorldAction = new QAction("Say \"&Hello World!\"", this); connect(helloWorldAction, SIGNAL(triggered()), SLOT(sayHelloWorld())); @@ -126,13 +111,15 @@ bool HelloWorldPlugin::initialize(const QStringList & /*arguments*/, QString *er actionManager->actionContainer(Core::Constants::M_TOOLS); toolsMenu->addMenu(helloWorldMenu); - // Add a mode with a push button based on BaseMode. Like the BaseView, it will unregister - // itself from the plugin manager when it is deleted. - addAutoReleasedObject(new Core::BaseMode(tr("Hello world!"), - "HelloWorld.HelloWorldMode", - QIcon(), - 0, // priority - new QPushButton(tr("Hello World PushButton!")))); + // Add a mode with a push button based on BaseMode. Like the BaseView, + // it will unregister itself from the plugin manager when it is deleted. + Core::BaseMode *baseMode = new Core::BaseMode; + baseMode->setUniqueModeName("HelloWorld.HelloWorldMode"); + baseMode->setName(tr("Hello world!")); + baseMode->setIcon(QIcon()); + baseMode->setPriority(0); + baseMode->setWidget(new QPushButton(tr("Hello World PushButton!"))); + addAutoReleasedObject(baseMode); // Add the Hello World action command to the mode manager (with 0 priority) Core::ModeManager *modeManager = core->modeManager(); diff --git a/src/plugins/help/Help.pluginspec b/src/plugins/help/Help.pluginspec index dfd438522a3..50c5863b8c9 100644 --- a/src/plugins/help/Help.pluginspec +++ b/src/plugins/help/Help.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Help system. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index bdc98b66ee1..5ecb375240d 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/perforce/Perforce.pluginspec b/src/plugins/perforce/Perforce.pluginspec index 496e420c36e..21df190d99a 100644 --- a/src/plugins/perforce/Perforce.pluginspec +++ b/src/plugins/perforce/Perforce.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Perforce integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp index 5a0b1d2340e..d54ce10de5f 100644 --- a/src/plugins/perforce/perforceeditor.cpp +++ b/src/plugins/perforce/perforceeditor.cpp @@ -151,7 +151,7 @@ QString PerforceEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) // Ask plugin to map back const QString fileName = m_plugin->fileNameFromPerforceName(diffFileName.trimmed(), &errorMessage); if (fileName.isEmpty()) - qWarning(errorMessage.toUtf8().constData()); + qWarning("%s", qPrintable(errorMessage)); return fileName; } } diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 4af2af4195c..bd7cbece15d 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -25,7 +25,8 @@ SUBDIRS = plugin_coreplugin \ # plugin_regexp \ # don't know what to do with this plugin_qtscripteditor \ plugin_cpaster \ - plugin_cmakeprojectmanager + plugin_cmakeprojectmanager \ + plugin_fakevim # These two plugins require private headers from Qt and therefore don't work # with an installed/released version of Qt. @@ -115,6 +116,11 @@ plugin_debugger.depends = plugin_projectexplorer plugin_debugger.depends += plugin_coreplugin plugin_debugger.depends += plugin_cppeditor +plugin_fakevim.subdir = fakevim +plugin_fakevim.depends = plugin_projectexplorer +plugin_fakevim.depends += plugin_coreplugin +plugin_fakevim.depends += plugin_cppeditor + plugin_qtestlib.subdir = qtestlib plugin_qtestlib.depends = plugin_projectexplorer plugin_qtestlib.depends += plugin_coreplugin diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec b/src/plugins/projectexplorer/ProjectExplorer.pluginspec index a60bbdf2949..aaecd57de93 100644 --- a/src/plugins/projectexplorer/ProjectExplorer.pluginspec +++ b/src/plugins/projectexplorer/ProjectExplorer.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License ProjectExplorer framework that can be extended with different kind of project types. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index c5d09426de0..c928239ed8b 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides project type for Qt 4 pro files and tools. http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/qt4projectmanager/directorywatcher.cpp b/src/plugins/qt4projectmanager/directorywatcher.cpp index 3434b0284d4..e2e0828219f 100644 --- a/src/plugins/qt4projectmanager/directorywatcher.cpp +++ b/src/plugins/qt4projectmanager/directorywatcher.cpp @@ -207,7 +207,8 @@ int FileWatcher::m_objectCount = 0; QHash FileWatcher::m_fileCount; QFileSystemWatcher *FileWatcher::m_watcher = 0; -FileWatcher::FileWatcher(QObject *parent) +FileWatcher::FileWatcher(QObject *parent) : + QObject(parent) { if (!m_watcher) m_watcher = new QFileSystemWatcher(); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp index 2ee2d0f8bc0..13fb5980a90 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp @@ -54,6 +54,8 @@ Qt4BuildConfigWidget::Qt4BuildConfigWidget(Qt4Project *project) { m_ui = new Ui::Qt4BuildConfigWidget(); m_ui->setupUi(this); + m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory")); + m_ui->shadowBuildDirEdit->setExpectedKind(Core::Utils::PathChooser::Directory); m_ui->invalidQtWarningLabel->setVisible(false); connect(m_ui->nameLineEdit, SIGNAL(textEdited(QString)), @@ -62,10 +64,10 @@ Qt4BuildConfigWidget::Qt4BuildConfigWidget(Qt4Project *project) connect(m_ui->shadowBuildCheckBox, SIGNAL(clicked(bool)), this, SLOT(shadowBuildCheckBoxClicked(bool))); - connect(m_ui->shadowBuildButton, SIGNAL(clicked(bool)), - this, SLOT(shadowBuildButtonClicked())); + connect(m_ui->shadowBuildDirEdit, SIGNAL(beforeBrowsing()), + this, SLOT(onBeforeBeforeShadowBuildDirBrowsed())); - connect(m_ui->shadowBuildLineEdit, SIGNAL(textEdited(QString)), + connect(m_ui->shadowBuildDirEdit, SIGNAL(changed()), this, SLOT(shadowBuildLineEditTextChanged())); connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)), @@ -102,10 +104,9 @@ void Qt4BuildConfigWidget::init(const QString &buildConfiguration) bool shadowBuild = m_pro->value(buildConfiguration, "useShadowBuild").toBool(); m_ui->shadowBuildCheckBox->setChecked(shadowBuild); - m_ui->shadowBuildLineEdit->setEnabled(shadowBuild); - m_ui->shadowBuildLineEdit->setText(m_pro->buildDirectory(buildConfiguration)); + m_ui->shadowBuildDirEdit->setEnabled(shadowBuild); + m_ui->shadowBuildDirEdit->setPath(m_pro->buildDirectory(buildConfiguration)); shadowBuildLineEditTextChanged(); // Update the import label - m_ui->shadowBuildButton->setEnabled(shadowBuild); } void Qt4BuildConfigWidget::changeConfigName(const QString &newName) @@ -145,47 +146,39 @@ void Qt4BuildConfigWidget::setupQtVersionsComboBox() this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString))); } -void Qt4BuildConfigWidget::shadowBuildButtonClicked() +void Qt4BuildConfigWidget::onBeforeBeforeShadowBuildDirBrowsed() { - QString initialDirectory = m_ui->shadowBuildLineEdit->text(); - if (initialDirectory.isEmpty()) - initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath(); - - QString shadowBuildDirectory = - QFileDialog::getExistingDirectory(this, tr("Shadow Build Directory"), initialDirectory ); - - if (shadowBuildDirectory != QString::null) - m_ui->shadowBuildLineEdit->setText(shadowBuildDirectory); - shadowBuildLineEditTextChanged(); + QString initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath(); + if (!initialDirectory.isEmpty()) + m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory); } void Qt4BuildConfigWidget::shadowBuildCheckBoxClicked(bool checked) { - m_ui->shadowBuildLineEdit->setEnabled(checked); - m_ui->shadowBuildButton->setEnabled(checked); + m_ui->shadowBuildDirEdit->setEnabled(checked); bool b = m_ui->shadowBuildCheckBox->isChecked(); m_pro->setValue(m_buildConfiguration, "useShadowBuild", b); if (b) - m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildLineEdit->text()); + m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path()); else m_pro->setValue(m_buildConfiguration, "buildDirectory", QVariant(QString::null)); } void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged() { - m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildLineEdit->text()); + m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path()); // if the directory already exists // check if we have a build in there and // offer to import it m_ui->importLabel->setVisible(false); if (m_ui->shadowBuildCheckBox->isChecked()) { - QString qtPath = m_pro->qt4ProjectManager()->versionManager()->findQtVersionFromMakefile(m_ui->shadowBuildLineEdit->text()); + QString qtPath = m_pro->qt4ProjectManager()->versionManager()->findQtVersionFromMakefile(m_ui->shadowBuildDirEdit->path()); if (!qtPath.isEmpty()) { m_ui->importLabel->setVisible(true); } } -// QFileInfo fi(m_ui->shadowBuildLineEdit->text()); +// QFileInfo fi(m_ui->shadowBuildDirEdit->path()); // if (fi.exists()) { // m_ui->shadowBuildLineEdit->setStyleSheet(""); // m_ui->shadowBuildLineEdit->setToolTip(""); @@ -198,7 +191,7 @@ void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged() void Qt4BuildConfigWidget::importLabelClicked() { if (m_ui->shadowBuildCheckBox->isChecked()) { - QString directory = m_ui->shadowBuildLineEdit->text(); + QString directory = m_ui->shadowBuildDirEdit->path(); if (!directory.isEmpty()) { QtVersionManager *vm = m_pro->qt4ProjectManager()->versionManager(); QString qtPath = vm->findQtVersionFromMakefile(directory); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h index 622ce98be2e..c7910b44b04 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h @@ -60,7 +60,7 @@ private slots: void changeConfigName(const QString &newName); void setupQtVersionsComboBox(); void shadowBuildCheckBoxClicked(bool checked); - void shadowBuildButtonClicked(); + void onBeforeBeforeShadowBuildDirBrowsed(); void shadowBuildLineEditTextChanged(); void importLabelClicked(); void qtVersionComboBoxCurrentIndexChanged(const QString &); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui b/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui index f62d4a69b53..ab5e8858611 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui @@ -110,39 +110,6 @@
- - - - - - - 100 - 0 - - - - - 16777215 - 16777215 - - - - - - - - - 0 - 0 - - - - ... - - - - - @@ -153,6 +120,16 @@ + + + + + 0 + 0 + + + +
@@ -186,6 +163,14 @@
+ + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 2a7fd0c242c..dd61dbde099 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/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 3c3de8fd0e0..e39240118d1 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -368,6 +368,10 @@ QtDirWidget::QtDirWidget(QWidget *parent, QList versions, int defau , m_specifyPathString(tr("")) { m_ui.setupUi(this); + m_ui.qtPath->setExpectedKind(Core::Utils::PathChooser::Directory); + m_ui.qtPath->setPromptDialogTitle(tr("Select QTDIR")); + m_ui.mingwPath->setExpectedKind(Core::Utils::PathChooser::Directory); + m_ui.qtPath->setPromptDialogTitle(tr("Select MinGW Directory")); m_ui.addButton->setIcon(QIcon(Core::Constants::ICON_PLUS)); m_ui.delButton->setIcon(QIcon(Core::Constants::ICON_MINUS)); @@ -385,19 +389,22 @@ QtDirWidget::QtDirWidget(QWidget *parent, QList versions, int defau connect(m_ui.nameEdit, SIGNAL(textEdited(const QString &)), this, SLOT(updateCurrentQtName())); - connect(m_ui.pathEdit, SIGNAL(textEdited(const QString &)), + + + connect(m_ui.qtPath, SIGNAL(changed()), this, SLOT(updateCurrentQtPath())); - connect(m_ui.mingwLineEdit, SIGNAL(textEdited(const QString &)), + connect(m_ui.mingwPath, SIGNAL(changed()), this, SLOT(updateCurrentMingwDirectory())); connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addQtDir())); connect(m_ui.delButton, SIGNAL(clicked()), this, SLOT(removeQtDir())); - connect(m_ui.browseButton, SIGNAL(clicked()), - this, SLOT(browse())); - connect(m_ui.mingwBrowseButton, SIGNAL(clicked()), - this, SLOT(mingwBrowse())); + + connect(m_ui.qtPath, SIGNAL(browsingFinished()), + this, SLOT(onQtBrowsed())); + connect(m_ui.mingwPath, SIGNAL(browsingFinished()), + this, SLOT(onMingwBrowsed())); connect(m_ui.qtdirList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(versionChanged(QTreeWidgetItem *, QTreeWidgetItem *))); @@ -421,11 +428,11 @@ void QtDirWidget::addQtDir() item->setText(1, newVersion->path()); item->setData(0, Qt::UserRole, newVersion->uniqueId()); - m_ui.nameEdit->setText(newVersion->name()); - m_ui.pathEdit->setText(newVersion->path()); - - m_ui.defaultCombo->addItem(newVersion->name()); m_ui.qtdirList->setCurrentItem(item); + + m_ui.nameEdit->setText(newVersion->name()); + m_ui.qtPath->setPath(newVersion->path()); + m_ui.defaultCombo->addItem(newVersion->name()); m_ui.nameEdit->setFocus(); m_ui.nameEdit->selectAll(); } @@ -459,10 +466,14 @@ void QtDirWidget::updateState() && m_versions.at(m_ui.qtdirList->indexOfTopLevelItem(m_ui.qtdirList->currentItem()))->isSystemVersion()); m_ui.delButton->setEnabled(enabled && !isSystemVersion); m_ui.nameEdit->setEnabled(enabled && !isSystemVersion); - m_ui.pathEdit->setEnabled(enabled && !isSystemVersion); - m_ui.browseButton->setEnabled(enabled && !isSystemVersion); - m_ui.mingwBrowseButton->setEnabled(enabled); - m_ui.mingwLineEdit->setEnabled(enabled); + m_ui.qtPath->setEnabled(enabled && !isSystemVersion); + m_ui.mingwPath->setEnabled(enabled); +} + +void QtDirWidget::makeMingwVisible(bool visible) +{ + m_ui.mingwLabel->setVisible(visible); + m_ui.mingwPath->setVisible(visible); } void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) @@ -475,16 +486,12 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) if (t == QtVersion::MinGW) { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(true); - m_ui.mingwLabel->setVisible(true); - m_ui.mingwBrowseButton->setVisible(true); - m_ui.mingwLineEdit->setText(m_versions.at(index)->mingwDirectory()); + makeMingwVisible(true); + m_ui.mingwPath->setPath(m_versions.at(index)->mingwDirectory()); } else if (t == QtVersion::MSVC || t == QtVersion::WINCE){ m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(true); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); QList msvcenvironments = MSVCEnvironment::availableVersions(); if (msvcenvironments.count() == 0) { m_ui.msvcLabel->setText(tr("No Visual Studio Installation found")); @@ -506,9 +513,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else if (t == QtVersion::INVALID) { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); if (!m_versions.at(index)->isInstalled()) m_ui.errorLabel->setText(tr("The Qt Version is not installed. Run make install") .arg(m_versions.at(index)->path())); @@ -517,9 +522,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { //QtVersion::Other m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); m_ui.errorLabel->setText("Found Qt version " + m_versions.at(index)->qtVersionString() + " using mkspec " @@ -528,9 +531,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); } } @@ -541,24 +542,21 @@ void QtDirWidget::versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old) } if (item) { m_ui.nameEdit->setText(item->text(0)); - m_ui.pathEdit->setText(item->text(1)); + m_ui.qtPath->setPath(item->text(1)); } else { m_ui.nameEdit->clear(); - m_ui.pathEdit->clear(); + m_ui.qtPath->setPath(""); // clear() } showEnvironmentPage(item); updateState(); } -void QtDirWidget::browse() +void QtDirWidget::onQtBrowsed() { - QString dir = QFileDialog::getExistingDirectory(this, tr("Select QTDIR")); - + const QString dir = m_ui.qtPath->path(); if (dir.isEmpty()) return; - dir = QDir::toNativeSeparators(dir); - m_ui.pathEdit->setText(dir); updateCurrentQtPath(); if (m_ui.nameEdit->text().isEmpty() || m_ui.nameEdit->text() == m_specifyNameString) { QStringList dirSegments = dir.split(QDir::separator(), QString::SkipEmptyParts); @@ -569,14 +567,12 @@ void QtDirWidget::browse() updateState(); } -void QtDirWidget::mingwBrowse() +void QtDirWidget::onMingwBrowsed() { - QString dir = QFileDialog::getExistingDirectory(this, tr("Select MinGW Directory")); + const QString dir = m_ui.mingwPath->path(); if (dir.isEmpty()) return; - dir = QDir::toNativeSeparators(dir); - m_ui.mingwLineEdit->setText(dir); updateCurrentMingwDirectory(); updateState(); } @@ -647,7 +643,7 @@ void QtDirWidget::updateCurrentQtPath() QTreeWidgetItem *currentItem = m_ui.qtdirList->currentItem(); Q_ASSERT(currentItem); int currentItemIndex = m_ui.qtdirList->indexOfTopLevelItem(currentItem); - m_versions[currentItemIndex]->setPath(m_ui.pathEdit->text()); + m_versions[currentItemIndex]->setPath(m_ui.qtPath->path()); currentItem->setText(1, m_versions[currentItemIndex]->path()); showEnvironmentPage(currentItem); @@ -658,7 +654,7 @@ void QtDirWidget::updateCurrentMingwDirectory() QTreeWidgetItem *currentItem = m_ui.qtdirList->currentItem(); Q_ASSERT(currentItem); int currentItemIndex = m_ui.qtdirList->indexOfTopLevelItem(currentItem); - m_versions[currentItemIndex]->setMingwDirectory(m_ui.mingwLineEdit->text()); + m_versions[currentItemIndex]->setMingwDirectory(m_ui.mingwPath->path()); } void QtDirWidget::msvcVersionChanged() @@ -1075,7 +1071,7 @@ void QtVersion::updateMkSpec() const if (line.startsWith("QMAKESPEC_ORIGINAL")) { const QList &temp = line.split('='); if (temp.size() == 2) { - mkspec = temp.at(1); + mkspec = temp.at(1).trimmed(); } break; } diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 164e40c6d8e..a76a62ada04 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -149,8 +149,9 @@ private slots: void addQtDir(); void removeQtDir(); void updateState(); - void browse(); - void mingwBrowse(); + void makeMingwVisible(bool visible); + void onQtBrowsed(); + void onMingwBrowsed(); void defaultChanged(int index); void updateCurrentQtName(); void updateCurrentQtPath(); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.ui b/src/plugins/qt4projectmanager/qtversionmanager.ui index de93505cb09..0d3941d0388 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.ui +++ b/src/plugins/qt4projectmanager/qtversionmanager.ui @@ -109,16 +109,6 @@ - - - - - - - ... - - - @@ -126,16 +116,6 @@ - - - - - - - ... - - - @@ -153,6 +133,12 @@ + + + + + + @@ -179,34 +165,20 @@ + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
qtdirList delButton nameEdit - pathEdit defaultCombo - browseButton - - - - - - - - - - - - - - - - - - - - - +
diff --git a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec index f303e35e454..1cb3129b81e 100644 --- a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec +++ b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for QtScript. http://www.trolltech.com/ - - + + diff --git a/src/plugins/quickopen/QuickOpen.pluginspec b/src/plugins/quickopen/QuickOpen.pluginspec index 088f2affc95..85d9a5cc476 100644 --- a/src/plugins/quickopen/QuickOpen.pluginspec +++ b/src/plugins/quickopen/QuickOpen.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the QuickOpen widget and the hooks for QuickOpen filter implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/quickopen/quickopentoolwindow.cpp b/src/plugins/quickopen/quickopentoolwindow.cpp index 415e347a3ac..b3232147f37 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 = ""; + QString searchText = ""; QAction *action = qobject_cast(sender()); QTC_ASSERT(action, return); IQuickOpenFilter *filter = action->data().value(); 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/regexp/RegExp.pluginspec b/src/plugins/regexp/RegExp.pluginspec index c284def7f3a..e0c4ac44c20 100644 --- a/src/plugins/regexp/RegExp.pluginspec +++ b/src/plugins/regexp/RegExp.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Regular Expression test widget. http://www.trolltech.com/ - + diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec b/src/plugins/resourceeditor/ResourceEditor.pluginspec index e46b249dbf4..fc7911e67cd 100644 --- a/src/plugins/resourceeditor/ResourceEditor.pluginspec +++ b/src/plugins/resourceeditor/ResourceEditor.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for qrc files. http://www.trolltech.com/ - + diff --git a/src/plugins/snippets/Snippets.pluginspec b/src/plugins/snippets/Snippets.pluginspec index 9128dc76e9a..f7e0a18c2a0 100644 --- a/src/plugins/snippets/Snippets.pluginspec +++ b/src/plugins/snippets/Snippets.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Code snippet plugin. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/subversion/Subversion.pluginspec b/src/plugins/subversion/Subversion.pluginspec index bddb93aba6c..4e9c76c118d 100644 --- a/src/plugins/subversion/Subversion.pluginspec +++ b/src/plugins/subversion/Subversion.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Subversion integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/texteditor/TextEditor.pluginspec b/src/plugins/texteditor/TextEditor.pluginspec index 5c9506925cf..5f7d9a66ce7 100644 --- a/src/plugins/texteditor/TextEditor.pluginspec +++ b/src/plugins/texteditor/TextEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Text editor framework and the implementation of the basic text editor. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 48de83d5ef2..ea4f665a7e9 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1603,7 +1603,6 @@ namespace TextEditor { int firstColumn; int lastColumn; }; - } } diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp index 661cda0c322..2c9f6017b7f 100644 --- a/src/plugins/texteditor/completionwidget.cpp +++ b/src/plugins/texteditor/completionwidget.cpp @@ -39,8 +39,9 @@ #include #include -#include #include +#include +#include #include #include @@ -130,6 +131,8 @@ CompletionWidget::CompletionWidget(CompletionSupport *support, ITextEditable *ed layout->addWidget(this); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_popupFrame->setMinimumSize(1, 1); + setMinimumSize(1, 1); } bool CompletionWidget::event(QEvent *e) @@ -227,20 +230,15 @@ void CompletionWidget::setCompletionItems(const QListcursorRect(startPos).bottomLeft(); - m_popupFrame->move(pos.x() - 16, pos.y()); - m_popupFrame->setMinimumSize(1, 1); - setMinimumSize(1, 1); - - updateSize(); - + updatePositionAndSize(startPos); m_popupFrame->show(); show(); setFocus(); } -void CompletionWidget::updateSize() +void CompletionWidget::updatePositionAndSize(int startPos) { + // Determine size by calculating the space of the visible items int visibleItems = m_model->rowCount(); if (visibleItems > NUMBER_OF_VISIBLE_ITEMS) visibleItems = NUMBER_OF_VISIBLE_ITEMS; @@ -254,10 +252,29 @@ void CompletionWidget::updateSize() shint = tmp; } - const int width = (shint.width() + (m_popupFrame->frameWidth() * 2) + 30); - const int height = (shint.height() * visibleItems) + m_popupFrame->frameWidth() * 2; + const int frameWidth = m_popupFrame->frameWidth(); + const int width = shint.width() + frameWidth * 2 + 30; + const int height = shint.height() * visibleItems + frameWidth * 2; - m_popupFrame->resize(width, height); + // Determine the position, keeping the popup on the screen + const QRect cursorRect = m_editor->cursorRect(startPos); + const QDesktopWidget *desktop = QApplication::desktop(); +#ifdef Q_OS_MAC + const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editorWidget)); +#else + const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editorWidget)); +#endif + + QPoint pos = cursorRect.bottomLeft(); + pos.rx() -= 16 + frameWidth; // Space for the icons + + if (pos.y() + height > screen.bottom()) + pos.setY(cursorRect.top() - height); + + if (pos.x() + width > screen.right()) + pos.setX(screen.right() - width); + + m_popupFrame->setGeometry(pos.x(), pos.y(), width, height); } void CompletionWidget::completionActivated(const QModelIndex &index) diff --git a/src/plugins/texteditor/completionwidget.h b/src/plugins/texteditor/completionwidget.h index c1fb28fc1cf..b124d2e257a 100644 --- a/src/plugins/texteditor/completionwidget.h +++ b/src/plugins/texteditor/completionwidget.h @@ -74,7 +74,7 @@ private slots: void completionActivated(const QModelIndex &index); private: - void updateSize(); + void updatePositionAndSize(int startPos); QPointer m_popupFrame; bool m_blockFocusOut; diff --git a/src/plugins/vcsbase/VCSBase.pluginspec b/src/plugins/vcsbase/VCSBase.pluginspec index 1f9cd30dd2d..87e3ae9eac8 100644 --- a/src/plugins/vcsbase/VCSBase.pluginspec +++ b/src/plugins/vcsbase/VCSBase.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Version Control System Base Plugin http://www.trolltech.com/ - - - + + + diff --git a/tests/auto/cplusplus/cplusplus.pro b/tests/auto/cplusplus/cplusplus.pro index 97256476470..55e6cd83f0e 100644 --- a/tests/auto/cplusplus/cplusplus.pro +++ b/tests/auto/cplusplus/cplusplus.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = shared ast +SUBDIRS = shared ast semantic CONFIG += ordered diff --git a/tests/auto/cplusplus/semantic/semantic.pro b/tests/auto/cplusplus/semantic/semantic.pro new file mode 100644 index 00000000000..71a8b5fab5f --- /dev/null +++ b/tests/auto/cplusplus/semantic/semantic.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +include(../shared/shared.pri) +QT = core + +SOURCES += tst_semantic.cpp diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp new file mode 100644 index 00000000000..2da819d5af7 --- /dev/null +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -0,0 +1,323 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CPLUSPLUS_USE_NAMESPACE + +class tst_Semantic: public QObject +{ + Q_OBJECT + + Control control; + +public: + tst_Semantic() + { control.setDiagnosticClient(&diag); } + + TranslationUnit *parse(const QByteArray &source, + TranslationUnit::ParseMode mode) + { + StringLiteral *fileId = control.findOrInsertFileName(""); + TranslationUnit *unit = new TranslationUnit(&control, fileId); + unit->setSource(source.constData(), source.length()); + unit->parse(mode); + return unit; + } + + class Document { + Q_DISABLE_COPY(Document) + + public: + Document(TranslationUnit *unit) + : unit(unit), globals(new Scope()), errorCount(0) + { } + + ~Document() + { delete globals; } + + void check() + { + QVERIFY(unit); + QVERIFY(unit->ast()); + Semantic sem(unit->control()); + TranslationUnitAST *ast = unit->ast()->asTranslationUnit(); + QVERIFY(ast); + for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { + sem.check(decl, globals); + } + } + + TranslationUnit *unit; + Scope *globals; + unsigned errorCount; + }; + + class Diagnostic: public DiagnosticClient { + public: + int errorCount; + + Diagnostic() + : errorCount(0) + { } + + virtual void report(int, StringLiteral *, + unsigned, unsigned, + const char *, va_list) + { ++errorCount; } + }; + + Diagnostic diag; + + + QSharedPointer document(const QByteArray &source) + { + diag.errorCount = 0; // reset the error count. + TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit); + QSharedPointer doc(new Document(unit)); + doc->check(); + doc->errorCount = diag.errorCount; + return doc; + } + +private slots: + void function_declaration_1(); + void function_declaration_2(); + void function_definition_1(); + void nested_class_1(); + void typedef_1(); + void typedef_2(); + void typedef_3(); +}; + +void tst_Semantic::function_declaration_1() +{ + QSharedPointer doc = document("void foo();"); + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); + QVERIFY(decl); + + FullySpecifiedType declTy = decl->type(); + Function *funTy = declTy->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 0U); + + QVERIFY(decl->name()->isNameId()); + Identifier *funId = decl->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} + +void tst_Semantic::function_declaration_2() +{ + QSharedPointer doc = document("void foo(const QString &s);"); + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); + QVERIFY(decl); + + FullySpecifiedType declTy = decl->type(); + Function *funTy = declTy->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 1U); + + // check the formal argument. + Argument *arg = funTy->argumentAt(0)->asArgument(); + QVERIFY(arg); + QVERIFY(arg->name()); + QVERIFY(! arg->hasInitializer()); + + // check the argument's name. + NameId *argNameId = arg->name()->asNameId(); + QVERIFY(argNameId); + + Identifier *argId = argNameId->identifier(); + QVERIFY(argId); + + QCOMPARE(QByteArray(argId->chars(), argId->size()), QByteArray("s")); + + // check the type of the formal argument + FullySpecifiedType argTy = arg->type(); + QVERIFY(argTy->isReferenceType()); + QVERIFY(argTy->asReferenceType()->elementType().isConst()); + NamedType *namedTy = argTy->asReferenceType()->elementType()->asNamedType(); + QVERIFY(namedTy); + QVERIFY(namedTy->name()); + Identifier *namedTypeId = namedTy->name()->asNameId()->identifier(); + QVERIFY(namedTypeId); + QCOMPARE(QByteArray(namedTypeId->chars(), namedTypeId->size()), + QByteArray("QString")); + + QVERIFY(decl->name()->isNameId()); + Identifier *funId = decl->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} + +void tst_Semantic::function_definition_1() +{ + QSharedPointer doc = document("void foo() {}"); + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Function *funTy = doc->globals->symbolAt(0)->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 0U); + + QVERIFY(funTy->name()->isNameId()); + Identifier *funId = funTy->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} + +void tst_Semantic::nested_class_1() +{ + QSharedPointer doc = document( +"class Object {\n" +" class Data;\n" +" Data *d;\n" +"};\n" +"class Object::Data {\n" +" Object *q;\n" +"};\n" + ); + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 2U); + + Class *classObject = doc->globals->symbolAt(0)->asClass(); + QVERIFY(classObject); + QVERIFY(classObject->name()); + NameId *classObjectNameId = classObject->name()->asNameId(); + QVERIFY(classObjectNameId); + Identifier *objectId = classObjectNameId->identifier(); + QCOMPARE(QByteArray(objectId->chars(), objectId->size()), QByteArray("Object")); + QCOMPARE(classObject->baseClassCount(), 0U); + QEXPECT_FAIL("", "Requires support for forward classes", Continue); + QCOMPARE(classObject->members()->symbolCount(), 2U); + + Class *classObjectData = doc->globals->symbolAt(1)->asClass(); + QVERIFY(classObjectData); + QVERIFY(classObjectData->name()); + QualifiedNameId *q = classObjectData->name()->asQualifiedNameId(); + QVERIFY(q); + QCOMPARE(q->nameCount(), 2U); + QVERIFY(q->nameAt(0)->asNameId()); + QVERIFY(q->nameAt(1)->asNameId()); + QCOMPARE(q->nameAt(0), classObject->name()); + QCOMPARE(doc->globals->lookat(q->nameAt(0)->asNameId()->identifier()), classObject); + + Declaration *decl = classObjectData->memberAt(0)->asDeclaration(); + QVERIFY(decl); + PointerType *ptrTy = decl->type()->asPointerType(); + QVERIFY(ptrTy); + NamedType *namedTy = ptrTy->elementType()->asNamedType(); + QVERIFY(namedTy); + QVERIFY(namedTy->name()->asNameId()); + QCOMPARE(namedTy->name()->asNameId()->identifier(), objectId); +} + +void tst_Semantic::typedef_1() +{ + QSharedPointer doc = document( +"typedef struct {\n" +" int x, y;\n" +"} Point;\n" +"int main() {\n" +" Point pt;\n" +" pt.x = 1;\n" +"}\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 3U); + + Class *anonStruct = doc->globals->symbolAt(0)->asClass(); + QVERIFY(anonStruct); + QCOMPARE(anonStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QCOMPARE(typedefPointDecl->type()->asClass(), anonStruct); + + Function *mainFun = doc->globals->symbolAt(2)->asFunction(); + QVERIFY(mainFun); +} + +void tst_Semantic::typedef_2() +{ + QSharedPointer doc = document( +"struct _Point {\n" +" int x, y;\n" +"};\n" +"typedef _Point Point;\n" +"int main() {\n" +" Point pt;\n" +" pt.x = 1;\n" +"}\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 3U); + + Class *_pointStruct= doc->globals->symbolAt(0)->asClass(); + QVERIFY(_pointStruct); + QCOMPARE(_pointStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QVERIFY(typedefPointDecl->type()->isNamedType()); + QCOMPARE(typedefPointDecl->type()->asNamedType()->name(), _pointStruct->name()); + + Function *mainFun = doc->globals->symbolAt(2)->asFunction(); + QVERIFY(mainFun); +} + +void tst_Semantic::typedef_3() +{ + QSharedPointer doc = document( +"typedef struct {\n" +" int x, y;\n" +"} *PointPtr;\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 2U); + + Class *_pointStruct= doc->globals->symbolAt(0)->asClass(); + QVERIFY(_pointStruct); + QCOMPARE(_pointStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QVERIFY(typedefPointDecl->type()->isPointerType()); + QCOMPARE(typedefPointDecl->type()->asPointerType()->elementType()->asClass(), + _pointStruct); +} + +QTEST_APPLESS_MAIN(tst_Semantic) +#include "tst_semantic.moc" diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro new file mode 100644 index 00000000000..29936b2568f --- /dev/null +++ b/tests/auto/fakevim/fakevim.pro @@ -0,0 +1,14 @@ + +QT += testlib + +FAKEVIMSOURCE = /data/qt-creator/src/plugins/fakevim + +INCLUDEPATH += $$FAKEVIMSOURCE + +SOURCES += \ + main.cpp \ + $$FAKEVIMSOURCE/handler.cpp + +HEADERS += \ + $$FAKEVIMSOURCE/handler.h + diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp new file mode 100644 index 00000000000..28a05dcd530 --- /dev/null +++ b/tests/auto/fakevim/main.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** +** +** 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 "handler.h" + +#include +#include + +class tst_FakeVim : public QObject +{ + Q_OBJECT + +private slots: +}; + + +QTEST_MAIN(tst_FakeVim) + +#include "main.moc" diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index 641c25366c8..c33bcbbeff7 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -32,20 +32,212 @@ ***************************************************************************/ #include +#include #include #include #include #include +#include -#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include -int main(int, char *[]) +class Rewrite { - Control control; - StringLiteral *fileId = control.findOrInsertFileName(""); + QMultiMap _insertBefore; + QMultiMap _insertAfter; + QSet _removed; + +public: + void remove(unsigned index) + { remove(index, index + 1); } + + void remove(unsigned first, unsigned last) + { + Q_ASSERT(first < last); + + for (; first != last; ++first) + _removed.insert(first); + } + + void insertTextBefore(unsigned index, const QByteArray &text) + { _insertBefore.insert(index, text); } + + void insertTextAfter(unsigned index, const QByteArray &text) + { _insertAfter.insert(index, text); } + + void rewrite(const TranslationUnit *unit, + const QByteArray &contents, + QByteArray *out) const + { + const char *source = contents.constData(); + unsigned previousTokenEndPosition = 0; + for (unsigned i = 0; i < unit->tokenCount(); ++i) { + const Token &tk = unit->tokenAt(i); + + if (previousTokenEndPosition != tk.begin()) { + Q_ASSERT(previousTokenEndPosition < tk.begin()); + out->append(source + previousTokenEndPosition, + tk.begin() - previousTokenEndPosition); + } + + QMultiMap::const_iterator it; + + it = _insertBefore.constFind(i); + for (; it != _insertBefore.constEnd() && it.key() == i; ++it) { + out->append(it.value()); + } + + if (! _removed.contains(i)) + out->append(source + tk.begin(), tk.length); + + it = _insertAfter.constFind(i); + for (; it != _insertAfter.constEnd() && it.key() == i; ++it) { + out->append(it.value()); + } + + previousTokenEndPosition = tk.end(); + } + } +}; + +class SimpleRefactor: protected ASTVisitor, Rewrite { +public: + SimpleRefactor(Control *control) + : ASTVisitor(control) + { } + + void operator()(const TranslationUnit *unit, + const QByteArray &source, + QByteArray *out) + { + accept(unit->ast()); + rewrite(unit, source, out); + } + +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) { + // change visibility from `private' to `public'. + remove(ast->access_specifier_token); + insertTextAfter(ast->access_specifier_token, "public /* #REF# private->public */"); + } + return true; + } + + virtual bool visit(FunctionDefinitionAST *ast) + { + bool isInline = false; + for (SpecifierAST *spec = ast->decl_specifier_seq; spec; spec = spec->next) { + if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) { + if (tokenKind(simpleSpec->specifier_token) == T_INLINE) { + isInline = true; + break; + } + } + } + + // force the `inline' specifier. + if (! isInline) + insertTextBefore(ast->firstToken(), "inline /* #REF# made inline */ "); + + return true; + } + + virtual bool visit(ClassSpecifierAST *ast) + { + // export/import the class using the macro MY_EXPORT. + if (ast->name) + insertTextBefore(ast->name->firstToken(), "MY_EXPORT "); + + // add QObject to the base clause. + if (ast->colon_token) + insertTextAfter(ast->colon_token, " public QObject,"); + else if (ast->lbrace_token) + insertTextBefore(ast->lbrace_token, ": public QObject "); + + // mark the class as Q_OBJECT. + if (ast->lbrace_token) + insertTextAfter(ast->lbrace_token, " Q_OBJECT\n"); + + 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(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 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)) @@ -53,19 +245,32 @@ int main(int, char *[]) const QByteArray source = in.readAll(); + Control control; + StringLiteral *fileId = control.findOrInsertFileName(""); TranslationUnit unit(&control, fileId); unit.setSource(source.constData(), source.size()); unit.parse(); - if (unit.ast()) { - TranslationUnitAST *ast = unit.ast()->asTranslationUnit(); - Q_ASSERT(ast != 0); + if (! unit.ast()) + return EXIT_FAILURE; - Scope globalScope; - Semantic sem(&control); - for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { - sem.check(decl, &globalScope); - } + TranslationUnitAST *ast = unit.ast()->asTranslationUnit(); + Q_ASSERT(ast != 0); + + Scope globalScope; + Semantic sem(&control); + for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { + sem.check(decl, &globalScope); } + // test the rewriter + 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 00000000000..7403721300e --- /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 00000000000..c0494257c8f --- /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 00000000000..c489dd3b072 --- /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(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 00000000000..ed3046b76c9 --- /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 00000000000..8c504a62a81 --- /dev/null +++ b/tests/manual/fakevim/main.cpp @@ -0,0 +1,63 @@ + +#include "handler.h" + +#include + +#include +#include +#include +#include +#include + +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 5156e6fb5fd..15ec4a7bd8e 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -191,6 +193,43 @@ void testIO() std::cerr << "std::cerr 3\n"; } +void testQLinkedList() +{ +#if 1 + QLinkedList li; + QLinkedList lu; + + for (int i = 0; i != 3; ++i) + li.append(i); + li.append(102); + + + lu.append(102); + lu.append(102); + lu.append(102); + + QLinkedList lpi; + lpi.append(new Foo(1)); + lpi.append(0); + lpi.append(new Foo(3)); + + QLinkedList l; + l.append(42); + l.append(43); + l.append(44); + l.append(45); + + QLinkedList f; + f.append(Foo(1)); + f.append(Foo(2)); +#endif + + QLinkedList v; + v.push_back("aa"); + v.push_back("bb"); + v.push_back("cc"); + v.push_back("dd"); + } void testQList() { @@ -289,6 +328,36 @@ void testQMap() #endif } +void testQMultiMap() +{ + QMultiMap 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 gg1; + gg1.insert("22.0", 22.0); + + QMultiMap gg2; + gg2.insert(22, "22.0"); + + QMultiMap gg3; + gg3.insert("22.0", Foo(22)); + gg3.insert("33.0", Foo(33)); + gg3.insert("22.0", Foo(22)); + + QObject ob; + QMultiMap > map; + map.insert("Hallo", QPointer(&ob)); + map.insert("Welt", QPointer(&ob)); + map.insert(".", QPointer(&ob)); + map.insert(".", QPointer(&ob)); +#endif +} + void testQObject(int &argc, char *argv[]) { QApplication app(argc, argv); @@ -850,12 +919,14 @@ int main(int argc, char *argv[]) testPlugin(); testQList(); + testQLinkedList(); testNamespace(); //return 0; testQByteArray(); testQHash(); testQImage(); testQMap(); + testQMultiMap(); testQString(); testQSet(); testQStringList(); @@ -868,7 +939,7 @@ int main(int argc, char *argv[]) testQVectorOfQList(); - *(int *)0 = 0; + //*(int *)0 = 0; testQObject(argc, argv);