Merge remote-tracking branch 'origin/4.6'

Conflicts:
	src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp

Change-Id: I4c619efd7c1060ffd759df44a03a111269d3478d
This commit is contained in:
Eike Ziller
2018-01-24 13:41:34 +01:00
29 changed files with 419 additions and 238 deletions

View File

@@ -1180,7 +1180,7 @@ void PropertiesView::MView::onClassMembersStatusChanged(bool valid)
if (valid) if (valid)
m_classMembersStatusLabel->clear(); m_classMembersStatusLabel->clear();
else else
m_classMembersStatusLabel->setText(tr("<font color=red>Invalid syntax.</font>")); m_classMembersStatusLabel->setText("<font color=red>" + tr("Invalid syntax.") + "</font>");
} }
void PropertiesView::MView::onParseClassMembers() void PropertiesView::MView::onParseClassMembers()

View File

@@ -866,10 +866,10 @@ TreeItem *TreeItem::reverseFindAnyChild(const std::function<bool (TreeItem *)> &
{ {
auto end = m_children.rend(); auto end = m_children.rend();
for (auto it = m_children.rbegin(); it != end; ++it) { for (auto it = m_children.rbegin(); it != end; ++it) {
if (pred(*it))
return *it;
if (TreeItem *found = (*it)->reverseFindAnyChild(pred)) if (TreeItem *found = (*it)->reverseFindAnyChild(pred))
return found; return found;
if (pred(*it))
return *it;
} }
return nullptr; return nullptr;
} }

View File

@@ -82,7 +82,8 @@ public:
void forSelectedChildren(const std::function<bool(TreeItem *)> &pred) const; void forSelectedChildren(const std::function<bool(TreeItem *)> &pred) const;
void forAllChildren(const std::function<void(TreeItem *)> &pred) const; void forAllChildren(const std::function<void(TreeItem *)> &pred) const;
TreeItem *findAnyChild(const std::function<bool(TreeItem *)> &pred) const; TreeItem *findAnyChild(const std::function<bool(TreeItem *)> &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<bool(TreeItem *)> &pred) const; TreeItem *reverseFindAnyChild(const std::function<bool(TreeItem *)> &pred) const;
// Levels are 1-based: Child at Level 1 is an immediate child. // Levels are 1-based: Child at Level 1 is an immediate child.

View File

@@ -405,7 +405,7 @@ void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart; const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart;
if (isProjectPartLoadedOrIsFallback(projectPart)) { if (isProjectPartLoadedOrIsFallback(projectPart)) {
registerTranslationUnitForEditor(projectPart.data()); registerTranslationUnitForEditor(*projectPart.data());
m_projectPart = projectPart; m_projectPart = projectPart;
m_isProjectFile = m_parser->projectPartInfo().hints m_isProjectFile = m_parser->projectPartInfo().hints
@@ -421,7 +421,132 @@ void ClangEditorDocumentProcessor::onParserFinished()
updateProjectPartAndTranslationUnitForEditor(); 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 // On registration we send the document content immediately as an unsaved
// file, because // file, because
@@ -433,12 +558,13 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::Pr
// like on Windows. // like on Windows.
if (m_projectPart) { if (m_projectPart) {
if (projectPart->id() == m_projectPart->id()) if (projectPart.id() == m_projectPart->id())
return; return;
} }
const FileOptionsBuilder fileOptions(filePath(), projectPart);
m_communicator.registerTranslationUnitsForEditor( m_communicator.registerTranslationUnitsForEditor(
{fileContainerWithArgumentsAndDocumentContent(projectPart)}); {fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())});
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision()); ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());
} }
@@ -503,137 +629,12 @@ ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
Utf8String::fromByteArray(codecName)); 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(), return ClangBackEnd::FileContainer(filePath(),
projectPart->id(), projectPart.id(),
Utf8StringVector(theFileArguments), Utf8StringVector(fileOptions),
textDocument()->toPlainText(), textDocument()->toPlainText(),
true, true,
revision()); revision());

View File

@@ -104,14 +104,14 @@ public:
private: private:
void onParserFinished(); void onParserFinished();
void updateProjectPartAndTranslationUnitForEditor(); void updateProjectPartAndTranslationUnitForEditor();
void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart); void registerTranslationUnitForEditor(CppTools::ProjectPart &projectPart);
void updateTranslationUnitIfProjectPartExists(); void updateTranslationUnitIfProjectPartExists();
void requestDocumentAnnotations(const QString &projectpartId); void requestDocumentAnnotations(const QString &projectpartId);
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget( HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic); const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const; ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const;
ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent( ClangBackEnd::FileContainer fileContainerWithOptionsAndDocumentContent(
CppTools::ProjectPart *projectPart) const; CppTools::ProjectPart &projectPart, const QStringList &fileOptions) const;
ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const; ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const;
private: private:

View File

