BareMetal: Allow to manage configurations of HW GDB servers

The user has only one possibility to setup of the remote GDB server
when a new device is created (or to modify it for existing device).
It is possible only in the host/port fields for connection to the
GDB server. It is a little inconvenient for the user. If the user
wants to use other configuration of the GDB server, then need every
time to edit the current configuration.

Improving this it is introduction a new concept with a new entity
named as "GDB server provider". Now to the device debugging purpose
the user can choose any of the GDB provider from the list (by analogy
with toolchain and so on). Each configuration of GDB provider is
created by the user manually on the new "GDB Server Provider" options
page. This can be made before or after creation of device.

A GDB server provider can work in three startup modes (depends on
implementation of concrete provider):

1) NoStartup mode.

This means that we do not want to startup a provider, we just trying
to connect to the already started GDB provider server. This mode uses
the TCP/IP connection with manually specifying of remote host and port.

2) StartupOnNetwork mode.

This means that we want to launch of the GDB provider automatically
before connect to it in process of remote debugging. This mode also
uses the TCP/IP protocol. In addition to it, a GDB provider can has
additional options which are contains a paths to provider executable
file, to configuration files and so on (it is depends on concrete
provider implementation). This mode (with NoStartup) covers about 90%
of usecase, and is supported by most set of the GDB server providers.

3) StartupOnPipe mode.

This is similar to StartupOnNetwork mode and we also automatically
starts the GDB server provider before debugging. But in this case is
used the Pipe mode instead of TCP/IP. Not each of the GDB provider
can support debugging via pipes.

This patch has concrete implementations for a following set of the
GDB server providers:

* "Default" provider which supports only the NoStartup mode.

