metainforeader.cpp 10.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
12
13
14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16
17
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
18
19
20
21
22
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25

26
#include "metainforeader.h"
27
28
29
#include "metainfo.h"

#include <QString>
30
#include <QFileInfo>
hjk's avatar
hjk committed
31
#include <QDebug>
32
33
34
35
36
#include <QIcon>

namespace QmlDesigner {
namespace Internal {

37
38
39
40
enum {
    debug = false
};

41
42
43
44
45
const QString rootElementName = QStringLiteral("MetaInfo");
const QString typeElementName = QStringLiteral("Type");
const QString ItemLibraryEntryElementName = QStringLiteral("ItemLibraryEntry");
const QString QmlSourceElementName = QStringLiteral("QmlSource");
const QString PropertyElementName = QStringLiteral("Property");
46

47
MetaInfoReader::MetaInfoReader(const MetaInfo &metaInfo)
48
49
        : m_parserState(Undefined),
          m_metaInfo(metaInfo)
50
{
51
    m_overwriteDuplicates = false;
52
53
}

54
void MetaInfoReader::readMetaInfoFile(const QString &path, bool overwriteDuplicates)
55
{
56
    m_documentPath = path;
57
    m_overwriteDuplicates = overwriteDuplicates;
58
59
60
61
62
63
64
    m_parserState = ParsingDocument;
    if (!SimpleAbstractStreamReader::readFile(path)) {
        qWarning() << "readMetaInfoFile()" << path;
        qWarning() << errors();
        m_parserState = Error;
        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
    }
65

66
67
68
69
70
    if (!errors().isEmpty()) {
        qWarning() << "readMetaInfoFile()" << path;
        qWarning() << errors();
        m_parserState = Error;
        throw InvalidMetaInfoException(__LINE__, __FUNCTION__, __FILE__);
71
72
73
    }
}

74
QStringList MetaInfoReader::errors()
75
{
76
    return QmlJS::SimpleAbstractStreamReader::errors();
77
78
}

79
void MetaInfoReader::setQualifcation(const TypeName &qualification)
80
81
82
83
{
    m_qualication = qualification;
}

84
void MetaInfoReader::elementStart(const QString &name)
85
{
86
87
88
89
90
91
92
    switch (parserState()) {
    case ParsingDocument: setParserState(readDocument(name)); break;
    case ParsingMetaInfo: setParserState(readMetaInfoRootElement(name)); break;
    case ParsingType: setParserState(readTypeElement(name)); break;
    case ParsingItemLibrary: setParserState(readItemLibraryEntryElement(name)); break;
    case ParsingProperty: setParserState(readPropertyElement(name)); break;
    case ParsingQmlSource: setParserState(readQmlSourceElement(name)); break;
93
    case Finished:
94
95
96
97
    case Undefined: setParserState(Error);
        addError(tr("Illegal state while parsing"), currentSourceLocation());
    case Error:
    default: return;
98
99
100
    }
}

101
void MetaInfoReader::elementEnd()
102
{
103
    switch (parserState()) {
104
    case ParsingMetaInfo: setParserState(Finished); break;
105
106
107
108
    case ParsingType: setParserState(ParsingMetaInfo); break;
    case ParsingItemLibrary: insertItemLibraryEntry(); setParserState((ParsingType)); break;
    case ParsingProperty: insertProperty(); setParserState(ParsingItemLibrary);  break;
    case ParsingQmlSource: setParserState(ParsingItemLibrary); break;
109
110
    case ParsingDocument:
    case Finished:
111
112
113
114
    case Undefined: setParserState(Error);
        addError(tr("Illegal state while parsing"), currentSourceLocation());
    case Error:
    default: return;
115
116
117
    }
}

118
void MetaInfoReader::propertyDefinition(const QString &name, const QVariant &value)
119
{
120
121
122
123
124
125
126
127
128
129
130
131
    switch (parserState()) {
    case ParsingType: readTypeProperty(name, value); break;
    case ParsingItemLibrary: readItemLibraryEntryProperty(name, value); break;
    case ParsingProperty: readPropertyProperty(name, value); break;
    case ParsingQmlSource: readQmlSourceProperty(name, value); break;
    case ParsingMetaInfo: addError(tr("No property definition allowed"), currentSourceLocation()); break;
    case ParsingDocument:
    case Finished:
    case Undefined: setParserState(Error);
        addError(tr("Illegal state while parsing"), currentSourceLocation());
    case Error:
    default: return;
132
    }
133
}
134

135
MetaInfoReader::ParserSate MetaInfoReader::readDocument(const QString &name)
136
{
137
    if (name == rootElementName) {
138
        m_currentClassName.clear();
139
        m_currentIcon.clear();
140
141
142
143
        return ParsingMetaInfo;
    } else {
        addErrorInvalidType(name);
        return Error;
144
145
146
    }
}

147
MetaInfoReader::ParserSate MetaInfoReader::readMetaInfoRootElement(const QString &name)
148
{
149
    if (name == typeElementName) {
150
151
        m_currentClassName.clear();
        m_currentIcon.clear();
152
153
154
155
156
157
        return ParsingType;
    } else {
        addErrorInvalidType(name);
        return Error;
    }
}
158

159
MetaInfoReader::ParserSate MetaInfoReader::readTypeElement(const QString &name)
160
{
161
    if (name == ItemLibraryEntryElementName) {
162
        m_currentEntry = ItemLibraryEntry();
163
        m_currentEntry.setType(m_currentClassName);
164
        m_currentEntry.setTypeIcon(QIcon(m_currentIcon));
165
166
167
168
169
170
        return ParsingItemLibrary;
    } else {
        addErrorInvalidType(name);
        return Error;
    }
}
171

172
MetaInfoReader::ParserSate MetaInfoReader::readItemLibraryEntryElement(const QString &name)
173
174
175
176
{
    if (name == QmlSourceElementName) {
        return ParsingQmlSource;
    } else if (name == PropertyElementName) {
177
        m_currentPropertyName = PropertyName();
178
        m_currentPropertyType.clear();
179
180
181
182
183
184
185
        m_currentPropertyValue = QVariant();
        return ParsingProperty;
    } else {
        addError(tr("Invalid type %1").arg(name), currentSourceLocation());
        return Error;
    }
}
186

187
MetaInfoReader::ParserSate MetaInfoReader::readPropertyElement(const QString &name)
188
189
190
191
{
    addError(tr("Invalid type %1").arg(name), currentSourceLocation());
    return Error;
}
192

193
MetaInfoReader::ParserSate MetaInfoReader::readQmlSourceElement(const QString &name)
194
195
196
197
{
    addError(tr("Invalid type %1").arg(name), currentSourceLocation());
    return Error;
}
198

199
void MetaInfoReader::readTypeProperty(const QString &name, const QVariant &value)
200
{
201
    if (name == QLatin1String("name")) {
202
        m_currentClassName = value.toString().toUtf8();
203
        if (!m_qualication.isEmpty()) //prepend qualification
204
            m_currentClassName = m_qualication + "." + m_currentClassName;
205
    } else if (name == QStringLiteral("icon")) {
206
        m_currentIcon = absoluteFilePathForDocument(value.toString());
207
208
209
    } else {
        addError(tr("Unknown property for Type %1").arg(name), currentSourceLocation());
        setParserState(Error);
210
211
212
    }
}

213
void MetaInfoReader::readItemLibraryEntryProperty(const QString &name, const QVariant &value)
214
{
215
    if (name == QStringLiteral("name")) {
216
        m_currentEntry.setName(value.toString());
217
    } else if (name == QStringLiteral("category")) {
218
        m_currentEntry.setCategory(value.toString());
219
    } else if (name == QStringLiteral("libraryIcon")) {
220
        m_currentEntry.setLibraryEntryIconPath(absoluteFilePathForDocument(value.toString()));
221
    } else if (name == QStringLiteral("version")) {
222
        setVersion(value.toString());
223
    } else if (name == QStringLiteral("requiredImport")) {
224
225
226
227
        m_currentEntry.setRequiredImport(value.toString());
    } else {
        addError(tr("Unknown property for ItemLibraryEntry %1").arg(name), currentSourceLocation());
        setParserState(Error);
228
229
230
    }
}

231
void MetaInfoReader::readPropertyProperty(const QString &name, const QVariant &value)
232
{
233
    if (name == QStringLiteral("name")) {
234
       m_currentPropertyName = value.toByteArray();
235
    } else if (name == QStringLiteral("type")) {
236
        m_currentPropertyType = value.toString();
237
    } else if (name == QStringLiteral("value")) {
238
239
240
241
242
243
        m_currentPropertyValue = value;
    } else {
        addError(tr("Unknown property for Property %1").arg(name), currentSourceLocation());
        setParserState(Error);
    }
}
244

245
void MetaInfoReader::readQmlSourceProperty(const QString &name, const QVariant &value)
246
{
247
    if (name == QStringLiteral("source")) {
248
        m_currentEntry.setQmlPath(absoluteFilePathForDocument(value.toString()));
249
250
251
    } else {
        addError(tr("Unknown property for QmlSource %1").arg(name), currentSourceLocation());
        setParserState(Error);
252
253
254
    }
}

255
void MetaInfoReader::setVersion(const QString &versionNumber)
256
{
257
    const TypeName typeName = m_currentEntry.typeName();
258
259
260
261
262
263
    int major = 1;
    int minor = 0;

    if (!versionNumber.isEmpty()) {
        int val;
        bool ok;
264
265
        if (versionNumber.contains(QLatin1Char('.'))) {
            val = versionNumber.split(QLatin1Char('.')).first().toInt(&ok);
266
            major = ok ? val : major;
267
            val = versionNumber.split(QLatin1Char('.')).last().toInt(&ok);
268
269
270
271
272
273
274
275
            minor = ok ? val : minor;
        } else {
            val = versionNumber.toInt(&ok);
            major = ok ? val : major;
        }
    }
    m_currentEntry.setType(typeName, major, minor);
}
276

277
MetaInfoReader::ParserSate MetaInfoReader::parserState() const
278
279
280
{
    return m_parserState;
}
281

282
void MetaInfoReader::setParserState(ParserSate newParserState)
283
284
285
{
    if (debug && newParserState == Error)
        qDebug() << "Error";
286

287
288
    m_parserState = newParserState;
}
289

290
void MetaInfoReader::insertItemLibraryEntry()
291
292
293
294
{
    if (debug) {
        qDebug() << "insertItemLibraryEntry()";
        qDebug() << m_currentEntry;
295
296
    }

297
    try {
298
        m_metaInfo.itemLibraryInfo()->addEntry(m_currentEntry, m_overwriteDuplicates);
299
    } catch (const InvalidMetaInfoException &) {
300
        addError(tr("Invalid or duplicate item library entry %1").arg(m_currentEntry.name()), currentSourceLocation());
301
302
303
    }
}

304
void MetaInfoReader::insertProperty()
305
306
{
    m_currentEntry.addProperty(m_currentPropertyName, m_currentPropertyType, m_currentPropertyValue);
307
}
308

309
void MetaInfoReader::addErrorInvalidType(const QString &typeName)
310
311
{
    addError(tr("Invalid type %1").arg(typeName), currentSourceLocation());
312
}
313

314
315
316
317
318
319
320
QString MetaInfoReader::absoluteFilePathForDocument(const QString &relativeFilePath)
{

    QFileInfo fileInfo(relativeFilePath);
    if (fileInfo.isAbsolute() && fileInfo.exists())
        return relativeFilePath;

321
    return QFileInfo(QFileInfo(m_documentPath).absolutePath() + QStringLiteral("/") + relativeFilePath).absoluteFilePath();
322
323
}

324
325
} //Internal
} //QmlDesigner