@@ -39,9 +39,10 @@ VersionSelector::VersionSelector(const QString &fileName, const QString &message
{ {
ui->setupUi(this); ui->setupUi(this);
ui->headerLabel->setText(ui->headerLabel->text().arg(fileName)); ui->headerLabel->setText(ui->headerLabel->text().arg(fileName));
ui->loadedText->setHtml(tr("<html><head/><body><p><b>Note: You will not be able to check in " ui->loadedText->setHtml("<html><head/><body><p><b>"
"this file without merging the changes (not supported by the " + tr("Note: You will not be able to check in this file without merging "
"plugin)</b></p></body></html>")); "the changes (not supported by the plugin)")
+ "</b></p></body></html>");
m_stream = new QTextStream(message.toLocal8Bit(), QIODevice::ReadOnly | QIODevice::Text); m_stream = new QTextStream(message.toLocal8Bit(), QIODevice::ReadOnly | QIODevice::Text);
QString line; QString line;
while (!m_stream->atEnd() && !line.contains(QLatin1String("1) Loaded version"))) while (!m_stream->atEnd() && !line.contains(QLatin1String("1) Loaded version")))

View File

@@ -450,9 +450,9 @@ KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k
} else { } else {
message = tr("Generator: %1<br>Extra generator: %2").arg(info.generator).arg(info.extraGenerator); message = tr("Generator: %1<br>Extra generator: %2").arg(info.generator).arg(info.extraGenerator);
if (!info.platform.isEmpty()) if (!info.platform.isEmpty())
message += tr("<br>Platform: %1").arg(info.platform); message += "<br/>" + tr("Platform: %1").arg(info.platform);
if (!info.toolset.isEmpty()) if (!info.toolset.isEmpty())
message += tr("<br>Toolset: %1").arg(info.toolset); message += "<br/>" + tr("Toolset: %1").arg(info.toolset);
} }
return ItemList() << qMakePair(tr("CMake Generator"), message); return ItemList() << qMakePair(tr("CMake Generator"), message);
} }

View File

@@ -115,7 +115,7 @@ void CMakeTargetNode::setTargetInformation(const QList<Utils::FileName> &artifac
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts"); m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts");
} else { } else {
const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput); const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput);
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:<br>") m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:") + "<br>"
+ tmp.join("<br>"); + tmp.join("<br>");
} }
} }

View File