* "Open On-Chip Debugger" (http://openocd.sourceforge.net/)
  provider which supports all modes.

* "STLinkUtil" (https://github.com/texane/stlink)
  provider which supports NoStartup and StartupOnNetwork modes.

Tested on Windows and Linux with:

* target HW: ARM Stm32F4Discovery board with HW debugger STLink-v2
* provider: OpenOCD v0.8.0 (tested on Windows and Linux)
* provider: STLink-Util (tested on Linux only)
* toolchain: ARM GCC v4.9.2
* debugger: GDB v7.8.1 (with Python support)
* QtCreator with QBS project

Task-number: QTCREATORBUG-13686
Change-Id: I59c775d91b0a4227d931188879850c536290e1ba
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
Denis Shienkov
2014-12-20 19:10:02 +00:00
committed by hjk
parent 18aa49e7c2
commit 165f008dce
34 changed files with 3970 additions and 299 deletions

View File

@@ -13,7 +13,16 @@ SOURCES += baremetalplugin.cpp \
baremetaldeviceconfigurationwizardpages.cpp \
baremetaldeviceconfigurationwizard.cpp \
baremetaldeviceconfigurationwidget.cpp \
baremetaldeviceconfigurationfactory.cpp
baremetaldeviceconfigurationfactory.cpp \
baremetaldebugsupport.cpp \
gdbserverproviderprocess.cpp \
gdbserverproviderssettingspage.cpp \
gdbserverprovider.cpp \
gdbserverproviderchooser.cpp \
gdbserverprovidermanager.cpp \
openocdgdbserverprovider.cpp \
defaultgdbserverprovider.cpp \
stlinkutilgdbserverprovider.cpp
HEADERS += baremetalplugin.h \
baremetalconstants.h \
@@ -26,4 +35,15 @@ HEADERS += baremetalplugin.h \
baremetaldeviceconfigurationfactory.h \
baremetaldeviceconfigurationwidget.h \
baremetaldeviceconfigurationwizard.h \
baremetaldeviceconfigurationwizardpages.h
baremetaldeviceconfigurationwizardpages.h \
baremetaldebugsupport.h \
gdbserverproviderprocess.h \
gdbserverproviderssettingspage.h \
gdbserverprovider.h \
gdbserverproviderchooser.h \
gdbserverprovidermanager.h \
openocdgdbserverprovider.h \
defaultgdbserverprovider.h \
stlinkutilgdbserverprovider.h
RESOURCES = baremetal.qrc

View File

@@ -13,6 +13,7 @@ QtcPlugin {
Depends { name: "QtSupport" }
files: [
"baremetal.qrc",
"baremetalconstants.h",
"baremetaldevice.cpp", "baremetaldevice.h",
"baremetaldeviceconfigurationfactory.cpp", "baremetaldeviceconfigurationfactory.h",
@@ -25,5 +26,14 @@ QtcPlugin {
"baremetalrunconfigurationfactory.cpp", "baremetalrunconfigurationfactory.h",
"baremetalrunconfigurationwidget.cpp", "baremetalrunconfigurationwidget.h",
"baremetalruncontrolfactory.cpp", "baremetalruncontrolfactory.h",
"baremetaldebugsupport.cpp", "baremetaldebugsupport.h",
"gdbserverproviderprocess.cpp", "gdbserverproviderprocess.h",
"gdbserverproviderssettingspage.cpp", "gdbserverproviderssettingspage.h",
"gdbserverprovider.cpp", "gdbserverprovider.h",
"gdbserverproviderchooser.cpp", "gdbserverproviderchooser.h",
"gdbserverprovidermanager.cpp", "gdbserverprovidermanager.h",
"openocdgdbserverprovider.cpp", "openocdgdbserverprovider.h",
"defaultgdbserverprovider.cpp", "defaultgdbserverprovider.h",
"stlinkutilgdbserverprovider.cpp", "stlinkutilgdbserverprovider.h",
]
}

View File

@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/baremetal">
<file>images/QtBareMetal.png</file>
</qresource>
</RCC>

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -39,8 +40,18 @@ const char BareMetalOsType[] = "BareMetalOsType";
const char ACTION_ID[] = "BareMetal.Action";
const char MENU_ID[] = "BareMetal.Menu";
const char BAREMETAL_SETTINGS_CATEGORY[] = "ZZ.BareMetal";
const char BAREMETAL_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("BareMetal", "BareMetal");
const char BAREMETAL_SETTINGS_CATEGORY_ICON[] = ":/baremetal/images/QtBareMetal.png";
const char GDB_PROVIDERS_SETTINGS_ID[] = "AA.BareMetal.GdbServerProvidersOptions";
// Debugger Server Provider Ids
const char OPENOCD_PROVIDER_ID[] = "BareMetal.GdbServerProvider.OpenOcd";
const char DEFAULT_PROVIDER_ID[] = "BareMetal.GdbServerProvider.Default";
const char STLINK_UTIL_PROVIDER_ID[] = "BareMetal.GdbServerProvider.STLinkUtil";
} // namespace BareMetal
} // namespace Constants
#endif // BAREMETALCONSTANTS_H

View File

@@ -0,0 +1,202 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "baremetaldebugsupport.h"
#include "baremetalrunconfiguration.h"
#include "baremetaldevice.h"
#include "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
#include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
namespace BareMetal {
namespace Internal {
BareMetalDebugSupport::BareMetalDebugSupport(
const ProjectExplorer::IDevice::ConstPtr device,
Debugger::DebuggerRunControl *runControl)
: QObject(runControl)
, m_appRunner(new ProjectExplorer::DeviceApplicationRunner(this))
, m_runControl(runControl)
, m_device(device)
, m_state(BareMetalDebugSupport::Inactive)
{
Q_ASSERT(runControl);
connect(m_runControl, &Debugger::DebuggerRunControl::requestRemoteSetup,
this, &BareMetalDebugSupport::remoteSetupRequested);
connect(runControl, &Debugger::DebuggerRunControl::finished,
this, &BareMetalDebugSupport::debuggingFinished);
}
BareMetalDebugSupport::~BareMetalDebugSupport()
{
setFinished();
}
void BareMetalDebugSupport::remoteSetupRequested()
{
QTC_ASSERT(m_state == Inactive, return);
startExecution();
}
void BareMetalDebugSupport::debuggingFinished()
{
setFinished();
reset();
}
void BareMetalDebugSupport::remoteOutputMessage(const QByteArray &output)
{
QTC_ASSERT(m_state == Inactive || m_state == Running, return);
showMessage(QString::fromUtf8(output), Debugger::AppOutput);
}
void BareMetalDebugSupport::remoteErrorOutputMessage(const QByteArray &output)
{
QTC_ASSERT(m_state == Inactive, return);
showMessage(QString::fromUtf8(output), Debugger::AppError);
// FIXME: Should we here parse an outputn?
}
void BareMetalDebugSupport::remoteProcessStarted()
{
QTC_ASSERT(m_state == StartingRunner, return);
adapterSetupDone();
}
void BareMetalDebugSupport::appRunnerFinished(bool success)
{
if (m_state == Inactive)
return;
if (m_state == Running) {
if (!success)
m_runControl->notifyInferiorIll();
} else if (m_state == StartingRunner) {
Debugger::RemoteSetupResult result;
result.success = false;
result.reason = tr("Debugging failed.");
m_runControl->notifyEngineRemoteSetupFinished(result);
}
reset();
}
void BareMetalDebugSupport::progressReport(const QString &progressOutput)
{
showMessage(progressOutput + QLatin1Char('\n'), Debugger::LogStatus);
}
void BareMetalDebugSupport::appRunnerError(const QString &error)
{
if (m_state == Running) {
showMessage(error, Debugger::AppError);
m_runControl->notifyInferiorIll();
} else if (m_state != Inactive) {
adapterSetupFailed(error);
}
}
void BareMetalDebugSupport::adapterSetupDone()
{
m_state = Running;
Debugger::RemoteSetupResult result;
result.success = true;
m_runControl->notifyEngineRemoteSetupFinished(result);
}
void BareMetalDebugSupport::adapterSetupFailed(const QString &error)
{
debuggingFinished();
Debugger::RemoteSetupResult result;
result.success = false;
result.reason = tr("Initial setup failed: %1").arg(error);
m_runControl->notifyEngineRemoteSetupFinished(result);
}
void BareMetalDebugSupport::startExecution()
{
auto dev = qSharedPointerCast<const BareMetalDevice>(m_device);
QTC_ASSERT(dev, return);
const GdbServerProvider *p = GdbServerProviderManager::instance()->findProvider(
dev->gdbServerProviderId());
QTC_ASSERT(p, return);
m_state = StartingRunner;
showMessage(tr("Starting GDB server...") + QLatin1Char('\n'), Debugger::LogStatus);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteStderr,
this, &BareMetalDebugSupport::remoteErrorOutputMessage);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteStdout,
this, &BareMetalDebugSupport::remoteOutputMessage);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteProcessStarted,
this, &BareMetalDebugSupport::remoteProcessStarted);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::finished,
this, &BareMetalDebugSupport::appRunnerFinished);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::reportProgress,
this, &BareMetalDebugSupport::progressReport);
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::reportError,
this, &BareMetalDebugSupport::appRunnerError);
const QString cmd = p->executable();
const QStringList args = p->arguments();
m_appRunner->start(m_device, cmd, args);
}
void BareMetalDebugSupport::setFinished()
{
if (m_state == Inactive)
return;
if (m_state == Running)
m_appRunner->stop();
m_state = Inactive;
}
void BareMetalDebugSupport::reset()
{
m_appRunner->disconnect(this);
m_state = Inactive;
}
void BareMetalDebugSupport::showMessage(const QString &msg, int channel)
{
if (m_state != Inactive)
m_runControl->showMessage(msg, channel);
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 BAREMETALDEBUGSUPPORT_H
#define BAREMETALDEBUGSUPPORT_H
#include <QObject>
#include <QPointer>
#include <projectexplorer/devicesupport/idevice.h>
namespace Debugger { class DebuggerRunControl; }
namespace ProjectExplorer {
class DeviceApplicationRunner;
class IDevice;
}
namespace BareMetal {
namespace Internal {
class GdbServerProvider;
class BareMetalRunConfiguration;
class BareMetalDebugSupport : public QObject
{
Q_OBJECT
public:
explicit BareMetalDebugSupport(const ProjectExplorer::IDevice::ConstPtr device,
Debugger::DebuggerRunControl *runControl);
~BareMetalDebugSupport();
private slots:
void remoteSetupRequested();
void debuggingFinished();
void remoteOutputMessage(const QByteArray &output);
void remoteErrorOutputMessage(const QByteArray &output);
void remoteProcessStarted();
void appRunnerFinished(bool success);
void progressReport(const QString &progressOutput);
void appRunnerError(const QString &error);
private:
enum State { Inactive, StartingRunner, Running };
void adapterSetupDone();
void adapterSetupFailed(const QString &error);
void startExecution();
void setFinished();
void reset();
void showMessage(const QString &msg, int channel);
QPointer<ProjectExplorer::DeviceApplicationRunner> m_appRunner;
const QPointer<Debugger::DebuggerRunControl> m_runControl;
const ProjectExplorer::IDevice::ConstPtr m_device;
BareMetalDebugSupport::State m_state;
};
} // namespace Internal
} // namespace BareMetal
#endif // BAREMETALDEBUGSUPPORT_H

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -30,6 +31,9 @@
#include "baremetaldevice.h"
#include "baremetaldeviceconfigurationwidget.h"
#include "gdbserverproviderprocess.h"
#include <coreplugin/id.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -39,8 +43,7 @@ using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
const char GdbResetKey[] = "GdbResetCommand";
const char GdbCommandsKey[] = "GdbCommands";
const char gdbServerProviderIdKeyC[] = "GdbServerProviderId";
BareMetalDevice::Ptr BareMetalDevice::create()
{
@@ -57,18 +60,26 @@ BareMetalDevice::Ptr BareMetalDevice::create(const BareMetalDevice &other)
return Ptr(new BareMetalDevice(other));
}
QString BareMetalDevice::gdbServerProviderId() const
{
return m_gdbServerProviderId;
}
void BareMetalDevice::setGdbServerProviderId(const QString &id)
{
m_gdbServerProviderId = id;
}
void BareMetalDevice::fromMap(const QVariantMap &map)
{
IDevice::fromMap(map);
setGdbResetCommands(map.value(QLatin1String(GdbResetKey)).toString());
setGdbInitCommands(map.value(QLatin1String(GdbCommandsKey)).toString());
setGdbServerProviderId(map.value(QLatin1String(gdbServerProviderIdKeyC)).toString());
}
QVariantMap BareMetalDevice::toMap() const
{
QVariantMap map = IDevice::toMap();
map.insert(QLatin1String(GdbResetKey), gdbResetCommands());
map.insert(QLatin1String(GdbCommandsKey), gdbInitCommands());
map.insert(QLatin1String(gdbServerProviderIdKeyC), gdbServerProviderId());
return map;
}
@@ -109,6 +120,11 @@ void BareMetalDevice::executeAction(Core::Id actionId, QWidget *parent)
Q_UNUSED(parent);
}
ProjectExplorer::DeviceProcess *BareMetalDevice::createProcess(QObject *parent) const
{
return new GdbServerProviderProcess(sharedFromThis(), parent);
}
BareMetalDevice::BareMetalDevice(const QString &name, Core::Id type, MachineType machineType, Origin origin, Core::Id id)
: IDevice(type, origin, machineType, id)
{
@@ -118,50 +134,7 @@ BareMetalDevice::BareMetalDevice(const QString &name, Core::Id type, MachineType
BareMetalDevice::BareMetalDevice(const BareMetalDevice &other)
: IDevice(other)
{
setGdbResetCommands(other.gdbResetCommands());
setGdbInitCommands(other.gdbInitCommands());
}
QString BareMetalDevice::exampleString()
{
return QLatin1String("<p><i>")
+ QCoreApplication::translate("BareMetal", "Example:")
+ QLatin1String("</i><p>");
}
QString BareMetalDevice::hostLineToolTip()
{
return QLatin1String("<html>")
+ QCoreApplication::translate("BareMetal",
"Enter your hostname like \"localhost\" or \"192.0.2.1\" or "
"a command which must support GDB pipelining "
"starting with a pipe symbol.")
+ exampleString() + QLatin1String(
"&nbsp;&nbsp;|openocd -c \"gdb_port pipe; "
"log_output openocd.log\" -f boards/myboard.cfg");
}
QString BareMetalDevice::resetCommandToolTip()
{
return QLatin1String("<html>")
+ QCoreApplication::translate("BareMetal",
"Enter the hardware reset command here.<br>"
"The CPU should be halted after this command.")
+ exampleString() + QLatin1String(
"&nbsp;&nbsp;monitor reset halt");
}
QString BareMetalDevice::initCommandToolTip()
{
return QLatin1String("<html>")
+ QCoreApplication::translate("BareMetal",
"Enter commands to reset the board, and write the nonvolatile memory.")
+ exampleString() + QLatin1String(
"&nbsp;&nbsp;set remote hardware-breakpoint-limit 6<br/>"
"&nbsp;&nbsp;set remote hardware-watchpoint-limit 4<br/>"
"&nbsp;&nbsp;monitor reset halt<br/>"
"&nbsp;&nbsp;load<br/>"
"&nbsp;&nbsp;monitor reset halt");
setGdbServerProviderId(other.gdbServerProviderId());
}
} //namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -56,20 +57,15 @@ public:
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const;
QString gdbResetCommands() const { return m_gdbResetCommands; }
void setGdbResetCommands(const QString &gdbResetCommands) { m_gdbResetCommands = gdbResetCommands; }
bool canCreateProcess() const { return true; }
ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const;
QString gdbInitCommands() const { return m_gdbInitCommands; }
void setGdbInitCommands(const QString &gdbCommands) { m_gdbInitCommands=gdbCommands; }
QString gdbServerProviderId() const;
void setGdbServerProviderId(const QString &id);
virtual void fromMap(const QVariantMap &map);
virtual QVariantMap toMap() const;
static QString exampleString();
static QString hostLineToolTip();
static QString initCommandToolTip();
static QString resetCommandToolTip();
protected:
BareMetalDevice() {}
BareMetalDevice(const QString &name, Core::Id type,
@@ -78,8 +74,7 @@ protected:
private:
BareMetalDevice &operator=(const BareMetalDevice &);
QString m_gdbResetCommands;
QString m_gdbInitCommands;
QString m_gdbServerProviderId;
};
} //namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -29,21 +30,14 @@
****************************************************************************/
#include "baremetaldeviceconfigurationwidget.h"
#include "baremetaldevice.h"
#include <coreplugin/variablechooser.h>
#include <ssh/sshconnection.h>
#include "gdbserverproviderchooser.h"
#include "gdbserverprovider.h"
#include <utils/qtcassert.h>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QSpinBox>
#include <QPlainTextEdit>
using namespace Core;
using namespace QSsh;
namespace BareMetal {
namespace Internal {
@@ -52,77 +46,31 @@ BareMetalDeviceConfigurationWidget::BareMetalDeviceConfigurationWidget(
const ProjectExplorer::IDevice::Ptr &deviceConfig, QWidget *parent)
: IDeviceWidget(deviceConfig, parent)
{
SshConnectionParameters sshParams = device()->sshParameters();
QSharedPointer<BareMetalDevice> p = qSharedPointerCast<BareMetalDevice>(device());
QTC_ASSERT(!p.isNull(), return);
const auto dev = qSharedPointerCast<const BareMetalDevice>(device());
QTC_ASSERT(dev, return);
m_gdbHostLineEdit = new QLineEdit(this);
m_gdbHostLineEdit->setText(sshParams.host);
m_gdbHostLineEdit->setToolTip(BareMetalDevice::hostLineToolTip());
m_gdbPortSpinBox = new QSpinBox(this);
m_gdbPortSpinBox->setRange(1, 65535);
m_gdbPortSpinBox->setValue(sshParams.port);
m_gdbInitCommandsTextEdit = new QPlainTextEdit(this);
m_gdbInitCommandsTextEdit->setPlainText(p->gdbInitCommands());
m_gdbInitCommandsTextEdit->setToolTip(BareMetalDevice::initCommandToolTip());
m_gdbResetCommandsTextEdit = new QPlainTextEdit(this);
m_gdbResetCommandsTextEdit->setPlainText(p->gdbResetCommands());
m_gdbResetCommandsTextEdit->setToolTip(BareMetalDevice::resetCommandToolTip());
QFormLayout *formLayout = new QFormLayout(this);
auto formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
formLayout->addRow(tr("GDB host:"), m_gdbHostLineEdit);
formLayout->addRow(tr("GDB port:"), m_gdbPortSpinBox);
formLayout->addRow(tr("Init commands:"), m_gdbInitCommandsTextEdit);
formLayout->addRow(tr("Reset commands:"), m_gdbResetCommandsTextEdit);
auto chooser = new VariableChooser(this);
chooser->addSupportedWidget(m_gdbResetCommandsTextEdit);
chooser->addSupportedWidget(m_gdbInitCommandsTextEdit);
m_gdbServerProviderChooser = new GdbServerProviderChooser(this);
m_gdbServerProviderChooser->populate();
m_gdbServerProviderChooser->setCurrentProviderId(dev->gdbServerProviderId());
formLayout->addRow(tr("GDB server provider:"), m_gdbServerProviderChooser);
connect(m_gdbHostLineEdit, SIGNAL(editingFinished()), SLOT(hostnameChanged()));
connect(m_gdbPortSpinBox, SIGNAL(valueChanged(int)), SLOT(portChanged()));
connect(m_gdbResetCommandsTextEdit, SIGNAL(textChanged()),SLOT(gdbResetCommandsChanged()));
connect(m_gdbInitCommandsTextEdit, SIGNAL(textChanged()), SLOT(gdbInitCommandsChanged()));
connect(m_gdbServerProviderChooser, &GdbServerProviderChooser::providerChanged,
this, &BareMetalDeviceConfigurationWidget::gdbServerProviderChanged);
}
void BareMetalDeviceConfigurationWidget::hostnameChanged()
void BareMetalDeviceConfigurationWidget::gdbServerProviderChanged()
{
SshConnectionParameters sshParams = device()->sshParameters();
sshParams.host = m_gdbHostLineEdit->text().trimmed();
device()->setSshParameters(sshParams);
}
void BareMetalDeviceConfigurationWidget::portChanged()
{
SshConnectionParameters sshParams = device()->sshParameters();
sshParams.port = m_gdbPortSpinBox->value();
device()->setSshParameters(sshParams);
}
void BareMetalDeviceConfigurationWidget::gdbResetCommandsChanged()
{
QSharedPointer<BareMetalDevice> p = qSharedPointerCast<BareMetalDevice>(device());
QTC_ASSERT(!p.isNull(), return);
p->setGdbResetCommands(m_gdbResetCommandsTextEdit->toPlainText().trimmed());
}
void BareMetalDeviceConfigurationWidget::gdbInitCommandsChanged()
{
QSharedPointer<BareMetalDevice> p = qSharedPointerCast<BareMetalDevice>(device());
QTC_ASSERT(!p.isNull(), return);
p->setGdbInitCommands(m_gdbInitCommandsTextEdit->toPlainText());
auto dev = qSharedPointerCast<BareMetalDevice>(device());
QTC_ASSERT(dev, return);
dev->setGdbServerProviderId(m_gdbServerProviderChooser->currentProviderId());
}
void BareMetalDeviceConfigurationWidget::updateDeviceFromUi()
{
hostnameChanged();
portChanged();
gdbResetCommandsChanged();
gdbInitCommandsChanged();
gdbServerProviderChanged();
}
} // namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -33,15 +34,13 @@
#include <projectexplorer/devicesupport/idevicewidget.h>
QT_BEGIN_NAMESPACE
class QLineEdit;
class QSpinBox;
class QPlainTextEdit;
QT_END_NAMESPACE
#include <QPointer>
namespace BareMetal {
namespace Internal {
class GdbServerProviderChooser;
class BareMetalDeviceConfigurationWidget
: public ProjectExplorer::IDeviceWidget
{
@@ -52,19 +51,12 @@ public:
const ProjectExplorer::IDevice::Ptr &deviceConfig, QWidget *parent = 0);
private slots:
void hostnameChanged();
void portChanged();
void gdbResetCommandsChanged();
void gdbInitCommandsChanged();
void gdbServerProviderChanged();
private:
void updateDeviceFromUi();
void initGui();
QLineEdit *m_gdbHostLineEdit;
QSpinBox *m_gdbPortSpinBox;
QPlainTextEdit *m_gdbResetCommandsTextEdit;
QPlainTextEdit *m_gdbInitCommandsTextEdit;
QPointer<GdbServerProviderChooser> m_gdbServerProviderChooser;
};
} // namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -32,9 +33,6 @@
#include "baremetaldeviceconfigurationwizardpages.h"
#include "baremetaldevice.h"
#include "baremetalconstants.h"
#include "ssh/sshconnection.h"
using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
@@ -50,19 +48,14 @@ BareMetalDeviceConfigurationWizard::BareMetalDeviceConfigurationWizard(QWidget *
m_setupPage->setCommitPage(true);
}
IDevice::Ptr BareMetalDeviceConfigurationWizard::device() const
ProjectExplorer::IDevice::Ptr BareMetalDeviceConfigurationWizard::device() const
{
//sshParams is not really used as ssh parameters but as debugger parameters
QSsh::SshConnectionParameters sshParams;
sshParams.host = m_setupPage->gdbHostname();
sshParams.port = m_setupPage->gdbPort();
BareMetalDevice::Ptr device = BareMetalDevice::create(m_setupPage->configurationName(),
auto dev = BareMetalDevice::create(m_setupPage->configurationName(),
Constants::BareMetalOsType,
IDevice::Hardware);
device->setSshParameters(sshParams);
device->setGdbResetCommands(m_setupPage->gdbResetCommands());
device->setGdbInitCommands(m_setupPage->gdbInitCommands());
return device;
ProjectExplorer::IDevice::Hardware);
dev->setGdbServerProviderId(m_setupPage->gdbServerProviderId());
return dev;
}
} // namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -31,66 +32,35 @@
#include "baremetaldeviceconfigurationwizardpages.h"
#include "baremetaldevice.h"
#include "gdbserverproviderchooser.h"
#include <coreplugin/variablechooser.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <QFormLayout>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QSpinBox>
using namespace Core;
namespace BareMetal {
namespace Internal {
BareMetalDeviceConfigurationWizardSetupPage::BareMetalDeviceConfigurationWizardSetupPage(QWidget *parent)
BareMetalDeviceConfigurationWizardSetupPage::BareMetalDeviceConfigurationWizardSetupPage(
QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Set up GDB Server or Hardware Debugger"));
m_nameLineEdit = new QLineEdit(this);
m_hostNameLineEdit = new QLineEdit(this);
m_hostNameLineEdit->setToolTip(BareMetalDevice::hostLineToolTip());
m_hostNameLineEdit->setText(QLatin1String(
"|openocd -c \"gdb_port pipe\" -c \"log_output openocd.log;\" "
"-f board/stm3241g_eval_stlink.cfg"));
m_portSpinBox = new QSpinBox(this);
m_portSpinBox->setRange(1, 65535);
m_portSpinBox->setValue(3333);
m_gdbInitCommandsPlainTextEdit = new QPlainTextEdit(this);
m_gdbInitCommandsPlainTextEdit->setToolTip(BareMetalDevice::initCommandToolTip());
m_gdbInitCommandsPlainTextEdit->setPlainText(QLatin1String(
"set remote hardware-breakpoint-limit 6\n"
"set remote hardware-watchpoint-limit 4\n"
"monitor reset halt\n"
"load\n"
"monitor reset halt"));
m_gdbResetCommandsTextEdit = new QPlainTextEdit(this);
m_gdbResetCommandsTextEdit->setToolTip(BareMetalDevice::resetCommandToolTip());
m_gdbResetCommandsTextEdit->setPlainText(QLatin1String("monitor reset halt"));
QFormLayout *formLayout = new QFormLayout(this);
auto formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
m_nameLineEdit = new QLineEdit(this);
formLayout->addRow(tr("Name:"), m_nameLineEdit);
formLayout->addRow(tr("GDB host:"), m_hostNameLineEdit);
formLayout->addRow(tr("GDB port:"), m_portSpinBox);
formLayout->addRow(tr("Init commands:"), m_gdbInitCommandsPlainTextEdit);
formLayout->addRow(tr("Reset commands:"), m_gdbResetCommandsTextEdit);
m_gdbServerProviderChooser = new GdbServerProviderChooser(false, this);
m_gdbServerProviderChooser->populate();
formLayout->addRow(tr("GDB server provider:"), m_gdbServerProviderChooser);
connect(m_nameLineEdit, SIGNAL(textChanged(QString)), SIGNAL(completeChanged()));
connect(m_hostNameLineEdit, SIGNAL(textChanged(QString)), SIGNAL(completeChanged()));
connect(m_portSpinBox, SIGNAL(valueChanged(int)), SIGNAL(completeChanged()));
connect(m_gdbResetCommandsTextEdit, SIGNAL(textChanged()), SIGNAL(completeChanged()));
connect(m_gdbInitCommandsPlainTextEdit, SIGNAL(textChanged()), SIGNAL(completeChanged()));
auto chooser = new VariableChooser(this);
chooser->addSupportedWidget(m_gdbResetCommandsTextEdit);
chooser->addSupportedWidget(m_gdbInitCommandsPlainTextEdit);
connect(m_nameLineEdit, SIGNAL(textChanged(QString)),
SIGNAL(completeChanged()));
connect(m_gdbServerProviderChooser, &GdbServerProviderChooser::providerChanged,
this, &QWizardPage::completeChanged);
}
void BareMetalDeviceConfigurationWizardSetupPage::initializePage()
@@ -108,24 +78,9 @@ QString BareMetalDeviceConfigurationWizardSetupPage::configurationName() const
return m_nameLineEdit->text().trimmed();
}
QString BareMetalDeviceConfigurationWizardSetupPage::gdbHostname() const
QString BareMetalDeviceConfigurationWizardSetupPage::gdbServerProviderId() const
{
return m_hostNameLineEdit->text().trimmed();
}
quint16 BareMetalDeviceConfigurationWizardSetupPage::gdbPort() const
{
return quint16(m_portSpinBox->value());
}
QString BareMetalDeviceConfigurationWizardSetupPage::gdbResetCommands() const
{
return m_gdbResetCommandsTextEdit->toPlainText().trimmed();
}
QString BareMetalDeviceConfigurationWizardSetupPage::gdbInitCommands() const
{
return m_gdbInitCommandsPlainTextEdit->toPlainText().trimmed();
return m_gdbServerProviderChooser->currentProviderId();
}
QString BareMetalDeviceConfigurationWizardSetupPage::defaultConfigurationName() const

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -31,17 +32,19 @@
#ifndef BAREMETALDEVICECONFIGURATIONWIZARDPAGES_H
#define BAREMETALDEVICECONFIGURATIONWIZARDPAGES_H
#include <QPointer>
#include <QWizardPage>
QT_BEGIN_NAMESPACE
class QLineEdit;
class QSpinBox;
class QPlainTextEdit;
QT_END_NAMESPACE
namespace BareMetal {
namespace Internal {
class GdbServerProviderChooser;
class BareMetalDeviceConfigurationWizardSetupPage : public QWizardPage
{
Q_OBJECT
@@ -52,19 +55,13 @@ public:
void initializePage();
bool isComplete() const;
QString configurationName() const;
QString gdbHostname() const;
quint16 gdbPort() const;
QString gdbResetCommands() const;
QString gdbInitCommands() const;
QString gdbServerProviderId() const;
virtual QString defaultConfigurationName() const;
private:
QLineEdit *m_nameLineEdit;
QLineEdit *m_hostNameLineEdit;
QSpinBox *m_portSpinBox;
QPlainTextEdit *m_gdbResetCommandsTextEdit;
QPlainTextEdit *m_gdbInitCommandsPlainTextEdit;
QPointer<QLineEdit> m_nameLineEdit;
QPointer<GdbServerProviderChooser> m_gdbServerProviderChooser;
};
} // namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -34,6 +35,9 @@
#include "baremetalruncontrolfactory.h"
#include "baremetalrunconfigurationfactory.h"
#include "gdbserverproviderssettingspage.h"
#include "gdbserverprovidermanager.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -67,10 +71,15 @@ bool BareMetalPlugin::initialize(const QStringList &arguments, QString *errorStr
addAutoReleasedObject(new BareMetalDeviceConfigurationFactory);
addAutoReleasedObject(new BareMetalRunControlFactory);
addAutoReleasedObject(new BareMetalRunConfigurationFactory);
addAutoReleasedObject(new GdbServerProvidersSettingsPage);
return true;
}
void BareMetalPlugin::extensionsInitialized()
{
GdbServerProviderManager::instance()->restoreProviders();
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -46,11 +47,10 @@ public:
~BareMetalPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized() { }
void extensionsInitialized();
};
} // namespace Internal
} // namespace BareMetal
#endif // BAREMETAL_H

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -32,6 +33,10 @@
#include "baremetalgdbcommandsdeploystep.h"
#include "baremetalrunconfiguration.h"
#include "baremetaldevice.h"
#include "baremetaldebugsupport.h"
#include "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
#include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerstartparameters.h>
@@ -68,82 +73,97 @@ BareMetalRunControlFactory::~BareMetalRunControlFactory()
bool BareMetalRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const
{
if (mode != NormalRunMode && mode != DebugRunMode && mode != DebugRunModeWithBreakOnMain
&& mode != QmlProfilerRunMode) {
if (mode != NormalRunMode && mode != DebugRunMode && mode != DebugRunModeWithBreakOnMain)
return false;
}
const QByteArray idStr = runConfiguration->id().name();
return runConfiguration->isEnabled() && idStr.startsWith(BareMetalRunConfiguration::IdPrefix);
}
DebuggerStartParameters BareMetalRunControlFactory::startParameters(const BareMetalRunConfiguration *runConfig)
{
DebuggerStartParameters params;
Target *target = runConfig->target();
Kit *k = target->kit();
const BareMetalDevice::ConstPtr device = qSharedPointerCast<const BareMetalDevice>(DeviceKitInformation::device(k));
QTC_ASSERT(device, return params);
params.sysRoot = SysRootKitInformation::sysRoot(k).toString();
params.debuggerCommand = DebuggerKitInformation::debuggerCommand(k).toString();
if (ToolChain *tc = ToolChainKitInformation::toolChain(k))
params.toolChainAbi = tc->targetAbi();
params.languages |= CppLanguage;
params.processArgs = runConfig->arguments();
params.startMode = AttachToRemoteServer;
params.executable = runConfig->localExecutableFilePath();
params.remoteSetupNeeded = false; //FIXME probably start debugserver with that, how?
params.displayName = runConfig->displayName();
if (const Project *project = target->project()) {
params.projectSourceDirectory = project->projectDirectory().toString();
if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
params.projectBuildDirectory = buildConfig->buildDirectory().toString();
params.projectSourceFiles = project->files(Project::ExcludeGeneratedFiles);
}
if (device->sshParameters().host.startsWith(QLatin1Char('|'))) //gdb pipe mode enabled
params.remoteChannel = device->sshParameters().host;
else
params.remoteChannel = device->sshParameters().host + QLatin1Char(':') + QString::number(device->sshParameters().port);
params.remoteSetupNeeded = false; // qml stuff, not needed
params.commandsAfterConnect = device->gdbInitCommands().toLatin1();
params.commandsForReset = device->gdbResetCommands().toLatin1();
BuildConfiguration *bc = target->activeBuildConfiguration();
BuildStepList *bsl = bc->stepList(BareMetalGdbCommandsDeployStep::stepId());
if (bsl) {
foreach (BuildStep *bs, bsl->steps()) {
BareMetalGdbCommandsDeployStep *ds = qobject_cast<BareMetalGdbCommandsDeployStep *>(bs);
if (ds) {
if (!params.commandsAfterConnect.endsWith("\n"))
params.commandsAfterConnect.append("\n");
params.commandsAfterConnect.append(ds->gdbCommands().toLatin1());
}
}
}
params.useContinueInsteadOfRun = true; //we can't execute as its always running
return params;
}
RunControl *BareMetalRunControlFactory::create(RunConfiguration *runConfiguration,
RunMode mode,
QString *errorMessage)
RunControl *BareMetalRunControlFactory::create(
RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
{
QTC_ASSERT(canRun(runConfiguration, mode), return 0);
BareMetalRunConfiguration *rc = qobject_cast<BareMetalRunConfiguration *>(runConfiguration);
const auto rc = qobject_cast<BareMetalRunConfiguration *>(runConfiguration);
QTC_ASSERT(rc, return 0);
IDevice::ConstPtr dev = DeviceKitInformation::device(rc->target()->kit());
const QString bin = rc->localExecutableFilePath();
if (bin.isEmpty()) {
*errorMessage = tr("Cannot debug: Local executable is not set.");
return 0;
} else if (!QFile::exists(bin)) {
*errorMessage = tr("Cannot debug: Could not find executable for \"%1\".")
.arg(bin);
return 0;
}
const Target *target = rc->target();
QTC_ASSERT(target, return 0);
const Kit *kit = target->kit();
QTC_ASSERT(kit, return 0);
auto dev = qSharedPointerCast<const BareMetalDevice>(DeviceKitInformation::device(kit));
if (!dev) {
*errorMessage = tr("Cannot debug: Kit has no device.");
return 0;
}
DebuggerStartParameters sp = startParameters(rc);
if (!QFile::exists(sp.executable)) {
*errorMessage = QApplication::translate("Core::Internal::ExecuteFilter",
"Could not find executable for \"%1\".")
.arg(sp.executable);
const GdbServerProvider *p = GdbServerProviderManager::instance()->findProvider(
dev->gdbServerProviderId());
if (!p) {
*errorMessage = tr("Cannot debug: Device has no GDB server provider configuration.");
return 0;
}
return DebuggerRunControlFactory::doCreate(sp, runConfiguration, errorMessage);
DebuggerStartParameters sp;
if (const ToolChain *tc = ToolChainKitInformation::toolChain(kit))
sp.toolChainAbi = tc->targetAbi();
if (const Project *project = target->project()) {
sp.projectSourceDirectory = project->projectDirectory().toString();
sp.projectSourceFiles = project->files(Project::ExcludeGeneratedFiles);
if (const BuildConfiguration *bc = target->activeBuildConfiguration()) {
sp.projectBuildDirectory = bc->buildDirectory().toString();
if (const BuildStepList *bsl = bc->stepList(BareMetalGdbCommandsDeployStep::stepId())) {
foreach (const BuildStep *bs, bsl->steps()) {
const auto ds = qobject_cast<const BareMetalGdbCommandsDeployStep *>(bs);
if (ds) {
if (!sp.commandsAfterConnect.endsWith("\n"))
sp.commandsAfterConnect.append("\n");
sp.commandsAfterConnect.append(ds->gdbCommands().toLatin1());
}
}
}
}
}
sp.executable = bin;
sp.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
sp.debuggerCommand = DebuggerKitInformation::debuggerCommand(kit).toString();
sp.languages |= CppLanguage;
sp.processArgs = rc->arguments();
sp.startMode = AttachToRemoteServer;
sp.displayName = rc->displayName();
sp.commandsAfterConnect = p->initCommands().toLatin1();
sp.commandsForReset = p->resetCommands().toLatin1();
sp.remoteChannel = p->channel();
sp.useContinueInsteadOfRun = true;
if (p->startupMode() == GdbServerProvider::StartupOnNetwork)
sp.remoteSetupNeeded = true;
DebuggerRunControl *runControl =
DebuggerRunControlFactory::doCreate(sp, rc, errorMessage);
if (runControl && sp.remoteSetupNeeded) {
const auto debugSupport = new BareMetalDebugSupport(dev, runControl);
Q_UNUSED(debugSupport);
}
return runControl;
}
} // namespace Internal

View File

@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Tim Sander <tim@krieglstein.org>
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -46,7 +47,6 @@ class BareMetalRunControlFactory : public ProjectExplorer::IRunControlFactory
public:
explicit BareMetalRunControlFactory(QObject *parent = 0);
~BareMetalRunControlFactory();
Debugger::DebuggerStartParameters startParameters(const BareMetalRunConfiguration *runConfig);
bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const;
ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration,
ProjectExplorer::RunMode mode,

View File

@@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "defaultgdbserverprovider.h"
#include "baremetalconstants.h"
#include "gdbserverprovidermanager.h"
#include <utils/qtcassert.h>
#include <QFormLayout>
#include <QPlainTextEdit>
namespace BareMetal {
namespace Internal {
static const char hostKeyC[] = "BareMetal.DefaultGdbServerProvider.Host";
static const char portKeyC[] = "BareMetal.DefaultGdbServerProvider.Port";
DefaultGdbServerProvider::DefaultGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::DEFAULT_PROVIDER_ID))
, m_host(QLatin1String("localhost"))
, m_port(3333)
{
}
DefaultGdbServerProvider::DefaultGdbServerProvider(const DefaultGdbServerProvider &other)
: GdbServerProvider(other)
, m_host(other.m_host)
, m_port(other.m_port)
{
}
QString DefaultGdbServerProvider::typeDisplayName() const
{
return DefaultGdbServerProviderFactory::tr("Default");
}
QString DefaultGdbServerProvider::channel() const
{
// Just return as "host:port" form.
return m_host + QLatin1Char(':') + QString::number(m_port);
}
bool DefaultGdbServerProvider::isValid() const
{
if (!GdbServerProvider::isValid())
return false;
if (m_host.isEmpty())
return false;
return true;
}
GdbServerProvider *DefaultGdbServerProvider::clone() const
{
return new DefaultGdbServerProvider(*this);
}
QVariantMap DefaultGdbServerProvider::toMap() const
{
auto data = GdbServerProvider::toMap();
data.insert(QLatin1String(hostKeyC), m_host);
data.insert(QLatin1String(portKeyC), m_port);
return data;
}
bool DefaultGdbServerProvider::fromMap(const QVariantMap &data)
{
if (!GdbServerProvider::fromMap(data))
return false;
m_host = data.value(QLatin1String(hostKeyC)).toString();
m_port = data.value(QLatin1String(portKeyC)).toInt();
return true;
}
bool DefaultGdbServerProvider::operator==(const GdbServerProvider &other) const
{
if (!GdbServerProvider::operator==(other))
return false;
const auto p = static_cast<const DefaultGdbServerProvider *>(&other);
return m_host == p->m_host && m_port == p->m_port;
}
GdbServerProviderConfigWidget *DefaultGdbServerProvider::configurationWidget()
{
return new DefaultGdbServerProviderConfigWidget(this);
}
DefaultGdbServerProviderFactory::DefaultGdbServerProviderFactory()
{
setId(QLatin1String(Constants::DEFAULT_PROVIDER_ID));
setDisplayName(tr("Default"));
}
GdbServerProvider *DefaultGdbServerProviderFactory::create()
{
return new DefaultGdbServerProvider;
}
bool DefaultGdbServerProviderFactory::canRestore(const QVariantMap &data)
{
const auto id = idFromMap(data);
return id.startsWith(QLatin1String(Constants::DEFAULT_PROVIDER_ID)
+ QLatin1Char(':'));
}
GdbServerProvider *DefaultGdbServerProviderFactory::restore(const QVariantMap &data)
{
auto p = new DefaultGdbServerProvider;
auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return 0;
}
DefaultGdbServerProviderConfigWidget::DefaultGdbServerProviderConfigWidget(
DefaultGdbServerProvider *provider)
: GdbServerProviderConfigWidget(provider)
{
Q_ASSERT(provider);
m_hostWidget = new HostWidget(this);
m_mainLayout->addRow(tr("Host:"), m_hostWidget);
m_initCommandsTextEdit = new QPlainTextEdit(this);
m_initCommandsTextEdit->setToolTip(defaultInitCommandsTooltip());
m_mainLayout->addRow(tr("Init commands:"), m_initCommandsTextEdit);
m_resetCommandsTextEdit = new QPlainTextEdit(this);
m_resetCommandsTextEdit->setToolTip(defaultResetCommandsTooltip());
m_mainLayout->addRow(tr("Reset commands:"), m_resetCommandsTextEdit);
addErrorLabel();
setFromProvider();
connect(m_hostWidget, &HostWidget::dataChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_initCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_resetCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
}
void DefaultGdbServerProviderConfigWidget::applyImpl()
{
auto p = static_cast<DefaultGdbServerProvider *>(provider());
Q_ASSERT(p);
p->m_host = m_hostWidget->host();
p->m_port = m_hostWidget->port();
p->setInitCommands(m_initCommandsTextEdit->toPlainText());
p->setResetCommands(m_resetCommandsTextEdit->toPlainText());
}
void DefaultGdbServerProviderConfigWidget::discardImpl()
{
setFromProvider();
}
void DefaultGdbServerProviderConfigWidget::setFromProvider()
{
const auto p = static_cast<DefaultGdbServerProvider *>(provider());
Q_ASSERT(p);
const auto b = blockSignals(true);
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
m_initCommandsTextEdit->setPlainText(p->initCommands());
m_resetCommandsTextEdit->setPlainText(p->resetCommands());
blockSignals(b);
}
} // namespace Internal
} // namespace ProjectExplorer

