Files
qt-creator/src/plugins/android/androiddeployqtwidget.cpp
Eskil Abrahamsen Blomfeldt c8393b10fd Extra library editor for Android
Add a list view to the deployment settings which allows you
to add and remove libraries from the ANDROID_EXTRA_LIBS
variable in the .pro file.

Task-number: QTCREATORBUG-9849
Change-Id: Ic0131c46be8fdef4b226b5ceb0ee82ea4dd82c6a
Reviewed-by: Daniel Teske <daniel.teske@digia.com>
2013-10-01 15:41:43 +02:00

370 lines
14 KiB
C++

/**************************************************************************
**
** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
** 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 "androiddeployqtwidget.h"
#include "ui_androiddeployqtwidget.h"
#include "androidcreatekeystorecertificate.h"
#include "androiddeployqtstep.h"
#include "androidmanager.h"
#include "createandroidmanifestwizard.h"
#include "androidextralibrarylistmodel.h"
#include <projectexplorer/target.h>
#include <qt4projectmanager/qt4buildconfiguration.h>
#include <qt4projectmanager/qt4project.h>
#include <qt4projectmanager/qt4nodes.h>
#include <QFileDialog>
#include <algorithm>
using namespace Android;
using namespace Internal;
AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step)
: ProjectExplorer::BuildStepConfigWidget(),
m_ui(new Ui::AndroidDeployQtWidget),
m_step(step),
m_currentBuildConfiguration(0),
m_ignoreChange(false)
{
m_ui->setupUi(this);
// Target sdk combobox
int minApiLevel = 9;
QStringList targets = AndroidConfigurations::instance().sdkTargets(minApiLevel);
m_ui->targetSDKComboBox->addItems(targets);
m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(step->buildTargetSdk()));
// deployment option
switch (m_step->deployAction()) {
case AndroidDeployQtStep::MinistroDeployment:
m_ui->ministroOption->setChecked(true);
break;
case AndroidDeployQtStep::DebugDeployment:
m_ui->temporaryQtOption->setChecked(true);
break;
case AndroidDeployQtStep::BundleLibrariesDeployment:
m_ui->bundleQtOption->setChecked(true);
break;
default:
// can't happen
break;
}
// signing
m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath().toUserOutput());
m_ui->signingDebugWarningIcon->hide();
m_ui->signingDebugWarningLabel->hide();
m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
bool oldFiles = AndroidManager::checkForQt51Files(m_step->project()->projectDirectory());
m_ui->oldFilesWarningIcon->setVisible(oldFiles);
m_ui->oldFilesWarningLabel->setVisible(oldFiles);
// target sdk
connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSdk(QString)));
// deployment options
connect(m_ui->ministroOption, SIGNAL(clicked()), SLOT(setMinistro()));
connect(m_ui->temporaryQtOption, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs()));
connect(m_ui->bundleQtOption, SIGNAL(clicked()), SLOT(setBundleQtLibs()));
connect(m_ui->installMinistroButton, SIGNAL(clicked()), SLOT(installMinistro()));
connect(m_ui->cleanLibsPushButton, SIGNAL(clicked()), SLOT(cleanLibsOnDevice()));
connect(m_ui->resetDefaultDevices, SIGNAL(clicked()), SLOT(resetDefaultDevices()));
connect(m_ui->openPackageLocationCheckBox, SIGNAL(toggled(bool)),
this, SLOT(openPackageLocationCheckBoxToggled(bool)));
connect(m_ui->verboseOutputCheckBox, SIGNAL(toggled(bool)),
this, SLOT(verboseOutputCheckBoxToggled(bool)));
//signing
connect(m_ui->signPackageCheckBox, SIGNAL(toggled(bool)),
this, SLOT(signPackageCheckBoxToggled(bool)));
connect(m_ui->KeystoreCreatePushButton, SIGNAL(clicked()),
this, SLOT(createKeyStore()));
connect(m_ui->KeystoreLocationPushButton, SIGNAL(clicked()),
this, SLOT(browseKeyStore()));
connect(m_ui->certificatesAliasComboBox, SIGNAL(activated(QString)),
this, SLOT(certificatesAliasComboBoxActivated(QString)));
connect(m_ui->certificatesAliasComboBox, SIGNAL(currentIndexChanged(QString)),
this, SLOT(certificatesAliasComboBoxCurrentIndexChanged(QString)));
activeBuildConfigurationChanged();
connect(m_step->target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
this, SLOT(activeBuildConfigurationChanged()));
connect(m_ui->inputFileComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(inputFileComboBoxIndexChanged()));
updateInputFileUi();
connect(m_step, SIGNAL(inputFileChanged()),
this, SLOT(updateInputFileUi()));
connect(m_ui->createAndroidManifestButton, SIGNAL(clicked()),
this, SLOT(createManifestButton()));
m_extraLibraryListModel = new AndroidExtraLibraryListModel(static_cast<Qt4ProjectManager::Qt4Project *>(m_step->project()),
this);
m_ui->androidExtraLibsListView->setModel(m_extraLibraryListModel);
connect(m_ui->androidExtraLibsListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(checkEnableRemoveButton()));
connect(m_ui->addAndroidExtraLibButton, SIGNAL(clicked()), this, SLOT(addAndroidExtraLib()));
connect(m_ui->removeAndroidExtraLibButton, SIGNAL(clicked()), this, SLOT(removeAndroidExtraLib()));
connect(m_step->project(), SIGNAL(proFilesEvaluated()), this, SLOT(checkProjectTemplate()));
checkProjectTemplate();
}
AndroidDeployQtWidget::~AndroidDeployQtWidget()
{
delete m_ui;
}
void AndroidDeployQtWidget::checkProjectTemplate()
{
Qt4ProjectManager::Qt4Project *project = static_cast<Qt4ProjectManager::Qt4Project *>(m_step->project());
if (project->rootQt4ProjectNode()->projectType() == Qt4ProjectManager::ApplicationTemplate)
m_ui->additionalLibrariesGroupBox->setEnabled(true);
else
m_ui->additionalLibrariesGroupBox->setEnabled(false);
}
void AndroidDeployQtWidget::createManifestButton()
{
CreateAndroidManifestWizard wizard(m_step->target());
wizard.exec();
}
void AndroidDeployQtWidget::updateInputFileUi()
{
Qt4ProjectManager::Qt4Project *project
= static_cast<Qt4ProjectManager::Qt4Project *>(m_step->project());
QList<Qt4ProjectManager::Qt4ProFileNode *> nodes = project->applicationProFiles();
int size = nodes.size();
if (size == 0 || size == 1) {
// there's nothing to select, e.g. before parsing
m_ui->inputFileLabel->setVisible(false);
m_ui->inputFileComboBox->setVisible(false);
} else {
m_ignoreChange = true;
m_ui->inputFileLabel->setVisible(true);
m_ui->inputFileComboBox->setVisible(true);
m_ui->inputFileComboBox->clear();
foreach (Qt4ProjectManager::Qt4ProFileNode *node, nodes) {
QString file = node->singleVariableValue(Qt4ProjectManager::AndroidDeploySettingsFile);
m_ui->inputFileComboBox->addItem(node->displayName(), file);
}
int index = m_ui->inputFileComboBox->findData(m_step->inputFile());
m_ui->inputFileComboBox->setCurrentIndex(index);
m_ignoreChange = false;
}
}
void AndroidDeployQtWidget::inputFileComboBoxIndexChanged()
{
if (m_ignoreChange)
return;
QString text = m_ui->inputFileComboBox->itemData(m_ui->inputFileComboBox->currentIndex()).toString();
m_step->setInputFile(text);
}
QString AndroidDeployQtWidget::displayName() const
{
return tr("<b>Deploy configurations</b>");
}
QString AndroidDeployQtWidget::summaryText() const
{
return displayName();
}
void AndroidDeployQtWidget::setTargetSdk(const QString &sdk)
{
m_step->setBuildTargetSdk(sdk);
}
void AndroidDeployQtWidget::setMinistro()
{
m_step->setDeployAction(AndroidDeployQtStep::MinistroDeployment);
}
void AndroidDeployQtWidget::setDeployLocalQtLibs()
{
m_step->setDeployAction(AndroidDeployQtStep::DebugDeployment);
}
void AndroidDeployQtWidget::setBundleQtLibs()
{
m_step->setDeployAction(AndroidDeployQtStep::BundleLibrariesDeployment);
}
void AndroidDeployQtWidget::installMinistro()
{
QString packagePath =
QFileDialog::getOpenFileName(this, tr("Qt Android Smart Installer"),
QDir::homePath(), tr("Android package (*.apk)"));
if (!packagePath.isEmpty())
AndroidManager::installQASIPackage(m_step->target(), packagePath);
}
void AndroidDeployQtWidget::cleanLibsOnDevice()
{
AndroidManager::cleanLibsOnDevice(m_step->target());
}
void AndroidDeployQtWidget::resetDefaultDevices()
{
AndroidConfigurations::instance().clearDefaultDevices(m_step->project());
}
void AndroidDeployQtWidget::signPackageCheckBoxToggled(bool checked)
{
m_ui->certificatesAliasComboBox->setEnabled(checked);
m_step->setSignPackage(checked);
updateSigningWarning();
if (!checked)
return;
if (!m_step->keystorePath().isEmpty())
setCertificates();
}
void AndroidDeployQtWidget::createKeyStore()
{
AndroidCreateKeystoreCertificate d;
if (d.exec() != QDialog::Accepted)
return;
m_ui->KeystoreLocationLineEdit->setText(d.keystoreFilePath().toUserOutput());
m_step->setKeystorePath(d.keystoreFilePath());
m_step->setKeystorePassword(d.keystorePassword());
m_step->setCertificateAlias(d.certificateAlias());
m_step->setCertificatePassword(d.certificatePassword());
setCertificates();
}
void AndroidDeployQtWidget::setCertificates()
{
QAbstractItemModel *certificates = m_step->keystoreCertificates();
m_ui->signPackageCheckBox->setChecked(certificates);
m_ui->certificatesAliasComboBox->setModel(certificates);
}
void AndroidDeployQtWidget::browseKeyStore()
{
Utils::FileName keystorePath = m_step->keystorePath();
if (keystorePath.isEmpty())
keystorePath = Utils::FileName::fromString(QDir::homePath());
Utils::FileName file = Utils::FileName::fromString(QFileDialog::getOpenFileName(this, tr("Select keystore file"), keystorePath.toString(), tr("Keystore files (*.keystore *.jks)")));
if (file.isEmpty())
return;
m_ui->KeystoreLocationLineEdit->setText(file.toUserOutput());
m_step->setKeystorePath(file);
m_ui->signPackageCheckBox->setChecked(false);
}
void AndroidDeployQtWidget::certificatesAliasComboBoxActivated(const QString &alias)
{
if (alias.length())
m_step->setCertificateAlias(alias);
}
void AndroidDeployQtWidget::certificatesAliasComboBoxCurrentIndexChanged(const QString &alias)
{
if (alias.length())
m_step->setCertificateAlias(alias);
}
void AndroidDeployQtWidget::openPackageLocationCheckBoxToggled(bool checked)
{
m_step->setOpenPackageLocation(checked);
}
void AndroidDeployQtWidget::verboseOutputCheckBoxToggled(bool checked)
{
m_step->setVerboseOutput(checked);
}
void AndroidDeployQtWidget::activeBuildConfigurationChanged()
{
if (m_currentBuildConfiguration)
disconnect(m_currentBuildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()),
this, SLOT(updateSigningWarning()));
updateSigningWarning();
Qt4ProjectManager::Qt4BuildConfiguration *bc
= qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(m_step->target()->activeBuildConfiguration());
m_currentBuildConfiguration = bc;
if (bc)
connect(bc, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateSigningWarning()));
m_currentBuildConfiguration = bc;
}
void AndroidDeployQtWidget::updateSigningWarning()
{
Qt4ProjectManager::Qt4BuildConfiguration *bc = qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(m_step->target()->activeBuildConfiguration());
bool debug = bc && (bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild);
if (m_step->signPackage() && debug) {
m_ui->signingDebugWarningIcon->setVisible(true);
m_ui->signingDebugWarningLabel->setVisible(true);
} else {
m_ui->signingDebugWarningIcon->setVisible(false);
m_ui->signingDebugWarningLabel->setVisible(false);
}
}
void AndroidDeployQtWidget::addAndroidExtraLib()
{
QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Select additional libraries"),
QDir::homePath(),
tr("Libraries (*.so)"));
if (!fileNames.isEmpty())
m_extraLibraryListModel->addEntries(fileNames);
}
void AndroidDeployQtWidget::removeAndroidExtraLib()
{
QModelIndexList removeList = m_ui->androidExtraLibsListView->selectionModel()->selectedIndexes();
m_extraLibraryListModel->removeEntries(removeList);
}
void AndroidDeployQtWidget::checkEnableRemoveButton()
{
m_ui->removeAndroidExtraLibButton->setEnabled(m_ui->androidExtraLibsListView->selectionModel()->hasSelection());
}