diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp index f0d18509fed..519f9ca15cb 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp @@ -1180,7 +1180,7 @@ void PropertiesView::MView::onClassMembersStatusChanged(bool valid) if (valid) m_classMembersStatusLabel->clear(); else - m_classMembersStatusLabel->setText(tr("Invalid syntax.")); + m_classMembersStatusLabel->setText("" + tr("Invalid syntax.") + ""); } void PropertiesView::MView::onParseClassMembers() diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index 61a6a8974c1..6c182ba48e6 100644 --- a/src/libs/utils/treemodel.cpp +++ b/src/libs/utils/treemodel.cpp @@ -866,10 +866,10 @@ TreeItem *TreeItem::reverseFindAnyChild(const std::function & { auto end = m_children.rend(); for (auto it = m_children.rbegin(); it != end; ++it) { - if (pred(*it)) - return *it; if (TreeItem *found = (*it)->reverseFindAnyChild(pred)) return found; + if (pred(*it)) + return *it; } return nullptr; } diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h index 41300b7dbc4..1cef3645111 100644 --- a/src/libs/utils/treemodel.h +++ b/src/libs/utils/treemodel.h @@ -82,7 +82,8 @@ public: void forSelectedChildren(const std::function &pred) const; void forAllChildren(const std::function &pred) const; TreeItem *findAnyChild(const std::function &pred) const; - // like findAnyChild() but processes children from bottom to top + // like findAnyChild() but processes children in exact reverse order + // (bottom to top, most inner children first) TreeItem *reverseFindAnyChild(const std::function &pred) const; // Levels are 1-based: Child at Level 1 is an immediate child. diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 2a405da1f76..3019664f497 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -405,7 +405,7 @@ void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor( const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart; if (isProjectPartLoadedOrIsFallback(projectPart)) { - registerTranslationUnitForEditor(projectPart.data()); + registerTranslationUnitForEditor(*projectPart.data()); m_projectPart = projectPart; m_isProjectFile = m_parser->projectPartInfo().hints @@ -421,7 +421,132 @@ void ClangEditorDocumentProcessor::onParserFinished() updateProjectPartAndTranslationUnitForEditor(); } -void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart) +namespace { +// TODO: Can we marry this with CompilerOptionsBuilder? +class FileOptionsBuilder +{ +public: + FileOptionsBuilder(const QString &filePath, CppTools::ProjectPart &projectPart) + : m_filePath(filePath) + , m_projectPart(projectPart) + { + addLanguageOptions(); + addDiagnosticOptions(); + addGlobalOptions(); + addPrecompiledHeaderOptions(); + } + + const QStringList &options() const { return m_options; } + +private: + void addLanguageOptions() + { + // Determine file kind with respect to ambiguous headers. + CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(m_filePath); + if (fileKind == CppTools::ProjectFile::AmbiguousHeader) { + fileKind = m_projectPart.languageVersion <= CppTools::ProjectPart::LatestCVersion + ? CppTools::ProjectFile::CHeader + : CppTools::ProjectFile::CXXHeader; + } + + CppTools::CompilerOptionsBuilder builder(m_projectPart); + builder.addLanguageOption(fileKind); + + m_options.append(builder.options()); + } + + void addDiagnosticOptions() + { + if (m_projectPart.project) { + ClangProjectSettings projectSettings(m_projectPart.project); + if (!projectSettings.useGlobalConfig()) { + const Core::Id warningConfigId = projectSettings.warningConfigId(); + const CppTools::ClangDiagnosticConfigsModel configsModel( + CppTools::codeModelSettings()->clangCustomDiagnosticConfigs()); + if (configsModel.hasConfigWithId(warningConfigId)) { + m_options.append( + configsModel.configWithId(warningConfigId).commandLineWarnings()); + return; + } + } + } + + m_options.append( + CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings()); + } + + void addXclangArg(const QString &argName, const QString &argValue = QString()) + { + m_options.append("-Xclang"); + m_options.append(argName); + if (!argValue.isEmpty()) { + m_options.append("-Xclang"); + m_options.append(argValue); + } + } + + void addTidyOptions() + { + const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks(); + if (tidyChecks.isEmpty()) + return; + + addXclangArg("-add-plugin", "clang-tidy"); + addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'"); + } + + void addClazyOptions() + { + const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks(); + if (clazyChecks.isEmpty()) + return; + + addXclangArg("-add-plugin", "clang-lazy"); + addXclangArg("-plugin-arg-clang-lazy", clazyChecks); + + // NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for + // all of them. That means that ignore-included-files will not change anything unless we decide + // to return the original -I prefix for some include paths. + addXclangArg("-plugin-arg-clang-lazy", "ignore-included-files"); + } + + void addGlobalOptions() + { + if (!m_projectPart.project) + m_options.append(ClangProjectSettings::globalCommandLineOptions()); + else + m_options.append(ClangProjectSettings{m_projectPart.project}.commandLineOptions()); + + addTidyOptions(); + addClazyOptions(); + } + + void addPrecompiledHeaderOptions() + { + using namespace CppTools; + + if (getPchUsage() == CompilerOptionsBuilder::PchUsage::None) + return; + + if (m_projectPart.precompiledHeaders.contains(m_filePath)) + return; + + CompilerOptionsBuilder builder(m_projectPart); + builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use); + + m_options.append(builder.options()); + } + +private: + const QString &m_filePath; + const CppTools::ProjectPart &m_projectPart; + + QStringList m_options; +}; +} // namespace + +void ClangEditorDocumentProcessor::registerTranslationUnitForEditor( + CppTools::ProjectPart &projectPart) { // On registration we send the document content immediately as an unsaved // file, because @@ -433,12 +558,13 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::Pr // like on Windows. if (m_projectPart) { - if (projectPart->id() == m_projectPart->id()) + if (projectPart.id() == m_projectPart->id()) return; } + const FileOptionsBuilder fileOptions(filePath(), projectPart); m_communicator.registerTranslationUnitsForEditor( - {fileContainerWithArgumentsAndDocumentContent(projectPart)}); + {fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())}); ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision()); } @@ -503,137 +629,12 @@ ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer( Utf8String::fromByteArray(codecName)); } -static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart) +ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithOptionsAndDocumentContent( + CppTools::ProjectPart &projectPart, const QStringList &fileOptions) const { - if (projectPart) - return *projectPart; - return *CppTools::CppModelManager::instance()->fallbackProjectPart().data(); -} - -static QStringList languageOptions(const QString &filePath, CppTools::ProjectPart *projectPart) -{ - const auto theProjectPart = projectPartForLanguageOption(projectPart); - - // Determine file kind with respect to ambiguous headers. - CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(filePath); - if (fileKind == CppTools::ProjectFile::AmbiguousHeader) { - fileKind = theProjectPart.languageVersion <= CppTools::ProjectPart::LatestCVersion - ? CppTools::ProjectFile::CHeader - : CppTools::ProjectFile::CXXHeader; - } - - CppTools::CompilerOptionsBuilder builder(theProjectPart); - builder.addLanguageOption(fileKind); - - return builder.options(); -} - -static QStringList warningOptions(CppTools::ProjectPart *projectPart) -{ - if (projectPart && projectPart->project) { - ClangProjectSettings projectSettings(projectPart->project); - if (!projectSettings.useGlobalConfig()) { - const Core::Id warningConfigId = projectSettings.warningConfigId(); - const CppTools::ClangDiagnosticConfigsModel configsModel( - CppTools::codeModelSettings()->clangCustomDiagnosticConfigs()); - if (configsModel.hasConfigWithId(warningConfigId)) - return configsModel.configWithId(warningConfigId).commandLineWarnings(); - } - } - - return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings(); -} - -static void addXclangArg(QStringList &list, const QString &argName, - const QString &argValue = QString()) -{ - list.append("-Xclang"); - list.append(argName); - if (!argValue.isEmpty()) { - list.append("-Xclang"); - list.append(argValue); - } -} - -static QStringList tidyCommandLine() -{ - const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks(); - - if (tidyChecks.isEmpty()) - return QStringList(); - - QStringList result; - addXclangArg(result, "-add-plugin", "clang-tidy"); - addXclangArg(result, "-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'"); - return result; -} - -static QStringList clazyCommandLine() -{ - const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks(); - - if (clazyChecks.isEmpty()) - return QStringList(); - - QStringList result; - addXclangArg(result, "-add-plugin", "clang-lazy"); - addXclangArg(result, "-plugin-arg-clang-lazy", clazyChecks); - - // NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for - // all of them. That means that ignore-included-files will not change anything unless we decide - // to return the original -I prefix for some include paths. - addXclangArg(result, "-plugin-arg-clang-lazy", "ignore-included-files"); - return result; -} - -static QStringList commandLineOptions(CppTools::ProjectPart *projectPart) -{ - QStringList result; - if (!projectPart || !projectPart->project) - result.append(ClangProjectSettings::globalCommandLineOptions()); - else - result.append(ClangProjectSettings{projectPart->project}.commandLineOptions()); - result.append(tidyCommandLine()); - result.append(clazyCommandLine()); - return result; -} - -static QStringList precompiledHeaderOptions( - const QString& filePath, - CppTools::ProjectPart *projectPart) -{ - using namespace CppTools; - - if (CppTools::getPchUsage() == CompilerOptionsBuilder::PchUsage::None) - return QStringList(); - - if (projectPart->precompiledHeaders.contains(filePath)) - return QStringList(); - - const CppTools::ProjectPart theProjectPart = projectPartForLanguageOption(projectPart); - CppTools::CompilerOptionsBuilder builder(theProjectPart); - builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use); - - return builder.options(); -} - -static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart) -{ - return languageOptions(filePath, projectPart) - + warningOptions(projectPart) - + commandLineOptions(projectPart) - + precompiledHeaderOptions(filePath, projectPart); -} - -ClangBackEnd::FileContainer -ClangEditorDocumentProcessor::fileContainerWithArgumentsAndDocumentContent( - CppTools::ProjectPart *projectPart) const -{ - const QStringList theFileArguments = fileArguments(filePath(), projectPart); - return ClangBackEnd::FileContainer(filePath(), - projectPart->id(), - Utf8StringVector(theFileArguments), + projectPart.id(), + Utf8StringVector(fileOptions), textDocument()->toPlainText(), true, revision()); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 27c4b355dc0..67ef0bc8a5d 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -104,14 +104,14 @@ public: private: void onParserFinished(); void updateProjectPartAndTranslationUnitForEditor(); - void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart); + void registerTranslationUnitForEditor(CppTools::ProjectPart &projectPart); void updateTranslationUnitIfProjectPartExists(); void requestDocumentAnnotations(const QString &projectpartId); HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget( const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic); ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const; - ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent( - CppTools::ProjectPart *projectPart) const; + ClangBackEnd::FileContainer fileContainerWithOptionsAndDocumentContent( + CppTools::ProjectPart &projectPart, const QStringList &fileOptions) const; ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const; private: diff --git a/src/plugins/clearcase/versionselector.cpp b/src/plugins/clearcase/versionselector.cpp index 42067fd0417..453ce132ab7 100644 --- a/src/plugins/clearcase/versionselector.cpp +++ b/src/plugins/clearcase/versionselector.cpp @@ -39,9 +39,10 @@ VersionSelector::VersionSelector(const QString &fileName, const QString &message { ui->setupUi(this); ui->headerLabel->setText(ui->headerLabel->text().arg(fileName)); - ui->loadedText->setHtml(tr("

Note: You will not be able to check in " - "this file without merging the changes (not supported by the " - "plugin)

")); + ui->loadedText->setHtml("

" + + tr("Note: You will not be able to check in this file without merging " + "the changes (not supported by the plugin)") + + "

"); m_stream = new QTextStream(message.toLocal8Bit(), QIODevice::ReadOnly | QIODevice::Text); QString line; while (!m_stream->atEnd() && !line.contains(QLatin1String("1) Loaded version"))) diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 3a52d6911ce..b59fb5e2353 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -450,9 +450,9 @@ KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k } else { message = tr("Generator: %1
Extra generator: %2").arg(info.generator).arg(info.extraGenerator); if (!info.platform.isEmpty()) - message += tr("
Platform: %1").arg(info.platform); + message += "
" + tr("Platform: %1").arg(info.platform); if (!info.toolset.isEmpty()) - message += tr("
Toolset: %1").arg(info.toolset); + message += "
" + tr("Toolset: %1").arg(info.toolset); } return ItemList() << qMakePair(tr("CMake Generator"), message); } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index 98e6b4efc22..3740aee8be5 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -115,7 +115,7 @@ void CMakeTargetNode::setTargetInformation(const QList &artifac m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts"); } else { const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput); - m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:
") + m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:") + "
" + tmp.join("
"); } } diff --git a/src/plugins/coreplugin/helpmanager.cpp b/src/plugins/coreplugin/helpmanager.cpp index 376323b6019..3d6780b9097 100644 --- a/src/plugins/coreplugin/helpmanager.cpp +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -53,10 +53,12 @@ namespace Core { struct HelpManagerPrivate { HelpManagerPrivate() : - m_needsSetup(true), m_helpEngine(0), m_collectionWatcher(0) + m_needsSetup(true), m_helpEngine(nullptr), m_collectionWatcher(nullptr) {} - QStringList documentationFromInstaller(); + ~HelpManagerPrivate(); + + const QStringList documentationFromInstaller(); void readSettings(); void writeSettings(); void cleanUpDocumentation(); @@ -73,8 +75,8 @@ struct HelpManagerPrivate QSet m_userRegisteredFiles; }; -static HelpManager *m_instance = 0; -static HelpManagerPrivate *d; +static HelpManager *m_instance = nullptr; +static HelpManagerPrivate *d = nullptr; static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " @@ -102,11 +104,8 @@ HelpManager::HelpManager(QObject *parent) : HelpManager::~HelpManager() { - d->writeSettings(); - delete d->m_helpEngine; - d->m_helpEngine = 0; - m_instance = 0; delete d; + m_instance = nullptr; } HelpManager *HelpManager::instance() @@ -124,13 +123,13 @@ QString HelpManager::collectionFilePath() void HelpManager::registerDocumentation(const QStringList &files) { if (d->m_needsSetup) { - foreach (const QString &filePath, files) + for (const QString &filePath : files) d->m_filesToRegister.insert(filePath); return; } bool docsChanged = false; - foreach (const QString &file, files) { + for (const QString &file : files) { const QString &nameSpace = d->m_helpEngine->namespaceName(file); if (nameSpace.isEmpty()) continue; @@ -162,13 +161,13 @@ void HelpManager::registerDocumentation(const QStringList &files) void HelpManager::unregisterDocumentation(const QStringList &nameSpaces) { if (d->m_needsSetup) { - foreach (const QString &name, nameSpaces) + for (const QString &name : nameSpaces) d->m_nameSpacesToUnregister.insert(name); return; } bool docsChanged = false; - foreach (const QString &nameSpace, nameSpaces) { + for (const QString &nameSpace : nameSpaces) { const QString filePath = d->m_helpEngine->documentationFileName(nameSpace); if (d->m_helpEngine->unregisterDocumentation(nameSpace)) { docsChanged = true; @@ -185,7 +184,7 @@ void HelpManager::unregisterDocumentation(const QStringList &nameSpaces) void HelpManager::registerUserDocumentation(const QStringList &filePaths) { - foreach (const QString &filePath, filePaths) + for (const QString &filePath : filePaths) d->m_userRegisteredFiles.insert(filePath); registerDocumentation(filePaths); } @@ -219,7 +218,7 @@ QMap HelpManager::linksForKeyword(const QString &key) QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { const QStringList ®isteredDocs = d->m_helpEngine->registeredDocumentations(); - foreach (const QString &nameSpace, registeredDocs) { + for (const QString &nameSpace : registeredDocs) { db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); if (db.open()) { QSqlQuery query = QSqlQuery(db); @@ -308,7 +307,7 @@ HelpManager::Filters HelpManager::filters() Filters filters; const QStringList &customFilters = d->m_helpEngine->customFilters(); - foreach (const QString &filter, customFilters) + for (const QString &filter : customFilters) filters.insert(filter, d->m_helpEngine->filterAttributes(filter)); return filters; } @@ -325,7 +324,7 @@ HelpManager::Filters HelpManager::fixedFilters() QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { const QStringList ®isteredDocs = d->m_helpEngine->registeredDocumentations(); - foreach (const QString &nameSpace, registeredDocs) { + for (const QString &nameSpace : registeredDocs) { db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); if (db.open()) { QSqlQuery query = QSqlQuery(db); @@ -382,7 +381,7 @@ void HelpManager::setupHelpManager() d->m_helpEngine = new QHelpEngineCore(collectionFilePath(), m_instance); d->m_helpEngine->setupData(); - foreach (const QString &filePath, d->documentationFromInstaller()) + for (const QString &filePath : d->documentationFromInstaller()) d->m_filesToRegister.insert(filePath); d->cleanUpDocumentation(); @@ -409,7 +408,7 @@ void HelpManagerPrivate::cleanUpDocumentation() // mark documentation for removal for which there is no documentation file anymore // mark documentation for removal that is neither user registered, nor marked for registration const QStringList ®isteredDocs = m_helpEngine->registeredDocumentations(); - foreach (const QString &nameSpace, registeredDocs) { + for (const QString &nameSpace : registeredDocs) { const QString filePath = m_helpEngine->documentationFileName(nameSpace); if (!QFileInfo::exists(filePath) || (!m_filesToRegister.contains(filePath) @@ -419,22 +418,28 @@ void HelpManagerPrivate::cleanUpDocumentation() } } -QStringList HelpManagerPrivate::documentationFromInstaller() +HelpManagerPrivate::~HelpManagerPrivate() +{ + writeSettings(); + delete m_helpEngine; + m_helpEngine = nullptr; +} + +const QStringList HelpManagerPrivate::documentationFromInstaller() { QSettings *installSettings = ICore::settings(); - QStringList documentationPaths = installSettings->value(QLatin1String("Help/InstalledDocumentation")) + const QStringList documentationPaths = installSettings->value(QLatin1String("Help/InstalledDocumentation")) .toStringList(); QStringList documentationFiles; - foreach (const QString &path, documentationPaths) { + for (const QString &path : documentationPaths) { QFileInfo pathInfo(path); if (pathInfo.isFile() && pathInfo.isReadable()) { documentationFiles << pathInfo.absoluteFilePath(); } else if (pathInfo.isDir()) { - QDir dir(path); - foreach (const QFileInfo &fileInfo, dir.entryInfoList(QStringList(QLatin1String("*.qch")), - QDir::Files | QDir::Readable)) { + const QFileInfoList files(QDir(path).entryInfoList(QStringList(QLatin1String("*.qch")), + QDir::Files | QDir::Readable)); + for (const QFileInfo &fileInfo : files) documentationFiles << fileInfo.absoluteFilePath(); - } } } return documentationFiles; diff --git a/src/plugins/coreplugin/helpmanager.h b/src/plugins/coreplugin/helpmanager.h index 07b22cbe9e8..d2205444962 100644 --- a/src/plugins/coreplugin/helpmanager.h +++ b/src/plugins/coreplugin/helpmanager.h @@ -99,7 +99,7 @@ signals: void helpRequested(const QUrl &url, Core::HelpManager::HelpViewerLocation location); private: - explicit HelpManager(QObject *parent = 0); + explicit HelpManager(QObject *parent = nullptr); ~HelpManager(); static void setupHelpManager(); diff --git a/src/plugins/cpaster/kdepasteprotocol.cpp b/src/plugins/cpaster/kdepasteprotocol.cpp index c5c09cb9bf5..bafe229e3d6 100644 --- a/src/plugins/cpaster/kdepasteprotocol.cpp +++ b/src/plugins/cpaster/kdepasteprotocol.cpp @@ -286,7 +286,8 @@ void KdePasteProtocol::paste(const QString &text, Protocol::ContentType ct, int QString details = tr("Pasting to KDE paster needs authentication.
" "Enter your KDE Identity credentials to continue."); if (m_loginFailed) - details.prepend(tr("Login failed

")); + details.prepend("" + + tr("Login failed") + "

"); AuthenticationDialog authDialog(details, Core::ICore::dialogParent()); authDialog.setWindowTitle("Authenticate for KDE paster"); diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index df579b8a602..3488be43047 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -447,9 +447,9 @@ BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent) m_labelUseFullPath->setToolTip(pathToolTip); const QString moduleToolTip = - tr("

Specifying the module (base name of the library or executable) " - "for function or file type breakpoints can significantly speed up " - "debugger startup times (CDB, LLDB)."); + "

" + tr("Specifying the module (base name of the library or executable) " + "for function or file type breakpoints can significantly speed up " + "debugger startup times (CDB, LLDB).") + "

"; m_lineEditModule = new QLineEdit(groupBoxAdvanced); m_lineEditModule->setToolTip(moduleToolTip); m_labelModule = new QLabel(tr("&Module:"), groupBoxAdvanced); @@ -457,8 +457,8 @@ BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent) m_labelModule->setToolTip(moduleToolTip); const QString commandsToolTip = - tr("

Debugger commands to be executed when the breakpoint is hit. " - "This feature is only available for GDB."); + "

" + tr("Debugger commands to be executed when the breakpoint is hit. " + "This feature is only available for GDB.") + "

"; m_textEditCommands = new SmallTextEdit(groupBoxAdvanced); m_textEditCommands->setToolTip(commandsToolTip); m_labelCommands = new QLabel(tr("&Commands:"), groupBoxAdvanced); diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index 7aeb3a7cb5e..d78e1b89481 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -320,10 +320,11 @@ QWidget *LocalsAndExpressionsOptionsPage::widget() auto groupBoxCustomDumperCommands = new QGroupBox(debuggingHelperGroupBox); groupBoxCustomDumperCommands->setTitle(tr("Debugging Helper Customization")); - groupBoxCustomDumperCommands->setToolTip(tr( - "

Python commands entered here will be executed after built-in " - "debugging helpers have been loaded and fully initialized. You can load additional " - "debugging helpers or modify existing ones here.

")); + groupBoxCustomDumperCommands->setToolTip("

" + + tr("Python commands entered here will be executed after built-in " + "debugging helpers have been loaded and fully initialized. You can " + "load additional debugging helpers or modify existing ones here.") + + "

"); auto textEditCustomDumperCommands = new QTextEdit(groupBoxCustomDumperCommands); textEditCustomDumperCommands->setAcceptRichText(false); diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 9f543f01ab7..f78f9807995 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -401,10 +401,11 @@ void DebuggerItemConfigWidget::load(const DebuggerItem *item) const bool is64bit = is64BitWindowsSystem(); const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version"); //: Label text for path configuration. %2 is "x-bit version". - text = tr("

Specify the path to the " - "Windows Console Debugger executable" - " (%2) here.

"""). - arg(QLatin1String(debuggingToolsWikiLinkC), versionString); + text = "

" + + tr("Specify the path to the " + "Windows Console Debugger executable" + " (%2) here.").arg(QLatin1String(debuggingToolsWikiLinkC), versionString) + + "

"; versionCommand = QLatin1String("-version"); } else { versionCommand = QLatin1String("--version"); diff --git a/src/plugins/modeleditor/actionhandler.cpp b/src/plugins/modeleditor/actionhandler.cpp index d03730ccfe0..7af2c6c5fbc 100644 --- a/src/plugins/modeleditor/actionhandler.cpp +++ b/src/plugins/modeleditor/actionhandler.cpp @@ -218,7 +218,8 @@ void ActionHandler::createActions() registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, nullptr, Core::Context(), true, tr("Add Canvas Diagram")); d->synchronizeBrowserAction = registerCommand( Constants::ACTION_SYNC_BROWSER, nullptr, Core::Context(), true, - tr("Synchronize Browser and Diagram
Press&Hold for options"))->action(); + tr("Synchronize Browser and Diagram") + "
" + + tr("Press && Hold for options") + "")->action(); d->synchronizeBrowserAction->setIcon(Utils::Icons::LINK.icon()); d->synchronizeBrowserAction->setCheckable(true); diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp index 52501649cd8..c8c0f1b1c30 100644 --- a/src/plugins/modeleditor/componentviewcontroller.cpp +++ b/src/plugins/modeleditor/componentviewcontroller.cpp @@ -344,7 +344,7 @@ bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source aToB = qmt::MDependency::BToA; bToA = qmt::MDependency::AToB; } - foreach (const qmt::Handle &handle, source->relations()) { + for (const qmt::Handle &handle : source->relations()) { if (auto dependency = dynamic_cast(handle.target())) { if (dependency->source() == source->uid() && dependency->target() == target->uid() diff --git a/src/plugins/modeleditor/modelindexer.cpp b/src/plugins/modeleditor/modelindexer.cpp index 4df25cd54ed..aa84b689548 100644 --- a/src/plugins/modeleditor/modelindexer.cpp +++ b/src/plugins/modeleditor/modelindexer.cpp @@ -215,7 +215,7 @@ ModelIndexer::DiagramsCollectorVisitor::DiagramsCollectorVisitor(IndexedModel *i void ModelIndexer::DiagramsCollectorVisitor::visitMObject(const qmt::MObject *object) { - foreach (const qmt::Handle &child, object->children()) { + for (const qmt::Handle &child : object->children()) { if (child.hasTarget()) child.target()->accept(this); } diff --git a/src/plugins/modeleditor/pxnodecontroller.cpp b/src/plugins/modeleditor/pxnodecontroller.cpp index bdbadae8a07..c1181fba983 100644 --- a/src/plugins/modeleditor/pxnodecontroller.cpp +++ b/src/plugins/modeleditor/pxnodecontroller.cpp @@ -205,7 +205,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore qmt::MPackage *package = roots.takeFirst(); // append all sub-packages of the same level as next root packages - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) roots.append(childPackage); @@ -219,7 +219,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore QString relativeSearchId = qmt::NameController::calcElementNameSearchId( relativeElements.at(relativeIndex)); found = false; - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { @@ -241,7 +241,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore if (diagram) return diagram; // find first diagram within deepest package - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto diagram = dynamic_cast(handle.target())) return diagram; diff --git a/src/plugins/modeleditor/pxnodeutilities.cpp b/src/plugins/modeleditor/pxnodeutilities.cpp index 4deec764ccb..7e6c986a509 100644 --- a/src/plugins/modeleditor/pxnodeutilities.cpp +++ b/src/plugins/modeleditor/pxnodeutilities.cpp @@ -120,7 +120,7 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath( roots.takeFirst(); // append all sub-packages of the same level as next root packages - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) { // only accept root packages in the same path as the suggested parent package @@ -139,7 +139,7 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath( QString relativeSearchId = qmt::NameController::calcElementNameSearchId( relativeElements.at(relativeIndex)); found = false; - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { @@ -198,7 +198,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement qmt::MPackage *package = roots.takeFirst(); // append all sub-packages of the same level as next root packages - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) roots.append(childPackage); @@ -212,7 +212,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement QString relativeSearchId = qmt::NameController::calcElementNameSearchId( relativeElements.at(relativeIndex)); found = false; - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { if (auto childPackage = dynamic_cast(handle.target())) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { @@ -230,7 +230,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement QMT_CHECK(relativeIndex >= relativeElements.size()); // chain was found so check for given object within deepest package QString objectSearchId = qmt::NameController::calcElementNameSearchId(object->name()); - foreach (const qmt::Handle &handle, package->children()) { + for (const qmt::Handle &handle : package->children()) { if (handle.hasTarget()) { qmt::MObject *target = handle.target(); if (typeid(*target) == typeid(*object) diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp index e63a28e0bdc..8595b7dfbfa 100644 --- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp @@ -73,7 +73,7 @@ const char QBS_RC_PREFIX[] = "Qbs.RunConfiguration:"; static QString rcNameSeparator() { return QLatin1String("---Qbs.RC.NameSeparator---"); } -static QString usingLibraryPathsKey() { return "Qbs.RunConfiguration.UsingLibraryPaths"; } +static QString usingLibraryPathsKey() { return QString("Qbs.RunConfiguration.UsingLibraryPaths"); } const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &uniqeName) { diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 1bf7725b989..81313c43022 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -29,32 +29,38 @@ #include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include #include +#include +#include #include #include -#include "itemlibrarymodel.h" -#include "itemlibraryimageprovider.h" -#include -#include -#include "rewritingexception.h" +#include #include #include #include -#include #include -#include #include +#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include #include @@ -69,6 +75,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : m_itemIconSize(24, 24), m_itemViewQuickWidget(new QQuickWidget), m_resourcesView(new ItemLibraryResourceView(this)), + m_importTagsWidget(new QWidget(this)), m_filterFlag(QtBasic) { m_compressionTimer.setInterval(200); @@ -126,7 +133,6 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2); connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter); - m_stackedWidget = new QStackedWidget(this); m_stackedWidget->addWidget(m_itemViewQuickWidget.data()); m_stackedWidget->addWidget(m_resourcesView.data()); @@ -141,7 +147,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : layout->addWidget(tabBar, 0, 0, 1, 1); layout->addWidget(spacer, 1, 0); layout->addWidget(lineEditFrame, 2, 0, 1, 1); - layout->addWidget(m_stackedWidget.data(), 3, 0, 1, 1); + layout->addWidget(m_importTagsWidget.data(), 3, 0, 1, 1); + layout->addWidget(m_stackedWidget.data(), 4, 0, 1, 1); setSearchFilter(QString()); @@ -154,6 +161,9 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel); + auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); + flowLayout->setMargin(4); + // init the first load of the QML UI elements reloadQmlSource(); } @@ -175,12 +185,8 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo) void ItemLibraryWidget::updateImports() { - if (m_model) { - QStringList imports; - foreach (const Import &import, m_model->imports()) - if (import.isLibraryImport()) - imports << import.url(); - } + if (m_model) + setupImportTagWidget(); } void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget) @@ -223,10 +229,16 @@ void ItemLibraryWidget::setModel(Model *model) void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index) { - if (index == 2) + if (index == 2) { m_filterLineEdit->setVisible(false); - else + m_importTagsWidget->setVisible(true); + } if (index == 1) { m_filterLineEdit->setVisible(true); + m_importTagsWidget->setVisible(false); + } else { + m_filterLineEdit->setVisible(true); + m_importTagsWidget->setVisible(true); + } m_stackedWidget->setCurrentIndex(index); } @@ -249,6 +261,38 @@ void ItemLibraryWidget::reloadQmlSource() m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlFilePath)); } +void ItemLibraryWidget::setupImportTagWidget() +{ + QTC_ASSERT(m_model, return); + + const QStringList imports = m_model->metaInfo().itemLibraryInfo()->showTagsForImports(); + + qDeleteAll(m_importTagsWidget->findChildren("", Qt::FindDirectChildrenOnly)); + + auto *flowLayout = m_importTagsWidget->layout(); + + auto createButton = [this](const QString &import) { + auto button = new QToolButton(m_importTagsWidget.data()); + auto font = button->font(); + font.setPixelSize(9); + button->setFont(font); + button->setIcon(Utils::Icons::PLUS.icon()); + button->setText(import); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + connect(button, &QToolButton::clicked, this, [this, import]() { + addPossibleImport(import); + }); + return button; + }; + + for (const QString &importPath : imports) { + const Import import = Import::createLibraryImport(importPath); + if (!m_model->hasImport(import, true, true) + && m_model->isImportPossible(import, true, true)) + flowLayout->addWidget(createButton(importPath)); + } +} + void ItemLibraryWidget::updateModel() { m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data()); @@ -293,8 +337,7 @@ void ItemLibraryWidget::startDragAndDrop(QQuickItem *mouseArea, QVariant itemLib void ItemLibraryWidget::removeImport(const QString &name) { - if (!m_model) - return; + QTC_ASSERT(m_model, return); QList toBeRemovedImportList; foreach (const Import &import, m_model->imports()) @@ -306,9 +349,21 @@ void ItemLibraryWidget::removeImport(const QString &name) void ItemLibraryWidget::addImport(const QString &name, const QString &version) { - if (!m_model) - return; + QTC_ASSERT(m_model, return); m_model->changeImports({Import::createLibraryImport(name, version)}, {}); } +void ItemLibraryWidget::addPossibleImport(const QString &name) +{ + QTC_ASSERT(m_model, return); + const Import import = m_model->highestPossibleImport(name); + try { + m_model->changeImports({Import::createLibraryImport(name, import.version())}, {}); + } + catch (const RewritingException &e) { + e.showException(); + } + QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); +} + } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index a831b4c5fd1..8ca7467bfee 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -86,18 +86,17 @@ public: Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId); -protected: - void removeImport(const QString &name); - void addImport(const QString &name, const QString &version); - signals: void itemActivated(const QString& itemName); private: void setCurrentIndexOfStackedWidget(int index); void reloadQmlSource(); + void setupImportTagWidget(); + void removeImport(const QString &name); + void addImport(const QString &name, const QString &version); + void addPossibleImport(const QString &name); -private: QTimer m_compressionTimer; QSize m_itemIconSize; @@ -111,6 +110,8 @@ private: QPointer m_filterLineEdit; QScopedPointer m_itemViewQuickWidget; QScopedPointer m_resourcesView; + QScopedPointer m_importTagsWidget; + QShortcut *m_qmlSourceUpdateShortcut; QPointer m_model; diff --git a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h index 6233b315788..8b743352091 100644 --- a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h +++ b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h @@ -106,6 +106,12 @@ public: bool containsEntry(const ItemLibraryEntry &entry); void clearEntries(); + QStringList blacklistImports() const; + QStringList showTagsForImports() const; + + void addBlacklistImports(const QStringList &list); + void addShowTagsForImports(const QStringList &list); + signals: void entriesChanged(); @@ -116,6 +122,9 @@ private: // functions private: // variables QHash m_nameToEntryHash; QPointer m_baseInfo; + + QStringList m_blacklistImports; + QStringList m_showTagsForImports; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/include/metainforeader.h b/src/plugins/qmldesigner/designercore/include/metainforeader.h index de8e2206983..375d161885e 100644 --- a/src/plugins/qmldesigner/designercore/include/metainforeader.h +++ b/src/plugins/qmldesigner/designercore/include/metainforeader.h @@ -66,6 +66,7 @@ private: ParsingDocument, ParsingMetaInfo, ParsingType, + ParsingImports, ParsingItemLibrary, ParsingHints, ParsingProperty, @@ -81,6 +82,7 @@ private: ParserSate readQmlSourceElement(const QString &name); void readTypeProperty(const QString &name, const QVariant &value); + void readImportsProperty(const QString &name, const QVariant &value); void readItemLibraryEntryProperty(const QString &name, const QVariant &value); void readPropertyProperty(const QString &name, const QVariant &value); void readQmlSourceProperty(const QString &name, const QVariant &value); diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index d5f16be0ed4..d959f4eb0fc 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -99,8 +99,10 @@ public: void setPossibleImports(const QList &possibleImports); void setUsedImports(const QList &usedImports); bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); + bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); QString pathForImport(const Import &import); QStringList importPaths() const; + Import highestPossibleImport(const QString &importPath); RewriterView *rewriterView() const; void setRewriterView(RewriterView *rewriterView); diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp index d18f252c884..30fe3b4cc27 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp @@ -337,6 +337,32 @@ void ItemLibraryInfo::clearEntries() emit entriesChanged(); } +QStringList ItemLibraryInfo::blacklistImports() const +{ + auto list = m_blacklistImports; + if (m_baseInfo) + list.append(m_baseInfo->m_blacklistImports); + return list; +} + +QStringList ItemLibraryInfo::showTagsForImports() const +{ + auto list = m_showTagsForImports; + if (m_baseInfo) + list.append(m_baseInfo->m_showTagsForImports); + return list; +} + +void ItemLibraryInfo::addBlacklistImports(const QStringList &list) +{ + m_blacklistImports.append(list); +} + +void ItemLibraryInfo::addShowTagsForImports(const QStringList &list) +{ + m_showTagsForImports.append(list); +} + void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo) { m_baseInfo = baseInfo; diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp index 1caff4817e3..9df2a85c7d5 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp @@ -40,6 +40,7 @@ enum { const QString rootElementName = QStringLiteral("MetaInfo"); const QString typeElementName = QStringLiteral("Type"); +const QString importsElementName = QStringLiteral("Imports"); const QString ItemLibraryEntryElementName = QStringLiteral("ItemLibraryEntry"); const QString HintsElementName = QStringLiteral("Hints"); const QString QmlSourceElementName = QStringLiteral("QmlSource"); @@ -106,6 +107,7 @@ void MetaInfoReader::elementEnd() switch (parserState()) { case ParsingMetaInfo: setParserState(Finished); break; case ParsingType: setParserState(ParsingMetaInfo); break; + case ParsingImports: setParserState(ParsingMetaInfo); break; case ParsingItemLibrary: keepCurrentItemLibraryEntry(); setParserState((ParsingType)); break; case ParsingHints: setParserState(ParsingType); break; case ParsingProperty: insertProperty(); setParserState(ParsingItemLibrary); break; @@ -123,6 +125,7 @@ void MetaInfoReader::propertyDefinition(const QString &name, const QVariant &val { switch (parserState()) { case ParsingType: readTypeProperty(name, value); break; + case ParsingImports: readImportsProperty(name, value); break; case ParsingItemLibrary: readItemLibraryEntryProperty(name, value); break; case ParsingProperty: readPropertyProperty(name, value); break; case ParsingQmlSource: readQmlSourceProperty(name, value); break; @@ -156,6 +159,8 @@ MetaInfoReader::ParserSate MetaInfoReader::readMetaInfoRootElement(const QString m_currentIcon.clear(); m_currentHints.clear(); return ParsingType; + } else if (name == importsElementName) { + return ParsingImports; } else { addErrorInvalidType(name); return Error; @@ -207,6 +212,20 @@ MetaInfoReader::ParserSate MetaInfoReader::readQmlSourceElement(const QString &n return Error; } +void MetaInfoReader::readImportsProperty(const QString &name, const QVariant &value) +{ + const auto values = value.toStringList(); + + if (name == "blacklistImports" && !values.isEmpty()) { + m_metaInfo.itemLibraryInfo()->addBlacklistImports(values); + } else if (name == "showTagsForImports" && !values.isEmpty()) { + m_metaInfo.itemLibraryInfo()->addShowTagsForImports(values); + } else { + addError(tr("Unknown property for Imports %1").arg(name), currentSourceLocation()); + setParserState(Error); + } +} + void MetaInfoReader::readTypeProperty(const QString &name, const QVariant &value) { if (name == QLatin1String("name")) { @@ -242,7 +261,7 @@ void MetaInfoReader::readItemLibraryEntryProperty(const QString &name, const QVa void MetaInfoReader::readPropertyProperty(const QString &name, const QVariant &value) { if (name == QStringLiteral("name")) { - m_currentPropertyName = value.toByteArray(); + m_currentPropertyName = value.toByteArray(); } else if (name == QStringLiteral("type")) { m_currentPropertyType = value.toString(); } else if (name == QStringLiteral("value")) { diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 70dd0f4fd43..8c79fee4c71 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1874,6 +1874,8 @@ void Model::setUsedImports(const QList &usedImports) static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion) { + if (version2.isEmpty()) + return true; if (version1 == version2) return true; if (!allowHigherVersion) @@ -1921,6 +1923,26 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe return false; } +bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowHigherVersion) +{ + if (imports().contains(import)) + return true; + if (!ignoreAlias) + return false; + + const auto importList = possibleImports(); + + for (const Import &possibleImport : importList) { + if (possibleImport.isFileImport() && import.isFileImport()) + if (possibleImport.file() == import.file()) + return true; + if (possibleImport.isLibraryImport() && import.isLibraryImport()) + if (possibleImport.url() == import.url() && compareVersions(possibleImport.version(), import.version(), allowHigherVersion)) + return true; + } + return false; +} + QString Model::pathForImport(const Import &import) { if (!rewriterView()) @@ -1944,6 +1966,20 @@ QStringList Model::importPaths() const return importPathList; } +Import Model::highestPossibleImport(const QString &importPath) +{ + Import candidate; + + for (const Import &import : possibleImports()) { + if (import.url() == importPath) { + if (candidate.isEmpty() || compareVersions(import.version(), candidate.version(), true)) + candidate = import; + } + } + + return candidate; +} + RewriterView *Model::rewriterView() const { return d->rewriterView(); diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index f94cd99fb7f..3f4e60fb32e 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -29,16 +29,18 @@ #include "modelnodepositionstorage.h" #include "abstractproperty.h" #include "bindingproperty.h" +#include "enumeration.h" #include "filemanager/firstdefinitionfinder.h" #include "filemanager/objectlengthcalculator.h" #include "filemanager/qmlrefactoring.h" +#include "itemlibraryinfo.h" +#include "metainfo.h" +#include "nodemetainfo.h" #include "nodeproperty.h" +#include "signalhandlerproperty.h" #include "propertyparser.h" #include "rewriterview.h" #include "variantproperty.h" -#include "signalhandlerproperty.h" -#include "nodemetainfo.h" -#include "enumeration.h" #include #include @@ -790,7 +792,20 @@ static bool isLatestImportVersion(const ImportKey &importKey, const QHashmetaInfo().itemLibraryInfo()->blacklistImports()) { + if (importKey.libraryQualifiedPath().contains(filter)) + return true; + } + + } + + return false; +} + +static bool isBlacklistImport(const ImportKey &importKey, Model *model) { const QString &importPathFirst = importKey.splitPath.constFirst(); const QString &importPathLast = importKey.splitPath.constLast(); @@ -799,6 +814,7 @@ static bool isBlacklistImport(const ImportKey &importKey) || importPathFirst == QStringLiteral("QtQml") || (importPathFirst == QStringLiteral("QtQuick") && importPathLast == QStringLiteral("PrivateWidgets")) || importPathLast == QStringLiteral("Private") + || importPathLast == QStringLiteral("private") || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Particles") //Unsupported || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Dialogs") //Unsupported || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Controls.Styles") //Unsupported @@ -813,14 +829,16 @@ static bool isBlacklistImport(const ImportKey &importKey) || importKey.libraryQualifiedPath() == QStringLiteral("QtBluetooth") || importKey.libraryQualifiedPath() == QStringLiteral("Enginio") - || (importKey.splitPath.count() == 1 && importPathFirst == QStringLiteral("QtQuick")); // Don't show Quick X.X imports + // Don't show Quick X.X imports + || (importKey.splitPath.count() == 1 && importPathFirst == QStringLiteral("QtQuick")) + || filterByMetaInfo(importKey, model); } -static QHash filterPossibleImportKeys(const QSet &possibleImportKeys) +static QHash filterPossibleImportKeys(const QSet &possibleImportKeys, Model *model) { QHash filteredPossibleImportKeys; foreach (const ImportKey &importKey, possibleImportKeys) { - if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey)) + if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey, model)) filteredPossibleImportKeys.insert(importKey.path(), importKey); } @@ -868,7 +886,8 @@ static QList generatePossibleLibraryImports(const QHash filteredPossibleImportKeys = filterPossibleImportKeys(snapshot.importDependencies()->libraryImports(viewContext)); + QHash filteredPossibleImportKeys = + filterPossibleImportKeys(snapshot.importDependencies()->libraryImports(viewContext), m_rewriterView->model()); removeUsedImports(filteredPossibleImportKeys, m_scopeChain->context()->imports(m_document.data())->all());