View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 DEFAULTGDBSERVERPROVIDER_H
#define DEFAULTGDBSERVERPROVIDER_H
#include "gdbserverprovider.h"
namespace BareMetal {
namespace Internal {
class DefaultGdbServerProviderConfigWidget;
class DefaultGdbServerProviderFactory;
class DefaultGdbServerProvider : public GdbServerProvider
{
public:
QString typeDisplayName() const;
QVariantMap toMap() const;
bool fromMap(const QVariantMap &data);
bool operator==(const GdbServerProvider &) const;
GdbServerProviderConfigWidget *configurationWidget();
GdbServerProvider *clone() const;
QString channel() const;
bool isValid() const;
private:
explicit DefaultGdbServerProvider();
explicit DefaultGdbServerProvider(const DefaultGdbServerProvider &);
QString m_host;
quint16 m_port;
friend class DefaultGdbServerProviderConfigWidget;
friend class DefaultGdbServerProviderFactory;
};
class DefaultGdbServerProviderFactory : public GdbServerProviderFactory
{
Q_OBJECT
public:
explicit DefaultGdbServerProviderFactory();
GdbServerProvider *create();
bool canRestore(const QVariantMap &data);
GdbServerProvider *restore(const QVariantMap &data);
GdbServerProviderConfigWidget *configurationWidget(GdbServerProvider *);
};
class DefaultGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
{
Q_OBJECT
public:
explicit DefaultGdbServerProviderConfigWidget(DefaultGdbServerProvider *);
private:
void applyImpl();
void discardImpl();
void setFromProvider();
QPointer<HostWidget> m_hostWidget;
QPointer<QPlainTextEdit> m_initCommandsTextEdit;
QPointer<QPlainTextEdit> m_resetCommandsTextEdit;
};
} // namespace Internal
} // namespace BareMetal
#endif // DEFAULTGDBSERVERPROVIDER_H

