summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/mcusupport/CMakeLists.txt1
-rw-r--r--src/plugins/mcusupport/mcusupport.pro2
-rw-r--r--src/plugins/mcusupport/mcusupport.qbs2
-rw-r--r--src/plugins/mcusupport/mcusupportoptions.cpp503
-rw-r--r--src/plugins/mcusupport/mcusupportoptions.h137
-rw-r--r--src/plugins/mcusupport/mcusupportoptionspage.cpp563
6 files changed, 648 insertions, 560 deletions
diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt
index 91fa58b620..ef25f4f45c 100644
--- a/src/plugins/mcusupport/CMakeLists.txt
+++ b/src/plugins/mcusupport/CMakeLists.txt
@@ -6,6 +6,7 @@ add_qtc_plugin(McuSupport
mcusupport_global.h
mcusupportconstants.h
mcusupportdevice.cpp mcusupportdevice.h
+ mcusupportoptions.cpp mcusupportoptions.h
mcusupportoptionspage.cpp mcusupportoptionspage.h
mcusupportplugin.cpp mcusupportplugin.h
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
diff --git a/src/plugins/mcusupport/mcusupport.pro b/src/plugins/mcusupport/mcusupport.pro
index 9bb79364f8..3f6d598f59 100644
--- a/src/plugins/mcusupport/mcusupport.pro
+++ b/src/plugins/mcusupport/mcusupport.pro
@@ -8,12 +8,14 @@ HEADERS += \
mcusupport_global.h \
mcusupportconstants.h \
mcusupportdevice.h \
+ mcusupportoptions.h \
mcusupportoptionspage.h \
mcusupportplugin.h \
mcusupportrunconfiguration.h
SOURCES += \
mcusupportdevice.cpp \
+ mcusupportoptions.cpp \
mcusupportoptionspage.cpp \
mcusupportplugin.cpp \
mcusupportrunconfiguration.cpp
diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs
index 732ecf81e4..35e3e9a471 100644
--- a/src/plugins/mcusupport/mcusupport.qbs
+++ b/src/plugins/mcusupport/mcusupport.qbs
@@ -18,6 +18,8 @@ QtcPlugin {
"mcusupportconstants.h",
"mcusupportdevice.cpp",
"mcusupportdevice.h",
+ "mcusupportoptions.cpp",
+ "mcusupportoptions.h",
"mcusupportoptionspage.cpp",
"mcusupportoptionspage.h",
"mcusupportplugin.cpp",
diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp
new file mode 100644
index 0000000000..c61a3b6f6d
--- /dev/null
+++ b/src/plugins/mcusupport/mcusupportoptions.cpp
@@ -0,0 +1,503 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mcusupportconstants.h"
+#include "mcusupportoptions.h"
+
+#include <coreplugin/icore.h>
+#include <cmakeprojectmanager/cmakekitinformation.h>
+#include <debugger/debuggeritem.h>
+#include <debugger/debuggeritemmanager.h>
+#include <debugger/debuggerkitinformation.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainmanager.h>
+#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/devicesupport/devicemanager.h>
+#include <utils/algorithm.h>
+#include <utils/fileutils.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <QDesktopServices>
+#include <QDir>
+#include <QFileInfo>
+#include <QLabel>
+#include <QToolButton>
+#include <QVBoxLayout>
+#include <QVariant>
+
+namespace McuSupport {
+namespace Internal {
+
+PackageOptions::PackageOptions(const QString &label, const QString &defaultPath,
+ const QString &detectionPath, const QString &settingsKey)
+ : m_label(label)
+ , m_defaultPath(defaultPath)
+ , m_detectionPath(detectionPath)
+ , m_settingsKey(settingsKey)
+{
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_GROUP);
+ m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
+ m_defaultPath).toString();
+ s->endGroup();
+}
+
+QString PackageOptions::path() const
+{
+ return QFileInfo(m_fileChooser->path() + m_relativePathModifier).absoluteFilePath();
+}
+
+QString PackageOptions::label() const
+{
+ return m_label;
+}
+
+QString PackageOptions::detectionPath() const
+{
+ return m_detectionPath;
+}
+
+QWidget *PackageOptions::widget()
+{
+ if (m_widget)
+ return m_widget;
+
+ m_widget = new QWidget;
+ m_fileChooser = new Utils::PathChooser;
+ QObject::connect(m_fileChooser, &Utils::PathChooser::pathChanged,
+ [this](){
+ updateStatus();
+ emit changed();
+ });
+
+ auto layout = new QGridLayout(m_widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ m_statusIcon = new QLabel;
+ m_statusIcon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
+ m_statusIcon->setAlignment(Qt::AlignTop);
+ m_statusLabel = new QLabel;
+ m_statusLabel->setWordWrap(true);
+ m_statusLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+
+ if (!m_downloadUrl.isEmpty()) {
+ auto downLoadButton = new QToolButton;
+ downLoadButton->setIcon(Utils::Icons::DOWNLOAD.icon());
+ downLoadButton->setToolTip(tr("Download from \"%1\"").arg(m_downloadUrl));
+ QObject::connect(downLoadButton, &QToolButton::pressed, [this]{
+ QDesktopServices::openUrl(m_downloadUrl);
+ });
+ layout->addWidget(downLoadButton, 0, 2);
+ }
+
+ layout->addWidget(m_fileChooser, 0, 0, 1, 2);
+ layout->addWidget(m_statusIcon, 1, 0);
+ layout->addWidget(m_statusLabel, 1, 1, 1, -1);
+
+ m_fileChooser->setPath(m_path); // Triggers updateStatus() call
+ return m_widget;
+}
+
+PackageOptions::Status PackageOptions::status() const
+{
+ return m_status;
+}
+
+void PackageOptions::setDownloadUrl(const QString &url)
+{
+ m_downloadUrl = url;
+}
+
+void PackageOptions::setEnvironmentVariableName(const QString &name)
+{
+ m_environmentVariableName = name;
+}
+
+QString PackageOptions::environmentVariableName() const
+{
+ return m_environmentVariableName;
+}
+
+void PackageOptions::setAddToPath(bool addToPath)
+{
+ m_addToPath = addToPath;
+}
+
+bool PackageOptions::addToPath() const
+{
+ return m_addToPath;
+}
+
+void PackageOptions::writeToSettings() const
+{
+ if (m_path.compare(m_defaultPath) == 0)
+ return;
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_GROUP);
+ s->setValue(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey, m_path);
+ s->endGroup();
+}
+
+void PackageOptions::setRelativePathModifier(const QString &path)
+{
+ m_relativePathModifier = path;
+}
+
+void PackageOptions::updateStatus()
+{
+ m_path = m_fileChooser->rawPath();
+ const bool validPath = m_fileChooser->isValid();
+ const Utils::FilePath detectionPath = Utils::FilePath::fromString(
+ m_fileChooser->path() + "/" + m_detectionPath);
+ const QString displayDetectionPath = Utils::FilePath::fromString(m_detectionPath).toUserOutput();
+ const bool validPackage = detectionPath.exists();
+
+ m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) : InvalidPath;
+
+ static const QPixmap okIcon = Utils::Icons::OK.pixmap();
+ static const QPixmap notOkIcon = Utils::Icons::BROKEN.pixmap();
+ m_statusIcon->setPixmap(m_status == ValidPackage ? okIcon : notOkIcon);
+
+ QString statusText;
+ switch (m_status) {
+ case ValidPackage:
+ statusText = tr("Path is valid, \"%1\" was found.").arg(displayDetectionPath);
+ break;
+ case ValidPathInvalidPackage:
+ statusText = tr("Path exists, but does not contain \"%1\".").arg(displayDetectionPath);
+ break;
+ case InvalidPath:
+ statusText = tr("Path does not exist.");
+ break;
+ }
+ m_statusLabel->setText(statusText);
+}
+
+BoardOptions::BoardOptions(const QString &model, const QString &toolChainFileName,
+ const QVector<PackageOptions*> &packages)
+ : m_model(model)
+ , m_toolChainFile(toolChainFileName)
+ , m_packages(packages)
+{
+}
+
+QString BoardOptions::model() const
+{
+ return m_model;
+}
+
+QString BoardOptions::toolChainFile() const
+{
+ return m_toolChainFile;
+}
+
+QVector<PackageOptions *> BoardOptions::packages() const
+{
+ return m_packages;
+}
+
+static PackageOptions *createQulPackage()
+{
+ auto result = new PackageOptions(
+ PackageOptions::tr("Qt MCU SDK"),
+ QDir::homePath(),
+ Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
+ "qulSdk");
+ result->setEnvironmentVariableName("Qul_DIR");
+ return result;
+}
+
+static PackageOptions *createArmGccPackage()
+{
+ const QString defaultPath =
+ Utils::HostOsInfo::isWindowsHost() ?
+ QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles(x86)"))
+ + "/GNU Tools ARM Embedded/"
+ : QString("%{Env:ARMGCC_DIR}");
+ auto result = new PackageOptions(
+ PackageOptions::tr("GNU Arm Embedded Toolchain"),
+ defaultPath,
+ Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
+ Constants::SETTINGS_KEY_PACKAGE_ARMGCC);
+ result->setDownloadUrl(
+ "https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads");
+ result->setEnvironmentVariableName("ARMGCC_DIR");
+ return result;
+}
+
+static PackageOptions *createStm32CubeFwF7SdkPackage()
+{
+ auto result = new PackageOptions(
+ PackageOptions::tr("STM32Cube SDK"),
+ "%{Env:STM32Cube_FW_F7_SDK_PATH}",
+ "Drivers/STM32F7xx_HAL_Driver",
+ "stm32CubeFwF7Sdk");
+ result->setDownloadUrl(
+ "https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-mcu-packages/stm32cubef7.html");
+ result->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
+ return result;
+}
+
+static PackageOptions *createStm32CubeProgrammerPackage()
+{
+ const QString defaultPath =
+ Utils::HostOsInfo::isWindowsHost() ?
+ QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles"))
+ + "/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
+ : QDir::homePath();
+ auto result = new PackageOptions(
+ PackageOptions::tr("STM32CubeProgrammer"),
+ defaultPath,
+ QLatin1String(Utils::HostOsInfo::isWindowsHost() ? "/bin/STM32_Programmer_CLI.exe"
+ : "/bin/STM32_Programmer.sh"),
+ "stm32CubeProgrammer");
+ result->setRelativePathModifier("/bin");
+ result->setDownloadUrl(
+ "https://www.st.com/en/development-tools/stm32cubeprog.html");
+ result->setAddToPath(true);
+ return result;
+}
+
+static PackageOptions *createEvkbImxrt1050SdkPackage()
+{
+ auto result = new PackageOptions(
+ PackageOptions::tr("NXP EVKB-IMXRT1050 SDK"),
+ "%{Env:EVKB_IMXRT1050_SDK_PATH}",
+ "EVKB-IMXRT1050_manifest_v3_5.xml",
+ "evkbImxrt1050Sdk");
+ result->setDownloadUrl("https://mcuxpresso.nxp.com/en/welcome");
+ return result;
+}
+
+static PackageOptions *createSeggerJLinkPackage()
+{
+ const QString defaultPath =
+ Utils::HostOsInfo::isWindowsHost() ?
+ QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles")) + "/SEGGER/JLink"
+ : QString("%{Env:SEGGER_JLINK_SOFTWARE_AND_DOCUMENTATION_PATH}");
+ auto result = new PackageOptions(
+ PackageOptions::tr("SEGGER JLink"),
+ defaultPath,
+ Utils::HostOsInfo::withExecutableSuffix("JLink"),
+ "seggerJLink");
+ result->setDownloadUrl("https://www.segger.com/downloads/jlink");
+ return result;
+}
+
+McuSupportOptions::McuSupportOptions(QObject *parent)
+ : QObject(parent)
+{
+ PackageOptions* qulPackage = createQulPackage();
+ PackageOptions* armGccPackage = createArmGccPackage();
+ PackageOptions* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
+ PackageOptions* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
+ PackageOptions* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
+ PackageOptions* seggerJLinkPackage = createSeggerJLinkPackage();
+
+ toolchainPackage = armGccPackage;
+
+
+ auto stmPackages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
+ qulPackage};
+ auto nxpPackages = {armGccPackage, evkbImxrt1050SdkPackage, seggerJLinkPackage,
+ qulPackage};
+ packages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
+ evkbImxrt1050SdkPackage, seggerJLinkPackage, qulPackage};
+
+ boards.append(new BoardOptions(
+ "stm32f7508", "CMake/stm32f7508-discovery.cmake", stmPackages));
+ boards.append(new BoardOptions(
+ "stm32f769i", "CMake/stm32f769i-discovery.cmake", stmPackages));
+ boards.append(new BoardOptions(
+ "evkbimxrt1050", "CMake/evkbimxrt1050-toolchain.cmake", nxpPackages));
+
+ for (auto package : packages)
+ connect(package, &PackageOptions::changed, [this](){
+ emit changed();
+ });
+}
+
+McuSupportOptions::~McuSupportOptions()
+{
+ qDeleteAll(packages);
+ packages.clear();
+ qDeleteAll(boards);
+ boards.clear();
+}
+
+QVector<BoardOptions *> McuSupportOptions::validBoards() const
+{
+ return Utils::filtered(boards, [](BoardOptions *board){
+ return !Utils::anyOf(board->packages(), [](PackageOptions *package){
+ return package->status() != PackageOptions::ValidPackage;});
+ });
+}
+
+static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language)
+{
+ using namespace ProjectExplorer;
+
+ ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
+ return t->compilerCommand() == path && t->language() == language;
+ });
+ if (!toolChain) {
+ ToolChainFactory *gccFactory =
+ Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
+ return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
+ });
+ if (gccFactory) {
+ const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
+ if (!detected.isEmpty()) {
+ toolChain = detected.first();
+ toolChain->setDetection(ToolChain::ManualDetection);
+ toolChain->setDisplayName("Arm GCC");
+ ToolChainManager::registerToolChain(toolChain);
+ }
+ }
+ }
+
+ return toolChain;
+}
+
+static void setKitProperties(ProjectExplorer::Kit *k, const BoardOptions* board)
+{
+ using namespace ProjectExplorer;
+
+ k->setUnexpandedDisplayName("Qt MCU - " + board->model());
+ k->setValue(Constants::KIT_BOARD_MODEL_KEY, board->model());
+ k->setAutoDetected(false);
+ k->setIrrelevantAspects({
+ SysRootKitAspect::id(),
+ "QtSupport.QtInformation" // QtKitAspect::id()
+ });
+}
+
+static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath)
+{
+ using namespace ProjectExplorer;
+
+ const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix(
+ armGccPath + "/bin/arm-none-eabi-%1");
+ ToolChain *cTc = armGccToolchain(
+ Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")),
+ ProjectExplorer::Constants::C_LANGUAGE_ID);
+ ToolChain *cxxTc = armGccToolchain(
+ Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")),
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChainKitAspect::setToolChain(k, cTc);
+ ToolChainKitAspect::setToolChain(k, cxxTc);
+}
+
+static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath)
+{
+ using namespace Debugger;
+
+ const Utils::FilePath command = Utils::FilePath::fromUserInput(
+ Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py"));
+ const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
+ QVariant debuggerId;
+ if (!debugger) {
+ DebuggerItem newDebugger;
+ newDebugger.setCommand(command);
+ newDebugger.setUnexpandedDisplayName(
+ PackageOptions::tr("Arm GDB at %1").arg(command.toUserOutput()));
+ debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
+ } else {
+ debuggerId = debugger->id();
+ }
+
+ DebuggerKitAspect::setDebugger(k, debuggerId);
+}
+
+static void setKitDevice(ProjectExplorer::Kit *k)
+{
+ using namespace ProjectExplorer;
+
+ DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
+}
+
+static void setKitEnvironment(ProjectExplorer::Kit *k, const BoardOptions* board)
+{
+ using namespace ProjectExplorer;
+
+ Utils::EnvironmentItems changes;
+ QStringList pathAdditions;
+ for (auto package : board->packages()) {
+ if (package->addToPath())
+ pathAdditions.append(QDir::toNativeSeparators(package->path()));
+ if (!package->environmentVariableName().isEmpty())
+ changes.append({package->environmentVariableName(),
+ QDir::toNativeSeparators(package->path())});
+ }
+ if (!pathAdditions.isEmpty()) {
+ pathAdditions.append("${Path}");
+ changes.append({"Path", pathAdditions.join(Utils::HostOsInfo::pathListSeparator())});
+ }
+ EnvironmentKitAspect::setEnvironmentChanges(k, changes);
+}
+
+static void setKitCMakeOptions(ProjectExplorer::Kit *k, const BoardOptions* board)
+{
+ using namespace CMakeProjectManager;
+
+ CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
+ config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE",
+ ("%{CurrentBuild:Env:Qul_DIR}/" +
+ board->toolChainFile()).toUtf8()));
+ CMakeConfigurationKitAspect::setConfiguration(k, config);
+}
+
+ProjectExplorer::Kit *McuSupportOptions::kit(const BoardOptions* board)
+{
+ using namespace ProjectExplorer;
+
+ Kit *kit = KitManager::kit([board](const Kit *k){
+ return board->model() == k->value(Constants::KIT_BOARD_MODEL_KEY).toString();
+ });
+ if (!kit) {
+ const QString armGccPath = toolchainPackage->path();
+ const auto init = [board, &armGccPath](Kit *k) {
+ KitGuard kitGuard(k);
+
+ setKitProperties(k, board);
+ setKitToolchains(k, armGccPath);
+ setKitDebugger(k, armGccPath);
+ setKitDevice(k);
+ setKitEnvironment(k, board);
+ setKitCMakeOptions(k, board);
+
+ k->setup();
+ k->fix();
+ };
+ kit = KitManager::registerKit(init);
+ }
+ return kit;
+}
+
+} // Internal
+} // McuSupport
diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h
new file mode 100644
index 0000000000..0cfdd2a4ff
--- /dev/null
+++ b/src/plugins/mcusupport/mcusupportoptions.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QLabel)
+
+namespace Utils {
+class PathChooser;
+}
+
+namespace ProjectExplorer {
+class Kit;
+}
+
+namespace McuSupport {
+namespace Internal {
+
+class PackageOptions : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Status {
+ InvalidPath,
+ ValidPathInvalidPackage,
+ ValidPackage
+ };
+
+ PackageOptions(const QString &label, const QString &defaultPath, const QString &detectionPath,
+ const QString &settingsKey);
+
+ QString path() const;
+ QString label() const;
+ QString detectionPath() const;
+ Status status() const;
+ void setDownloadUrl(const QString &url);
+ void setEnvironmentVariableName(const QString &name);
+ void setAddToPath(bool addToPath);
+ bool addToPath() const;
+ void writeToSettings() const;
+ void setRelativePathModifier(const QString &path);
+
+ QWidget *widget();
+
+ QString environmentVariableName() const;
+
+signals:
+ void changed();
+
+private:
+ void updateStatus();
+
+ QWidget *m_widget = nullptr;
+ Utils::PathChooser *m_fileChooser = nullptr;
+ QLabel *m_statusIcon = nullptr;
+ QLabel *m_statusLabel = nullptr;
+
+ const QString m_label;
+ const QString m_defaultPath;
+ const QString m_detectionPath;
+ const QString m_settingsKey;
+
+ QString m_path;
+ QString m_relativePathModifier; // relative path to m_path to be returned by path()
+ QString m_downloadUrl;
+ QString m_environmentVariableName;
+ bool m_addToPath = false;
+
+ Status m_status = InvalidPath;
+};
+
+class BoardOptions : public QObject
+{
+ Q_OBJECT
+
+public:
+ BoardOptions(const QString &model, const QString &toolChainFile,
+ const QVector<PackageOptions *> &packages);
+
+ QString model() const;
+ QString toolChainFile() const;
+ QVector<PackageOptions *> packages() const;
+
+private:
+ const QString m_model;
+ const QString m_toolChainFile;
+ const QVector<PackageOptions*> m_packages;
+};
+
+class McuSupportOptions : public QObject
+{
+ Q_OBJECT
+
+public:
+ McuSupportOptions(QObject *parent = nullptr);
+ ~McuSupportOptions() override;
+
+ QVector<BoardOptions*> validBoards() const;
+
+ QVector<PackageOptions*> packages;
+ QVector<BoardOptions*> boards;
+ PackageOptions *toolchainPackage = nullptr;
+
+ ProjectExplorer::Kit *kit(const BoardOptions* board);
+
+signals:
+ void changed();
+};
+
+} // namespace Internal
+} // namespace McuSupport
diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp
index 64d45bf7b0..d22f213be5 100644
--- a/src/plugins/mcusupport/mcusupportoptionspage.cpp
+++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp
@@ -25,441 +25,24 @@
#include "mcusupportconstants.h"
#include "mcusupportoptionspage.h"
+#include "mcusupportoptions.h"
#include <coreplugin/icore.h>
-#include <cmakeprojectmanager/cmakekitinformation.h>
-#include <debugger/debuggeritem.h>
-#include <debugger/debuggeritemmanager.h>
-#include <debugger/debuggerkitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/toolchain.h>
-#include <projectexplorer/toolchainmanager.h>
-#include <projectexplorer/kitmanager.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/devicesupport/devicemanager.h>
#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
-#include <QAction>
#include <QComboBox>
-#include <QDebug>
-#include <QDesktopServices>
#include <QDir>
-#include <QFileInfo>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
-#include <QSizePolicy>
-#include <QToolButton>
#include <QVBoxLayout>
-#include <QVariant>
namespace McuSupport {
namespace Internal {
-class PackageOptions : public QObject
-{
- Q_OBJECT
-
-public:
- enum Status {
- InvalidPath,
- ValidPathInvalidPackage,
- ValidPackage
- };
-
- PackageOptions(const QString &label, const QString &defaultPath, const QString &detectionPath,
- const QString &settingsKey);
-
- QString path() const;
- QString label() const;
- QString detectionPath() const;
- Status status() const;
- void setDownloadUrl(const QUrl &url);
- void setEnvironmentVariableName(const QString &name);
- void setAddToPath(bool addToPath);
- bool addToPath() const;
- void writeToSettings() const;
- void setRelativePathModifier(const QString &path);
-
- QWidget *widget();
-
-
- QString environmentVariableName() const;
-
-signals:
- void changed();
-
-private:
- void updateStatus();
-
- QWidget *m_widget = nullptr;
- Utils::PathChooser *m_fileChooser = nullptr;
- QLabel *m_statusIcon = nullptr;
- QLabel *m_statusLabel = nullptr;
-
- const QString m_label;
- const QString m_defaultPath;
- const QString m_detectionPath;
- const QString m_settingsKey;
-
- QString m_path;
- QString m_relativePathModifier; // relative path to m_path to be returned by path()
- QUrl m_downloadUrl;
- QString m_environmentVariableName;
- bool m_addToPath = false;
-
- Status m_status = InvalidPath;
-};
-
-PackageOptions::PackageOptions(const QString &label, const QString &defaultPath,
- const QString &detectionPath, const QString &settingsKey)
- : m_label(label)
- , m_defaultPath(defaultPath)
- , m_detectionPath(detectionPath)
- , m_settingsKey(settingsKey)
-{
- QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
- m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
- m_defaultPath).toString();
- s->endGroup();
-}
-
-QString PackageOptions::path() const
-{
- return QFileInfo(m_fileChooser->path() + m_relativePathModifier).absoluteFilePath();
-}
-
-QString PackageOptions::label() const
-{
- return m_label;
-}
-
-QString PackageOptions::detectionPath() const
-{
- return m_detectionPath;
-}
-
-QWidget *PackageOptions::widget()
-{
- if (m_widget)
- return m_widget;
-
- m_widget = new QWidget;
- m_fileChooser = new Utils::PathChooser;
- QObject::connect(m_fileChooser, &Utils::PathChooser::pathChanged,
- [this](){
- updateStatus();
- emit changed();
- });
-
- auto layout = new QGridLayout(m_widget);
- layout->setContentsMargins(0, 0, 0, 0);
- m_statusIcon = new QLabel;
- m_statusIcon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
- m_statusIcon->setAlignment(Qt::AlignTop);
- m_statusLabel = new QLabel;
- m_statusLabel->setWordWrap(true);
- m_statusLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
-
- if (!m_downloadUrl.isEmpty()) {
- auto downLoadButton = new QToolButton;
- downLoadButton->setIcon(Utils::Icons::DOWNLOAD.icon());
- downLoadButton->setToolTip(McuSupportOptionsPage::tr("Download from \"%1\"")
- .arg(m_downloadUrl.toString()));
- QObject::connect(downLoadButton, &QToolButton::pressed, [this]{
- QDesktopServices::openUrl(m_downloadUrl);
- });
- layout->addWidget(downLoadButton, 0, 2);
- }
-
- layout->addWidget(m_fileChooser, 0, 0, 1, 2);
- layout->addWidget(m_statusIcon, 1, 0);
- layout->addWidget(m_statusLabel, 1, 1, 1, -1);
-
- m_fileChooser->setPath(m_path); // Triggers updateStatus() call
- return m_widget;
-}
-
-PackageOptions::Status PackageOptions::status() const
-{
- return m_status;
-}
-
-void PackageOptions::setDownloadUrl(const QUrl &url)
-{
- m_downloadUrl = url;
-}
-
-void PackageOptions::setEnvironmentVariableName(const QString &name)
-{
- m_environmentVariableName = name;
-}
-
-QString PackageOptions::environmentVariableName() const
-{
- return m_environmentVariableName;
-}
-
-void PackageOptions::setAddToPath(bool addToPath)
-{
- m_addToPath = addToPath;
-}
-
-bool PackageOptions::addToPath() const
-{
- return m_addToPath;
-}
-
-void PackageOptions::writeToSettings() const
-{
- if (m_path.compare(m_defaultPath) == 0)
- return;
- QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
- s->setValue(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey, m_path);
- s->endGroup();
-}
-
-void PackageOptions::setRelativePathModifier(const QString &path)
-{
- m_relativePathModifier = path;
-}
-
-void PackageOptions::updateStatus()
-{
- m_path = m_fileChooser->rawPath();
- const bool validPath = m_fileChooser->isValid();
- const Utils::FilePath detectionPath = Utils::FilePath::fromString(
- m_fileChooser->path() + "/" + m_detectionPath);
- const QString displayDetectionPath = Utils::FilePath::fromString(m_detectionPath).toUserOutput();
- const bool validPackage = detectionPath.exists();
-
- m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) : InvalidPath;
-
- static const QPixmap okIcon = Utils::Icons::OK.pixmap();
- static const QPixmap notOkIcon = Utils::Icons::BROKEN.pixmap();
- m_statusIcon->setPixmap(m_status == ValidPackage ? okIcon : notOkIcon);
-
- QString statusText;
- switch (m_status) {
- case ValidPackage:
- statusText = McuSupportOptionsPage::tr(
- "Path is valid, \"%1\" was found.").arg(displayDetectionPath);
- break;
- case ValidPathInvalidPackage:
- statusText = McuSupportOptionsPage::tr(
- "Path exists, but does not contain \"%1\".").arg(displayDetectionPath);
- break;
- case InvalidPath:
- statusText = McuSupportOptionsPage::tr("Path does not exist.");
- break;
- }
- m_statusLabel->setText(statusText);
-}
-
-class BoardOptions : public QObject
-{
- Q_OBJECT
-
-public:
- BoardOptions(const QString &model, const QString &toolChainFile,
- const QVector<PackageOptions *> &packages);
-
- QString model() const;
- QString toolChainFile() const;
- QVector<PackageOptions *> packages() const;
-
-private:
- const QString m_model;
- const QString m_toolChainFile;
- const QVector<PackageOptions*> m_packages;
-};
-
-BoardOptions::BoardOptions(const QString &model, const QString &toolChainFileName,
- const QVector<PackageOptions*> &packages)
- : m_model(model)
- , m_toolChainFile(toolChainFileName)
- , m_packages(packages)
-{
-}
-
-QString BoardOptions::model() const
-{
- return m_model;
-}
-
-QString BoardOptions::toolChainFile() const
-{
- return m_toolChainFile;
-}
-
-QVector<PackageOptions *> BoardOptions::packages() const
-{
- return m_packages;
-}
-
-class McuSupportOptions : public QObject
-{
- Q_OBJECT
-
-public:
- McuSupportOptions(QObject *parent = nullptr);
- ~McuSupportOptions() override;
-
- QVector<BoardOptions*> validBoards() const;
-
- QVector<PackageOptions*> packages;
- QVector<BoardOptions*> boards;
- PackageOptions* toolchainPackage = nullptr;
-
-signals:
- void changed();
-};
-
-static PackageOptions* createQulPackage()
-{
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("Qt MCU SDK"),
- QDir::homePath(),
- Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
- "qulSdk");
- result->setEnvironmentVariableName("Qul_DIR");
- return result;
-}
-
-static PackageOptions* createArmGccPackage()
-{
- const QString defaultPath =
- Utils::HostOsInfo::isWindowsHost() ?
- QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles(x86)"))
- + "/GNU Tools ARM Embedded/"
- : QString("%{Env:ARMGCC_DIR}");
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("GNU Arm Embedded Toolchain"),
- defaultPath,
- Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
- Constants::SETTINGS_KEY_PACKAGE_ARMGCC);
- result->setDownloadUrl(
- QUrl::fromUserInput("https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads"));
- result->setEnvironmentVariableName("ARMGCC_DIR");
- return result;
-}
-
-static PackageOptions* createStm32CubeFwF7SdkPackage()
-{
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("STM32Cube SDK"),
- "%{Env:STM32Cube_FW_F7_SDK_PATH}",
- "Drivers/STM32F7xx_HAL_Driver",
- "stm32CubeFwF7Sdk");
- result->setDownloadUrl(
- QUrl::fromUserInput("https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-mcu-packages/stm32cubef7.html"));
- result->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
- return result;
-}
-
-static PackageOptions* createStm32CubeProgrammerPackage()
-{
- const QString defaultPath =
- Utils::HostOsInfo::isWindowsHost() ?
- QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles"))
- + "/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
- : QDir::homePath();
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("STM32CubeProgrammer"),
- defaultPath,
- QLatin1String(Utils::HostOsInfo::isWindowsHost() ? "/bin/STM32_Programmer_CLI.exe"
- : "/bin/STM32_Programmer.sh"),
- "stm32CubeProgrammer");
- result->setRelativePathModifier("/bin");
- result->setDownloadUrl(
- QUrl::fromUserInput("https://www.st.com/en/development-tools/stm32cubeprog.html"));
- result->setAddToPath(true);
- return result;
-}
-
-static PackageOptions* createEvkbImxrt1050SdkPackage()
-{
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("NXP EVKB-IMXRT1050 SDK"),
- "%{Env:EVKB_IMXRT1050_SDK_PATH}",
- "EVKB-IMXRT1050_manifest_v3_5.xml",
- "evkbImxrt1050Sdk");
- result->setDownloadUrl(
- QUrl::fromUserInput("https://mcuxpresso.nxp.com/en/welcome"));
- return result;
-}
-
-static PackageOptions* createSeggerJLinkPackage()
-{
- const QString defaultPath =
- Utils::HostOsInfo::isWindowsHost() ?
- QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles")) + "/SEGGER/JLink"
- : QString("%{Env:SEGGER_JLINK_SOFTWARE_AND_DOCUMENTATION_PATH}");
- auto result = new PackageOptions(
- McuSupportOptionsPage::tr("SEGGER JLink"),
- defaultPath,
- Utils::HostOsInfo::withExecutableSuffix("JLink"),
- "seggerJLink");
- result->setDownloadUrl(
- QUrl::fromUserInput("https://www.segger.com/downloads/jlink"));
- return result;
-}
-
-McuSupportOptions::McuSupportOptions(QObject *parent)
- : QObject(parent)
-{
- PackageOptions* qulPackage = createQulPackage();
- PackageOptions* armGccPackage = createArmGccPackage();
- PackageOptions* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
- PackageOptions* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
- PackageOptions* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
- PackageOptions* seggerJLinkPackage = createSeggerJLinkPackage();
-
- toolchainPackage = armGccPackage;
-
-
- auto stmPackages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
- qulPackage};
- auto nxpPackages = {armGccPackage, evkbImxrt1050SdkPackage, seggerJLinkPackage,
- qulPackage};
- packages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
- evkbImxrt1050SdkPackage, seggerJLinkPackage, qulPackage};
-
- boards.append(new BoardOptions(
- "stm32f7508", "CMake/stm32f7508-discovery.cmake", stmPackages));
- boards.append(new BoardOptions(
- "stm32f769i", "CMake/stm32f769i-discovery.cmake", stmPackages));
- boards.append(new BoardOptions(
- "evkbimxrt1050", "CMake/evkbimxrt1050-toolchain.cmake", nxpPackages));
-
- for (auto package : packages)
- connect(package, &PackageOptions::changed, [this](){
- emit changed();
- });
-}
-
-McuSupportOptions::~McuSupportOptions()
-{
- qDeleteAll(packages);
- packages.clear();
- qDeleteAll(boards);
- boards.clear();
-}
-
-QVector<BoardOptions *> McuSupportOptions::validBoards() const
-{
- return Utils::filtered(boards, [](BoardOptions *board){
- return !Utils::anyOf(board->packages(), [](PackageOptions *package){
- return package->status() != PackageOptions::ValidPackage;});
- });
-}
-
class McuSupportOptionsWidget : public QWidget
{
public:
@@ -562,7 +145,7 @@ McuSupportOptionsPage::McuSupportOptionsPage(QObject* parent)
setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY);
}
-QWidget* McuSupportOptionsPage::widget()
+QWidget *McuSupportOptionsPage::widget()
{
if (!m_options)
m_options = new McuSupportOptions(this);
@@ -571,146 +154,6 @@ QWidget* McuSupportOptionsPage::widget()
return m_widget;
}
-static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language)
-{
- using namespace ProjectExplorer;
-
- ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
- return t->compilerCommand() == path && t->language() == language;
- });
- if (!toolChain) {
- ToolChainFactory *gccFactory =
- Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
- return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
- });
- if (gccFactory) {
- const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
- if (!detected.isEmpty()) {
- toolChain = detected.first();
- toolChain->setDetection(ToolChain::ManualDetection);
- toolChain->setDisplayName("Arm GCC");
- ToolChainManager::registerToolChain(toolChain);
- }
- }
- }
-
- return toolChain;
-}
-
-static void setKitProperties(ProjectExplorer::Kit *k, const BoardOptions* board)
-{
- using namespace ProjectExplorer;
-
- k->setUnexpandedDisplayName("Qt MCU - " + board->model());
- k->setValue(Constants::KIT_BOARD_MODEL_KEY, board->model());
- k->setAutoDetected(false);
- k->setIrrelevantAspects({
- SysRootKitAspect::id(),
- "QtSupport.QtInformation" // QtKitAspect::id()
- });
-}
-
-static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath)
-{
- using namespace ProjectExplorer;
-
- const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix(
- armGccPath + "/bin/arm-none-eabi-%1");
- ToolChain *cTc = armGccToolchain(
- Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")),
- ProjectExplorer::Constants::C_LANGUAGE_ID);
- ToolChain *cxxTc = armGccToolchain(
- Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")),
- ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- ToolChainKitAspect::setToolChain(k, cTc);
- ToolChainKitAspect::setToolChain(k, cxxTc);
-}
-
-static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath)
-{
- using namespace Debugger;
-
- const Utils::FilePath command = Utils::FilePath::fromUserInput(
- Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py"));
- const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
- QVariant debuggerId;
- if (!debugger) {
- DebuggerItem newDebugger;
- newDebugger.setCommand(command);
- newDebugger.setUnexpandedDisplayName(
- McuSupportOptionsPage::tr("Arm GDB at %1").arg(command.toUserOutput()));
- debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
- } else {
- debuggerId = debugger->id();
- }
-
- DebuggerKitAspect::setDebugger(k, debuggerId);
-}
-
-static void setKitDevice(ProjectExplorer::Kit *k)
-{
- using namespace ProjectExplorer;
-
- DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
-}
-
-static void setKitEnvironment(ProjectExplorer::Kit *k, const BoardOptions* board)
-{
- using namespace ProjectExplorer;
-
- Utils::EnvironmentItems changes;
- QStringList pathAdditions;
- for (auto package : board->packages()) {
- if (package->addToPath())
- pathAdditions.append(QDir::toNativeSeparators(package->path()));
- if (!package->environmentVariableName().isEmpty())
- changes.append({package->environmentVariableName(),
- QDir::toNativeSeparators(package->path())});
- }
- if (!pathAdditions.isEmpty()) {
- pathAdditions.append("${Path}");
- changes.append({"Path", pathAdditions.join(Utils::HostOsInfo::pathListSeparator())});
- }
- EnvironmentKitAspect::setEnvironmentChanges(k, changes);
-}
-
-static void setKitCMakeOptions(ProjectExplorer::Kit *k, const BoardOptions* board)
-{
- using namespace CMakeProjectManager;
-
- CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
- config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE",
- ("%{CurrentBuild:Env:Qul_DIR}/" +
- board->toolChainFile()).toUtf8()));
- CMakeConfigurationKitAspect::setConfiguration(k, config);
-}
-
-static ProjectExplorer::Kit* boardKit(const BoardOptions* board, const QString &armGccPath)
-{
- using namespace ProjectExplorer;
-
- Kit *kit = KitManager::kit([board](const Kit *k){
- return board->model() == k->value(Constants::KIT_BOARD_MODEL_KEY).toString();
- });
- if (!kit) {
- const auto init = [board, &armGccPath](Kit *k) {
- KitGuard kitGuard(k);
-
- setKitProperties(k, board);
- setKitToolchains(k, armGccPath);
- setKitDebugger(k, armGccPath);
- setKitDevice(k);
- setKitEnvironment(k, board);
- setKitCMakeOptions(k, board);
-
- k->setup();
- k->fix();
- };
- kit = KitManager::registerKit(init);
- }
- return kit;
-}
-
void McuSupportOptionsPage::apply()
{
for (auto package : m_options->packages)
@@ -723,7 +166,7 @@ void McuSupportOptionsPage::apply()
using namespace ProjectExplorer;
for (auto board : validBoards)
- boardKit(board, m_options->toolchainPackage->path());
+ m_options->kit(board);
}
void McuSupportOptionsPage::finish()