diff --git a/doc/qtcreator-faq.qdoc b/doc/qtcreator-faq.qdoc index a3da396138a..543444b8be6 100644 --- a/doc/qtcreator-faq.qdoc +++ b/doc/qtcreator-faq.qdoc @@ -174,26 +174,62 @@ 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 - \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 diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4aaa8ff6125..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 */ @@ -5212,12 +5264,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 @@ -8826,13 +8872,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 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, diff --git a/src/plugins/coreplugin/mimedatabase.cpp b/src/plugins/coreplugin/mimedatabase.cpp index 05188cd53d9..8624aabdda8 100644 --- a/src/plugins/coreplugin/mimedatabase.cpp +++ b/src/plugins/coreplugin/mimedatabase.cpp @@ -1705,9 +1705,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 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 diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 6630dc3beb7..dcfc8316eee 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1661,8 +1661,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; @@ -1671,9 +1670,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(); 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); 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))); 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) 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) 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); } 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() 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))); 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 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 + 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 9cfcf8bb062..08aba5778b8 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. @@ -241,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 @@ -275,7 +269,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(); @@ -292,15 +286,14 @@ 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 litCount = 0; - int expCount = 0; - bool inError = false; + int wordCount = 0; // Number of words in currently accumulated expression 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; @@ -308,44 +301,53 @@ bool ProFileParser::read(ProFile *pro, const QString &in) ptr += 4; ushort *xprPtr = ptr; - 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 { @@ -356,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; } @@ -417,11 +414,10 @@ bool ProFileParser::read(ProFile *pro, const QString &in) --end; } - if (!inError) { // Finally, do the tokenization ushort tok, rtok; int tlen; - newToken: + newWord: do { if (cur == end) goto lineEnd; @@ -435,27 +431,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; @@ -499,9 +475,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; @@ -523,8 +500,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; @@ -532,9 +508,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++; @@ -543,17 +522,17 @@ 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: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; + needSep = 0; goto nextChr; } } else if (c == '\\' && cur != end) { @@ -582,15 +561,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; { @@ -600,74 +579,71 @@ 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.")); - goto parseErr; + FLUSH_LHS_LITERAL(); + if (wordCount != 1) { + if (wordCount) + parseError(fL1S("Extra characters after test expression.")); + else + parseError(fL1S("Opening parenthesis without prior test name.")); + pro->setOk(false); + ptr = buf; // Put empty function name } *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) { @@ -699,19 +675,19 @@ 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.")); - goto parseErr; + if (wordCount != 1) { + parseError(fL1S("Assignment needs exactly one word on the left hand side.")); + pro->setOk(false); + // Put empty variable name. + } else { + putBlock(tokPtr, buf, ptr - buf); } - putBlock(tokPtr, buf, tlen); putTok(tokPtr, tok); context = CtxValue; ptr = ++tokPtr; - litCount = expCount = 0; - needSep = 0; goto nextToken; } } else { // context == CtxValue @@ -719,10 +695,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; } @@ -745,7 +719,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; } @@ -753,29 +728,37 @@ 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; - } - 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) { - tokPtr[-1] = litCount ? litCount + expCount : 0; - tokPtr = ptr; - putTok(tokPtr, TokValueTerminator); + 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 { - finalizeCond(tokPtr, buf, ptr); + finalizeCond(tokPtr, buf, ptr, wordCount); } if (!c) break; ++m_lineNo; goto freshLine; } - } // !inError - skip: + if (!lineCont) { cur = cptr; ++m_lineNo; @@ -787,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).")); @@ -799,6 +781,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 @@ -883,10 +866,25 @@ void ProFileParser::finalizeTest(ushort *&tokPtr) m_canElse = true; } -void ProFileParser::finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr) +void ProFileParser::bogusTest(ushort *&tokPtr) { - if (ptr == uc) + 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.")); + bogusTest(tokPtr); + } return; + } // Check for magic tokens if (*uc == TokHashLiteral) { @@ -950,7 +948,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) { @@ -998,7 +996,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) { @@ -1024,8 +1022,8 @@ 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); + if (!m_inError && m_handler) + 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 304ebff55eb..22a104191ce 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 @@ -100,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 @@ -116,9 +113,10 @@ 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 bogusTest(ushort *&tokPtr); void enterScope(ushort *&tokPtr, bool special, ScopeState state); void leaveScope(ushort *&tokPtr); void flushCond(ushort *&tokPtr); @@ -127,12 +125,13 @@ private: void parseError(const QString &msg) const; // Current location - QString m_fileName; + ProFile *m_proFile; int m_lineNo; 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 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 },