View File

@@ -0,0 +1,414 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
#include <utils/qtcassert.h>
#include <utils/environment.h>
#include <QCoreApplication>
#include <QUuid>
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QPlainTextEdit>
namespace BareMetal {
namespace Internal {
const char idKeyC[] = "BareMetal.GdbServerProvider.Id";
const char displayNameKeyC[] = "BareMetal.GdbServerProvider.DisplayName";
const char startupModeKeyC[] = "BareMetal.GdbServerProvider.Mode";
const char initCommandsKeyC[] = "BareMetal.GdbServerProvider.InitCommands";
const char resetCommandsKeyC[] = "BareMetal.GdbServerProvider.ResetCommands";
static QString createId(const QString &id)
{
QString newId = id.left(id.indexOf(QLatin1Char(':')));
newId.append(QLatin1Char(':') + QUuid::createUuid().toString());
return newId;
}
GdbServerProvider::GdbServerProvider(const QString &id)
: m_id(createId(id))
, m_startupMode(NoStartup)
{
}
GdbServerProvider::GdbServerProvider(const GdbServerProvider &other)
: m_id(other.m_id)
, m_startupMode(other.m_startupMode)
, m_initCommands(other.m_initCommands)
, m_resetCommands(other.m_resetCommands)
{
m_displayName = QCoreApplication::translate(
"BareMetal::GdbServerProvider", "Clone of %1")
.arg(other.displayName());
}
GdbServerProvider::~GdbServerProvider()
{
}
QString GdbServerProvider::displayName() const
{
if (m_displayName.isEmpty())
return typeDisplayName();
return m_displayName;
}
void GdbServerProvider::setDisplayName(const QString &name)
{
if (m_displayName == name)
return;
m_displayName = name;
providerUpdated();
}
QString GdbServerProvider::id() const
{
return m_id;
}
GdbServerProvider::StartupMode GdbServerProvider::startupMode() const
{
return m_startupMode;
}
void GdbServerProvider::setStartupMode(StartupMode m)
{
if (m == m_startupMode)
return;
m_startupMode = m;
}
QString GdbServerProvider::initCommands() const
{
return m_initCommands;
}
void GdbServerProvider::setInitCommands(const QString &cmds)
{
if (cmds == m_initCommands)
return;
m_initCommands = cmds;
}
QString GdbServerProvider::resetCommands() const
{
return m_resetCommands;
}
void GdbServerProvider::setResetCommands(const QString &cmds)
{
if (cmds == m_resetCommands)
return;
m_resetCommands = cmds;
}
QString GdbServerProvider::executable() const
{
return QString();
}
QStringList GdbServerProvider::arguments() const
{
return QStringList();
}
bool GdbServerProvider::operator==(const GdbServerProvider &other) const
{
if (this == &other)
return true;
const QString thisId = id().left(id().indexOf(QLatin1Char(':')));
const QString otherId = other.id().left(other.id().indexOf(QLatin1Char(':')));
// We ignore displayname
return thisId == otherId
&& m_startupMode == other.m_startupMode
&& m_initCommands == other.m_initCommands
&& m_resetCommands == other.m_resetCommands
;
}
QVariantMap GdbServerProvider::toMap() const
{
QVariantMap result;
result.insert(QLatin1String(idKeyC), m_id);
result.insert(QLatin1String(displayNameKeyC), m_displayName);
result.insert(QLatin1String(startupModeKeyC), m_startupMode);
result.insert(QLatin1String(initCommandsKeyC), m_initCommands);
result.insert(QLatin1String(resetCommandsKeyC), m_resetCommands);
return result;
}
bool GdbServerProvider::isValid() const
{
return !channel().isNull();
}
bool GdbServerProvider::canStartupMode(StartupMode m) const
{
return m == NoStartup;
}
void GdbServerProvider::providerUpdated()
{
GdbServerProviderManager::instance()->notifyAboutUpdate(this);
}
bool GdbServerProvider::fromMap(const QVariantMap &data)
{
m_id = data.value(QLatin1String(idKeyC)).toString();
m_displayName = data.value(QLatin1String(displayNameKeyC)).toString();
m_startupMode = static_cast<StartupMode>(data.value(QLatin1String(startupModeKeyC)).toInt());
m_initCommands = data.value(QLatin1String(initCommandsKeyC)).toString();
m_resetCommands = data.value(QLatin1String(resetCommandsKeyC)).toString();
return true;
}
QString GdbServerProviderFactory::id() const
{
return m_id;
}
void GdbServerProviderFactory::setId(const QString &id)
{
m_id = id;
}
QString GdbServerProviderFactory::displayName() const
{
return m_displayName;
}
void GdbServerProviderFactory::setDisplayName(const QString &name)
{
m_displayName = name;
}
QString GdbServerProviderFactory::idFromMap(const QVariantMap &data)
{
return data.value(QLatin1String(idKeyC)).toString();
}
void GdbServerProviderFactory::idToMap(QVariantMap &data, const QString id)
{
data.insert(QLatin1String(idKeyC), id);
}
GdbServerProviderConfigWidget::GdbServerProviderConfigWidget(
GdbServerProvider *provider)
: m_provider(provider)
{
Q_ASSERT(provider);
m_mainLayout = new QFormLayout(this);
m_mainLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
m_nameLineEdit = new QLineEdit(this);
m_nameLineEdit->setToolTip(tr("Enter the name of the GDB server provider."));
m_mainLayout->addRow(tr("Name:"), m_nameLineEdit);
m_startupModeComboBox = new QComboBox(this);
m_startupModeComboBox->setToolTip(tr("Choose the desired startup mode "
"of the GDB server provider."));
m_mainLayout->addRow(tr("Startup mode:"), m_startupModeComboBox);
populateStartupModes();
setFromProvider();
connect(m_nameLineEdit, SIGNAL(textChanged(QString)), SIGNAL(dirty()));
connect(m_startupModeComboBox, SIGNAL(currentIndexChanged(int)), SIGNAL(dirty()));
}
void GdbServerProviderConfigWidget::apply()
{
m_provider->setDisplayName(m_nameLineEdit->text());
m_provider->setStartupMode(startupMode());
applyImpl();
}
void GdbServerProviderConfigWidget::discard()
{
m_nameLineEdit->setText(m_provider->displayName());
discardImpl();
}
GdbServerProvider *GdbServerProviderConfigWidget::provider() const
{
return m_provider;
}
void GdbServerProviderConfigWidget::addErrorLabel()
{
if (!m_errorLabel) {
m_errorLabel = new QLabel;
m_errorLabel->setVisible(false);
}
m_mainLayout->addRow(m_errorLabel);
}
GdbServerProvider::StartupMode GdbServerProviderConfigWidget::startupModeFromIndex(
int idx) const
{
return static_cast<GdbServerProvider::StartupMode>(
m_startupModeComboBox->itemData(idx).toInt());
}
GdbServerProvider::StartupMode GdbServerProviderConfigWidget::startupMode() const
{
const int idx = m_startupModeComboBox->currentIndex();
return startupModeFromIndex(idx);
}
void GdbServerProviderConfigWidget::setStartupMode(GdbServerProvider::StartupMode m)
{
for (int idx = 0; idx < m_startupModeComboBox->count(); ++idx) {
if (m == startupModeFromIndex(idx)) {
m_startupModeComboBox->setCurrentIndex(idx);
break;
}
}
}
void GdbServerProviderConfigWidget::populateStartupModes()
{
for (int i = 0; i < GdbServerProvider::StartupModesCount; ++i) {
const auto m = static_cast<GdbServerProvider::StartupMode>(i);
if (!m_provider->canStartupMode(m))
continue;
const int idx = m_startupModeComboBox->count();
m_startupModeComboBox->insertItem(
idx,
(m == GdbServerProvider::NoStartup)
? tr("No startup")
: ((m == GdbServerProvider::StartupOnNetwork)
? tr("Startup in TCP/IP mode")
: tr("Startup in Pipe mode")),
m);
}
}
void GdbServerProviderConfigWidget::setErrorMessage(const QString &m)
{
QTC_ASSERT(m_errorLabel, return);
if (m.isEmpty()) {
clearErrorMessage();
} else {
m_errorLabel->setText(m);
m_errorLabel->setStyleSheet(QLatin1String("background-color: \"red\""));
m_errorLabel->setVisible(true);
}
}
void GdbServerProviderConfigWidget::clearErrorMessage()
{
QTC_ASSERT(m_errorLabel, return);
m_errorLabel->clear();
m_errorLabel->setStyleSheet(QString());
m_errorLabel->setVisible(false);
}
void GdbServerProviderConfigWidget::setFromProvider()
{
const bool b = blockSignals(true);
m_nameLineEdit->setText(m_provider->displayName());
setStartupMode(m_provider->startupMode());
blockSignals(b);
}
QString GdbServerProviderConfigWidget::defaultInitCommandsTooltip()
{
return QCoreApplication::translate("BareMetal",
"Enter GDB commands to reset of the board, "
"and to write the nonvolatile memory.");
}
QString GdbServerProviderConfigWidget::defaultResetCommandsTooltip()
{
return QCoreApplication::translate("BareMetal",
"Enter GDB commands to hardware reset. "
"The MCU should be halted after this commands.");
}
HostWidget::HostWidget(QWidget *parent)
: QWidget(parent)
{
m_hostLineEdit = new QLineEdit(this);
m_hostLineEdit->setToolTip(tr("Enter TCP/IP hostname of the GDB server provider, "
"like \"localhost\" or \"192.0.2.1\"."));
m_portSpinBox = new QSpinBox(this);
m_portSpinBox->setRange(1, 65535);
m_portSpinBox->setToolTip(tr("Enter TCP/IP port which will be listened by "
"the GDB server provider."));
auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_hostLineEdit);
layout->addWidget(m_portSpinBox);
connect(m_hostLineEdit, SIGNAL(textChanged(QString)), SIGNAL(dataChanged()));
connect(m_portSpinBox, SIGNAL(valueChanged(int)), SIGNAL(dataChanged()));
}
void HostWidget::setHost(const QString &host)
{
const bool b = blockSignals(true);
m_hostLineEdit->setText(host);
blockSignals(b);
}
QString HostWidget::host() const
{
return m_hostLineEdit->text();
}
void HostWidget::setPort(const quint16 &port)
{
const bool b = blockSignals(true);
m_portSpinBox->setValue(port);
blockSignals(b);
}
quint16 HostWidget::port() const
{
return m_portSpinBox->value();
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 GDBSERVERPROVIDER_H
#define GDBSERVERPROVIDER_H
#include <QObject>
#include <QPointer>
#include <QVariantMap>
#include <QWidget>
#include <utils/fileutils.h>
QT_BEGIN_NAMESPACE
class QFormLayout;
class QLineEdit;
class QLabel;
class QComboBox;
class QSpinBox;
class QPlainTextEdit;
QT_END_NAMESPACE
namespace BareMetal {
namespace Internal {
class GdbServerProviderConfigWidget;
class GdbServerProviderFactory;
class GdbServerProviderManager;
class GdbServerProvider
{
public:
enum StartupMode {
NoStartup = 0,
StartupOnNetwork,
StartupOnPipe,
StartupModesCount
};
virtual ~GdbServerProvider();
QString displayName() const;
void setDisplayName(const QString &name);
QString id() const;
StartupMode startupMode() const;
QString initCommands() const;
QString resetCommands() const;
virtual bool operator==(const GdbServerProvider &) const;
virtual QString typeDisplayName() const = 0;
virtual GdbServerProviderConfigWidget *configurationWidget() = 0;
virtual QString channel() const = 0;
virtual GdbServerProvider *clone() const = 0;
virtual QVariantMap toMap() const;
virtual QString executable() const;
virtual QStringList arguments() const;
virtual bool isValid() const;
virtual bool canStartupMode(StartupMode) const;
protected:
explicit GdbServerProvider(const QString &id);
explicit GdbServerProvider(const GdbServerProvider &);
void setStartupMode(StartupMode);
void setInitCommands(const QString &);
void setResetCommands(const QString &);
void providerUpdated();
virtual bool fromMap(const QVariantMap &data);
private:
QString m_id;
mutable QString m_displayName;
StartupMode m_startupMode;
QString m_initCommands;
QString m_resetCommands;
friend class GdbServerProviderConfigWidget;
};
class GdbServerProviderFactory : public QObject
{
Q_OBJECT
public:
QString id() const;
QString displayName() const;
virtual GdbServerProvider *create() = 0;
virtual bool canRestore(const QVariantMap &data) = 0;
virtual GdbServerProvider *restore(const QVariantMap &data) = 0;
static QString idFromMap(const QVariantMap &data);
static void idToMap(QVariantMap &data, const QString id);
protected:
void setId(const QString &id);
void setDisplayName(const QString &name);
private:
QString m_displayName;
QString m_id;
};
class GdbServerProviderConfigWidget : public QWidget
{
Q_OBJECT
public:
explicit GdbServerProviderConfigWidget(GdbServerProvider *);
GdbServerProvider *provider() const;
void apply();
void discard();
signals:
void dirty();
protected slots:
void setErrorMessage(const QString &);
void clearErrorMessage();
protected:
virtual void applyImpl() = 0;
virtual void discardImpl() = 0;
void addErrorLabel();
GdbServerProvider::StartupMode startupModeFromIndex(int idx) const;
GdbServerProvider::StartupMode startupMode() const;
void setStartupMode(GdbServerProvider::StartupMode mode);
void populateStartupModes();
static QString defaultInitCommandsTooltip();
static QString defaultResetCommandsTooltip();
QPointer<QFormLayout> m_mainLayout;
QPointer<QLineEdit> m_nameLineEdit;
QPointer<QComboBox> m_startupModeComboBox;
private:
void setFromProvider();
GdbServerProvider *m_provider;
QPointer<QLabel> m_errorLabel;
};
class HostWidget : public QWidget
{
Q_OBJECT
public:
explicit HostWidget(QWidget *parent = 0);
void setHost(const QString &host);
QString host() const;
void setPort(const quint16 &port);
quint16 port() const;
signals:
void dataChanged();
private:
QPointer<QLineEdit> m_hostLineEdit;
QPointer<QSpinBox> m_portSpinBox;
};
} // namespace Internal
} // namespace BareMetal
#endif // GDBSERVERPROVIDER_H

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "gdbserverproviderchooser.h"
#include "gdbserverprovidermanager.h"
#include "gdbserverprovider.h"
#include "baremetalconstants.h"
#include <coreplugin/icore.h>
#include <QComboBox>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSettings>
namespace BareMetal {
namespace Internal {
GdbServerProviderChooser::GdbServerProviderChooser(
bool useManageButton, QWidget *parent)
: QWidget(parent)
{
m_chooser = new QComboBox(this);
m_chooser->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
m_manageButton = new QPushButton(tr("Manage..."), this);
m_manageButton->setEnabled(useManageButton);
m_manageButton->setVisible(useManageButton);
auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_chooser);
layout->addWidget(m_manageButton);
setFocusProxy(m_manageButton);
connect(m_chooser, SIGNAL(currentIndexChanged(int)),
SLOT(currentIndexChanged(int)));
connect(m_manageButton, SIGNAL(clicked()),
SLOT(manageButtonClicked()));
connect(GdbServerProviderManager::instance(), SIGNAL(providersChanged()),
SLOT(populate()));
}
QString GdbServerProviderChooser::currentProviderId() const
{
const int idx = m_chooser->currentIndex();
return qvariant_cast<QString>(m_chooser->itemData(idx));
}
void GdbServerProviderChooser::setCurrentProviderId(const QString &id)
{
for (int i = 0; i < m_chooser->count(); ++i) {
if (id != qvariant_cast<QString>(m_chooser->itemData(i)))
continue;
m_chooser->setCurrentIndex(i);
}
}
void GdbServerProviderChooser::manageButtonClicked()
{
Core::ICore::showOptionsDialog(Constants::BAREMETAL_SETTINGS_CATEGORY,
Constants::GDB_PROVIDERS_SETTINGS_ID, this);
}
void GdbServerProviderChooser::currentIndexChanged(int index)
{
Q_UNUSED(index);
emit providerChanged();
}
bool GdbServerProviderChooser::providerMatches(const GdbServerProvider *provider) const
{
return provider->isValid();
}
QString GdbServerProviderChooser::providerText(const GdbServerProvider *provider) const
{
return provider->displayName();
}
void GdbServerProviderChooser::populate()
{
const bool b = m_chooser->blockSignals(true);
m_chooser->clear();
m_chooser->addItem(tr("None"));
foreach (const GdbServerProvider *p,
GdbServerProviderManager::instance()->providers()) {
if (!providerMatches(p))
continue;
m_chooser->addItem(providerText(p), qVariantFromValue(p->id()));
}
m_chooser->blockSignals(b);
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 GDBSERVERPROVIDERCHOOSER_H
#define GDBSERVERPROVIDERCHOOSER_H
#include <QPointer>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QComboBox;
class QPushButton;
QT_END_NAMESPACE
namespace Core { class Id; }
namespace BareMetal {
namespace Internal {
class GdbServerProvider;
class GdbServerProviderChooser : public QWidget
{
Q_OBJECT
public:
explicit GdbServerProviderChooser(
bool useManageButton = true, QWidget *parent = 0);
QString currentProviderId() const;
void setCurrentProviderId(const QString &id);
signals:
void providerChanged();
public slots:
void populate();
private slots:
void currentIndexChanged(int index);
void manageButtonClicked();
protected:
bool providerMatches(const GdbServerProvider *) const;
QString providerText(const GdbServerProvider *) const;
private:
QPointer<QComboBox> m_chooser;
QPointer<QPushButton> m_manageButton;
};
} // namespace Internal
} // namespace BareMetal
#endif // GDBSERVERPROVIDERCHOOSER_H

View File

@@ -0,0 +1,215 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "gdbserverprovidermanager.h"
#include "gdbserverprovider.h"
#include "openocdgdbserverprovider.h"
#include "defaultgdbserverprovider.h"
#include "stlinkutilgdbserverprovider.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/persistentsettings.h>
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <QDir>
namespace BareMetal {
namespace Internal {
const char dataKeyC[] = "GdbServerProvider.";
const char countKeyC[] = "GdbServerProvider.Count";
const char fileVersionKeyC[] = "Version";
const char fileNameKeyC[] = "/qtcreator/gdbserverproviders.xml";
static Utils::FileName settingsFileName(const QString &path)
{
const QFileInfo settingsLocation(Core::ICore::settings()->fileName());
return Utils::FileName::fromString(settingsLocation.absolutePath() + path);
}
static QList<GdbServerProviderFactory *> createFactories()
{
QList<GdbServerProviderFactory *> result;
result << new DefaultGdbServerProviderFactory
<< new OpenOcdGdbServerProviderFactory
<< new StLinkUtilGdbServerProviderFactory
;
return result;
}
GdbServerProviderManager *GdbServerProviderManager::m_instance = 0;
GdbServerProviderManager::GdbServerProviderManager(QObject *parent)
: QObject(parent)
, m_configFile(settingsFileName(QLatin1String(fileNameKeyC)))
, m_factories(createFactories())
{
m_writer = new Utils::PersistentSettingsWriter(
m_configFile, QLatin1String("QtCreatorGdbServerProviders"));
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
this, &GdbServerProviderManager::saveProviders);
connect(this, SIGNAL(providerAdded(GdbServerProvider*)),
SIGNAL(providersChanged()));
connect(this, SIGNAL(providerRemoved(GdbServerProvider*)),
SIGNAL(providersChanged()));
connect(this, SIGNAL(providerUpdated(GdbServerProvider*)),
SIGNAL(providersChanged()));
}
GdbServerProviderManager::~GdbServerProviderManager()
{
qDeleteAll(m_providers);
m_providers.clear();
delete m_writer;
m_instance = 0;
}
GdbServerProviderManager *GdbServerProviderManager::instance()
{
if (!m_instance)
m_instance = new GdbServerProviderManager;
return m_instance;
}
void GdbServerProviderManager::restoreProviders()
{
Utils::PersistentSettingsReader reader;
if (!reader.load(m_configFile))
return;
const QVariantMap data = reader.restoreValues();
const int version = data.value(QLatin1String(fileVersionKeyC), 0).toInt();
if (version < 1)
return;
const int count = data.value(QLatin1String(countKeyC), 0).toInt();
for (int i = 0; i < count; ++i) {
const QString key = QString::fromLatin1(dataKeyC) + QString::number(i);
if (!data.contains(key))
break;
const QVariantMap map = data.value(key).toMap();
bool restored = false;
foreach (GdbServerProviderFactory *f, m_factories) {
if (f->canRestore(map)) {
if (GdbServerProvider *p = f->restore(map)) {
registerProvider(p);
restored = true;
break;
}
}
}
if (!restored)
qWarning("Warning: Unable to restore provider '%s' stored in %s.",
qPrintable(GdbServerProviderFactory::idFromMap(map)),
qPrintable(m_configFile.toUserOutput()));
}
emit providersLoaded();
}
void GdbServerProviderManager::saveProviders()
{
QVariantMap data;
data.insert(QLatin1String(fileVersionKeyC), 1);
int count = 0;
foreach (const GdbServerProvider *p, m_providers) {
if (p->isValid()) {
const QVariantMap tmp = p->toMap();
if (tmp.isEmpty())
continue;
const QString key = QString::fromLatin1(dataKeyC) + QString::number(count);
data.insert(key, tmp);
++count;
}
}
data.insert(QLatin1String(countKeyC), count);
m_writer->save(data, Core::ICore::mainWindow());
}
QList<GdbServerProvider *> GdbServerProviderManager::providers() const
{
return m_providers;
}
QList<GdbServerProviderFactory *> GdbServerProviderManager::factories() const
{
return m_factories;
}
GdbServerProvider *GdbServerProviderManager::findProvider(const QString &id) const
{
if (id.isEmpty())
return 0;
return Utils::findOrDefault(m_providers, Utils::equal(&GdbServerProvider::id, id));
}
void GdbServerProviderManager::notifyAboutUpdate(GdbServerProvider *provider)
{
if (!provider || !m_providers.contains(provider))
return;
emit providerUpdated(provider);
}
bool GdbServerProviderManager::registerProvider(GdbServerProvider *provider)
{
if (!provider || m_providers.contains(provider))
return true;
foreach (const GdbServerProvider *current, m_providers) {
if (*provider == *current)
return false;
QTC_ASSERT(current->id() != provider->id(), return false);
}
m_providers.append(provider);
emit providerAdded(provider);
return true;
}
void GdbServerProviderManager::deregisterProvider(GdbServerProvider *provider)
{
if (!provider || !m_providers.contains(provider))
return;
m_providers.removeOne(provider);
emit providerRemoved(provider);
delete provider;
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 GDBSERVERPROVIDERMANAGER_H
#define GDBSERVERPROVIDERMANAGER_H
#include <QObject>
#include <QList>
#include <utils/fileutils.h>
namespace Utils { class PersistentSettingsWriter; }
namespace BareMetal {
namespace Internal {
class BareMetalPlugin;
class GdbServerProvider;
class GdbServerProviderFactory;
class GdbServerProviderManager : public QObject
{
Q_OBJECT
public:
static GdbServerProviderManager *instance();
~GdbServerProviderManager();
QList<GdbServerProvider *> providers() const;
QList<GdbServerProviderFactory *> factories() const;
GdbServerProvider *findProvider(const QString &id) const;
bool registerProvider(GdbServerProvider *);
void deregisterProvider(GdbServerProvider *);
public slots:
void saveProviders();
signals:
void providerAdded(GdbServerProvider *);
void providerRemoved(GdbServerProvider *);
void providerUpdated(GdbServerProvider *);
void providersChanged();
void providersLoaded();
private:
explicit GdbServerProviderManager(QObject *parent = 0);
void restoreProviders();
void notifyAboutUpdate(GdbServerProvider *);
Utils::PersistentSettingsWriter *m_writer;
QList<GdbServerProvider *> m_providers;
const Utils::FileName m_configFile;
const QList<GdbServerProviderFactory *> m_factories;
static GdbServerProviderManager *m_instance;
friend class BareMetalPlugin; // for constructor
friend class GdbServerProvider;
};
} // namespace Internal
} // namespace BareMetal
#endif // GDBSERVERPROVIDERMANAGER_H

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "gdbserverproviderprocess.h"
#include <projectexplorer/devicesupport/idevice.h>
#include <utils/environment.h>
#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
#include <QStringList>
namespace BareMetal {
namespace Internal {
GdbServerProviderProcess::GdbServerProviderProcess(
const QSharedPointer<const ProjectExplorer::IDevice> &device,
QObject *parent)
: ProjectExplorer::DeviceProcess(device, parent)
, m_process(new QProcess(this))
{
connect(m_process, SIGNAL(error(QProcess::ProcessError)),
SIGNAL(error(QProcess::ProcessError)));
connect(m_process, SIGNAL(finished(int)), SIGNAL(finished()));
connect(m_process, &QProcess::readyReadStandardOutput,
this, &ProjectExplorer::DeviceProcess::readyReadStandardOutput);
connect(m_process, &QProcess::readyReadStandardError,
this, &ProjectExplorer::DeviceProcess::readyReadStandardError);
connect(m_process, &QProcess::started,
this, &ProjectExplorer::DeviceProcess::started);
}
void GdbServerProviderProcess::start(const QString &executable, const QStringList &arguments)
{
QTC_ASSERT(m_process->state() == QProcess::NotRunning, return);
m_process->start(executable, arguments);
}
void GdbServerProviderProcess::interrupt()
{
device()->signalOperation()->interruptProcess(Utils::qPidToPid(m_process->pid()));
}
void GdbServerProviderProcess::terminate()
{
m_process->terminate();
}
void GdbServerProviderProcess::kill()
{
m_process->kill();
}
QProcess::ProcessState GdbServerProviderProcess::state() const
{
return m_process->state();
}
QProcess::ExitStatus GdbServerProviderProcess::exitStatus() const
{
return m_process->exitStatus();
}
int GdbServerProviderProcess::exitCode() const
{
return m_process->exitCode();
}
QString GdbServerProviderProcess::errorString() const
{
return m_process->errorString();
}
Utils::Environment GdbServerProviderProcess::environment() const
{
return Utils::Environment(m_process->processEnvironment().toStringList());
}
void GdbServerProviderProcess::setEnvironment(const Utils::Environment &env)
{
m_process->setProcessEnvironment(env.toProcessEnvironment());
}
void GdbServerProviderProcess::setWorkingDirectory(const QString &dir)
{
m_process->setWorkingDirectory(dir);
}
QByteArray GdbServerProviderProcess::readAllStandardOutput()
{
return m_process->readAllStandardOutput();
}
QByteArray GdbServerProviderProcess::readAllStandardError()
{
return m_process->readAllStandardError();
}
qint64 GdbServerProviderProcess::write(const QByteArray &data)
{
return m_process->write(data);
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 GDBSERVERPROVIDERPROCESS_H
#define GDBSERVERPROVIDERPROCESS_H
#include <projectexplorer/devicesupport/deviceprocess.h>
namespace BareMetal {
namespace Internal {
class GdbServerProviderProcess : public ProjectExplorer::DeviceProcess
{
Q_OBJECT
public:
explicit GdbServerProviderProcess(
const QSharedPointer<const ProjectExplorer::IDevice> &device,
QObject *parent = 0);
void start(const QString &executable, const QStringList &arguments);
void interrupt();
void terminate();
void kill();
QProcess::ProcessState state() const;
QProcess::ExitStatus exitStatus() const;
int exitCode() const;
QString errorString() const;
Utils::Environment environment() const;
void setEnvironment(const Utils::Environment &);
void setWorkingDirectory(const QString &);
QByteArray readAllStandardOutput();
QByteArray readAllStandardError();
qint64 write(const QByteArray &data);
private:
QProcess * const m_process;
};
} // namespace Internal
} // namespace BareMetal
#endif // GDBSERVERPROVIDERPROCESS_H

View File

@@ -0,0 +1,621 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "gdbserverproviderssettingspage.h"
#include "gdbserverprovider.h"
#include "baremetalconstants.h"
#include "gdbserverprovidermanager.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <QApplication>
#include <QAction>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QItemSelectionModel>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QSignalMapper>
#include <QSpacerItem>
#include <QTextStream>
#include <QTreeView>
#include <QVBoxLayout>
namespace BareMetal {
namespace Internal {
class GdbServerProviderNode
{
public:
explicit GdbServerProviderNode(GdbServerProviderNode *parent,
GdbServerProvider *provider = 0,
bool changed = false);
~GdbServerProviderNode();
GdbServerProviderNode *parent;
QList<GdbServerProviderNode *> childNodes;
GdbServerProvider *provider;
GdbServerProviderConfigWidget *widget;
bool changed;
};
GdbServerProviderNode::GdbServerProviderNode(
GdbServerProviderNode *parent,
GdbServerProvider *provider,
bool changed)
: parent(parent)
, provider(provider)
, changed(changed)
{
if (parent)
parent->childNodes.append(this);
widget = provider ? provider->configurationWidget() : 0;
}
GdbServerProviderNode::~GdbServerProviderNode()
{
// Do not delete provider, we do not own it.
for (int i = childNodes.size(); --i >= 0; ) {
GdbServerProviderNode *child = childNodes.at(i);
child->parent = 0;
delete child;
}
if (parent)
parent->childNodes.removeOne(this);
}
GdbServerProviderModel::GdbServerProviderModel(QObject *parent)
: QAbstractItemModel(parent)
, m_root(new GdbServerProviderNode(0))
{
const GdbServerProviderManager *manager = GdbServerProviderManager::instance();
connect(manager, &GdbServerProviderManager::providerAdded,
this, &GdbServerProviderModel::addProvider);
connect(manager, &GdbServerProviderManager::providerRemoved,
this, &GdbServerProviderModel::removeProvider);
foreach (GdbServerProvider *p, manager->providers())
addProvider(p);
}
GdbServerProviderModel::~GdbServerProviderModel()
{
delete m_root;
}
QModelIndex GdbServerProviderModel::index(
int row, int column, const QModelIndex &parent) const
{
if (!parent.isValid()) {
if (row >= 0 && row < m_root->childNodes.count())
return createIndex(row, column, m_root->childNodes.at(row));
}
return QModelIndex();
}
QModelIndex GdbServerProviderModel::index(
const QModelIndex &topIdx, const GdbServerProvider *provider) const
{
const GdbServerProviderNode *current =
topIdx.isValid() ? nodeFromIndex(topIdx) : m_root;
QTC_ASSERT(current, return QModelIndex());
if (current->provider == provider)
return topIdx;
for (int i = 0; i < current->childNodes.count(); ++i) {
const QModelIndex idx = index(index(current->childNodes.at(i)), provider);
if (idx.isValid())
return idx;
}
return QModelIndex();
}
QModelIndex GdbServerProviderModel::parent(const QModelIndex &idx) const
{
const GdbServerProviderNode *n = nodeFromIndex(idx);
return (n->parent == m_root) ? QModelIndex() : index(n->parent);
}
int GdbServerProviderModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return m_root->childNodes.count();
const GdbServerProviderNode *n = nodeFromIndex(parent);
return n->childNodes.count();
}
int GdbServerProviderModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return ColumnsCount;
}
QVariant GdbServerProviderModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
const GdbServerProviderNode *n = nodeFromIndex(index);
QTC_ASSERT(n, return QVariant());
if (!n->provider)
return QVariant();
if (role == Qt::FontRole) {
QFont f = QApplication::font();
if (n->changed)
f.setBold(true);
return f;
} else if (role == Qt::DisplayRole) {
return (index.column() == NameIndex)
? n->provider->displayName()
: n->provider->typeDisplayName();
}
// FIXME: Need to handle also and ToolTipRole role?
return QVariant();
}
Qt::ItemFlags GdbServerProviderModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
const GdbServerProviderNode *n = nodeFromIndex(index);
Q_ASSERT(n);
return (n->provider) ? (Qt::ItemIsEnabled | Qt::ItemIsSelectable)
: Qt::ItemIsEnabled;
}
QVariant GdbServerProviderModel::headerData(
int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return section == NameIndex ? tr("Name") : tr("Type");
return QVariant();
}
GdbServerProvider *GdbServerProviderModel::provider(
const QModelIndex &index) const
{
if (!index.isValid())
return 0;
const GdbServerProviderNode *n = nodeFromIndex(index);
Q_ASSERT(n);
return n->provider;
}
GdbServerProviderConfigWidget *GdbServerProviderModel::widget(
const QModelIndex &index) const
{
if (!index.isValid())
return 0;
const GdbServerProviderNode *n = nodeFromIndex(index);
Q_ASSERT(n);
return n->widget;
}
bool GdbServerProviderModel::isDirty() const
{
return Utils::anyOf(m_root->childNodes, [](GdbServerProviderNode *n) {
return n->changed;
});
}
bool GdbServerProviderModel::isDirty(GdbServerProvider *p) const
{
return Utils::anyOf(m_root->childNodes, [p](GdbServerProviderNode *n) {
return n->provider == p && n->changed;
});
}
void GdbServerProviderModel::setDirty()
{
const auto w = qobject_cast<GdbServerProviderConfigWidget *>(sender());
foreach (GdbServerProviderNode *n, m_root->childNodes) {
if (n->widget == w) {
n->changed = true;
emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex())));
}
}
}
void GdbServerProviderModel::apply()
{
// Remove unused providers
foreach (const GdbServerProviderNode *n, m_toRemoveNodes) {
Q_ASSERT(!n->parent);
GdbServerProviderManager::instance()->deregisterProvider(n->provider);
}
Q_ASSERT(m_toRemoveNodes.isEmpty());
// Update providers
foreach (GdbServerProviderNode *n, m_root->childNodes) {
Q_ASSERT(n);
if (!n->changed)
continue;
Q_ASSERT(n->provider);
if (n->widget)
n->widget->apply();
n->changed = false;
emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex())));
}
// Add new (and already updated) providers
QStringList removedProviders;
foreach (const GdbServerProviderNode *n, m_toAddNodes) {
if (!GdbServerProviderManager::instance()->registerProvider(n->provider))
removedProviders << n->provider->displayName();
}
qDeleteAll(m_toAddNodes);
if (removedProviders.count() == 1) {
QMessageBox::warning(Core::ICore::dialogParent(),
tr("Duplicate Providers Detected"),
tr("The following provider was already configured:<br>"
"&nbsp;%1<br>"
"It was not configured again.")
.arg(removedProviders.at(0)));
} else if (!removedProviders.isEmpty()) {
QMessageBox::warning(Core::ICore::dialogParent(),
tr("Duplicate Providers Detected"),
tr("The following providers were already configured:<br>"
"&nbsp;%1<br>"
"They were not configured again.")
.arg(removedProviders.join(QLatin1String(",<br>&nbsp;"))));
}
}
void GdbServerProviderModel::markForRemoval(GdbServerProvider *provider)
{
GdbServerProviderNode *n = findNode(m_root->childNodes, provider);
QTC_ASSERT(n, return);
const int row = m_root->childNodes.indexOf(n);
emit beginRemoveRows(index(m_root), row, row);
m_root->childNodes.removeOne(n);
n->parent = 0;
if (m_toAddNodes.contains(n)) {
delete n->provider;
n->provider = 0;
m_toAddNodes.removeOne(n);
delete n;
} else {
m_toRemoveNodes.append(n);
}
emit endRemoveRows();
}
void GdbServerProviderModel::markForAddition(GdbServerProvider *provider)
{
const int pos = m_root->childNodes.size();
emit beginInsertRows(index(m_root), pos, pos);
GdbServerProviderNode *n = createNode(m_root, provider, true);
m_toAddNodes.append(n);
emit endInsertRows();
}
QModelIndex GdbServerProviderModel::index(
GdbServerProviderNode *n, int column) const
{
if (n == m_root)
return QModelIndex();
if (n->parent == m_root)
return index(m_root->childNodes.indexOf(n), column, QModelIndex());
return index(n->parent->childNodes.indexOf(n),
column, index(n->parent));
}
GdbServerProviderNode *GdbServerProviderModel::createNode(
GdbServerProviderNode *parent,
GdbServerProvider *provider, bool changed)
{
auto n = new GdbServerProviderNode(parent, provider, changed);
if (n->widget) {
connect(n->widget, &GdbServerProviderConfigWidget::dirty,
this, &GdbServerProviderModel::setDirty);
}
return n;
}
GdbServerProviderNode *GdbServerProviderModel::nodeFromIndex(
const QModelIndex &index) const
{
return static_cast<GdbServerProviderNode *>(index.internalPointer());
}
GdbServerProviderNode *GdbServerProviderModel::findNode(
const QList<GdbServerProviderNode *> &container,
const GdbServerProvider *provider)
{
return Utils::findOrDefault(container, [provider](GdbServerProviderNode *n) {
return n->provider == provider;
});
}
void GdbServerProviderModel::addProvider(GdbServerProvider *provider)
{
GdbServerProviderNode *n = findNode(m_toAddNodes, provider);
if (n) {
m_toAddNodes.removeOne(n);
// do not delete n: Still used elsewhere!
return;
}
const int row = m_root->childNodes.count();
beginInsertRows(index(m_root), row, row);
createNode(m_root, provider, false);
endInsertRows();
emit providerStateChanged();
}
void GdbServerProviderModel::removeProvider(GdbServerProvider *provider)
{
GdbServerProviderNode *n = findNode(m_toRemoveNodes, provider);
if (n) {
m_toRemoveNodes.removeOne(n);
delete n;
return;
}
int row = 0;
foreach (GdbServerProviderNode *current, m_root->childNodes) {
if (current->provider == provider) {
n = current;
break;
}
++row;
}
beginRemoveRows(index(m_root), row, row);
m_root->childNodes.removeAt(row);
delete n;
endRemoveRows();
emit providerStateChanged();
}
GdbServerProvidersSettingsPage::GdbServerProvidersSettingsPage(
QObject *parent)
: Core::IOptionsPage(parent)
{
setCategory(Constants::BAREMETAL_SETTINGS_CATEGORY);
setDisplayCategory(QCoreApplication::translate(
"BareMetal", Constants::BAREMETAL_SETTINGS_TR_CATEGORY));
setCategoryIcon(QLatin1String(Constants::BAREMETAL_SETTINGS_CATEGORY_ICON));
setId(Constants::GDB_PROVIDERS_SETTINGS_ID);
setDisplayName(tr("GDB Server Providers"));
}
QWidget *GdbServerProvidersSettingsPage::widget()
{
if (!m_configWidget) {
// Actual page setup:
m_configWidget = new QWidget;
m_providerView = new QTreeView(m_configWidget);
m_providerView->setUniformRowHeights(true);
m_providerView->header()->setStretchLastSection(false);
m_addButton = new QPushButton(tr("Add"), m_configWidget);
m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
m_delButton = new QPushButton(tr("Remove"), m_configWidget);
m_container = new Utils::DetailsWidget(m_configWidget);
m_container->setState(Utils::DetailsWidget::NoSummary);
m_container->setMinimumWidth(500);
m_container->setVisible(false);
auto buttonLayout = new QHBoxLayout();
buttonLayout->setSpacing(6);
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->addWidget(m_addButton);
buttonLayout->addWidget(m_cloneButton);
buttonLayout->addWidget(m_delButton);
auto spacerItem = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
buttonLayout->addItem(spacerItem);
auto verticalLayout = new QVBoxLayout();
verticalLayout->addWidget(m_providerView);
verticalLayout->addLayout(buttonLayout);
auto horizontalLayout = new QHBoxLayout(m_configWidget);
horizontalLayout->addLayout(verticalLayout);
horizontalLayout->addWidget(m_container);
Q_ASSERT(!m_model);
m_model = new GdbServerProviderModel(m_configWidget);
connect(m_model, &GdbServerProviderModel::providerStateChanged,
this, &GdbServerProvidersSettingsPage::updateState);
m_providerView->setModel(m_model);
auto headerView = m_providerView->header();
headerView->setSectionResizeMode(0, QHeaderView::ResizeToContents);
headerView->setSectionResizeMode(1, QHeaderView::Stretch);
m_providerView->expandAll();
m_selectionModel = m_providerView->selectionModel();
connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SLOT(providerSelectionChanged()));
connect(GdbServerProviderManager::instance(), &GdbServerProviderManager::providersChanged,
this, &GdbServerProvidersSettingsPage::providerSelectionChanged);
// Set up add menu:
auto addMenu = new QMenu(m_addButton);
auto mapper = new QSignalMapper(addMenu);
connect(mapper, SIGNAL(mapped(QObject*)), SLOT(createProvider(QObject*)));
foreach (const auto f, GdbServerProviderManager::instance()->factories()) {
auto action = new QAction(addMenu);
action->setText(f->displayName());
connect(action, SIGNAL(triggered()), mapper, SLOT(map()));
mapper->setMapping(action, static_cast<QObject *>(f));
addMenu->addAction(action);
}
connect(m_cloneButton, SIGNAL(clicked()), mapper, SLOT(map()));
mapper->setMapping(m_cloneButton, static_cast<QObject *>(0));
m_addButton->setMenu(addMenu);
connect(m_delButton, &QPushButton::clicked,
this, &GdbServerProvidersSettingsPage::removeProvider);
updateState();
}
return m_configWidget;
}
void GdbServerProvidersSettingsPage::apply()
{
if (m_model)
m_model->apply();
}
void GdbServerProvidersSettingsPage::finish()
{
disconnect(GdbServerProviderManager::instance(), SIGNAL(providersChanged()),
this, SLOT(providerSelectionChanged()));
delete m_configWidget;
}
void GdbServerProvidersSettingsPage::providerSelectionChanged()
{
if (!m_container)
return;
const QModelIndex current = currentIndex();
QWidget *w = m_container->takeWidget(); // Prevent deletion.
if (w)
w->setVisible(false);
w = current.isValid() ? m_model->widget(current) : 0;
m_container->setWidget(w);
m_container->setVisible(w != 0);
updateState();
}
void GdbServerProvidersSettingsPage::createProvider(QObject *factoryObject)
{
GdbServerProvider *provider = 0;
auto f = static_cast<GdbServerProviderFactory *>(factoryObject);
if (!f) {
GdbServerProvider *old = m_model->provider(currentIndex());
if (!old)
return;
provider = old->clone();
} else {
provider = f->create();
} if (!provider) {
return;
}
m_model->markForAddition(provider);
const QModelIndex newIdx = m_model->index(QModelIndex(), provider);
m_selectionModel->select(newIdx,
QItemSelectionModel::Clear
| QItemSelectionModel::SelectCurrent
| QItemSelectionModel::Rows);
}
void GdbServerProvidersSettingsPage::removeProvider()
{
GdbServerProvider *p = m_model->provider(currentIndex());
if (!p)
return;
m_model->markForRemoval(p);
}
void GdbServerProvidersSettingsPage::updateState()
{
if (!m_cloneButton)
return;
bool canCopy = false;
bool canDelete = false;
const GdbServerProvider *p = m_model->provider(currentIndex());
if (p) {
canCopy = p->isValid();
canDelete = true;
}
m_cloneButton->setEnabled(canCopy);
m_delButton->setEnabled(canDelete);
}
QModelIndex GdbServerProvidersSettingsPage::currentIndex() const
{
if (!m_selectionModel)
return QModelIndex();
const QModelIndexList rows = m_selectionModel->selectedRows();
if (rows.count() != 1)
return QModelIndex();
return rows.at(0);
}
} // namespace Internal
} // namespace BareMetal

