androidsettingswidget.cpp 19.4 KB
Newer Older
1
/****************************************************************************
BogDan Vatra's avatar
BogDan Vatra committed
2
**
3
4
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
BogDan Vatra's avatar
BogDan Vatra committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
BogDan Vatra's avatar
BogDan Vatra committed
7
**
hjk's avatar
hjk committed
8
9
10
11
** 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
12
13
14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
BogDan Vatra's avatar
BogDan Vatra committed
15
**
16
17
18
19
20
21
22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
BogDan Vatra's avatar
BogDan Vatra committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
BogDan Vatra's avatar
BogDan Vatra committed
25
26
27
28
29
30
31

#include "androidsettingswidget.h"

#include "ui_androidsettingswidget.h"

#include "androidconfigurations.h"
#include "androidconstants.h"
Daniel Teske's avatar
Daniel Teske committed
32
#include "androidtoolchain.h"
Vikas Pachdha's avatar
Vikas Pachdha committed
33
#include "androidavdmanager.h"
BogDan Vatra's avatar
BogDan Vatra committed
34

35
#include <utils/environment.h>
36
#include <utils/hostosinfo.h>
37
#include <utils/pathchooser.h>
Eike Ziller's avatar
Eike Ziller committed
38
#include <utils/runextensions.h>
Ulf Hermann's avatar
Ulf Hermann committed
39
#include <utils/utilsicons.h>
Daniel Teske's avatar
Daniel Teske committed
40
41
42
#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/kitinformation.h>
43
#include <projectexplorer/projectexplorerconstants.h>
Daniel Teske's avatar
Daniel Teske committed
44
45
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
46

BogDan Vatra's avatar
BogDan Vatra committed
47
48
49
#include <QFile>
#include <QTextStream>
#include <QProcess>
50
51
#include <QTimer>
#include <QTime>
BogDan Vatra's avatar
BogDan Vatra committed
52

53
#include <QDesktopServices>
BogDan Vatra's avatar
BogDan Vatra committed
54
55
56
#include <QFileDialog>
#include <QMessageBox>
#include <QModelIndex>
57
#include <QtCore/QUrl>
BogDan Vatra's avatar
BogDan Vatra committed
58
59
60
61

namespace Android {
namespace Internal {

Vikas Pachdha's avatar
Vikas Pachdha committed
62
void AvdModel::setAvdList(const AndroidDeviceInfoList &list)
BogDan Vatra's avatar
BogDan Vatra committed
63
{
64
    beginResetModel();
BogDan Vatra's avatar
BogDan Vatra committed
65
    m_list = list;
66
    endResetModel();
BogDan Vatra's avatar
BogDan Vatra committed
67
68
}

69
70
71
72
73
74
75
76
77
QModelIndex AvdModel::indexForAvdName(const QString &avdName) const
{
    for (int i = 0; i < m_list.size(); ++i) {
        if (m_list.at(i).serialNumber == avdName)
            return index(i, 0);
    }
    return QModelIndex();
}

78
QString AvdModel::avdName(const QModelIndex &index) const
BogDan Vatra's avatar
BogDan Vatra committed
79
{
80
    return m_list.at(index.row()).avdname;
BogDan Vatra's avatar
BogDan Vatra committed
81
82
}

hjk's avatar
hjk committed
83
QVariant AvdModel::data(const QModelIndex &index, int role) const
BogDan Vatra's avatar
BogDan Vatra committed
84
85
86
87
88
{
    if (role != Qt::DisplayRole || !index.isValid())
        return QVariant();
    switch (index.column()) {
        case 0:
89
            return m_list[index.row()].avdname;
BogDan Vatra's avatar
BogDan Vatra committed
90
91
        case 1:
            return QString::fromLatin1("API %1").arg(m_list[index.row()].sdk);
92
93
94
95
        case 2: {
            QStringList cpuAbis = m_list[index.row()].cpuAbi;
            return cpuAbis.isEmpty() ? QVariant() : QVariant(cpuAbis.first());
        }
BogDan Vatra's avatar
BogDan Vatra committed
96
97
98
99
    }
    return QVariant();
}

hjk's avatar
hjk committed
100
QVariant AvdModel::headerData(int section, Qt::Orientation orientation, int role) const
BogDan Vatra's avatar
BogDan Vatra committed
101
102
103
104
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        switch (section) {
            case 0:
Friedemann Kleint's avatar
Friedemann Kleint committed
105
                //: AVD - Android Virtual Device
BogDan Vatra's avatar
BogDan Vatra committed
106
107
108
109
110
111
112
113
114
115
                return tr("AVD Name");
            case 1:
                return tr("AVD Target");
            case 2:
                return tr("CPU/ABI");
        }
    }
    return QAbstractItemModel::headerData(section, orientation, role );
}

hjk's avatar
hjk committed
116
int AvdModel::rowCount(const QModelIndex &/*parent*/) const
BogDan Vatra's avatar
BogDan Vatra committed
117
118
119
120
{
    return m_list.size();
}

