Convert Examples model to FilePath

Change-Id: I56219d2f9516662b32d45fd9b2108a0ad34113cc
Reviewed-by: David Schulz <david.schulz@qt.io>
(cherry picked from commit 255afd45bf)
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Eike Ziller
2023-02-22 10:17:19 +01:00
parent e6e9405cc9
commit ac17e0e2ad
5 changed files with 101 additions and 107 deletions

View File

@@ -298,14 +298,15 @@ static bool isValidExampleOrDemo(ExampleItem *item)
doesn't have any namespace */ doesn't have any namespace */
QString reason; QString reason;
bool ok = true; bool ok = true;
if (!item->hasSourceCode || !QFileInfo::exists(item->projectPath)) { if (!item->hasSourceCode || !item->projectPath.exists()) {
ok = false; ok = false;
reason = QString::fromLatin1("projectPath \"%1\" empty or does not exist").arg(item->projectPath); reason = QString::fromLatin1("projectPath \"%1\" empty or does not exist")
.arg(item->projectPath.toUserOutput());
} else if (item->imageUrl.startsWith(invalidPrefix) || !QUrl(item->imageUrl).isValid()) { } else if (item->imageUrl.startsWith(invalidPrefix) || !QUrl(item->imageUrl).isValid()) {
ok = false; ok = false;
reason = QString::fromLatin1("imageUrl \"%1\" not valid").arg(item->imageUrl); reason = QString::fromLatin1("imageUrl \"%1\" not valid").arg(item->imageUrl);
} else if (!item->docUrl.isEmpty() } else if (!item->docUrl.isEmpty()
&& (item->docUrl.startsWith(invalidPrefix) || !QUrl(item->docUrl).isValid())) { && (item->docUrl.startsWith(invalidPrefix) || !QUrl(item->docUrl).isValid())) {
ok = false; ok = false;
reason = QString::fromLatin1("docUrl \"%1\" non-empty but not valid").arg(item->docUrl); reason = QString::fromLatin1("docUrl \"%1\" non-empty but not valid").arg(item->docUrl);
} }
@@ -331,13 +332,17 @@ void ExamplesViewController::updateExamples()
QList<ExampleItem *> items; QList<ExampleItem *> items;
for (const QString &exampleSource : sources) { for (const QString &exampleSource : sources) {
const auto manifest = FilePath::fromUserInput(exampleSource);
if (debugExamples()) { if (debugExamples()) {
qWarning() << QString::fromLatin1("Reading file \"%1\"...") qWarning() << QString::fromLatin1("Reading file \"%1\"...")
.arg(QFileInfo(exampleSource).absoluteFilePath()); .arg(manifest.absoluteFilePath().toUserOutput());
} }
const expected_str<QList<ExampleItem *>> result const expected_str<QList<ExampleItem *>> result
= parseExamples(exampleSource, examplesInstallPath, demosInstallPath, m_isExamples); = parseExamples(manifest,
FilePath::fromUserInput(examplesInstallPath),
FilePath::fromUserInput(demosInstallPath),
m_isExamples);
if (!result) { if (!result) {
if (debugExamples()) { if (debugExamples()) {
qWarning() << "ERROR: Could not read examples from" << exampleSource << ":" qWarning() << "ERROR: Could not read examples from" << exampleSource << ":"

View File

@@ -4,11 +4,9 @@
#include "examplesparser.h" #include "examplesparser.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/filepath.h>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QPixmapCache> #include <QPixmapCache>
#include <QXmlStreamReader> #include <QXmlStreamReader>
@@ -16,16 +14,15 @@ using namespace Utils;
namespace QtSupport::Internal { namespace QtSupport::Internal {
static QString relativeOrInstallPath(const QString &path, static FilePath relativeOrInstallPath(const FilePath &path,
const QString &manifestPath, const FilePath &manifestPath,
const QString &installPath) const FilePath &installPath)
{ {
const QChar slash = QLatin1Char('/'); const FilePath relativeResolvedPath = manifestPath.resolvePath(path);
const QString relativeResolvedPath = manifestPath + slash + path; const FilePath installResolvedPath = installPath.resolvePath(path);
const QString installResolvedPath = installPath + slash + path; if (relativeResolvedPath.exists())
if (QFile::exists(relativeResolvedPath))
return relativeResolvedPath; return relativeResolvedPath;
if (QFile::exists(installResolvedPath)) if (installResolvedPath.exists())
return installResolvedPath; return installResolvedPath;
// doesn't exist, just return relative // doesn't exist, just return relative
return relativeResolvedPath; return relativeResolvedPath;
@@ -47,12 +44,11 @@ static QStringList trimStringList(const QStringList &stringlist)
} }
static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader, static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
const QString &projectsOffset, const FilePath &projectsOffset,
const QString &examplesInstallPath) const FilePath &examplesInstallPath)
{ {
QList<ExampleItem *> result; QList<ExampleItem *> result;
std::unique_ptr<ExampleItem> item; std::unique_ptr<ExampleItem> item;
const QChar slash = QLatin1Char('/');
while (!reader->atEnd()) { while (!reader->atEnd()) {
switch (reader->readNext()) { switch (reader->readNext()) {
case QXmlStreamReader::StartElement: case QXmlStreamReader::StartElement:
@@ -61,7 +57,8 @@ static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
item->type = Example; item->type = Example;
QXmlStreamAttributes attributes = reader->attributes(); QXmlStreamAttributes attributes = reader->attributes();
item->name = attributes.value(QLatin1String("name")).toString(); item->name = attributes.value(QLatin1String("name")).toString();
item->projectPath = attributes.value(QLatin1String("projectPath")).toString(); item->projectPath = FilePath::fromUserInput(
attributes.value(QLatin1String("projectPath")).toString());
item->hasSourceCode = !item->projectPath.isEmpty(); item->hasSourceCode = !item->projectPath.isEmpty();
item->projectPath = relativeOrInstallPath(item->projectPath, item->projectPath = relativeOrInstallPath(item->projectPath,
projectsOffset, projectsOffset,
@@ -75,9 +72,9 @@ static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
} else if (reader->name() == QLatin1String("fileToOpen")) { } else if (reader->name() == QLatin1String("fileToOpen")) {
const QString mainFileAttribute const QString mainFileAttribute
= reader->attributes().value(QLatin1String("mainFile")).toString(); = reader->attributes().value(QLatin1String("mainFile")).toString();
const QString filePath const FilePath filePath
= relativeOrInstallPath(reader->readElementText( = relativeOrInstallPath(FilePath::fromUserInput(reader->readElementText(
QXmlStreamReader::ErrorOnUnexpectedElement), QXmlStreamReader::ErrorOnUnexpectedElement)),
projectsOffset, projectsOffset,
examplesInstallPath); examplesInstallPath);
item->filesToOpen.append(filePath); item->filesToOpen.append(filePath);
@@ -88,8 +85,8 @@ static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("dependency")) { } else if (reader->name() == QLatin1String("dependency")) {
item->dependencies.append( item->dependencies.append(
projectsOffset + slash projectsOffset
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); / reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("tags")) { } else if (reader->name() == QLatin1String("tags")) {
item->tags = trimStringList( item->tags = trimStringList(
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement) reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
@@ -115,12 +112,11 @@ static QList<ExampleItem *> parseExamples(QXmlStreamReader *reader,
} }
static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader, static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
const QString &projectsOffset, const FilePath &projectsOffset,
const QString &demosInstallPath) const FilePath &demosInstallPath)
{ {
QList<ExampleItem *> result; QList<ExampleItem *> result;
std::unique_ptr<ExampleItem> item; std::unique_ptr<ExampleItem> item;
const QChar slash = QLatin1Char('/');
while (!reader->atEnd()) { while (!reader->atEnd()) {
switch (reader->readNext()) { switch (reader->readNext()) {
case QXmlStreamReader::StartElement: case QXmlStreamReader::StartElement:
@@ -129,7 +125,8 @@ static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
item->type = Demo; item->type = Demo;
QXmlStreamAttributes attributes = reader->attributes(); QXmlStreamAttributes attributes = reader->attributes();
item->name = attributes.value(QLatin1String("name")).toString(); item->name = attributes.value(QLatin1String("name")).toString();
item->projectPath = attributes.value(QLatin1String("projectPath")).toString(); item->projectPath = FilePath::fromUserInput(
attributes.value(QLatin1String("projectPath")).toString());
item->hasSourceCode = !item->projectPath.isEmpty(); item->hasSourceCode = !item->projectPath.isEmpty();
item->projectPath = relativeOrInstallPath(item->projectPath, item->projectPath = relativeOrInstallPath(item->projectPath,
projectsOffset, projectsOffset,
@@ -141,8 +138,8 @@ static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
== QLatin1String("true"); == QLatin1String("true");
} else if (reader->name() == QLatin1String("fileToOpen")) { } else if (reader->name() == QLatin1String("fileToOpen")) {
item->filesToOpen.append( item->filesToOpen.append(
relativeOrInstallPath(reader->readElementText( relativeOrInstallPath(FilePath::fromUserInput(reader->readElementText(
QXmlStreamReader::ErrorOnUnexpectedElement), QXmlStreamReader::ErrorOnUnexpectedElement)),
projectsOffset, projectsOffset,
demosInstallPath)); demosInstallPath));
} else if (reader->name() == QLatin1String("description")) { } else if (reader->name() == QLatin1String("description")) {
@@ -150,8 +147,8 @@ static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("dependency")) { } else if (reader->name() == QLatin1String("dependency")) {
item->dependencies.append( item->dependencies.append(
projectsOffset + slash projectsOffset
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); / reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("tags")) { } else if (reader->name() == QLatin1String("tags")) {
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement) item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
.split(QLatin1Char(',')); .split(QLatin1Char(','));
@@ -171,11 +168,10 @@ static QList<ExampleItem *> parseDemos(QXmlStreamReader *reader,
return result; return result;
} }
static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QString &projectsOffset) static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const FilePath &projectsOffset)
{ {
QList<ExampleItem *> result; QList<ExampleItem *> result;
std::unique_ptr<ExampleItem> item = std::make_unique<ExampleItem>(); std::unique_ptr<ExampleItem> item = std::make_unique<ExampleItem>();
const QChar slash = QLatin1Char('/');
while (!reader->atEnd()) { while (!reader->atEnd()) {
switch (reader->readNext()) { switch (reader->readNext()) {
case QXmlStreamReader::StartElement: case QXmlStreamReader::StartElement:
@@ -184,10 +180,9 @@ static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QStri
item->type = Tutorial; item->type = Tutorial;
QXmlStreamAttributes attributes = reader->attributes(); QXmlStreamAttributes attributes = reader->attributes();
item->name = attributes.value(QLatin1String("name")).toString(); item->name = attributes.value(QLatin1String("name")).toString();
item->projectPath = attributes.value(QLatin1String("projectPath")).toString(); item->projectPath = projectsOffset
/ attributes.value(QLatin1String("projectPath")).toString();
item->hasSourceCode = !item->projectPath.isEmpty(); item->hasSourceCode = !item->projectPath.isEmpty();
item->projectPath.prepend(slash);
item->projectPath.prepend(projectsOffset);
item->imageUrl = Utils::StyleHelper::dpiSpecificImageFile( item->imageUrl = Utils::StyleHelper::dpiSpecificImageFile(
attributes.value(QLatin1String("imageUrl")).toString()); attributes.value(QLatin1String("imageUrl")).toString());
QPixmapCache::remove(item->imageUrl); QPixmapCache::remove(item->imageUrl);
@@ -198,15 +193,15 @@ static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QStri
item->videoLength = attributes.value(QLatin1String("videoLength")).toString(); item->videoLength = attributes.value(QLatin1String("videoLength")).toString();
} else if (reader->name() == QLatin1String("fileToOpen")) { } else if (reader->name() == QLatin1String("fileToOpen")) {
item->filesToOpen.append( item->filesToOpen.append(
projectsOffset + slash projectsOffset
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); / reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("description")) { } else if (reader->name() == QLatin1String("description")) {
item->description = fixStringForTags( item->description = fixStringForTags(
reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("dependency")) { } else if (reader->name() == QLatin1String("dependency")) {
item->dependencies.append( item->dependencies.append(
projectsOffset + slash projectsOffset
+ reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); / reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement));
} else if (reader->name() == QLatin1String("tags")) { } else if (reader->name() == QLatin1String("tags")) {
item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement) item->tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)
.split(QLatin1Char(',')); .split(QLatin1Char(','));
@@ -225,31 +220,28 @@ static QList<ExampleItem *> parseTutorials(QXmlStreamReader *reader, const QStri
return result; return result;
} }
expected_str<QList<ExampleItem *>> parseExamples(const QString &manifest, expected_str<QList<ExampleItem *>> parseExamples(const FilePath &manifest,
const QString &examplesInstallPath, const FilePath &examplesInstallPath,
const QString &demosInstallPath, const FilePath &demosInstallPath,
const bool examples) const bool examples)
{ {
QFile exampleFile(manifest); const expected_str<QByteArray> contents = manifest.fileContents();
if (!exampleFile.open(QIODevice::ReadOnly)) if (!contents)
return make_unexpected(QString("Could not open file \"%1\"").arg(manifest)); return make_unexpected(contents.error());
QFileInfo fi(manifest); const FilePath path = manifest.parentDir();
QString offsetPath = fi.path();
QDir examplesDir(offsetPath);
QDir demosDir(offsetPath);
QList<ExampleItem *> items; QList<ExampleItem *> items;
QXmlStreamReader reader(&exampleFile); QXmlStreamReader reader(*contents);
while (!reader.atEnd()) { while (!reader.atEnd()) {
switch (reader.readNext()) { switch (reader.readNext()) {
case QXmlStreamReader::StartElement: case QXmlStreamReader::StartElement:
if (examples && reader.name() == QLatin1String("examples")) if (examples && reader.name() == QLatin1String("examples"))
items += parseExamples(&reader, examplesDir.path(), examplesInstallPath); items += parseExamples(&reader, path, examplesInstallPath);
else if (examples && reader.name() == QLatin1String("demos")) else if (examples && reader.name() == QLatin1String("demos"))
items += parseDemos(&reader, demosDir.path(), demosInstallPath); items += parseDemos(&reader, path, demosInstallPath);
else if (!examples && reader.name() == QLatin1String("tutorials")) else if (!examples && reader.name() == QLatin1String("tutorials"))
items += parseTutorials(&reader, examplesDir.path()); items += parseTutorials(&reader, path);
break; break;
default: // nothing default: // nothing
break; break;
@@ -259,7 +251,7 @@ expected_str<QList<ExampleItem *>> parseExamples(const QString &manifest,
if (reader.hasError()) { if (reader.hasError()) {
qDeleteAll(items); qDeleteAll(items);
return make_unexpected(QString("Could not parse file \"%1\" as XML document: %2:%3: %4") return make_unexpected(QString("Could not parse file \"%1\" as XML document: %2:%3: %4")
.arg(manifest) .arg(manifest.toUserOutput())
.arg(reader.lineNumber()) .arg(reader.lineNumber())
.arg(reader.columnNumber()) .arg(reader.columnNumber())
.arg(reader.errorString())); .arg(reader.errorString()));

View File

@@ -5,6 +5,7 @@
#include <coreplugin/welcomepagehelper.h> #include <coreplugin/welcomepagehelper.h>
#include <utils/expected.h> #include <utils/expected.h>
#include <utils/filepath.h>
namespace QtSupport::Internal { namespace QtSupport::Internal {
@@ -13,11 +14,11 @@ enum InstructionalType { Example = 0, Demo, Tutorial };
class ExampleItem : public Core::ListItem class ExampleItem : public Core::ListItem
{ {
public: public:
QString projectPath; Utils::FilePath projectPath;
QString docUrl; QString docUrl;
QStringList filesToOpen; Utils::FilePaths filesToOpen;
QString mainFile; /* file to be visible after opening filesToOpen */ Utils::FilePath mainFile; /* file to be visible after opening filesToOpen */
QStringList dependencies; Utils::FilePaths dependencies;
InstructionalType type; InstructionalType type;
int difficulty = 0; int difficulty = 0;
bool hasSourceCode = false; bool hasSourceCode = false;
@@ -28,9 +29,9 @@ public:
QStringList platforms; QStringList platforms;
}; };
Utils::expected_str<QList<ExampleItem *>> parseExamples(const QString &manifest, Utils::expected_str<QList<ExampleItem *>> parseExamples(const Utils::FilePath &manifest,
const QString &examplesInstallPath, const Utils::FilePath &examplesInstallPath,
const QString &demosInstallPath, const Utils::FilePath &demosInstallPath,
bool examples); bool examples);
} // namespace QtSupport::Internal } // namespace QtSupport::Internal

View File

@@ -69,16 +69,18 @@ Id ExamplesWelcomePage::id() const
return m_showExamples ? "Examples" : "Tutorials"; return m_showExamples ? "Examples" : "Tutorials";
} }
QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileInfo, QStringList &filesToOpen, const QStringList& dependencies) FilePath ExamplesWelcomePage::copyToAlternativeLocation(const FilePath &proFile,
FilePaths &filesToOpen,
const FilePaths &dependencies)
{ {
const QString projectDir = proFileInfo.canonicalPath(); const FilePath projectDir = proFile.canonicalPath().parentDir();
QDialog d(ICore::dialogParent()); QDialog d(ICore::dialogParent());
auto lay = new QGridLayout(&d); auto lay = new QGridLayout(&d);
auto descrLbl = new QLabel; auto descrLbl = new QLabel;
d.setWindowTitle(Tr::tr("Copy Project to writable Location?")); d.setWindowTitle(Tr::tr("Copy Project to writable Location?"));
descrLbl->setTextFormat(Qt::RichText); descrLbl->setTextFormat(Qt::RichText);
descrLbl->setWordWrap(false); descrLbl->setWordWrap(false);
const QString nativeProjectDir = QDir::toNativeSeparators(projectDir); const QString nativeProjectDir = projectDir.toUserOutput();
descrLbl->setText(QString::fromLatin1("<blockquote>%1</blockquote>").arg(nativeProjectDir)); descrLbl->setText(QString::fromLatin1("<blockquote>%1</blockquote>").arg(nativeProjectDir));
descrLbl->setMinimumWidth(descrLbl->sizeHint().width()); descrLbl->setMinimumWidth(descrLbl->sizeHint().width());
descrLbl->setWordWrap(true); descrLbl->setWordWrap(true);
@@ -95,9 +97,10 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
txt->setBuddy(chooser); txt->setBuddy(chooser);
chooser->setExpectedKind(PathChooser::ExistingDirectory); chooser->setExpectedKind(PathChooser::ExistingDirectory);
chooser->setHistoryCompleter(QLatin1String("Qt.WritableExamplesDir.History")); chooser->setHistoryCompleter(QLatin1String("Qt.WritableExamplesDir.History"));
const QString defaultRootDirectory = DocumentManager::projectsDirectory().toString(); const FilePath defaultRootDirectory = DocumentManager::projectsDirectory();
QtcSettings *settings = ICore::settings(); QtcSettings *settings = ICore::settings();
chooser->setFilePath(FilePath::fromSettings(settings->value(C_FALLBACK_ROOT, defaultRootDirectory))); chooser->setFilePath(
FilePath::fromSettings(settings->value(C_FALLBACK_ROOT, defaultRootDirectory.toVariant())));
lay->addWidget(txt, 1, 0); lay->addWidget(txt, 1, 0);
lay->addWidget(chooser, 1, 1); lay->addWidget(chooser, 1, 1);
enum { Copy = QDialog::Accepted + 1, Keep = QDialog::Accepted + 2 }; enum { Copy = QDialog::Accepted + 1, Keep = QDialog::Accepted + 2 };
@@ -111,35 +114,32 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
connect(chooser, &PathChooser::validChanged, copyBtn, &QWidget::setEnabled); connect(chooser, &PathChooser::validChanged, copyBtn, &QWidget::setEnabled);
int code = d.exec(); int code = d.exec();
if (code == Copy) { if (code == Copy) {
QString exampleDirName = proFileInfo.dir().dirName(); const QString exampleDirName = projectDir.fileName();
QString destBaseDir = chooser->filePath().toString(); const FilePath destBaseDir = chooser->filePath();
settings->setValueWithDefault(C_FALLBACK_ROOT, destBaseDir, defaultRootDirectory); settings->setValueWithDefault(C_FALLBACK_ROOT, destBaseDir, defaultRootDirectory);
QDir toDirWithExamplesDir(destBaseDir); const FilePath targetDir = destBaseDir / exampleDirName;
if (toDirWithExamplesDir.cd(exampleDirName)) { if (targetDir.exists()) {
toDirWithExamplesDir.cdUp(); // step out, just to not be in the way
QMessageBox::warning(ICore::dialogParent(), QMessageBox::warning(ICore::dialogParent(),
Tr::tr("Cannot Use Location"), Tr::tr("Cannot Use Location"),
Tr::tr("The specified location already exists. " Tr::tr("The specified location already exists. "
"Please specify a valid location."), "Please specify a valid location."),
QMessageBox::Ok, QMessageBox::Ok,
QMessageBox::NoButton); QMessageBox::NoButton);
return QString(); return {};
} else { } else {
QString targetDir = destBaseDir + QLatin1Char('/') + exampleDirName; expected_str<void> result = projectDir.copyRecursively(targetDir);
expected_str<void> result
= FilePath::fromString(projectDir).copyRecursively(FilePath::fromString(targetDir));
if (result) { if (result) {
// set vars to new location // set vars to new location
const QStringList::Iterator end = filesToOpen.end(); const FilePaths::Iterator end = filesToOpen.end();
for (QStringList::Iterator it = filesToOpen.begin(); it != end; ++it) for (FilePaths::Iterator it = filesToOpen.begin(); it != end; ++it) {
it->replace(projectDir, targetDir); const FilePath relativePath = it->relativeChildPath(projectDir);
*it = targetDir.resolvePath(relativePath);
}
for (const QString &dependency : dependencies) { for (const FilePath &dependency : dependencies) {
const FilePath targetFile = FilePath::fromString(targetDir) const FilePath targetFile = targetDir.pathAppended(dependency.fileName());
.pathAppended(QDir(dependency).dirName()); result = dependency.copyRecursively(targetFile);
result = FilePath::fromString(dependency).copyRecursively(targetFile);
if (!result) { if (!result) {
QMessageBox::warning(ICore::dialogParent(), QMessageBox::warning(ICore::dialogParent(),
Tr::tr("Cannot Copy Project"), Tr::tr("Cannot Copy Project"),
@@ -148,7 +148,7 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
} }
} }
return targetDir + QLatin1Char('/') + proFileInfo.fileName(); return targetDir / proFile.fileName();
} else { } else {
QMessageBox::warning(ICore::dialogParent(), QMessageBox::warning(ICore::dialogParent(),
Tr::tr("Cannot Copy Project"), Tr::tr("Cannot Copy Project"),
@@ -157,46 +157,43 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
} }
} }
if (code == Keep) if (code == Keep)
return proFileInfo.absoluteFilePath(); return proFile.absoluteFilePath();
return QString(); return {};
} }
void ExamplesWelcomePage::openProject(const ExampleItem *item) void ExamplesWelcomePage::openProject(const ExampleItem *item)
{ {
using namespace ProjectExplorer; using namespace ProjectExplorer;
QString proFile = item->projectPath; FilePath proFile = item->projectPath;
if (proFile.isEmpty()) if (proFile.isEmpty())
return; return;
QStringList filesToOpen = item->filesToOpen; FilePaths filesToOpen = item->filesToOpen;
if (!item->mainFile.isEmpty()) { if (!item->mainFile.isEmpty()) {
// ensure that the main file is opened on top (i.e. opened last) // ensure that the main file is opened on top (i.e. opened last)
filesToOpen.removeAll(item->mainFile); filesToOpen.removeAll(item->mainFile);
filesToOpen.append(item->mainFile); filesToOpen.append(item->mainFile);
} }
QFileInfo proFileInfo(proFile); if (!proFile.exists())
if (!proFileInfo.exists())
return; return;
// If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail // If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail
// Same if it is installed in non-writable location for other reasons // Same if it is installed in non-writable location for other reasons
const bool needsCopy = withNtfsPermissions<bool>([proFileInfo] { const bool needsCopy = withNtfsPermissions<bool>([proFile] {
QFileInfo pathInfo(proFileInfo.path()); return !proFile.isWritableFile()
return !proFileInfo.isWritable() || !proFile.parentDir().isWritableDir() /* path of project file */
|| !pathInfo.isWritable() /* path of .pro file */ || !proFile.parentDir().parentDir().isWritableDir() /* shadow build directory */;
|| !QFileInfo(pathInfo.path()).isWritable() /* shadow build directory */;
}); });
if (needsCopy) if (needsCopy)
proFile = copyToAlternativeLocation(proFileInfo, filesToOpen, item->dependencies); proFile = copyToAlternativeLocation(proFile, filesToOpen, item->dependencies);
// don't try to load help and files if loading the help request is being cancelled // don't try to load help and files if loading the help request is being cancelled
if (proFile.isEmpty()) if (proFile.isEmpty())
return; return;
ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::openProject(proFile);
ProjectExplorerPlugin::openProject(FilePath::fromString(proFile));
if (result) { if (result) {
ICore::openFiles(FileUtils::toFilePathList(filesToOpen)); ICore::openFiles(filesToOpen);
ModeManager::activateMode(Core::Constants::MODE_EDIT); ModeManager::activateMode(Core::Constants::MODE_EDIT);
QUrl docUrl = QUrl::fromUserInput(item->docUrl); QUrl docUrl = QUrl::fromUserInput(item->docUrl);
if (docUrl.isValid()) if (docUrl.isValid())

View File

@@ -4,10 +4,7 @@
#pragma once #pragma once
#include <coreplugin/iwelcomepage.h> #include <coreplugin/iwelcomepage.h>
#include <utils/filepath.h>
QT_BEGIN_NAMESPACE
class QFileInfo;
QT_END_NAMESPACE
namespace QtSupport { namespace QtSupport {
namespace Internal { namespace Internal {
@@ -29,7 +26,9 @@ public:
static void openProject(const ExampleItem *item); static void openProject(const ExampleItem *item);
private: private:
static QString copyToAlternativeLocation(const QFileInfo &fileInfo, QStringList &filesToOpen, const QStringList &dependencies); static Utils::FilePath copyToAlternativeLocation(const Utils::FilePath &fileInfo,
Utils::FilePaths &filesToOpen,
const Utils::FilePaths &dependencies);
const bool m_showExamples; const bool m_showExamples;
}; };