View File

@@ -0,0 +1,149 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 GDBSERVERPROVIDERSSETTINGSPAGE_H
#define GDBSERVERPROVIDERSSETTINGSPAGE_H
#include <coreplugin/dialogs/ioptionspage.h>
#include <QAbstractItemModel>
#include <QPointer>
QT_BEGIN_NAMESPACE
class QItemSelectionModel;
class QPushButton;
class QTreeView;
QT_END_NAMESPACE
namespace Utils { class DetailsWidget; }
namespace BareMetal {
namespace Internal {
class GdbServerProvider;
class GdbServerProviderConfigWidget;
class GdbServerProviderNode;
class GdbServerProviderModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit GdbServerProviderModel(QObject *parent = 0);
~GdbServerProviderModel();
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex index(const QModelIndex &topIdx, const GdbServerProvider *) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
GdbServerProvider *provider(const QModelIndex &) const;
GdbServerProviderConfigWidget *widget(const QModelIndex &) const;
bool isDirty() const;
bool isDirty(GdbServerProvider *) const;
void apply();
void markForRemoval(GdbServerProvider *);
void markForAddition(GdbServerProvider *);
signals:
void providerStateChanged();
private slots:
void addProvider(GdbServerProvider *);
void removeProvider(GdbServerProvider *);
void setDirty();
private:
enum ColumnIndex { NameIndex = 0, TypeIndex, ColumnsCount };
QModelIndex index(GdbServerProviderNode *, int column = 0) const;
GdbServerProviderNode *createNode(GdbServerProviderNode *parent,
GdbServerProvider *, bool changed);
GdbServerProviderNode *nodeFromIndex(const QModelIndex &) const;
static GdbServerProviderNode *findNode(
const QList<GdbServerProviderNode *> &container,
const GdbServerProvider *);
GdbServerProviderNode *m_root;
QList<GdbServerProviderNode *> m_toAddNodes;
QList<GdbServerProviderNode *> m_toRemoveNodes;
};
class GdbServerProvidersSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
explicit GdbServerProvidersSettingsPage(QObject *parent = 0);
QWidget *widget();
void apply();
void finish();
private slots:
void providerSelectionChanged();
void createProvider(QObject *);
void removeProvider();
void updateState();
private:
QModelIndex currentIndex() const;
QPointer<QWidget> m_configWidget;
QPointer<GdbServerProviderModel> m_model;
QPointer<QItemSelectionModel> m_selectionModel;
QPointer<QTreeView> m_providerView;
QPointer<Utils::DetailsWidget> m_container;
QPointer<QPushButton> m_addButton;
QPointer<QPushButton> m_cloneButton;
QPointer<QPushButton> m_delButton;
};
} // namespace Internal
} // namespace BareMetal
#endif // GDBSERVERPROVIDERSSETTINGSPAGE_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,365 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "openocdgdbserverprovider.h"
#include "baremetalconstants.h"
#include "gdbserverprovidermanager.h"
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/fileutils.h>
#include <QString>
#include <QFileInfo>
#include <QFormLayout>
#include <QLineEdit>
#include <QComboBox>
#include <QPlainTextEdit>
namespace BareMetal {
namespace Internal {
const char hostKeyC[] = "BareMetal.OpenOcdGdbServerProvider.Host";
const char portKeyC[] = "BareMetal.OpenOcdGdbServerProvider.Port";
const char executableFileKeyC[] = "BareMetal.OpenOcdGdbServerProvider.ExecutableFile";
const char rootScriptsDirKeyC[] = "BareMetal.OpenOcdGdbServerProvider.RootScriptsDir";
const char configurationFileKeyC[] = "BareMetal.OpenOcdGdbServerProvider.ConfigurationPath";
const char additionalArgumentsKeyC[] = "BareMetal.OpenOcdGdbServerProvider.AdditionalArguments";
OpenOcdGdbServerProvider::OpenOcdGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::OPENOCD_PROVIDER_ID))
, m_host(QLatin1String("localhost"))
, m_port(3333)
, m_executableFile(QLatin1String("openocd"))
{
setInitCommands(defaultInitCommands());
setResetCommands(defaultResetCommands());
}
OpenOcdGdbServerProvider::OpenOcdGdbServerProvider(
const OpenOcdGdbServerProvider &other)
: GdbServerProvider(other)
, m_host(other.m_host)
, m_port(other.m_port)
, m_executableFile(other.m_executableFile)
, m_rootScriptsDir(other.m_rootScriptsDir)
, m_configurationFile(other.m_configurationFile)
, m_additionalArguments(other.m_additionalArguments)
{
}
QString OpenOcdGdbServerProvider::defaultInitCommands()
{
return QLatin1String("set remote hardware-breakpoint-limit 6\n"
"set remote hardware-watchpoint-limit 4\n"
"monitor reset halt\n"
"load\n"
"monitor reset halt\n");
}
QString OpenOcdGdbServerProvider::defaultResetCommands()
{
return QLatin1String("monitor reset halt\n");
}
QString OpenOcdGdbServerProvider::typeDisplayName() const
{
return OpenOcdGdbServerProviderFactory::tr("OpenOCD");
}
QString OpenOcdGdbServerProvider::channel() const
{
switch (startupMode()) {
case NoStartup:
// fallback
case StartupOnNetwork:
// Just return as "host:port" form.
return m_host + QLatin1Char(':') + QString::number(m_port);
case StartupOnPipe: {
QStringList args;
// In the pipe mode need to add quotes to each item of arguments;
// otherwise running will be stuck.
foreach (const QString &a, arguments()) {
if (a.startsWith(QLatin1Char('\"')) && a.endsWith(QLatin1Char('\"')))
continue;
args << (QLatin1Char('\"') + a + QLatin1Char('\"'));
}
args.prepend(executable());
args.prepend(QLatin1String("|"));
return args.join(QLatin1Char(' '));
}
default: // wrong
return QString();
}
}
QString OpenOcdGdbServerProvider::executable() const
{
return m_executableFile;
}
QStringList OpenOcdGdbServerProvider::arguments() const
{
QStringList args;
args << QLatin1String("-c");
if (startupMode() == StartupOnPipe)
args << QLatin1String("gdb_port pipe");
else
args << (QLatin1String("gdb_port ") + QString::number(m_port));
if (!m_rootScriptsDir.isEmpty())
args << QLatin1String("-s") << m_rootScriptsDir;
if (!m_configurationFile.isEmpty())
args << QLatin1String("-f") << m_configurationFile;
if (!m_additionalArguments.isEmpty())
args << m_additionalArguments;
return args;
}
bool OpenOcdGdbServerProvider::canStartupMode(StartupMode m) const
{
return m == NoStartup || m == StartupOnNetwork || m == StartupOnPipe;
}
bool OpenOcdGdbServerProvider::isValid() const
{
if (!GdbServerProvider::isValid())
return false;
const StartupMode m = startupMode();
if (m == NoStartup || m == StartupOnNetwork) {
if (m_host.isEmpty())
return false;
}
if (m == StartupOnNetwork || m == StartupOnPipe) {
if (m_executableFile.isEmpty() || m_configurationFile.isEmpty())
return false;
}
return true;
}
GdbServerProvider *OpenOcdGdbServerProvider::clone() const
{
return new OpenOcdGdbServerProvider(*this);
}
QVariantMap OpenOcdGdbServerProvider::toMap() const
{
QVariantMap data = GdbServerProvider::toMap();
data.insert(QLatin1String(hostKeyC), m_host);
data.insert(QLatin1String(portKeyC), m_port);
data.insert(QLatin1String(executableFileKeyC), m_executableFile);
data.insert(QLatin1String(rootScriptsDirKeyC), m_rootScriptsDir);
data.insert(QLatin1String(configurationFileKeyC), m_configurationFile);
data.insert(QLatin1String(additionalArgumentsKeyC), m_additionalArguments);
return data;
}
bool OpenOcdGdbServerProvider::fromMap(const QVariantMap &data)
{
if (!GdbServerProvider::fromMap(data))
return false;
m_host = data.value(QLatin1String(hostKeyC)).toString();
m_port = data.value(QLatin1String(portKeyC)).toInt();
m_executableFile = data.value(QLatin1String(executableFileKeyC)).toString();
m_rootScriptsDir = data.value(QLatin1String(rootScriptsDirKeyC)).toString();
m_configurationFile = data.value(QLatin1String(configurationFileKeyC)).toString();
m_additionalArguments = data.value(QLatin1String(additionalArgumentsKeyC)).toString();
return true;
}
bool OpenOcdGdbServerProvider::operator==(const GdbServerProvider &other) const
{
if (!GdbServerProvider::operator==(other))
return false;
const auto p = static_cast<const OpenOcdGdbServerProvider *>(&other);
return m_host == p->m_host
&& m_port == p->m_port
&& m_executableFile == p->m_executableFile
&& m_rootScriptsDir == p->m_rootScriptsDir
&& m_configurationFile == p->m_configurationFile
&& m_additionalArguments == p->m_additionalArguments;
}
GdbServerProviderConfigWidget *OpenOcdGdbServerProvider::configurationWidget()
{
return new OpenOcdGdbServerProviderConfigWidget(this);
}
OpenOcdGdbServerProviderFactory::OpenOcdGdbServerProviderFactory()
{
setId(QLatin1String(Constants::OPENOCD_PROVIDER_ID));
setDisplayName(tr("OpenOCD"));
}
GdbServerProvider *OpenOcdGdbServerProviderFactory::create()
{
return new OpenOcdGdbServerProvider;
}
bool OpenOcdGdbServerProviderFactory::canRestore(const QVariantMap &data)
{
const QString id = idFromMap(data);
return id.startsWith(QLatin1String(Constants::OPENOCD_PROVIDER_ID)
+ QLatin1Char(':'));
}
GdbServerProvider *OpenOcdGdbServerProviderFactory::restore(const QVariantMap &data)
{
auto p = new OpenOcdGdbServerProvider;
auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return 0;
}
OpenOcdGdbServerProviderConfigWidget::OpenOcdGdbServerProviderConfigWidget(
OpenOcdGdbServerProvider *p)
: GdbServerProviderConfigWidget(p)
{
Q_ASSERT(p);
m_hostWidget = new HostWidget(this);
m_mainLayout->addRow(tr("Host:"), m_hostWidget);
m_executableFileChooser = new Utils::PathChooser;
m_executableFileChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_executableFileChooser->setCommandVersionArguments(QStringList(QLatin1String("--version")));
m_mainLayout->addRow(tr("Executable file:"), m_executableFileChooser);
m_rootScriptsDirChooser = new Utils::PathChooser;
m_rootScriptsDirChooser->setExpectedKind(Utils::PathChooser::Directory);
m_mainLayout->addRow(tr("Root scripts directory:"), m_rootScriptsDirChooser);
m_configurationFileChooser = new Utils::PathChooser;
m_configurationFileChooser->setExpectedKind(Utils::PathChooser::File);
m_configurationFileChooser->setPromptDialogFilter(QLatin1String("*.cfg"));
m_mainLayout->addRow(tr("Configuration file:"), m_configurationFileChooser);
m_additionalArgumentsLineEdit = new QLineEdit(this);
m_mainLayout->addRow(tr("Additional arguments:"), m_additionalArgumentsLineEdit);
m_initCommandsTextEdit = new QPlainTextEdit(this);
m_initCommandsTextEdit->setToolTip(defaultInitCommandsTooltip());
m_mainLayout->addRow(tr("Init commands:"), m_initCommandsTextEdit);
m_resetCommandsTextEdit = new QPlainTextEdit(this);
m_resetCommandsTextEdit->setToolTip(defaultResetCommandsTooltip());
m_mainLayout->addRow(tr("Reset commands:"), m_resetCommandsTextEdit);
addErrorLabel();
setFromProvider();
connect(m_hostWidget, &HostWidget::dataChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_executableFileChooser, &Utils::PathChooser::changed,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_rootScriptsDirChooser, &Utils::PathChooser::changed,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_configurationFileChooser, &Utils::PathChooser::changed,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_additionalArgumentsLineEdit, &QLineEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_initCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_resetCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_startupModeComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(startupModeChanged()));
}
void OpenOcdGdbServerProviderConfigWidget::startupModeChanged()
{
const GdbServerProvider::StartupMode m = startupMode();
const bool isStartup = m != GdbServerProvider::NoStartup;
m_executableFileChooser->setVisible(isStartup);
m_mainLayout->labelForField(m_executableFileChooser)->setVisible(isStartup);
m_rootScriptsDirChooser->setVisible(isStartup);
m_mainLayout->labelForField(m_rootScriptsDirChooser)->setVisible(isStartup);
m_configurationFileChooser->setVisible(isStartup);
m_mainLayout->labelForField(m_configurationFileChooser)->setVisible(isStartup);
m_additionalArgumentsLineEdit->setVisible(isStartup);
m_mainLayout->labelForField(m_additionalArgumentsLineEdit)->setVisible(isStartup);
const bool isNetwork = m != GdbServerProvider::StartupOnPipe;
m_hostWidget->setVisible(isNetwork);
m_mainLayout->labelForField(m_hostWidget)->setVisible(isNetwork);
}
void OpenOcdGdbServerProviderConfigWidget::applyImpl()
{
auto p = static_cast<OpenOcdGdbServerProvider *>(provider());
Q_ASSERT(p);
p->m_host = m_hostWidget->host();
p->m_port = m_hostWidget->port();
p->m_executableFile = m_executableFileChooser->fileName().toString();
p->m_rootScriptsDir = m_rootScriptsDirChooser->fileName().toString();
p->m_configurationFile = m_configurationFileChooser->fileName().toString();
p->m_additionalArguments = m_additionalArgumentsLineEdit->text();
p->setInitCommands(m_initCommandsTextEdit->toPlainText());
p->setResetCommands(m_resetCommandsTextEdit->toPlainText());
}
void OpenOcdGdbServerProviderConfigWidget::discardImpl()
{
setFromProvider();
}
void OpenOcdGdbServerProviderConfigWidget::setFromProvider()
{
const auto p = static_cast<OpenOcdGdbServerProvider *>(provider());
Q_ASSERT(p);
const bool b = blockSignals(true);
startupModeChanged();
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
m_executableFileChooser->setFileName(Utils::FileName::fromString(p->m_executableFile));
m_rootScriptsDirChooser->setFileName(Utils::FileName::fromString(p->m_rootScriptsDir));
m_configurationFileChooser->setFileName(Utils::FileName::fromString(p->m_configurationFile));
m_additionalArgumentsLineEdit->setText(p->m_additionalArguments);
m_initCommandsTextEdit->setPlainText(p->initCommands());
m_resetCommandsTextEdit->setPlainText(p->resetCommands());
blockSignals(b);
}
} // namespace Internal
} // namespace ProjectExplorer