hjk's avatar
hjk committed
121
int AvdModel::columnCount(const QModelIndex &/*parent*/) const
BogDan Vatra's avatar
BogDan Vatra committed
122
123
124
125
126
127
{
    return 3;
}

AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
    : QWidget(parent),
Daniel Teske's avatar
Daniel Teske committed
128
129
130
      m_sdkState(NotSet),
      m_ndkState(NotSet),
      m_javaState(NotSet),
BogDan Vatra's avatar
BogDan Vatra committed
131
      m_ui(new Ui_AndroidSettingsWidget),
132
      m_androidConfig(AndroidConfigurations::currentConfig()),
Vikas Pachdha's avatar
Vikas Pachdha committed
133
      m_avdManager(new AndroidAvdManager(m_androidConfig))
BogDan Vatra's avatar
BogDan Vatra committed
134
{
Daniel Teske's avatar
Daniel Teske committed
135
    m_ui->setupUi(this);
BogDan Vatra's avatar
BogDan Vatra committed
136

137
138
139
140
    m_ui->SDKLocationPathChooser->setFileName(m_androidConfig.sdkLocation());
    m_ui->SDKLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK folder"));
    m_ui->NDKLocationPathChooser->setFileName(m_androidConfig.ndkLocation());
    m_ui->NDKLocationPathChooser->setPromptDialogTitle(tr("Select Android NDK folder"));
BogDan Vatra's avatar
BogDan Vatra committed
141

142
143
    m_ui->OpenJDKLocationPathChooser->setFileName(m_androidConfig.openJDKLocation());
    m_ui->OpenJDKLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path"));
Daniel Teske's avatar
Daniel Teske committed
144
145
    m_ui->DataPartitionSizeSpinBox->setValue(m_androidConfig.partitionSize());
    m_ui->CreateKitCheckBox->setChecked(m_androidConfig.automaticKitCreation());
BogDan Vatra's avatar
BogDan Vatra committed
146
    m_ui->AVDTableView->setModel(&m_AVDModel);
147
148
    m_ui->AVDTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_ui->AVDTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
Daniel Teske's avatar
Daniel Teske committed
149

150
    m_ui->downloadOpenJDKToolButton->setVisible(!Utils::HostOsInfo::isLinuxHost());
Daniel Teske's avatar
Daniel Teske committed
151

Ulf Hermann's avatar
Ulf Hermann committed
152
    const QPixmap warningPixmap = Utils::Icons::WARNING.pixmap();
153
154
155
    m_ui->jdkWarningIconLabel->setPixmap(warningPixmap);
    m_ui->kitWarningIconLabel->setPixmap(warningPixmap);

156
    const QPixmap errorPixmap = Utils::Icons::CRITICAL.pixmap();
157
158
159
    m_ui->sdkWarningIconLabel->setPixmap(errorPixmap);
    m_ui->ndkWarningIconLabel->setPixmap(errorPixmap);

Orgad Shaneh's avatar
Orgad Shaneh committed
160
161
    connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
            this, &AndroidSettingsWidget::updateAvds);
162

Daniel Teske's avatar
Daniel Teske committed
163
164
    check(All);
    applyToUi(All);
165

