From 01ebbe19bae9af7fa352a60461e12d48bf739720 Mon Sep 17 00:00:00 2001
From: Mehdi Fekari <mfekari@rim.com>
Date: Thu, 22 Aug 2013 17:00:58 +0200
Subject: [PATCH] Qnx: Support multiple BlackBerry target configurations

The new bbndk 10.2 is based on multiple targets (based on multiple bbnk-env scripts).
There is no default/common bbnk-env.sh file anymore, and an NDK directory may contain
various bbndk-env scripts (i.e targets).

This patch makes the BlackBerryConfiguration based on the bbnk-env script path
rather than on the NDK path. This will enable having multiple configurations
per targets in the same NDK directory.

N.B: NDKs 10.1 with one default bbnk-env file are still supported.

Change-Id: Icec57c6e722caec7e5ff81e3a9ce4d2cf11f249a
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
Reviewed-by: Nicolas Arnaud-Cormos <nicolas@kdab.com>
---
 src/plugins/qnx/blackberryconfiguration.cpp   |  22 ++-
 src/plugins/qnx/blackberryconfiguration.h     |   5 +-
 .../qnx/blackberryconfigurationmanager.cpp    |  25 ++-
 .../qnx/blackberryconfigurationmanager.h      |   2 +-
 .../qnx/blackberryndksettingswidget.cpp       |  96 +++-------
 src/plugins/qnx/blackberryndksettingswidget.h |   7 +-
 .../qnx/blackberryndksettingswidget.ui        | 171 +++++++++++++++++-
 src/plugins/qnx/blackberryqtversion.cpp       |  34 +++-
 src/plugins/qnx/blackberryqtversion.h         |   5 +
 src/plugins/qnx/qnxutils.cpp                  |   6 +-
 src/plugins/qnx/qnxutils.h                    |   4 +-
 11 files changed, 276 insertions(+), 101 deletions(-)

diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp
index db449ef36e9..e19250008c9 100644
--- a/src/plugins/qnx/blackberryconfiguration.cpp
+++ b/src/plugins/qnx/blackberryconfiguration.cpp
@@ -54,12 +54,15 @@
 namespace Qnx {
 namespace Internal {
 
-BlackBerryConfiguration::BlackBerryConfiguration(const QString &ndkPath, bool isAutoDetected, const QString &displayName)
+BlackBerryConfiguration::BlackBerryConfiguration(const Utils::FileName &ndkEnvFile, bool isAutoDetected,
+                                                 const QString &displayName)
 {
-    m_ndkPath = ndkPath;
+    Q_ASSERT(!QFileInfo(ndkEnvFile.toString()).isDir());
+    m_ndkEnvFile = ndkEnvFile;
     m_isAutoDetected = isAutoDetected;
-    m_displayName = displayName.isEmpty() ? m_ndkPath.split(QDir::separator()).last() : displayName;
-    m_qnxEnv = QnxUtils::parseEnvironmentFile(QnxUtils::envFilePath(m_ndkPath));
+    QString ndkPath = ndkEnvFile.parentDir().toString();
+    m_displayName = displayName.isEmpty() ? ndkPath.split(QDir::separator()).last() : displayName;
+    m_qnxEnv = QnxUtils::parseEnvironmentFile(m_ndkEnvFile.toString());
 
     QString ndkTarget = m_qnxEnv.value(QLatin1String("QNX_TARGET"));
     QString sep = QString::fromLatin1("%1qnx6").arg(QDir::separator());
@@ -94,7 +97,7 @@ BlackBerryConfiguration::BlackBerryConfiguration(const QString &ndkPath, bool is
 
 QString BlackBerryConfiguration::ndkPath() const
 {
-    return m_ndkPath;
+    return m_ndkEnvFile.parentDir().toString();
 }
 
 QString BlackBerryConfiguration::displayName() const
@@ -125,6 +128,11 @@ bool BlackBerryConfiguration::isValid() const
             || m_deviceDebuger.isEmpty() || m_simulatorDebuger.isEmpty());
 }
 
+Utils::FileName BlackBerryConfiguration::ndkEnvFile() const
+{
+    return m_ndkEnvFile;
+}
+
 Utils::FileName BlackBerryConfiguration::qmake4BinaryFile() const
 {
     return m_qmake4BinaryFile;
@@ -193,7 +201,7 @@ QtSupport::BaseQtVersion *BlackBerryConfiguration::createQtVersion(const Utils::
         return version;
     }
 
-    version = new BlackBerryQtVersion(QnxUtils::cpudirToArch(cpuDir), qmakePath, m_isAutoDetected, QString(), m_ndkPath);
+    version = new BlackBerryQtVersion(QnxUtils::cpudirToArch(cpuDir), qmakePath, m_isAutoDetected, QString(), m_ndkEnvFile.toString());
     if (!version) {
         if (!m_isAutoDetected)
             QMessageBox::warning(0, QObject::tr("Invalid Qt Version"),
@@ -288,7 +296,7 @@ bool BlackBerryConfiguration::activate()
         if (m_isAutoDetected)
             return false;
 
-        QString errorMessage = QObject::tr("The following errors occurred while activating NDK: %1").arg(m_ndkPath);
+        QString errorMessage = QObject::tr("The following errors occurred while activating Target: %1").arg(m_targetName);
         if (m_qmake4BinaryFile.isEmpty() && m_qmake4BinaryFile.isEmpty())
             errorMessage += QLatin1Char('\n') + QObject::tr("- No Qt version found.");
 
diff --git a/src/plugins/qnx/blackberryconfiguration.h b/src/plugins/qnx/blackberryconfiguration.h
index 2df1430dcfc..7e860be16d8 100644
--- a/src/plugins/qnx/blackberryconfiguration.h
+++ b/src/plugins/qnx/blackberryconfiguration.h
@@ -50,7 +50,7 @@ namespace Internal {
 class BlackBerryConfiguration
 {
 public:
-    BlackBerryConfiguration(const QString& ndkPath, bool isAutoDetected, const QString &displayName = QString());
+    BlackBerryConfiguration(const Utils::FileName &ndkEnvFile, bool isAutoDetected, const QString &displayName = QString());
     bool activate();
     void deactivate();
     QString ndkPath() const;
@@ -59,6 +59,7 @@ public:
     bool isAutoDetected() const;
     bool isActive() const;
     bool isValid() const;
+    Utils::FileName ndkEnvFile() const;
     Utils::FileName qmake4BinaryFile() const;
     Utils::FileName qmake5BinaryFile() const;
     Utils::FileName gccCompiler() const;
@@ -68,10 +69,10 @@ public:
     QMultiMap<QString, QString> qnxEnv() const;
 
 private:
-    QString m_ndkPath;
     QString m_displayName;
     QString m_targetName;
     bool m_isAutoDetected;
+    Utils::FileName m_ndkEnvFile;
     Utils::FileName m_qmake4BinaryFile;
     Utils::FileName m_qmake5BinaryFile;
     Utils::FileName m_gccCompiler;
diff --git a/src/plugins/qnx/blackberryconfigurationmanager.cpp b/src/plugins/qnx/blackberryconfigurationmanager.cpp
index 713e52aa788..96a22464877 100644
--- a/src/plugins/qnx/blackberryconfigurationmanager.cpp
+++ b/src/plugins/qnx/blackberryconfigurationmanager.cpp
@@ -49,13 +49,15 @@
 #include <qtsupport/qtkitinformation.h>
 
 #include <QMessageBox>
+#include <QFileInfo>
 
 namespace Qnx {
 namespace Internal {
 
 namespace {
 const QLatin1String SettingsGroup("BlackBerryConfiguration");
-const QLatin1String NDKLocationKey("NDKLocation");
+const QLatin1String NDKLocationKey("NDKLocation"); // For 10.1 NDK support (< QTC 3.0)
+const QLatin1String NDKEnvFileKey("NDKEnvFile");
 const QLatin1String CertificateGroup("Certificates");
 const QLatin1String ManualNDKsGroup("ManualNDKs");
 }
@@ -102,7 +104,16 @@ void BlackBerryConfigurationManager::loadManualConfigurations()
 
     foreach (const QString &manualNdk, settings->childGroups()) {
         settings->beginGroup(manualNdk);
-        BlackBerryConfiguration *config = new BlackBerryConfiguration(settings->value(NDKLocationKey).toString(),
+        QString ndkEnvPath = settings->value(NDKEnvFileKey).toString();
+        // For 10.1 NDK support (< QTC 3.0):
+        // Since QTC 3.0 BBConfigurations are based on the bbndk-env file
+        // to support multiple targets per NDK
+        if (ndkEnvPath.isEmpty()) {
+            QString ndkPath = settings->value(NDKLocationKey).toString();
+            ndkEnvPath = QnxUtils::envFilePath(ndkPath);
+        }
+
+        BlackBerryConfiguration *config = new BlackBerryConfiguration(Utils::FileName::fromString(ndkEnvPath),
                                                                       false);
         if (!addConfiguration(config))
             delete config;
@@ -117,7 +128,9 @@ void BlackBerryConfigurationManager::loadManualConfigurations()
 void BlackBerryConfigurationManager::loadAutoDetectedConfigurations()
 {
     foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks()) {
-        BlackBerryConfiguration *config = new BlackBerryConfiguration(ndkInfo.path, true, ndkInfo.name);
+        QString envFilePath = QnxUtils::envFilePath(ndkInfo.path, ndkInfo.version);
+        BlackBerryConfiguration *config = new BlackBerryConfiguration(Utils::FileName::fromString(envFilePath),
+                                                                      true, ndkInfo.name);
         if (!addConfiguration(config))
             delete config;
     }
@@ -157,7 +170,7 @@ void BlackBerryConfigurationManager::saveManualConfigurations()
 
     foreach (BlackBerryConfiguration *config, manualConfigurations()) {
         settings->beginGroup(config->displayName());
-        settings->setValue(NDKLocationKey, config->ndkPath());
+        settings->setValue(NDKEnvFileKey, config->ndkEnvFile().toString());
         settings->endGroup();
     }
 
@@ -243,10 +256,10 @@ QList<BlackBerryConfiguration *> BlackBerryConfigurationManager::manualConfigura
     return manuals;
 }
 
-BlackBerryConfiguration *BlackBerryConfigurationManager::configurationFromNdkPath(const QString &ndkPath) const
+BlackBerryConfiguration *BlackBerryConfigurationManager::configurationFromEnvFile(const Utils::FileName &envFile) const
 {
     foreach (BlackBerryConfiguration *config, m_configs) {
-        if (config->ndkPath() == ndkPath)
+        if (config->ndkEnvFile() == envFile)
             return config;
     }
 
diff --git a/src/plugins/qnx/blackberryconfigurationmanager.h b/src/plugins/qnx/blackberryconfigurationmanager.h
index c76ac4e2028..d170436875d 100644
--- a/src/plugins/qnx/blackberryconfigurationmanager.h
+++ b/src/plugins/qnx/blackberryconfigurationmanager.h
@@ -54,7 +54,7 @@ public:
     void removeConfiguration(BlackBerryConfiguration *config);
     QList<BlackBerryConfiguration*> configurations() const;
     QList<BlackBerryConfiguration*> manualConfigurations() const;
-    BlackBerryConfiguration *configurationFromNdkPath(const QString &ndkPath) const;
+    BlackBerryConfiguration *configurationFromEnvFile(const Utils::FileName &envFile) const;
 
     QString barsignerCskPath() const;
     QString barsignerDbPath() const;
diff --git a/src/plugins/qnx/blackberryndksettingswidget.cpp b/src/plugins/qnx/blackberryndksettingswidget.cpp
index 0be77f4ba67..1db4ab6bf24 100644
--- a/src/plugins/qnx/blackberryndksettingswidget.cpp
+++ b/src/plugins/qnx/blackberryndksettingswidget.cpp
@@ -62,12 +62,11 @@ BlackBerryNDKSettingsWidget::BlackBerryNDKSettingsWidget(QWidget *parent) :
 
     m_ui->removeNdkButton->setEnabled(false);
 
-    initInfoTable();
     initNdkList();
 
     connect(m_ui->wizardButton, SIGNAL(clicked()), this, SLOT(launchBlackBerrySetupWizard()));
-    connect(m_ui->addNdkButton, SIGNAL(clicked()), this, SLOT(addNdk()));
-    connect(m_ui->removeNdkButton, SIGNAL(clicked()), this, SLOT(removeNdk()));
+    connect(m_ui->addNdkButton, SIGNAL(clicked()), this, SLOT(addNdkTarget()));
+    connect(m_ui->removeNdkButton, SIGNAL(clicked()), this, SLOT(removeNdkTarget()));
     connect(m_ui->ndksTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateInfoTable(QTreeWidgetItem*)));
 }
 
@@ -98,49 +97,27 @@ void BlackBerryNDKSettingsWidget::launchBlackBerrySetupWizard() const
 
 void BlackBerryNDKSettingsWidget::updateInfoTable(QTreeWidgetItem* currentNdk)
 {
-    QString ndkPath = currentNdk->text(1);
-    if (ndkPath.isEmpty()) {
+    QString envFilePath = currentNdk->text(1);
+    if (envFilePath.isEmpty()) {
         m_ui->removeNdkButton->setEnabled(false);
         return;
     }
 
-    QMultiMap<QString, QString> env = QnxUtils::parseEnvironmentFile(QnxUtils::envFilePath(ndkPath));
-    if (env.isEmpty()) {
-        clearInfoTable();
-        return;
-    }
-
-    m_infoModel->clear();
-    m_infoModel->setHorizontalHeaderItem(0, new QStandardItem(QString(QLatin1String("Variable"))));
-    m_infoModel->setHorizontalHeaderItem(1, new QStandardItem(QString(QLatin1String("Value"))));
-
-    m_ui->ndkInfosTableView->horizontalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
-    m_ui->ndkInfosTableView->horizontalHeader()->setStretchLastSection(true);
-
-    QMultiMap<QString, QString>::const_iterator it;
-    QMultiMap<QString, QString>::const_iterator end(env.constEnd());
-    for (it = env.constBegin(); it != end; ++it) {
-        const QString key = it.key();
-        const QString value = it.value();
-        QList <QStandardItem*> row;
-        row << new QStandardItem(key) << new QStandardItem(value);
-        m_infoModel->appendRow(row);
-    }
-
-    BlackBerryConfiguration *config = m_bbConfigManager->configurationFromNdkPath(ndkPath);
+    BlackBerryConfiguration *config = m_bbConfigManager->configurationFromEnvFile(Utils::FileName::fromString(envFilePath));
     if (!config)
         return;
 
-    QString qmake4Path = config->qmake4BinaryFile().toString();
-    QString qmake5Path = config->qmake5BinaryFile().toString();
-
-    if (!qmake4Path.isEmpty())
-        m_infoModel->appendRow(QList<QStandardItem*>() << new QStandardItem(QString(QLatin1String("QMAKE 4"))) << new QStandardItem(qmake4Path));
-
-    if (!qmake5Path.isEmpty())
-        m_infoModel->appendRow(QList<QStandardItem*>() << new QStandardItem(QString(QLatin1String("QMAKE 5"))) << new QStandardItem(qmake5Path));
-
-    m_infoModel->appendRow(QList<QStandardItem*>() << new QStandardItem(QString(QLatin1String("COMPILER"))) << new QStandardItem(config->gccCompiler().toString()));
+    foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks())
+    {
+        if (ndkInfo.target.contains(config->targetName())) {
+            m_ui->baseNameLabel->setText(ndkInfo.name);
+            m_ui->ndkPathLabel->setText(ndkInfo.path);
+            m_ui->versionLabel->setText(ndkInfo.version);
+            m_ui->hostLabel->setText(ndkInfo.host);
+            m_ui->targetLabel->setText(ndkInfo.target);
+            break;
+        }
+    }
 
     m_ui->removeNdkButton->setEnabled(!config->isAutoDetected());
 }
@@ -151,7 +128,7 @@ void BlackBerryNDKSettingsWidget::updateNdkList()
         QTreeWidgetItem *parent = config->isAutoDetected() ? m_autoDetectedNdks : m_manualNdks;
         QTreeWidgetItem *item = new QTreeWidgetItem(parent);
         item->setText(0, config->displayName());
-        item->setText(1, config->ndkPath()); // TODO: should be target name for NDKs >= v10.2
+        item->setText(1, config->ndkEnvFile().toString());
     }
 
     if (m_autoDetectedNdks->child(0)) {
@@ -160,22 +137,17 @@ void BlackBerryNDKSettingsWidget::updateNdkList()
     }
 }
 
-void BlackBerryNDKSettingsWidget::clearInfoTable()
+void BlackBerryNDKSettingsWidget::addNdkTarget()
 {
-    m_infoModel->clear();
-}
-
-void BlackBerryNDKSettingsWidget::addNdk()
-{
-    QString selectedPath = QFileDialog::getExistingDirectory(0, tr("Select the NDK path"),
-                                                             QString(),
-                                                             QFileDialog::ShowDirsOnly);
-    if (selectedPath.isEmpty())
+    QString selectedPath = QFileDialog::getOpenFileName(0, tr("Select the NDK Environment file"),
+                                                        QString(), tr("BlackBerry Environment File (*.sh *.bat)"));
+    if (selectedPath.isEmpty() || !QFileInfo(selectedPath).exists())
         return;
 
-    BlackBerryConfiguration *config = m_bbConfigManager->configurationFromNdkPath(selectedPath);
+    BlackBerryConfiguration *config = m_bbConfigManager->configurationFromEnvFile(Utils::FileName::fromString(selectedPath));
+
     if (!config) {
-        config = new BlackBerryConfiguration(selectedPath, false);
+        config = new BlackBerryConfiguration(Utils::FileName::fromString(selectedPath), false);
         if (!m_bbConfigManager->addConfiguration(config)) {
             delete config;
             return;
@@ -188,17 +160,18 @@ void BlackBerryNDKSettingsWidget::addNdk()
     }
 }
 
-void BlackBerryNDKSettingsWidget::removeNdk()
+void BlackBerryNDKSettingsWidget::removeNdkTarget()
 {
-    QString ndkPath = m_ui->ndksTreeWidget->currentItem()->text(1);
+    QString ndk = m_ui->ndksTreeWidget->currentItem()->text(0);
+    QString envFilePath = m_ui->ndksTreeWidget->currentItem()->text(1);
     QMessageBox::StandardButton button =
             QMessageBox::question(Core::ICore::mainWindow(),
                                   tr("Clean BlackBerry 10 Configuration"),
-                                  tr("Are you sure you want to remove:\n %1?").arg(ndkPath),
+                                  tr("Are you sure you want to remove:\n %1?").arg(ndk),
                                   QMessageBox::Yes | QMessageBox::No);
 
     if (button == QMessageBox::Yes) {
-        BlackBerryConfiguration *config = m_bbConfigManager->configurationFromNdkPath(ndkPath);
+        BlackBerryConfiguration *config = m_bbConfigManager->configurationFromEnvFile(Utils::FileName::fromString(envFilePath));
         if (config)
             m_bbConfigManager->removeConfiguration(config);
             m_manualNdks->removeChild(m_ui->ndksTreeWidget->currentItem());
@@ -206,20 +179,11 @@ void BlackBerryNDKSettingsWidget::removeNdk()
 
 }
 
-void BlackBerryNDKSettingsWidget::initInfoTable()
-{
-    m_infoModel = new QStandardItemModel(this);
-
-    m_ui->ndkInfosTableView->setModel(m_infoModel);
-    m_ui->ndkInfosTableView->verticalHeader()->hide();
-    m_ui->ndkInfosTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
-}
-
 void BlackBerryNDKSettingsWidget::initNdkList()
 {
     m_ui->ndksTreeWidget->header()->setResizeMode(QHeaderView::Stretch);
     m_ui->ndksTreeWidget->header()->setStretchLastSection(false);
-    m_ui->ndksTreeWidget->setHeaderItem(new QTreeWidgetItem(QStringList() << tr("NDK") << tr("Path")));
+    m_ui->ndksTreeWidget->setHeaderItem(new QTreeWidgetItem(QStringList() << tr("NDK") << tr("NDK Environment File")));
     m_ui->ndksTreeWidget->setTextElideMode(Qt::ElideNone);
     m_ui->ndksTreeWidget->setColumnCount(2);
     m_autoDetectedNdks = new QTreeWidgetItem(m_ui->ndksTreeWidget);
diff --git a/src/plugins/qnx/blackberryndksettingswidget.h b/src/plugins/qnx/blackberryndksettingswidget.h
index a841edec140..dc05704a6c4 100644
--- a/src/plugins/qnx/blackberryndksettingswidget.h
+++ b/src/plugins/qnx/blackberryndksettingswidget.h
@@ -62,17 +62,14 @@ public slots:
     void launchBlackBerrySetupWizard() const;
     void updateInfoTable(QTreeWidgetItem* currentNdk);
     void updateNdkList();
-    void clearInfoTable();
-    void addNdk();
-    void removeNdk();
+    void addNdkTarget();
+    void removeNdkTarget();
 
 private:
-    void initInfoTable();
     void initNdkList();
 
     Ui_BlackBerryNDKSettingsWidget *m_ui;
     BlackBerryConfigurationManager *m_bbConfigManager;
-    QStandardItemModel *m_infoModel;
     QTreeWidgetItem *m_autoDetectedNdks;
     QTreeWidgetItem *m_manualNdks;
 };
diff --git a/src/plugins/qnx/blackberryndksettingswidget.ui b/src/plugins/qnx/blackberryndksettingswidget.ui
index 7742136a9ad..85ce8e60436 100644
--- a/src/plugins/qnx/blackberryndksettingswidget.ui
+++ b/src/plugins/qnx/blackberryndksettingswidget.ui
@@ -147,9 +147,6 @@
    </item>
    <item>
     <layout class="QGridLayout" name="gridLayout">
-     <item row="2" column="0">
-      <widget class="QTableView" name="ndkInfosTableView"/>
-     </item>
      <item row="0" column="0">
       <layout class="QHBoxLayout" name="horizontalLayout_2">
        <item>
@@ -166,14 +163,14 @@
          <item>
           <widget class="QPushButton" name="addNdkButton">
            <property name="text">
-            <string>Add NDK</string>
+            <string>Add Target</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QPushButton" name="removeNdkButton">
            <property name="text">
-            <string>Remove NDK</string>
+            <string>Remove Target</string>
            </property>
           </widget>
          </item>
@@ -196,6 +193,170 @@
      </item>
     </layout>
    </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>BlackBerry NDK Information</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_7">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_7">
+        <item>
+         <widget class="QLabel" name="label">
+          <property name="text">
+           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;NDK Base Name:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="baseNameLabel">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_8">
+        <item>
+         <widget class="QLabel" name="label_2">
+          <property name="text">
+           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;NDK Path:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="ndkPathLabel">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_3">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_9">
+        <item>
+         <widget class="QLabel" name="label_3">
+          <property name="text">
+           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Version:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="versionLabel">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_4">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_10">
+        <item>
+         <widget class="QLabel" name="label_4">
+          <property name="text">
+           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Host:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="hostLabel">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_5">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_11">
+        <item>
+         <widget class="QLabel" name="label_5">
+          <property name="text">
+           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Target:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="targetLabel">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_6">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
   </layout>
  </widget>
  <resources/>
diff --git a/src/plugins/qnx/blackberryqtversion.cpp b/src/plugins/qnx/blackberryqtversion.cpp
index 12bd3638791..0eeeef4f7f1 100644
--- a/src/plugins/qnx/blackberryqtversion.cpp
+++ b/src/plugins/qnx/blackberryqtversion.cpp
@@ -39,11 +39,16 @@
 #include <utils/hostosinfo.h>
 #include <utils/qtcassert.h>
 
+#include <QFileInfo>
 #include <QTextStream>
 
 using namespace Qnx;
 using namespace Qnx::Internal;
 
+namespace {
+const QLatin1String NndkEnvFile("ndkEnvFile");
+}
+
 BlackBerryQtVersion::BlackBerryQtVersion()
     : QnxAbstractQtVersion()
 {
@@ -52,10 +57,17 @@ BlackBerryQtVersion::BlackBerryQtVersion()
 BlackBerryQtVersion::BlackBerryQtVersion(QnxArchitecture arch, const Utils::FileName &path, bool isAutoDetected, const QString &autoDetectionSource, const QString &sdkPath)
     : QnxAbstractQtVersion(arch, path, isAutoDetected, autoDetectionSource)
 {
-    if (QnxUtils::isValidNdkPath(sdkPath))
-        setSdkPath(sdkPath);
-    else
+    if (!sdkPath.isEmpty()) {
+        if (QFileInfo(sdkPath).isDir()) {
+            setSdkPath(sdkPath);
+        } else {
+            m_ndkEnvFile = sdkPath;
+            setSdkPath(QFileInfo(sdkPath).absolutePath());
+        }
+
+    } else {
         setDefaultSdkPath();
+    }
 }
 
 BlackBerryQtVersion::~BlackBerryQtVersion()
@@ -78,13 +90,27 @@ QString BlackBerryQtVersion::description() const
     return tr("BlackBerry %1", "Qt Version is meant for BlackBerry").arg(archString());
 }
 
+QVariantMap BlackBerryQtVersion::toMap() const
+{
+    QVariantMap result = QnxAbstractQtVersion::toMap();
+    result.insert(NndkEnvFile, m_ndkEnvFile);
+    return result;
+}
+
+void BlackBerryQtVersion::fromMap(const QVariantMap &map)
+{
+    QnxAbstractQtVersion::fromMap(map);
+    m_ndkEnvFile = map.value(NndkEnvFile).toString();
+}
+
 QMultiMap<QString, QString> BlackBerryQtVersion::environment() const
 {
     QTC_CHECK(!sdkPath().isEmpty());
     if (sdkPath().isEmpty())
         return QMultiMap<QString, QString>();
 
-    return QnxUtils::parseEnvironmentFile(QnxUtils::envFilePath(sdkPath()));
+    QString envFile = m_ndkEnvFile.isEmpty() ? QnxUtils::envFilePath(sdkPath()) : m_ndkEnvFile;
+    return QnxUtils::parseEnvironmentFile(envFile);
 }
 
 void BlackBerryQtVersion::setDefaultSdkPath()
diff --git a/src/plugins/qnx/blackberryqtversion.h b/src/plugins/qnx/blackberryqtversion.h
index 59160e1c357..fd2bf0bdc2c 100644
--- a/src/plugins/qnx/blackberryqtversion.h
+++ b/src/plugins/qnx/blackberryqtversion.h
@@ -54,6 +54,9 @@ public:
 
     QString description() const;
 
+    QVariantMap toMap() const;
+    void fromMap(const QVariantMap &map);
+
     Core::FeatureSet availableFeatures() const;
     QString platformName() const;
     QString platformDisplayName() const;
@@ -63,6 +66,8 @@ public:
 private:
     QMultiMap<QString, QString> environment() const;
     void setDefaultSdkPath();
+
+    QString m_ndkEnvFile;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp
index ad4ee89361e..dadacceb0c1 100644
--- a/src/plugins/qnx/qnxutils.cpp
+++ b/src/plugins/qnx/qnxutils.cpp
@@ -187,7 +187,7 @@ bool QnxUtils::isValidNdkPath(const QString &ndkPath)
     return (QFileInfo(envFilePath(ndkPath)).exists());
 }
 
-QString QnxUtils::envFilePath(const QString &ndkPath)
+QString QnxUtils::envFilePath(const QString &ndkPath, const QString &targetVersion)
 {
     QString envFile;
     if (Utils::HostOsInfo::isWindowsHost())
@@ -196,7 +196,7 @@ QString QnxUtils::envFilePath(const QString &ndkPath)
         envFile = ndkPath + QLatin1String("/bbndk-env.sh");
 
     if (!QFileInfo(envFile).exists()) {
-        QString version = ndkVersion(ndkPath);
+        QString version = targetVersion.isEmpty() ? defaultTargetVersion(ndkPath) : targetVersion;
         version = version.replace(QLatin1Char('.'), QLatin1Char('_'));
         if (Utils::HostOsInfo::isWindowsHost())
             envFile = ndkPath + QLatin1String("/bbndk-env_") + version + QLatin1String(".bat");
@@ -262,7 +262,7 @@ QString QnxUtils::qConfigPath()
     }
 }
 
-QString QnxUtils::ndkVersion(const QString &ndkPath)
+QString QnxUtils::defaultTargetVersion(const QString &ndkPath)
 {
     foreach (const NdkInstallInformation &ndkInfo, installedNdks()) {
         if (!ndkInfo.path.compare(ndkPath, Utils::HostOsInfo::fileNameCaseSensitivity()))
diff --git a/src/plugins/qnx/qnxutils.h b/src/plugins/qnx/qnxutils.h
index 6f094cd2366..7c68825359a 100644
--- a/src/plugins/qnx/qnxutils.h
+++ b/src/plugins/qnx/qnxutils.h
@@ -64,12 +64,12 @@ public:
     static QStringList searchPaths(QnxAbstractQtVersion *qtVersion);
     static QMultiMap<QString, QString> parseEnvironmentFile(const QString &fileName);
     static bool isValidNdkPath(const QString & ndkPath);
-    static QString envFilePath(const QString & ndkPath);
+    static QString envFilePath(const QString & ndkPath, const QString& targetVersion = QString());
     static void prependQnxMapToEnvironment(const QMultiMap<QString, QString> &qnxMap, Utils::Environment &env);
     static Utils::FileName executableWithExtension(const Utils::FileName &fileName);
     static QString dataDirPath();
     static QString qConfigPath();
-    static QString ndkVersion(const QString& ndkPath);
+    static QString defaultTargetVersion(const QString& ndkPath);
     static QList<NdkInstallInformation> installedNdks();
 };
 
-- 
GitLab