View File

@@ -0,0 +1,125 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 OPENOCDGDBSERVERPROVIDER_H
#define OPENOCDGDBSERVERPROVIDER_H
#include "gdbserverprovider.h"
namespace Utils { class PathChooser; }
namespace BareMetal {
namespace Internal {
class OpenOcdGdbServerProviderConfigWidget;
class OpenOcdGdbServerProviderFactory;
class OpenOcdGdbServerProvider : public GdbServerProvider
{
public:
QString typeDisplayName() const;
QVariantMap toMap() const;
bool fromMap(const QVariantMap &data);
bool operator==(const GdbServerProvider &) const;
GdbServerProviderConfigWidget *configurationWidget();
GdbServerProvider *clone() const;
QString channel() const;
QString executable() const;
QStringList arguments() const;
bool canStartupMode(StartupMode mode) const;
bool isValid() const;
private:
explicit OpenOcdGdbServerProvider();
explicit OpenOcdGdbServerProvider(const OpenOcdGdbServerProvider &);
static QString defaultInitCommands();
static QString defaultResetCommands();
QString m_host;
quint16 m_port;
QString m_executableFile;
QString m_rootScriptsDir;
QString m_configurationFile;
QString m_additionalArguments;
friend class OpenOcdGdbServerProviderConfigWidget;
friend class OpenOcdGdbServerProviderFactory;
};
class OpenOcdGdbServerProviderFactory : public GdbServerProviderFactory
{
Q_OBJECT
public:
explicit OpenOcdGdbServerProviderFactory();
GdbServerProvider *create();
bool canRestore(const QVariantMap &data);
GdbServerProvider *restore(const QVariantMap &data);
GdbServerProviderConfigWidget *configurationWidget(GdbServerProvider *);
};
class OpenOcdGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
{
Q_OBJECT
public:
explicit OpenOcdGdbServerProviderConfigWidget(OpenOcdGdbServerProvider *);
private slots:
void startupModeChanged();
private:
void applyImpl();
void discardImpl();
void setFromProvider();
QPointer<HostWidget> m_hostWidget;
QPointer<Utils::PathChooser> m_executableFileChooser;
QPointer<Utils::PathChooser> m_rootScriptsDirChooser;
QPointer<Utils::PathChooser> m_configurationFileChooser;
QPointer<QLineEdit> m_additionalArgumentsLineEdit;
QPointer<QPlainTextEdit> m_initCommandsTextEdit;
QPointer<QPlainTextEdit> m_resetCommandsTextEdit;
};
} // namespace Internal
} // namespace BareMetal
#endif // OPENOCDGDBSERVERPROVIDER_H