Orgad Shaneh's avatar
Orgad Shaneh committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
    connect(&m_futureWatcher, &QFutureWatcherBase::finished,
            this, &AndroidSettingsWidget::avdAdded);

    connect(m_ui->NDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
            this, &AndroidSettingsWidget::ndkLocationEditingFinished);
    connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
            this, &AndroidSettingsWidget::sdkLocationEditingFinished);
    connect(m_ui->OpenJDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
            this, &AndroidSettingsWidget::openJDKLocationEditingFinished);
    connect(m_ui->AVDAddPushButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::addAVD);
    connect(m_ui->AVDRemovePushButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::removeAVD);
    connect(m_ui->AVDStartPushButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::startAVD);
    connect(m_ui->AVDTableView, &QAbstractItemView::activated,
            this, &AndroidSettingsWidget::avdActivated);
    connect(m_ui->AVDTableView, &QAbstractItemView::clicked,
            this, &AndroidSettingsWidget::avdActivated);
    connect(m_ui->DataPartitionSizeSpinBox, &QAbstractSpinBox::editingFinished,
            this, &AndroidSettingsWidget::dataPartitionSizeEditingFinished);
    connect(m_ui->manageAVDPushButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::manageAVD);
    connect(m_ui->CreateKitCheckBox, &QAbstractButton::toggled,
            this, &AndroidSettingsWidget::createKitToggled);
    connect(m_ui->downloadSDKToolButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::openSDKDownloadUrl);
    connect(m_ui->downloadNDKToolButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::openNDKDownloadUrl);
    connect(m_ui->downloadOpenJDKToolButton, &QAbstractButton::clicked,
            this, &AndroidSettingsWidget::openOpenJDKDownloadUrl);
BogDan Vatra's avatar
BogDan Vatra committed
197
198
}

Daniel Teske's avatar
Daniel Teske committed
199
AndroidSettingsWidget::~AndroidSettingsWidget()
BogDan Vatra's avatar
BogDan Vatra committed
200
{
Daniel Teske's avatar
Daniel Teske committed
201
    delete m_ui;
202
    m_futureWatcher.waitForFinished();
BogDan Vatra's avatar
BogDan Vatra committed
203
204
}

