forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.12'
Conflicts: src/plugins/cmakeprojectmanager/tealeafreader.cpp src/plugins/cmakeprojectmanager/tealeafreader.h src/plugins/projectexplorer/miniprojecttargetselector.cpp Change-Id: I88d85be3903f57a55fddb7901e771a4822db1b85
This commit is contained in:
@@ -100,6 +100,7 @@ namespace {
|
||||
|
||||
const QLatin1String SettingsGroup("AndroidConfigurations");
|
||||
const QLatin1String SDKLocationKey("SDKLocation");
|
||||
const QLatin1String CustomNdkLocationsKey("CustomNdkLocations");
|
||||
const QLatin1String SdkFullyConfiguredKey("AllEssentialsInstalled");
|
||||
const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs");
|
||||
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
|
||||
@@ -235,6 +236,7 @@ void AndroidConfig::load(const QSettings &settings)
|
||||
// user settings
|
||||
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
|
||||
m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString());
|
||||
m_customNdkList = settings.value(CustomNdkLocationsKey).toStringList();
|
||||
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
|
||||
m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString());
|
||||
m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString());
|
||||
@@ -246,12 +248,14 @@ void AndroidConfig::load(const QSettings &settings)
|
||||
&& settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
|
||||
// persisten settings
|
||||
m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
|
||||
m_customNdkList = reader.restoreValue(CustomNdkLocationsKey).toStringList();
|
||||
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
|
||||
m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
|
||||
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
|
||||
m_sdkFullyConfigured = reader.restoreValue(SdkFullyConfiguredKey, m_sdkFullyConfigured).toBool();
|
||||
// persistent settings
|
||||
}
|
||||
m_customNdkList.removeAll("");
|
||||
parseDependenciesJson();
|
||||
}
|
||||
|
||||
@@ -263,6 +267,7 @@ void AndroidConfig::save(QSettings &settings) const
|
||||
|
||||
// user settings
|
||||
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
|
||||
settings.setValue(CustomNdkLocationsKey, m_customNdkList);
|
||||
settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs);
|
||||
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
|
||||
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
|
||||
@@ -353,6 +358,22 @@ QVector<int> AndroidConfig::availableNdkPlatforms(const BaseQtVersion *qtVersion
|
||||
return availableNdkPlatforms;
|
||||
}
|
||||
|
||||
QStringList AndroidConfig::getCustomNdkList() const
|
||||
{
|
||||
return m_customNdkList;
|
||||
}
|
||||
|
||||
void AndroidConfig::addCustomNdk(const QString &customNdk)
|
||||
{
|
||||
if (!m_customNdkList.contains(customNdk))
|
||||
m_customNdkList.append(customNdk);
|
||||
}
|
||||
|
||||
void AndroidConfig::removeCustomNdk(const QString &customNdk)
|
||||
{
|
||||
m_customNdkList.removeAll(customNdk);
|
||||
}
|
||||
|
||||
QStringList AndroidConfig::apiLevelNamesFor(const SdkPlatformList &platforms)
|
||||
{
|
||||
return Utils::transform(platforms, AndroidConfig::apiLevelNameFor);
|
||||
@@ -415,9 +436,9 @@ FilePath AndroidConfig::aaptToolPath() const
|
||||
return aaptToolPath.pathAppended(toolPath);
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
||||
FilePath AndroidConfig::toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const
|
||||
{
|
||||
const FilePath toolchainPath = ndkLocation(qtVersion).pathAppended("toolchains/llvm/prebuilt/");
|
||||
const FilePath toolchainPath = ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
|
||||
|
||||
// detect toolchain host
|
||||
QStringList hostPatterns;
|
||||
@@ -443,23 +464,41 @@ FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
||||
return {};
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const
|
||||
FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
||||
{
|
||||
const FilePath path = toolchainPath(qtVersion);
|
||||
return toolchainPathFromNdk(ndkLocation(qtVersion));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::clangPathFromNdk(const Utils::FilePath &ndkLocation) const
|
||||
{
|
||||
const FilePath path = toolchainPathFromNdk(ndkLocation);
|
||||
if (path.isEmpty())
|
||||
return {};
|
||||
return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const
|
||||
{
|
||||
return clangPathFromNdk(ndkLocation(qtVersion));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi, const BaseQtVersion *qtVersion) const
|
||||
{
|
||||
const FilePath path = ndkLocation(qtVersion).pathAppended(
|
||||
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(qtVersion), QTC_HOST_EXE_SUFFIX));
|
||||
return gdbPathFromNdk(abi, ndkLocation(qtVersion));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::gdbPathFromNdk(const Abi &abi, const FilePath &ndkLocation) const
|
||||
{
|
||||
const FilePath path = ndkLocation.pathAppended(
|
||||
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHostFromNdk(ndkLocation), QTC_HOST_EXE_SUFFIX));
|
||||
if (path.exists())
|
||||
return path;
|
||||
// fallback for old NDKs (e.g. 10e)
|
||||
return ndkLocation(qtVersion).pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
|
||||
.arg(toolchainPrefix(abi), toolchainHost(qtVersion), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX));
|
||||
return ndkLocation.pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
|
||||
.arg(toolchainPrefix(abi),
|
||||
toolchainHostFromNdk(ndkLocation),
|
||||
toolsPrefix(abi),
|
||||
QTC_HOST_EXE_SUFFIX));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::makePath(const BaseQtVersion *qtVersion) const
|
||||
@@ -733,6 +772,16 @@ bool AndroidConfig::useNativeUiTools() const
|
||||
return !version.isNull() && version <= QVersionNumber(25, 3 ,0);
|
||||
}
|
||||
|
||||
bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
|
||||
{
|
||||
auto ndkPath = Utils::FilePath::fromUserInput(ndkLocation);
|
||||
const Utils::FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms");
|
||||
|
||||
return ndkPath.exists() && ndkPath.pathAppended("toolchains").exists()
|
||||
&& ndkPlatformsDir.exists() && !ndkPlatformsDir.toString().contains(' ')
|
||||
&& !ndkVersion(ndkPath).isNull();
|
||||
}
|
||||
|
||||
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
|
||||
{
|
||||
target = std::max(AndroidManager::apiLevelRange().first, target);
|
||||
@@ -1076,10 +1125,53 @@ void AndroidConfigurations::registerNewToolChains()
|
||||
const QList<ToolChain *> existingAndroidToolChains
|
||||
= ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId,
|
||||
Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
|
||||
const QList<ToolChain *> newToolchains
|
||||
= AndroidToolChainFactory::autodetectToolChainsForNdk(existingAndroidToolChains);
|
||||
QList<ToolChain *> newToolchains = AndroidToolChainFactory::autodetectToolChains(
|
||||
existingAndroidToolChains);
|
||||
|
||||
foreach (ToolChain *tc, newToolchains)
|
||||
ToolChainManager::registerToolChain(tc);
|
||||
|
||||
registerCustomToolChainsAndDebuggers();
|
||||
}
|
||||
|
||||
void AndroidConfigurations::registerCustomToolChainsAndDebuggers()
|
||||
{
|
||||
const QList<ToolChain *> existingAndroidToolChains = ToolChainManager::toolChains(
|
||||
Utils::equal(&ToolChain::typeId, Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
|
||||
QList<FilePath> customNdks = Utils::transform(currentConfig().getCustomNdkList(),
|
||||
FilePath::fromString);
|
||||
QList<ToolChain *> customToolchains
|
||||
= AndroidToolChainFactory::autodetectToolChainsFromNdks(existingAndroidToolChains,
|
||||
customNdks,
|
||||
true);
|
||||
for (ToolChain *tc : customToolchains) {
|
||||
ToolChainManager::registerToolChain(tc);
|
||||
|
||||
const FilePath ndk = static_cast<AndroidToolChain *>(tc)->ndkLocation();
|
||||
const FilePath command = AndroidConfigurations::currentConfig()
|
||||
.gdbPathFromNdk(tc->targetAbi(), ndk);
|
||||
|
||||
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(
|
||||
command);
|
||||
QString abiStr
|
||||
= static_cast<AndroidToolChain *>(tc)->platformLinkerFlags().at(1).split('-').first();
|
||||
Abi abi = Abi::abiFromTargetTriplet(abiStr);
|
||||
if (existing && existing->abis().contains(abi))
|
||||
continue;
|
||||
|
||||
Debugger::DebuggerItem debugger;
|
||||
debugger.setCommand(command);
|
||||
debugger.setEngineType(Debugger::GdbEngineType);
|
||||
debugger.setUnexpandedDisplayName(
|
||||
AndroidConfigurations::tr("Custom Android Debugger (%1, NDK %2)")
|
||||
.arg(abiStr,
|
||||
AndroidConfigurations::currentConfig().ndkVersion(ndk).toString()));
|
||||
debugger.setAutoDetected(true);
|
||||
debugger.setAbi(abi);
|
||||
debugger.reinitializeFromFile();
|
||||
|
||||
Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidConfigurations::removeOldToolChains()
|
||||
@@ -1090,22 +1182,75 @@ void AndroidConfigurations::removeOldToolChains()
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant findOrRegisterDebugger(ToolChain *tc, const BaseQtVersion *qtVersion)
|
||||
void AndroidConfigurations::removeUnusedDebuggers()
|
||||
{
|
||||
const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi(), qtVersion);
|
||||
QList<FilePath> uniqueNdks;
|
||||
const QList<QtSupport::BaseQtVersion *> qtVersions
|
||||
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
|
||||
return v->type() == Constants::ANDROIDQT;
|
||||
});
|
||||
|
||||
for (const QtSupport::BaseQtVersion *qt : qtVersions) {
|
||||
FilePath ndkLocation = currentConfig().ndkLocation(qt);
|
||||
if (!uniqueNdks.contains(ndkLocation))
|
||||
uniqueNdks.append(ndkLocation);
|
||||
}
|
||||
|
||||
uniqueNdks.append(Utils::transform(currentConfig().getCustomNdkList(), FilePath::fromString));
|
||||
|
||||
const QList<Debugger::DebuggerItem> allDebuggers = Debugger::DebuggerItemManager::debuggers();
|
||||
for (const Debugger::DebuggerItem &debugger : allDebuggers) {
|
||||
if (!debugger.displayName().contains("Android"))
|
||||
continue;
|
||||
|
||||
bool isChildOfNdk = false;
|
||||
for (const FilePath &path : uniqueNdks) {
|
||||
if (debugger.command().isChildOf(path)) {
|
||||
isChildOfNdk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isChildOfNdk && debugger.isAutoDetected())
|
||||
Debugger::DebuggerItemManager::deregisterDebugger(debugger.id());
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant findOrRegisterDebugger(ToolChain *tc,
|
||||
const QStringList &abisList,
|
||||
const BaseQtVersion *qtVersion)
|
||||
{
|
||||
const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi(),
|
||||
qtVersion);
|
||||
// check if the debugger is already registered, but ignoring the display name
|
||||
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command);
|
||||
|
||||
QList<Abi> abis = Utils::transform(abisList, Abi::abiFromTargetTriplet);
|
||||
|
||||
auto containsAbis = [abis](const Abis &secondAbis) {
|
||||
for (const Abi &abi : secondAbis) {
|
||||
if (!abis.contains(abi))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (existing && existing->engineType() == Debugger::GdbEngineType && existing->isAutoDetected()
|
||||
&& existing->abis() == Abis{tc->targetAbi()})
|
||||
&& containsAbis(existing->abis())) {
|
||||
// update debugger info with new
|
||||
return existing->id();
|
||||
}
|
||||
|
||||
// debugger not found, register a new one
|
||||
Debugger::DebuggerItem debugger;
|
||||
debugger.setCommand(command);
|
||||
debugger.setEngineType(Debugger::GdbEngineType);
|
||||
debugger.setUnexpandedDisplayName(
|
||||
AndroidConfigurations::tr("Android Debugger for %1").arg(tc->displayName()));
|
||||
AndroidConfigurations::tr("Android Debugger (%1, NDK %2)")
|
||||
.arg(abisList.join(", "),
|
||||
AndroidConfigurations::currentConfig().ndkVersion(qtVersion).toString()));
|
||||
debugger.setAutoDetected(true);
|
||||
debugger.setAbi(tc->targetAbi());
|
||||
debugger.setAbis(abis.toVector());
|
||||
debugger.reinitializeFromFile();
|
||||
return Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||
}
|
||||
@@ -1136,6 +1281,8 @@ void AndroidConfigurations::updateAutomaticKitList()
|
||||
return false;
|
||||
});
|
||||
|
||||
removeUnusedDebuggers();
|
||||
|
||||
QHash<Abi, QList<const QtSupport::BaseQtVersion *> > qtVersionsForArch;
|
||||
const QList<QtSupport::BaseQtVersion *> qtVersions
|
||||
= QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) {
|
||||
@@ -1199,10 +1346,11 @@ void AndroidConfigurations::updateAutomaticKitList()
|
||||
ToolChainKitAspect::setToolChain(k, tc);
|
||||
QtSupport::QtKitAspect::setQtVersion(k, qt);
|
||||
DeviceKitAspect::setDevice(k, device);
|
||||
Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc, QtKitAspect::qtVersion(k)));
|
||||
QStringList abis = static_cast<const AndroidQtVersion *>(qt)->androidAbis();
|
||||
Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc, abis, QtKitAspect::qtVersion(k)));
|
||||
k->makeSticky();
|
||||
k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
|
||||
.arg(static_cast<const AndroidQtVersion *>(qt)->androidAbis().join(","))
|
||||
.arg(abis.join(","))
|
||||
.arg(qt->displayName()));
|
||||
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation(qt).toString());
|
||||
k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
|
||||
|
||||
@@ -160,9 +160,12 @@ public:
|
||||
Utils::FilePath aaptToolPath() const;
|
||||
|
||||
Utils::FilePath toolchainPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||
Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||
Utils::FilePath clangPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||
Utils::FilePath clangPathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||
|
||||
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const;
|
||||
Utils::FilePath gdbPathFromNdk(const ProjectExplorer::Abi &abi, const Utils::FilePath &ndkLocation) const;
|
||||
Utils::FilePath makePath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||
Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||
|
||||
@@ -188,6 +191,11 @@ public:
|
||||
bool sdkFullyConfigured() const { return m_sdkFullyConfigured; };
|
||||
void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; };
|
||||
|
||||
bool isValidNdk(const QString &ndkLocation) const;
|
||||
QStringList getCustomNdkList() const;
|
||||
void addCustomNdk(const QString &customNdk);
|
||||
void removeCustomNdk(const QString &customNdk);
|
||||
|
||||
private:
|
||||
static QString getDeviceProperty(const Utils::FilePath &adbToolPath,
|
||||
const QString &device, const QString &property);
|
||||
@@ -216,6 +224,7 @@ private:
|
||||
QStringList m_commonEssentialPkgs;
|
||||
SdkForQtVersions m_defaultSdkDepends;
|
||||
QList<SdkForQtVersions> m_specificQtVersions;
|
||||
QStringList m_customNdkList;
|
||||
bool m_sdkFullyConfigured = false;
|
||||
|
||||
//caches
|
||||
@@ -237,6 +246,8 @@ public:
|
||||
static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name
|
||||
static void clearDefaultDevices(ProjectExplorer::Project *project);
|
||||
static void registerNewToolChains();
|
||||
static void registerCustomToolChainsAndDebuggers();
|
||||
static void removeUnusedDebuggers();
|
||||
static void removeOldToolChains();
|
||||
static void updateAutomaticKitList();
|
||||
static bool force32bitEmulator();
|
||||
|
||||
@@ -240,6 +240,18 @@ void AndroidManifestEditorWidget::initializePage()
|
||||
m_targetLineEdit->installEventFilter(this);
|
||||
formLayout->addRow(tr("Run:"), m_targetLineEdit);
|
||||
|
||||
m_styleExtractMethod = new QComboBox(applicationGroupBox);
|
||||
formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod);
|
||||
const QList<QStringList> styleMethodsMap = {
|
||||
{"default", "In most cases this will be the same as \"full\", but it can also be something else if needed, e.g. for compatibility reasons."},
|
||||
{"full", "Useful for Qt Widgets & Qt Quick Controls 1 apps."},
|
||||
{"minimal", "Useful for Qt Quick Controls 2 apps, it is much faster than \"full\"."},
|
||||
{"none", "Useful for apps that don't use Qt Widgets, Qt Quick Controls 1 or Qt Quick Controls 2."}};
|
||||
for (int i = 0; i <styleMethodsMap.size(); ++i) {
|
||||
m_styleExtractMethod->addItem(styleMethodsMap.at(i).first());
|
||||
m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole);
|
||||
}
|
||||
|
||||
auto iconLayout = new QHBoxLayout();
|
||||
|
||||
createDPIButton(iconLayout,
|
||||
@@ -297,6 +309,9 @@ void AndroidManifestEditorWidget::initializePage()
|
||||
this, setDirtyFunc);
|
||||
connect(m_targetLineEdit, &QComboBox::currentTextChanged,
|
||||
this, setDirtyFunc);
|
||||
connect(m_styleExtractMethod,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, setDirtyFunc);
|
||||
|
||||
connect(m_masterIconButton, &QAbstractButton::clicked,
|
||||
this, &AndroidManifestEditorWidget::setMasterIcon);
|
||||
@@ -331,17 +346,6 @@ void AndroidManifestEditorWidget::initializePage()
|
||||
m_defaultFeaturesCheckBox->setText(tr("Include default features for Qt modules."));
|
||||
layout->addWidget(m_defaultFeaturesCheckBox, 1, 0);
|
||||
|
||||
m_permissionsModel = new PermissionsModel(this);
|
||||
|
||||
m_permissionsListView = new QListView(permissionsGroupBox);
|
||||
m_permissionsListView->setModel(m_permissionsModel);
|
||||
m_permissionsListView->setMinimumSize(QSize(0, 200));
|
||||
layout->addWidget(m_permissionsListView, 2, 0, 3, 1);
|
||||
|
||||
m_removePermissionButton = new QPushButton(permissionsGroupBox);
|
||||
m_removePermissionButton->setText(tr("Remove"));
|
||||
layout->addWidget(m_removePermissionButton, 2, 1);
|
||||
|
||||
m_permissionsComboBox = new QComboBox(permissionsGroupBox);
|
||||
m_permissionsComboBox->insertItems(0, QStringList()
|
||||
<< QLatin1String("android.permission.ACCESS_CHECKIN_PROPERTIES")
|
||||
@@ -476,11 +480,22 @@ void AndroidManifestEditorWidget::initializePage()
|
||||
<< QLatin1String("android.permission.WRITE_USER_DICTIONARY")
|
||||
);
|
||||
m_permissionsComboBox->setEditable(true);
|
||||
layout->addWidget(m_permissionsComboBox, 6, 0);
|
||||
layout->addWidget(m_permissionsComboBox, 2, 0);
|
||||
|
||||
m_addPermissionButton = new QPushButton(permissionsGroupBox);
|
||||
m_addPermissionButton->setText(tr("Add"));
|
||||
layout->addWidget(m_addPermissionButton, 6, 1);
|
||||
layout->addWidget(m_addPermissionButton, 2, 1);
|
||||
|
||||
m_permissionsModel = new PermissionsModel(this);
|
||||
|
||||
m_permissionsListView = new QListView(permissionsGroupBox);
|
||||
m_permissionsListView->setModel(m_permissionsModel);
|
||||
m_permissionsListView->setMinimumSize(QSize(0, 200));
|
||||
layout->addWidget(m_permissionsListView, 3, 0, 3, 1);
|
||||
|
||||
m_removePermissionButton = new QPushButton(permissionsGroupBox);
|
||||
m_removePermissionButton->setText(tr("Remove"));
|
||||
layout->addWidget(m_removePermissionButton, 3, 1);
|
||||
|
||||
permissionsGroupBox->setLayout(layout);
|
||||
|
||||
@@ -804,11 +819,21 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
|
||||
|
||||
QDomElement metadataElem = activityElem.firstChildElement(QLatin1String("meta-data"));
|
||||
|
||||
const int parseItemsCount = 2;
|
||||
int counter = 0;
|
||||
while (!metadataElem.isNull()) {
|
||||
if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) {
|
||||
m_targetLineEdit->setEditText(metadataElem.attribute(QLatin1String("android:value")));
|
||||
break;
|
||||
++counter;
|
||||
} else if (metadataElem.attribute(QLatin1String("android:name"))
|
||||
== QLatin1String("android.app.extract_android_style")) {
|
||||
m_styleExtractMethod->setCurrentText(
|
||||
metadataElem.attribute(QLatin1String("android:value")));
|
||||
++counter;
|
||||
}
|
||||
|
||||
if (counter == parseItemsCount)
|
||||
break;
|
||||
metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data"));
|
||||
}
|
||||
|
||||
@@ -1093,15 +1118,24 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt
|
||||
{
|
||||
Q_ASSERT(reader.isStartElement());
|
||||
|
||||
bool found = false;
|
||||
const int parseItemsCount = 2;
|
||||
int counter = 0;
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
QXmlStreamAttributes result;
|
||||
QStringList keys;
|
||||
QStringList values;
|
||||
|
||||
if (attributes.value(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) {
|
||||
QStringList keys = QStringList("android:value");
|
||||
QStringList values = QStringList(m_targetLineEdit->currentText());
|
||||
keys = QStringList("android:value");
|
||||
values = QStringList(m_targetLineEdit->currentText());
|
||||
result = modifyXmlStreamAttributes(attributes, keys, values);
|
||||
found = true;
|
||||
++counter;
|
||||
} else if (attributes.value(QLatin1String("android:name"))
|
||||
== QLatin1String("android.app.extract_android_style")) {
|
||||
keys = QStringList("android:value");
|
||||
values = QStringList(m_styleExtractMethod->currentText());
|
||||
result = modifyXmlStreamAttributes(attributes, keys, values);
|
||||
++counter;
|
||||
} else {
|
||||
result = attributes;
|
||||
}
|
||||
@@ -1114,7 +1148,7 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt
|
||||
while (!reader.atEnd()) {
|
||||
if (reader.isEndElement()) {
|
||||
writer.writeCurrentToken(reader);
|
||||
return found;
|
||||
return counter == parseItemsCount;
|
||||
} else if (reader.isStartElement()) {
|
||||
parseUnknownElement(reader, writer);
|
||||
} else {
|
||||
@@ -1122,7 +1156,7 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt
|
||||
}
|
||||
reader.readNext();
|
||||
}
|
||||
return found; // should never be reached
|
||||
return counter == parseItemsCount; // should never be reached
|
||||
}
|
||||
|
||||
void AndroidManifestEditorWidget::parseUsesSdk(QXmlStreamReader &reader, QXmlStreamWriter & writer)
|
||||
|
||||
@@ -189,6 +189,7 @@ private:
|
||||
QLineEdit *m_appNameLineEdit;
|
||||
QLineEdit *m_activityNameLineEdit;
|
||||
QComboBox *m_targetLineEdit;
|
||||
QComboBox *m_styleExtractMethod;
|
||||
QToolButton *m_masterIconButton;
|
||||
QToolButton *m_lIconButton;
|
||||
QToolButton *m_lIconClearButton;
|
||||
|
||||
@@ -177,8 +177,8 @@ void AndroidPlugin::kitsRestored()
|
||||
&AndroidPlugin::askUserAboutAndroidSetup, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
AndroidConfigurations::updateAutomaticKitList();
|
||||
AndroidConfigurations::registerNewToolChains();
|
||||
AndroidConfigurations::updateAutomaticKitList();
|
||||
connect(QtSupport::QtVersionManager::instance(), &QtSupport::QtVersionManager::qtVersionsChanged,
|
||||
AndroidConfigurations::instance(), &AndroidConfigurations::updateAutomaticKitList);
|
||||
disconnect(KitManager::instance(), &KitManager::kitsLoaded,
|
||||
|
||||
@@ -133,6 +133,7 @@ private:
|
||||
bool sdkToolsOk() const;
|
||||
Utils::FilePath getDefaultSdkPath();
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void addCustomNdkItem();
|
||||
|
||||
Ui_AndroidSettingsWidget *m_ui;
|
||||
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
||||
@@ -342,7 +343,7 @@ void AndroidSettingsWidget::showEvent(QShowEvent *event)
|
||||
// Reloading SDK packages (force) is still synchronous. Use zero timer
|
||||
// to let settings dialog open first.
|
||||
QTimer::singleShot(0, std::bind(&AndroidSdkManager::reloadPackages,
|
||||
m_sdkManager.get(), true));
|
||||
m_sdkManager.get(), false));
|
||||
m_isInitialReloadDone = true;
|
||||
}
|
||||
}
|
||||
@@ -352,6 +353,22 @@ void AndroidSettingsWidget::updateNdkList()
|
||||
m_ui->ndkListComboBox->clear();
|
||||
for (const Ndk *ndk : m_sdkManager->installedNdkPackages())
|
||||
m_ui->ndkListComboBox->addItem(ndk->installedLocation().toString());
|
||||
|
||||
for (const QString &ndk : m_androidConfig.getCustomNdkList()) {
|
||||
if (m_androidConfig.isValidNdk(ndk))
|
||||
m_ui->ndkListComboBox->addItem(ndk);
|
||||
else
|
||||
m_androidConfig.removeCustomNdk(ndk);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::addCustomNdkItem()
|
||||
{
|
||||
const QString ndkPath = QDir::toNativeSeparators(m_ui->customNdkPathChooser->rawPath());
|
||||
m_androidConfig.addCustomNdk(ndkPath);
|
||||
if (m_ui->ndkListComboBox->findData(ndkPath) == -1)
|
||||
m_ui->ndkListComboBox->addItem(ndkPath);
|
||||
m_ui->ndkListComboBox->setCurrentText(ndkPath);
|
||||
}
|
||||
|
||||
AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
@@ -435,8 +452,23 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
|
||||
connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
|
||||
this, &AndroidSettingsWidget::onSdkPathChanged);
|
||||
connect(m_ui->ndkListComboBox, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
||||
[this](const QString) { validateNdk(); });
|
||||
connect(m_ui->ndkListComboBox,
|
||||
QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
||||
[this](const QString &ndk) {
|
||||
validateNdk();
|
||||
m_ui->removeCustomNdkButton->setEnabled(m_androidConfig.getCustomNdkList().contains(ndk));
|
||||
});
|
||||
connect(m_ui->customNdkPathChooser, &Utils::PathChooser::rawPathChanged, this, [this]() {
|
||||
const QString ndkPath = m_ui->customNdkPathChooser->rawPath();
|
||||
m_ui->addCustomNdkButton->setEnabled(m_androidConfig.isValidNdk(ndkPath));
|
||||
});
|
||||
connect(m_ui->addCustomNdkButton, &QPushButton::clicked, this,
|
||||
&AndroidSettingsWidget::addCustomNdkItem);
|
||||
connect(m_ui->removeCustomNdkButton, &QPushButton::clicked, this, [this]() {
|
||||
m_androidConfig.removeCustomNdk(m_ui->ndkListComboBox->currentText());
|
||||
m_ui->ndkListComboBox->removeItem(m_ui->ndkListComboBox->currentIndex());
|
||||
});
|
||||
|
||||
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
|
||||
this, &AndroidSettingsWidget::updateAvds);
|
||||
connect(m_ui->AVDRefreshPushButton, &QAbstractButton::clicked,
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="SDKLocationLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -106,21 +106,24 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QToolButton" name="downloadSDKToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Download Android SDK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="ndkComboBoxLabel">
|
||||
<widget class="QLabel" name="customNdkLabel">
|
||||
<property name="text">
|
||||
<string>Android NDK list:</string>
|
||||
<string>Add custom NDK:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="1" column="6">
|
||||
<widget class="QToolButton" name="downloadNDKToolButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QToolButton" name="sdkToolsAutoDownloadButton">
|
||||
<property name="toolTip">
|
||||
<string>Automatically download Android SDK Tools to selected location.</string>
|
||||
@@ -130,29 +133,74 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="5">
|
||||
<item row="3" column="0" colspan="7">
|
||||
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QToolButton" name="downloadNDKToolButton">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="ndkComboBoxLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
<string>Android NDK list:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true">
|
||||
<item row="0" column="6">
|
||||
<widget class="QToolButton" name="downloadSDKToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Download Android SDK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="Utils::PathChooser" name="customNdkPathChooser" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="addCustomNdkButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add the selected custom NDK. The toolchains and debuggers will be created automatically.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="ndkListComboBox"/>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="removeCustomNdkButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove the selected custom NDK.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -351,6 +399,10 @@
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
<slots>
|
||||
<signal>editingFinished()</signal>
|
||||
<signal>browsingFinished()</signal>
|
||||
</slots>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Utils::DetailsWidget</class>
|
||||
|
||||
@@ -93,14 +93,22 @@ AndroidToolChain::~AndroidToolChain() = default;
|
||||
|
||||
bool AndroidToolChain::isValid() const
|
||||
{
|
||||
if (m_ndkLocation.isEmpty()) {
|
||||
QStringList ndkParts(compilerCommand().toString().split("toolchains/llvm/prebuilt/"));
|
||||
if (ndkParts.size() > 1) {
|
||||
QString ndkLocation(ndkParts.first());
|
||||
if (ndkLocation.endsWith('/'))
|
||||
ndkLocation.chop(1);
|
||||
m_ndkLocation = FilePath::fromString(ndkLocation);
|
||||
}
|
||||
}
|
||||
|
||||
const bool isChildofNdk = compilerCommand().isChildOf(m_ndkLocation);
|
||||
// If we're restoring a toolchain we set NDK path ourselves so it's enough to check against SDK
|
||||
const bool isChildofSdk = compilerCommand().isChildOf(
|
||||
AndroidConfigurations::currentConfig().sdkLocation());
|
||||
|
||||
return ClangToolChain::isValid() && typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
|
||||
&& targetAbi().isValid()
|
||||
&& (isChildofNdk || isChildofSdk)
|
||||
&& targetAbi().isValid() && (isChildofNdk || isChildofSdk)
|
||||
&& !originalTargetTriple().isEmpty();
|
||||
}
|
||||
|
||||
@@ -163,7 +171,7 @@ AndroidToolChainFactory::AndroidToolChainFactory()
|
||||
|
||||
ToolChainList AndroidToolChainFactory::autoDetect(const ToolChainList &alreadyKnown)
|
||||
{
|
||||
return autodetectToolChainsForNdk(alreadyKnown);
|
||||
return autodetectToolChains(alreadyKnown);
|
||||
}
|
||||
|
||||
static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
||||
@@ -173,7 +181,7 @@ static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
||||
QFileInfo(clangPath.toString()).baseName() + "++"));
|
||||
}
|
||||
|
||||
static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
|
||||
static QList<FilePath> uniqueNdksForCurrentQtVersions()
|
||||
{
|
||||
AndroidConfig config = AndroidConfigurations::currentConfig();
|
||||
|
||||
@@ -182,36 +190,40 @@ static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
|
||||
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
|
||||
});
|
||||
|
||||
auto shouldRemove = [config](const QtSupport::BaseQtVersion *first,
|
||||
const QtSupport::BaseQtVersion *second) {
|
||||
return config.ndkLocation(first) == config.ndkLocation(second);
|
||||
};
|
||||
QList<FilePath> uniqueNdks;
|
||||
for (const QtSupport::BaseQtVersion *version : androidQtVersions) {
|
||||
FilePath ndk = config.ndkLocation(version);
|
||||
if (!uniqueNdks.contains(ndk))
|
||||
uniqueNdks.append(ndk);
|
||||
}
|
||||
|
||||
QList<QtSupport::BaseQtVersion *>::iterator it = std::unique(androidQtVersions.begin(),
|
||||
androidQtVersions.end(),
|
||||
shouldRemove);
|
||||
androidQtVersions.erase(it, androidQtVersions.end());
|
||||
|
||||
return androidQtVersions;
|
||||
return uniqueNdks;
|
||||
}
|
||||
|
||||
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChainList &alreadyKnown)
|
||||
ToolChainList AndroidToolChainFactory::autodetectToolChains(const ToolChainList &alreadyKnown)
|
||||
{
|
||||
const QList<Utils::FilePath> uniqueNdks = uniqueNdksForCurrentQtVersions();
|
||||
return autodetectToolChainsFromNdks(alreadyKnown, uniqueNdks);
|
||||
}
|
||||
|
||||
ToolChainList AndroidToolChainFactory::autodetectToolChainsFromNdks(
|
||||
const ToolChainList &alreadyKnown,
|
||||
const QList<Utils::FilePath> &ndkLocations,
|
||||
const bool isCustom)
|
||||
{
|
||||
QList<ToolChain *> result;
|
||||
const QList<QtSupport::BaseQtVersion *> androidQtVersions = androidQtVersionsWithUniqueNdk();
|
||||
const AndroidConfig config = AndroidConfigurations::currentConfig();
|
||||
|
||||
for (const QtSupport::BaseQtVersion *qtVersion : androidQtVersions) {
|
||||
FilePath clangPath = config.clangPath(qtVersion);
|
||||
for (const Utils::FilePath &ndkLocation : ndkLocations) {
|
||||
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:" << ndkLocation;
|
||||
|
||||
FilePath clangPath = config.clangPathFromNdk(ndkLocation);
|
||||
if (!clangPath.exists()) {
|
||||
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
|
||||
<< clangPath;
|
||||
return result;
|
||||
continue;
|
||||
}
|
||||
|
||||
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
|
||||
<< config.ndkLocation(qtVersion);
|
||||
|
||||
for (const Core::Id &lang : LanguageIds) {
|
||||
FilePath compilerCommand = clangPath;
|
||||
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
||||
@@ -229,10 +241,11 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
|
||||
const QString target = targetItr.key();
|
||||
ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown);
|
||||
|
||||
const QString displayName(QString("Android Clang (%1, %2, NDK %3)")
|
||||
QLatin1String customStr = isCustom ? QLatin1String("Custom ") : QLatin1String();
|
||||
const QString displayName(customStr + QString("Android Clang (%1, %2, NDK %3)")
|
||||
.arg(ToolChainManager::displayNameOfLanguageId(lang),
|
||||
AndroidConfig::displayName(abi),
|
||||
config.ndkVersion(qtVersion).toString()));
|
||||
config.ndkVersion(ndkLocation).toString()));
|
||||
if (tc) {
|
||||
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
||||
// make sure to update the toolchain with current name format
|
||||
@@ -241,7 +254,7 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
|
||||
} else {
|
||||
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
||||
auto atc = new AndroidToolChain();
|
||||
atc->setNdkLocation(config.ndkLocation(qtVersion));
|
||||
atc->setNdkLocation(ndkLocation);
|
||||
atc->setOriginalTargetTriple(target);
|
||||
atc->setLanguage(lang);
|
||||
atc->setTargetAbi(ClangTargets[target]);
|
||||
|
||||
@@ -59,7 +59,7 @@ private:
|
||||
|
||||
friend class AndroidToolChainFactory;
|
||||
|
||||
Utils::FilePath m_ndkLocation;
|
||||
mutable Utils::FilePath m_ndkLocation;
|
||||
};
|
||||
|
||||
class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory
|
||||
@@ -78,7 +78,10 @@ public:
|
||||
QString version;
|
||||
};
|
||||
|
||||
static ToolChainList autodetectToolChainsForNdk(const ToolChainList &alreadyKnown);
|
||||
static ToolChainList autodetectToolChains(const ToolChainList &alreadyKnown);
|
||||
static ToolChainList autodetectToolChainsFromNdks(const ToolChainList &alreadyKnown,
|
||||
const QList<Utils::FilePath> &ndkLocations,
|
||||
const bool isCustom = false);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <texteditor/codeassist/keywordscompletionassist.h>
|
||||
#include <coreplugin/editormanager/ieditorfactory.h>
|
||||
#include <texteditor/normalindenter.h>
|
||||
#include <texteditor/textdocument.h>
|
||||
#include <texteditor/texteditoractionhandler.h>
|
||||
#include <texteditor/texteditorconstants.h>
|
||||
|
||||
Reference in New Issue
Block a user