summaryrefslogtreecommitdiff
path: root/src/plugins/projectexplorer/targetsetuppage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/projectexplorer/targetsetuppage.cpp')
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
new file mode 100644
index 0000000000..ddbf1911e0
--- /dev/null
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -0,0 +1,531 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "targetsetuppage.h"
+#include "buildconfiguration.h"
+#include "buildinfo.h"
+#include "kit.h"
+#include "kitmanager.h"
+#include "importwidget.h"
+#include "project.h"
+#include "projectexplorerconstants.h"
+#include "target.h"
+#include "targetsetupwidget.h"
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QFileInfo>
+#include <QLabel>
+#include <QMessageBox>
+#include <QScrollArea>
+#include <QVBoxLayout>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class TargetSetupPageUi
+{
+public:
+ QWidget *centralWidget;
+ QWidget *scrollAreaWidget;
+ QScrollArea *scrollArea;
+ QLabel *headerLabel;
+ QLabel *descriptionLabel;
+ QLabel *noValidKitLabel;
+ QLabel *optionHintLabel;
+
+ void setupUi(QWidget *q)
+ {
+ QWidget *setupTargetPage = new QWidget(q);
+ descriptionLabel = new QLabel(setupTargetPage);
+ descriptionLabel->setWordWrap(true);
+ descriptionLabel->setVisible(false);
+
+ headerLabel = new QLabel(setupTargetPage);
+ headerLabel->setWordWrap(true);
+ headerLabel->setVisible(false);
+
+ noValidKitLabel = new QLabel(setupTargetPage);
+ noValidKitLabel->setWordWrap(true);
+ noValidKitLabel->setText(TargetSetupPage::tr("<span style=\" font-weight:600;\">No valid kits found.</span>"));
+
+
+ optionHintLabel = new QLabel(setupTargetPage);
+ optionHintLabel->setWordWrap(true);
+ optionHintLabel->setText(TargetSetupPage::tr(
+ "Please add a kit in the <a href=\"buildandrun\">options</a> "
+ "or via the maintenance tool of the SDK."));
+ optionHintLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ optionHintLabel->setVisible(false);
+
+ centralWidget = new QWidget(setupTargetPage);
+ QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ policy.setHorizontalStretch(0);
+ policy.setVerticalStretch(0);
+ policy.setHeightForWidth(centralWidget->sizePolicy().hasHeightForWidth());
+ centralWidget->setSizePolicy(policy);
+
+ scrollAreaWidget = new QWidget(setupTargetPage);
+ scrollArea = new QScrollArea(scrollAreaWidget);
+ scrollArea->setWidgetResizable(true);
+
+ QWidget *scrollAreaWidgetContents;
+ scrollAreaWidgetContents = new QWidget();
+ scrollAreaWidgetContents->setGeometry(QRect(0, 0, 230, 81));
+ scrollArea->setWidget(scrollAreaWidgetContents);
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout(scrollAreaWidget);
+ verticalLayout->setSpacing(0);
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+ verticalLayout->addWidget(scrollArea);
+
+ QVBoxLayout *verticalLayout_2 = new QVBoxLayout(setupTargetPage);
+ verticalLayout_2->addWidget(headerLabel);
+ verticalLayout_2->addWidget(noValidKitLabel);
+ verticalLayout_2->addWidget(descriptionLabel);
+ verticalLayout_2->addWidget(optionHintLabel);
+ verticalLayout_2->addWidget(centralWidget);
+ verticalLayout_2->addWidget(scrollAreaWidget);
+
+ QVBoxLayout *verticalLayout_3 = new QVBoxLayout(q);
+ verticalLayout_3->setContentsMargins(0, 0, 0, -1);
+ verticalLayout_3->addWidget(setupTargetPage);
+
+ QObject::connect(optionHintLabel, SIGNAL(linkActivated(QString)),
+ q, SLOT(openOptions()));
+ }
+};
+
+} // namespace Internal
+
+using namespace Internal;
+
+TargetSetupPage::TargetSetupPage(QWidget *parent) :
+ QWizardPage(parent),
+ m_requiredMatcher(0),
+ m_preferredMatcher(0),
+ m_importer(0),
+ m_baseLayout(0),
+ m_importSearch(false),
+ m_firstWidget(0),
+ m_ui(new TargetSetupPageUi),
+ m_importWidget(new Internal::ImportWidget(this)),
+ m_spacer(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)),
+ m_forceOptionHint(false)
+{
+ setObjectName(QLatin1String("TargetSetupPage"));
+ setWindowTitle(tr("Select Kits for Your Project"));
+ m_ui->setupUi(this);
+
+ QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ policy.setHorizontalStretch(0);
+ policy.setVerticalStretch(0);
+ policy.setHeightForWidth(sizePolicy().hasHeightForWidth());
+ setSizePolicy(policy);
+
+ QWidget *centralWidget = new QWidget(this);
+ m_ui->scrollArea->setWidget(centralWidget);
+ centralWidget->setLayout(new QVBoxLayout);
+ m_ui->centralWidget->setLayout(new QVBoxLayout);
+ m_ui->centralWidget->layout()->setMargin(0);
+
+ setUseScrollArea(true);
+ setImportSearch(false);
+
+ setTitle(tr("Kit Selection"));
+
+ QObject *km = KitManager::instance();
+ connect(km, SIGNAL(kitAdded(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitAddition(ProjectExplorer::Kit*)));
+ connect(km, SIGNAL(kitRemoved(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitRemoval(ProjectExplorer::Kit*)));
+ connect(km, SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitUpdate(ProjectExplorer::Kit*)));
+ connect(m_importWidget, SIGNAL(importFrom(Utils::FileName)),
+ this, SLOT(import(Utils::FileName)));
+}
+
+void TargetSetupPage::initializePage()
+{
+ reset();
+
+ setupWidgets();
+ setupImports();
+ selectAtLeastOneKit();
+}
+
+void TargetSetupPage::setRequiredKitMatcher(KitMatcher *matcher)
+{
+ m_requiredMatcher = matcher;
+}
+
+QList<Core::Id> TargetSetupPage::selectedKits() const
+{
+ QList<Core::Id> result;
+ QMap<Core::Id, Internal::TargetSetupWidget *>::const_iterator it, end;
+ it = m_widgets.constBegin();
+ end = m_widgets.constEnd();
+
+ for ( ; it != end; ++it) {
+ if (isKitSelected(it.key()))
+ result << it.key();
+ }
+ return result;
+}
+
+void TargetSetupPage::setPreferredKitMatcher(KitMatcher *matcher)
+{
+ m_preferredMatcher = matcher;
+}
+
+TargetSetupPage::~TargetSetupPage()
+{
+ reset();
+ delete m_ui;
+ delete m_preferredMatcher;
+ delete m_requiredMatcher;
+ delete m_importer;
+}
+
+bool TargetSetupPage::isKitSelected(Core::Id id) const
+{
+ TargetSetupWidget *widget = m_widgets.value(id);
+ return widget && widget->isKitSelected();
+}
+
+void TargetSetupPage::setKitSelected(Core::Id id, bool selected)
+{
+ TargetSetupWidget *widget = m_widgets.value(id);
+ if (widget)
+ widget->setKitSelected(selected);
+}
+
+bool TargetSetupPage::isComplete() const
+{
+ foreach (TargetSetupWidget *widget, m_widgets.values())
+ if (widget->isKitSelected())
+ return true;
+ return false;
+}
+
+void TargetSetupPage::setImportSearch(bool b)
+{
+ m_importSearch = b;
+ m_importWidget->setVisible(b);
+}
+
+void TargetSetupPage::setupWidgets()
+{
+ QList<Kit *> kitList;
+ // Known profiles:
+ if (m_requiredMatcher)
+ kitList = KitManager::matchingKits(*m_requiredMatcher);
+ else
+ kitList = KitManager::kits();
+
+ foreach (Kit *k, kitList)
+ addWidget(k);
+
+ // Setup import widget:
+ m_baseLayout->addWidget(m_importWidget);
+ Utils::FileName path = Utils::FileName::fromString(m_projectPath);
+ path = path.parentDir(); // base dir
+ path = path.parentDir(); // parent dir
+ m_importWidget->setCurrentDirectory(path);
+
+ updateVisibility();
+}
+
+void TargetSetupPage::reset()
+{
+ foreach (TargetSetupWidget *widget, m_widgets.values()) {
+ Kit *k = widget->kit();
+ if (!k)
+ continue;
+ if (m_importer)
+ m_importer->removeProject(k, m_projectPath);
+ delete widget;
+ }
+
+ m_widgets.clear();
+ m_firstWidget = 0;
+}
+
+void TargetSetupPage::setProjectPath(const QString &path)
+{
+ m_projectPath = path;
+ if (!m_projectPath.isEmpty())
+ m_ui->headerLabel->setText(tr("Qt Creator can use the following kits for project <b>%1</b>:",
+ "%1: Project name").arg(QFileInfo(m_projectPath).baseName()));
+ m_ui->headerLabel->setVisible(!m_projectPath.isEmpty());
+
+ if (m_widgets.isEmpty())
+ return;
+
+ reset();
+ setupWidgets();
+}
+
+void TargetSetupPage::setProjectImporter(ProjectImporter *importer)
+{
+ if (m_importer)
+ delete m_importer;
+ m_importer = importer;
+
+ reset();
+ setupWidgets();
+}
+
+void TargetSetupPage::setNoteText(const QString &text)
+{
+ m_ui->descriptionLabel->setText(text);
+ m_ui->descriptionLabel->setVisible(!text.isEmpty());
+}
+
+void TargetSetupPage::showOptionsHint(bool show)
+{
+ m_forceOptionHint = show;
+ updateVisibility();
+}
+
+void TargetSetupPage::setupImports()
+{
+ if (!m_importer || !m_importSearch || m_projectPath.isEmpty())
+ return;
+
+ QStringList toImport = m_importer->importCandidates(Utils::FileName::fromString(m_projectPath));
+ foreach (const QString &path, toImport)
+ import(Utils::FileName::fromString(path), true);
+}
+
+void TargetSetupPage::handleKitAddition(Kit *k)
+{
+ if (isUpdating())
+ return;
+
+ Q_ASSERT(!m_widgets.contains(k->id()));
+ addWidget(k);
+ updateVisibility();
+}
+
+void TargetSetupPage::handleKitRemoval(Kit *k)
+{
+ if (m_importer)
+ m_importer->cleanupKit(k);
+
+ if (isUpdating())
+ return;
+
+ removeWidget(k);
+ updateVisibility();
+}
+
+void TargetSetupPage::handleKitUpdate(Kit *k)
+{
+ if (isUpdating())
+ return;
+
+ if (m_importer)
+ m_importer->makePermanent(k);
+
+ TargetSetupWidget *widget = m_widgets.value(k->id());
+
+ bool acceptable = true;
+ if (m_requiredMatcher && !m_requiredMatcher->matches(k))
+ acceptable = false;
+
+ if (widget && !acceptable)
+ removeWidget(k);
+ else if (!widget && acceptable)
+ addWidget(k);
+
+ updateVisibility();
+}
+
+void TargetSetupPage::selectAtLeastOneKit()
+{
+ bool atLeastOneKitSelected = false;
+ foreach (TargetSetupWidget *w, m_widgets.values()) {
+ if (w->isKitSelected()) {
+ atLeastOneKitSelected = true;
+ break;
+ }
+ }
+
+ if (!atLeastOneKitSelected) {
+ TargetSetupWidget *widget = m_firstWidget;
+ Kit *defaultKit = KitManager::defaultKit();
+ if (defaultKit)
+ widget = m_widgets.value(defaultKit->id(), m_firstWidget);
+ if (widget)
+ widget->setKitSelected(true);
+ m_firstWidget = 0;
+ }
+ emit completeChanged(); // Is this necessary?
+}
+
+void TargetSetupPage::updateVisibility()
+{
+ // Always show the widgets, the import widget always makes sense to show.
+ m_ui->scrollAreaWidget->setVisible(m_baseLayout == m_ui->scrollArea->widget()->layout());
+ m_ui->centralWidget->setVisible(m_baseLayout == m_ui->centralWidget->layout());
+
+ bool hasKits = !m_widgets.isEmpty();
+ m_ui->noValidKitLabel->setVisible(!hasKits);
+ m_ui->optionHintLabel->setVisible(m_forceOptionHint || !hasKits);
+
+ emit completeChanged();
+}
+
+void TargetSetupPage::openOptions()
+{
+ Core::ICore::instance()->showOptionsDialog(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY,
+ Constants::KITS_SETTINGS_PAGE_ID,
+ this);
+}
+
+void TargetSetupPage::import(const Utils::FileName &path)
+{
+ import(path, false);
+}
+
+bool TargetSetupPage::isUpdating() const
+{
+ if (m_importer)
+ return m_importer->isUpdating();
+ return false;
+}
+
+void TargetSetupPage::import(const Utils::FileName &path, bool silent)
+{
+ if (!m_importer)
+ return;
+
+ QList<BuildInfo *> toImport = m_importer->import(path, silent);
+ foreach (BuildInfo *info, toImport) {
+ TargetSetupWidget *widget = m_widgets.value(info->kitId, 0);
+ if (!widget) {
+ Kit *k = KitManager::find(info->kitId);
+ Q_ASSERT(k);
+ addWidget(k);
+ }
+ widget = m_widgets.value(info->kitId, 0);
+ if (!widget) {
+ delete info;
+ continue;
+ }
+
+ widget->addBuildInfo(info, true);
+ widget->setKitSelected(true);
+ }
+}
+
+void TargetSetupPage::removeWidget(Kit *k)
+{
+ TargetSetupWidget *widget = m_widgets.value(k->id());
+ if (!widget)
+ return;
+ if (widget == m_firstWidget)
+ m_firstWidget = 0;
+ widget->deleteLater();
+ m_widgets.remove(k->id());
+}
+
+TargetSetupWidget *TargetSetupPage::addWidget(Kit *k)
+{
+ if (!k || (m_requiredMatcher && !m_requiredMatcher->matches(k)))
+ return 0;
+
+ IBuildConfigurationFactory *factory
+ = IBuildConfigurationFactory::find(k, m_projectPath);
+ if (!factory)
+ return 0;
+
+ QList<BuildInfo *> infoList = factory->availableSetups(k, m_projectPath);
+ TargetSetupWidget *widget = infoList.isEmpty() ? 0 : new TargetSetupWidget(k, m_projectPath, infoList);
+ if (!widget)
+ return 0;
+
+ m_baseLayout->removeWidget(m_importWidget);
+ m_baseLayout->removeItem(m_spacer);
+
+ widget->setKitSelected(m_preferredMatcher && m_preferredMatcher->matches(k));
+ m_widgets.insert(k->id(), widget);
+ m_baseLayout->addWidget(widget);
+
+ m_baseLayout->addWidget(m_importWidget);
+ m_baseLayout->addItem(m_spacer);
+
+ connect(widget, SIGNAL(selectedToggled()),
+ this, SIGNAL(completeChanged()));
+
+ if (!m_firstWidget)
+ m_firstWidget = widget;
+
+ return widget;
+}
+
+bool TargetSetupPage::setupProject(Project *project)
+{
+ QList<const BuildInfo *> toSetUp; // Pointers are managed by the widgets!
+ foreach (TargetSetupWidget *widget, m_widgets.values()) {
+ if (!widget->isKitSelected())
+ continue;
+
+ Kit *k = widget->kit();
+ if (m_importer)
+ m_importer->makePermanent(k);
+ toSetUp << widget->selectedBuildInfoList();
+ widget->clearKit();
+ }
+
+ project->setup(toSetUp);
+
+ reset(); // This will delete the pointers held in toSetUp!
+ toSetUp.clear();
+
+ Target *activeTarget = 0;
+ if (m_importer)
+ activeTarget = m_importer->preferredTarget(project->targets());
+ if (activeTarget)
+ project->setActiveTarget(activeTarget);
+
+ return true;
+}
+
+void TargetSetupPage::setUseScrollArea(bool b)
+{
+ m_baseLayout = b ? m_ui->scrollArea->widget()->layout() : m_ui->centralWidget->layout();
+ m_ui->scrollAreaWidget->setVisible(b);
+ m_ui->centralWidget->setVisible(!b);
+}
+
+} // namespace ProjectExplorer