Daniel Teske's avatar
Daniel Teske committed
205
void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
BogDan Vatra's avatar
BogDan Vatra committed
206
{
Daniel Teske's avatar
Daniel Teske committed
207
    if (mode & Sdk) {
208
        m_sdkState = verifySdkInstallation(&m_sdkInstallationError) ? Okay : Error;
209
    }
Daniel Teske's avatar
Daniel Teske committed
210
211
212
213
214
215
216
217

    if (mode & Ndk) {
        m_ndkState = Okay;
        Utils::FileName platformPath = m_androidConfig.ndkLocation();
        Utils::FileName toolChainPath = m_androidConfig.ndkLocation();
        Utils::FileName sourcesPath = m_androidConfig.ndkLocation();
        if (m_androidConfig.ndkLocation().isEmpty()) {
            m_ndkState = NotSet;
hjk's avatar
hjk committed
218
219
220
        } else if (!platformPath.appendPath(QLatin1String("platforms")).exists()
                || !toolChainPath.appendPath(QLatin1String("toolchains")).exists()
                || !sourcesPath.appendPath(QLatin1String("sources/cxx-stl")).exists()) {
Daniel Teske's avatar
Daniel Teske committed
221
            m_ndkState = Error;
222
223
            m_ndkErrorMessage = tr("\"%1\" does not seem to be an Android NDK top folder.")
                    .arg(m_androidConfig.ndkLocation().toUserOutput());
224
        } else if (platformPath.toString().contains(QLatin1Char(' '))) {
225
226
            m_ndkState = Error;
            m_ndkErrorMessage = tr("The Android NDK cannot be installed into a path with spaces.");
Daniel Teske's avatar
Daniel Teske committed
227
228
229
230
231
232
        } else {
            QList<AndroidToolChainFactory::AndroidToolChainInformation> compilerPaths
                    = AndroidToolChainFactory::toolchainPathsForNdk(m_androidConfig.ndkLocation());
            m_ndkCompilerCount = compilerPaths.count();

            // See if we have qt versions for those toolchains
Daniel Teske's avatar
Daniel Teske committed
233
            QSet<ProjectExplorer::Abi> toolchainsForAbi;
Tobias Hunger's avatar
Tobias Hunger committed
234
            foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
235
                if (ati.language == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
Tobias Hunger's avatar
Tobias Hunger committed
236
237
                    toolchainsForAbi.insert(ati.abi);
            }
Daniel Teske's avatar
Daniel Teske committed
238

239
            const QList<QtSupport::BaseQtVersion *> androidQts
240
                    = QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
241
242
                return v->type() == QLatin1String(Constants::ANDROIDQT) && !v->qtAbis().isEmpty();
            });
Daniel Teske's avatar
Daniel Teske committed
243
            QSet<ProjectExplorer::Abi> qtVersionsForAbi;
244
            foreach (QtSupport::BaseQtVersion *qtVersion, androidQts)
Daniel Teske's avatar
Daniel Teske committed
245
                qtVersionsForAbi.insert(qtVersion->qtAbis().first());
Daniel Teske's avatar
Daniel Teske committed
246

Daniel Teske's avatar
Daniel Teske committed
247
            QSet<ProjectExplorer::Abi> missingQtArchs = toolchainsForAbi.subtract(qtVersionsForAbi);
Daniel Teske's avatar
Daniel Teske committed
248
249
250
251
252
253
            if (missingQtArchs.isEmpty()) {
                m_ndkMissingQtArchs.clear();
            } else {
                if (missingQtArchs.count() == 1) {
                    m_ndkMissingQtArchs = tr("Qt version for architecture %1 is missing.\n"
                                             "To add the Qt version, select Options > Build & Run > Qt Versions.")
Daniel Teske's avatar
Daniel Teske committed
254
                            .arg((*missingQtArchs.constBegin()).toString());
Daniel Teske's avatar
Daniel Teske committed
255
                } else {
Robert Loehning's avatar
Robert Loehning committed
256
257
258
                    m_ndkMissingQtArchs = tr("Qt versions for %n architectures are missing.\n"
                                             "To add the Qt versions, select Options > Build & Run > Qt Versions.",
                                             nullptr, missingQtArchs.size());
Daniel Teske's avatar
Daniel Teske committed
259
260
261
                }
            }
        }
BogDan Vatra's avatar
BogDan Vatra committed
262
263
    }

Daniel Teske's avatar
Daniel Teske committed
264
265
266
267
268
269
    if (mode & Java) {
        m_javaState = Okay;
        if (m_androidConfig.openJDKLocation().isEmpty()) {
            m_javaState = NotSet;
        } else {
            Utils::FileName bin = m_androidConfig.openJDKLocation();
270
            bin.appendPath(QLatin1String("bin/javac" QTC_HOST_EXE_SUFFIX));
hjk's avatar
hjk committed
271
            if (!m_androidConfig.openJDKLocation().exists() || !bin.exists())
Daniel Teske's avatar
Daniel Teske committed
272
273
                m_javaState = Error;
        }
Daniel Teske's avatar
Daniel Teske committed
274
275
276
    }
}

