1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "itemlibraryinfo.h"
27 #include "nodemetainfo.h"
28 
29 #include <QSharedData>
30 
31 #include <utils/algorithm.h>
32 #include <utils/fileutils.h>
33 
34 namespace QmlDesigner {
35 
36 namespace Internal {
37 
38 class ItemLibraryEntryData
39 {
40 public:
41     QString name;
42     TypeName typeName;
43     QString category;
44     int majorVersion{-1};
45     int minorVersion{-1};
46     QString libraryEntryIconPath;
47     QIcon typeIcon = QIcon(":/ItemLibrary/images/item-default-icon.png");
48     QList<PropertyContainer> properties;
49     QString qml;
50     QString qmlSource;
51     QString requiredImport;
52     QHash<QString, QString> hints;
53     QString customComponentSource;
54     QStringList extraFilePaths;
55 };
56 
57 } // namespace Internal
58 
setTypeIcon(const QIcon & icon)59 void ItemLibraryEntry::setTypeIcon(const QIcon &icon)
60 {
61     m_data->typeIcon = icon;
62 }
63 
addProperty(const Property & property)64 void ItemLibraryEntry::addProperty(const Property &property)
65 {
66     m_data->properties.append(property);
67 }
68 
properties() const69 QList<ItemLibraryEntry::Property> ItemLibraryEntry::properties() const
70 {
71     return m_data->properties;
72 }
73 
hints() const74 QHash<QString, QString> ItemLibraryEntry::hints() const
75 {
76     return m_data->hints;
77 }
78 
ItemLibraryEntry()79 ItemLibraryEntry::ItemLibraryEntry() : m_data(new Internal::ItemLibraryEntryData)
80 {
81     m_data->name.clear();
82 }
83 
name() const84 QString ItemLibraryEntry::name() const
85 {
86     return m_data->name;
87 }
88 
typeName() const89 TypeName ItemLibraryEntry::typeName() const
90 {
91     return m_data->typeName;
92 }
93 
qmlPath() const94 QString ItemLibraryEntry::qmlPath() const
95 {
96     return m_data->qml;
97 }
98 
qmlSource() const99 QString ItemLibraryEntry::qmlSource() const
100 {
101     return m_data->qmlSource;
102 }
103 
requiredImport() const104 QString ItemLibraryEntry::requiredImport() const
105 {
106     return m_data->requiredImport;
107 }
108 
customComponentSource() const109 QString ItemLibraryEntry::customComponentSource() const
110 {
111     return m_data->customComponentSource;
112 }
113 
extraFilePaths() const114 QStringList ItemLibraryEntry::extraFilePaths() const
115 {
116     return m_data->extraFilePaths;
117 }
118 
majorVersion() const119 int ItemLibraryEntry::majorVersion() const
120 {
121     return m_data->majorVersion;
122 }
123 
minorVersion() const124 int ItemLibraryEntry::minorVersion() const
125 {
126     return m_data->minorVersion;
127 }
128 
category() const129 QString ItemLibraryEntry::category() const
130 {
131     return m_data->category;
132 }
133 
setCategory(const QString & category)134 void ItemLibraryEntry::setCategory(const QString &category)
135 {
136     m_data->category = category;
137 }
138 
typeIcon() const139 QIcon ItemLibraryEntry::typeIcon() const
140 {
141     return m_data->typeIcon;
142 }
143 
libraryEntryIconPath() const144 QString ItemLibraryEntry::libraryEntryIconPath() const
145 {
146     return m_data->libraryEntryIconPath;
147 }
148 
setName(const QString & name)149 void ItemLibraryEntry::setName(const QString &name)
150 {
151      m_data->name = name;
152 }
153 
setType(const TypeName & typeName,int majorVersion,int minorVersion)154 void ItemLibraryEntry::setType(const TypeName &typeName, int majorVersion, int minorVersion)
155 {
156     m_data->typeName = typeName;
157     m_data->majorVersion = majorVersion;
158     m_data->minorVersion = minorVersion;
159 }
160 
setLibraryEntryIconPath(const QString & iconPath)161 void ItemLibraryEntry::setLibraryEntryIconPath(const QString &iconPath)
162 {
163     m_data->libraryEntryIconPath = iconPath;
164 }
165 
getSourceForUrl(const QString & fileURl)166 static QByteArray getSourceForUrl(const QString &fileURl)
167 {
168     Utils::FileReader fileReader;
169 
170     if (fileReader.fetch(Utils::FilePath::fromString(fileURl)))
171         return fileReader.data();
172     else
173         return Utils::FileReader::fetchQrc(fileURl);
174 }
175 
setQmlPath(const QString & qml)176 void ItemLibraryEntry::setQmlPath(const QString &qml)
177 {
178     m_data->qml = qml;
179 
180     m_data->qmlSource = QString::fromUtf8(getSourceForUrl(qml));
181 }
182 
setRequiredImport(const QString & requiredImport)183 void ItemLibraryEntry::setRequiredImport(const QString &requiredImport)
184 {
185     m_data->requiredImport = requiredImport;
186 }
187 
addHints(const QHash<QString,QString> & hints)188 void ItemLibraryEntry::addHints(const QHash<QString, QString> &hints)
189 {
190     Utils::addToHash(&m_data->hints, hints);
191 }
192 
setCustomComponentSource(const QString & source)193 void ItemLibraryEntry::setCustomComponentSource(const QString &source)
194 {
195     m_data->customComponentSource = source;
196 }
197 
addExtraFilePath(const QString & extraFile)198 void ItemLibraryEntry::addExtraFilePath(const QString &extraFile)
199 {
200     m_data->extraFilePaths.append(extraFile);
201 }
202 
addProperty(PropertyName & name,QString & type,QVariant & value)203 void ItemLibraryEntry::addProperty(PropertyName &name, QString &type, QVariant &value)
204 {
205     Property property;
206     property.set(name, type, value);
207     addProperty(property);
208 }
209 
operator <<(QDataStream & stream,const ItemLibraryEntry & itemLibraryEntry)210 QDataStream& operator<<(QDataStream& stream, const ItemLibraryEntry &itemLibraryEntry)
211 {
212     stream << itemLibraryEntry.name();
213     stream << itemLibraryEntry.typeName();
214     stream << itemLibraryEntry.majorVersion();
215     stream << itemLibraryEntry.minorVersion();
216     stream << itemLibraryEntry.typeIcon();
217     stream << itemLibraryEntry.libraryEntryIconPath();
218     stream << itemLibraryEntry.category();
219     stream << itemLibraryEntry.requiredImport();
220     stream << itemLibraryEntry.hints();
221 
222     stream << itemLibraryEntry.m_data->properties;
223     stream << itemLibraryEntry.m_data->qml;
224     stream << itemLibraryEntry.m_data->qmlSource;
225     stream << itemLibraryEntry.m_data->customComponentSource;
226     stream << itemLibraryEntry.m_data->extraFilePaths;
227 
228     return stream;
229 }
230 
operator >>(QDataStream & stream,ItemLibraryEntry & itemLibraryEntry)231 QDataStream& operator>>(QDataStream& stream, ItemLibraryEntry &itemLibraryEntry)
232 {
233     // Clear containers so that we don't simply append to them in case the object is reused
234     itemLibraryEntry.m_data->hints.clear();
235     itemLibraryEntry.m_data->properties.clear();
236 
237     stream >> itemLibraryEntry.m_data->name;
238     stream >> itemLibraryEntry.m_data->typeName;
239     stream >> itemLibraryEntry.m_data->majorVersion;
240     stream >> itemLibraryEntry.m_data->minorVersion;
241     stream >> itemLibraryEntry.m_data->typeIcon;
242     stream >> itemLibraryEntry.m_data->libraryEntryIconPath;
243     stream >> itemLibraryEntry.m_data->category;
244     stream >> itemLibraryEntry.m_data->requiredImport;
245     stream >> itemLibraryEntry.m_data->hints;
246 
247     stream >> itemLibraryEntry.m_data->properties;
248     stream >> itemLibraryEntry.m_data->qml;
249     stream >> itemLibraryEntry.m_data->qmlSource;
250     stream >> itemLibraryEntry.m_data->customComponentSource;
251     stream >> itemLibraryEntry.m_data->extraFilePaths;
252 
253     return stream;
254 }
255 
operator <<(QDebug debug,const ItemLibraryEntry & itemLibraryEntry)256 QDebug operator<<(QDebug debug, const ItemLibraryEntry &itemLibraryEntry)
257 {
258     debug << itemLibraryEntry.m_data->name;
259     debug << itemLibraryEntry.m_data->typeName;
260     debug << itemLibraryEntry.m_data->majorVersion;
261     debug << itemLibraryEntry.m_data->minorVersion;
262     debug << itemLibraryEntry.m_data->typeIcon;
263     debug << itemLibraryEntry.m_data->libraryEntryIconPath;
264     debug << itemLibraryEntry.m_data->category;
265     debug << itemLibraryEntry.m_data->requiredImport;
266     debug << itemLibraryEntry.m_data->hints;
267 
268     debug << itemLibraryEntry.m_data->properties;
269     debug << itemLibraryEntry.m_data->qml;
270     debug << itemLibraryEntry.m_data->qmlSource;
271     debug << itemLibraryEntry.m_data->customComponentSource;
272     debug << itemLibraryEntry.m_data->extraFilePaths;
273 
274     return debug.space();
275 }
276 
277 //
278 // ItemLibraryInfo
279 //
280 
ItemLibraryInfo(QObject * parent)281 ItemLibraryInfo::ItemLibraryInfo(QObject *parent)
282     : QObject(parent)
283 {
284 }
285 
286 
287 
entriesForType(const QByteArray & typeName,int majorVersion,int minorVersion) const288 QList<ItemLibraryEntry> ItemLibraryInfo::entriesForType(const QByteArray &typeName, int majorVersion, int minorVersion) const
289 {
290     QList<ItemLibraryEntry> entries;
291 
292     foreach (const ItemLibraryEntry &entry, m_nameToEntryHash) {
293         if (entry.typeName() == typeName)
294             entries += entry;
295     }
296 
297     if (m_baseInfo)
298         entries += m_baseInfo->entriesForType(typeName, majorVersion, minorVersion);
299 
300     return entries;
301 }
302 
entries() const303 QList<ItemLibraryEntry> ItemLibraryInfo::entries() const
304 {
305     QList<ItemLibraryEntry> list = m_nameToEntryHash.values();
306     if (m_baseInfo)
307         list += m_baseInfo->entries();
308     return list;
309 }
310 
keyForEntry(const ItemLibraryEntry & entry)311 static inline QString keyForEntry(const ItemLibraryEntry &entry)
312 {
313     return entry.name() + entry.category() + QString::number(entry.majorVersion());
314 }
315 
addEntries(const QList<ItemLibraryEntry> & entries,bool overwriteDuplicate)316 void ItemLibraryInfo::addEntries(const QList<ItemLibraryEntry> &entries, bool overwriteDuplicate)
317 {
318     foreach (const ItemLibraryEntry &entry, entries) {
319         const QString key = keyForEntry(entry);
320         if (!overwriteDuplicate && m_nameToEntryHash.contains(key))
321             throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
322         m_nameToEntryHash.insert(key, entry);
323     }
324     emit entriesChanged();
325 }
326 
containsEntry(const ItemLibraryEntry & entry)327 bool ItemLibraryInfo::containsEntry(const ItemLibraryEntry &entry)
328 {
329     const QString key = keyForEntry(entry);
330     return m_nameToEntryHash.contains(key);
331 }
332 
clearEntries()333 void ItemLibraryInfo::clearEntries()
334 {
335     m_nameToEntryHash.clear();
336     emit entriesChanged();
337 }
338 
blacklistImports() const339 QStringList ItemLibraryInfo::blacklistImports() const
340 {
341     auto list = m_blacklistImports;
342     if (m_baseInfo)
343         list.append(m_baseInfo->m_blacklistImports);
344     return list;
345 }
346 
priorityImports() const347 QSet<QString> ItemLibraryInfo::priorityImports() const
348 {
349     QSet<QString> set = m_priorityImports;
350     if (m_baseInfo)
351         set.unite(m_baseInfo->m_priorityImports);
352     return set;
353 }
354 
addBlacklistImports(const QStringList & list)355 void ItemLibraryInfo::addBlacklistImports(const QStringList &list)
356 {
357     m_blacklistImports.append(list);
358 }
359 
addPriorityImports(const QSet<QString> & set)360 void ItemLibraryInfo::addPriorityImports(const QSet<QString> &set)
361 {
362     if (!set.isEmpty()) {
363         m_priorityImports.unite(set);
364         emit priorityImportsChanged();
365     }
366 }
367 
setBaseInfo(ItemLibraryInfo * baseInfo)368 void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
369 {
370     m_baseInfo = baseInfo;
371 }
372 
373 } // namespace QmlDesigner
374