View File

@@ -0,0 +1,401 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 "stlinkutilgdbserverprovider.h"
#include "baremetalconstants.h"
#include "gdbserverprovidermanager.h"
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/fileutils.h>
#include <QString>
#include <QFileInfo>
#include <QFormLayout>
#include <QLineEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QCheckBox>
#include <QPlainTextEdit>
namespace BareMetal {
namespace Internal {
const char hostKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.Host";
const char portKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.Port";
const char executableFileKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.ExecutableFile";
const char verboseLevelKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.VerboseLevel";
const char extendedModeKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.ExtendedMode";
const char resetBoardKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.ResetBoard";
const char transportLayerKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.TransportLayer";
StLinkUtilGdbServerProvider::StLinkUtilGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::STLINK_UTIL_PROVIDER_ID))
, m_host(QLatin1String("localhost"))
, m_port(4242)
, m_executableFile(QLatin1String("st-util"))
, m_verboseLevel(0)
, m_extendedMode(false)
, m_resetBoard(true)
, m_transport(RawUsb)
{
setInitCommands(defaultInitCommands());
setResetCommands(defaultResetCommands());
}
StLinkUtilGdbServerProvider::StLinkUtilGdbServerProvider(
const StLinkUtilGdbServerProvider &other)
: GdbServerProvider(other)
, m_host(other.m_host)
, m_port(other.m_port)
, m_executableFile(other.m_executableFile)
, m_verboseLevel(0)
, m_extendedMode(false)
, m_resetBoard(true)
, m_transport(RawUsb)
{
}
QString StLinkUtilGdbServerProvider::defaultInitCommands()
{
return QLatin1String("load\n");
}
QString StLinkUtilGdbServerProvider::defaultResetCommands()
{
return QLatin1String("");
}
QString StLinkUtilGdbServerProvider::typeDisplayName() const
{
return StLinkUtilGdbServerProviderFactory::tr("STLink-Util");
}
QString StLinkUtilGdbServerProvider::channel() const
{
switch (startupMode()) {
case NoStartup:
// fallback
case StartupOnNetwork:
// Just return as "host:port" form.
return m_host + QLatin1Char(':') + QString::number(m_port);
case StartupOnPipe:
// Unsupported mode
return QString();
default: // wrong
return QString();
}
}
QString StLinkUtilGdbServerProvider::executable() const
{
return m_executableFile;
}
QStringList StLinkUtilGdbServerProvider::arguments() const
{
QStringList args;
if (m_extendedMode)
args << QLatin1String("--multi");
if (!m_resetBoard)
args << QLatin1String("--no-reset");
args << (QLatin1String("--stlink_version=") + QString::number(m_transport));
args << (QLatin1String("--listen_port=") + QString::number(m_port));
args << (QLatin1String("--verbose=") + QString::number(m_verboseLevel));
return args;
}
bool StLinkUtilGdbServerProvider::canStartupMode(StartupMode m) const
{
return m == NoStartup || m == StartupOnNetwork;
}
bool StLinkUtilGdbServerProvider::isValid() const
{
if (!GdbServerProvider::isValid())
return false;
const StartupMode m = startupMode();
if (m == NoStartup || m == StartupOnNetwork) {
if (m_host.isEmpty())
return false;
}
if (m == StartupOnNetwork) {
if (m_executableFile.isEmpty())
return false;
}
return true;
}
GdbServerProvider *StLinkUtilGdbServerProvider::clone() const
{
return new StLinkUtilGdbServerProvider(*this);
}
QVariantMap StLinkUtilGdbServerProvider::toMap() const
{
QVariantMap data = GdbServerProvider::toMap();
data.insert(QLatin1String(hostKeyC), m_host);
data.insert(QLatin1String(portKeyC), m_port);
data.insert(QLatin1String(executableFileKeyC), m_executableFile);
data.insert(QLatin1String(verboseLevelKeyC), m_verboseLevel);
data.insert(QLatin1String(extendedModeKeyC), m_extendedMode);
data.insert(QLatin1String(resetBoardKeyC), m_resetBoard);
data.insert(QLatin1String(transportLayerKeyC), m_transport);
return data;
}
bool StLinkUtilGdbServerProvider::fromMap(const QVariantMap &data)
{
if (!GdbServerProvider::fromMap(data))
return false;
m_host = data.value(QLatin1String(hostKeyC)).toString();
m_port = data.value(QLatin1String(portKeyC)).toInt();
m_executableFile = data.value(QLatin1String(executableFileKeyC)).toString();
m_verboseLevel = data.value(QLatin1String(verboseLevelKeyC)).toInt();
m_extendedMode = data.value(QLatin1String(extendedModeKeyC)).toBool();
m_resetBoard = data.value(QLatin1String(resetBoardKeyC)).toBool();
m_transport = static_cast<TransportLayer>(
data.value(QLatin1String(transportLayerKeyC)).toInt());
return true;
}
bool StLinkUtilGdbServerProvider::operator==(const GdbServerProvider &other) const
{
if (!GdbServerProvider::operator==(other))
return false;
const auto p = static_cast<const StLinkUtilGdbServerProvider *>(&other);
return m_host == p->m_host
&& m_port == p->m_port
&& m_executableFile == p->m_executableFile
&& m_verboseLevel == p->m_verboseLevel
&& m_extendedMode == p->m_extendedMode
&& m_resetBoard == p->m_resetBoard
&& m_transport == p->m_transport;
}
GdbServerProviderConfigWidget *StLinkUtilGdbServerProvider::configurationWidget()
{
return new StLinkUtilGdbServerProviderConfigWidget(this);
}
StLinkUtilGdbServerProviderFactory::StLinkUtilGdbServerProviderFactory()
{
setId(QLatin1String(Constants::STLINK_UTIL_PROVIDER_ID));
setDisplayName(tr("STLink-Util"));
}
GdbServerProvider *StLinkUtilGdbServerProviderFactory::create()
{
return new StLinkUtilGdbServerProvider;
}
bool StLinkUtilGdbServerProviderFactory::canRestore(const QVariantMap &data)
{
const QString id = idFromMap(data);
return id.startsWith(QLatin1String(Constants::STLINK_UTIL_PROVIDER_ID)
+ QLatin1Char(':'));
}
GdbServerProvider *StLinkUtilGdbServerProviderFactory::restore(const QVariantMap &data)
{
auto p = new StLinkUtilGdbServerProvider;
auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return 0;
}
StLinkUtilGdbServerProviderConfigWidget::StLinkUtilGdbServerProviderConfigWidget(
StLinkUtilGdbServerProvider *p)
: GdbServerProviderConfigWidget(p)
{
Q_ASSERT(p);
m_hostWidget = new HostWidget(this);
m_mainLayout->addRow(tr("Host:"), m_hostWidget);
m_executableFileChooser = new Utils::PathChooser;
m_executableFileChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_mainLayout->addRow(tr("Executable file:"), m_executableFileChooser);
m_verboseLevelSpinBox = new QSpinBox;
m_verboseLevelSpinBox->setRange(0, 99);
m_verboseLevelSpinBox->setToolTip(tr("Specify the verbosity level (0..99)."));
m_mainLayout->addRow(tr("Verbosity level:"), m_verboseLevelSpinBox);
m_extendedModeCheckBox = new QCheckBox;
m_extendedModeCheckBox->setToolTip(tr("Continue listening for connections "
"after disconnect."));
m_mainLayout->addRow(tr("Extended mode:"), m_extendedModeCheckBox);
m_resetBoardCheckBox = new QCheckBox;
m_resetBoardCheckBox->setToolTip(tr("Reset board on connection."));
m_mainLayout->addRow(tr("Reset on connection:"), m_resetBoardCheckBox);
m_transportLayerComboBox = new QComboBox;
m_transportLayerComboBox->setToolTip(tr("Transport layer type."));
m_mainLayout->addRow(tr("Version:"), m_transportLayerComboBox);
m_initCommandsTextEdit = new QPlainTextEdit(this);
m_initCommandsTextEdit->setToolTip(defaultInitCommandsTooltip());
m_mainLayout->addRow(tr("Init commands:"), m_initCommandsTextEdit);
m_resetCommandsTextEdit = new QPlainTextEdit(this);
m_resetCommandsTextEdit->setToolTip(defaultResetCommandsTooltip());
m_mainLayout->addRow(tr("Reset commands:"), m_resetCommandsTextEdit);
populateTransportLayers();
addErrorLabel();
setFromProvider();
connect(m_hostWidget, &HostWidget::dataChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_executableFileChooser, &Utils::PathChooser::changed,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_verboseLevelSpinBox, SIGNAL(valueChanged(int)), SIGNAL(dirty()));
connect(m_extendedModeCheckBox, SIGNAL(clicked()), SIGNAL(dirty()));
connect(m_resetBoardCheckBox, SIGNAL(clicked()), SIGNAL(dirty()));
connect(m_transportLayerComboBox, SIGNAL(currentIndexChanged(int)), SIGNAL(dirty()));
connect(m_initCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_resetCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_startupModeComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(startupModeChanged()));
}
void StLinkUtilGdbServerProviderConfigWidget::startupModeChanged()
{
const GdbServerProvider::StartupMode m = startupMode();
const bool isStartup = m != GdbServerProvider::NoStartup;
m_executableFileChooser->setVisible(isStartup);
m_mainLayout->labelForField(m_executableFileChooser)->setVisible(isStartup);
m_verboseLevelSpinBox->setVisible(isStartup);
m_mainLayout->labelForField(m_verboseLevelSpinBox)->setVisible(isStartup);
m_extendedModeCheckBox->setVisible(isStartup);
m_mainLayout->labelForField(m_extendedModeCheckBox)->setVisible(isStartup);
m_resetBoardCheckBox->setVisible(isStartup);
m_mainLayout->labelForField(m_resetBoardCheckBox)->setVisible(isStartup);
m_transportLayerComboBox->setVisible(isStartup);
m_mainLayout->labelForField(m_transportLayerComboBox)->setVisible(isStartup);
}
void StLinkUtilGdbServerProviderConfigWidget::applyImpl()
{
auto p = static_cast<StLinkUtilGdbServerProvider *>(provider());
Q_ASSERT(p);
p->m_host = m_hostWidget->host();
p->m_port = m_hostWidget->port();
p->m_executableFile = m_executableFileChooser->fileName().toString();
p->m_verboseLevel = m_verboseLevelSpinBox->value();
p->m_extendedMode = m_extendedModeCheckBox->isChecked();
p->m_resetBoard = m_resetBoardCheckBox->isChecked();
p->m_transport = transportLayer();
p->setInitCommands(m_initCommandsTextEdit->toPlainText());
p->setResetCommands(m_resetCommandsTextEdit->toPlainText());
}
void StLinkUtilGdbServerProviderConfigWidget::discardImpl()
{
setFromProvider();
}
StLinkUtilGdbServerProvider::TransportLayer
StLinkUtilGdbServerProviderConfigWidget::transportLayerFromIndex(int idx) const
{
return static_cast<StLinkUtilGdbServerProvider::TransportLayer>(
m_transportLayerComboBox->itemData(idx).toInt());
}
StLinkUtilGdbServerProvider::TransportLayer
StLinkUtilGdbServerProviderConfigWidget::transportLayer() const
{
const int idx = m_transportLayerComboBox->currentIndex();
return transportLayerFromIndex(idx);
}
void StLinkUtilGdbServerProviderConfigWidget::setTransportLayer(
StLinkUtilGdbServerProvider::TransportLayer tl)
{
for (int idx = 0; idx < m_transportLayerComboBox->count(); ++idx) {
if (tl == transportLayerFromIndex(idx)) {
m_transportLayerComboBox->setCurrentIndex(idx);
break;
}
}
}
void StLinkUtilGdbServerProviderConfigWidget::populateTransportLayers()
{
m_transportLayerComboBox->insertItem(
m_transportLayerComboBox->count(), tr("STLINKv1"),
StLinkUtilGdbServerProvider::ScsiOverUsb);
m_transportLayerComboBox->insertItem(
m_transportLayerComboBox->count(), tr("STLINKv2"),
StLinkUtilGdbServerProvider::RawUsb);
}
void StLinkUtilGdbServerProviderConfigWidget::setFromProvider()
{
const auto p = static_cast<StLinkUtilGdbServerProvider *>(provider());
Q_ASSERT(p);
const bool b = blockSignals(true);
startupModeChanged();
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
m_executableFileChooser->setFileName(Utils::FileName::fromString(p->m_executableFile));
m_verboseLevelSpinBox->setValue(p->m_verboseLevel);
m_extendedModeCheckBox->setChecked(p->m_extendedMode);
m_resetBoardCheckBox->setChecked(p->m_resetBoard);
setTransportLayer(p->m_transport);
m_initCommandsTextEdit->setPlainText(p->initCommands());
m_resetCommandsTextEdit->setPlainText(p->resetCommands());
blockSignals(b);
}
} // namespace Internal
} // namespace ProjectExplorer

