1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "targetsetuppage.h"
27 #include "buildconfiguration.h"
28 #include "buildinfo.h"
29 #include "importwidget.h"
30 #include "kit.h"
31 #include "kitmanager.h"
32 #include "project.h"
33 #include "projectexplorerconstants.h"
34 #include "session.h"
35 #include "target.h"
36 #include "targetsetupwidget.h"
37 #include "task.h"
38 
39 #include <coreplugin/icore.h>
40 
41 #include <projectexplorer/ipotentialkit.h>
42 
43 #include <utils/qtcassert.h>
44 #include <utils/qtcprocess.h>
45 #include <utils/wizard.h>
46 #include <utils/algorithm.h>
47 #include <utils/fancylineedit.h>
48 
49 #include <QFileInfo>
50 #include <QLabel>
51 #include <QMessageBox>
52 #include <QScrollArea>
53 #include <QVBoxLayout>
54 #include <QCheckBox>
55 
56 using namespace Utils;
57 
58 namespace ProjectExplorer {
59 
60 static QList<IPotentialKit *> g_potentialKits;
61 
IPotentialKit()62 IPotentialKit::IPotentialKit()
63 {
64     g_potentialKits.append(this);
65 }
66 
~IPotentialKit()67 IPotentialKit::~IPotentialKit()
68 {
69     g_potentialKits.removeOne(this);
70 }
71 
72 namespace Internal {
importDirectory(const FilePath & projectPath)73 static FilePath importDirectory(const FilePath &projectPath)
74 {
75     // Setup import widget:
76     auto path = projectPath;
77     path = path.parentDir(); // base dir
78     path = path.parentDir(); // parent dir
79 
80     return path;
81 }
82 
83 class TargetSetupPageUi
84 {
85 public:
86     QWidget *centralWidget;
87     QWidget *scrollAreaWidget;
88     QScrollArea *scrollArea;
89     QLabel *headerLabel;
90     QLabel *noValidKitLabel;
91     QCheckBox *allKitsCheckBox;
92     FancyLineEdit *kitFilterLineEdit;
93 
setupUi(TargetSetupPage * q)94     void setupUi(TargetSetupPage *q)
95     {
96         auto setupTargetPage = new QWidget(q);
97 
98         headerLabel = new QLabel(setupTargetPage);
99         headerLabel->setWordWrap(true);
100         headerLabel->setVisible(false);
101 
102         noValidKitLabel = new QLabel(setupTargetPage);
103         noValidKitLabel->setWordWrap(true);
104         noValidKitLabel->setText("<span style=\" font-weight:600;\">"
105                                  + TargetSetupPage::tr("No suitable kits found.") + "</span><br/>"
106                                  + TargetSetupPage::tr("Add a kit in the <a href=\"buildandrun\">"
107                                                        "options</a> or via the maintenance tool of"
108                                                        " the SDK."));
109         noValidKitLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
110         noValidKitLabel->setVisible(false);
111 
112         allKitsCheckBox = new QCheckBox(setupTargetPage);
113         allKitsCheckBox->setTristate(true);
114         allKitsCheckBox->setText(TargetSetupPage::tr("Select all kits"));
115 
116         kitFilterLineEdit = new FancyLineEdit(setupTargetPage);
117         kitFilterLineEdit->setFiltering(true);
118         kitFilterLineEdit->setPlaceholderText(TargetSetupPage::tr("Type to filter kits by name..."));
119 
120         centralWidget = new QWidget(setupTargetPage);
121         QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed);
122         policy.setHorizontalStretch(0);
123         policy.setVerticalStretch(0);
124         policy.setHeightForWidth(centralWidget->sizePolicy().hasHeightForWidth());
125         centralWidget->setSizePolicy(policy);
126 
127         scrollAreaWidget = new QWidget(setupTargetPage);
128         scrollArea = new QScrollArea(scrollAreaWidget);
129         scrollArea->setWidgetResizable(true);
130 
131         auto scrollAreaWidgetContents = new QWidget();
132         scrollAreaWidgetContents->setGeometry(QRect(0, 0, 230, 81));
133         scrollArea->setWidget(scrollAreaWidgetContents);
134 
135         auto verticalLayout = new QVBoxLayout(scrollAreaWidget);
136         verticalLayout->setSpacing(0);
137         verticalLayout->setContentsMargins(0, 0, 0, 0);
138         verticalLayout->addWidget(scrollArea);
139 
140         auto verticalLayout_2 = new QVBoxLayout(setupTargetPage);
141         verticalLayout_2->addWidget(headerLabel);
142         verticalLayout_2->addWidget(kitFilterLineEdit);
143         verticalLayout_2->addWidget(noValidKitLabel);
144         verticalLayout_2->addWidget(allKitsCheckBox);
145         verticalLayout_2->addWidget(centralWidget);
146         verticalLayout_2->addWidget(scrollAreaWidget);
147 
148         auto verticalLayout_3 = new QVBoxLayout(q);
149         verticalLayout_3->setContentsMargins(0, 0, 0, -1);
150         verticalLayout_3->addWidget(setupTargetPage);
151 
152         QObject::connect(noValidKitLabel, &QLabel::linkActivated,
153                          q, &TargetSetupPage::openOptions);
154 
155         QObject::connect(allKitsCheckBox, &QAbstractButton::clicked,
156                          q, &TargetSetupPage::changeAllKitsSelections);
157 
158         QObject::connect(kitFilterLineEdit, &FancyLineEdit::filterChanged,
159                          q, &TargetSetupPage::kitFilterChanged);
160     }
161 };
162 
163 } // namespace Internal
164 
defaultTasksGenerator(const TasksGenerator & childGenerator)165 static TasksGenerator defaultTasksGenerator(const TasksGenerator &childGenerator)
166 {
167     return [childGenerator](const Kit *k) -> Tasks {
168         if (!k->isValid())
169             return {
170                 CompileTask(Task::Error,
171                             QCoreApplication::translate("ProjectExplorer", "Kit is not valid."))};
172         if (childGenerator)
173             return childGenerator(k);
174         return {};
175     };
176 }
177 
178 using namespace Internal;
179 
TargetSetupPage(QWidget * parent)180 TargetSetupPage::TargetSetupPage(QWidget *parent)
181     : WizardPage(parent)
182     , m_tasksGenerator(defaultTasksGenerator({}))
183     , m_ui(new TargetSetupPageUi)
184     , m_importWidget(new ImportWidget(this))
185     , m_spacer(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding))
186 {
187     m_importWidget->setVisible(false);
188 
189     setObjectName(QLatin1String("TargetSetupPage"));
190     setWindowTitle(tr("Select Kits for Your Project"));
191     m_ui->setupUi(this);
192 
193     QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
194     policy.setHorizontalStretch(0);
195     policy.setVerticalStretch(0);
196     policy.setHeightForWidth(sizePolicy().hasHeightForWidth());
197     setSizePolicy(policy);
198 
199     auto centralWidget = new QWidget(this);
200     m_ui->scrollArea->setWidget(centralWidget);
201     centralWidget->setLayout(new QVBoxLayout);
202     m_ui->centralWidget->setLayout(new QVBoxLayout);
203     m_ui->centralWidget->layout()->setContentsMargins(0, 0, 0, 0);
204 
205     setTitle(tr("Kit Selection"));
206 
207     for (IPotentialKit *pk : qAsConst(g_potentialKits))
208         if (pk->isEnabled())
209             m_potentialWidgets.append(pk->createWidget(this));
210 
211     setUseScrollArea(true);
212 
213     KitManager *km = KitManager::instance();
214     // do note that those slots are triggered once *per* targetsetuppage
215     // thus the same slot can be triggered multiple times on different instances!
216     connect(km, &KitManager::kitAdded, this, &TargetSetupPage::handleKitAddition);
217     connect(km, &KitManager::kitRemoved, this, &TargetSetupPage::handleKitRemoval);
218     connect(km, &KitManager::kitUpdated, this, &TargetSetupPage::handleKitUpdate);
219     connect(m_importWidget, &ImportWidget::importFrom,
__anond4c89d290202(const FilePath &dir) 220             this, [this](const FilePath &dir) { import(dir); });
221     connect(KitManager::instance(), &KitManager::kitsChanged,
222             this, &TargetSetupPage::updateVisibility);
223 
224     setProperty(SHORT_TITLE_PROPERTY, tr("Kits"));
225 }
226 
initializePage()227 void TargetSetupPage::initializePage()
228 {
229     if (KitManager::isLoaded()) {
230         doInitializePage();
231     } else {
232         connect(KitManager::instance(), &KitManager::kitsLoaded,
233                 this, &TargetSetupPage::doInitializePage);
234     }
235 }
236 
setTasksGenerator(const TasksGenerator & tasksGenerator)237 void TargetSetupPage::setTasksGenerator(const TasksGenerator &tasksGenerator)
238 {
239     m_tasksGenerator = defaultTasksGenerator(tasksGenerator);
240 }
241 
selectedKits() const242 QList<Utils::Id> TargetSetupPage::selectedKits() const
243 {
244     QList<Utils::Id> result;
245     for (TargetSetupWidget *w : m_widgets) {
246         if (w->isKitSelected())
247             result.append(w->kit()->id());
248     }
249     return result;
250 }
251 
~TargetSetupPage()252 TargetSetupPage::~TargetSetupPage()
253 {
254     disconnect();
255     reset();
256     delete m_spacer;
257     delete m_ui;
258 }
259 
isComplete() const260 bool TargetSetupPage::isComplete() const
261 {
262     return anyOf(m_widgets, [](const TargetSetupWidget *w) {
263         return w->isKitSelected();
264     });
265 }
266 
setupWidgets(const QString & filterText)267 void TargetSetupPage::setupWidgets(const QString &filterText)
268 {
269     const auto kitList = KitManager::sortKits(KitManager::kits());
270     for (Kit *k : kitList) {
271         if (!filterText.isEmpty() && !k->displayName().contains(filterText, Qt::CaseInsensitive))
272             continue;
273         const auto widget = new TargetSetupWidget(k, m_projectPath);
274         connect(widget, &TargetSetupWidget::selectedToggled,
275                 this, &TargetSetupPage::kitSelectionChanged);
276         connect(widget, &TargetSetupWidget::selectedToggled, this, &QWizardPage::completeChanged);
277         updateWidget(widget);
278         m_widgets.push_back(widget);
279         m_baseLayout->addWidget(widget);
280     }
281     addAdditionalWidgets();
282 
283     // Setup import widget:
284     m_importWidget->setCurrentDirectory(Internal::importDirectory(m_projectPath));
285 
286     kitSelectionChanged();
287     updateVisibility();
288 }
289 
reset()290 void TargetSetupPage::reset()
291 {
292     removeAdditionalWidgets();
293     while (m_widgets.size() > 0) {
294         TargetSetupWidget *w = m_widgets.back();
295 
296         Kit *k = w->kit();
297         if (k && m_importer)
298             m_importer->removeProject(k);
299 
300         removeWidget(w);
301     }
302 
303     m_ui->allKitsCheckBox->setChecked(false);
304 }
305 
widget(const Utils::Id kitId,TargetSetupWidget * fallback) const306 TargetSetupWidget *TargetSetupPage::widget(const Utils::Id kitId,
307                                            TargetSetupWidget *fallback) const
308 {
309     return findOr(m_widgets, fallback, [kitId](const TargetSetupWidget *w) {
310         return w->kit() && w->kit()->id() == kitId;
311     });
312 }
313 
setProjectPath(const FilePath & path)314 void TargetSetupPage::setProjectPath(const FilePath &path)
315 {
316     m_projectPath = path;
317     if (!m_projectPath.isEmpty()) {
318         QFileInfo fileInfo(QDir::cleanPath(path.toString()));
319         QStringList subDirsList = fileInfo.absolutePath().split('/');
320         m_ui->headerLabel->setText(tr("The following kits can be used for project <b>%1</b>:",
321                                       "%1: Project name").arg(subDirsList.last()));
322     }
323     m_ui->headerLabel->setVisible(!m_projectPath.isEmpty());
324 
325     if (m_widgetsWereSetUp)
326         initializePage();
327 }
328 
setProjectImporter(ProjectImporter * importer)329 void TargetSetupPage::setProjectImporter(ProjectImporter *importer)
330 {
331     if (importer == m_importer)
332         return;
333 
334     if (m_widgetsWereSetUp)
335         reset(); // Reset before changing the importer!
336 
337     m_importer = importer;
338     m_importWidget->setVisible(m_importer);
339 
340     if (m_widgetsWereSetUp)
341         initializePage();
342 }
343 
importLineEditHasFocus() const344 bool TargetSetupPage::importLineEditHasFocus() const
345 {
346     return m_importWidget->ownsReturnKey();
347 }
348 
setupImports()349 void TargetSetupPage::setupImports()
350 {
351     if (!m_importer || m_projectPath.isEmpty())
352         return;
353 
354     const QStringList toImport = m_importer->importCandidates();
355     for (const QString &path : toImport)
356         import(FilePath::fromString(path), true);
357 }
358 
handleKitAddition(Kit * k)359 void TargetSetupPage::handleKitAddition(Kit *k)
360 {
361     if (isUpdating())
362         return;
363 
364     Q_ASSERT(!widget(k));
365     addWidget(k);
366     kitSelectionChanged();
367     updateVisibility();
368 }
369 
handleKitRemoval(Kit * k)370 void TargetSetupPage::handleKitRemoval(Kit *k)
371 {
372     if (isUpdating())
373         return;
374 
375     if (m_importer)
376         m_importer->cleanupKit(k);
377 
378     removeWidget(k);
379     kitSelectionChanged();
380     updateVisibility();
381 }
382 
handleKitUpdate(Kit * k)383 void TargetSetupPage::handleKitUpdate(Kit *k)
384 {
385     if (isUpdating())
386         return;
387 
388     if (m_importer)
389         m_importer->makePersistent(k);
390 
391     const auto newWidgetList = sortedWidgetList();
392     if (newWidgetList != m_widgets) { // Sorting has changed.
393         m_widgets = newWidgetList;
394         reLayout();
395     }
396     updateWidget(widget(k));
397     kitSelectionChanged();
398     updateVisibility();
399 }
400 
selectAtLeastOneEnabledKit()401 void TargetSetupPage::selectAtLeastOneEnabledKit()
402 {
403     if (anyOf(m_widgets, [](const TargetSetupWidget *w) { return w->isKitSelected(); })) {
404         // Something is already selected, we are done.
405         return;
406     }
407 
408     TargetSetupWidget *toCheckWidget = nullptr;
409 
410     const Kit *defaultKit = KitManager::defaultKit();
411 
412     auto isPreferred = [this](const TargetSetupWidget *w) {
413         const Tasks tasks = m_tasksGenerator(w->kit());
414         return w->isEnabled() && tasks.isEmpty();
415     };
416 
417     // Use default kit if that is preferred:
418     toCheckWidget = findOrDefault(m_widgets, [defaultKit, isPreferred](const TargetSetupWidget *w) {
419         return isPreferred(w) && w->kit() == defaultKit;
420     });
421 
422     if (!toCheckWidget) {
423         // Use the first preferred widget:
424         toCheckWidget = findOrDefault(m_widgets, isPreferred);
425     }
426 
427     if (!toCheckWidget) {
428         // Use default kit if it is enabled:
429         toCheckWidget = findOrDefault(m_widgets, [defaultKit](const TargetSetupWidget *w) {
430             return w->isEnabled() && w->kit() == defaultKit;
431         });
432     }
433 
434     if (!toCheckWidget) {
435         // Use the first enabled widget:
436         toCheckWidget = findOrDefault(m_widgets,
437                                       [](const TargetSetupWidget *w) { return w->isEnabled(); });
438     }
439 
440     if (toCheckWidget) {
441         toCheckWidget->setKitSelected(true);
442 
443         emit completeChanged(); // Is this necessary?
444     }
445 }
446 
updateVisibility()447 void TargetSetupPage::updateVisibility()
448 {
449     // Always show the widgets, the import widget always makes sense to show.
450     m_ui->scrollAreaWidget->setVisible(m_baseLayout == m_ui->scrollArea->widget()->layout());
451     m_ui->centralWidget->setVisible(m_baseLayout == m_ui->centralWidget->layout());
452 
453     const bool hasUsableKits = KitManager::kit([this](const Kit *k) { return isUsable(k); });
454     m_ui->noValidKitLabel->setVisible(!hasUsableKits);
455     m_ui->allKitsCheckBox->setVisible(hasUsableKits);
456 
457     emit completeChanged();
458 }
459 
reLayout()460 void TargetSetupPage::reLayout()
461 {
462     removeAdditionalWidgets();
463     for (TargetSetupWidget * const w : qAsConst(m_widgets))
464         m_baseLayout->removeWidget(w);
465     for (TargetSetupWidget * const w : qAsConst(m_widgets))
466         m_baseLayout->addWidget(w);
467     addAdditionalWidgets();
468 }
469 
compareKits(const Kit * k1,const Kit * k2)470 bool TargetSetupPage::compareKits(const Kit *k1, const Kit *k2)
471 {
472     const QString name1 = k1->displayName();
473     const QString name2 = k2->displayName();
474     if (name1 < name2)
475         return true;
476     if (name1 > name2)
477         return false;
478     return k1 < k2;
479 }
480 
sortedWidgetList() const481 std::vector<TargetSetupWidget *> TargetSetupPage::sortedWidgetList() const
482 {
483     std::vector<TargetSetupWidget *> list = m_widgets;
484     sort(list, [](const TargetSetupWidget *w1, const TargetSetupWidget *w2) {
485         return compareKits(w1->kit(), w2->kit());
486     });
487     return list;
488 }
489 
openOptions()490 void TargetSetupPage::openOptions()
491 {
492     Core::ICore::showOptionsDialog(Constants::KITS_SETTINGS_PAGE_ID, this);
493 }
494 
kitSelectionChanged()495 void TargetSetupPage::kitSelectionChanged()
496 {
497     int selected = 0;
498     int deselected = 0;
499     for (const TargetSetupWidget *widget : m_widgets) {
500         if (widget->isKitSelected())
501             ++selected;
502         else
503             ++deselected;
504     }
505     if (selected > 0 && deselected > 0)
506         m_ui->allKitsCheckBox->setCheckState(Qt::PartiallyChecked);
507     else if (selected > 0 && deselected == 0)
508         m_ui->allKitsCheckBox->setCheckState(Qt::Checked);
509     else
510         m_ui->allKitsCheckBox->setCheckState(Qt::Unchecked);
511 }
512 
kitFilterChanged(const QString & filterText)513 void TargetSetupPage::kitFilterChanged(const QString &filterText)
514 {
515     // Remember selected kits:
516     const std::vector<TargetSetupWidget *> selectedWidgets
517         = filtered(m_widgets, &TargetSetupWidget::isKitSelected);
518     const QVector<Utils::Id> selectedKitIds = transform<QVector>(selectedWidgets,
519                                                                 [](const TargetSetupWidget *w) {
520                                                                     return w->kit()->id();
521                                                                 });
522 
523     // Reset currently shown kits
524     reset();
525     setupWidgets(filterText);
526 
527     // Re-select kits:
528     for (TargetSetupWidget *w : qAsConst(m_widgets))
529         w->setKitSelected(selectedKitIds.contains(w->kit()->id()));
530 }
531 
doInitializePage()532 void TargetSetupPage::doInitializePage()
533 {
534     reset();
535     setupWidgets();
536     setupImports();
537 
538     selectAtLeastOneEnabledKit();
539 
540     updateVisibility();
541 }
542 
showEvent(QShowEvent * event)543 void TargetSetupPage::showEvent(QShowEvent *event)
544 {
545     WizardPage::showEvent(event);
546     setFocus(); // Ensure "Configure Project" gets triggered on <Return>
547 }
548 
changeAllKitsSelections()549 void TargetSetupPage::changeAllKitsSelections()
550 {
551     if (m_ui->allKitsCheckBox->checkState() == Qt::PartiallyChecked)
552         m_ui->allKitsCheckBox->setCheckState(Qt::Checked);
553     bool checked = m_ui->allKitsCheckBox->isChecked();
554     for (TargetSetupWidget *widget : m_widgets)
555         widget->setKitSelected(checked);
556     emit completeChanged();
557 }
558 
isUpdating() const559 bool TargetSetupPage::isUpdating() const
560 {
561     return m_importer && m_importer->isUpdating();
562 }
563 
import(const FilePath & path,bool silent)564 void TargetSetupPage::import(const FilePath &path, bool silent)
565 {
566     if (!m_importer)
567         return;
568 
569     for (const BuildInfo &info : m_importer->import(path, silent)) {
570         TargetSetupWidget *w = widget(info.kitId);
571         if (!w) {
572             Kit *k = KitManager::kit(info.kitId);
573             Q_ASSERT(k);
574             addWidget(k);
575         }
576         w = widget(info.kitId);
577         if (!w)
578             continue;
579 
580         w->addBuildInfo(info, true);
581         w->setKitSelected(true);
582         w->expandWidget();
583         kitSelectionChanged();
584     }
585     emit completeChanged();
586 }
587 
removeWidget(TargetSetupWidget * w)588 void TargetSetupPage::removeWidget(TargetSetupWidget *w)
589 {
590     if (!w)
591         return;
592     w->deleteLater();
593     w->clearKit();
594     m_widgets.erase(std::find(m_widgets.begin(), m_widgets.end(), w));
595 }
596 
addWidget(Kit * k)597 TargetSetupWidget *TargetSetupPage::addWidget(Kit *k)
598 {
599     const auto widget = new TargetSetupWidget(k, m_projectPath);
600     updateWidget(widget);
601     connect(widget, &TargetSetupWidget::selectedToggled,
602             this, &TargetSetupPage::kitSelectionChanged);
603     connect(widget, &TargetSetupWidget::selectedToggled, this, &QWizardPage::completeChanged);
604 
605 
606     // Insert widget, sorted.
607     const auto insertionPos = std::find_if(m_widgets.begin(), m_widgets.end(),
608                                            [k](const TargetSetupWidget *w) {
609         return compareKits(k, w->kit());
610     });
611     const bool addedToEnd = insertionPos == m_widgets.end();
612     m_widgets.insert(insertionPos, widget);
613     if (addedToEnd) {
614         removeAdditionalWidgets();
615         m_baseLayout->addWidget(widget);
616         addAdditionalWidgets();
617     } else {
618         reLayout();
619     }
620 
621     return widget;
622 }
623 
addAdditionalWidgets()624 void TargetSetupPage::addAdditionalWidgets()
625 {
626     m_baseLayout->addWidget(m_importWidget);
627     for (QWidget * const widget : qAsConst(m_potentialWidgets))
628         m_baseLayout->addWidget(widget);
629     m_baseLayout->addItem(m_spacer);
630 }
631 
removeAdditionalWidgets(QLayout * layout)632 void TargetSetupPage::removeAdditionalWidgets(QLayout *layout)
633 {
634     layout->removeWidget(m_importWidget);
635     for (QWidget * const potentialWidget : qAsConst(m_potentialWidgets))
636         layout->removeWidget(potentialWidget);
637     layout->removeItem(m_spacer);
638 }
639 
updateWidget(TargetSetupWidget * widget)640 void TargetSetupPage::updateWidget(TargetSetupWidget *widget)
641 {
642     QTC_ASSERT(widget, return );
643     widget->update(m_tasksGenerator);
644 }
645 
isUsable(const Kit * kit) const646 bool TargetSetupPage::isUsable(const Kit *kit) const
647 {
648     return !containsType(m_tasksGenerator(kit), Task::Error);
649 }
650 
setupProject(Project * project)651 bool TargetSetupPage::setupProject(Project *project)
652 {
653     QList<BuildInfo> toSetUp;
654     for (TargetSetupWidget *widget : m_widgets) {
655         if (!widget->isKitSelected())
656             continue;
657 
658         Kit *k = widget->kit();
659 
660         if (k && m_importer)
661             m_importer->makePersistent(k);
662         toSetUp << widget->selectedBuildInfoList();
663         widget->clearKit();
664     }
665 
666     project->setup(toSetUp);
667     toSetUp.clear();
668 
669     // Only reset now that toSetUp has been cleared!
670     reset();
671 
672     Target *activeTarget = nullptr;
673     if (m_importer)
674         activeTarget = m_importer->preferredTarget(project->targets());
675     if (activeTarget)
676         SessionManager::setActiveTarget(project, activeTarget, SetActive::NoCascade);
677 
678     return true;
679 }
680 
setUseScrollArea(bool b)681 void TargetSetupPage::setUseScrollArea(bool b)
682 {
683     QLayout *oldBaseLayout = m_baseLayout;
684     m_baseLayout = b ? m_ui->scrollArea->widget()->layout() : m_ui->centralWidget->layout();
685     if (oldBaseLayout == m_baseLayout)
686         return;
687     m_ui->scrollAreaWidget->setVisible(b);
688     m_ui->centralWidget->setVisible(!b);
689 
690     if (oldBaseLayout)
691         removeAdditionalWidgets(oldBaseLayout);
692     addAdditionalWidgets();
693 }
694 
695 } // namespace ProjectExplorer
696