From 1e986f2d5213953df197b7eb3b4d95e718a9c3dd Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 5 Apr 2011 16:41:49 +0200 Subject: [PATCH 01/24] QmlDesigner.propertyEditor: crash fix Reviewed-by: Marco Bubke --- .../qmldesigner/components/propertyeditor/siblingcombobox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/siblingcombobox.cpp b/src/plugins/qmldesigner/components/propertyeditor/siblingcombobox.cpp index b1b54e90e15..31f8489652d 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/siblingcombobox.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/siblingcombobox.cpp @@ -81,7 +81,7 @@ void SiblingComboBox::setup() //We currently have no instanceChildren(). //So we double check here if the instanceParents are equal. foreach (const QmlItemNode &node, m_itemList) - if (node.instanceParent().modelNode() != m_itemNode.instanceParent().modelNode()) + if (node.isValid() && (node.instanceParent().modelNode() != m_itemNode.instanceParent().modelNode())) m_itemList.removeAll(node); disconnect(this, SIGNAL(currentIndexChanged (int)), this, SLOT(changeSelection(int))); From 40d8f686c9062e7cc7c810ccf42588a1b3851799 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 5 Apr 2011 16:42:37 +0200 Subject: [PATCH 02/24] QmlDesigner.model: crash fix Reviewed-by: Marco Bubke --- src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp index a31114f12e7..a8d8dcea05e 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp @@ -292,7 +292,7 @@ NodeInstance QmlModelView::instanceForModelNode(const ModelNode &modelNode) bool QmlModelView::hasInstanceForModelNode(const ModelNode &modelNode) { - return nodeInstanceView()->hasInstanceForNode(modelNode); + return nodeInstanceView() && nodeInstanceView()->hasInstanceForNode(modelNode); } void QmlModelView::modelAttached(Model *model) From 5251643c850f46308019cfae8e34263c7a342707 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 5 Apr 2011 16:43:38 +0200 Subject: [PATCH 03/24] QmlDesigner.model: bugfix for TabBar A defaultProperty is always a list property. Reviewed-by: Marco Bubke --- .../qmldesigner/designercore/model/nodeabstractproperty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp index c7e7f6aabd3..3812dd079cb 100644 --- a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp +++ b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp @@ -67,7 +67,7 @@ void NodeAbstractProperty::reparentHere(const ModelNode &modelNode) if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty()) reparentHere(modelNode, isNodeListProperty()); else - reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name())); //we could use the metasystem instead? + reparentHere(modelNode, parentModelNode().metaInfo().propertyIsListProperty(name()) || isDefaultProperty()); //we could use the metasystem instead? } void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNodeList) From af73d108c1ca6d76d3e7257b1f0400e890b277a0 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 5 Apr 2011 17:11:00 +0200 Subject: [PATCH 04/24] mimetypes: remove grid lines from table view More consistent. Reviewed-by: Leandro Melo --- src/plugins/coreplugin/mimetypesettingspage.ui | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/mimetypesettingspage.ui b/src/plugins/coreplugin/mimetypesettingspage.ui index 66643e4c854..29dab60049f 100644 --- a/src/plugins/coreplugin/mimetypesettingspage.ui +++ b/src/plugins/coreplugin/mimetypesettingspage.ui @@ -21,7 +21,14 @@ - + + + false + + + Qt::NoPen + + @@ -85,6 +92,12 @@ 100 + + false + + + Qt::NoPen + Magic Header From cfdbd3ca9a97f8ebb764c0403a1c25c0e46250ca Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 5 Apr 2011 15:11:49 +0200 Subject: [PATCH 05/24] QmlDesigner: Remove qDebug Reviewed-by: Thomas Hartmann --- .../qmldesigner/components/formeditor/formeditorscene.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp index 66a12630e39..a2a3095d394 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp @@ -83,9 +83,7 @@ FormEditorScene::~FormEditorScene() void FormEditorScene::setupScene() { m_formLayerItem = new LayerItem(this); - qDebug() << "formLayerItem" << m_formLayerItem.data(); m_manipulatorLayerItem = new LayerItem(this); - qDebug() << "manipulatorLayerItem" << m_manipulatorLayerItem.data(); m_manipulatorLayerItem->setZValue(1.0); m_formLayerItem->setZValue(0.0); m_formLayerItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); From 7b25f438c67c7cf395ccd2cd846e5d413f6d9222 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 6 Apr 2011 09:19:46 +0200 Subject: [PATCH 06/24] Fixed import of "." in a library with a hack. Task-number: QTCREATORBUG-4198 Reviewed-by: Kai Koehne --- src/libs/qmljs/qmljslink.cpp | 28 +++++++++++++++++++++++++--- src/libs/qmljs/qmljslink.h | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 68586351238..a079b517531 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -183,6 +183,28 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc) // explicit imports, whether directories, files or libraries foreach (const ImportInfo &info, doc->bind()->imports()) { ObjectValue *import = d->importCache.value(ImportCacheKey(info)); + + //### Hack: if this document is in a library, and if there is an qmldir file in the same directory, and if the prefix is an import-path, the import means to import everything in this library. + if (info.ast() && info.ast()->fileName && info.ast()->fileName->asString() == QLatin1String(".")) { + const QString importInfoName(info.name()); + if (QFileInfo(QDir(importInfoName), QLatin1String("qmldir")).exists()) { + foreach (const QString &importPath, d->importPaths) { + if (importInfoName.startsWith(importPath)) { + // Got it. + + const QString cleanPath = QFileInfo(importInfoName).canonicalFilePath(); + const QString forcedPackageName = cleanPath.mid(importPath.size() + 1).replace('/', '.').replace('\\', '.'); + import = importNonFile(doc, info, forcedPackageName); + if (import) + d->importCache.insert(ImportCacheKey(info), import); + + break; + } + } + } + } + //### End of hack. + if (!import) { switch (info.type()) { case ImportInfo::FileImport: @@ -245,12 +267,12 @@ ObjectValue *Link::importFileOrDirectory(Document::Ptr doc, const ImportInfo &im import Qt 4.6 as Xxx (import com.nokia.qt is the same as the ones above) */ -ObjectValue *Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo) +ObjectValue *Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo, const QString &forcedPackageName) { Q_D(Link); ObjectValue *import = new ObjectValue(engine()); - const QString packageName = Bind::toString(importInfo.ast()->importUri, '.'); + const QString packageName = forcedPackageName.isEmpty() ? Bind::toString(importInfo.ast()->importUri, '.') : forcedPackageName; const ComponentVersion version = importInfo.version(); bool importFound = false; @@ -277,7 +299,7 @@ ObjectValue *Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo } } - if (!importFound) { + if (!importFound && importInfo.ast()) { error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(), importInfo.ast()->lastSourceLocation()), tr("package not found")); diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h index a81a8faa003..41c46266aed 100644 --- a/src/libs/qmljs/qmljslink.h +++ b/src/libs/qmljs/qmljslink.h @@ -71,7 +71,7 @@ private: void populateImportedTypes(Interpreter::TypeEnvironment *typeEnv, Document::Ptr doc); Interpreter::ObjectValue *importFileOrDirectory(Document::Ptr doc, const Interpreter::ImportInfo &importInfo); - Interpreter::ObjectValue *importNonFile(Document::Ptr doc, const Interpreter::ImportInfo &importInfo); + Interpreter::ObjectValue *importNonFile(Document::Ptr doc, const Interpreter::ImportInfo &importInfo, const QString &forcedPackageName = QString::null); void importObject(Bind *bind, const QString &name, Interpreter::ObjectValue *object, NameId *targetNamespace); bool importLibrary(Document::Ptr doc, From 67df1185f7a196b4a632afe78c978c5ece92a84a Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 5 Apr 2011 11:53:44 +0200 Subject: [PATCH 07/24] Doc: fix formatting --- doc/qtcreator-faq.qdoc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/qtcreator-faq.qdoc b/doc/qtcreator-faq.qdoc index a3da396138a..ea6a8752572 100644 --- a/doc/qtcreator-faq.qdoc +++ b/doc/qtcreator-faq.qdoc @@ -174,17 +174,13 @@ Ubuntu or Debian?} \code - @ sudo apt-get install libglib2.0-dev libSM-dev libxrender-dev libfontconfig1-dev libxext-dev - @ \endcode If you use QtOpenGL, you also need: \code - @ sudo apt-get install libgl-dev libglu-dev - @ \endcode \section1 Platform Releated Questions From da0708fd61440478d060c436c43f6bcdaecc670f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 5 Apr 2011 11:54:11 +0200 Subject: [PATCH 08/24] Doc: remove obsolete info --- doc/qtcreator.qdoc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4aaa8ff6125..4f1f0f7ee0a 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -8826,13 +8826,6 @@ .qml file in your project. All the other files in the project are automatically added to the application project. - For example, you can open and run the - \l {http://doc.qt.nokia.com/4.7/qdeclarativeexamples.html} {QML examples and demos} - to learn how to use various aspects of QML. To run the examples in the QML Viewer - on the desktop, open them in the \gui Welcome mode. To view the examples on - mobile devices, use the \gui {Qt Quick Application} wizard to convert them into - Qt Quick Applications. - To import QML applications: \list 1 From 4c9696f9f37d1ac79c3a59aea71bc0fc72ed18bf Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 5 Apr 2011 11:54:34 +0200 Subject: [PATCH 09/24] Doc: remove obsolete note --- doc/qtcreator.qdoc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4f1f0f7ee0a..c13e01fbc00 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -5212,12 +5212,6 @@ (using the Certified Signed path or the manufacturer-specific channel). For more information, see \l{Deploying Applications to Symbian Devices}. - \note At the time of writing this document, the distribution of Qt 4.7.x based - applications is supported by neither Ovi Store nor Smart Installer. - For up-to-date information about the packages available for distribution, see the - \l{http://wiki.forum.nokia.com/index.php/Nokia_Smart_Installer_for_Symbian}{Nokia Smart Installer for Symbian} - wiki. - To use the publishing wizard: \list 1 From 356cd9a2a5c7676f822f6087395604f2fd569760 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 5 Apr 2011 16:53:42 +0200 Subject: [PATCH 10/24] Doc: differences in displaying application output Reviewed-by: Friedemann Kleint --- doc/qtcreator-faq.qdoc | 48 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/doc/qtcreator-faq.qdoc b/doc/qtcreator-faq.qdoc index ea6a8752572..543444b8be6 100644 --- a/doc/qtcreator-faq.qdoc +++ b/doc/qtcreator-faq.qdoc @@ -185,11 +185,51 @@ \section1 Platform Releated Questions - \bold {Can I develop Qt for Symbian applications with Qt Creator?} + \bold {Where is application output shown in Qt Creator?} - Qt Creator comes with support for developing Qt applications that target - the Symbian platform. For more information, see - \l{Creating a Mobile Application with Qt SDK}. + \bold {On Unix (Linux and Mac OS):} \c qDebug() and related functions use + the standard output and error output. When you run or debug the + application, you can view the output in the \gui{Application Output} pane. + + For console applications that require input, select \gui {Projects > Run + Settings > Run in terminal}. + + \bold {On Windows:} Output is displayed differently for \e{console + applications} and \e{GUI applications}. + + The setting \c {CONFIG += console} in the .pro file specifies that the + application is built as a console application using some other runtime. + When you run a console application, you can view the output in the console + window of the calling application. If the + calling application is a GUI application (for example, a release-built + version of Qt Creator), a new console window is opened. For this + type of application, \c qDebug() and related functions use standard output + and error output. + + We recommend that you select \gui {Projects > Run Settings > Run in + terminal} for console applications. + + For GUI applications, \c qDebug() and related functions use the Windows API + function \c OutputDebugString(). The output is displayed in the + \gui{Application Output} pane. However, only one output pane tab may be + open at a time or the output is not displayed correctly. You can use an + external debug output viewer, such as the + \l{http://technet.microsoft.com/en-us/sysinternals/bb896647}{DebugView for Windows} + to display output from GUI applications. + + \bold {On Symbian OS}: \c qDebug() and related functions use the native + \c RDebug::Print functionality. + + When you use the Symbian emulator on Windows, the output is redirected to + standard debug output. To view it, you can use a Windows debug output + viewer, such as the DebugView for Windows. + + On devices, the \c RDebug output is intercepted by \e CODA or \e {App TRK} + and then propagated to Qt Creator, which displays it in the + \gui {Application Output} pane. + + Symbian OS provides no support for differentiating between standard output + and error output. \section1 Questions about New Features From 956435f9e570d5dcf9e4ea8cc0d368bf7f0517ee Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 6 Apr 2011 10:54:38 +0200 Subject: [PATCH 11/24] Doc: differences between integrated and stand-alone Qt Designer Task-number: QTCREATORBUG-3592 Reviewed-by: Friedemann Kleint --- doc/qtcreator.qdoc | 98 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index c13e01fbc00..6952d03cf80 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -1024,17 +1024,48 @@ \title Developing Widget Based Applications - Widgets and forms created with \QD are integrated seamlessly with programmed code, - using the Qt signals and slots mechanism, that lets you easily assign behavior to + Widgets and forms created with \QD are integrated seamlessly with + programmed code by using the Qt signals and slots mechanism that allows you + to easily assign behavior to graphical elements. All properties set in \QD can be changed dynamically within the code. - Furthermore, features like widget promotion and custom plugins allow you to use your - own widgets with \QD. + Furthermore, features such as widget promotion and custom plugins allow you to use your + own widgets with \QD. For more information, see + \l{Adding Qt Designer Plugins}. - Qt Creator automatically opens all .ui files in \QD. + Qt Creator automatically opens all .ui files in the integrated \QD, in + \gui Design mode. \image qtcreator-formedit.png + For more information about \QD, see the + \l{http://doc.qt.nokia.com/4.7/designer-manual.html}{Qt Designer Manual}. + + Generally, the integrated \QD contains the same functions as the standalone + \QD. The following sections describe the differences. + + \section1 Code Editor Integration + + To switch between forms (\gui Design mode) and code (\gui Edit mode), + press \key Shift+F4. + + You can use Qt Creator to create stub implementations of slot functions. + In the \gui Design mode, right-click a widget to open a context menu, and + then select \gui {Go to Slot...}. Select a signal in the list to go to an + existing slot function or to create a new slot function. + + \section1 Managing Image Resources + + In standalone \QD, image resources are created using the built-in + \gui {Resource Editor}. In Qt Creator, .ui files are usually part of a + project, which may contain several resource files (.qrc). They are created + and maintained by using the Qt Creator Resource Editor. The \QD + \gui {Resource Editor} is de-activated and the image resources are + displayed in the \QD \gui {Resource Browser}. + + \section1 Specifying Settings for Qt Designer + To change the layout of \QD user interface elements: + \list 1 \o Select \gui Tools > \gui{Form Editor} > \gui Views > \gui Locked. @@ -1044,29 +1075,50 @@ position. \endlist - To change \QD properties, select \gui Tools > \gui Options... > - \gui Designer. - \list - \o Set the class properties and code generation preferences in \gui - {Class Generation}. - \o Set an additional folder for saving templates in \gui{Template - Paths}. - \o Set the grid settings and preview preferences in \gui Forms. To - preview your form with skins, enable \gui{Print/Preview - Configuration} and select your skin. Otherwise default preview - settings are used. + To specify settings for \QD: + + \list + + \o Select \gui Tools > \gui Options... > \gui Designer. + + \o Specify settins for generating classes and code in \gui {Class + Generation}. + + \o Specify embedded device profiles, that determine style, font, and + screen resolution, for example, in \gui{Embedded Design}. + + \o Specify settings for the grid and previewing forms in \gui Forms. + + \o Specify an additional folder for saving templates in \gui{Template + Paths}. - To preview the settings, select \gui Tools > \gui{Form Editor} > - \gui Preview, or press \key Alt+Shift+R. - \o To specify embedded device profiles, such as style, font, and screen - resolution, select \gui{Embedded Design}. \endlist - To switch between forms and code, use \key Shift+F4. + To preview the settings, select \gui Tools > \gui{Form Editor} > + \gui Preview, or press \key Alt+Shift+R. - For more information on \QD, see - \l{http://doc.qt.nokia.com/4.7/designer-manual.html}{Qt Designer Manual}. + \section1 Previewing Forms Using Device Skins + A \e {device skin} is a set of configuration files that describe a mobile + device. It includes a border image that surrounds the form and depicts a + mobile device with its buttons. + + To preview your form using device skins: + + \list 1 + + \o Select \gui Tools > \gui Options... > \gui Designer. + + \o Select the \gui{Print/Preview Configuration} check box. + + \o In the \gui {Device skin} field, select a device skin. + + \o When the form is open in \gui Design mode, press \key Alt+Shift+R. + + \o To end the preview, right-click the skin and select \gui Close in + the context menu. + + \endlist */ From ac2af19ee09db276a3a4771c9cf1f5c27bfb7155 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 6 Apr 2011 12:18:45 +0200 Subject: [PATCH 12/24] QMakeStep: Fix qmljsdebugger warning issues Debugging requires 4.7.1 minimum. Also update the label if the user switches Qt versions. Reviewed-by: dt --- src/plugins/qt4projectmanager/qmakestep.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index 8ad8afdc92d..e90c9790e40 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -336,7 +336,7 @@ bool QMakeStep::isQmlDebuggingLibrarySupported(QString *reason) const return false; } - if (qt4BuildConfiguration()->qtVersion()->qtVersion() < QtVersionNumber(4, 7 ,0)) { + if (qt4BuildConfiguration()->qtVersion()->qtVersion() < QtVersionNumber(4, 7, 1)) { if (reason) *reason = tr("Requires Qt 4.7.1 or newer."); return false; @@ -449,6 +449,7 @@ void QMakeStepConfigWidget::qtVersionChanged() { updateSummaryLabel(); updateEffectiveQMakeCall(); + updateQmlDebuggingWarningsLabel(); } void QMakeStepConfigWidget::qmakeBuildConfigChanged() From b7c3e821c9a59fde2b283d58e433603d0384dd6a Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 6 Apr 2011 12:35:56 +0200 Subject: [PATCH 13/24] QuickDesigner: Jump to right column for QML syntax errors column count for errors start with 1. Task-number: QTCREATORBUG-4347 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designmodewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 88d17cd2772..9c81adcf6bd 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -155,7 +155,7 @@ QList ItemLibrarySideBarItem::createToolBarWidgets() void DocumentWarningWidget::goToError() { - m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column()); + m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column() - 1); Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT); } From cad1c094f59b55780cd92e6f0d9867edaf1117f1 Mon Sep 17 00:00:00 2001 From: Pawel Polanski Date: Wed, 6 Apr 2011 13:20:43 +0200 Subject: [PATCH 14/24] CODA: CODA responds to the Device Removed event --- src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp index c3d332a9a4a..931a0d41c87 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp @@ -322,11 +322,13 @@ void S60DeployStep::stop() void S60DeployStep::setupConnections() { - if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) { + if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection + || m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(SymbianUtils::SymbianDevice)), this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice))); - connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); + if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) { + connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(connectFailed(QString))); connect(m_launcher, SIGNAL(copyingStarted(QString)), this, SLOT(printCopyingNotice(QString))); connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(createFileFailed(QString,QString))); From dc25adbe67383c0d0f23bfcc9b0320440658349b Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Wed, 6 Apr 2011 11:47:48 +0200 Subject: [PATCH 15/24] Fix duplicate mime types in the user file Also avoid writing the file on every apply and do it only when the dialog is finished. Reset can still be improved to take effect immediately. Reviewed-by: con --- src/plugins/coreplugin/mimedatabase.cpp | 10 +++- src/plugins/coreplugin/mimetypesettings.cpp | 54 +++++++++++++++------ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/plugins/coreplugin/mimedatabase.cpp b/src/plugins/coreplugin/mimedatabase.cpp index 50c9548b8af..abf7229d911 100644 --- a/src/plugins/coreplugin/mimedatabase.cpp +++ b/src/plugins/coreplugin/mimedatabase.cpp @@ -1554,9 +1554,15 @@ QList MimeDatabasePrivate::readUserModifiedMimeTypes() void MimeDatabasePrivate::writeUserModifiedMimeTypes(const QList &mimeTypes) { - // Keep mime types modified which are already on file. + // Keep mime types modified which are already on file, unless they are part of the current set. + QSet currentMimeTypes; + foreach (const MimeType &mimeType, mimeTypes) + currentMimeTypes.insert(mimeType.type()); + const QList &inFileMimeTypes = readUserModifiedMimeTypes(); QList allModifiedMimeTypes = mimeTypes; - allModifiedMimeTypes.append(readUserModifiedMimeTypes()); + foreach (const MimeType &mimeType, inFileMimeTypes) + if (!currentMimeTypes.contains(mimeType.type())) + allModifiedMimeTypes.append(mimeType); if (QFile::exists(kModifiedMimeTypesPath) || QDir().mkpath(kModifiedMimeTypesPath)) { QFile file(kModifiedMimeTypesPath + kModifiedMimeTypesFile); diff --git a/src/plugins/coreplugin/mimetypesettings.cpp b/src/plugins/coreplugin/mimetypesettings.cpp index ebede48aa12..45bb4da6b0e 100644 --- a/src/plugins/coreplugin/mimetypesettings.cpp +++ b/src/plugins/coreplugin/mimetypesettings.cpp @@ -204,7 +204,7 @@ void MimeTypeSettingsModel::updateKnownPatterns(const QStringList &oldPatterns, } } -// MimeTypeSettingsPagePrivate +// MimeTypeSettingsPrivate class MimeTypeSettingsPrivate : public QObject { Q_OBJECT @@ -231,6 +231,7 @@ public: void editMagicHeaderRowData(const int row, const MagicData &data); void updateMimeDatabase(); + void resetState(); public slots: void syncData(const QModelIndex ¤t, const QModelIndex &previous); @@ -249,6 +250,7 @@ public: int m_mimeForPatternSync; int m_mimeForMagicSync; bool m_reset; + bool m_persist; QList m_modifiedMimeTypes; Ui::MimeTypeSettingsPage m_ui; }; @@ -261,6 +263,7 @@ MimeTypeSettingsPrivate::MimeTypeSettingsPrivate() , m_mimeForPatternSync(-1) , m_mimeForMagicSync(-1) , m_reset(false) + , m_persist(false) {} MimeTypeSettingsPrivate::~MimeTypeSettingsPrivate() @@ -507,22 +510,32 @@ void MimeTypeSettingsPrivate::editMagicHeader() void MimeTypeSettingsPrivate::updateMimeDatabase() { - MimeDatabase *db = ICore::instance()->mimeDatabase(); + if (m_modifiedMimeTypes.isEmpty()) + return; + // For this case it is a better approach to simply use a list and to remove duplicates // afterwards than to keep a more complex data structure like a hash table. qSort(m_modifiedMimeTypes.begin(), m_modifiedMimeTypes.end()); m_modifiedMimeTypes.erase(std::unique(m_modifiedMimeTypes.begin(), m_modifiedMimeTypes.end()), m_modifiedMimeTypes.end()); - if (!m_modifiedMimeTypes.isEmpty()) { - QList allModified; - foreach (int index, m_modifiedMimeTypes) { - const MimeType &mimeType = m_model->m_mimeTypes.at(index); - db->setGlobPatterns(mimeType.type(), mimeType.globPatterns()); - db->setMagicMatchers(mimeType.type(), mimeType.magicMatchers()); - allModified.append(mimeType); - } - db->writeUserModifiedMimeTypes(allModified); + + MimeDatabase *db = ICore::instance()->mimeDatabase(); + QList allModified; + foreach (int index, m_modifiedMimeTypes) { + const MimeType &mimeType = m_model->m_mimeTypes.at(index); + db->setGlobPatterns(mimeType.type(), mimeType.globPatterns()); + db->setMagicMatchers(mimeType.type(), mimeType.magicMatchers()); + allModified.append(mimeType); } + db->writeUserModifiedMimeTypes(allModified); +} + +void MimeTypeSettingsPrivate::resetState() +{ + clearSyncData(); + m_modifiedMimeTypes.clear(); + m_reset = false; + m_persist = false; } void MimeTypeSettingsPrivate::resetMimeTypes() @@ -581,9 +594,7 @@ QWidget *MimeTypeSettings::createPage(QWidget *parent) void MimeTypeSettings::apply() { - if (m_d->m_reset) { - ICore::instance()->mimeDatabase()->clearUserModifiedMimeTypes(); - } else if (!m_d->m_modifiedMimeTypes.isEmpty()) { + if (!m_d->m_modifiedMimeTypes.isEmpty()) { const QModelIndex &modelIndex = m_d->m_ui.mimeTypesTableView->selectionModel()->currentIndex(); if (modelIndex.isValid()) { @@ -592,12 +603,23 @@ void MimeTypeSettings::apply() if (m_d->m_mimeForMagicSync == modelIndex.row()) m_d->syncMimeMagic(); } - m_d->updateMimeDatabase(); + m_d->clearSyncData(); } + + if (!m_d->m_persist) + m_d->m_persist = true; } void MimeTypeSettings::finish() -{} +{ + if (m_d->m_persist) { + if (m_d->m_reset) + ICore::instance()->mimeDatabase()->clearUserModifiedMimeTypes(); + else + m_d->updateMimeDatabase(); + } + m_d->resetState(); +} } // Internal } // Core From d88a821c82b57e2a04afac00995814817ff61a51 Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Wed, 6 Apr 2011 16:10:51 +0200 Subject: [PATCH 16/24] Remove grid from snippets table view Reviewed-by: con --- src/plugins/texteditor/snippets/snippetssettingspage.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.ui b/src/plugins/texteditor/snippets/snippetssettingspage.ui index e95fa7afc7c..320810dbc9b 100644 --- a/src/plugins/texteditor/snippets/snippetssettingspage.ui +++ b/src/plugins/texteditor/snippets/snippetssettingspage.ui @@ -50,6 +50,12 @@ QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + false + + + Qt::NoPen + From 46bca1eeff5c33cefb37b37c0e9870e11abb684c Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Wed, 6 Apr 2011 16:37:02 +0200 Subject: [PATCH 17/24] Remove grid from highlight definitions table view Reviewed-by: con --- .../generichighlighter/managedefinitionsdialog.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui index d6db77b0335..351d38c2752 100644 --- a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui +++ b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui @@ -34,6 +34,12 @@ QAbstractItemView::SelectRows + + false + + + Qt::NoPen + 3 From 367a28d5a171ddd1802d20983172f7e659831d75 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 6 Apr 2011 17:34:08 +0200 Subject: [PATCH 18/24] debugger: display inability to "finish" in status line Reviewed-by: Friedemann Kleint Task-number: QTCREATORBUG-4382 --- src/plugins/debugger/gdb/gdbengine.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1b1a9fb8a37..33531acceef 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1673,8 +1673,7 @@ void GdbEngine::handleExecuteContinue(const GdbResponse &response) return; } QByteArray msg = response.data.findChild("msg").data(); - if (msg.startsWith("Cannot find bounds of current function") - || msg.startsWith("\"finish\" not meaningful in the outermost frame")) { + if (msg.startsWith("Cannot find bounds of current function")) { notifyInferiorRunFailed(); if (isDying()) return; @@ -1683,9 +1682,14 @@ void GdbEngine::handleExecuteContinue(const GdbResponse &response) QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); showStatusMessage(tr("Stopped."), 5000); reloadStack(true); - //showStatusMessage(tr("No debug information available. " - // "Leaving function...")); - //executeStepOut(); + } else if (msg.startsWith("\"finish\" not meaningful in the outermost frame")) { + notifyInferiorRunFailed(); + if (isDying()) + return; + QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); + // FIXME: Fix translation in master. + showStatusMessage(QString::fromLocal8Bit(msg), 5000); + gotoLocation(stackHandler()->currentFrame()); } else { showExecutionError(QString::fromLocal8Bit(msg)); notifyInferiorIll(); From 63d5dbd9ac9cb6534ad85e96a78b1b80bd10b1ab Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Apr 2011 17:27:39 +0200 Subject: [PATCH 19/24] support QT_INSTALL_IMPORTS in testreader --- tests/manual/proparser/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/manual/proparser/main.cpp b/tests/manual/proparser/main.cpp index 9afe6f52a94..6f98cc8c83d 100644 --- a/tests/manual/proparser/main.cpp +++ b/tests/manual/proparser/main.cpp @@ -169,6 +169,7 @@ int main(int argc, char **argv) } props[] = { { "QT_INSTALL_DATA", QLibraryInfo::DataPath }, { "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath }, + { "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath }, { "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath }, { "QT_INSTALL_DEMOS", QLibraryInfo::DemosPath }, { "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath }, From 0cf7dbd816e56d40a70c58abe8ecd9ebca5e6747 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 4 Apr 2011 18:17:08 +0200 Subject: [PATCH 20/24] simplify copy c'tor --- src/shared/proparser/profileparser.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/shared/proparser/profileparser.h b/src/shared/proparser/profileparser.h index 304ebff55eb..568896bae2d 100644 --- a/src/shared/proparser/profileparser.h +++ b/src/shared/proparser/profileparser.h @@ -81,9 +81,7 @@ public: private: struct BlockScope { BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {} - BlockScope(BlockScope &other) : - start(other.start), braceLevel(other.braceLevel), - special(other.special), inBranch(other.inBranch) {} + BlockScope(const BlockScope &other) { *this = other; } ushort *start; // Where this block started; store length here int braceLevel; // Nesting of braces in scope bool special; // Single-line conditionals inside loops, etc. cannot have else branches From 5433b43efd448c90c86fd5f233dd57489d7311f3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 4 Apr 2011 20:48:29 +0200 Subject: [PATCH 21/24] const-correctness --- src/shared/proparser/profileparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/proparser/profileparser.cpp b/src/shared/proparser/profileparser.cpp index 9cfcf8bb062..e274cd997bb 100644 --- a/src/shared/proparser/profileparser.cpp +++ b/src/shared/proparser/profileparser.cpp @@ -275,7 +275,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) // Expression precompiler buffer. QString xprBuff; xprBuff.reserve(tokBuff.capacity()); // Excessive, but simple - ushort *buf = (ushort *)xprBuff.constData(); + ushort * const buf = (ushort *)xprBuff.constData(); // Parser state m_blockstack.clear(); From c87eda573c82380a1349ba37b75ac3c7a1968f47 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Apr 2011 11:16:37 +0200 Subject: [PATCH 22/24] remove useless initializations reverts 6f5bf29e. coverity sucks, thankyouverymuch. --- src/shared/proparser/profileparser.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/shared/proparser/profileparser.cpp b/src/shared/proparser/profileparser.cpp index e274cd997bb..cab98cb8e04 100644 --- a/src/shared/proparser/profileparser.cpp +++ b/src/shared/proparser/profileparser.cpp @@ -115,13 +115,7 @@ void ProFileParser::initialize() } ProFileParser::ProFileParser(ProFileCache *cache, ProFileParserHandler *handler) - : m_lineNo(0) - , m_state(StNew) - , m_markLine(0) - , m_canElse(false) - , m_invert(false) - , m_operator(NoOperator) - , m_cache(cache) + : m_cache(cache) , m_handler(handler) { // So that single-threaded apps don't have to call initialize() for now. From d9e5f676efeceff2a947bc9e861545b4e9673c1f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Apr 2011 17:04:03 +0200 Subject: [PATCH 23/24] reshuffle word counting in expressions this makes the value list sizehints more correct: instead of the number of literals and expansions, it's now the number of actual words, and that only if the expression starts with a literal (otherwise the pre-allocation is discarded anyway). the performance impact seems negligible, with qt being a tad slower and creator a tad faster. as a side effect, complaining about excess words in a test expression does not immediately terminate the current line's parsing. --- src/shared/proparser/profileparser.cpp | 180 ++++++++++++------------- src/shared/proparser/profileparser.h | 7 +- 2 files changed, 88 insertions(+), 99 deletions(-) diff --git a/src/shared/proparser/profileparser.cpp b/src/shared/proparser/profileparser.cpp index cab98cb8e04..e7d3fa50009 100644 --- a/src/shared/proparser/profileparser.cpp +++ b/src/shared/proparser/profileparser.cpp @@ -235,7 +235,7 @@ void ProFileParser::finalizeHashStr(ushort *buf, uint len) bool ProFileParser::read(ProFile *pro, const QString &in) { - m_fileName = pro->fileName(); + m_proFile = pro; m_lineNo = 1; // Final precompiled token stream buffer @@ -289,12 +289,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in) Context context = CtxTest; int parens = 0; // Braces in value context int argc = 0; - int litCount = 0; - int expCount = 0; + int wordCount = 0; // Number of words in currently accumulated expression bool inError = false; bool putSpace = false; // Only ever true inside quoted string bool lineMarked = true; // For in-expression markers - ushort needSep = 0; // Complementary to putSpace: separator outside quotes + ushort needSep = TokNewStr; // Complementary to putSpace: separator outside quotes ushort quote = 0; ushort term = 0; @@ -304,42 +303,53 @@ bool ProFileParser::read(ProFile *pro, const QString &in) ushort *oldTokPtr = tokPtr; -#define FLUSH_LHS_LITERAL(setSep) \ +#define FLUSH_LHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ - if (needSep) \ - goto extraChars; \ finalizeHashStr(xprPtr, tlen); \ - if (setSep) \ - needSep = TokNewStr; \ + if (needSep) { \ + wordCount++; \ + needSep = 0; \ + } \ } else { \ ptr -= 4; \ - if (setSep && ptr != buf) \ - needSep = TokNewStr; \ } \ } while (0) -#define FLUSH_RHS_LITERAL(setSep) \ +#define FLUSH_RHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ xprPtr[-2] = TokLiteral | needSep; \ xprPtr[-1] = tlen; \ - if (setSep) \ - needSep = TokNewStr; \ - litCount++; \ + if (needSep) { \ + wordCount++; \ + needSep = 0; \ + } \ } else { \ ptr -= 2; \ - if (setSep && ptr != ((context == CtxValue) ? tokPtr : buf)) \ - needSep = TokNewStr; \ } \ } while (0) -#define FLUSH_LITERAL(setSep) \ +#define FLUSH_LITERAL() \ do { \ if (context == CtxTest) \ - FLUSH_LHS_LITERAL(setSep); \ + FLUSH_LHS_LITERAL(); \ else \ - FLUSH_RHS_LITERAL(setSep); \ + FLUSH_RHS_LITERAL(); \ + } while (0) + +#define FLUSH_VALUE_LIST() \ + do { \ + if (wordCount > 1) { \ + xprPtr = tokPtr; \ + if (*xprPtr == TokLine) \ + xprPtr += 2; \ + tokPtr[-1] = ((*xprPtr & TokMask) == TokLiteral) ? wordCount : 0; \ + } else { \ + tokPtr[-1] = 0; \ + } \ + tokPtr = ptr; \ + putTok(tokPtr, TokValueTerminator); \ } while (0) forever { @@ -415,7 +425,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) // Finally, do the tokenization ushort tok, rtok; int tlen; - newToken: + newWord: do { if (cur == end) goto lineEnd; @@ -429,27 +439,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) putSpace = false; *ptr++ = ' '; } - tlen = ptr - xprPtr; - if (context == CtxTest) { - if (needSep) { - extraChars: - parseError(fL1S("Extra characters after test expression.")); - goto parseErr; - } - if (tlen) - finalizeHashStr(xprPtr, tlen); - else - ptr -= 4; - } else { - if (tlen) { - xprPtr[-2] = TokLiteral | needSep; - xprPtr[-1] = tlen; - needSep = 0; - litCount++; - } else { - ptr -= 2; - } - } + FLUSH_LITERAL(); if (!lineMarked) { lineMarked = true; *ptr++ = TokLine; @@ -493,9 +483,10 @@ bool ProFileParser::read(ProFile *pro, const QString &in) notfunc: if (quote) tok |= TokQuoted; - tok |= needSep; - needSep = 0; - expCount++; + if (needSep) { + tok |= needSep; + wordCount++; + } tlen = ptr - xprPtr; if (rtok == TokVariable) { xprPtr[-4] = tok; @@ -517,8 +508,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) top.terminator = term; top.context = context; top.argc = argc; - top.litCount = litCount; - top.expCount = expCount; + top.wordCount = wordCount; } parens = 0; quote = 0; @@ -526,9 +516,12 @@ bool ProFileParser::read(ProFile *pro, const QString &in) argc = 1; context = CtxArgs; nextToken: + wordCount = 0; + nextWord: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; - goto newToken; + needSep = TokNewStr; + goto newWord; } if (term) { cur++; @@ -548,6 +541,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) joinToken: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; + needSep = 0; goto nextChr; } } else if (c == '\\' && cur != end) { @@ -576,15 +570,15 @@ bool ProFileParser::read(ProFile *pro, const QString &in) quote = c; goto nextChr; } else if (c == ' ' || c == '\t') { - FLUSH_LITERAL(true); - goto nextToken; + FLUSH_LITERAL(); + goto nextWord; } else if (context == CtxArgs) { // Function arg context if (c == '(') { ++parens; } else if (c == ')') { if (--parens < 0) { - FLUSH_RHS_LITERAL(false); + FLUSH_RHS_LITERAL(); *ptr++ = TokFuncTerminator; int theargc = argc; { @@ -594,74 +588,70 @@ bool ProFileParser::read(ProFile *pro, const QString &in) term = top.terminator; context = top.context; argc = top.argc; - litCount = top.litCount; - expCount = top.expCount; + wordCount = top.wordCount; xprStack.resize(xprStack.size() - 1); } if (term == ':') { finalizeCall(tokPtr, buf, ptr, theargc); - needSep = TokNewStr; goto nextItem; } else if (term == '}') { c = (cur == end) ? 0 : *cur++; - needSep = 0; goto checkTerm; } else { Q_ASSERT(!term); - needSep = 0; goto joinToken; } } } else if (!parens && c == ',') { - FLUSH_RHS_LITERAL(false); + FLUSH_RHS_LITERAL(); *ptr++ = TokArgSeparator; argc++; - needSep = 0; goto nextToken; } } else if (context == CtxTest) { // Test or LHS context if (c == '(') { - FLUSH_LHS_LITERAL(false); - if (ptr == buf) { - parseError(fL1S("Opening parenthesis without prior test name.")); + FLUSH_LHS_LITERAL(); + if (wordCount != 1) { + if (wordCount) + parseError(fL1S("Extra characters after test expression.")); + else + parseError(fL1S("Opening parenthesis without prior test name.")); goto parseErr; } *ptr++ = TokTestCall; term = ':'; - needSep = 0; goto funcCall; } else if (c == '!' && ptr == xprPtr) { m_invert ^= true; goto nextChr; } else if (c == ':') { - FLUSH_LHS_LITERAL(false); - finalizeCond(tokPtr, buf, ptr); + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); if (m_state == StNew) parseError(fL1S("And operator without prior condition.")); else m_operator = AndOperator; nextItem: ptr = buf; - needSep = 0; goto nextToken; } else if (c == '|') { - FLUSH_LHS_LITERAL(false); - finalizeCond(tokPtr, buf, ptr); + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); if (m_state != StCond) parseError(fL1S("Or operator without prior condition.")); else m_operator = OrOperator; goto nextItem; } else if (c == '{') { - FLUSH_LHS_LITERAL(false); - finalizeCond(tokPtr, buf, ptr); + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); flushCond(tokPtr); ++m_blockstack.top().braceLevel; goto nextItem; } else if (c == '}') { - FLUSH_LHS_LITERAL(false); - finalizeCond(tokPtr, buf, ptr); + FLUSH_LHS_LITERAL(); + finalizeCond(tokPtr, buf, ptr, wordCount); flushScopes(tokPtr); closeScope: if (!m_blockstack.top().braceLevel) { @@ -693,19 +683,17 @@ bool ProFileParser::read(ProFile *pro, const QString &in) } else if (c == '=') { tok = TokAssign; doOp: - FLUSH_LHS_LITERAL(false); + FLUSH_LHS_LITERAL(); flushCond(tokPtr); putLineMarker(tokPtr); - if (!(tlen = ptr - buf)) { - parseError(fL1S("Assignment operator without prior variable name.")); + if (wordCount != 1) { + parseError(fL1S("Assignment needs exactly one word on the left hand side.")); goto parseErr; } - putBlock(tokPtr, buf, tlen); + putBlock(tokPtr, buf, ptr - buf); putTok(tokPtr, tok); context = CtxValue; ptr = ++tokPtr; - litCount = expCount = 0; - needSep = 0; goto nextToken; } } else { // context == CtxValue @@ -713,10 +701,8 @@ bool ProFileParser::read(ProFile *pro, const QString &in) ++parens; } else if (c == '}') { if (!parens) { - FLUSH_RHS_LITERAL(false); - tokPtr[-1] = litCount ? litCount + expCount : 0; - tokPtr = ptr; - putTok(tokPtr, TokValueTerminator); + FLUSH_RHS_LITERAL(); + FLUSH_VALUE_LIST(); context = CtxTest; goto closeScope; } @@ -739,7 +725,8 @@ bool ProFileParser::read(ProFile *pro, const QString &in) if (quote) { putSpace = true; } else { - FLUSH_LITERAL(true); + FLUSH_LITERAL(); + needSep = TokNewStr; ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; } @@ -747,7 +734,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) c = '\n'; cur = cptr; flushLine: - FLUSH_LITERAL(false); + FLUSH_LITERAL(); if (quote) { parseError(fL1S("Missing closing %1 quote").arg(QChar(quote))); goto parseErr; @@ -756,13 +743,10 @@ bool ProFileParser::read(ProFile *pro, const QString &in) parseError(fL1S("Missing closing parenthesis in function call")); goto parseErr; } - if (context == CtxValue) { - tokPtr[-1] = litCount ? litCount + expCount : 0; - tokPtr = ptr; - putTok(tokPtr, TokValueTerminator); - } else { - finalizeCond(tokPtr, buf, ptr); - } + if (context == CtxValue) + FLUSH_VALUE_LIST(); + else + finalizeCond(tokPtr, buf, ptr, wordCount); if (!c) break; ++m_lineNo; @@ -793,6 +777,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in) *pro->itemsRef() = QString(tokBuff.constData(), tokPtr - (ushort *)tokBuff.constData()); return true; +#undef FLUSH_VALUE_LIST #undef FLUSH_LITERAL #undef FLUSH_LHS_LITERAL #undef FLUSH_RHS_LITERAL @@ -877,10 +862,15 @@ void ProFileParser::finalizeTest(ushort *&tokPtr) m_canElse = true; } -void ProFileParser::finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr) +void ProFileParser::finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount) { - if (ptr == uc) + if (wordCount != 1) { + if (wordCount) { + parseError(fL1S("Extra characters after test expression.")); + m_proFile->setOk(false); + } return; + } // Check for magic tokens if (*uc == TokHashLiteral) { @@ -944,7 +934,7 @@ void ProFileParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int a parseError(fL1S("Unexpected operator in front of for().")); return; } - if (*uce == TokLiteral) { + if (*uce == (TokLiteral|TokNewStr)) { nlen = uce[1]; uc = uce + 2 + nlen; if (*uc == TokFuncTerminator) { @@ -992,7 +982,7 @@ void ProFileParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int a parseError(fL1S("Unexpected operator in front of function definition.")); return; } - if (*uce == TokLiteral) { + if (*uce == (TokLiteral|TokNewStr)) { uint nlen = uce[1]; if (uce[nlen + 2] == TokFuncTerminator) { if (m_operator != NoOperator) { @@ -1019,7 +1009,7 @@ void ProFileParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int a void ProFileParser::parseError(const QString &msg) const { if (m_handler) - m_handler->parseError(m_fileName, m_lineNo, msg); + m_handler->parseError(m_proFile->fileName(), m_lineNo, msg); } QT_END_NAMESPACE diff --git a/src/shared/proparser/profileparser.h b/src/shared/proparser/profileparser.h index 568896bae2d..ce31d2042c1 100644 --- a/src/shared/proparser/profileparser.h +++ b/src/shared/proparser/profileparser.h @@ -98,8 +98,7 @@ private: struct ParseCtx { int parens; // Nesting of non-functional parentheses int argc; // Number of arguments in current function call - int litCount; // Number of literals in current expression - int expCount; // Number of expansions in current expression + int wordCount; // Number of words in current expression Context context; ushort quote; // Enclosing quote type ushort terminator; // '}' if replace function call is braced, ':' if test function @@ -114,7 +113,7 @@ private: void putHashStr(ushort *&pTokPtr, const ushort *buf, uint len); void finalizeHashStr(ushort *buf, uint len); void putLineMarker(ushort *&tokPtr); - void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr); + void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); void finalizeTest(ushort *&tokPtr); void enterScope(ushort *&tokPtr, bool special, ScopeState state); @@ -125,7 +124,7 @@ private: void parseError(const QString &msg) const; // Current location - QString m_fileName; + ProFile *m_proFile; int m_lineNo; QStack m_blockstack; From 17740d2ec3db585b90acb7e244aebadd05a71a3c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 6 Apr 2011 21:26:20 +0200 Subject: [PATCH 24/24] continue parsing line despite errors as far as possible, anyway. and suppress messages after the first one. this avoids that scope nesting gets thrown off and thus spurious followup-errors crop up. as a "side effect", this fixes a crash resulting from us rewinding the token stream but ignoring the block stack on the way. Task-number: QTCREATORBUG-4368 --- src/shared/proparser/profileevaluator.cpp | 9 ++- src/shared/proparser/profileparser.cpp | 76 ++++++++++++++--------- src/shared/proparser/profileparser.h | 2 + 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index a417e01d9de..c4c22c1c973 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -909,7 +909,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock( case TokCondition: if (!m_skipLevel && okey != or_op) { if (curr.size() != 1) { - evalError(fL1S("Conditional must expand to exactly one word.")); + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Conditional must expand to exactly one word.")); okey = false; } else { okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true) ^ invert; @@ -922,7 +923,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock( case TokTestCall: if (!m_skipLevel && okey != or_op) { if (curr.size() != 1) { - evalError(fL1S("Test name must expand to exactly one word.")); + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Test name must expand to exactly one word.")); skipExpression(tokPtr); okey = false; } else { @@ -1067,7 +1069,8 @@ void ProFileEvaluator::Private::visitProVariable( if (curr.size() != 1) { skipExpression(tokPtr); - evalError(fL1S("Left hand side of assignment must expand to exactly one word.")); + if (!m_cumulative || !curr.isEmpty()) + evalError(fL1S("Left hand side of assignment must expand to exactly one word.")); return; } const ProString &varName = map(curr.first()); diff --git a/src/shared/proparser/profileparser.cpp b/src/shared/proparser/profileparser.cpp index e7d3fa50009..08aba5778b8 100644 --- a/src/shared/proparser/profileparser.cpp +++ b/src/shared/proparser/profileparser.cpp @@ -286,11 +286,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in) m_invert = false; m_operator = NoOperator; m_markLine = m_lineNo; + m_inError = false; Context context = CtxTest; int parens = 0; // Braces in value context int argc = 0; int wordCount = 0; // Number of words in currently accumulated expression - bool inError = false; bool putSpace = false; // Only ever true inside quoted string bool lineMarked = true; // For in-expression markers ushort needSep = TokNewStr; // Complementary to putSpace: separator outside quotes @@ -301,8 +301,6 @@ bool ProFileParser::read(ProFile *pro, const QString &in) ptr += 4; ushort *xprPtr = ptr; - ushort *oldTokPtr = tokPtr; - #define FLUSH_LHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ @@ -360,14 +358,9 @@ bool ProFileParser::read(ProFile *pro, const QString &in) c = *cur; if (c == '\n') { ++cur; - if (!inError) - goto flushLine; - ++m_lineNo; - goto freshLine; + goto flushLine; } else if (!c) { - if (!inError) - goto flushLine; - goto flushFile; + goto flushLine; } else if (c != ' ' && c != '\t' && c != '\r') { break; } @@ -421,7 +414,6 @@ bool ProFileParser::read(ProFile *pro, const QString &in) --end; } - if (!inError) { // Finally, do the tokenization ushort tok, rtok; int tlen; @@ -530,12 +522,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in) parseError(fL1S("Missing %1 terminator [found %2]") .arg(QChar(term)) .arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); - parseErr: pro->setOk(false); - xprStack.resize(0); - tokPtr = oldTokPtr; - inError = true; - goto skip; + m_inError = true; + if (c) + cur--; + // Just parse on, as if there was a terminator ... } } joinToken: @@ -617,7 +608,8 @@ bool ProFileParser::read(ProFile *pro, const QString &in) parseError(fL1S("Extra characters after test expression.")); else parseError(fL1S("Opening parenthesis without prior test name.")); - goto parseErr; + pro->setOk(false); + ptr = buf; // Put empty function name } *ptr++ = TokTestCall; term = ':'; @@ -688,9 +680,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in) putLineMarker(tokPtr); if (wordCount != 1) { parseError(fL1S("Assignment needs exactly one word on the left hand side.")); - goto parseErr; + pro->setOk(false); + // Put empty variable name. + } else { + putBlock(tokPtr, buf, ptr - buf); } - putBlock(tokPtr, buf, ptr - buf); putTok(tokPtr, tok); context = CtxValue; ptr = ++tokPtr; @@ -737,23 +731,34 @@ bool ProFileParser::read(ProFile *pro, const QString &in) FLUSH_LITERAL(); if (quote) { parseError(fL1S("Missing closing %1 quote").arg(QChar(quote))); - goto parseErr; - } - if (!xprStack.isEmpty()) { + if (!xprStack.isEmpty()) { + context = xprStack.at(0).context; + xprStack.clear(); + } + goto flErr; + } else if (!xprStack.isEmpty()) { parseError(fL1S("Missing closing parenthesis in function call")); - goto parseErr; - } - if (context == CtxValue) + context = xprStack.at(0).context; + xprStack.clear(); + flErr: + pro->setOk(false); + if (context == CtxValue) { + tokPtr[-1] = 0; // sizehint + putTok(tokPtr, TokValueTerminator); + } else { + bogusTest(tokPtr); + } + } else if (context == CtxValue) { FLUSH_VALUE_LIST(); - else + } else { finalizeCond(tokPtr, buf, ptr, wordCount); + } if (!c) break; ++m_lineNo; goto freshLine; } - } // !inError - skip: + if (!lineCont) { cur = cptr; ++m_lineNo; @@ -765,7 +770,6 @@ bool ProFileParser::read(ProFile *pro, const QString &in) ++m_lineNo; } - flushFile: flushScopes(tokPtr); if (m_blockstack.size() > 1) { parseError(fL1S("Missing closing brace(s).")); @@ -862,12 +866,22 @@ void ProFileParser::finalizeTest(ushort *&tokPtr) m_canElse = true; } +void ProFileParser::bogusTest(ushort *&tokPtr) +{ + flushScopes(tokPtr); + m_operator = NoOperator; + m_invert = false; + m_state = StCond; + m_canElse = true; + m_proFile->setOk(false); +} + void ProFileParser::finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount) { if (wordCount != 1) { if (wordCount) { parseError(fL1S("Extra characters after test expression.")); - m_proFile->setOk(false); + bogusTest(tokPtr); } return; } @@ -1008,7 +1022,7 @@ void ProFileParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int a void ProFileParser::parseError(const QString &msg) const { - if (m_handler) + if (!m_inError && m_handler) m_handler->parseError(m_proFile->fileName(), m_lineNo, msg); } diff --git a/src/shared/proparser/profileparser.h b/src/shared/proparser/profileparser.h index ce31d2042c1..22a104191ce 100644 --- a/src/shared/proparser/profileparser.h +++ b/src/shared/proparser/profileparser.h @@ -116,6 +116,7 @@ private: void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); void finalizeTest(ushort *&tokPtr); + void bogusTest(ushort *&tokPtr); void enterScope(ushort *&tokPtr, bool special, ScopeState state); void leaveScope(ushort *&tokPtr); void flushCond(ushort *&tokPtr); @@ -130,6 +131,7 @@ private: QStack m_blockstack; ScopeState m_state; int m_markLine; // Put marker for this line + bool m_inError; // Current line had a parsing error; suppress followup error messages bool m_canElse; // Conditionals met on previous line, but no scope was opened bool m_invert; // Pending conditional is negated enum { NoOperator, AndOperator, OrOperator } m_operator; // Pending conditional is ORed/ANDed