From 31517f00bb75c4be2ed61e67399471df9bd23b30 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 10 Apr 2019 18:15:47 +0200 Subject: [PATCH] Wizards: Let user decide which project file to use When importing projects, it can happen that several files are encountered that could serve as the main project file. Until now, we basically opened a random one, which was less than ideal. Now the user can choose. Fixes: QTCREATORBUG-17828 Change-Id: Iec08c942d0f9ff349c9752503c8157556f07b416 Reviewed-by: Eike Ziller Reviewed-by: Leena Miettinen --- .../creator-projects-custom-wizards-json.qdoc | 3 - .../projectexplorer/jsonwizard/jsonwizard.cpp | 102 ++++++++++++++++++ .../jsonwizard/jsonwizardscannergenerator.cpp | 23 ++-- .../jsonwizard/jsonwizardscannergenerator.h | 2 - 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc b/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc index c6dc6a24b4c..e63abe650c6 100644 --- a/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc +++ b/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc @@ -981,9 +981,6 @@ as the top level directory. This setting defaults to an empty list and no subdirectories will be scanned. - \li \c firstProjectOnly is a boolean value, which will determine whether - all project files that were found will be opened as a project or - only the first one. This setting defaults to \c true. \endlist */ diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp index a3bad8656f0..5db2186c46a 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp @@ -36,11 +36,19 @@ #include #include +#include #include +#include #include +#include +#include +#include #include +#include #include +#include +#include #include #ifdef WITH_TESTS @@ -49,6 +57,92 @@ namespace ProjectExplorer { +namespace Internal { + +class ProjectFileTreeItem : public Utils::TreeItem +{ +public: + ProjectFileTreeItem(JsonWizard::GeneratorFile *candidate) : m_candidate(candidate) + { + toggleProjectFileStatus(false); + } + + void toggleProjectFileStatus(bool on) + { + m_candidate->file.setAttributes(m_candidate->file.attributes() + .setFlag(Core::GeneratedFile::OpenProjectAttribute, on)); + } + +private: + QVariant data(int column, int role) const override + { + if (column != 0 || role != Qt::DisplayRole) + return QVariant(); + return QDir::toNativeSeparators(m_candidate->file.path()); + } + + JsonWizard::GeneratorFile * const m_candidate; +}; + +class ProjectFilesModel : public Utils::TreeModel +{ +public: + ProjectFilesModel(const QList &candidates, QObject *parent) + : TreeModel(parent) + { + setHeader({QCoreApplication::translate("ProjectExplorer::JsonWizard", "Project File")}); + for (JsonWizard::GeneratorFile * const candidate : candidates) + rootItem()->appendChild(new ProjectFileTreeItem(candidate)); + } +}; + +class ProjectFileChooser : public QDialog +{ +public: + ProjectFileChooser(const QList &candidates, QWidget *parent) + : QDialog(parent), m_view(new Utils::TreeView(this)) + { + setWindowTitle(QCoreApplication::translate("ProjectExplorer::JsonWizard", + "Choose project file")); + const auto model = new ProjectFilesModel(candidates, this); + m_view->setSelectionMode(Utils::TreeView::ExtendedSelection); + m_view->setSelectionBehavior(Utils::TreeView::SelectRows); + m_view->setModel(model); + const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + const auto updateOkButton = [buttonBox, this] { + buttonBox->button(QDialogButtonBox::Ok) + ->setEnabled(m_view->selectionModel()->hasSelection()); + }; + connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged, + this, updateOkButton); + updateOkButton(); + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + const auto layout = new QVBoxLayout(this); + layout->addWidget(new QLabel(QCoreApplication::translate("ProjectExplorer::JsonWizard", + "The project contains more than one project file. " + "Please select the one you would like to use."))); + layout->addWidget(m_view); + layout->addWidget(buttonBox); + } + +private: + void accept() override + { + const QModelIndexList selected = m_view->selectionModel()->selectedRows(); + const auto * const model = static_cast(m_view->model()); + for (const QModelIndex &index : selected) { + const auto item = static_cast(model->itemForIndex(index)); + QTC_ASSERT(item, continue); + item->toggleProjectFileStatus(true); + } + QDialog::accept(); + } + + Utils::TreeView * const m_view; +}; + +} // namespace Internal + JsonWizard::JsonWizard(QWidget *parent) : Utils::Wizard(parent) { setMinimumSize(800, 500); @@ -113,6 +207,14 @@ JsonWizard::GeneratorFiles JsonWizard::generateFileList() return GeneratorFiles(); } + QList projectFiles; + for (JsonWizard::GeneratorFile &f : list) { + if (f.file.attributes().testFlag(Core::GeneratedFile::OpenProjectAttribute)) + projectFiles << &f; + } + if (projectFiles.count() > 1) + Internal::ProjectFileChooser(projectFiles, this).exec(); + return list; } diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp index 08d3ed1f885..01494d3dd22 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp @@ -42,6 +42,8 @@ #include #include +#include + namespace ProjectExplorer { namespace Internal { @@ -70,8 +72,6 @@ bool JsonWizardScannerGenerator::setup(const QVariant &data, QString *errorMessa m_subDirectoryExpressions << regexp; } - m_firstProjectOnly = gen.value(QLatin1String("firstProjectOnly"), QLatin1String("true")).toString(); - return true; } @@ -97,17 +97,28 @@ Core::GeneratedFiles JsonWizardScannerGenerator::fileList(Utils::MacroExpander * } } - bool onlyFirst = JsonWizard::boolFromVariant(m_firstProjectOnly, expander); - result = scan(project.absolutePath(), project); - int projectCount = 0; + static const auto getDepth = [](const QString &filePath) { return filePath.count('/'); }; + int minDepth = std::numeric_limits::max(); for (auto it = result.begin(); it != result.end(); ++it) { const QString relPath = project.relativeFilePath(it->path()); it->setBinary(binaryPattern.match(relPath).hasMatch()); bool found = ProjectManager::canOpenProjectForMimeType(Utils::mimeTypeForFile(relPath)); - if (found && !(onlyFirst && projectCount++)) + if (found) { it->setAttributes(it->attributes() | Core::GeneratedFile::OpenProjectAttribute); + minDepth = std::min(minDepth, getDepth(it->path())); + } + } + + // Project files that appear on a lower level in the file system hierarchy than + // other project files are not candidates for opening. + for (Core::GeneratedFile &f : result) { + if (f.attributes().testFlag(Core::GeneratedFile::OpenProjectAttribute) + && getDepth(f.path()) > minDepth) { + f.setAttributes(f.attributes().setFlag(Core::GeneratedFile::OpenProjectAttribute, + false)); + } } return result; diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h index e852ad1fe06..76475d4f97c 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h @@ -43,13 +43,11 @@ public: Core::GeneratedFiles fileList(Utils::MacroExpander *expander, const QString &wizardDir, const QString &projectDir, QString *errorMessage) override; - private: Core::GeneratedFiles scan(const QString &dir, const QDir &base); bool matchesSubdirectoryPattern(const QString &path); QString m_binaryPattern; - QString m_firstProjectOnly; QList m_subDirectoryExpressions; };