View File

@@ -0,0 +1,137 @@
/****************************************************************************
**
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** 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://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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 STLINKUTILGDBSERVERPROVIDER_H
#define STLINKUTILGDBSERVERPROVIDER_H
#include "gdbserverprovider.h"
QT_BEGIN_NAMESPACE
class QCheckBox;
QT_END_NAMESPACE
namespace Utils { class PathChooser; }
namespace BareMetal {
namespace Internal {
class StLinkUtilGdbServerProviderConfigWidget;
class StLinkUtilGdbServerProviderFactory;
class StLinkUtilGdbServerProvider : public GdbServerProvider
{
public:
enum TransportLayer { ScsiOverUsb = 1, RawUsb = 2 };
QString typeDisplayName() const;
QVariantMap toMap() const;
bool fromMap(const QVariantMap &data);
bool operator==(const GdbServerProvider &) const;
GdbServerProviderConfigWidget *configurationWidget();
GdbServerProvider *clone() const;
QString channel() const;
QString executable() const;
QStringList arguments() const;
bool canStartupMode(StartupMode mode) const;
bool isValid() const;
private:
explicit StLinkUtilGdbServerProvider();
explicit StLinkUtilGdbServerProvider(const StLinkUtilGdbServerProvider &);
static QString defaultInitCommands();
static QString defaultResetCommands();
QString m_host;
quint16 m_port;
QString m_executableFile;
int m_verboseLevel; // 0..99
bool m_extendedMode; // Listening for connections after disconnect
bool m_resetBoard;
TransportLayer m_transport;
friend class StLinkUtilGdbServerProviderConfigWidget;
friend class StLinkUtilGdbServerProviderFactory;
};
class StLinkUtilGdbServerProviderFactory : public GdbServerProviderFactory
{
Q_OBJECT
public:
explicit StLinkUtilGdbServerProviderFactory();
GdbServerProvider *create();
bool canRestore(const QVariantMap &data);
GdbServerProvider *restore(const QVariantMap &data);
GdbServerProviderConfigWidget *configurationWidget(GdbServerProvider *);
};
class StLinkUtilGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
{
Q_OBJECT
public:
explicit StLinkUtilGdbServerProviderConfigWidget(StLinkUtilGdbServerProvider *);
private slots:
void startupModeChanged();
private:
void applyImpl();
void discardImpl();
StLinkUtilGdbServerProvider::TransportLayer transportLayerFromIndex(int idx) const;
StLinkUtilGdbServerProvider::TransportLayer transportLayer() const;
void setTransportLayer(StLinkUtilGdbServerProvider::TransportLayer);
void populateTransportLayers();
void setFromProvider();
QPointer<HostWidget> m_hostWidget;
QPointer<Utils::PathChooser> m_executableFileChooser;
QPointer<QSpinBox> m_verboseLevelSpinBox;
QPointer<QCheckBox> m_extendedModeCheckBox;
QPointer<QCheckBox> m_resetBoardCheckBox;
QPointer<QComboBox> m_transportLayerComboBox;
QPointer<QPlainTextEdit> m_initCommandsTextEdit;
QPointer<QPlainTextEdit> m_resetCommandsTextEdit;
};
} // namespace Internal
} // namespace BareMetal
#endif // STLINKUTILGDBSERVERPROVIDER_H