From 8d5d0b0c9c624d7a7849a0905be3bde2df368bc6 Mon Sep 17 00:00:00 2001 From: David Kaspar Date: Thu, 13 Feb 2014 09:47:06 +0100 Subject: [PATCH] Qnx: BlackBerry Setup options page Setup options page checks for general setup of API Levels, Signing Keys and Devices. It is meant to become a central point for BlackBerry settings. Adding BlackBerryConfigurationManager::settingsChanged signal to notify about any change to BBConfig settings. Fixing BlackBerrySigningUtils to correctly ask for password and reopen the certificate in case an invalid password is entered and a generic ResultCode::Error happens. Fixing header define for blackberryinstallwizard.h Fixing URL for BlackBerry Legacy Keys. Change-Id: I1c4592c03ab07678ef829b85ce7b13457b9304a9 Reviewed-by: David Kaspar Reviewed-by: Nicolas Arnaud-Cormos --- src/plugins/qnx/blackberryconfiguration.cpp | 5 + .../qnx/blackberryconfigurationmanager.cpp | 12 + .../qnx/blackberryconfigurationmanager.h | 4 +- src/plugins/qnx/blackberryinstallwizard.h | 6 +- src/plugins/qnx/blackberrykeyswidget.cpp | 26 +- .../qnx/blackberryndksettingswidget.cpp | 17 +- src/plugins/qnx/blackberryndksettingswidget.h | 4 + src/plugins/qnx/blackberrysetuppage.cpp | 67 ++++ src/plugins/qnx/blackberrysetuppage.h | 59 ++++ src/plugins/qnx/blackberrysetupwidget.cpp | 332 ++++++++++++++++++ src/plugins/qnx/blackberrysetupwidget.h | 143 ++++++++ src/plugins/qnx/blackberrysigningutils.cpp | 53 ++- src/plugins/qnx/blackberrysigningutils.h | 9 + src/plugins/qnx/images/error.png | Bin 0 -> 627 bytes src/plugins/qnx/images/info.png | Bin 0 -> 630 bytes src/plugins/qnx/images/ok.png | Bin 0 -> 220 bytes src/plugins/qnx/images/warning.png | Bin 0 -> 743 bytes src/plugins/qnx/qnx.pro | 8 +- src/plugins/qnx/qnx.qbs | 4 + src/plugins/qnx/qnx.qrc | 4 + src/plugins/qnx/qnxconstants.h | 11 + src/plugins/qnx/qnxplugin.cpp | 2 + 22 files changed, 733 insertions(+), 33 deletions(-) create mode 100644 src/plugins/qnx/blackberrysetuppage.cpp create mode 100644 src/plugins/qnx/blackberrysetuppage.h create mode 100644 src/plugins/qnx/blackberrysetupwidget.cpp create mode 100644 src/plugins/qnx/blackberrysetupwidget.h create mode 100644 src/plugins/qnx/images/error.png create mode 100644 src/plugins/qnx/images/info.png create mode 100644 src/plugins/qnx/images/ok.png create mode 100644 src/plugins/qnx/images/warning.png diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp index 58ab0a9d70e..a8840b9d755 100644 --- a/src/plugins/qnx/blackberryconfiguration.cpp +++ b/src/plugins/qnx/blackberryconfiguration.cpp @@ -30,6 +30,7 @@ ****************************************************************************/ #include "blackberryconfiguration.h" +#include "blackberryconfigurationmanager.h" #include "blackberryqtversion.h" #include "qnxtoolchain.h" @@ -435,6 +436,8 @@ bool BlackBerryConfiguration::activate() if (qt5X86Version) createKit(qt5X86Version, x86ToolChain, x86DebuggerItemId); + BlackBerryConfigurationManager::instance().emitSettingsChanged(); + return true; } @@ -456,6 +459,8 @@ void BlackBerryConfiguration::deactivate() KitManager::deregisterKit(kit); } } + + BlackBerryConfigurationManager::instance().emitSettingsChanged(); } #ifdef WITH_TESTS diff --git a/src/plugins/qnx/blackberryconfigurationmanager.cpp b/src/plugins/qnx/blackberryconfigurationmanager.cpp index 14407645e61..52707592718 100644 --- a/src/plugins/qnx/blackberryconfigurationmanager.cpp +++ b/src/plugins/qnx/blackberryconfigurationmanager.cpp @@ -150,6 +150,8 @@ void BlackBerryConfigurationManager::restoreConfigurations() if (!useNewestConfiguration && (config->ndkEnvFile().toString() == ndkEnvFile)) setDefaultConfiguration(config); } + + emit settingsChanged(); } // Backward compatibility: Read existing entries in the ManualNDKsGroup @@ -205,6 +207,7 @@ void BlackBerryConfigurationManager::setDefaultConfiguration(BlackBerryConfigura } m_defaultConfiguration = config; + emit settingsChanged(); } bool BlackBerryConfigurationManager::newestConfigurationEnabled() const @@ -212,6 +215,11 @@ bool BlackBerryConfigurationManager::newestConfigurationEnabled() const return !m_defaultConfiguration; } +void BlackBerryConfigurationManager::emitSettingsChanged() +{ + emit settingsChanged(); +} + void BlackBerryConfigurationManager::setKitsAutoDetectionSource() { foreach (Kit *kit, KitManager::kits()) { @@ -267,6 +275,7 @@ bool BlackBerryConfigurationManager::addConfiguration(BlackBerryConfiguration *c if (config->isValid()) { insertByVersion(config); + emit settingsChanged(); return true; } @@ -287,6 +296,8 @@ void BlackBerryConfigurationManager::removeConfiguration(BlackBerryConfiguration setDefaultConfiguration(0); delete config; + + emit settingsChanged(); } QList BlackBerryConfigurationManager::configurations() const @@ -369,6 +380,7 @@ void BlackBerryConfigurationManager::loadSettings() m_configs.first()->activate(); emit settingsLoaded(); + emit settingsChanged(); } void BlackBerryConfigurationManager::saveSettings() diff --git a/src/plugins/qnx/blackberryconfigurationmanager.h b/src/plugins/qnx/blackberryconfigurationmanager.h index c0e9cd8d474..88e9f8fdf8a 100644 --- a/src/plugins/qnx/blackberryconfigurationmanager.h +++ b/src/plugins/qnx/blackberryconfigurationmanager.h @@ -64,7 +64,6 @@ public: QString barsignerDbPath() const; QString defaultKeystorePath() const; QString defaultDebugTokenPath() const; - void clearConfigurationSettings(BlackBerryConfiguration *config); // returns the environment for the default API level QList defaultConfigurationEnv() const; @@ -74,6 +73,8 @@ public: bool newestConfigurationEnabled() const; + void emitSettingsChanged(); + public slots: void loadSettings(); void saveSettings(); @@ -81,6 +82,7 @@ public slots: signals: void settingsLoaded(); + void settingsChanged(); private: BlackBerryConfigurationManager(QObject *parent = 0); diff --git a/src/plugins/qnx/blackberryinstallwizard.h b/src/plugins/qnx/blackberryinstallwizard.h index cac543928fb..5d1d76d7ecc 100644 --- a/src/plugins/qnx/blackberryinstallwizard.h +++ b/src/plugins/qnx/blackberryinstallwizard.h @@ -29,8 +29,8 @@ ** ****************************************************************************/ -#ifndef QNX_INTERNAL_BLACKBERRYDEVICECONFIGURATIONWIZARD_H -#define QNX_INTERNAL_BLACKBERRYDEVICECONFIGURATIONWIZARD_H +#ifndef QNX_INTERNAL_BLACKBERRYINSTALLWIZARD_H +#define QNX_INTERNAL_BLACKBERRYINSTALLWIZARD_H #include @@ -105,4 +105,4 @@ private: } // namespace Internal } // namespace Qnx -#endif // QNX_INTERNAL_BLACKBERRYDEVICECONFIGURATIONWIZARD_H +#endif // QNX_INTERNAL_BLACKBERRYINSTALLWIZARD_H diff --git a/src/plugins/qnx/blackberrykeyswidget.cpp b/src/plugins/qnx/blackberrykeyswidget.cpp index fb38b8c011d..43f286985ed 100644 --- a/src/plugins/qnx/blackberrykeyswidget.cpp +++ b/src/plugins/qnx/blackberrykeyswidget.cpp @@ -135,19 +135,8 @@ void BlackBerryKeysWidget::certificateLoaded(int status) void BlackBerryKeysWidget::createCertificate() { - BlackBerryCreateCertificateDialog dialog(this); - - const int result = dialog.exec(); - - if (result == QDialog::Rejected) - return; - - BlackBerryCertificate *certificate = dialog.certificate(); - - if (certificate) { - m_utils.setDefaultCertificate(certificate); + if (m_utils.createCertificate()) updateCertificateSection(); - } } void BlackBerryKeysWidget::clearCertificate() @@ -194,17 +183,16 @@ void BlackBerryKeysWidget::updateCertificateSection() void BlackBerryKeysWidget::updateKeysSection() { if (m_utils.hasLegacyKeys()) { - m_ui->keyStatus->setText(tr("It appears you are using legacy key files. " - "Please refer to the " - "" - "BlackBerry website to find out how to update your keys.")); + m_ui->keyStatus->setText(tr("It appears you are using legacy key files. Please refer to the " + "BlackBerry website to find out how to update your keys.") + .arg(QLatin1String(Qnx::Constants::QNX_LEGACY_KEYS_URL))); } else if (m_utils.hasRegisteredKeys()) { m_ui->keyStatus->setText(tr("Your keys are ready to be used")); } else { m_ui->keyStatus->setText(tr("No keys found. Please refer to the " - "BlackBerry website " - "to find out how to request your keys.")); + "BlackBerry website " + "to find out how to request your keys.") + .arg(QLatin1String(Qnx::Constants::QNX_REGISTER_KEYS_URL))); } } diff --git a/src/plugins/qnx/blackberryndksettingswidget.cpp b/src/plugins/qnx/blackberryndksettingswidget.cpp index 3b0a3157534..d641fc173e3 100644 --- a/src/plugins/qnx/blackberryndksettingswidget.cpp +++ b/src/plugins/qnx/blackberryndksettingswidget.cpp @@ -91,8 +91,15 @@ BlackBerryNDKSettingsWidget::BlackBerryNDKSettingsWidget(QWidget *parent) : connect(m_ui->ndksTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateInfoTable(QTreeWidgetItem*))); connect(this, SIGNAL(targetsUpdated()), this, SLOT(populateDefaultConfigurationCombo())); - updateNdkList(); - populateDefaultConfigurationCombo(); + // BlackBerryConfigurationManager.settingsChanged signal may be emitted multiple times + // during the same event handling. This would result in multiple updatePage() calls even through + // just one is needed. + // QTimer allows to merge those multiple signal emits into a single updatePage() call. + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(updatePage())); + + updatePage(); + connect(&m_bbConfigManager, SIGNAL(settingsChanged()), &m_timer, SLOT(start())); } void BlackBerryNDKSettingsWidget::setWizardMessageVisible(bool visible) @@ -393,6 +400,12 @@ void BlackBerryNDKSettingsWidget::launchBlackBerryInstallerWizard(BlackBerryInst wizard.exec(); } +void BlackBerryNDKSettingsWidget::updatePage() +{ + updateNdkList(); + populateDefaultConfigurationCombo(); +} + } // namespace Internal } // namespace Qnx diff --git a/src/plugins/qnx/blackberryndksettingswidget.h b/src/plugins/qnx/blackberryndksettingswidget.h index 8be29019d54..0fd527dc1e5 100644 --- a/src/plugins/qnx/blackberryndksettingswidget.h +++ b/src/plugins/qnx/blackberryndksettingswidget.h @@ -35,6 +35,7 @@ #include "blackberryinstallwizard.h" #include +#include QT_BEGIN_NAMESPACE class QStandardItemModel; @@ -80,6 +81,7 @@ public slots: void handleUninstallationFinished(); void updateUi(QTreeWidgetItem* item, BlackBerryConfiguration* config); void populateDefaultConfigurationCombo(); + void updatePage(); private: void launchBlackBerryInstallerWizard(BlackBerryInstallerDataHandler::Mode mode, @@ -93,6 +95,8 @@ private: QList m_activatedTargets; QList m_deactivatedTargets; + + QTimer m_timer; }; } // namespace Internal diff --git a/src/plugins/qnx/blackberrysetuppage.cpp b/src/plugins/qnx/blackberrysetuppage.cpp new file mode 100644 index 00000000000..70cfd7b1667 --- /dev/null +++ b/src/plugins/qnx/blackberrysetuppage.cpp @@ -0,0 +1,67 @@ +/************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** +** Contact: BlackBerry (qt@blackberry.com) +** +** 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 "blackberrysetuppage.h" +#include "blackberrysetupwidget.h" +#include "qnxconstants.h" + +#include + +namespace Qnx { +namespace Internal { + +BlackBerrySetupPage::BlackBerrySetupPage(QObject *parent) + : Core::IOptionsPage(parent) +{ + setId(Core::Id(Constants::QNX_BB_SETUP_ID)); + setDisplayName(tr("Setup")); + setCategory(Constants::QNX_BB_CATEGORY); + setDisplayCategory(QCoreApplication::translate("BlackBerry", Constants::QNX_BB_CATEGORY_TR)); + setCategoryIcon(QLatin1String(Constants::QNX_BB_CATEGORY_ICON)); +} + +QWidget *BlackBerrySetupPage::widget() +{ + if (!m_widget) + m_widget = new BlackBerrySetupWidget; + return m_widget; +} + +void BlackBerrySetupPage::apply() +{ +} + +void BlackBerrySetupPage::finish() +{ + delete m_widget; +} + +} // namespace Internal +} // namespace Qnx diff --git a/src/plugins/qnx/blackberrysetuppage.h b/src/plugins/qnx/blackberrysetuppage.h new file mode 100644 index 00000000000..8c3d23c901d --- /dev/null +++ b/src/plugins/qnx/blackberrysetuppage.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** +** Contact: BlackBerry (qt@blackberry.com) +** +** 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. +** +****************************************************************************/ + +#ifndef BLACKBERRYSETUPPAGE_H +#define BLACKBERRYSETUPPAGE_H + +#include + +#include + +namespace Qnx { +namespace Internal { + +class BlackBerrySetupWidget; + +class BlackBerrySetupPage : public Core::IOptionsPage +{ + Q_OBJECT +public: + explicit BlackBerrySetupPage(QObject *parent = 0); + QWidget *widget(); + void apply(); + void finish(); + +private: + QPointer m_widget; +}; + +} // namespace Internal +} // namespace Qnx + +#endif // BLACKBERRYSETUPPAGE_H diff --git a/src/plugins/qnx/blackberrysetupwidget.cpp b/src/plugins/qnx/blackberrysetupwidget.cpp new file mode 100644 index 00000000000..8938364379d --- /dev/null +++ b/src/plugins/qnx/blackberrysetupwidget.cpp @@ -0,0 +1,332 @@ +/************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** +** Contact: BlackBerry (qt@blackberry.com) +** +** 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 "blackberrysetupwidget.h" + +#include "blackberryconfigurationmanager.h" +#include "blackberryconfiguration.h" +#include "blackberrysigningutils.h" +#include "blackberrydeviceconfigurationwizard.h" +#include "blackberryinstallwizard.h" +#include "blackberrycertificate.h" +#include "qnxconstants.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Qnx { +namespace Internal { + +SetupItem::SetupItem(const QString &desc, QWidget *parent) +: QFrame(parent) +{ + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(validate())); + + setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + QVBoxLayout *frameLayout = new QVBoxLayout(this); + + QHBoxLayout *childLayout = new QHBoxLayout; + frameLayout->addLayout(childLayout); + + m_icon = new QLabel; + childLayout->addWidget(m_icon); + + m_label = new QLabel; + m_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + childLayout->addWidget(m_label); + + m_button = new QPushButton; + childLayout->addWidget(m_button); + QObject::connect(m_button, SIGNAL(clicked()), this, SLOT(onFixPressed())); + + if (!desc.isEmpty()) { + m_desc = new QLabel(desc); + m_desc->setWordWrap(true); + QFont font = m_desc->font(); + font.setItalic(true); + m_desc->setFont(font); + frameLayout->addWidget(m_desc); + } +} + +void SetupItem::set(Status status, const QString &message, const QString &fixText) +{ + const char *icon; + switch (status) { + case Ok: + icon = Qnx::Constants::QNX_OK_ICON; + break; + case Info: + icon = Qnx::Constants::QNX_INFO_ICON; + break; + case Warning: + icon = Qnx::Constants::QNX_WARNING_ICON; + break; + case Error: + icon = Qnx::Constants::QNX_ERROR_ICON; + break; + } + m_icon->setPixmap(QPixmap(QLatin1String(icon))); + m_label->setText(message); + m_button->setVisible(!fixText.isEmpty()); + m_button->setText(fixText); +} + +void SetupItem::onFixPressed() +{ + fix(); + validate(); +} + +void SetupItem::validateLater() +{ + // BlackBerryConfigurationManager.settingsChanged and DeviceManager.updated signals + // may be emitted multiple times during the same event handling. This would result in multiple + // validation() calls even through just one is needed. + // QTimer allows to merge those multiple signal emits into a single validate() call. + m_timer.start(); +} + +APILevelSetupItem::APILevelSetupItem(QWidget *parent) +: SetupItem(tr("API Level defines kits, Qt versions, compilers, debuggers needed" + " for building BlackBerry applications."), parent) +{ + validate(); + connect(&BlackBerryConfigurationManager::instance(), SIGNAL(settingsChanged()), + this, SLOT(validateLater())); +} + +void APILevelSetupItem::validate() +{ + FoundTypes found = resolvedFoundType(); + if (!found.testFlag(Any)) + set(Error, tr("No API Level is installed."), tr("Install")); + else if (!found.testFlag(Valid)) + set(Error, tr("No valid API Level is installed."), tr("Install")); + else if (!found.testFlag(Active)) + set(Error, tr("Valid API Level is not activated."), tr("Activate")); + else if (!found.testFlag(V_10_2)) + set(Warning, tr("Valid API Level 10.2 or newer is not installed."), tr("Install")); + else if (!found.testFlag(V_10_2_AS_DEFAULT)) + set(Warning, tr("Valid API Level 10.2 or newer is not set as default."), tr("Set")); + else + set(Ok, tr("API Level is configured.")); + // TODO: should we check something more e.g. BB10 kits are valid? +} + +void APILevelSetupItem::fix() +{ + FoundTypes found = resolvedFoundType(); + if (!found.testFlag(Any) || !found.testFlag(Valid)) { + installAPILevel(); + } else if (!found.testFlag(Active)) { + foreach (BlackBerryConfiguration *config, + BlackBerryConfigurationManager::instance().configurations()) { + if (config->isValid() && !config->isActive()) { + config->activate(); + break; + } + } + } else if (!found.testFlag(V_10_2)) { + // TODO: install filter for 10.2 only + installAPILevel(); + } else if (!found.testFlag(V_10_2_AS_DEFAULT)) { + BlackBerryConfigurationManager::instance().setDefaultConfiguration(0); + } +} + +APILevelSetupItem::FoundTypes APILevelSetupItem::resolvedFoundType() +{ + FoundTypes found; + + // TODO: for now, all Trunk versions are understood as 10.2 compliant + BlackBerryVersionNumber version_10_2(QLatin1String("10.2.0.0")); + foreach (BlackBerryConfiguration *config, + BlackBerryConfigurationManager::instance().configurations()) { + found |= Any; + if (config->isValid()) { + found |= Valid; + if (config->isActive()) + found |= Active; + if (config->version() > version_10_2) + found |= V_10_2; + } + } + + BlackBerryConfiguration *config = BlackBerryConfigurationManager::instance().defaultConfiguration(); + if (config && config->version() > version_10_2) + found |= V_10_2_AS_DEFAULT; + + return found; +} + +void APILevelSetupItem::installAPILevel() +{ + BlackBerryInstallWizard wizard( + BlackBerryInstallerDataHandler::InstallMode, + BlackBerryInstallerDataHandler::ApiLevel, QString(), this); + connect(&wizard, SIGNAL(processFinished()), this, SLOT(handleInstallationFinished())); + wizard.exec(); +} + +void APILevelSetupItem::handleInstallationFinished() +{ + // manually-added API Levels are automatically registered by BlackBerryInstallWizard + // auto-detected API Levels needs to reloaded explicitly + BlackBerryConfigurationManager::instance().loadAutoDetectedConfigurations(); + validate(); +} + +SigningKeysSetupItem::SigningKeysSetupItem(QWidget *parent) +: SetupItem(tr("Signing keys are needed for signing BlackBerry applications" + " and managing debug tokens."), parent) +{ + validate(); + connect(&BlackBerrySigningUtils::instance(), SIGNAL(defaultCertificateLoaded(int)), + this, SLOT(validate())); +} + +void SigningKeysSetupItem::validate() +{ + BlackBerrySigningUtils &utils = BlackBerrySigningUtils::instance(); + if (utils.hasLegacyKeys()) + set(Error, tr("Found legacy BlackBerry signing keys."), tr("Update")); + else if (!utils.hasRegisteredKeys()) + set(Error, tr("Cannot find BlackBerry signing keys."), tr("Request")); + else if (!QFileInfo(BlackBerryConfigurationManager::instance().defaultKeystorePath()).exists()) + set(Error, tr("Cannot find developer certificate."), tr("Create")); + else if (utils.defaultCertificateOpeningStatus() != BlackBerrySigningUtils::Opened) + set(Info, tr("Developer certificate is not opened."), tr("Open")); + else + set(Ok, tr("Signing keys are ready to use.")); +} + +void SigningKeysSetupItem::fix() +{ + BlackBerrySigningUtils &utils = BlackBerrySigningUtils::instance(); + if (utils.hasLegacyKeys()) { + QDesktopServices::openUrl(QUrl(QLatin1String(Qnx::Constants::QNX_LEGACY_KEYS_URL))); + } else if (!utils.hasRegisteredKeys()) { + QDesktopServices::openUrl(QUrl(QLatin1String(Qnx::Constants::QNX_REGISTER_KEYS_URL))); + } else if (!QFileInfo(BlackBerryConfigurationManager::instance().defaultKeystorePath()).exists()) { + set(Info, tr("Opening certificate...")); + utils.createCertificate(); + } else if (utils.defaultCertificateOpeningStatus() != BlackBerrySigningUtils::Opened) { + connect(&utils, SIGNAL(defaultCertificateLoaded(int)), this, SLOT(defaultCertificateLoaded(int))); + utils.openDefaultCertificate(this); + } +} + +void SigningKeysSetupItem::defaultCertificateLoaded(int status) +{ + BlackBerrySigningUtils &utils = BlackBerrySigningUtils::instance(); + disconnect(&utils, SIGNAL(defaultCertificateLoaded(int)), this, SLOT(defaultCertificateLoaded(int))); + switch (status) { + case BlackBerryCertificate::Success: + // handled by the connect in ctor already + break; + case BlackBerryCertificate::WrongPassword: + QMessageBox::critical(this, tr("Qt Creator"), tr("Invalid certificate password.")); + break; + case BlackBerryCertificate::Busy: + case BlackBerryCertificate::InvalidOutputFormat: + case BlackBerryCertificate::Error: + QMessageBox::critical(this, tr("Qt Creator"), tr("Error loading certificate.")); + break; + } +} + +DeviceSetupItem::DeviceSetupItem(QWidget *parent) +: SetupItem(tr("BlackBerry 10 device or simulator is needed for running BlackBerry applications."), + parent) +{ + validate(); + connect(ProjectExplorer::DeviceManager::instance(), SIGNAL(updated()), + this, SLOT(validateLater())); +} + +void DeviceSetupItem::validate() +{ + bool found = false; + ProjectExplorer::DeviceManager *manager = ProjectExplorer::DeviceManager::instance(); + for (int i = 0; i < manager->deviceCount(); i ++) { + ProjectExplorer::IDevice::ConstPtr device = manager->deviceAt(i); + if (device->type() == Constants::QNX_BB_OS_TYPE) { + found = true; + break; + } + } + if (!found) + set(Error, tr("No BlackBerry 10 device or simulator is registered."), tr("Add")); + else + set(Ok, tr("BlackBerry 10 device or simulator is registered.")); + // TODO: check for existence of an API Level matching a device? +} + +void DeviceSetupItem::fix() +{ + BlackBerryDeviceConfigurationWizard wizard(this); + if (wizard.exec() == QDialog::Accepted) + ProjectExplorer::DeviceManager::instance()->addDevice(wizard.device()); +} + +BlackBerrySetupWidget::BlackBerrySetupWidget(QWidget *parent) + : QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + setLayout(layout); + + layout->addWidget(new APILevelSetupItem); + layout->addWidget(new SigningKeysSetupItem); + layout->addWidget(new DeviceSetupItem); + + layout->addStretch(); + + QLabel *howTo = new QLabel; + howTo->setTextFormat(Qt::RichText); + howTo->setTextInteractionFlags(Qt::TextBrowserInteraction); + howTo->setOpenExternalLinks(true); + howTo->setText(tr("How to Setup Qt Creator for BlackBerry 10 development") + .arg(QLatin1String(Qnx::Constants::QNX_BLACKBERRY_SETUP_URL))); + layout->addWidget(howTo); +} + +} // namespace Internal +} // namespace Qnx diff --git a/src/plugins/qnx/blackberrysetupwidget.h b/src/plugins/qnx/blackberrysetupwidget.h new file mode 100644 index 00000000000..a42b8870cf8 --- /dev/null +++ b/src/plugins/qnx/blackberrysetupwidget.h @@ -0,0 +1,143 @@ +/************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** +** Contact: BlackBerry (qt@blackberry.com) +** +** 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. +** +****************************************************************************/ + +#ifndef BLACKBERRYSETUPWIDGET_H +#define BLACKBERRYSETUPWIDGET_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QPushButton; +QT_END_NAMESPACE + +namespace Qnx { +namespace Internal { + + +class SetupItem : public QFrame { + Q_OBJECT + +public: + enum Status { + Ok, Info, Warning, Error + }; + + SetupItem(const QString &desc = QString(), QWidget *parent = 0); + +protected: + void set(Status status, const QString &message, const QString &fixText = QString()); + Q_SLOT virtual void validate() = 0; + virtual void fix() = 0; + +private slots: + void onFixPressed(); + void validateLater(); + +private: + QLabel *m_icon; + QLabel *m_label; + QPushButton *m_button; + QLabel *m_desc; + QTimer m_timer; +}; + +class APILevelSetupItem : public SetupItem +{ + Q_OBJECT + +public: + APILevelSetupItem(QWidget *parent = 0); + + enum FoundType { + Any = (1 << 0), + Valid = (1 << 1), + Active = (1 << 2), + V_10_2 = (1 << 3), + V_10_2_AS_DEFAULT = (1 << 4) + }; + Q_DECLARE_FLAGS(FoundTypes, FoundType) + +protected: + virtual void validate(); + virtual void fix(); + +private slots: + void handleInstallationFinished(); + +private: + FoundTypes resolvedFoundType(); + void installAPILevel(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(APILevelSetupItem::FoundTypes) + +class SigningKeysSetupItem : public SetupItem +{ + Q_OBJECT + +public: + SigningKeysSetupItem(QWidget *parent = 0); + +protected: + virtual void validate(); + virtual void fix(); + +private slots: + void defaultCertificateLoaded(int status); +}; + +class DeviceSetupItem : public SetupItem +{ + Q_OBJECT + +public: + DeviceSetupItem(QWidget *parent = 0); + +protected: + virtual void validate(); + virtual void fix(); +}; + +class BlackBerrySetupWidget : public QWidget +{ + Q_OBJECT + +public: + explicit BlackBerrySetupWidget(QWidget *parent = 0); +}; + +} // namespace Internal +} // namespeace Qnx + +#endif // BLACKBERRYSETUPWIDGET_H diff --git a/src/plugins/qnx/blackberrysigningutils.cpp b/src/plugins/qnx/blackberrysigningutils.cpp index f230c86b8af..1a987784053 100644 --- a/src/plugins/qnx/blackberrysigningutils.cpp +++ b/src/plugins/qnx/blackberrysigningutils.cpp @@ -33,10 +33,12 @@ #include "blackberrycertificate.h" #include "blackberryconfiguration.h" #include "blackberryconfigurationmanager.h" +#include "blackberrycreatecertificatedialog.h" #include "blackberrydebugtokenreader.h" #include +#include #include #include #include @@ -59,7 +61,8 @@ BlackBerrySigningUtils & BlackBerrySigningUtils::instance() BlackBerrySigningUtils::BlackBerrySigningUtils(QObject *parent) : QObject(parent), - m_defaultCertificate(0) + m_defaultCertificate(0), + m_defaultCertificateStatus(NotOpened) { loadDebugTokens(); } @@ -118,22 +121,37 @@ const BlackBerryCertificate * BlackBerrySigningUtils::defaultCertificate() const return m_defaultCertificate; } +BlackBerrySigningUtils::Status BlackBerrySigningUtils::defaultCertificateOpeningStatus() const +{ + return m_defaultCertificateStatus; +} + void BlackBerrySigningUtils::openDefaultCertificate(QWidget *passwordPromptParent) { - if (m_defaultCertificate) { + switch (m_defaultCertificateStatus) { + case Opening: + return; + case Opened: emit defaultCertificateLoaded(BlackBerryCertificate::Success); return; + default: + m_defaultCertificateStatus = Opening; } bool ok; const QString password = certificatePassword(passwordPromptParent, &ok); // action has been canceled - if (!ok) + if (!ok) { + m_defaultCertificateStatus = NotOpened; return; + } BlackBerryConfigurationManager &configManager = BlackBerryConfigurationManager::instance(); + if (m_defaultCertificate) + m_defaultCertificate->deleteLater(); + m_defaultCertificate = new BlackBerryCertificate(configManager.defaultKeystorePath(), QString(), password, this); @@ -149,6 +167,7 @@ void BlackBerrySigningUtils::setDefaultCertificate(BlackBerryCertificate *certif certificate->setParent(this); m_defaultCertificate = certificate; + m_defaultCertificateStatus = Opened; } void BlackBerrySigningUtils::clearCskPassword() @@ -166,6 +185,7 @@ void BlackBerrySigningUtils::deleteDefaultCertificate() clearCertificatePassword(); m_defaultCertificate->deleteLater(); m_defaultCertificate = 0; + m_defaultCertificateStatus = NotOpened; BlackBerryConfigurationManager &configuration = BlackBerryConfigurationManager::instance(); @@ -192,15 +212,36 @@ void BlackBerrySigningUtils::removeDebugToken(const QString &dt) emit debugTokenListChanged(); } +bool BlackBerrySigningUtils::createCertificate() +{ + BlackBerryCreateCertificateDialog dialog; + + const int result = dialog.exec(); + + if (result == QDialog::Rejected) + return false; + + BlackBerryCertificate *certificate = dialog.certificate(); + + if (certificate) + setDefaultCertificate(certificate); + + return certificate; +} + void BlackBerrySigningUtils::certificateLoaded(int status) { if (status != BlackBerryCertificate::Success) { + m_defaultCertificateStatus = NotOpened; m_defaultCertificate->deleteLater(); m_defaultCertificate = 0; - if (status == BlackBerryCertificate::WrongPassword) - clearCertificatePassword(); - } + // we have clear the password under any error since we are not able to distinquish + // if password is correct or not in case BlackBerryCertificate::Error status happens + clearCertificatePassword(); + } else + m_defaultCertificateStatus = Opened; + emit defaultCertificateLoaded(status); } diff --git a/src/plugins/qnx/blackberrysigningutils.h b/src/plugins/qnx/blackberrysigningutils.h index dad994c097e..cb29e20059a 100644 --- a/src/plugins/qnx/blackberrysigningutils.h +++ b/src/plugins/qnx/blackberrysigningutils.h @@ -50,6 +50,12 @@ class BlackBerrySigningUtils : public QObject Q_OBJECT public: + enum Status { + NotOpened, + Opening, + Opened + }; + static BlackBerrySigningUtils &instance(); bool hasRegisteredKeys(); @@ -60,12 +66,14 @@ public: QString certificatePassword(QWidget *passwordPromptParent = 0, bool *ok = 0); const BlackBerryCertificate *defaultCertificate() const; + Status defaultCertificateOpeningStatus() const; void openDefaultCertificate(QWidget *passwordPromptParent = 0); void setDefaultCertificate(BlackBerryCertificate *certificate); void clearCskPassword(); void clearCertificatePassword(); void deleteDefaultCertificate(); + bool createCertificate(); void addDebugToken(const QString &dt); void removeDebugToken(const QString &dt); @@ -90,6 +98,7 @@ private: QString promptPassword(const QString &message, QWidget *dialogParent = 0, bool *ok = 0) const; BlackBerryCertificate *m_defaultCertificate; + Status m_defaultCertificateStatus; QString m_cskPassword; QString m_certificatePassword; diff --git a/src/plugins/qnx/images/error.png b/src/plugins/qnx/images/error.png new file mode 100644 index 0000000000000000000000000000000000000000..0d49c16f431bc38e566a7516adbbd6c9140ff3e6 GIT binary patch literal 627 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo*pj^6T^Rm>;A@F1O$-bS zoCO|{#S9D#9$@TtGTRO$SXSVe4$=$86+TOsF)%Qed%8G=cpQH_)i+PXP@r}H^Z7Fy zEF8J@Ch9y;n4_d^;ge^0+LBpH?4;qQb4-Rax5XZ9I;YZD=-)Agw@cN#Z1?ZcuM>skCWUq&3rlIROvIpEZ14iP3pw?|1Ie_tt|eNX42L}o{ZU+p@kRtCdGQ#dT| z$KNUH++DCbqSND5(wAN}MkmELzw0#JM3@yg6n?SPvcB`+%iAHDcdmbZyuy;qydBng z4{HDX6xk^mCcQ8$N2ap8kWt9|`STkQAEFLQ-HWmpY@cH@^O*hIxeHe|C7o-T;=p)( zW6*}eBVG@0r!mW#pSLZ$6%+U9^2^tG?sxA6<<|#okG_@no#W4Z5t{%;*><}lJEUcT z7F>^i_TT>l_q(`NdpsgNOc@v$R7+eVN>UO_QmvAUQWHy38H@}Jjdcx;bPbI{3@ojT zEv*cVwG9ld3=F<{NXMdR$jwj5OsmALp+$7@Lk0#0NstY}`DrEPiAAXljw$&`sS2LC diRr09sfj6-g(p*O7#J8BJYD@<);T3K0RScX@3H^@ literal 0 HcmV?d00001 diff --git a/src/plugins/qnx/images/info.png b/src/plugins/qnx/images/info.png new file mode 100644 index 0000000000000000000000000000000000000000..8d81e904ac3eed88302dc9576bfdee82a93bff77 GIT binary patch literal 630 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo*pj^6T^Rm>;A@F1O$-bS zoCO|{#S9D#9$@TtGTRO$SXSVe4$=$86+TOsF)%PzdAc};cpQH_)i6)QQNZ>7dbvqE zk9tj$$xWKc{YF$~vXH{Wf(cWdgH(j{4ssq)5WE#-aa3qS?ED4kd%K_9+p25nn3w6c z^yRFotNXpKZaN#huHw>*^9{e(Je+a3W~0qD)?Xig#@2rh5I-yKz5cxaMB&>B$vpxd z0!e?0Y6UK_o)P!{Z)blr@?fWN;wRArPECcTkFS<-cjkSVuDfINBj2N?hhKeay84uL zUHyW*g0&N-e!a<1<(PHN|PQ;e!V7f$lj;NnUa{jx&IdgEr#klUVhd+S*b zy!qPBX|g41#r>YUvelPtgy%fibv&uu%l_bP0Q4u5!@S%=XnsQK+l zh0N?NK1k44ofy`glX=O&z`&N| z?e44>*acjWu2!ty2^z%v(8Qo;V&+6X3uXC%I5UtIUXj{(-i0s&cL9iS=>66X~ioB P1_lOCS3j3^P6;A@F1O$-bS zoCO|{#S9D#9$@TtGTRO$SXSVe4$=$86+TOsF)%Q`_H=O!@i=~U>iH}YM}cGY@#o+9 zoharI5<02<=IZ3>lJ6N6D?TKAQL5-rSfRlk>1k7OVRn1ueZ~BTCzqf2H}meycb_f@ z#}-U~vmo$NfI;x((EHy*ORt|ev*X;;b*8`fGrZVxbI#Y&NdMk*=Gt%n2PWKaPY{jZ zUC5O6>9BZMO$8gvr}q3a`)tM6HBU)+)wt`$wTo?BYuHu?%xFG);qBuW{K+3CM=YK@ z{lW4G4aF%5-D0YnxDMH{{g#Z3HW>N4m)d0X?tM)vCEzHhxb zF2~>h%M-ireZAW@hlTfK9K;%SCC*O_bBsum@Z#Wh%YT1tcVelH#B3%B#<%s z#NP^FUTB!`U-#ZOUK?5XP2`ZsPtG5bVqPhtGa6Z5HF|GMk-lU0bFp!R;o@uj z*4LRo&-lzSL1@$Qcm@qN%OIva?mJ>dFK?Ob*F5oS)1$}P9I9Ez8d@!XRR$&94s43y zFV18M@~W#i^Wsj4DntE-bu2$_zkc@LDBtb?|MYf-8QUuUsWUJzsFt`!l%ync8tWPw=^7e^7+6{vTUr?!Ya19^85n%^kd8&skei>9nO2EgLyPF*hYSo1 xk{}y`^V3So6N^$A98>a>QWZRN6Vp?JQWH}u3s0unFfcGMc)I$ztaD0e0ss)VFHQge literal 0 HcmV?d00001 diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index 67dcdfc7960..877a4e81c11 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -102,7 +102,9 @@ SOURCES += qnxplugin.cpp \ blackberrycheckdevicestatusstep.cpp \ qnxattachdebugsupport.cpp \ qnxattachdebugdialog.cpp \ - blackberrydeployqtlibrariesdialog.cpp + blackberrydeployqtlibrariesdialog.cpp \ + blackberrysetuppage.cpp \ + blackberrysetupwidget.cpp HEADERS += qnxplugin.h\ qnxconstants.h \ @@ -204,7 +206,9 @@ HEADERS += qnxplugin.h\ blackberrycheckdevicestatusstepconfigwidget.h \ qnxattachdebugsupport.h \ qnxattachdebugdialog.h \ - blackberrydeployqtlibrariesdialog.h + blackberrydeployqtlibrariesdialog.h \ + blackberrysetuppage.h \ + blackberrysetupwidget.h FORMS += \ blackberrydeviceconfigurationwizardsetuppage.ui \ diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs index 9061e93a9d3..58ab679db40 100644 --- a/src/plugins/qnx/qnx.qbs +++ b/src/plugins/qnx/qnx.qbs @@ -147,6 +147,10 @@ QtcPlugin { "blackberryruncontrol.h", "blackberryruncontrolfactory.cpp", "blackberryruncontrolfactory.h", + "blackberrysetuppage.cpp", + "blackberrysetuppage.h", + "blackberrysetupwidget.cpp", + "blackberrysetupwidget.h", "blackberrysigningpasswordsdialog.h", "blackberrysigningpasswordsdialog.cpp", "blackberrysigningpasswordsdialog.ui", diff --git a/src/plugins/qnx/qnx.qrc b/src/plugins/qnx/qnx.qrc index 04a66a42ed5..e449f9a5d3b 100644 --- a/src/plugins/qnx/qnx.qrc +++ b/src/plugins/qnx/qnx.qrc @@ -2,5 +2,9 @@ images/target-small.png images/target.png + images/ok.png + images/info.png + images/warning.png + images/error.png diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h index 8d92a172642..db342752a5b 100644 --- a/src/plugins/qnx/qnxconstants.h +++ b/src/plugins/qnx/qnxconstants.h @@ -96,6 +96,7 @@ const char QNX_TOOLCHAIN_ID[] = "Qnx.QccToolChain"; const char QNX_BB_CATEGORY[] = "XF.BlackBerry"; const char QNX_BB_CATEGORY_TR[] = QT_TRANSLATE_NOOP("BlackBerry", "BlackBerry"); const char QNX_BB_CATEGORY_ICON[] = ":/qnx/images/target.png"; +const char QNX_BB_SETUP_ID[] = "ZA.BlackBerry Setup"; const char QNX_BB_NDK_SETTINGS_ID[] = "ZZ.BlackBerry NDK Configuration"; const char QNX_BB_SIGNING_ID[] = "ZZ.BlackBerry Signing Infrastructure Configuration"; @@ -119,6 +120,16 @@ const char QNX_DEBUGGING_GROUP[] = "Debugger.Group.Qnx"; const char QNX_BLACKBERRY_DEFAULT_DEPLOY_QT_BASEPATH[] = "/accounts/devuser/"; +const char QNX_OK_ICON[] = ":/qnx/images/ok.png"; +const char QNX_INFO_ICON[] = ":/qnx/images/info.png"; +const char QNX_WARNING_ICON[] = ":/qnx/images/warning.png"; +const char QNX_ERROR_ICON[] = ":/qnx/images/error.png"; + +const char QNX_BLACKBERRY_SETUP_URL[] = "http://qt-project.org/wiki/Qt-Creator-with-BlackBerry-10"; +const char QNX_LEGACY_KEYS_URL[] = "https://developer.blackberry.com/native/documentation/core" + "/com.qnx.doc.native_sdk.devguide/topic/bbid_to_sa.html"; +const char QNX_REGISTER_KEYS_URL[] = "https://www.blackberry.com/SignedKeys/codesigning.html"; + } // namespace Constants } // namespace Qnx diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp index 9b80454a84a..84bd85f9e0a 100644 --- a/src/plugins/qnx/qnxplugin.cpp +++ b/src/plugins/qnx/qnxplugin.cpp @@ -46,6 +46,7 @@ #include "qnxdeployconfigurationfactory.h" #include "qnxrunconfigurationfactory.h" #include "qnxqtversionfactory.h" +#include "blackberrysetuppage.h" #include "blackberryndksettingspage.h" #include "bardescriptoreditorfactory.h" #include "bardescriptormagicmatcher.h" @@ -98,6 +99,7 @@ bool QNXPlugin::initialize(const QStringList &arguments, QString *errorString) addAutoReleasedObject(new BlackBerryDeployStepFactory); addAutoReleasedObject(new BlackBerryRunConfigurationFactory); addAutoReleasedObject(new BlackBerryRunControlFactory); + addAutoReleasedObject(new BlackBerrySetupPage); addAutoReleasedObject(new BlackBerryNDKSettingsPage); addAutoReleasedObject(new BlackBerryKeysPage); addAutoReleasedObject(new BlackBerryCheckDeviceStatusStepFactory);