QmlDesigner: Add features to .metainfo file

Allows black listing and white listing of imports.
The .metainfo files of QML and QmlDesigner plugins currently
define the contents of the item library.
This patch also allows to blacklist imports in the import manager
and to define important imports that can e. g. be added using a tag list.

Change-Id: I358cf7abe6dc68d54f33488ae7d164fc10e5ea94
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Thomas Hartmann
2018-01-10 09:36:56 +01:00
parent a40f11e071
commit f00b805da1
5 changed files with 84 additions and 9 deletions

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

@@ -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

@@ -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());