Daniel Teske's avatar
Daniel Teske committed
277
void AndroidSettingsWidget::applyToUi(AndroidSettingsWidget::Mode mode)
BogDan Vatra's avatar
BogDan Vatra committed
278
{
Daniel Teske's avatar
Daniel Teske committed
279
280
281
282
    if (mode & Sdk) {
        if (m_sdkState == Error) {
            m_ui->sdkWarningIconLabel->setVisible(true);
            m_ui->sdkWarningLabel->setVisible(true);
283
            m_ui->sdkWarningLabel->setText(m_sdkInstallationError);
Daniel Teske's avatar
Daniel Teske committed
284
285
286
287
        } else {
            m_ui->sdkWarningIconLabel->setVisible(false);
            m_ui->sdkWarningLabel->setVisible(false);
        }
BogDan Vatra's avatar
BogDan Vatra committed
288
    }
Daniel Teske's avatar
Daniel Teske committed
289

Daniel Teske's avatar
Daniel Teske committed
290
291
292
293
294
295
296
    if (mode & Ndk) {
        if (m_ndkState == NotSet) {
            m_ui->ndkWarningIconLabel->setVisible(false);
            m_ui->toolchainFoundLabel->setVisible(false);
            m_ui->kitWarningIconLabel->setVisible(false);
            m_ui->kitWarningLabel->setVisible(false);
        } else if (m_ndkState == Error) {
297
            m_ui->toolchainFoundLabel->setText(m_ndkErrorMessage);
Daniel Teske's avatar
Daniel Teske committed
298
299
            m_ui->toolchainFoundLabel->setVisible(true);
            m_ui->ndkWarningIconLabel->setVisible(true);
300
301
            m_ui->kitWarningIconLabel->setVisible(false);
            m_ui->kitWarningLabel->setVisible(false);
Daniel Teske's avatar
Daniel Teske committed
302
303
304
305
306
307
308
309
310
        } else {
            if (m_ndkCompilerCount > 0) {
                m_ui->ndkWarningIconLabel->setVisible(false);
                m_ui->toolchainFoundLabel->setText(tr("Found %n toolchains for this NDK.", 0, m_ndkCompilerCount));
                m_ui->toolchainFoundLabel->setVisible(true);
            } else {
                m_ui->ndkWarningIconLabel->setVisible(false);
                m_ui->toolchainFoundLabel->setVisible(false);
            }
Daniel Teske's avatar
Daniel Teske committed
311

Daniel Teske's avatar
Daniel Teske committed
312
313
314
315
316
317
318
319
320
321
            if (m_ndkMissingQtArchs.isEmpty()) {
                m_ui->kitWarningIconLabel->setVisible(false);
                m_ui->kitWarningLabel->setVisible(false);
            } else {
                m_ui->kitWarningIconLabel->setVisible(true);
                m_ui->kitWarningLabel->setVisible(true);
                m_ui->kitWarningLabel->setText(m_ndkMissingQtArchs);
            }
        }
    }
Daniel Teske's avatar
Daniel Teske committed
322

Daniel Teske's avatar
Daniel Teske committed
323
324
325
326
327
328
329
    if (mode & Java) {
        Utils::FileName location = m_androidConfig.openJDKLocation();
        bool error = m_javaState == Error;
        m_ui->jdkWarningIconLabel->setVisible(error);
        m_ui->jdkWarningLabel->setVisible(error);
        if (error)
            m_ui->jdkWarningLabel->setText(tr("\"%1\" does not seem to be a JDK folder.").arg(location.toUserOutput()));
Daniel Teske's avatar
Daniel Teske committed
330
331
    }

Daniel Teske's avatar
Daniel Teske committed
332
333
334
    if (mode & Sdk || mode & Java) {
        if (m_sdkState == Okay && m_javaState == Okay) {
            m_ui->AVDManagerFrame->setEnabled(true);
Daniel Teske's avatar
Daniel Teske committed
335
        } else {
Daniel Teske's avatar
Daniel Teske committed
336
            m_ui->AVDManagerFrame->setEnabled(false);
Daniel Teske's avatar
Daniel Teske committed
337
        }
Daniel Teske's avatar
Daniel Teske committed
338

339
        startUpdateAvd();
Daniel Teske's avatar
Daniel Teske committed
340
    }
Daniel Teske's avatar
Daniel Teske committed
341
}
Daniel Teske's avatar
Daniel Teske committed
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
void AndroidSettingsWidget::disableAvdControls()
{
    m_ui->AVDAddPushButton->setEnabled(false);
    m_ui->AVDTableView->setEnabled(false);
    m_ui->AVDRemovePushButton->setEnabled(false);
    m_ui->AVDStartPushButton->setEnabled(false);
}

void AndroidSettingsWidget::enableAvdControls()
{
    m_ui->AVDTableView->setEnabled(true);
    m_ui->AVDAddPushButton->setEnabled(true);
    avdActivated(m_ui->AVDTableView->currentIndex());
}

