Commit 3c2facab authored by Daniel Teske's avatar Daniel Teske

Android Manifest Editor: Add support for minimum and target sdk settings

Task-number: QTCREATORBUG-9692

Change-Id: Ide85392d86e7f3df4df9644f01d186ed939f5124
Reviewed-by: default avatarEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
parent 211e56b5
......@@ -647,6 +647,57 @@ QString AndroidManager::loadLocalJarsInitClasses(ProjectExplorer::Target *target
return loadLocal(target, apiLevel, type, QLatin1String("initClass"));
}
QPair<int, int> AndroidManager::apiLevelRange(ProjectExplorer::Target *target)
{
// 4 is the minimum version on which qt is supported
// 19 and 20 are not yet released, but allow the user
// to set them
int minApiLevel = 4;
QtSupport::BaseQtVersion *qt;
if (target && (qt = QtSupport::QtKitInformation::qtVersion(target->kit())))
if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
minApiLevel = 9;
return qMakePair(minApiLevel, 20);
}
QString AndroidManager::androidNameForApiLevel(int x)
{
switch (x) {
case 4:
return QLatin1String("Android 1.6");
case 5:
return QLatin1String("Android 2.0");
case 6:
return QLatin1String("Android 2.0.1");
case 7:
return QLatin1String("Android 2.1.x");
case 8:
return QLatin1String("Android 2.2.x");
case 9:
return QLatin1String("Android 2.3, 2.3.1, 2.3.2");
case 10:
return QLatin1String("Android 2.3.3, 2.3.4");
case 11:
return QLatin1String("Android 3.0.x");
case 12:
return QLatin1String("Android 3.1.x");
case 13:
return QLatin1String("Android 3.2");
case 14:
return QLatin1String("Android 4.0, 4.0.1, 4.0.2");
case 15:
return QLatin1String("Android 4.0.3, 4.0.4");
case 16:
return QLatin1String("Android 4.1, 4.1.1");
case 17:
return QLatin1String("Android 4.2, 4.2.2");
case 18:
return QLatin1String("Android 4.3");
default:
return QLatin1String("Unknown Android version.");
}
}
QVector<AndroidManager::Library> AndroidManager::availableQtLibsWithDependencies(ProjectExplorer::Target *target)
{
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
......
......@@ -95,6 +95,9 @@ public:
static QString loadLocalBundledFiles(ProjectExplorer::Target *target, int apiLevel = -1);
static QString loadLocalJarsInitClasses(ProjectExplorer::Target *target, int apiLevel = -1);
static QPair<int, int> apiLevelRange(ProjectExplorer::Target *target);
static QString androidNameForApiLevel(int x);
class Library
{
public:
......
......@@ -31,12 +31,18 @@
#include "androidmanifesteditor.h"
#include "androidconstants.h"
#include "androidmanifestdocument.h"
#include "androidmanager.h"
#include <coreplugin/icore.h>
#include <coreplugin/infobar.h>
#include <texteditor/plaintexteditor.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectwindow.h>
#include <projectexplorer/iprojectproperties.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/kitinformation.h>
#include <texteditor/texteditoractionhandler.h>
#include <QLineEdit>
......@@ -67,6 +73,21 @@ bool checkPackageName(const QString &packageName)
{
return QRegExp(packageNameRegExp).exactMatch(packageName);
}
ProjectExplorer::Project *androidProject(const QString &file)
{
ProjectExplorer::SessionManager *session = ProjectExplorer::ProjectExplorerPlugin::instance()->session();
Utils::FileName fileName = Utils::FileName::fromString(file);
foreach (ProjectExplorer::Project *project, session->projects()) {
if (!project->activeTarget())
continue;
ProjectExplorer::Kit *kit = project->activeTarget()->kit();
if (ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(kit) == Android::Constants::ANDROID_DEVICE_TYPE
&& fileName.isChildOf(Utils::FileName::fromString(project->projectDirectory())))
return project;
}
return 0;
}
} // anonymous namespace
......@@ -107,6 +128,7 @@ TextEditor::BaseTextEditor *AndroidManifestEditorWidget::createEditor()
return new AndroidManifestEditor(this);
}
void AndroidManifestEditorWidget::initializePage()
{
QWidget *mainWidget = new QWidget(this);
......@@ -170,6 +192,21 @@ void AndroidManifestEditorWidget::initializePage()
m_versionNameLinedit = new QLineEdit(packageGroupBox);
formLayout->addRow(tr("Version name:"), m_versionNameLinedit);
m_androidMinSdkVersion = new QComboBox(packageGroupBox);
m_androidMinSdkVersion->setToolTip(
tr("Sets the minimum required version on which this application can be run."));
m_androidMinSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Minimum required SDK:"), m_androidMinSdkVersion);
m_androidTargetSdkVersion = new QComboBox(packageGroupBox);
m_androidTargetSdkVersion->setToolTip(
tr("Sets the targe SDK, set this to the highest tested version."
"This disables compatibility behavior of the system for your application."));
m_androidTargetSdkVersion->addItem(tr("Not set"), 0);
formLayout->addRow(tr("Target SDK:"), m_androidTargetSdkVersion);
packageGroupBox->setLayout(formLayout);
connect(m_packageNameLineEdit, SIGNAL(textEdited(QString)),
......@@ -178,6 +215,10 @@ void AndroidManifestEditorWidget::initializePage()
this, SLOT(setDirty()));
connect(m_versionNameLinedit, SIGNAL(textEdited(QString)),
this, SLOT(setDirty()));
connect(m_androidMinSdkVersion, SIGNAL(currentIndexChanged(int)),
this, SLOT(setDirty()));
connect(m_androidTargetSdkVersion, SIGNAL(currentIndexChanged(int)),
this, SLOT(setDirty()));
}
......@@ -434,6 +475,7 @@ bool AndroidManifestEditorWidget::open(QString *errorString, const QString &file
}
// some error occured
updateInfoBar(error, errorLine, errorColumn);
updateSdkVersions();
setActivePage(Source);
return true;
......@@ -606,6 +648,23 @@ void AndroidManifestEditorWidget::updateInfoBar()
updateInfoBar(errorMessage, errorLine, errorColumn);
}
void AndroidManifestEditorWidget::updateSdkVersions()
{
const QString docPath(static_cast<AndroidManifestDocument *>(editor()->document())->filePath());
QPair<int, int> apiLevels = AndroidManager::apiLevelRange(androidProject(docPath)->activeTarget());
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidMinSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidTargetSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
}
void AndroidManifestEditorWidget::updateInfoBar(const QString &errorMessage, int line, int column)
{
Core::InfoBar *infoBar = editorDocument()->infoBar();
......@@ -636,6 +695,23 @@ void AndroidManifestEditorWidget::gotoError()
gotoLine(m_errorLine, m_errorColumn);
}
void setApiLevel(QComboBox *box, const QDomElement &element, const QString &attribute)
{
if (!element.isNull() && element.hasAttribute(attribute)) {
bool ok;
int tmp = element.attribute(attribute).toInt(&ok);
if (ok) {
int index = box->findData(tmp);
if (index != -1) {
box->setCurrentIndex(index);
return;
}
}
}
int index = box->findData(0);
box->setCurrentIndex(index);
}
void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
{
m_stayClean = true;
......@@ -644,6 +720,10 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
m_versionCode->setValue(manifest.attribute(QLatin1String("android:versionCode")).toInt());
m_versionNameLinedit->setText(manifest.attribute(QLatin1String("android:versionName")));
QDomElement usesSdkElement = manifest.firstChildElement(QLatin1String("uses-sdk"));
setApiLevel(m_androidMinSdkVersion, usesSdkElement, QLatin1String("android:minSdkVersion"));
setApiLevel(m_androidTargetSdkVersion, usesSdkElement, QLatin1String("android:targetSdkVersion"));
QString baseDir = QFileInfo(static_cast<AndroidManifestDocument *>(editor()->document())->filePath()).absolutePath();
QString fileName = baseDir + QLatin1String("/res/values/strings.xml");
......@@ -692,6 +772,53 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
m_dirty = false;
}
void setUsesSdk(QDomDocument &doc, QDomElement &manifest, int minimumSdk, int targetSdk)
{
QDomElement usesSdk = manifest.firstChildElement(QLatin1String("uses-sdk"));
if (usesSdk.isNull()) { // doesn't exist yet
if (minimumSdk == 0 && targetSdk == 0) {
// and doesn't need to exist
} else {
usesSdk = doc.createElement(QLatin1String("uses-sdk"));
if (minimumSdk != 0)
usesSdk.setAttribute(QLatin1String("android:minSdkVersion"), minimumSdk);
if (targetSdk != 0)
usesSdk.setAttribute(QLatin1String("android:targetSdkVersion"), targetSdk);
manifest.appendChild(usesSdk);
}
} else {
if (minimumSdk == 0 && targetSdk == 0) {
// We might be able to remove the whole element
// check if there are other attributes
QDomNamedNodeMap usesSdkAttributes = usesSdk.attributes();
bool keepNode = false;
for (int i = 0; i < usesSdkAttributes.size(); ++i) {
if (usesSdkAttributes.item(i).nodeName() != QLatin1String("android:minSdkVersion")
&& usesSdkAttributes.item(i).nodeName() != QLatin1String("android:targetSdkVersion")) {
keepNode = true;
break;
}
}
if (keepNode) {
usesSdk.removeAttribute(QLatin1String("android:minSdkVersion"));
usesSdk.removeAttribute(QLatin1String("android:targetSdkVersion"));
} else {
manifest.removeChild(usesSdk);
}
} else {
if (minimumSdk == 0)
usesSdk.removeAttribute(QLatin1String("android:minSdkVersion"));
else
usesSdk.setAttribute(QLatin1String("android:minSdkVersion"), minimumSdk);
if (targetSdk == 0)
usesSdk.removeAttribute(QLatin1String("android:targetSdkVersion"));
else
usesSdk.setAttribute(QLatin1String("android:targetSdkVersion"), targetSdk);
}
}
}
void AndroidManifestEditorWidget::syncToEditor()
{
QDomDocument doc;
......@@ -706,6 +833,9 @@ void AndroidManifestEditorWidget::syncToEditor()
manifest.setAttribute(QLatin1String("android:versionCode"), m_versionCode->value());
manifest.setAttribute(QLatin1String("android:versionName"), m_versionNameLinedit->text());
setUsesSdk(doc, manifest, m_androidMinSdkVersion->currentText().toInt(),
m_androidTargetSdkVersion->currentText().toInt());
setAndroidAppLibName(doc, manifest.firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")), m_targetLineEdit->text());
// permissions
......
......@@ -115,6 +115,7 @@ private slots:
void setPackageName();
void gotoError();
void updateInfoBar();
void updateSdkVersions();
void startParseCheck();
void delayedParseCheck();
private:
......@@ -144,6 +145,8 @@ private:
QLabel *m_packageNameWarning;
QSpinBox *m_versionCode;
QLineEdit *m_versionNameLinedit;
QComboBox *m_androidMinSdkVersion;
QComboBox *m_androidTargetSdkVersion;
// Application
QLineEdit *m_appNameLineEdit;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment