From 7e7509744761cf8b42bdfbb5f6f849d432a3ec9f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 21 Feb 2023 14:11:40 +0100 Subject: [PATCH] Move examples manifest parser in separate function and file. To make it auto-testable. Change-Id: I19d263bf080a0089eb9a4ec0f379c52446771c0a Reviewed-by: David Schulz --- src/plugins/qtsupport/CMakeLists.txt | 2 + src/plugins/qtsupport/exampleslistmodel.cpp | 230 ++------------- src/plugins/qtsupport/exampleslistmodel.h | 25 -- src/plugins/qtsupport/examplesparser.cpp | 270 ++++++++++++++++++ src/plugins/qtsupport/examplesparser.h | 38 +++ .../qtsupport/gettingstartedwelcomepage.cpp | 1 + src/plugins/qtsupport/qtsupport.qbs | 2 + 7 files changed, 330 insertions(+), 238 deletions(-) create mode 100644 src/plugins/qtsupport/examplesparser.cpp create mode 100644 src/plugins/qtsupport/examplesparser.h diff --git a/src/plugins/qtsupport/CMakeLists.txt b/src/plugins/qtsupport/CMakeLists.txt index 30fe2fb32bf..5d69a7fc38a 100644 --- a/src/plugins/qtsupport/CMakeLists.txt +++ b/src/plugins/qtsupport/CMakeLists.txt @@ -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 diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp index 26af348ca76..700248e1f97 100644 --- a/src/plugins/qtsupport/exampleslistmodel.cpp +++ b/src/plugins/qtsupport/exampleslistmodel.cpp @@ -3,6 +3,7 @@ #include "exampleslistmodel.h" +#include "examplesparser.h" #include "qtsupporttr.h" #include @@ -288,38 +289,11 @@ ExamplesViewController::ExamplesViewController(ExampleSetModel *exampleSetModel, updateExamples(); } -static QString fixStringForTags(const QString &string) -{ - QString returnString = string; - returnString.remove(QLatin1String("")); - returnString.remove(QLatin1String("")); - returnString.remove(QLatin1String("")); - returnString.remove(QLatin1String("")); - 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 parseExamples(QXmlStreamReader *reader, - const QString &projectsOffset, - const QString &examplesInstallPath) -{ - QList result; - std::unique_ptr item; - const QChar slash = QLatin1Char('/'); - while (!reader->atEnd()) { - switch (reader->readNext()) { - case QXmlStreamReader::StartElement: - if (reader->name() == QLatin1String("example")) { - item = std::make_unique(); - 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 parseDemos(QXmlStreamReader *reader, - const QString &projectsOffset, - const QString &demosInstallPath) -{ - QList result; - std::unique_ptr item; - const QChar slash = QLatin1Char('/'); - while (!reader->atEnd()) { - switch (reader->readNext()) { - case QXmlStreamReader::StartElement: - if (reader->name() == QLatin1String("demo")) { - item = std::make_unique(); - 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 parseTutorials(QXmlStreamReader *reader, const QString &projectsOffset) -{ - QList result; - std::unique_ptr item = std::make_unique(); - const QChar slash = QLatin1Char('/'); - while (!reader->atEnd()) { - switch (reader->readNext()) { - case QXmlStreamReader::StartElement: - if (reader->name() == QLatin1String("tutorial")) { - item = std::make_unique(); - 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 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> 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) { diff --git a/src/plugins/qtsupport/exampleslistmodel.h b/src/plugins/qtsupport/exampleslistmodel.h index a4e8fe9eba6..0047bf45e3e 100644 --- a/src/plugins/qtsupport/exampleslistmodel.h +++ b/src/plugins/qtsupport/exampleslistmodel.h @@ -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 *) diff --git a/src/plugins/qtsupport/examplesparser.cpp b/src/plugins/qtsupport/examplesparser.cpp new file mode 100644 index 00000000000..2bd50bf8102 --- /dev/null +++ b/src/plugins/qtsupport/examplesparser.cpp @@ -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 +#include + +#include +#include +#include +#include +#include + +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("")); + returnString.remove(QLatin1String("")); + returnString.remove(QLatin1String("")); + returnString.remove(QLatin1String("")); + return returnString; +} + +static QStringList trimStringList(const QStringList &stringlist) +{ + return Utils::transform(stringlist, [](const QString &str) { return str.trimmed(); }); +} + +static QList parseExamples(QXmlStreamReader *reader, + const QString &projectsOffset, + const QString &examplesInstallPath) +{ + QList result; + std::unique_ptr item; + const QChar slash = QLatin1Char('/'); + while (!reader->atEnd()) { + switch (reader->readNext()) { + case QXmlStreamReader::StartElement: + if (reader->name() == QLatin1String("example")) { + item = std::make_unique(); + 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 parseDemos(QXmlStreamReader *reader, + const QString &projectsOffset, + const QString &demosInstallPath) +{ + QList result; + std::unique_ptr item; + const QChar slash = QLatin1Char('/'); + while (!reader->atEnd()) { + switch (reader->readNext()) { + case QXmlStreamReader::StartElement: + if (reader->name() == QLatin1String("demo")) { + item = std::make_unique(); + 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 parseTutorials(QXmlStreamReader *reader, const QString &projectsOffset) +{ + QList result; + std::unique_ptr item = std::make_unique(); + const QChar slash = QLatin1Char('/'); + while (!reader->atEnd()) { + switch (reader->readNext()) { + case QXmlStreamReader::StartElement: + if (reader->name() == QLatin1String("tutorial")) { + item = std::make_unique(); + 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> 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 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 diff --git a/src/plugins/qtsupport/examplesparser.h b/src/plugins/qtsupport/examplesparser.h new file mode 100644 index 00000000000..d08a8da11bc --- /dev/null +++ b/src/plugins/qtsupport/examplesparser.h @@ -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 +#include + +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> parseExamples(const QString &manifest, + const QString &examplesInstallPath, + const QString &demosInstallPath, + bool examples); + +} // namespace QtSupport::Internal + +Q_DECLARE_METATYPE(QtSupport::Internal::ExampleItem *) diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index 36bbcfb902b..fea56880356 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -4,6 +4,7 @@ #include "gettingstartedwelcomepage.h" #include "exampleslistmodel.h" +#include "examplesparser.h" #include "qtsupporttr.h" #include diff --git a/src/plugins/qtsupport/qtsupport.qbs b/src/plugins/qtsupport/qtsupport.qbs index 58f0ea61c3b..526cf4a24fe 100644 --- a/src/plugins/qtsupport/qtsupport.qbs +++ b/src/plugins/qtsupport/qtsupport.qbs @@ -77,6 +77,8 @@ Project { "qtsupport.qrc", "exampleslistmodel.cpp", "exampleslistmodel.h", + "examplesparser.cpp", + "examplesparser.h", "profilereader.cpp", "profilereader.h", "qscxmlcgenerator.cpp",