@@ -53,10 +53,12 @@ namespace Core {
struct HelpManagerPrivate struct HelpManagerPrivate
{ {
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 readSettings();
void writeSettings(); void writeSettings();
void cleanUpDocumentation(); void cleanUpDocumentation();
@@ -73,8 +75,8 @@ struct HelpManagerPrivate
QSet<QString> m_userRegisteredFiles; QSet<QString> m_userRegisteredFiles;
}; };
static HelpManager *m_instance = 0; static HelpManager *m_instance = nullptr;
static HelpManagerPrivate *d; static HelpManagerPrivate *d = nullptr;
static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, "
"d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, "
@@ -102,11 +104,8 @@ HelpManager::HelpManager(QObject *parent) :
HelpManager::~HelpManager() HelpManager::~HelpManager()
{ {
d->writeSettings();
delete d->m_helpEngine;
d->m_helpEngine = 0;
m_instance = 0;
delete d; delete d;
m_instance = nullptr;
} }
HelpManager *HelpManager::instance() HelpManager *HelpManager::instance()
@@ -124,13 +123,13 @@ QString HelpManager::collectionFilePath()
void HelpManager::registerDocumentation(const QStringList &files) void HelpManager::registerDocumentation(const QStringList &files)
{ {
if (d->m_needsSetup) { if (d->m_needsSetup) {
foreach (const QString &filePath, files) for (const QString &filePath : files)
d->m_filesToRegister.insert(filePath); d->m_filesToRegister.insert(filePath);
return; return;
} }
bool docsChanged = false; bool docsChanged = false;
foreach (const QString &file, files) { for (const QString &file : files) {
const QString &nameSpace = d->m_helpEngine->namespaceName(file); const QString &nameSpace = d->m_helpEngine->namespaceName(file);
if (nameSpace.isEmpty()) if (nameSpace.isEmpty())
continue; continue;
@@ -162,13 +161,13 @@ void HelpManager::registerDocumentation(const QStringList &files)
void HelpManager::unregisterDocumentation(const QStringList &nameSpaces) void HelpManager::unregisterDocumentation(const QStringList &nameSpaces)
{ {
if (d->m_needsSetup) { if (d->m_needsSetup) {
foreach (const QString &name, nameSpaces) for (const QString &name : nameSpaces)
d->m_nameSpacesToUnregister.insert(name); d->m_nameSpacesToUnregister.insert(name);
return; return;
} }
bool docsChanged = false; bool docsChanged = false;
foreach (const QString &nameSpace, nameSpaces) { for (const QString &nameSpace : nameSpaces) {
const QString filePath = d->m_helpEngine->documentationFileName(nameSpace); const QString filePath = d->m_helpEngine->documentationFileName(nameSpace);
if (d->m_helpEngine->unregisterDocumentation(nameSpace)) { if (d->m_helpEngine->unregisterDocumentation(nameSpace)) {
docsChanged = true; docsChanged = true;
@@ -185,7 +184,7 @@ void HelpManager::unregisterDocumentation(const QStringList &nameSpaces)
void HelpManager::registerUserDocumentation(const QStringList &filePaths) void HelpManager::registerUserDocumentation(const QStringList &filePaths)
{ {
foreach (const QString &filePath, filePaths) for (const QString &filePath : filePaths)
d->m_userRegisteredFiles.insert(filePath); d->m_userRegisteredFiles.insert(filePath);
registerDocumentation(filePaths); registerDocumentation(filePaths);
} }
@@ -219,7 +218,7 @@ QMap<QString, QUrl> HelpManager::linksForKeyword(const QString &key)
QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name);
if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) {
const QStringList &registeredDocs = d->m_helpEngine->registeredDocumentations(); const QStringList &registeredDocs = d->m_helpEngine->registeredDocumentations();
foreach (const QString &nameSpace, registeredDocs) { for (const QString &nameSpace : registeredDocs) {
db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace));
if (db.open()) { if (db.open()) {
QSqlQuery query = QSqlQuery(db); QSqlQuery query = QSqlQuery(db);
@@ -308,7 +307,7 @@ HelpManager::Filters HelpManager::filters()
Filters filters; Filters filters;
const QStringList &customFilters = d->m_helpEngine->customFilters(); 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)); filters.insert(filter, d->m_helpEngine->filterAttributes(filter));
return filters; return filters;
} }
@@ -325,7 +324,7 @@ HelpManager::Filters HelpManager::fixedFilters()
QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name);
if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) {
const QStringList &registeredDocs = d->m_helpEngine->registeredDocumentations(); const QStringList &registeredDocs = d->m_helpEngine->registeredDocumentations();
foreach (const QString &nameSpace, registeredDocs) { for (const QString &nameSpace : registeredDocs) {
db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace));
if (db.open()) { if (db.open()) {
QSqlQuery query = QSqlQuery(db); QSqlQuery query = QSqlQuery(db);
@@ -382,7 +381,7 @@ void HelpManager::setupHelpManager()
d->m_helpEngine = new QHelpEngineCore(collectionFilePath(), m_instance); d->m_helpEngine = new QHelpEngineCore(collectionFilePath(), m_instance);
d->m_helpEngine->setupData(); d->m_helpEngine->setupData();
foreach (const QString &filePath, d->documentationFromInstaller()) for (const QString &filePath : d->documentationFromInstaller())
d->m_filesToRegister.insert(filePath); d->m_filesToRegister.insert(filePath);
d->cleanUpDocumentation(); 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 for which there is no documentation file anymore
// mark documentation for removal that is neither user registered, nor marked for registration // mark documentation for removal that is neither user registered, nor marked for registration
const QStringList &registeredDocs = m_helpEngine->registeredDocumentations(); const QStringList &registeredDocs = m_helpEngine->registeredDocumentations();
foreach (const QString &nameSpace, registeredDocs) { for (const QString &nameSpace : registeredDocs) {
const QString filePath = m_helpEngine->documentationFileName(nameSpace); const QString filePath = m_helpEngine->documentationFileName(nameSpace);
if (!QFileInfo::exists(filePath) if (!QFileInfo::exists(filePath)
|| (!m_filesToRegister.contains(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(); QSettings *installSettings = ICore::settings();
QStringList documentationPaths = installSettings->value(QLatin1String("Help/InstalledDocumentation")) const QStringList documentationPaths = installSettings->value(QLatin1String("Help/InstalledDocumentation"))
.toStringList(); .toStringList();
QStringList documentationFiles; QStringList documentationFiles;
foreach (const QString &path, documentationPaths) { for (const QString &path : documentationPaths) {
QFileInfo pathInfo(path); QFileInfo pathInfo(path);
if (pathInfo.isFile() && pathInfo.isReadable()) { if (pathInfo.isFile() && pathInfo.isReadable()) {
documentationFiles << pathInfo.absoluteFilePath(); documentationFiles << pathInfo.absoluteFilePath();
} else if (pathInfo.isDir()) { } else if (pathInfo.isDir()) {
QDir dir(path); const QFileInfoList files(QDir(path).entryInfoList(QStringList(QLatin1String("*.qch")),
foreach (const QFileInfo &fileInfo, dir.entryInfoList(QStringList(QLatin1String("*.qch")), QDir::Files | QDir::Readable));
QDir::Files | QDir::Readable)) { for (const QFileInfo &fileInfo : files)
documentationFiles << fileInfo.absoluteFilePath(); documentationFiles << fileInfo.absoluteFilePath();
}
} }
} }
return documentationFiles; return documentationFiles;

View File

@@ -99,7 +99,7 @@ signals:
void helpRequested(const QUrl &url, Core::HelpManager::HelpViewerLocation location); void helpRequested(const QUrl &url, Core::HelpManager::HelpViewerLocation location);
private: private:
explicit HelpManager(QObject *parent = 0); explicit HelpManager(QObject *parent = nullptr);
~HelpManager(); ~HelpManager();
static void setupHelpManager(); static void setupHelpManager();

View File

@@ -286,7 +286,8 @@ void KdePasteProtocol::paste(const QString &text, Protocol::ContentType ct, int
QString details = tr("Pasting to KDE paster needs authentication.<br/>" QString details = tr("Pasting to KDE paster needs authentication.<br/>"
"Enter your KDE Identity credentials to continue."); "Enter your KDE Identity credentials to continue.");
if (m_loginFailed) if (m_loginFailed)
details.prepend(tr("<span style='background-color:LightYellow;color:red'>Login failed</span><br/><br/>")); details.prepend("<span style='background-color:LightYellow;color:red'>"
+ tr("Login failed") + "</span><br/><br/>");
AuthenticationDialog authDialog(details, Core::ICore::dialogParent()); AuthenticationDialog authDialog(details, Core::ICore::dialogParent());
authDialog.setWindowTitle("Authenticate for KDE paster"); authDialog.setWindowTitle("Authenticate for KDE paster");

View File

@@ -447,9 +447,9 @@ BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent)
m_labelUseFullPath->setToolTip(pathToolTip); m_labelUseFullPath->setToolTip(pathToolTip);
const QString moduleToolTip = const QString moduleToolTip =
tr("<p>Specifying the module (base name of the library or executable) " "<p>" + tr("Specifying the module (base name of the library or executable) "
"for function or file type breakpoints can significantly speed up " "for function or file type breakpoints can significantly speed up "
"debugger startup times (CDB, LLDB)."); "debugger startup times (CDB, LLDB).") + "</p>";
m_lineEditModule = new QLineEdit(groupBoxAdvanced); m_lineEditModule = new QLineEdit(groupBoxAdvanced);
m_lineEditModule->setToolTip(moduleToolTip); m_lineEditModule->setToolTip(moduleToolTip);
m_labelModule = new QLabel(tr("&Module:"), groupBoxAdvanced); m_labelModule = new QLabel(tr("&Module:"), groupBoxAdvanced);
@@ -457,8 +457,8 @@ BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent)
m_labelModule->setToolTip(moduleToolTip); m_labelModule->setToolTip(moduleToolTip);
const QString commandsToolTip = const QString commandsToolTip =
tr("<p>Debugger commands to be executed when the breakpoint is hit. " "<p>" + tr("Debugger commands to be executed when the breakpoint is hit. "
"This feature is only available for GDB."); "This feature is only available for GDB.") + "</p>";
m_textEditCommands = new SmallTextEdit(groupBoxAdvanced); m_textEditCommands = new SmallTextEdit(groupBoxAdvanced);
m_textEditCommands->setToolTip(commandsToolTip); m_textEditCommands->setToolTip(commandsToolTip);
m_labelCommands = new QLabel(tr("&Commands:"), groupBoxAdvanced); m_labelCommands = new QLabel(tr("&Commands:"), groupBoxAdvanced);

View File

@@ -320,10 +320,11 @@ QWidget *LocalsAndExpressionsOptionsPage::widget()
auto groupBoxCustomDumperCommands = new QGroupBox(debuggingHelperGroupBox); auto groupBoxCustomDumperCommands = new QGroupBox(debuggingHelperGroupBox);
groupBoxCustomDumperCommands->setTitle(tr("Debugging Helper Customization")); groupBoxCustomDumperCommands->setTitle(tr("Debugging Helper Customization"));
groupBoxCustomDumperCommands->setToolTip(tr( groupBoxCustomDumperCommands->setToolTip("<html><head/><body><p>"
"<html><head/><body><p>Python commands entered here will be executed after built-in " + 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 have been loaded and fully initialized. You can "
"debugging helpers or modify existing ones here.</p></body></html>")); "load additional debugging helpers or modify existing ones here.")
+ "</p></body></html>");
auto textEditCustomDumperCommands = new QTextEdit(groupBoxCustomDumperCommands); auto textEditCustomDumperCommands = new QTextEdit(groupBoxCustomDumperCommands);
textEditCustomDumperCommands->setAcceptRichText(false); textEditCustomDumperCommands->setAcceptRichText(false);

View File

@@ -401,10 +401,11 @@ void DebuggerItemConfigWidget::load(const DebuggerItem *item)
const bool is64bit = is64BitWindowsSystem(); const bool is64bit = is64BitWindowsSystem();
const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version"); const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
//: Label text for path configuration. %2 is "x-bit version". //: Label text for path configuration. %2 is "x-bit version".
text = tr("<html><body><p>Specify the path to the " text = "<html><body><p>"
"<a href=\"%1\">Windows Console Debugger executable</a>" + tr("Specify the path to the "
" (%2) here.</p>""</body></html>"). "<a href=\"%1\">Windows Console Debugger executable</a>"
arg(QLatin1String(debuggingToolsWikiLinkC), versionString); " (%2) here.").arg(QLatin1String(debuggingToolsWikiLinkC), versionString)
+ "</p></body></html>";
versionCommand = QLatin1String("-version"); versionCommand = QLatin1String("-version");
} else { } else {
versionCommand = QLatin1String("--version"); versionCommand = QLatin1String("--version");

View File

@@ -218,7 +218,8 @@ void ActionHandler::createActions()
registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, nullptr, Core::Context(), true, tr("Add Canvas Diagram")); registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, nullptr, Core::Context(), true, tr("Add Canvas Diagram"));
d->synchronizeBrowserAction = registerCommand( d->synchronizeBrowserAction = registerCommand(
Constants::ACTION_SYNC_BROWSER, nullptr, Core::Context(), true, Constants::ACTION_SYNC_BROWSER, nullptr, Core::Context(), true,
tr("Synchronize Browser and Diagram<br><i><small>Press&Hold for options</small></i>"))->action(); tr("Synchronize Browser and Diagram") + "<br><i><small>"
+ tr("Press && Hold for options") + "</small></i>")->action();
d->synchronizeBrowserAction->setIcon(Utils::Icons::LINK.icon()); d->synchronizeBrowserAction->setIcon(Utils::Icons::LINK.icon());
d->synchronizeBrowserAction->setCheckable(true); d->synchronizeBrowserAction->setCheckable(true);

View File

@@ -344,7 +344,7 @@ bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source
aToB = qmt::MDependency::BToA; aToB = qmt::MDependency::BToA;
bToA = qmt::MDependency::AToB; bToA = qmt::MDependency::AToB;
} }
foreach (const qmt::Handle<qmt::MRelation> &handle, source->relations()) { for (const qmt::Handle<qmt::MRelation> &handle : source->relations()) {
if (auto dependency = dynamic_cast<qmt::MDependency *>(handle.target())) { if (auto dependency = dynamic_cast<qmt::MDependency *>(handle.target())) {
if (dependency->source() == source->uid() if (dependency->source() == source->uid()
&& dependency->target() == target->uid() && dependency->target() == target->uid()

View File

@@ -215,7 +215,7 @@ ModelIndexer::DiagramsCollectorVisitor::DiagramsCollectorVisitor(IndexedModel *i
void ModelIndexer::DiagramsCollectorVisitor::visitMObject(const qmt::MObject *object) void ModelIndexer::DiagramsCollectorVisitor::visitMObject(const qmt::MObject *object)
{ {
foreach (const qmt::Handle<qmt::MObject> &child, object->children()) { for (const qmt::Handle<qmt::MObject> &child : object->children()) {
if (child.hasTarget()) if (child.hasTarget())
child.target()->accept(this); child.target()->accept(this);
} }

View File

@@ -205,7 +205,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore
qmt::MPackage *package = roots.takeFirst(); qmt::MPackage *package = roots.takeFirst();
// append all sub-packages of the same level as next root packages // append all sub-packages of the same level as next root packages
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target()))
roots.append(childPackage); roots.append(childPackage);
@@ -219,7 +219,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore
QString relativeSearchId = qmt::NameController::calcElementNameSearchId( QString relativeSearchId = qmt::NameController::calcElementNameSearchId(
relativeElements.at(relativeIndex)); relativeElements.at(relativeIndex));
found = false; found = false;
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) { if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) {
if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) {
@@ -241,7 +241,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore
if (diagram) if (diagram)
return diagram; return diagram;
// find first diagram within deepest package // find first diagram within deepest package
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto diagram = dynamic_cast<qmt::MDiagram *>(handle.target())) if (auto diagram = dynamic_cast<qmt::MDiagram *>(handle.target()))
return diagram; return diagram;

View File

@@ -120,7 +120,7 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath(
roots.takeFirst(); roots.takeFirst();
// append all sub-packages of the same level as next root packages // append all sub-packages of the same level as next root packages
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) { if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) {
// only accept root packages in the same path as the suggested parent package // 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( QString relativeSearchId = qmt::NameController::calcElementNameSearchId(
relativeElements.at(relativeIndex)); relativeElements.at(relativeIndex));
found = false; found = false;
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) { if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) {
if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) {
@@ -198,7 +198,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement
qmt::MPackage *package = roots.takeFirst(); qmt::MPackage *package = roots.takeFirst();
// append all sub-packages of the same level as next root packages // append all sub-packages of the same level as next root packages
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target()))
roots.append(childPackage); roots.append(childPackage);
@@ -212,7 +212,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement
QString relativeSearchId = qmt::NameController::calcElementNameSearchId( QString relativeSearchId = qmt::NameController::calcElementNameSearchId(
relativeElements.at(relativeIndex)); relativeElements.at(relativeIndex));
found = false; found = false;
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) { if (auto childPackage = dynamic_cast<qmt::MPackage *>(handle.target())) {
if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) { if (qmt::NameController::calcElementNameSearchId(childPackage->name()) == relativeSearchId) {
@@ -230,7 +230,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement
QMT_CHECK(relativeIndex >= relativeElements.size()); QMT_CHECK(relativeIndex >= relativeElements.size());
// chain was found so check for given object within deepest package // chain was found so check for given object within deepest package
QString objectSearchId = qmt::NameController::calcElementNameSearchId(object->name()); QString objectSearchId = qmt::NameController::calcElementNameSearchId(object->name());
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) { for (const qmt::Handle<qmt::MObject> &handle : package->children()) {
if (handle.hasTarget()) { if (handle.hasTarget()) {
qmt::MObject *target = handle.target(); qmt::MObject *target = handle.target();
if (typeid(*target) == typeid(*object) if (typeid(*target) == typeid(*object)

View File

@@ -73,7 +73,7 @@ const char QBS_RC_PREFIX[] = "Qbs.RunConfiguration:";
static QString rcNameSeparator() { return QLatin1String("---Qbs.RC.NameSeparator---"); } 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) const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &uniqeName)
{ {

View File

@@ -29,32 +29,38 @@
#include <theme.h> #include <theme.h>
#include <itemlibrarymodel.h>
#include <itemlibraryimageprovider.h>
#include <itemlibraryinfo.h>
#include <metainfo.h>
#include <model.h>
#include <rewritingexception.h>
#include <qmldesignerplugin.h>
#include <utils/flowlayout.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include "itemlibrarymodel.h"
#include "itemlibraryimageprovider.h"
#include <model.h>
#include <metainfo.h>
#include "rewritingexception.h"
#include <QApplication>
#include <QDrag> #include <QDrag>
#include <QFileInfo> #include <QFileInfo>
#include <QFileSystemModel> #include <QFileSystemModel>
#include <QStackedWidget>
#include <QGridLayout> #include <QGridLayout>
#include <QTabBar>
#include <QImageReader> #include <QImageReader>
#include <QMenu>
#include <QMimeData> #include <QMimeData>
#include <QMouseEvent> #include <QMouseEvent>
#include <QWheelEvent>
#include <QMenu>
#include <QApplication>
#include <QTimer>
#include <QShortcut> #include <QShortcut>
#include <QStackedWidget>
#include <QTabBar>
#include <QTimer>
#include <QToolButton>
#include <QWheelEvent>
#include <QQmlContext> #include <QQmlContext>
#include <QQuickItem> #include <QQuickItem>
@@ -69,6 +75,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_itemIconSize(24, 24), m_itemIconSize(24, 24),
m_itemViewQuickWidget(new QQuickWidget), m_itemViewQuickWidget(new QQuickWidget),
m_resourcesView(new ItemLibraryResourceView(this)), m_resourcesView(new ItemLibraryResourceView(this)),
m_importTagsWidget(new QWidget(this)),
m_filterFlag(QtBasic) m_filterFlag(QtBasic)
{ {
m_compressionTimer.setInterval(200); m_compressionTimer.setInterval(200);
@@ -126,7 +133,6 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2); lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2);
connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter); connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter);
m_stackedWidget = new QStackedWidget(this); m_stackedWidget = new QStackedWidget(this);
m_stackedWidget->addWidget(m_itemViewQuickWidget.data()); m_stackedWidget->addWidget(m_itemViewQuickWidget.data());
m_stackedWidget->addWidget(m_resourcesView.data()); m_stackedWidget->addWidget(m_resourcesView.data());
@@ -141,7 +147,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
layout->addWidget(tabBar, 0, 0, 1, 1); layout->addWidget(tabBar, 0, 0, 1, 1);
layout->addWidget(spacer, 1, 0); layout->addWidget(spacer, 1, 0);
layout->addWidget(lineEditFrame, 2, 0, 1, 1); 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()); setSearchFilter(QString());
@@ -154,6 +161,9 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel); 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 // init the first load of the QML UI elements
reloadQmlSource(); reloadQmlSource();
} }
@@ -175,12 +185,8 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
void ItemLibraryWidget::updateImports() void ItemLibraryWidget::updateImports()
{ {
if (m_model) { if (m_model)
QStringList imports; setupImportTagWidget();
foreach (const Import &import, m_model->imports())
if (import.isLibraryImport())
imports << import.url();
}
} }
void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget) void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget)
@@ -223,10 +229,16 @@ void ItemLibraryWidget::setModel(Model *model)
void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index) void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
{ {
if (index == 2) if (index == 2) {
m_filterLineEdit->setVisible(false); m_filterLineEdit->setVisible(false);
else m_importTagsWidget->setVisible(true);
} if (index == 1) {
m_filterLineEdit->setVisible(true); m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(false);
} else {
m_filterLineEdit->setVisible(true);
m_importTagsWidget->setVisible(true);
}
m_stackedWidget->setCurrentIndex(index); m_stackedWidget->setCurrentIndex(index);
} }
@@ -249,6 +261,38 @@ void ItemLibraryWidget::reloadQmlSource()
m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlFilePath)); 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<QWidget*>("", 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() void ItemLibraryWidget::updateModel()
{ {
m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data()); 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) void ItemLibraryWidget::removeImport(const QString &name)
{ {
if (!m_model) QTC_ASSERT(m_model, return);
return;
QList<Import> toBeRemovedImportList; QList<Import> toBeRemovedImportList;
foreach (const Import &import, m_model->imports()) 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) void ItemLibraryWidget::addImport(const QString &name, const QString &version)
{ {
if (!m_model) QTC_ASSERT(m_model, return);
return;
m_model->changeImports({Import::createLibraryImport(name, version)}, {}); 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();
}
} }

View File

@@ -86,18 +86,17 @@ public:
Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId); Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId);
protected:
void removeImport(const QString &name);
void addImport(const QString &name, const QString &version);
signals: signals:
void itemActivated(const QString& itemName); void itemActivated(const QString& itemName);
private: private:
void setCurrentIndexOfStackedWidget(int index); void setCurrentIndexOfStackedWidget(int index);
void reloadQmlSource(); 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; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
@@ -111,6 +110,8 @@ private:
QPointer<Utils::FancyLineEdit> m_filterLineEdit; QPointer<Utils::FancyLineEdit> m_filterLineEdit;
QScopedPointer<QQuickWidget> m_itemViewQuickWidget; QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
QScopedPointer<ItemLibraryResourceView> m_resourcesView; QScopedPointer<ItemLibraryResourceView> m_resourcesView;
QScopedPointer<QWidget> m_importTagsWidget;
QShortcut *m_qmlSourceUpdateShortcut; QShortcut *m_qmlSourceUpdateShortcut;
QPointer<Model> m_model; QPointer<Model> m_model;

View File

@@ -106,6 +106,12 @@ public:
bool containsEntry(const ItemLibraryEntry &entry); bool containsEntry(const ItemLibraryEntry &entry);
void clearEntries(); void clearEntries();
QStringList blacklistImports() const;
QStringList showTagsForImports() const;
void addBlacklistImports(const QStringList &list);
void addShowTagsForImports(const QStringList &list);
signals: signals:
void entriesChanged(); void entriesChanged();
@@ -116,6 +122,9 @@ private: // functions
private: // variables private: // variables
QHash<QString, ItemLibraryEntry> m_nameToEntryHash; QHash<QString, ItemLibraryEntry> m_nameToEntryHash;
QPointer<ItemLibraryInfo> m_baseInfo; QPointer<ItemLibraryInfo> m_baseInfo;
QStringList m_blacklistImports;
QStringList m_showTagsForImports;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -66,6 +66,7 @@ private:
ParsingDocument, ParsingDocument,
ParsingMetaInfo, ParsingMetaInfo,
ParsingType, ParsingType,
ParsingImports,
ParsingItemLibrary, ParsingItemLibrary,
ParsingHints, ParsingHints,
ParsingProperty, ParsingProperty,
@@ -81,6 +82,7 @@ private:
ParserSate readQmlSourceElement(const QString &name); ParserSate readQmlSourceElement(const QString &name);
void readTypeProperty(const QString &name, const QVariant &value); 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 readItemLibraryEntryProperty(const QString &name, const QVariant &value);
void readPropertyProperty(const QString &name, const QVariant &value); void readPropertyProperty(const QString &name, const QVariant &value);
void readQmlSourceProperty(const QString &name, const QVariant &value); void readQmlSourceProperty(const QString &name, const QVariant &value);

View File

@@ -99,8 +99,10 @@ public:
void setPossibleImports(const QList<Import> &possibleImports); void setPossibleImports(const QList<Import> &possibleImports);
void setUsedImports(const QList<Import> &usedImports); void setUsedImports(const QList<Import> &usedImports);
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); 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); QString pathForImport(const Import &import);
QStringList importPaths() const; QStringList importPaths() const;
Import highestPossibleImport(const QString &importPath);
RewriterView *rewriterView() const; RewriterView *rewriterView() const;
void setRewriterView(RewriterView *rewriterView); void setRewriterView(RewriterView *rewriterView);

View File

@@ -337,6 +337,32 @@ void ItemLibraryInfo::clearEntries()
emit entriesChanged(); 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) void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
{ {
m_baseInfo = baseInfo; m_baseInfo = baseInfo;

View File

@@ -40,6 +40,7 @@ enum {
const QString rootElementName = QStringLiteral("MetaInfo"); const QString rootElementName = QStringLiteral("MetaInfo");
const QString typeElementName = QStringLiteral("Type"); const QString typeElementName = QStringLiteral("Type");
const QString importsElementName = QStringLiteral("Imports");
const QString ItemLibraryEntryElementName = QStringLiteral("ItemLibraryEntry"); const QString ItemLibraryEntryElementName = QStringLiteral("ItemLibraryEntry");
const QString HintsElementName = QStringLiteral("Hints"); const QString HintsElementName = QStringLiteral("Hints");
const QString QmlSourceElementName = QStringLiteral("QmlSource"); const QString QmlSourceElementName = QStringLiteral("QmlSource");
@@ -106,6 +107,7 @@ void MetaInfoReader::elementEnd()
switch (parserState()) { switch (parserState()) {
case ParsingMetaInfo: setParserState(Finished); break; case ParsingMetaInfo: setParserState(Finished); break;
case ParsingType: setParserState(ParsingMetaInfo); break; case ParsingType: setParserState(ParsingMetaInfo); break;
case ParsingImports: setParserState(ParsingMetaInfo); break;
case ParsingItemLibrary: keepCurrentItemLibraryEntry(); setParserState((ParsingType)); break; case ParsingItemLibrary: keepCurrentItemLibraryEntry(); setParserState((ParsingType)); break;
case ParsingHints: setParserState(ParsingType); break; case ParsingHints: setParserState(ParsingType); break;
case ParsingProperty: insertProperty(); setParserState(ParsingItemLibrary); break; case ParsingProperty: insertProperty(); setParserState(ParsingItemLibrary); break;
@@ -123,6 +125,7 @@ void MetaInfoReader::propertyDefinition(const QString &name, const QVariant &val
{ {
switch (parserState()) { switch (parserState()) {
case ParsingType: readTypeProperty(name, value); break; case ParsingType: readTypeProperty(name, value); break;
case ParsingImports: readImportsProperty(name, value); break;
case ParsingItemLibrary: readItemLibraryEntryProperty(name, value); break; case ParsingItemLibrary: readItemLibraryEntryProperty(name, value); break;
case ParsingProperty: readPropertyProperty(name, value); break; case ParsingProperty: readPropertyProperty(name, value); break;
case ParsingQmlSource: readQmlSourceProperty(name, value); break; case ParsingQmlSource: readQmlSourceProperty(name, value); break;
@@ -156,6 +159,8 @@ MetaInfoReader::ParserSate MetaInfoReader::readMetaInfoRootElement(const QString
m_currentIcon.clear(); m_currentIcon.clear();
m_currentHints.clear(); m_currentHints.clear();
return ParsingType; return ParsingType;
} else if (name == importsElementName) {
return ParsingImports;
} else { } else {
addErrorInvalidType(name); addErrorInvalidType(name);
return Error; return Error;
@@ -207,6 +212,20 @@ MetaInfoReader::ParserSate MetaInfoReader::readQmlSourceElement(const QString &n
return Error; 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) void MetaInfoReader::readTypeProperty(const QString &name, const QVariant &value)
{ {
if (name == QLatin1String("name")) { 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) void MetaInfoReader::readPropertyProperty(const QString &name, const QVariant &value)
{ {
if (name == QStringLiteral("name")) { if (name == QStringLiteral("name")) {
m_currentPropertyName = value.toByteArray(); m_currentPropertyName = value.toByteArray();
} else if (name == QStringLiteral("type")) { } else if (name == QStringLiteral("type")) {
m_currentPropertyType = value.toString(); m_currentPropertyType = value.toString();
} else if (name == QStringLiteral("value")) { } else if (name == QStringLiteral("value")) {

View File

@@ -1874,6 +1874,8 @@ void Model::setUsedImports(const QList<Import> &usedImports)
static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion) static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
{ {
if (version2.isEmpty())
return true;
if (version1 == version2) if (version1 == version2)
return true; return true;
if (!allowHigherVersion) if (!allowHigherVersion)
@@ -1921,6 +1923,26 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe
return false; 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) QString Model::pathForImport(const Import &import)
{ {
if (!rewriterView()) if (!rewriterView())
@@ -1944,6 +1966,20 @@ QStringList Model::importPaths() const
return importPathList; 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 RewriterView *Model::rewriterView() const
{ {
return d->rewriterView(); return d->rewriterView();

View File

@@ -29,16 +29,18 @@
#include "modelnodepositionstorage.h" #include "modelnodepositionstorage.h"
#include "abstractproperty.h" #include "abstractproperty.h"
#include "bindingproperty.h" #include "bindingproperty.h"
#include "enumeration.h"
#include "filemanager/firstdefinitionfinder.h" #include "filemanager/firstdefinitionfinder.h"
#include "filemanager/objectlengthcalculator.h" #include "filemanager/objectlengthcalculator.h"
#include "filemanager/qmlrefactoring.h" #include "filemanager/qmlrefactoring.h"
#include "itemlibraryinfo.h"
#include "metainfo.h"
#include "nodemetainfo.h"
#include "nodeproperty.h" #include "nodeproperty.h"
#include "signalhandlerproperty.h"
#include "propertyparser.h" #include "propertyparser.h"
#include "rewriterview.h" #include "rewriterview.h"
#include "variantproperty.h" #include "variantproperty.h"
#include "signalhandlerproperty.h"
#include "nodemetainfo.h"
#include "enumeration.h"
#include <qmljs/qmljsevaluate.h> #include <qmljs/qmljsevaluate.h>
#include <qmljs/qmljslink.h> #include <qmljs/qmljslink.h>
@@ -790,7 +792,20 @@ static bool isLatestImportVersion(const ImportKey &importKey, const QHash<QStrin
&& filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion); && filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion);
} }
static bool isBlacklistImport(const ImportKey &importKey) static bool filterByMetaInfo(const ImportKey &importKey, Model *model)
{
if (model) {
for (const QString &filter : model->metaInfo().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 &importPathFirst = importKey.splitPath.constFirst();
const QString &importPathLast = importKey.splitPath.constLast(); const QString &importPathLast = importKey.splitPath.constLast();
@@ -799,6 +814,7 @@ static bool isBlacklistImport(const ImportKey &importKey)
|| importPathFirst == QStringLiteral("QtQml") || importPathFirst == QStringLiteral("QtQml")
|| (importPathFirst == QStringLiteral("QtQuick") && importPathLast == QStringLiteral("PrivateWidgets")) || (importPathFirst == QStringLiteral("QtQuick") && importPathLast == QStringLiteral("PrivateWidgets"))
|| importPathLast == QStringLiteral("Private") || importPathLast == QStringLiteral("Private")
|| importPathLast == QStringLiteral("private")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Particles") //Unsupported || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Particles") //Unsupported
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Dialogs") //Unsupported || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Dialogs") //Unsupported
|| importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Controls.Styles") //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("QtBluetooth")
|| importKey.libraryQualifiedPath() == QStringLiteral("Enginio") || 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<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey> &possibleImportKeys) static QHash<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey> &possibleImportKeys, Model *model)
{ {
QHash<QString, ImportKey> filteredPossibleImportKeys; QHash<QString, ImportKey> filteredPossibleImportKeys;
foreach (const ImportKey &importKey, possibleImportKeys) { foreach (const ImportKey &importKey, possibleImportKeys) {
if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey)) if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey, model))
filteredPossibleImportKeys.insert(importKey.path(), importKey); filteredPossibleImportKeys.insert(importKey.path(), importKey);
} }
@@ -868,7 +886,8 @@ static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QSt
void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext) void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext)
{ {
QHash<QString, ImportKey> filteredPossibleImportKeys = filterPossibleImportKeys(snapshot.importDependencies()->libraryImports(viewContext)); QHash<QString, ImportKey> filteredPossibleImportKeys =
filterPossibleImportKeys(snapshot.importDependencies()->libraryImports(viewContext), m_rewriterView->model());
removeUsedImports(filteredPossibleImportKeys, m_scopeChain->context()->imports(m_document.data())->all()); removeUsedImports(filteredPossibleImportKeys, m_scopeChain->context()->imports(m_document.data())->all());