void AndroidSettingsWidget::startUpdateAvd()
{
    disableAvdControls();
Vikas Pachdha's avatar
Vikas Pachdha committed
361
    m_virtualDevicesWatcher.setFuture(m_avdManager->avdList());
362
363
364
365
366
367
368
369
370
371
372
373
}

void AndroidSettingsWidget::updateAvds()
{
    m_AVDModel.setAvdList(m_virtualDevicesWatcher.result());
    if (!m_lastAddedAvd.isEmpty()) {
        m_ui->AVDTableView->setCurrentIndex(m_AVDModel.indexForAvdName(m_lastAddedAvd));
        m_lastAddedAvd.clear();
    }
    enableAvdControls();
}

374
bool AndroidSettingsWidget::verifySdkInstallation(QString *errorDetails) const
375
{
376
377
378
379
380
    if (m_androidConfig.sdkLocation().isEmpty()) {
        if (errorDetails)
            *errorDetails = tr("Android SDK path not set.");
        return false;
    }
381

382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
    if (!m_androidConfig.sdkLocation().exists()) {
        if (errorDetails)
            *errorDetails = tr("Android SDK path does not exist.");
        return false;
    }

    if (m_androidConfig.sdkToolsVersion().isNull()) {
        if (errorDetails)
            *errorDetails = tr("The SDK path does not seem to be a valid Android SDK top folder.");
        return false;
    }

    QStringList missingComponents;
    if (!m_androidConfig.adbToolPath().exists())
        missingComponents << "Platform Tools";

    if (m_androidConfig.buildToolsVersion().isNull())
        missingComponents << "Build Tools";

    if (m_androidConfig.sdkTargets().isEmpty())
        missingComponents << "Platform SDK";

    if (!missingComponents.isEmpty() && errorDetails) {
        *errorDetails = tr("Android SDK components missing (%1).\nUse Android SDK Manager to "
                           "manage SDK components.").arg(missingComponents.join(", "));
    }

    return missingComponents.isEmpty();
410
411
}

Daniel Teske's avatar
Daniel Teske committed
412
413
414
415
416
417
418
419
void AndroidSettingsWidget::saveSettings()
{
    sdkLocationEditingFinished();
    ndkLocationEditingFinished();
    openJDKLocationEditingFinished();
    dataPartitionSizeEditingFinished();
    AndroidConfigurations::setConfig(m_androidConfig);
}
BogDan Vatra's avatar
BogDan Vatra committed
420
421
422

void AndroidSettingsWidget::sdkLocationEditingFinished()
{
423
    m_androidConfig.setSdkLocation(Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath()));
Daniel Teske's avatar
Daniel Teske committed
424
425
426

    check(Sdk);
    applyToUi(Sdk);
BogDan Vatra's avatar
BogDan Vatra committed
427
428
429
430
}

void AndroidSettingsWidget::ndkLocationEditingFinished()
{
431
    m_androidConfig.setNdkLocation(Utils::FileName::fromUserInput(m_ui->NDKLocationPathChooser->rawPath()));
Daniel Teske's avatar
Daniel Teske committed
432
433
434

    check(Ndk);
    applyToUi(Ndk);
BogDan Vatra's avatar
BogDan Vatra committed
435
436
437
438
}

void AndroidSettingsWidget::openJDKLocationEditingFinished()
{
439
    m_androidConfig.setOpenJDKLocation(Utils::FileName::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath()));
Daniel Teske's avatar
Daniel Teske committed
440
441
442

    check(Java);
    applyToUi(Java);
BogDan Vatra's avatar
BogDan Vatra committed
443
444
}

445
446
void AndroidSettingsWidget::openSDKDownloadUrl()
{
447
    QDesktopServices::openUrl(QUrl::fromUserInput("https://developer.android.com/studio/"));
448
449
450
451
}

void AndroidSettingsWidget::openNDKDownloadUrl()
{
452
    QDesktopServices::openUrl(QUrl::fromUserInput("https://developer.android.com/ndk/downloads/"));
453
454
455
456
}

void AndroidSettingsWidget::openOpenJDKDownloadUrl()
{
457
    QDesktopServices::openUrl(QUrl::fromUserInput("http://www.oracle.com/technetwork/java/javase/downloads/"));
458
459
}

