forked from qt-creator/qt-creator
Move examples manifest parser in separate function
and file. To make it auto-testable. Change-Id: I19d263bf080a0089eb9a4ec0f379c52446771c0a Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -8,6 +8,8 @@ add_qtc_plugin(QtSupport
|
||||
codegensettings.cpp codegensettings.h
|
||||
codegensettingspage.cpp codegensettingspage.h
|
||||
exampleslistmodel.cpp exampleslistmodel.h
|
||||
examplesparser.cpp
|
||||
examplesparser.h
|
||||
externaleditors.cpp externaleditors.h
|
||||
gettingstartedwelcomepage.cpp gettingstartedwelcomepage.h
|
||||
profilereader.cpp profilereader.h
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "exampleslistmodel.h"
|
||||
|
||||
#include "examplesparser.h"
|
||||
#include "qtsupporttr.h"
|
||||
|
||||
#include <QBuffer>
|
||||
@@ -288,38 +289,11 @@ ExamplesViewController::ExamplesViewController(ExampleSetModel *exampleSetModel,
|
||||
updateExamples();
|
||||
}
|
||||
|
||||
static QString fixStringForTags(const QString &string)
|
||||
{
|
||||
QString returnString = string;
|
||||
returnString.remove(QLatin1String("<i>"));
|
||||
returnString.remove(QLatin1String("</i>"));
|
||||
returnString.remove(QLatin1String("<tt>"));
|
||||
returnString.remove(QLatin1String("</tt>"));
|
||||
return returnString;
|
||||
}
|
||||
|
||||
static QStringList trimStringList(const QStringList &stringlist)
|
||||
{
|
||||
return Utils::transform(stringlist, [](const QString &str) { return str.trimmed(); });
|
||||
}
|
||||
|
||||
static QString relativeOrInstallPath(const QString &path, const QString &manifestPath,
|
||||
const QString &installPath)
|
||||
{
|
||||
const QChar slash = QLatin1Char('/');
|
||||
const QString relativeResolvedPath = manifestPath + slash + path;
|
||||
const QString installResolvedPath = installPath + slash + path;
|
||||
if (QFile::exists(relativeResolvedPath))
|
||||
return relativeResolvedPath;
|
||||
if (QFile::exists(installResolvedPath))
|
||||
return installResolvedPath;
|
||||
// doesn't exist, just return relative
|
||||
return relativeResolvedPath;
|
||||
}
|
||||
|
||||
static bool isValidExampleOrDemo(ExampleItem *item)
|
||||
{
|
||||
QTC_ASSERT(item, return false);
|
||||
if (item->type == Tutorial)
|
||||
return true;
|
||||
static QString invalidPrefix = QLatin1String("qthelp:////"); /* means that the qthelp url
|
||||
doesn't have any namespace */
|
||||
QString reason;
|
||||
@@ -345,158 +319,6 @@ static bool isValidExampleOrDemo(ExampleItem *item)
|
||||
return ok || debugExamples();
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
|
||||
const QString &projectsOffset,
|
||||
const QString &examplesInstallPath)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item;
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("example")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Example;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath = relativeOrInstallPath(item->projectPath, projectsOffset, examplesInstallPath);
|
||||
item->imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
||||
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
const QString mainFileAttribute = reader->attributes().value(
|
||||
QLatin1String("mainFile")).toString();
|
||||
const QString filePath = relativeOrInstallPath(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement),
|
||||
projectsOffset, examplesInstallPath);
|
||||
item->filesToOpen.append(filePath);
|
||||
if (mainFileAttribute.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)
|
||||
item->mainFile = filePath;
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(projectsOffset + slash + reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = trimStringList(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','), Qt::SkipEmptyParts));
|
||||
} else if (reader->name() == QLatin1String("platforms")) {
|
||||
item->platforms = trimStringList(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','), Qt::SkipEmptyParts));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("example")) {
|
||||
if (isValidExampleOrDemo(item.get()))
|
||||
result.push_back(item.release());
|
||||
} else if (reader->name() == QLatin1String("examples")) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
|
||||
const QString &projectsOffset,
|
||||
const QString &demosInstallPath)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item;
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("demo")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Demo;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath = relativeOrInstallPath(item->projectPath, projectsOffset, demosInstallPath);
|
||||
item->imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
item->filesToOpen.append(relativeOrInstallPath(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement),
|
||||
projectsOffset, demosInstallPath));
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(projectsOffset + slash + reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("demo")) {
|
||||
if (isValidExampleOrDemo(item.get()))
|
||||
result.push_back(item.release());
|
||||
} else if (reader->name() == QLatin1String("demos")) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QString &projectsOffset)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item = std::make_unique<ExampleItem>();
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("tutorial")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Tutorial;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath.prepend(slash);
|
||||
item->projectPath.prepend(projectsOffset);
|
||||
item->imageUrl = Utils::StyleHelper::dpiSpecificImageFile(
|
||||
attributes.value(QLatin1String("imageUrl")).toString());
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
|
||||
item->videoUrl = attributes.value(QLatin1String("videoUrl")).toString();
|
||||
item->videoLength = attributes.value(QLatin1String("videoLength")).toString();
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
item->filesToOpen.append(projectsOffset + slash + reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(projectsOffset + slash + reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("tutorial"))
|
||||
result.push_back(item.release());
|
||||
else if (reader->name() == QLatin1String("tutorials"))
|
||||
return result;
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExamplesViewController::updateExamples()
|
||||
{
|
||||
QString examplesInstallPath;
|
||||
@@ -509,41 +331,23 @@ void ExamplesViewController::updateExamples()
|
||||
|
||||
QList<ExampleItem *> items;
|
||||
for (const QString &exampleSource : sources) {
|
||||
QFile exampleFile(exampleSource);
|
||||
if (!exampleFile.open(QIODevice::ReadOnly)) {
|
||||
if (debugExamples())
|
||||
qWarning() << "ERROR: Could not open file" << exampleSource;
|
||||
if (debugExamples()) {
|
||||
qWarning() << QString::fromLatin1("Reading file \"%1\"...")
|
||||
.arg(QFileInfo(exampleSource).absoluteFilePath());
|
||||
}
|
||||
|
||||
const expected_str<QList<ExampleItem *>> result
|
||||
= parseExamples(exampleSource, examplesInstallPath, demosInstallPath, m_isExamples);
|
||||
if (!result) {
|
||||
if (debugExamples()) {
|
||||
qWarning() << "ERROR: Could not read examples from" << exampleSource << ":"
|
||||
<< result.error();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo fi(exampleSource);
|
||||
QString offsetPath = fi.path();
|
||||
QDir examplesDir(offsetPath);
|
||||
QDir demosDir(offsetPath);
|
||||
|
||||
if (debugExamples())
|
||||
qWarning() << QString::fromLatin1("Reading file \"%1\"...").arg(fi.absoluteFilePath());
|
||||
QXmlStreamReader reader(&exampleFile);
|
||||
while (!reader.atEnd())
|
||||
switch (reader.readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (m_isExamples && reader.name() == QLatin1String("examples"))
|
||||
items += parseExamples(&reader, examplesDir.path(), examplesInstallPath);
|
||||
else if (m_isExamples && reader.name() == QLatin1String("demos"))
|
||||
items += parseDemos(&reader, demosDir.path(), demosInstallPath);
|
||||
else if (!m_isExamples && reader.name() == QLatin1String("tutorials"))
|
||||
items += parseTutorials(&reader, examplesDir.path());
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.hasError() && debugExamples()) {
|
||||
qWarning().noquote().nospace() << "ERROR: Could not parse file as XML document ("
|
||||
<< exampleSource << "):" << reader.lineNumber() << ':' << reader.columnNumber()
|
||||
<< ": " << reader.errorString();
|
||||
}
|
||||
items += filtered(*result, isValidExampleOrDemo);
|
||||
}
|
||||
|
||||
if (m_isExamples) {
|
||||
if (m_exampleSetModel->selectedQtSupports(Android::Constants::ANDROID_DEVICE_TYPE)) {
|
||||
items = Utils::filtered(items, [](ExampleItem *item) {
|
||||
|
@@ -77,29 +77,6 @@ private:
|
||||
bool m_initalized = false;
|
||||
};
|
||||
|
||||
enum InstructionalType
|
||||
{
|
||||
Example = 0, Demo, Tutorial
|
||||
};
|
||||
|
||||
class ExampleItem : public Core::ListItem
|
||||
{
|
||||
public:
|
||||
QString projectPath;
|
||||
QString docUrl;
|
||||
QStringList filesToOpen;
|
||||
QString mainFile; /* file to be visible after opening filesToOpen */
|
||||
QStringList dependencies;
|
||||
InstructionalType type;
|
||||
int difficulty = 0;
|
||||
bool hasSourceCode = false;
|
||||
bool isVideo = false;
|
||||
bool isHighlighted = false;
|
||||
QString videoUrl;
|
||||
QString videoLength;
|
||||
QStringList platforms;
|
||||
};
|
||||
|
||||
class ExamplesViewController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -119,5 +96,3 @@ private:
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QtSupport
|
||||
|
||||
Q_DECLARE_METATYPE(QtSupport::Internal::ExampleItem *)
|
||||
|
270
src/plugins/qtsupport/examplesparser.cpp
Normal file
270
src/plugins/qtsupport/examplesparser.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "examplesparser.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QPixmapCache>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace QtSupport::Internal {
|
||||
|
||||
static QString relativeOrInstallPath(const QString &path,
|
||||
const QString &manifestPath,
|
||||
const QString &installPath)
|
||||
{
|
||||
const QChar slash = QLatin1Char('/');
|
||||
const QString relativeResolvedPath = manifestPath + slash + path;
|
||||
const QString installResolvedPath = installPath + slash + path;
|
||||
if (QFile::exists(relativeResolvedPath))
|
||||
return relativeResolvedPath;
|
||||
if (QFile::exists(installResolvedPath))
|
||||
return installResolvedPath;
|
||||
// doesn't exist, just return relative
|
||||
return relativeResolvedPath;
|
||||
}
|
||||
|
||||
static QString fixStringForTags(const QString &string)
|
||||
{
|
||||
QString returnString = string;
|
||||
returnString.remove(QLatin1String("<i>"));
|
||||
returnString.remove(QLatin1String("</i>"));
|
||||
returnString.remove(QLatin1String("<tt>"));
|
||||
returnString.remove(QLatin1String("</tt>"));
|
||||
return returnString;
|
||||
}
|
||||
|
||||
static QStringList trimStringList(const QStringList &stringlist)
|
||||
{
|
||||
return Utils::transform(stringlist, [](const QString &str) { return str.trimmed(); });
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
|
||||
const QString &projectsOffset,
|
||||
const QString &examplesInstallPath)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item;
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("example")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Example;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath = relativeOrInstallPath(item->projectPath,
|
||||
projectsOffset,
|
||||
examplesInstallPath);
|
||||
item->imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString()
|
||||
== QLatin1String("true");
|
||||
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
const QString mainFileAttribute
|
||||
= reader->attributes().value(QLatin1String("mainFile")).toString();
|
||||
const QString filePath
|
||||
= relativeOrInstallPath(reader->readElementText(
|
||||
QXmlStreamReader::ErrorOnUnexpectedElement),
|
||||
projectsOffset,
|
||||
examplesInstallPath);
|
||||
item->filesToOpen.append(filePath);
|
||||
if (mainFileAttribute.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)
|
||||
item->mainFile = filePath;
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(
|
||||
projectsOffset + slash
|
||||
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = trimStringList(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
|
||||
.split(QLatin1Char(','), Qt::SkipEmptyParts));
|
||||
} else if (reader->name() == QLatin1String("platforms")) {
|
||||
item->platforms = trimStringList(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
|
||||
.split(QLatin1Char(','), Qt::SkipEmptyParts));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("example")) {
|
||||
result.push_back(item.release());
|
||||
} else if (reader->name() == QLatin1String("examples")) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
|
||||
const QString &projectsOffset,
|
||||
const QString &demosInstallPath)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item;
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("demo")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Demo;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath = relativeOrInstallPath(item->projectPath,
|
||||
projectsOffset,
|
||||
demosInstallPath);
|
||||
item->imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString()
|
||||
== QLatin1String("true");
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
item->filesToOpen.append(
|
||||
relativeOrInstallPath(reader->readElementText(
|
||||
QXmlStreamReader::ErrorOnUnexpectedElement),
|
||||
projectsOffset,
|
||||
demosInstallPath));
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(
|
||||
projectsOffset + slash
|
||||
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
|
||||
.split(QLatin1Char(','));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("demo")) {
|
||||
result.push_back(item.release());
|
||||
} else if (reader->name() == QLatin1String("demos")) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QString &projectsOffset)
|
||||
{
|
||||
QList<ExampleItem *> result;
|
||||
std::unique_ptr<ExampleItem> item = std::make_unique<ExampleItem>();
|
||||
const QChar slash = QLatin1Char('/');
|
||||
while (!reader->atEnd()) {
|
||||
switch (reader->readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader->name() == QLatin1String("tutorial")) {
|
||||
item = std::make_unique<ExampleItem>();
|
||||
item->type = Tutorial;
|
||||
QXmlStreamAttributes attributes = reader->attributes();
|
||||
item->name = attributes.value(QLatin1String("name")).toString();
|
||||
item->projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||
item->hasSourceCode = !item->projectPath.isEmpty();
|
||||
item->projectPath.prepend(slash);
|
||||
item->projectPath.prepend(projectsOffset);
|
||||
item->imageUrl = Utils::StyleHelper::dpiSpecificImageFile(
|
||||
attributes.value(QLatin1String("imageUrl")).toString());
|
||||
QPixmapCache::remove(item->imageUrl);
|
||||
item->docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||
item->isVideo = attributes.value(QLatin1String("isVideo")).toString()
|
||||
== QLatin1String("true");
|
||||
item->videoUrl = attributes.value(QLatin1String("videoUrl")).toString();
|
||||
item->videoLength = attributes.value(QLatin1String("videoLength")).toString();
|
||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||
item->filesToOpen.append(
|
||||
projectsOffset + slash
|
||||
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("description")) {
|
||||
item->description = fixStringForTags(
|
||||
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("dependency")) {
|
||||
item->dependencies.append(
|
||||
projectsOffset + slash
|
||||
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
|
||||
} else if (reader->name() == QLatin1String("tags")) {
|
||||
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
|
||||
.split(QLatin1Char(','));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader->name() == QLatin1String("tutorial"))
|
||||
result.push_back(item.release());
|
||||
else if (reader->name() == QLatin1String("tutorials"))
|
||||
return result;
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expected_str<QList<ExampleItem *>> parseExamples(const QString &manifest,
|
||||
const QString &examplesInstallPath,
|
||||
const QString &demosInstallPath,
|
||||
const bool examples)
|
||||
{
|
||||
QFile exampleFile(manifest);
|
||||
if (!exampleFile.open(QIODevice::ReadOnly))
|
||||
return make_unexpected(QString("Could not open file \"%1\"").arg(manifest));
|
||||
|
||||
QFileInfo fi(manifest);
|
||||
QString offsetPath = fi.path();
|
||||
QDir examplesDir(offsetPath);
|
||||
QDir demosDir(offsetPath);
|
||||
|
||||
QList<ExampleItem *> items;
|
||||
QXmlStreamReader reader(&exampleFile);
|
||||
while (!reader.atEnd()) {
|
||||
switch (reader.readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (examples && reader.name() == QLatin1String("examples"))
|
||||
items += parseExamples(&reader, examplesDir.path(), examplesInstallPath);
|
||||
else if (examples && reader.name() == QLatin1String("demos"))
|
||||
items += parseDemos(&reader, demosDir.path(), demosInstallPath);
|
||||
else if (!examples && reader.name() == QLatin1String("tutorials"))
|
||||
items += parseTutorials(&reader, examplesDir.path());
|
||||
break;
|
||||
default: // nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qDeleteAll(items);
|
||||
return make_unexpected(QString("Could not parse file \"%1\" as XML document: %2:%3: %4")
|
||||
.arg(manifest)
|
||||
.arg(reader.lineNumber())
|
||||
.arg(reader.columnNumber())
|
||||
.arg(reader.errorString()));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
} // namespace QtSupport::Internal
|
38
src/plugins/qtsupport/examplesparser.h
Normal file
38
src/plugins/qtsupport/examplesparser.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <coreplugin/welcomepagehelper.h>
|
||||
#include <utils/expected.h>
|
||||
|
||||
namespace QtSupport::Internal {
|
||||
|
||||
enum InstructionalType { Example = 0, Demo, Tutorial };
|
||||
|
||||
class ExampleItem : public Core::ListItem
|
||||
{
|
||||
public:
|
||||
QString projectPath;
|
||||
QString docUrl;
|
||||
QStringList filesToOpen;
|
||||
QString mainFile; /* file to be visible after opening filesToOpen */
|
||||
QStringList dependencies;
|
||||
InstructionalType type;
|
||||
int difficulty = 0;
|
||||
bool hasSourceCode = false;
|
||||
bool isVideo = false;
|
||||
bool isHighlighted = false;
|
||||
QString videoUrl;
|
||||
QString videoLength;
|
||||
QStringList platforms;
|
||||
};
|
||||
|
||||
Utils::expected_str<QList<ExampleItem *>> parseExamples(const QString &manifest,
|
||||
const QString &examplesInstallPath,
|
||||
const QString &demosInstallPath,
|
||||
bool examples);
|
||||
|
||||
} // namespace QtSupport::Internal
|
||||
|
||||
Q_DECLARE_METATYPE(QtSupport::Internal::ExampleItem *)
|
@@ -4,6 +4,7 @@
|
||||
#include "gettingstartedwelcomepage.h"
|
||||
|
||||
#include "exampleslistmodel.h"
|
||||
#include "examplesparser.h"
|
||||
#include "qtsupporttr.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
@@ -77,6 +77,8 @@ Project {
|
||||
"qtsupport.qrc",
|
||||
"exampleslistmodel.cpp",
|
||||
"exampleslistmodel.h",
|
||||
"examplesparser.cpp",
|
||||
"examplesparser.h",
|
||||
"profilereader.cpp",
|
||||
"profilereader.h",
|
||||
"qscxmlcgenerator.cpp",
|
||||
|
Reference in New Issue
Block a user