diff options
Diffstat (limited to 'src/plugins')
67 files changed, 633 insertions, 340 deletions
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 5b4c95bf31..91e7b478a5 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -422,7 +422,7 @@ AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(ProjectExplorer::Proje return info; } - AndroidDeviceDialog dialog(apiLevel, abi); + AndroidDeviceDialog dialog(apiLevel, abi, Core::ICore::mainWindow()); if (dialog.exec() == QDialog::Accepted) { AndroidDeviceInfo info = dialog.device(); if (dialog.saveDeviceSelection()) { @@ -496,9 +496,9 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::connectedDevices(QString *erro return devices; } -QString AndroidConfigurations::createAVD(int minApiLevel, QString targetArch) const +QString AndroidConfigurations::createAVD(QWidget *parent, int minApiLevel, QString targetArch) const { - QDialog d; + QDialog d(parent); Ui::AddNewAVDDialog avdDialog; avdDialog.setupUi(&d); // NOTE: adb list targets does actually include information on which abis are supported per apilevel diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 09c00d6b11..f69a830aed 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -102,7 +102,7 @@ public: Utils::FileName zipalignPath() const; Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; - QString createAVD(int minApiLevel = 0, QString targetArch = QString()) const; + QString createAVD(QWidget *parent, int minApiLevel = 0, QString targetArch = QString()) const; QString createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize) const; bool removeAVD(const QString &name) const; QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const; diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 53f1b148af..c4a5adc67a 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -388,7 +388,7 @@ bool AndroidDeployQtStep::fromMap(const QVariantMap &map) m_deployAction = AndroidDeployQtAction(map.value(QLatin1String(DeployActionKey), BundleLibrariesDeployment).toInt()); m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString()); - m_signPackage = map.value(SignPackageKey).toBool(); + m_signPackage = false; // don't restore this m_buildTargetSdk = map.value(BuildTargetSdkKey).toString(); m_verbose = map.value(VerboseOutputKey).toBool(); m_inputFile = map.value(InputFile).toString(); diff --git a/src/plugins/android/androiddeployqtwidget.cpp b/src/plugins/android/androiddeployqtwidget.cpp index a1dee1ddba..7cc2e1561c 100644 --- a/src/plugins/android/androiddeployqtwidget.cpp +++ b/src/plugins/android/androiddeployqtwidget.cpp @@ -82,9 +82,11 @@ AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step) } // signing + m_ui->signPackageCheckBox->setChecked(m_step->signPackage()); m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath().toUserOutput()); m_ui->signingDebugWarningIcon->hide(); m_ui->signingDebugWarningLabel->hide(); + signPackageCheckBoxToggled(m_step->signPackage()); m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput()); m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation()); diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp index 66f4c1ea98..6b3fb90bd5 100644 --- a/src/plugins/android/androiddevicedialog.cpp +++ b/src/plugins/android/androiddevicedialog.cpp @@ -446,7 +446,7 @@ void AndroidDeviceDialog::refreshDeviceList() void AndroidDeviceDialog::createAvd() { - QString avd = AndroidConfigurations::instance().createAVD(m_apiLevel, m_abi); + QString avd = AndroidConfigurations::instance().createAVD(this, m_apiLevel, m_abi); if (avd.isEmpty()) return; refreshDeviceList(); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index fc0a01c22a..4ab8228d0b 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -402,14 +402,16 @@ void AndroidSettingsWidget::browseOpenJDKLocation() void AndroidSettingsWidget::addAVD() { - AndroidConfigurations::instance().createAVD(); + AndroidConfigurations::instance().createAVD(this); m_AVDModel.setAvdList(AndroidConfigurations::instance().androidVirtualDevices()); + avdActivated(m_ui->AVDTableView->currentIndex()); } void AndroidSettingsWidget::removeAVD() { AndroidConfigurations::instance().removeAVD(m_AVDModel.avdName(m_ui->AVDTableView->currentIndex())); m_AVDModel.setAvdList(AndroidConfigurations::instance().androidVirtualDevices()); + avdActivated(m_ui->AVDTableView->currentIndex()); } void AndroidSettingsWidget::startAVD() diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp index 84def92065..be51fb1c77 100644 --- a/src/plugins/android/createandroidmanifestwizard.cpp +++ b/src/plugins/android/createandroidmanifestwizard.cpp @@ -76,6 +76,7 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const foreach (QmakeProFileNode *node, nodes) m_comboBox->addItem(node->displayName(), QVariant::fromValue(static_cast<void *>(node))); // TODO something more? + nodeSelected(0); connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(nodeSelected(int))); diff --git a/src/plugins/baremetal/baremetalruncontrolfactory.cpp b/src/plugins/baremetal/baremetalruncontrolfactory.cpp index 3ba17b73bf..50edf9a152 100644 --- a/src/plugins/baremetal/baremetalruncontrolfactory.cpp +++ b/src/plugins/baremetal/baremetalruncontrolfactory.cpp @@ -89,7 +89,7 @@ DebuggerStartParameters BareMetalRunControlFactory::startParameters(const BareMe params.languages |= CppLanguage; params.processArgs = runConfig->arguments(); params.startMode = AttachToRemoteServer; - params.executable = Utils::HostOsInfo::withExecutableSuffix(runConfig->localExecutableFilePath()); + params.executable = runConfig->localExecutableFilePath(); params.remoteSetupNeeded = false; //FIXME probably start debugserver with that, how? params.displayName = runConfig->displayName(); if (const Project *project = target->project()) { diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index 4c08a10556..a08ec4e96d 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -1551,7 +1551,7 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName QFile::rename(absPath + QLatin1String(".hijack"), absPath); } - if ((!response.error || response.stdOut.contains(QLatin1String("already checked out"))) + if ((!response.error || response.stdErr.contains(QLatin1String("already checked out"))) && !m_settings.disableIndexer) { setStatus(absPath, FileStatus::CheckedOut); } @@ -1683,7 +1683,7 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title, runCleartool(workingDir, args, m_settings.timeOutMS(), ShowStdOutInLogWindow | FullySynchronously); if (coResponse.error) { - if (coResponse.stdOut.contains(QLatin1String("already checked out"))) + if (coResponse.stdErr.contains(QLatin1String("already checked out"))) noCheckout = true; else return false; diff --git a/src/plugins/coreplugin/core.qrc b/src/plugins/coreplugin/core.qrc index d54182e37b..6fd7523c22 100644 --- a/src/plugins/coreplugin/core.qrc +++ b/src/plugins/coreplugin/core.qrc @@ -3,6 +3,7 @@ <file>images/clean_pane_small.png</file> <file>images/clear.png</file> <file>images/closebutton.png</file> + <file>images/compile_error_taskbar.png</file> <file>images/dir.png</file> <file>images/editcopy.png</file> <file>images/editcut.png</file> diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index fb7620213f..253662a78f 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -114,8 +114,6 @@ using namespace Utils; //===================EditorManager===================== -EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0; - EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent) : QWidget(parent), m_mode(mode) { @@ -129,16 +127,17 @@ EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *p EditorManagerPlaceHolder::~EditorManagerPlaceHolder() { - if (m_current == this) { - EditorManager::instance()->setParent(0); - EditorManager::instance()->hide(); + // EditorManager will be deleted in ~MainWindow() + EditorManager *em = EditorManager::instance(); + if (em && em->parent() == this) { + em->hide(); + em->setParent(0); } } void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode) { if (m_mode == mode) { - m_current = this; QWidget *previousFocus = 0; if (EditorManager::instance()->focusWidget() && EditorManager::instance()->focusWidget()->hasFocus()) previousFocus = EditorManager::instance()->focusWidget(); @@ -146,16 +145,9 @@ void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode) EditorManager::instance()->show(); if (previousFocus) previousFocus->setFocus(); - } else if (m_current == this) { - m_current = 0; } } -EditorManagerPlaceHolder* EditorManagerPlaceHolder::current() -{ - return m_current; -} - // ---------------- EditorManager namespace Core { diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 4b58092b41..9e554b4a46 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -79,12 +79,10 @@ class CORE_EXPORT EditorManagerPlaceHolder : public QWidget public: explicit EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent = 0); ~EditorManagerPlaceHolder(); - static EditorManagerPlaceHolder* current(); private slots: void currentModeChanged(Core::IMode *); private: Core::IMode *m_mode; - static EditorManagerPlaceHolder* m_current; }; class CORE_EXPORT EditorManager : public QWidget diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp index 6bba67ba06..4e56cd96b9 100644 --- a/src/plugins/coreplugin/fileiconprovider.cpp +++ b/src/plugins/coreplugin/fileiconprovider.cpp @@ -75,7 +75,7 @@ public: : m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon)) {} - QIcon icon(const QFileInfo &info) const; + QIcon icon(const QFileInfo &info); using QFileIconProvider::icon; void registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix) @@ -113,23 +113,26 @@ QFileIconProvider *iconProvider() return instance(); } -QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo) const +QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo) { if (debug) qDebug() << "FileIconProvider::icon" << fileInfo.absoluteFilePath(); // Check for cached overlay icons by file suffix. - if (!m_cache.isEmpty() && !fileInfo.isDir()) { - const QString suffix = fileInfo.suffix(); - if (!suffix.isEmpty() && m_cache.contains(suffix)) { + bool isDir = fileInfo.isDir(); + QString suffix = !isDir ? fileInfo.suffix() : QString(); + if (!m_cache.isEmpty() && !isDir && !suffix.isEmpty()) { + if (m_cache.contains(suffix)) return m_cache.value(suffix); - } } // Get icon from OS. + QIcon icon; if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost()) - return QFileIconProvider::icon(fileInfo); - - // File icons are unknown on linux systems. - return fileInfo.isDir() ? QFileIconProvider::icon(fileInfo) : m_unknownFileIcon; + icon = QFileIconProvider::icon(fileInfo); + else // File icons are unknown on linux systems. + icon = isDir ? QFileIconProvider::icon(fileInfo) : m_unknownFileIcon; + if (!isDir && !suffix.isEmpty()) + m_cache.insert(suffix, icon); + return icon; } /*! diff --git a/src/plugins/coreplugin/images/compile_error_taskbar.png b/src/plugins/coreplugin/images/compile_error_taskbar.png Binary files differnew file mode 100644 index 0000000000..71dd4ede42 --- /dev/null +++ b/src/plugins/coreplugin/images/compile_error_taskbar.png diff --git a/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp b/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp index 39ad2439de..1f04e55d47 100644 --- a/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp +++ b/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp @@ -122,7 +122,7 @@ void Core::Internal::ProgressManagerPrivate::doSetApplicationLabel(const QString if (text.isEmpty()) { pITask->SetOverlayIcon(winId, NULL, NULL); } else { - QPixmap pix = QPixmap(QLatin1String(":/projectexplorer/images/compile_error.png")); + QPixmap pix = QPixmap(QLatin1String(":/core/images/compile_error_taskbar.png")); QPainter p(&pix); p.setPen(Qt::white); QFont font = p.font(); diff --git a/src/plugins/cppeditor/cppdoxygen_test.cpp b/src/plugins/cppeditor/cppdoxygen_test.cpp index 8feffc6579..ab8a947940 100644 --- a/src/plugins/cppeditor/cppdoxygen_test.cpp +++ b/src/plugins/cppeditor/cppdoxygen_test.cpp @@ -51,6 +51,9 @@ using namespace CPlusPlus; using namespace CppEditor::Internal; namespace { + +typedef QByteArray _; + /** * Encapsulates the whole process of setting up an editor, * pressing ENTER and checking the result. @@ -140,205 +143,149 @@ void TestCase::run(const QByteArray &expected, int undoCount) } } // anonymous namespace -void CppEditorPlugin::test_doxygen_comments_qt_style() +void CppEditorPlugin::test_doxygen_comments_data() { - const QByteArray given = + QTest::addColumn<QByteArray>("given"); + QTest::addColumn<QByteArray>("expected"); + + QTest::newRow("qt_style") << _( "bool preventFolding;\n" "/*!|\n" "int a;\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "/*!\n" " * \\brief a\n" " */\n" "int a;\n" - ; + ); - TestCase data(given); - data.run(expected); -} - -void CppEditorPlugin::test_doxygen_comments_qt_style_continuation() -{ - const QByteArray given = + QTest::newRow("qt_style_continuation") << _( "bool preventFolding;\n" "/*!\n" " * \\brief a|\n" " */\n" "int a;\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "/*!\n" " * \\brief a\n" - " *\n" + " * \n" " */\n" "int a;\n" - ; + ); - TestCase data(given); - data.run(expected); -} - -void CppEditorPlugin::test_doxygen_comments_java_style() -{ - const QByteArray given = + QTest::newRow("java_style") << _( "bool preventFolding;\n" "/**|\n" "int a;\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "/**\n" " * @brief a\n" " */\n" "int a;\n" - ; - - TestCase data(given); - data.run(expected); -} + ); -void CppEditorPlugin::test_doxygen_comments_java_style_continuation() -{ - const QByteArray given = + QTest::newRow("java_style_continuation") << _( "bool preventFolding;\n" "/**\n" " * @brief a|\n" " */\n" "int a;\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "/**\n" " * @brief a\n" - " *\n" + " * \n" " */\n" "int a;\n" - ; - - TestCase data(given); - data.run(expected); -} + ); -void CppEditorPlugin::test_doxygen_comments_cpp_styleA() -{ - const QByteArray given = + QTest::newRow("cpp_styleA") << _( "bool preventFolding;\n" "///|\n" "int a;\n" - ; - - const QByteArray expected = + ) << _( "bool preventFolding;\n" "///\n" "/// \\brief a\n" "///\n" "int a;\n" - ; - TestCase data(given); - data.run(expected); -} + ); -void CppEditorPlugin::test_doxygen_comments_cpp_styleB() -{ - const QByteArray given = + QTest::newRow("cpp_styleB") << _( "bool preventFolding;\n" "//!|\n" "int a;\n" - ; - - const QByteArray expected = + ) << _( "bool preventFolding;\n" "//!\n" "//! \\brief a\n" "//!\n" "int a;\n" - ; - TestCase data(given); - data.run(expected); -} + ); -void CppEditorPlugin::test_doxygen_comments_cpp_styleA_continuation() -{ - const QByteArray given = + QTest::newRow("cpp_styleA_continuation") << _( "bool preventFolding;\n" "///\n" "/// \\brief a|\n" "///\n" "int a;\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "///\n" "/// \\brief a\n" - "///\n" + "/// \n" "///\n" "int a;\n" - ; - - TestCase data(given); - data.run(expected); -} + ); -/// test cpp style doxygen comment when inside a indented scope -void CppEditorPlugin::test_doxygen_comments_cpp_styleA_indented() -{ - const QByteArray given = + /// test cpp style doxygen comment when inside a indented scope + QTest::newRow("cpp_styleA_indented") << _( " bool preventFolding;\n" " ///|\n" " int a;\n" - ; - - const QByteArray expected = + ) << _( " bool preventFolding;\n" " ///\n" " /// \\brief a\n" " ///\n" " int a;\n" - ; - TestCase data(given); - data.run(expected); -} + ); -/// test cpp style doxygen comment continuation when inside a indented scope -void CppEditorPlugin::test_doxygen_comments_cpp_styleA_indented_continuation() -{ - const QByteArray given = + /// test cpp style doxygen comment continuation when inside a indented scope + QTest::newRow("cpp_styleA_indented_continuation") << _( " bool preventFolding;\n" " ///\n" " /// \\brief a|\n" " ///\n" " int a;\n" - ; - const QByteArray expected = + ) << _( " bool preventFolding;\n" " ///\n" " /// \\brief a\n" - " ///\n" + " /// \n" " ///\n" " int a;\n" - ; + ); - TestCase data(given); - data.run(expected); -} - -void CppEditorPlugin::test_doxygen_comments_cpp_styleA_corner_case() -{ - const QByteArray given = + QTest::newRow("cpp_styleA_corner_case") << _( "bool preventFolding;\n" "///\n" "void d(); ///|\n" - ; - const QByteArray expected = + ) << _( "bool preventFolding;\n" "///\n" "void d(); ///\n" "\n" - ; + ); +} +void CppEditorPlugin::test_doxygen_comments() +{ + QFETCH(QByteArray, given); + QFETCH(QByteArray, expected); TestCase data(given); data.run(expected); } diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 331c66946c..63d5bc2e5b 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -430,6 +430,7 @@ bool handleDoxygenCppStyleContinuation(QTextCursor &cursor, const QString commentMarker = text.mid(offset, 3); newLine.append(commentMarker); + newLine.append(QLatin1Char(' ')); cursor.insertText(newLine); e->accept(); @@ -481,12 +482,13 @@ bool handleDoxygenContinuation(QTextCursor &cursor, c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, offset); newLine.append(c.selectedText()); if (text.at(offset) == QLatin1Char('/')) { - newLine.append(QLatin1String(" *")); + newLine.append(QLatin1String(" * ")); } else { int start = offset; while (offset < blockPos && text.at(offset) == QLatin1Char('*')) ++offset; newLine.append(QString(offset - start, QLatin1Char('*'))); + newLine.append(QLatin1Char(' ')); } cursor.insertText(newLine); e->accept(); diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index a05dc7bdd7..0989225538 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -116,16 +116,8 @@ private slots: void test_FollowSymbolUnderCursor_virtualFunctionCall(); void test_FollowSymbolUnderCursor_virtualFunctionCall_multipleDocuments(); - void test_doxygen_comments_qt_style(); - void test_doxygen_comments_qt_style_continuation(); - void test_doxygen_comments_java_style(); - void test_doxygen_comments_java_style_continuation(); - void test_doxygen_comments_cpp_styleA(); - void test_doxygen_comments_cpp_styleB(); - void test_doxygen_comments_cpp_styleA_indented(); - void test_doxygen_comments_cpp_styleA_continuation(); - void test_doxygen_comments_cpp_styleA_indented_continuation(); - void test_doxygen_comments_cpp_styleA_corner_case(); + void test_doxygen_comments_data(); + void test_doxygen_comments(); void test_quickfix_CompleteSwitchCaseStatement_basic1(); void test_quickfix_CompleteSwitchCaseStatement_basic2(); diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp index 15a2429f82..3efde4c154 100644 --- a/src/plugins/cppeditor/cppincludehierarchy.cpp +++ b/src/plugins/cppeditor/cppincludehierarchy.cpp @@ -36,6 +36,7 @@ #include "cppincludehierarchymodel.h" #include "cppincludehierarchytreeview.h" +#include <coreplugin/editormanager/editormanager.h> #include <cplusplus/CppDocument.h> #include <utils/annotateditemdelegate.h> @@ -89,7 +90,8 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() : m_treeView(0), m_model(0), m_delegate(0), - m_includeHierarchyInfoLabel(0) + m_includeHierarchyInfoLabel(0), + m_editor(0) { m_inspectedFile = new CppIncludeLabel(this); m_inspectedFile->setMargin(5); @@ -118,6 +120,9 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() : setLayout(layout); connect(CppEditorPlugin::instance(), SIGNAL(includeHierarchyRequested()), SLOT(perform())); + connect(Core::EditorManager::instance(), SIGNAL(editorsClosed(QList<Core::IEditor *>)), + this, SLOT(editorsClosed(QList<Core::IEditor *>))); + } CppIncludeHierarchyWidget::~CppIncludeHierarchyWidget() @@ -128,15 +133,16 @@ void CppIncludeHierarchyWidget::perform() { showNoIncludeHierarchyLabel(); - CPPEditor *editor = qobject_cast<CPPEditor *>(Core::EditorManager::currentEditor()); - if (!editor) + m_editor = qobject_cast<CPPEditor *>(Core::EditorManager::currentEditor()); + if (!m_editor) return; - CPPEditorWidget *widget = qobject_cast<CPPEditorWidget *>(editor->widget()); + + CPPEditorWidget *widget = qobject_cast<CPPEditorWidget *>(m_editor->widget()); if (!widget) return; m_model->clear(); - m_model->buildHierarchy(widget->editorDocument()->filePath()); + m_model->buildHierarchy(m_editor, widget->editorDocument()->filePath()); if (m_model->isEmpty()) return; @@ -162,6 +168,14 @@ void CppIncludeHierarchyWidget::onItemClicked(const QModelIndex &index) Constants::CPPEDITOR_ID); } +void CppIncludeHierarchyWidget::editorsClosed(QList<Core::IEditor *> editors) +{ + foreach (Core::IEditor *editor, editors) { + if (m_editor == editor) + perform(); + } +} + void CppIncludeHierarchyWidget::showNoIncludeHierarchyLabel() { m_inspectedFile->hide(); diff --git a/src/plugins/cppeditor/cppincludehierarchy.h b/src/plugins/cppeditor/cppincludehierarchy.h index fd8d31cbde..cb7720db5e 100644 --- a/src/plugins/cppeditor/cppincludehierarchy.h +++ b/src/plugins/cppeditor/cppincludehierarchy.h @@ -55,6 +55,7 @@ class FileName; namespace CppEditor { namespace Internal { +class CPPEditor; class CPPEditorWidget; class CppInclude; class CppIncludeLabel; @@ -73,6 +74,7 @@ public slots: private slots: void onItemClicked(const QModelIndex &index); + void editorsClosed(QList<Core::IEditor *> editors); private: void showNoIncludeHierarchyLabel(); @@ -84,6 +86,7 @@ private: Utils::AnnotatedItemDelegate *m_delegate; CppIncludeLabel *m_inspectedFile; QLabel *m_includeHierarchyInfoLabel; + CPPEditor *m_editor; }; // @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the diff --git a/src/plugins/cppeditor/cppincludehierarchy_test.cpp b/src/plugins/cppeditor/cppincludehierarchy_test.cpp index e52273743c..7e641e7494 100644 --- a/src/plugins/cppeditor/cppincludehierarchy_test.cpp +++ b/src/plugins/cppeditor/cppincludehierarchy_test.cpp @@ -30,6 +30,8 @@ #include "cppeditorplugin.h" #include "cppincludehierarchymodel.h" +#include <coreplugin/editormanager/editormanager.h> +#include <cppeditor/cppeditor.h> #include <cpptools/cppmodelmanagerinterface.h> #include <utils/fileutils.h> @@ -47,6 +49,7 @@ class TestCase public: TestCase(const QList<QByteArray> &sourceList) : m_cmm(CppModelManagerInterface::instance()) + , m_editor(0) { QStringList filePaths; const int sourceListSize = sourceList.size(); @@ -82,22 +85,30 @@ public: ~TestCase() { + // Close editor + if (m_editor) + Core::EditorManager::closeEditor(m_editor, false); + m_cmm->GC(); QVERIFY(m_cmm->snapshot().isEmpty()); } - void run(int includesCount, int includedByCount) const + void run(int includesCount, int includedByCount) { const QString fileName = QDir::tempPath() + QLatin1String("/file1.h"); + m_editor = qobject_cast<CPPEditor *>(Core::EditorManager::openEditor(fileName)); + QVERIFY(m_editor); + CppIncludeHierarchyModel model(0); - model.buildHierarchy(fileName); + model.buildHierarchy(m_editor, fileName); QCOMPARE(model.rowCount(model.index(0, 0)), includesCount); QCOMPARE(model.rowCount(model.index(1, 0)), includedByCount); } private: CppModelManagerInterface *m_cmm; + CPPEditor *m_editor; }; } diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp index 7709bed2d5..06fe941cd9 100644 --- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp +++ b/src/plugins/cppeditor/cppincludehierarchymodel.cpp @@ -35,10 +35,12 @@ #include <cplusplus/CppDocument.h> #include <cppeditor/cppeditor.h> #include <cpptools/cppmodelmanagerinterface.h> +#include <cpptools/cpptoolseditorsupport.h> #include <QSet> using namespace CPlusPlus; +using namespace CppTools; namespace CppEditor { namespace Internal { @@ -48,7 +50,7 @@ CppIncludeHierarchyModel::CppIncludeHierarchyModel(QObject *parent) , m_rootItem(new CppIncludeHierarchyItem(QString())) , m_includesItem(new CppIncludeHierarchyItem(tr("Includes"), m_rootItem)) , m_includedByItem(new CppIncludeHierarchyItem(tr("Included by"), m_rootItem)) - + , m_editor(0) { m_rootItem->appendChild(m_includesItem); m_rootItem->appendChild(m_includedByItem); @@ -199,6 +201,15 @@ void CppIncludeHierarchyModel::clear() endResetModel(); } +void CppIncludeHierarchyModel::buildHierarchy(CPPEditor *editor, const QString &filePath) +{ + m_editor = editor; + beginResetModel(); + buildHierarchyIncludes(filePath); + buildHierarchyIncludedBy(filePath); + endResetModel(); +} + bool CppIncludeHierarchyModel::hasChildren(const QModelIndex &parent) const { if (!parent.isValid()) @@ -210,14 +221,6 @@ bool CppIncludeHierarchyModel::hasChildren(const QModelIndex &parent) const return parentItem->hasChildren(); } -void CppIncludeHierarchyModel::buildHierarchy(const QString &filePath) -{ - beginResetModel(); - buildHierarchyIncludes(filePath); - buildHierarchyIncludedBy(filePath); - endResetModel(); -} - bool CppIncludeHierarchyModel::isEmpty() const { return !m_includesItem->hasChildren() && !m_includedByItem->hasChildren(); @@ -233,7 +236,11 @@ void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &file CppIncludeHierarchyItem *parent, QSet<QString> *cyclic, bool recursive) { - const Snapshot &snapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); + if (!m_editor) + return; + + CppModelManagerInterface *cppMM = CppModelManagerInterface::instance(); + const Snapshot &snapshot = cppMM->cppEditorSupport(m_editor)->snapshotUpdater()->snapshot(); Document::Ptr doc = snapshot.document(filePath); if (!doc) return; diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.h b/src/plugins/cppeditor/cppincludehierarchymodel.h index cc9cbef050..afb4c7ceb8 100644 --- a/src/plugins/cppeditor/cppincludehierarchymodel.h +++ b/src/plugins/cppeditor/cppincludehierarchymodel.h @@ -41,9 +41,14 @@ enum ItemRole { } // Anonymous +namespace Core { +class IEditor; +} + namespace CppEditor { namespace Internal { +class CPPEditor; class CppIncludeHierarchyItem; class CppIncludeHierarchyModel : public QAbstractItemModel @@ -63,7 +68,7 @@ public: bool hasChildren(const QModelIndex &parent) const; void clear(); - void buildHierarchy(const QString &filePath); + void buildHierarchy(CPPEditor *editor, const QString &filePath); bool isEmpty() const; private: @@ -77,6 +82,7 @@ private: CppIncludeHierarchyItem *m_rootItem; CppIncludeHierarchyItem *m_includesItem; CppIncludeHierarchyItem *m_includedByItem; + CPPEditor *m_editor; }; } // namespace Internal diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp index 89e787d081..85c304cad6 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.cpp +++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp @@ -169,6 +169,7 @@ CppEditorSupport::~CppEditorSupport() m_highlighter.cancel(); m_futureSemanticInfo.cancel(); + m_documentParser.waitForFinished(); m_highlighter.waitForFinished(); m_futureSemanticInfo.waitForFinished(); } diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 2b46a94b93..f928fd40e3 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -64,6 +64,7 @@ public: attachPID(-1), useTerminal(false), breakOnMain(false), + continueAfterAttach(false), multiProcess(false), languages(AnyLanguage), qmlServerAddress(QLatin1String("127.0.0.1")), @@ -102,6 +103,7 @@ public: qint64 attachPID; bool useTerminal; bool breakOnMain; + bool continueAfterAttach; bool multiProcess; DebuggerLanguages languages; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index ae83e0801f..882dfaac9d 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3603,6 +3603,7 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &) void GdbEngine::reloadFullStack() { PENDING_DEBUG("RELOAD FULL STACK"); + resetLocation(); postCommand("-stack-list-frames", Discardable, CB(handleStackListFrames), QVariant::fromValue<StackCookie>(StackCookie(true, true))); } @@ -4307,10 +4308,8 @@ void GdbEngine::assignValueInDebugger(const WatchData *data, + value.toString().toUtf8().toHex(); postCommand(cmd, Discardable, CB(handleVarAssign)); } else { - postCommand("-var-delete assign"); - postCommand("-var-create assign * " + expression.toLatin1()); - postCommand("-var-assign assign " + - GdbMi::escapeCString(value.toString().toLatin1()), + postCommand("set variable (" + expression.toLatin1() + ")=" + + GdbMi::escapeCString(value.toString().toLatin1()), Discardable, CB(handleVarAssign)); } } diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 7e740f0bd8..c2c7b69141 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -83,7 +83,7 @@ static QByteArray tooltipIName(const QString &exp) /////////////////////////////////////////////////////////////////////// LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters) - : DebuggerEngine(startParameters) + : DebuggerEngine(startParameters), m_continueAtNextSpontaneousStop(false) { m_lastAgentId = 0; m_lastToken = 0; @@ -197,13 +197,19 @@ void LldbEngine::setupInferior() cmd.arg("executable", QFileInfo(sp.executable).absoluteFilePath()); cmd.arg("startMode", sp.startMode); // directly relying on this is brittle wrt. insertions, so check it here cmd.arg("processArgs", sp.processArgs); - cmd.arg("attachPid", ((sp.startMode == AttachCrashedExternal || sp.startMode == AttachExternal) - ? sp.attachPID : 0)); + + QTC_CHECK(!sp.attachPID || (sp.startMode == AttachCrashedExternal + || sp.startMode == AttachExternal)); + cmd.arg("attachPid", sp.attachPID); cmd.arg("sysRoot", sp.sysRoot); cmd.arg("remoteChannel", ((sp.startMode == AttachToRemoteProcess || sp.startMode == AttachToRemoteServer) ? sp.remoteChannel : QString())); cmd.arg("platform", sp.platform); + QTC_CHECK(!sp.continueAfterAttach || (sp.startMode == AttachToRemoteProcess + || sp.startMode == AttachExternal + || sp.startMode == AttachToRemoteServer)); + m_continueAtNextSpontaneousStop = false; runCommand(cmd); updateLocals(); // update display options } @@ -1014,9 +1020,13 @@ void LldbEngine::refreshState(const GdbMi &reportedState) notifyInferiorRunOk(); else if (newState == "inferiorrunfailed") notifyInferiorRunFailed(); - else if (newState == "stopped") + else if (newState == "stopped") { notifyInferiorSpontaneousStop(); - else if (newState == "inferiorstopok") + if (m_continueAtNextSpontaneousStop) { + m_continueAtNextSpontaneousStop = false; + continueInferior(); + } + } else if (newState == "inferiorstopok") notifyInferiorStopOk(); else if (newState == "inferiorstopfailed") notifyInferiorStopFailed(); @@ -1028,9 +1038,11 @@ void LldbEngine::refreshState(const GdbMi &reportedState) notifyEngineRunFailed(); else if (newState == "inferiorsetupok") notifyInferiorSetupOk(); - else if (newState == "enginerunandinferiorrunok") + else if (newState == "enginerunandinferiorrunok") { + if (startParameters().continueAfterAttach) + m_continueAtNextSpontaneousStop = true; notifyEngineRunAndInferiorRunOk(); - else if (newState == "enginerunandinferiorstopok") + } else if (newState == "enginerunandinferiorstopok") notifyEngineRunAndInferiorStopOk(); else if (newState == "inferiorshutdownok") notifyInferiorShutdownOk(); diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 22d05cb293..dc4e174768 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -201,6 +201,7 @@ private: // FIXME: Make generic. int m_lastAgentId; int m_lastToken; + int m_continueAtNextSpontaneousStop; QMap<QPointer<DisassemblerAgent>, int> m_disassemblerAgents; QMap<QPointer<MemoryAgent>, int> m_memoryAgents; QHash<int, QPointer<QObject> > m_memoryAgentTokens; diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp index 4996d34752..63b1e1375e 100644 --- a/src/plugins/debugger/threadshandler.cpp +++ b/src/plugins/debugger/threadshandler.cpp @@ -36,12 +36,11 @@ #include <utils/qtcassert.h> #include <QDebug> -#include <QSortFilterProxyModel> namespace Debugger { namespace Internal { -void mergeThreadData(ThreadData &data, const ThreadData &other) +static void mergeThreadData(ThreadData &data, const ThreadData &other) { if (!other.core.isEmpty()) data.core = other.core; @@ -67,6 +66,40 @@ void mergeThreadData(ThreadData &data, const ThreadData &other) data.lineNumber = other.lineNumber; } +static QVariant threadPart(const ThreadData &thread, int column) +{ + switch (column) { + case ThreadData::IdColumn: + return thread.id.raw(); + case ThreadData::FunctionColumn: + return thread.function; + case ThreadData::FileColumn: + return thread.fileName.isEmpty() ? thread.module : thread.fileName; + case ThreadData::LineColumn: + return thread.lineNumber >= 0 + ? QString::number(thread.lineNumber) : QString(); + case ThreadData::AddressColumn: + return thread.address > 0 + ? QLatin1String("0x") + QString::number(thread.address, 16) + : QString(); + case ThreadData::CoreColumn: + return thread.core; + case ThreadData::StateColumn: + return thread.state; + case ThreadData::TargetIdColumn: + if (thread.targetId.startsWith(QLatin1String("Thread "))) + return thread.targetId.mid(7); + return thread.targetId; + case ThreadData::NameColumn: + return thread.name; + case ThreadData::DetailsColumn: + return thread.details; + case ThreadData::ComboNameColumn: + return QString::fromLatin1("#%1 %2").arg(thread.id.raw()).arg(thread.name); + } + return QVariant(); +} + //////////////////////////////////////////////////////////////////////// // // ThreadsHandler @@ -137,8 +170,6 @@ ThreadsHandler::ThreadsHandler() { m_resetLocationScheduled = false; setObjectName(QLatin1String("ThreadsModel")); - m_proxyModel = new QSortFilterProxyModel(this); - m_proxyModel->setSourceModel(this); } int ThreadsHandler::currentThreadIndex() const @@ -168,35 +199,7 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: - switch (index.column()) { - case ThreadData::IdColumn: - return thread.id.raw(); - case ThreadData::FunctionColumn: - return thread.function; - case ThreadData::FileColumn: - return thread.fileName.isEmpty() ? thread.module : thread.fileName; - case ThreadData::LineColumn: - return thread.lineNumber >= 0 - ? QString::number(thread.lineNumber) : QString(); - case ThreadData::AddressColumn: - return thread.address > 0 - ? QLatin1String("0x") + QString::number(thread.address, 16) - : QString(); - case ThreadData::CoreColumn: - return thread.core; - case ThreadData::StateColumn: - return thread.state; - case ThreadData::TargetIdColumn: - if (thread.targetId.startsWith(QLatin1String("Thread "))) - return thread.targetId.mid(7); - return thread.targetId; - case ThreadData::NameColumn: - return thread.name; - case ThreadData::DetailsColumn: - return thread.details; - case ThreadData::ComboNameColumn: - return QString::fromLatin1("#%1 %2").arg(thread.id.raw()).arg(thread.name); - } + return threadPart(thread, index.column()); case Qt::ToolTipRole: return threadToolTip(thread); case Qt::DecorationRole: @@ -250,6 +253,33 @@ Qt::ItemFlags ThreadsHandler::flags(const QModelIndex &index) const return stopped ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0); } +struct Sorter +{ + Sorter(int column, Qt::SortOrder order) + : m_column(column), m_order(order) + {} + + bool operator()(const ThreadData &t1, const ThreadData &t2) const + { + const QVariant v1 = threadPart(t1, m_column); + const QVariant v2 = threadPart(t2, m_column); + if (v1 == v2) + return false; + // FIXME: Use correct toXXX(); + return (v1.toString() < v2.toString()) ^ (m_order == Qt::DescendingOrder); + } + + int m_column; + Qt::SortOrder m_order; +}; + +void ThreadsHandler::sort(int column, Qt::SortOrder order) +{ + layoutAboutToBeChanged(); + qSort(m_threads.begin(), m_threads.end(), Sorter(column, order)); + layoutChanged(); +} + ThreadId ThreadsHandler::currentThread() const { return m_currentId; @@ -490,7 +520,7 @@ void ThreadsHandler::resetLocation() QAbstractItemModel *ThreadsHandler::model() { - return m_proxyModel; + return this; } } // namespace Internal diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h index 1bf9ef6da9..30f458ee36 100644 --- a/src/plugins/debugger/threadshandler.h +++ b/src/plugins/debugger/threadshandler.h @@ -30,14 +30,10 @@ #ifndef THREADSHANDLER_H #define THREADSHANDLER_H -#include <QAbstractTableModel> -#include <QIcon> - #include "threaddata.h" -QT_BEGIN_NAMESPACE -class QSortFilterProxyModel; -QT_END_NAMESPACE +#include <QAbstractTableModel> +#include <QIcon> //////////////////////////////////////////////////////////////////////// // @@ -92,6 +88,7 @@ private: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &index) const; + void sort(int, Qt::SortOrder); void updateThreadBox(); void threadDataChanged(ThreadId id); @@ -101,7 +98,6 @@ private: const QIcon m_emptyIcon; bool m_resetLocationScheduled; - QSortFilterProxyModel *m_proxyModel; }; } // namespace Internal diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 5c3050f81d..388e60c7eb 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -784,6 +784,12 @@ static const QMap<QString, int> &vimKeyNames() return k; } +bool isControlModifier(const Qt::KeyboardModifiers &mods) +{ + static const int ctrl = HostOsInfo::controlModifier(); + return (mods & ctrl) == ctrl; +} + Range::Range() : beginPos(-1), endPos(-1), rangemode(RangeCharMode) @@ -938,12 +944,12 @@ public: bool is(int c) const { - return m_xkey == c && m_modifiers != HostOsInfo::controlModifier(); + return m_xkey == c && !isControl(); } bool isControl() const { - return m_modifiers == HostOsInfo::controlModifier(); + return isControlModifier(m_modifiers); } bool isControl(int c) const @@ -2215,7 +2221,7 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) } // We are interested in overriding most Ctrl key combinations. - if (mods == HostOsInfo::controlModifier() + if (isControlModifier(mods) && !config(ConfigPassControlKey).toBool() && ((key >= Key_A && key <= Key_Z && key != Key_K) || key == Key_BracketLeft || key == Key_BracketRight)) { diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index c37ff7c12e..1b3d521559 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1443,7 +1443,7 @@ void GitClient::show(const QString &source, const QString &id, GitDiffHandler *handler = new GitDiffHandler(diffEditor, gitBinaryPath(), - workingDirectory, + findRepositoryForDirectory(workingDirectory), processEnvironment(), settings()->intValue(GitSettings::timeoutKey)); handler->show(id); diff --git a/src/plugins/ios/iosdebugsupport.cpp b/src/plugins/ios/iosdebugsupport.cpp index 0d761320b9..32d69447af 100644 --- a/src/plugins/ios/iosdebugsupport.cpp +++ b/src/plugins/ios/iosdebugsupport.cpp @@ -84,6 +84,8 @@ RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfi } params.displayName = runConfig->appName(); params.remoteSetupNeeded = true; + if (!params.breakOnMain) + params.continueAfterAttach = true; Debugger::DebuggerRunConfigurationAspect *aspect = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>(); diff --git a/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp b/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp index bb93d20043..169afe0cac 100644 --- a/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp @@ -249,9 +249,6 @@ void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line, if (!nextLine.startsWith(QLatin1String("QML_IMPORT_PATH ="))) return; proFile << nextLine << endl; - } else if (line.contains(QLatin1String("# HARMATTAN_BOOSTABLE"))) { - QString nextLine = proFileTemplate.readLine(); // eats '# CONFIG += qdeclarative-boostable' - proFile << nextLine << endl; } } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 9ed39b9f63..677d13bd81 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -119,6 +119,9 @@ void FormEditorItem::setHighlightBoundingRect(bool highlight) void FormEditorItem::blurContent(bool blurContent) { + if (!scene()) + return; + if (m_blurContent != blurContent) { m_blurContent = blurContent; update(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 8358c18608..1205aae5ae 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -510,7 +510,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) if ((valid || entry.forceImport()) && (entry.requiredImport().isEmpty() - || model->hasImport(entryToImport(entry), true, false) || entry.forceImport())) { + || model->hasImport(entryToImport(entry), true, true) || entry.forceImport())) { QString itemSectionName = entry.category(); ItemLibrarySectionModel *sectionModel; ItemLibraryItemModel *itemModel; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index ad7edd745c..99e92d88ea 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -367,13 +367,10 @@ void ItemLibraryWidget::startDragAndDrop(int itemLibId) { QMimeData *mimeData = m_itemLibraryModel->getMimeData(itemLibId); QDrag *drag = new QDrag(this); - const QImage image = qvariant_cast<QImage>(mimeData->imageData()); drag->setPixmap(m_itemLibraryModel->getIcon(itemLibId).pixmap(32, 32)); drag->setMimeData(mimeData); - QQuickItem *rootItem = qobject_cast<QQuickItem*>(m_itemsView->rootObject()); - drag->exec(); } diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 8e4334d87c..3d6e903d93 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -99,6 +99,8 @@ public: QList<Import> possibleImports() const; QList<Import> usedImports() const; void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved); + void setPossibleImports(const QList<Import> &possibleImports); + void setUsedImports(const QList<Import> &usedImports); bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); QString pathForImport(const Import &import); diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index 2405ef8412..bf845dcc81 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -75,6 +75,8 @@ static inline QStringList importPaths() { static inline bool checkIfDerivedFromItem(const QString &fileName) { + return true; + QmlJS::Snapshot snapshot; @@ -101,7 +103,7 @@ static inline bool checkIfDerivedFromItem(const QString &fileName) snapshot.insert(document); - QmlJS::Link link(snapshot, modelManager->importPaths(), QmlJS::ModelManagerInterface::instance()->builtins(document)); + QmlJS::Link link(snapshot, modelManager->defaultVContext(), QmlJS::ModelManagerInterface::instance()->builtins(document)); QList<QmlJS::DiagnosticMessage> diagnosticLinkMessages; QmlJS::ContextPtr context = link(document, &diagnosticLinkMessages); diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index df895a4048..b2c2019bb7 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1731,25 +1731,12 @@ QList<Import> Model::imports() const QList<Import> Model::possibleImports() const { - QList<Import> possibleImportList; - - possibleImportList.append(Import::createLibraryImport("QtQuick.Controls", "1.0")); - possibleImportList.append(Import::createLibraryImport("QtQuick.Layouts", "1.0")); - possibleImportList.append(Import::createLibraryImport("QtQuick.Window", "2.0")); - - return possibleImportList; + return d->m_possibleImportList; } QList<Import> Model::usedImports() const { - QList<Import> usedImportList; - - usedImportList.append(Import::createLibraryImport("QtQuick", "1.0")); - usedImportList.append(Import::createLibraryImport("QtQuick", "1.1")); - usedImportList.append(Import::createLibraryImport("QtQuick", "2.0")); - usedImportList.append(Import::createLibraryImport("QtQuick", "2.1")); - - return usedImportList; + return d->m_usedImportList; } void Model::changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved) @@ -1757,6 +1744,16 @@ void Model::changeImports(const QList<Import> &importsToBeAdded, const QList<Imp d->changeImports(importsToBeAdded, importsToBeRemoved); } +void Model::setPossibleImports(const QList<Import> &possibleImports) +{ + d->m_possibleImportList = possibleImports; +} + +void Model::setUsedImports(const QList<Import> &usedImports) +{ + d->m_usedImportList = usedImports; +} + static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion) { diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 7dcc150491..8b2653ed9c 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -236,6 +236,8 @@ private: Model *m_q; MetaInfo m_metaInfo; QList<Import> m_imports; + QList<Import> m_possibleImportList; + QList<Import> m_usedImportList; QList<QWeakPointer<AbstractView> > m_viewList; QList<InternalNodePointer> m_selectedInternalNodeList; QHash<QString,InternalNodePointer> m_idNodeHash; diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 20eec5c8e1..7b0b170d23 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -48,6 +48,7 @@ #include <qmljs/qmljsutils.h> #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsqrcparser.h> +#include <qmljs/qmljsinterpreter.h> #include <utils/qtcassert.h> @@ -306,10 +307,10 @@ class ReadingContext { public: ReadingContext(const Snapshot &snapshot, const Document::Ptr &doc, - const QStringList importPaths) + const ViewerContext &vContext) : m_snapshot(snapshot) , m_doc(doc) - , m_link(snapshot, importPaths, + , m_link(snapshot, vContext, QmlJS::ModelManagerInterface::instance()->builtins(doc)) , m_context(m_link(doc, &m_diagnosticLinkMessages)) , m_scopeChain(doc, m_context) @@ -726,6 +727,67 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc, differenceHandler.importAbsentInQMl(import); } +void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext) +{ + QList<Import> possibleImports; + + QSet<ImportKey> possibleImportKeys = snapshot.importDependencies()->libraryImports(viewContext); + + QHash<QString, ImportKey> filteredPossibleImportKeys; + foreach (const ImportKey &importKey, possibleImportKeys) { + if (!filteredPossibleImportKeys.contains(importKey.path()) + || filteredPossibleImportKeys.value(importKey.path()).majorVersion < importKey.majorVersion + || (filteredPossibleImportKeys.value(importKey.path()).majorVersion == importKey.majorVersion + && filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion)) + filteredPossibleImportKeys.insert(importKey.path(), importKey); + } + + filteredPossibleImportKeys.remove(QLatin1String("<cpp>")); + filteredPossibleImportKeys.remove(QLatin1String("QML")); + filteredPossibleImportKeys.remove(QLatin1String("QtQml")); + filteredPossibleImportKeys.remove(QLatin1String("QtQuick/PrivateWidgets")); + + QList<QmlJS::Import> allImports = m_scopeChain->context()->imports(m_document.data())->all(); + + foreach (const QmlJS::Import &import, allImports) { + filteredPossibleImportKeys.remove(import.info.path()); + } + + foreach (const ImportKey &importKey, filteredPossibleImportKeys) { + QString libraryName = importKey.splitPath.join(QLatin1Char('.')); + QString version = QString(QStringLiteral("%1.%2").arg(importKey.majorVersion).arg(importKey.minorVersion)); + possibleImports.append(Import::createLibraryImport(libraryName, version)); + } + + if ( m_rewriterView->isAttached()) + m_rewriterView->model()->setPossibleImports(possibleImports); +} + +void TextToModelMerger::setupUsedImports() +{ + QList<QmlJS::Import> allImports = m_scopeChain->context()->imports(m_document.data())->all(); + + QList<Import> usedImports; + + foreach (const QmlJS::Import &import, allImports) { + if (import.used) { + if (import.info.type() == ImportType::Library) { + usedImports.append(Import::createLibraryImport(import.info.name(), import.info.version().toString(), import.info.as())); + } else if (import.info.type() == ImportType::Directory || import.info.type() == ImportType::File) { + usedImports.append(Import::createFileImport(import.info.name(), import.info.version().toString(), import.info.as())); + } + } + } + // even if not explicitly used we probably want to keep QtQuick imports + usedImports.append(Import::createLibraryImport("QtQuick", "1.0")); + usedImports.append(Import::createLibraryImport("QtQuick", "1.1")); + usedImports.append(Import::createLibraryImport("QtQuick", "2.0")); + usedImports.append(Import::createLibraryImport("QtQuick", "2.1")); + + if (m_rewriterView->isAttached()) + m_rewriterView->model()->setUsedImports(usedImports); +} + bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceHandler) { // qDebug() << "TextToModelMerger::load with data:" << data; @@ -751,7 +813,11 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH return false; } snapshot.insert(doc); - ReadingContext ctxt(snapshot, doc, importPaths); + QmlJS::ViewerContext vContext; + vContext.language = QmlJS::Language::Qml; + vContext.paths = importPaths; + vContext.flags = QmlJS::ViewerContext::Complete; + ReadingContext ctxt(snapshot, doc, vContext); m_scopeChain = QSharedPointer<const ScopeChain>( new ScopeChain(ctxt.scopeChain())); m_document = doc; @@ -764,6 +830,8 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH } setupImports(doc, differenceHandler); + setupPossibleImports(snapshot, vContext); + setupUsedImports(); if (m_rewriterView->model()->imports().isEmpty()) { const QmlJS::DiagnosticMessage diagnosticMessage(QmlJS::Severity::Error, AST::SourceLocation(0, 0, 0, 0), QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import statements found")); diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h index 8c98376db2..d82bf851fe 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h @@ -59,6 +59,8 @@ public: bool isActive() const; void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler); + void setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext); + void setupUsedImports(); bool load(const QString &data, DifferenceHandler &differenceHandler); RewriterView *view() const diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp index a8b7d70914..48a16d0de0 100644 --- a/src/plugins/qmljseditor/qmljsfindreferences.cpp +++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp @@ -831,7 +831,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future, QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - Link link(snapshot, modelManager->importPaths(), modelManager->builtins(doc)); + Link link(snapshot, modelManager->defaultVContext(), modelManager->builtins(doc)); ContextPtr context = link(); ScopeChain scopeChain(doc, context); diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp index 2e4a73b57e..30b3422cc5 100644 --- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp +++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp @@ -122,7 +122,7 @@ QmlJSTools::SemanticInfo SemanticInfoUpdater::makeNewSemanticInfo(const QmlJS::D ModelManagerInterface *modelManager = ModelManagerInterface::instance(); - Link link(semanticInfo.snapshot, modelManager->importPaths(), modelManager->builtins(doc)); + Link link(semanticInfo.snapshot, modelManager->defaultVContext(), modelManager->builtins(doc)); semanticInfo.context = link(doc, &semanticInfo.semanticMessages); ScopeChain *scopeChain = new ScopeChain(doc, semanticInfo.context); diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp index 42f78bec19..40d19319aa 100644 --- a/src/plugins/qmljseditor/qmltaskmanager.cpp +++ b/src/plugins/qmljseditor/qmltaskmanager.cpp @@ -92,13 +92,13 @@ static QList<ProjectExplorer::Task> convertToTasks(const QList<StaticAnalysis::M void QmlTaskManager::collectMessages( QFutureInterface<FileErrorMessages> &future, Snapshot snapshot, QList<ModelManagerInterface::ProjectInfo> projectInfos, - QStringList importPaths, bool updateSemantic) + ViewerContext vContext, bool updateSemantic) { foreach (const ModelManagerInterface::ProjectInfo &info, projectInfos) { QHash<QString, QList<DiagnosticMessage> > linkMessages; ContextPtr context; if (updateSemantic) { - Link link(snapshot, importPaths, snapshot.libraryInfo(info.qtImportsPath)); + Link link(snapshot, vContext, snapshot.libraryInfo(info.qtImportsPath)); context = link(&linkMessages); } @@ -161,7 +161,7 @@ void QmlTaskManager::updateMessagesNow(bool updateSemantic) QFuture<FileErrorMessages> future = QtConcurrent::run<FileErrorMessages>( &collectMessages, modelManager->newestSnapshot(), modelManager->projectInfos(), - modelManager->importPaths(), updateSemantic); + modelManager->defaultVContext(), updateSemantic); m_messageCollector.setFuture(future); } diff --git a/src/plugins/qmljseditor/qmltaskmanager.h b/src/plugins/qmljseditor/qmltaskmanager.h index 986a2e65f3..f7aaf0ab74 100644 --- a/src/plugins/qmljseditor/qmltaskmanager.h +++ b/src/plugins/qmljseditor/qmltaskmanager.h @@ -85,7 +85,7 @@ private: static void collectMessages(QFutureInterface<FileErrorMessages> &future, QmlJS::Snapshot snapshot, QList<QmlJS::ModelManagerInterface::ProjectInfo> projectInfos, - QStringList importPaths, + QmlJS::ViewerContext vContext, bool updateSemantic); private: diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp index 0d2bd263f5..13c88da73f 100644 --- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp +++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp @@ -609,14 +609,12 @@ static LanguageUtils::FakeMetaObject::Ptr buildFakeMetaObject( BaseClass *base = klass->baseClassAt(0); if (!base->name()) return fmo; - const QString baseClassName = namePrinter.prettyName(base->name()); fmo->setSuperclassName(baseClassName); Class *baseClass = lookupClass(baseClassName, klass, typeOf); if (!baseClass) return fmo; - buildFakeMetaObject(baseClass, fakeMetaObjects, typeOf); } @@ -735,8 +733,10 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) // convert to list of FakeMetaObject::ConstPtr m_exportedTypes.reserve(fakeMetaObjects.size()); - foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects) + foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects) { + fmo->updateFingerprint(); m_exportedTypes += fmo; + } } QList<LanguageUtils::FakeMetaObject::ConstPtr> FindExportedCppTypes::exportedTypes() const diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 46beb6a345..61470f40c2 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -49,6 +49,7 @@ #include <qtsupport/qmldumptool.h> #include <qtsupport/qtsupportconstants.h> #include <utils/hostosinfo.h> +#include <utils/function.h> #include <extensionsystem/pluginmanager.h> #include <QDir> @@ -360,7 +361,7 @@ QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles, QFuture<void> result = QtConcurrent::run(&ModelManager::parse, workingCopy(), sourceFiles, - this, + this, Language::Qml, emitDocumentOnDiskChanged); if (m_synchronizer.futures().size() > 10) { @@ -386,7 +387,7 @@ void ModelManager::fileChangedOnDisk(const QString &path) { QtConcurrent::run(&ModelManager::parse, workingCopy(), QStringList() << path, - this, true); + this, Language::Unknown, true); } void ModelManager::removeFiles(const QStringList &files) @@ -700,7 +701,8 @@ static bool findNewQmlLibraryInPath(const QString &path, ModelManager *modelManager, QStringList *importedFiles, QSet<QString> *scannedPaths, - QSet<QString> *newLibraries) + QSet<QString> *newLibraries, + bool ignoreMissing) { // if we know there is a library, done const LibraryInfo &existingInfo = snapshot.libraryInfo(path); @@ -715,8 +717,10 @@ static bool findNewQmlLibraryInPath(const QString &path, const QDir dir(path); QFile qmldirFile(dir.filePath(QLatin1String("qmldir"))); if (!qmldirFile.exists()) { - LibraryInfo libraryInfo(LibraryInfo::NotFound); - modelManager->updateLibraryInfo(path, libraryInfo); + if (!ignoreMissing) { + LibraryInfo libraryInfo(LibraryInfo::NotFound); + modelManager->updateLibraryInfo(path, libraryInfo); + } return false; } @@ -765,18 +769,18 @@ static void findNewQmlLibrary( QString::number(version.minorVersion())); findNewQmlLibraryInPath( libraryPath, snapshot, modelManager, - importedFiles, scannedPaths, newLibraries); + importedFiles, scannedPaths, newLibraries, false); libraryPath = QString::fromLatin1("%1.%2").arg( path, QString::number(version.majorVersion())); findNewQmlLibraryInPath( libraryPath, snapshot, modelManager, - importedFiles, scannedPaths, newLibraries); + importedFiles, scannedPaths, newLibraries, false); findNewQmlLibraryInPath( path, snapshot, modelManager, - importedFiles, scannedPaths, newLibraries); + importedFiles, scannedPaths, newLibraries, false); } static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot, @@ -785,7 +789,7 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap { // scan current dir findNewQmlLibraryInPath(doc->path(), snapshot, modelManager, - importedFiles, scannedPaths, newLibraries); + importedFiles, scannedPaths, newLibraries, false); // scan dir and lib imports const QStringList importPaths = modelManager->importPaths(); @@ -793,7 +797,7 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap if (import.type() == ImportType::Directory) { const QString targetPath = import.path(); findNewQmlLibraryInPath(targetPath, snapshot, modelManager, - importedFiles, scannedPaths, newLibraries); + importedFiles, scannedPaths, newLibraries, false); } if (import.type() == ImportType::Library) { @@ -808,24 +812,18 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap } } -void ModelManager::parse(QFutureInterface<void> &future, - WorkingCopy workingCopy, - QStringList files, - ModelManager *modelManager, - bool emitDocChangedOnDisk) +void ModelManager::parseLoop(QSet<QString> &scannedPaths, + QSet<QString> &newLibraries, + WorkingCopy workingCopy, + QStringList files, + ModelManager *modelManager, + Language::Enum mainLanguage, + bool emitDocChangedOnDisk, + Utils::function<bool(qreal)> reportProgress) { - int progressRange = files.size(); - future.setProgressRange(0, progressRange); - - // paths we have scanned for files and added to the files list - QSet<QString> scannedPaths; - // libraries we've found while scanning imports - QSet<QString> newLibraries; - for (int i = 0; i < files.size(); ++i) { - if (future.isCanceled()) - break; - future.setProgressValue(qreal(i) / files.size() * progressRange); + if (!reportProgress(qreal(i) / files.size())) + return; const QString fileName = files.at(i); @@ -835,7 +833,9 @@ void ModelManager::parse(QFutureInterface<void> &future, modelManager->updateQrcFile(fileName); continue; } - + if (language == Language::Qml + && (mainLanguage == Language::QmlQtQuick1 || Language::QmlQtQuick2)) + language = mainLanguage; QString contents; int documentRevision = 0; @@ -878,7 +878,116 @@ void ModelManager::parse(QFutureInterface<void> &future, if (emitDocChangedOnDisk) modelManager->emitDocumentChangedOnDisk(doc); } +} + +class FutureReporter +{ +public: + FutureReporter(QFutureInterface<void> &future, int multiplier = 100, int base = 0) + :future(future), multiplier(multiplier), base(base) + { } + bool operator()(qreal val) + { + if (future.isCanceled()) + return false; + future.setProgressValue(int(base + multiplier * val)); + return true; + } +private: + QFutureInterface<void> &future; + int multiplier; + int base; +}; + +void ModelManager::parse(QFutureInterface<void> &future, + WorkingCopy workingCopy, + QStringList files, + ModelManager *modelManager, + Language::Enum mainLanguage, + bool emitDocChangedOnDisk) +{ + FutureReporter reporter(future); + future.setProgressRange(0, 100); + + // paths we have scanned for files and added to the files list + QSet<QString> scannedPaths; + // libraries we've found while scanning imports + QSet<QString> newLibraries; + parseLoop(scannedPaths, newLibraries, workingCopy, files, modelManager, mainLanguage, + emitDocChangedOnDisk, reporter); + future.setProgressValue(100); +} + +struct ScanItem { + QString path; + int depth; + ScanItem(QString path = QString(), int depth = 0) + : path(path), depth(depth) + { } +}; + +void ModelManager::importScan(QFutureInterface<void> &future, + ModelManagerInterface::WorkingCopy workingCopy, + QStringList paths, ModelManager *modelManager, + Language::Enum language, + bool emitDocChangedOnDisk) +{ + // paths we have scanned for files and added to the files list + QSet<QString> scannedPaths = modelManager->m_scannedPaths; + // libraries we've found while scanning imports + QSet<QString> newLibraries; + QVector<ScanItem> pathsToScan; + pathsToScan.reserve(paths.size()); + foreach (const QString &path, paths) { + QString cPath = QDir::cleanPath(path); + if (modelManager->m_scannedPaths.contains(cPath)) + continue; + pathsToScan.append(ScanItem(cPath)); + } + const int maxScanDepth = 5; + int progressRange = pathsToScan.size() * (1 << (2 + maxScanDepth)); + int totalWork(progressRange), workDone(0); + future.setProgressRange(0, progressRange); // update max length while iterating? + const bool libOnly = true; // FIXME remove when tested more + while (!pathsToScan.isEmpty() && !future.isCanceled()) { + ScanItem toScan = pathsToScan.last(); + pathsToScan.pop_back(); + int pathBudget = (maxScanDepth + 2 - toScan.depth); + if (!scannedPaths.contains(toScan.path)) { + QStringList importedFiles; + const Snapshot snapshot = modelManager->snapshot(); + if (!findNewQmlLibraryInPath(toScan.path, snapshot, modelManager, &importedFiles, + &scannedPaths, &newLibraries, true) + && !libOnly && snapshot.documentsInDirectory(toScan.path).isEmpty()) + importedFiles += qmlFilesInDirectory(toScan.path); + workDone += 1; + future.setProgressValue(progressRange * workDone / totalWork); + if (!importedFiles.isEmpty()) { + FutureReporter reporter(future, progressRange * pathBudget / (4 * totalWork), + progressRange * workDone / totalWork); + parseLoop(scannedPaths, newLibraries, workingCopy, importedFiles, modelManager, + language, emitDocChangedOnDisk, reporter); // run in parallel?? + importedFiles.clear(); + } + workDone += pathBudget / 4 - 1; + future.setProgressValue(progressRange * workDone / totalWork); + } else { + workDone += pathBudget / 4; + } + // always descend tree, as we might have just scanned with a smaller depth + if (toScan.depth < maxScanDepth) { + QDir dir(toScan.path); + QStringList subDirs(dir.entryList(QDir::Dirs)); + workDone += 1; + totalWork += pathBudget / 2 * subDirs.size() - pathBudget * 3 / 4 + 1; + foreach (const QString path, subDirs) + pathsToScan.append(ScanItem(dir.absoluteFilePath(path), toScan.depth + 1)); + } else { + workDone += pathBudget *3 / 4; + } + future.setProgressValue(progressRange * workDone / totalWork); + } future.setProgressValue(progressRange); } @@ -993,6 +1102,33 @@ void ModelManager::updateImportPaths() findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries); updateSourceFiles(importedFiles, true); + + QStringList pathToScan; + foreach (QString importPath, allImportPaths) + if (!m_scannedPaths.contains(importPath)) + pathToScan.append(importPath); + + if (pathToScan.count() > 1) { + QFuture<void> result = QtConcurrent::run(&ModelManager::importScan, + workingCopy(), pathToScan, + this, Language::Qml, + true); + + if (m_synchronizer.futures().size() > 10) { + QList<QFuture<void> > futures = m_synchronizer.futures(); + + m_synchronizer.clearFutures(); + + foreach (const QFuture<void> &future, futures) { + if (! (future.isFinished() || future.isCanceled())) + m_synchronizer.addFuture(future); + } + } + + m_synchronizer.addFuture(result); + + ProgressManager::addTask(result, tr("Qml import scan"), Constants::TASK_IMPORT_SCAN); + } } void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &importPath, @@ -1121,6 +1257,35 @@ LibraryInfo ModelManager::builtins(const Document::Ptr &doc) const return _validSnapshot.libraryInfo(info.qtImportsPath); } +ViewerContext ModelManager::completeVContext(const ViewerContext &vCtx, + const Document::Ptr &doc) const +{ + Q_UNUSED(doc); + ViewerContext res = vCtx; + switch (res.flags) { + case ViewerContext::Complete: + break; + case ViewerContext::AddQtPath: + case ViewerContext::AddAllPaths: + res.paths << importPaths(); + } + res.flags = ViewerContext::Complete; + return res; +} + +ViewerContext ModelManager::defaultVContext(bool autoComplete, const Document::Ptr &doc) const +{ + if (autoComplete) + return completeVContext(m_vContext, doc); + else + return m_vContext; +} + +void ModelManager::setDefaultVContext(const ViewerContext &vContext) +{ + m_vContext = vContext; +} + void ModelManager::joinAllThreads() { foreach (QFuture<void> future, m_synchronizer.futures()) diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 04cb3d5d4e..6d30d536e2 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -34,6 +34,7 @@ #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsqrcparser.h> +#include <qmljs/qmljsconstants.h> #include <cplusplus/CppDocument.h> #include <utils/qtcoverride.h> @@ -115,6 +116,14 @@ public: QmlJS::LibraryInfo builtins(const QmlJS::Document::Ptr &doc) const QTC_OVERRIDE; + QmlJS::ViewerContext completeVContext( + const QmlJS::ViewerContext &vCtx, + const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE; + QmlJS::ViewerContext defaultVContext( + bool autoComplete = true, + const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE; + void setDefaultVContext(const QmlJS::ViewerContext &vContext) QTC_OVERRIDE; + void joinAllThreads() QTC_OVERRIDE; public slots: @@ -127,11 +136,22 @@ protected: QFuture<void> refreshSourceFiles(const QStringList &sourceFiles, bool emitDocumentOnDiskChanged); + static void parseLoop(QSet<QString> &scannedPaths, QSet<QString> &newLibraries, + WorkingCopy workingCopy, QStringList files, ModelManager *modelManager, + QmlJS::Language::Enum mainLanguage, bool emitDocChangedOnDisk, + Utils::function<bool (qreal)> reportProgress); static void parse(QFutureInterface<void> &future, WorkingCopy workingCopy, QStringList files, ModelManager *modelManager, + QmlJS::Language::Enum mainLanguage, bool emitDocChangedOnDisk); + static void importScan(QFutureInterface<void> &future, + WorkingCopy workingCopy, + QStringList paths, + ModelManager *modelManager, + QmlJS::Language::Enum mainLanguage, + bool emitDocChangedOnDisk); void loadQmlTypeDescriptions(); void loadQmlTypeDescriptions(const QString &path); @@ -158,6 +178,8 @@ private: QStringList m_defaultImportPaths; QmlJS::QmlLanguageBundles m_activeBundles; QmlJS::QmlLanguageBundles m_extendedBundles; + QmlJS::ViewerContext m_vContext; + QSet<QString> m_scannedPaths; QTimer *m_updateCppQmlTypesTimer; QTimer *m_asyncResetTimer; diff --git a/src/plugins/qmljstools/qmljsplugindumper.cpp b/src/plugins/qmljstools/qmljsplugindumper.cpp index bb8a4a8835..d0fb8a7b46 100644 --- a/src/plugins/qmljstools/qmljsplugindumper.cpp +++ b/src/plugins/qmljstools/qmljsplugindumper.cpp @@ -339,6 +339,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode) if (!warning.isEmpty()) printParseWarnings(libraryPath, warning); } + libraryInfo.updateFingerprint(); m_modelManager->updateLibraryInfo(libraryPath, libraryInfo); } @@ -361,6 +362,7 @@ void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError) const Snapshot snapshot = m_modelManager->snapshot(); LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath); libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages)); + libraryInfo.updateFingerprint(); m_modelManager->updateLibraryInfo(libraryPath, libraryInfo); } } @@ -418,6 +420,7 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, if (!warnings.isEmpty()) printParseWarnings(libraryPath, warnings.join(QLatin1String("\n"))); + libraryInfo.updateFingerprint(); m_modelManager->updateLibraryInfo(libraryPath, libraryInfo); } @@ -456,6 +459,7 @@ void PluginDumper::dump(const Plugin &plugin) } libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, errorMessage); + libraryInfo.updateFingerprint(); m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo); return; } diff --git a/src/plugins/qmljstools/qmljstools_test.cpp b/src/plugins/qmljstools/qmljstools_test.cpp index e4336b0146..010da935dc 100644 --- a/src/plugins/qmljstools/qmljstools_test.cpp +++ b/src/plugins/qmljstools/qmljstools_test.cpp @@ -53,7 +53,7 @@ void QmlJSTools::Internal::QmlJSToolsPlugin::test_basic() Document::Ptr doc = snapshot.document(welcomescreenRootPath); QVERIFY(doc && doc->isQmlDocument()); - ContextPtr context = Link(snapshot, QStringList(), LibraryInfo())(); + ContextPtr context = Link(snapshot, ViewerContext(), LibraryInfo())(); QVERIFY(context); const CppComponentValue *rectangleValue = context->valueOwner()->cppQmlTypes().objectByQualifiedName( diff --git a/src/plugins/qmljstools/qmljstoolsconstants.h b/src/plugins/qmljstools/qmljstoolsconstants.h index 4662204fe0..2a0d7644f1 100644 --- a/src/plugins/qmljstools/qmljstoolsconstants.h +++ b/src/plugins/qmljstools/qmljstoolsconstants.h @@ -43,6 +43,7 @@ const char JS_MIMETYPE[] = "application/javascript"; const char JSON_MIMETYPE[] = "application/json"; const char TASK_INDEX[] = "QmlJSEditor.TaskIndex"; +const char TASK_IMPORT_SCAN[] = "QmlJSEditor.TaskImportScan"; const char QML_JS_CODE_STYLE_SETTINGS_ID[] = "A.Code Style"; const char QML_JS_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("QmlJSTools", "Code Style"); diff --git a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp index 9107e53d48..3503807896 100644 --- a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp +++ b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp @@ -92,6 +92,13 @@ void QmlProfilerCanvas::componentComplete() QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); } QQuickItem::componentComplete(); + requestRedraw(); +} + +void QmlProfilerCanvas::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChanged(newGeometry, oldGeometry); + requestRedraw(); } } diff --git a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h index b320601396..4a360d012c 100644 --- a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h +++ b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h @@ -61,6 +61,7 @@ private slots: protected: virtual void paint(QPainter *); virtual void componentComplete(); + virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); private: Context2D *m_context2d; diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index f067422819..9b2864c19b 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -330,6 +330,7 @@ Rectangle { contentWidth: 0 height: labels.height + labelsTail.height flickableDirection: Flickable.HorizontalFlick + boundsBehavior: Flickable.StopAtBounds onContentXChanged: view.updateZoomControl() clip:true diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml index 86fdb2a7c6..e3930c7d16 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRange.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml @@ -69,6 +69,11 @@ RangeMover { } function setPos(pos) { + if (pos < 0) + pos = 0; + else if (pos > width) + pos = width; + switch (creationState) { case 1: { setLeft(pos); diff --git a/src/plugins/qmlprofiler/qml/TimeDisplay.qml b/src/plugins/qmlprofiler/qml/TimeDisplay.qml index 81bc47d337..5a6a63b9e4 100644 --- a/src/plugins/qmlprofiler/qml/TimeDisplay.qml +++ b/src/plugins/qmlprofiler/qml/TimeDisplay.qml @@ -38,17 +38,6 @@ Canvas2D { property real endTime : 0 property real timePerPixel: 0 - - Component.onCompleted: { - requestRedraw(); - } - onWidthChanged: { - requestRedraw(); - } - onHeightChanged: { - requestRedraw(); - } - Connections { target: zoomControl onRangeChanged: { diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index ee06d501d8..6d48cbb014 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -38,21 +38,6 @@ Canvas2D { property real endTime property real timePerPixel - Component.onCompleted: { - requestRedraw(); - } - - onWidthChanged: { - requestRedraw(); - } - onHeightChanged: { - requestRedraw(); - } - - onYChanged: { - requestRedraw(); - } - Connections { target: labels onHeightChanged: { requestRedraw(); } diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp index 397c82ab94..9125b07a62 100644 --- a/src/plugins/qnx/blackberryconfiguration.cpp +++ b/src/plugins/qnx/blackberryconfiguration.cpp @@ -73,27 +73,27 @@ BlackBerryConfiguration::BlackBerryConfiguration(const FileName &ndkEnvFile, boo m_qnxEnv = QnxUtils::qnxEnvironmentFromNdkFile(m_ndkEnvFile.toString()); QString ndkTarget; - QString qnxHost; foreach (const Utils::EnvironmentItem &item, m_qnxEnv) { if (item.name == QLatin1String("QNX_TARGET")) ndkTarget = item.value; else if (item.name == QLatin1String("QNX_HOST")) - qnxHost = item.value; + m_qnxHost = item.value; } - QString sep = QString::fromLatin1("%1qnx6").arg(QDir::separator()); - m_targetName = ndkTarget.split(sep).first().split(QDir::separator()).last(); + // The QNX_TARGET value is using Unix-like separator on all platforms. + QString sep = QString::fromLatin1("/qnx6"); + m_targetName = ndkTarget.split(sep).first().split(QLatin1Char('/')).last(); if (QDir(ndkTarget).exists()) m_sysRoot = FileName::fromString(ndkTarget); - FileName qmake4Path = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qmake"))); - FileName qmake5Path = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qt5/qmake"))); - FileName gccPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qcc"))); - FileName deviceGdbPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/ntoarm-gdb"))); - FileName simulatorGdbPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/ntox86-gdb"))); + FileName qmake4Path = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qmake"))); + FileName qmake5Path = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qt5/qmake"))); + FileName gccPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qcc"))); + FileName deviceGdbPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/ntoarm-gdb"))); + FileName simulatorGdbPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/ntox86-gdb"))); if (qmake4Path.toFileInfo().exists()) m_qmake4BinaryFile = qmake4Path; @@ -126,6 +126,11 @@ QString BlackBerryConfiguration::targetName() const return m_targetName; } +QString BlackBerryConfiguration::qnxHost() const +{ + return m_qnxHost; +} + bool BlackBerryConfiguration::isAutoDetected() const { return m_isAutoDetected; diff --git a/src/plugins/qnx/blackberryconfiguration.h b/src/plugins/qnx/blackberryconfiguration.h index 51473a5b0a..1b31d186b3 100644 --- a/src/plugins/qnx/blackberryconfiguration.h +++ b/src/plugins/qnx/blackberryconfiguration.h @@ -66,6 +66,7 @@ public: QString ndkPath() const; QString displayName() const; QString targetName() const; + QString qnxHost() const; bool isAutoDetected() const; bool isActive() const; bool isValid() const; @@ -81,6 +82,7 @@ public: private: QString m_displayName; QString m_targetName; + QString m_qnxHost; bool m_isAutoDetected; Utils::FileName m_ndkEnvFile; Utils::FileName m_qmake4BinaryFile; diff --git a/src/plugins/qnx/blackberryinstallwizardpages.cpp b/src/plugins/qnx/blackberryinstallwizardpages.cpp index b854475ff5..b2bd3f5dc0 100644 --- a/src/plugins/qnx/blackberryinstallwizardpages.cpp +++ b/src/plugins/qnx/blackberryinstallwizardpages.cpp @@ -64,10 +64,13 @@ NdkPathChooser::NdkPathChooser(Mode mode, QWidget *parent) : Utils::PathChooser(parent) , m_mode(mode) { - if (m_mode == NdkPathChooser::InstallMode) + if (m_mode == NdkPathChooser::InstallMode) { setExpectedKind(Utils::PathChooser::Directory); - else + } else { setExpectedKind(Utils::PathChooser::File); + setPromptDialogFilter(Utils::HostOsInfo::isWindowsHost() ? QLatin1String("*.bat") : + QLatin1String("*.sh")); + } } bool NdkPathChooser::validatePath(const QString &path, QString *errorMessage) @@ -80,7 +83,10 @@ bool NdkPathChooser::validatePath(const QString &path, QString *errorMessage) return !(QnxUtils::sdkInstallerPath(path).isEmpty()); QFileInfo fi(path); - return (fi.suffix() == QLatin1String("sh") || fi.suffix() == QLatin1String("bat")); + if (Utils::HostOsInfo::isWindowsHost()) + return fi.suffix() == QLatin1String("bat"); + + return fi.suffix() == QLatin1String("sh"); } //------------------------------------------------------------------ diff --git a/src/plugins/qnx/blackberryndksettingswidget.cpp b/src/plugins/qnx/blackberryndksettingswidget.cpp index 9ca62b4aa6..a1982539e7 100644 --- a/src/plugins/qnx/blackberryndksettingswidget.cpp +++ b/src/plugins/qnx/blackberryndksettingswidget.cpp @@ -144,15 +144,18 @@ void BlackBerryNDKSettingsWidget::updateInfoTable(QTreeWidgetItem* currentItem) if (!config) return; - foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks()) - { - if (ndkInfo.name == config->displayName()) { - m_ui->baseNameLabel->setText(ndkInfo.name); - m_ui->ndkPathLabel->setText(ndkInfo.path); - m_ui->versionLabel->setText(ndkInfo.version); - m_ui->hostLabel->setText(ndkInfo.host); - m_ui->targetLabel->setText(ndkInfo.target); - break; + m_ui->baseNameLabel->setText(config->displayName()); + m_ui->ndkPathLabel->setText(QDir::toNativeSeparators(config->ndkPath())); + m_ui->hostLabel->setText(QDir::toNativeSeparators(config->qnxHost())); + m_ui->targetLabel->setText(QDir::toNativeSeparators(config->sysRoot().toString())); + m_ui->versionLabel->clear(); + // TODO: Add a versionNumber attribute for the BlackBerryConfiguration class + if (config->isAutoDetected()) { + foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks()) { + if (ndkInfo.name == config->displayName()) { + m_ui->versionLabel->setText(ndkInfo.version); + break; + } } } diff --git a/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp b/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp index 3291e0c762..d21fa5af86 100644 --- a/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp +++ b/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp @@ -129,11 +129,6 @@ CascadesImportWizard::~CascadesImportWizard() { } -Core::FeatureSet CascadesImportWizard::requiredFeatures() const -{ - return Core::FeatureSet(Constants::QNX_BB_FEATURE); -} - Core::BaseFileWizard::ExtensionList CascadesImportWizard::selectExtensions() { return Core::BaseFileWizard::ExtensionList(); diff --git a/src/plugins/qnx/cascadesimport/cascadesimportwizard.h b/src/plugins/qnx/cascadesimport/cascadesimportwizard.h index 599be858e6..9a60db994e 100644 --- a/src/plugins/qnx/cascadesimport/cascadesimportwizard.h +++ b/src/plugins/qnx/cascadesimport/cascadesimportwizard.h @@ -68,7 +68,6 @@ public: CascadesImportWizard(QObject *parent = 0); virtual ~CascadesImportWizard(); - Core::FeatureSet requiredFeatures() const; protected: ExtensionList selectExtensions(); QWizard* createWizardDialog(QWidget *parent, diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp index 19211acdbb..a894b2f092 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp @@ -75,7 +75,8 @@ Highlighter::Highlighter(QTextDocument *parent) : << TextEditor::C_TEXT // TODO : add style for error (eg. red underline) << TextEditor::C_FUNCTION << TextEditor::C_TEXT - << TextEditor::C_TEXT; + << TextEditor::C_TEXT + << TextEditor::C_LOCAL; } setTextFormatCategories(categories); @@ -113,6 +114,7 @@ KateFormatMap::KateFormatMap() m_ids.insert(QLatin1String("dsFunction"), Highlighter::Function); m_ids.insert(QLatin1String("dsRegionMarker"), Highlighter::RegionMarker); m_ids.insert(QLatin1String("dsOthers"), Highlighter::Others); + m_ids.insert(QLatin1String("dsIdentifier"), Highlighter::Identifier); } Q_GLOBAL_STATIC(KateFormatMap, kateFormatMap) diff --git a/src/plugins/texteditor/generichighlighter/highlighter.h b/src/plugins/texteditor/generichighlighter/highlighter.h index 968a48a6c1..ef0498036a 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.h +++ b/src/plugins/texteditor/generichighlighter/highlighter.h @@ -83,7 +83,8 @@ public: Error, Function, RegionMarker, - Others + Others, + Identifier }; void setTabSettings(const TabSettings &ts); |