BogDan Vatra's avatar
BogDan Vatra committed
460
461
void AndroidSettingsWidget::addAVD()
{
462
    disableAvdControls();
463
464
    AndroidConfig::CreateAvdInfo info = m_androidConfig.gatherCreateAVDInfo(this);

Vikas Pachdha's avatar
Vikas Pachdha committed
465
    if (!info.target.isValid()) {
466
        enableAvdControls();
467
468
469
        return;
    }

Vikas Pachdha's avatar
Vikas Pachdha committed
470
    m_futureWatcher.setFuture(m_avdManager->createAvd(info));
471
472
473
474
475
476
}

void AndroidSettingsWidget::avdAdded()
{
    AndroidConfig::CreateAvdInfo info = m_futureWatcher.result();
    if (!info.error.isEmpty()) {
477
        enableAvdControls();
478
479
480
481
        QMessageBox::critical(this, QApplication::translate("AndroidConfig", "Error Creating AVD"), info.error);
        return;
    }

482
483
    startUpdateAvd();
    m_lastAddedAvd = info.name;
BogDan Vatra's avatar
BogDan Vatra committed
484
485
486
487
}

void AndroidSettingsWidget::removeAVD()
{
488
    disableAvdControls();
489
490
491
492
    QString avdName = m_AVDModel.avdName(m_ui->AVDTableView->currentIndex());
    if (QMessageBox::question(this, tr("Remove Android Virtual Device"),
                              tr("Remove device \"%1\"? This cannot be undone.").arg(avdName),
                              QMessageBox::Yes | QMessageBox::No)
493
494
            == QMessageBox::No) {
        enableAvdControls();
495
        return;
496
    }
497

Vikas Pachdha's avatar
Vikas Pachdha committed
498
    m_avdManager->removeAvd(avdName);
499
    startUpdateAvd();
BogDan Vatra's avatar
BogDan Vatra committed
500
501
502
503
}

void AndroidSettingsWidget::startAVD()
{
Vikas Pachdha's avatar
Vikas Pachdha committed
504
    m_avdManager->startAvdAsync(m_AVDModel.avdName(m_ui->AVDTableView->currentIndex()));
BogDan Vatra's avatar
BogDan Vatra committed
505
506
}

507
void AndroidSettingsWidget::avdActivated(const QModelIndex &index)
BogDan Vatra's avatar
BogDan Vatra committed
508
509
510
511
512
513
514
{
    m_ui->AVDRemovePushButton->setEnabled(index.isValid());
    m_ui->AVDStartPushButton->setEnabled(index.isValid());
}

void AndroidSettingsWidget::dataPartitionSizeEditingFinished()
{
Daniel Teske's avatar
Daniel Teske committed
515
    m_androidConfig.setPartitionSize(m_ui->DataPartitionSizeSpinBox->value());
BogDan Vatra's avatar
BogDan Vatra committed
516
517
}

Daniel Teske's avatar
Daniel Teske committed
518
519
void AndroidSettingsWidget::createKitToggled()
{
Daniel Teske's avatar
Daniel Teske committed
520
    m_androidConfig.setAutomaticKitCreation(m_ui->CreateKitCheckBox->isChecked());
Daniel Teske's avatar
Daniel Teske committed
521
522
}

BogDan Vatra's avatar
BogDan Vatra committed
523
524
void AndroidSettingsWidget::manageAVD()
{
Vikas Pachdha's avatar
Vikas Pachdha committed
525
526
527
528
529
530
531
532
533
    if (m_avdManager->avdManagerUiToolAvailable()) {
        m_avdManager->launchAvdManagerUiTool();
    } else {
        QMessageBox::warning(this, tr("AVD Manager Not Available"),
                             tr("AVD manager UI tool is not available in the installed SDK tools"
                                "(version %1). Use the command line tool \"avdmanager\" for "
                                "advanced AVD management.")
                             .arg(m_androidConfig.sdkToolsVersion().toString()));
    }
BogDan Vatra's avatar
BogDan Vatra committed
534
535
536
537
538
}


} // namespace Internal
} // namespace Android