BareMetal: Fix parsing of software pack description files for UVSC provider

A target device info locates in the *.pdsc files provided by the device
description packages which are installed into the Keil MDK-ARM instance.

We parse this files to provide possibility for the user to choose a
specific MCU target for debugging.

Previous parsing implementation was complicated and did not take in
account the specific *.pdsc format features:

 * https://www.keil.com/pack/doc/CMSIS/Pack/html/packFormat.html

It turns out that the following entries as 'family', 'sub-family',
'device', and 'device-variant' may contain an attributes with the
same names. So, we can simplify creation of an items, use only one
base implementation for all items. Besides, a new implementation
simplifies parsing and for other *.pdsc files (e.g. non only for
STMicroelectronics).

Tested with Keil MDK-ARM v5.23 using STM32 NUCLEO-F767ZI board.

Change-Id: Idd51b8fa3e36a7896254b4cb8aa4c1287b9f0df5
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Denis Shienkov
2020-03-13 14:32:30 +03:00
parent e3e62d852f
commit d44b181923
6 changed files with 196 additions and 240 deletions

View File

@@ -54,16 +54,9 @@ static QString buildToolsetNumber(int number)
return QStringLiteral("0x%1").arg(QString::number(number, 16));
}
static QString buildVendor(const QString &vendor)
{
// Remove the colon symbol.
const int colonIndex = vendor.lastIndexOf(':');
return vendor.mid(0, colonIndex);
}
static QString buildPackageId(const DeviceSelection::Package &package)
{
return QStringLiteral("%1.%2.%3").arg(package.vendor, package.name, package.version);
return QStringLiteral("%1.%2.%3").arg(package.vendorName, package.name, package.version);
}
static QString buildCpu(const DeviceSelection &device)
@@ -139,8 +132,7 @@ Project::Project(const UvscServerProvider *provider, DebuggerRunTool *runTool)
const auto targetCommonOption = targetOption->appendPropertyGroup("TargetCommonOption");
const DeviceSelection device = provider->deviceSelection();
targetCommonOption->appendProperty("Device", device.name);
const QString vendor = buildVendor(device.vendor);
targetCommonOption->appendProperty("Vendor", vendor);
targetCommonOption->appendProperty("Vendor", device.vendorName);
const QString packageId = buildPackageId(device.package);
targetCommonOption->appendProperty("PackID", packageId);
targetCommonOption->appendProperty("PackURL", device.package.url);

View File

@@ -25,6 +25,8 @@
#include "uvtargetdevicemodel.h"
#include <utils/algorithm.h>
#include <QDirIterator>
#include <QFile>
#include <QTextStream>
@@ -81,14 +83,19 @@ static QStringList findKeilPackFiles(const QString &path)
return files;
}
static void fillElementProperty(QXmlStreamReader &in, QString &prop)
{
prop = in.readElementText().trimmed();
}
static void fillCpu(QXmlStreamReader &in, DeviceSelection::Cpu &cpu)
{
const QXmlStreamAttributes attrs = in.attributes();
in.skipCurrentElement();
cpu.core = attrs.hasAttribute("Dcore") ? attrs.value("Dcore").toString() : cpu.core;
cpu.clock = attrs.hasAttribute("Dclock") ? attrs.value("Dclock").toString() : cpu.clock;
cpu.fpu = attrs.hasAttribute("Dfpu") ? attrs.value("Dfpu").toString() : cpu.fpu;
cpu.mpu = attrs.hasAttribute("Dmpu") ? attrs.value("Dmpu").toString() : cpu.mpu;
cpu.core = attrs.value("Dcore").toString();
cpu.clock = attrs.value("Dclock").toString();
cpu.fpu = attrs.value("Dfpu").toString();
cpu.mpu = attrs.value("Dmpu").toString();
}
static void fillMemories(QXmlStreamReader &in, DeviceSelection::Memories &memories)
@@ -113,140 +120,67 @@ static void fillAlgorithms(QXmlStreamReader &in, DeviceSelection::Algorithms &al
algorithms.push_back(algorithm);
}
static void fillVendor(const QString &vendor, QString &vendorName, QString &vendorId)
{
const auto colonIndex = vendor.lastIndexOf(':');
vendorName = vendor.mid(0, colonIndex);
if (colonIndex != -1)
vendorId = vendor.mid(colonIndex + 1);
}
static void fillVendor(QXmlStreamReader &in, QString &vendorName, QString &vendorId)
{
QString vendor;
fillElementProperty(in, vendor);
fillVendor(vendor, vendorName, vendorId);
}
static void fillSvd(QXmlStreamReader &in, QString &svd)
{
const QXmlStreamAttributes attrs = in.attributes();
in.skipCurrentElement();
svd = attrs.value("svd").toString();
}
// DeviceSelectionItem
class DeviceSelectionItem : public TreeItem
class DeviceSelectionItem final : public TreeItem
{
public:
enum class Type { Unknown, Package, Family, SubFamily, Device, DeviceVariant };
enum Column { NameColumn, VersionColumn, VendorColumn };
explicit DeviceSelectionItem(Type type = Type::Unknown)
: m_type(type)
{}
QVariant data(int column, int role) const override
{
if (role == Qt::DisplayRole && column == NameColumn)
return m_name;
return {};
}
Qt::ItemFlags flags(int column) const override
{
Q_UNUSED(column)
return Qt::ItemIsEnabled;
}
DeviceSelectionItem *parentPackItem() const
{
return static_cast<DeviceSelectionItem *>(parent());
}
QString m_name;
const Type m_type;
};
// PackageItem
class PackageItem final : public DeviceSelectionItem
{
public:
explicit PackageItem(const QString &file)
: DeviceSelectionItem(Type::Package), m_file(file), m_version(extractPackVersion(file))
enum Column { NameColumn, VersionColumn, VendorNameColumn };
explicit DeviceSelectionItem()
{}
QVariant data(int column, int role) const final
{
if (role == Qt::DisplayRole) {
if (column == NameColumn)
return m_name;
return name;
else if (column == VersionColumn)
return m_version;
else if (column == VendorColumn)
return m_vendor;
return version;
else if (column == VendorNameColumn)
return vendorName;
}
return {};
}
QString m_file;
QString m_version;
QString m_desc;
QString m_vendor;
QString m_url;
};
// FamilyItem
class FamilyItem final : public DeviceSelectionItem
{
public:
explicit FamilyItem()
: DeviceSelectionItem(Type::Family)
{}
QVariant data(int column, int role) const final
{
if (role == Qt::DisplayRole) {
if (column == NameColumn) {
return m_name;
} else if (column == VendorColumn) {
const auto colonIndex = m_vendor.lastIndexOf(':');
return m_vendor.mid(0, colonIndex);
}
}
return {};
}
QString m_desc;
QString m_vendor;
};
// SubFamilyItem
class SubFamilyItem final : public DeviceSelectionItem
{
public:
explicit SubFamilyItem()
: DeviceSelectionItem(Type::SubFamily)
{}
QString m_svd;
};
// DeviceItem
class DeviceItem final : public DeviceSelectionItem
{
public:
explicit DeviceItem()
: DeviceSelectionItem(Type::Device)
{}
Qt::ItemFlags flags(int column) const final
{
Q_UNUSED(column)
return hasChildren() ? Qt::ItemIsEnabled : (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
DeviceSelection::Cpu m_cpu;
DeviceSelection::Memories m_memories;
DeviceSelection::Algorithms m_algorithms;
};
// DeviceVariantItem
class DeviceVariantItem final : public DeviceSelectionItem
{
public:
explicit DeviceVariantItem()
: DeviceSelectionItem(Type::DeviceVariant)
{}
Qt::ItemFlags flags(int column) const final
{
Q_UNUSED(column)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QString desc;
QString fullPath;
QString name;
QString svd;
QString url;
QString vendorId;
QString vendorName;
QString version;
DeviceSelection::Algorithms algorithms;
DeviceSelection::Cpu cpu;
DeviceSelection::Memories memories;
};
// DeviceSelectionModel
@@ -298,20 +232,23 @@ void DeviceSelectionModel::parsePackage(const QString &packageFile)
}
}
void DeviceSelectionModel::parsePackage(QXmlStreamReader &in, const QString &file)
void DeviceSelectionModel::parsePackage(QXmlStreamReader &in, const QString &packageFile)
{
const auto child = new PackageItem(file);
// Create and fill the 'package' item.
const auto child = new DeviceSelectionItem;
rootItem()->appendChild(child);
child->fullPath = packageFile;
child->version = extractPackVersion(packageFile);
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
if (elementName == "name") {
child->m_name = in.readElementText().trimmed();
fillElementProperty(in, child->name);
} else if (elementName == "description") {
child->m_desc = in.readElementText().trimmed();
fillElementProperty(in, child->desc);
} else if (elementName == "vendor") {
child->m_vendor = in.readElementText().trimmed();
fillVendor(in, child->vendorName, child->vendorId);
} else if (elementName == "url") {
child->m_url = in.readElementText().trimmed();
fillElementProperty(in, child->url);
} else if (elementName == "devices") {
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
@@ -328,90 +265,93 @@ void DeviceSelectionModel::parsePackage(QXmlStreamReader &in, const QString &fil
void DeviceSelectionModel::parseFamily(QXmlStreamReader &in, DeviceSelectionItem *parent)
{
const auto child = new FamilyItem;
// Create and fill the 'family' item.
const auto child = new DeviceSelectionItem;
parent->appendChild(child);
const QXmlStreamAttributes attrs = in.attributes();
child->m_name = attrs.value("Dfamily").toString();
child->m_vendor = attrs.value("Dvendor").toString();
DeviceSelection::Cpu cpu;
DeviceSelection::Memories memories;
child->name = attrs.value("Dfamily").toString();
fillVendor(attrs.value("Dvendor").toString(), child->vendorName, child->vendorId);
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
if (elementName == "processor") {
fillCpu(in, cpu);
fillCpu(in, child->cpu);
} else if (elementName == "memory") {
fillMemories(in, memories);
fillMemories(in, child->memories);
} else if (elementName == "description") {
child->m_desc = in.readElementText().trimmed();
fillElementProperty(in, child->desc);
} else if (elementName == "subFamily") {
parseSubFamily(in, child, cpu);
parseSubFamily(in, child);
} else if (elementName == "device") {
parseDevice(in, child, cpu, memories);
parseDevice(in, child);
} else {
in.skipCurrentElement();
}
}
}
void DeviceSelectionModel::parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent,
DeviceSelection::Cpu &cpu)
void DeviceSelectionModel::parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent)
{
const auto child = new SubFamilyItem;
// Create and fill the 'sub-family' item.
const auto child = new DeviceSelectionItem;
parent->appendChild(child);
const QXmlStreamAttributes attrs = in.attributes();
child->m_name = attrs.value("DsubFamily").toString();
child->name = attrs.value("DsubFamily").toString();
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
if (elementName == "processor") {
fillCpu(in, cpu);
fillCpu(in, child->cpu);
} else if (elementName == "debug") {
const QXmlStreamAttributes attrs = in.attributes();
in.skipCurrentElement();
child->m_svd = attrs.value("svd").toString();
fillSvd(in, child->svd);
} else if (elementName == "device") {
DeviceSelection::Memories memories;
parseDevice(in, child, cpu, memories);
parseDevice(in, child);
} else {
in.skipCurrentElement();
}
}
}
void DeviceSelectionModel::parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent,
DeviceSelection::Cpu &cpu,
DeviceSelection::Memories &memories)
void DeviceSelectionModel::parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent)
{
const auto child = new DeviceItem;
// Create and fill the 'device' item.
const auto child = new DeviceSelectionItem;
parent->appendChild(child);
const QXmlStreamAttributes attrs = in.attributes();
child->m_name = attrs.value("Dname").toString();
DeviceSelection::Algorithms algorithms;
child->name = attrs.value("Dname").toString();
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
if (elementName == "processor") {
fillCpu(in, cpu);
fillCpu(in, child->cpu);
} else if (elementName == "memory") {
fillMemories(in, memories);
fillMemories(in, child->memories);
} else if (elementName == "algorithm") {
fillAlgorithms(in, algorithms);
fillAlgorithms(in, child->algorithms);
} else if (elementName == "variant") {
parseDeviceVariant(in, child);
} else {
in.skipCurrentElement();
}
}
child->m_cpu = cpu;
child->m_memories = memories;
child->m_algorithms = algorithms;
}
void DeviceSelectionModel::parseDeviceVariant(QXmlStreamReader &in, DeviceSelectionItem *parent)
{
const auto child = new DeviceVariantItem;
// Create and fill the 'device-variant' item.
const auto child = new DeviceSelectionItem;
parent->appendChild(child);
const QXmlStreamAttributes attrs = in.attributes();
child->name = attrs.value("Dvariant").toString();
while (in.readNextStartElement()) {
const QStringRef elementName = in.name();
if (elementName == "processor") {
fillCpu(in, child->cpu);
} else if (elementName == "memory") {
fillMemories(in, child->memories);
} else if (elementName == "algorithm") {
fillAlgorithms(in, child->algorithms);
} else {
in.skipCurrentElement();
child->m_name = attrs.value("Dvariant").toString();
}
}
}
// DeviceSelectionView
@@ -433,70 +373,87 @@ void DeviceSelectionView::currentChanged(const QModelIndex &current, const QMode
if (!selectionModel)
return;
const DeviceSelectionItem *item = selectionModel->itemForIndex(current);
if (isValidItem(item)) {
if (!item || item->hasChildren())
return; // We need only in a last 'device' or 'device-variant' item!
const auto selection = buildSelection(item);
if (!selection.name.isEmpty())
emit deviceSelected(selection);
}
}
bool DeviceSelectionView::isValidItem(const DeviceSelectionItem *item) const
{
if (!item)
return false;
if (item->m_type == DeviceSelectionItem::Type::DeviceVariant)
return true;
if (item->m_type == DeviceSelectionItem::Type::Device && !item->hasChildren())
return true;
return false;
}
DeviceSelection DeviceSelectionView::buildSelection(const DeviceSelectionItem *item) const
{
DeviceSelection selection;
// We need to iterate from the lower 'Device|DeviceVariant' items to
// the upper 'Package' item to fill whole information.
// We need to iterate from the lower 'device' or 'device-variant' item to
// the upper 'package' item to fill a whole information.
DeviceSelection::Algorithms &algs = selection.algorithms;
DeviceSelection::Cpu &cpu = selection.cpu;
DeviceSelection::Memories &mems = selection.memories;
DeviceSelection::Package &pkg = selection.package;
do {
switch (item->m_type) {
case DeviceSelectionItem::Type::DeviceVariant:
selection.name = item->m_name;
break;
case DeviceSelectionItem::Type::Device: {
const auto deviceItem = static_cast<const DeviceItem *>(item);
if (!deviceItem->hasChildren())
selection.name = item->m_name;
selection.cpu = deviceItem->m_cpu;
selection.memories = deviceItem->m_memories;
selection.algorithms = deviceItem->m_algorithms;
if (selection.name.isEmpty())
selection.name = item->name;
else if (selection.subfamily.isEmpty())
selection.subfamily = item->name;
else if (selection.family.isEmpty())
selection.family = item->name;
else if (pkg.name.isEmpty())
pkg.name = item->name;
if (selection.desc.isEmpty())
selection.desc = item->desc;
else if (pkg.desc.isEmpty())
pkg.desc = item->desc;
if (selection.vendorId.isEmpty())
selection.vendorId = item->vendorId;
else if (pkg.vendorId.isEmpty())
pkg.vendorId = item->vendorId;
if (selection.vendorName.isEmpty())
selection.vendorName = item->vendorName;
else if (pkg.vendorName.isEmpty())
pkg.vendorName = item->vendorName;
if (selection.svd.isEmpty())
selection.svd = item->svd;
if (cpu.clock.isEmpty())
cpu.clock = item->cpu.clock;
if (cpu.core.isEmpty())
cpu.core = item->cpu.core;
if (cpu.fpu.isEmpty())
cpu.fpu = item->cpu.fpu;
if (cpu.mpu.isEmpty())
cpu.mpu = item->cpu.mpu;
if (pkg.file.isEmpty())
pkg.file = item->fullPath;
if (pkg.url.isEmpty())
pkg.url = item->url;
if (pkg.version.isEmpty())
pkg.version = item->version;
// Add only new flash algorithms.
for (const DeviceSelection::Algorithm &newAlg : item->algorithms) {
const bool contains = Utils::contains(algs, [&newAlg](const DeviceSelection::Algorithm &existAlg) {
return newAlg.path == existAlg.path;
});
if (!contains)
algs.push_back(newAlg);
}
break;
case DeviceSelectionItem::Type::SubFamily: {
const auto subFamilyItem = static_cast<const SubFamilyItem *>(item);
selection.subfamily = subFamilyItem->m_name;
selection.svd = subFamilyItem->m_svd;
// Add only new memory regions.
for (const DeviceSelection::Memory &newMem : item->memories) {
const bool contains = Utils::contains(mems, [&newMem](const DeviceSelection::Memory &existMem) {
return newMem.id == existMem.id;
});
if (!contains)
mems.push_back(newMem);
}
break;
case DeviceSelectionItem::Type::Family: {
const auto familyItem = static_cast<const FamilyItem *>(item);
selection.family = familyItem->m_name;
selection.desc = familyItem->m_desc;
selection.vendor = familyItem->m_vendor;
}
break;
case DeviceSelectionItem::Type::Package: {
const auto packageItem = static_cast<const PackageItem *>(item);
selection.package.desc = packageItem->m_desc;
selection.package.file = packageItem->m_file;
selection.package.name = packageItem->m_name;
selection.package.url = packageItem->m_url;
selection.package.vendor = packageItem->m_vendor;
selection.package.version = packageItem->m_version;
}
break;
default:
break;
}
} while ((item = item->parentPackItem()));
} while ((item->level() > 1) && (item = static_cast<const DeviceSelectionItem *>(item->parent())));
return selection;
}

View File

@@ -52,12 +52,10 @@ public:
private:
void parsePackage(const QString &packageFile);
void parsePackage(QXmlStreamReader &in, const QString &file);
void parsePackage(QXmlStreamReader &in, const QString &packageFile);
void parseFamily(QXmlStreamReader &in, DeviceSelectionItem *parent);
void parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent,
DeviceSelection::Cpu &cpu);
void parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent,
DeviceSelection::Cpu &cpu, DeviceSelection::Memories &memories);
void parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent);
void parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent);
void parseDeviceVariant(QXmlStreamReader &in, DeviceSelectionItem *parent);
Utils::FilePath m_toolsIniFile;
@@ -77,7 +75,6 @@ signals:
private:
void currentChanged(const QModelIndex &current, const QModelIndex &previous) final;
bool isValidItem(const DeviceSelectionItem *item) const;
DeviceSelection buildSelection(const DeviceSelectionItem *item) const;
};

View File

@@ -41,14 +41,16 @@ constexpr char packageDescrKeyC[] = "BareMetal.UvscServerProvider.PackageDescrip
constexpr char packageFileKeyC[] = "BareMetal.UvscServerProvider.PackageFile";
constexpr char packageNameKeyC[] = "BareMetal.UvscServerProvider.PackageName";
constexpr char packageUrlKeyC[] = "BareMetal.UvscServerProvider.PackageUrl";
constexpr char packageVendorKeyC[] = "BareMetal.UvscServerProvider.PackageVendor";
constexpr char packageVendorNameKeyC[] = "BareMetal.UvscServerProvider.PackageVendorName";
constexpr char packageVendorIdKeyC[] = "BareMetal.UvscServerProvider.PackageVendorId";
constexpr char packageVersionKeyC[] = "BareMetal.UvscServerProvider.PackageVersion";
// Device data keys.
constexpr char deviceNameKeyC[] = "BareMetal.UvscServerProvider.DeviceName";
constexpr char deviceDescrKeyC[] = "BareMetal.UvscServerProvider.DeviceDescription";
constexpr char deviceFamilyKeyC[] = "BareMetal.UvscServerProvider.DeviceFamily";
constexpr char deviceSubFamilyKeyC[] = "BareMetal.UvscServerProvider.DeviceSubFamily";
constexpr char deviceVendorKeyC[] = "BareMetal.UvscServerProvider.DeviceVendor";
constexpr char deviceVendorNameKeyC[] = "BareMetal.UvscServerProvider.DeviceVendorName";
constexpr char deviceVendorIdKeyC[] = "BareMetal.UvscServerProvider.DeviceVendorId";
constexpr char deviceSvdKeyC[] = "BareMetal.UvscServerProvider.DeviceSVD";
// Device CPU data keys.
constexpr char deviceClockKeyC[] = "BareMetal.UvscServerProvider.DeviceClock";
@@ -77,14 +79,16 @@ QVariantMap DeviceSelection::toMap() const
map.insert(packageFileKeyC, package.file);
map.insert(packageNameKeyC, package.name);
map.insert(packageUrlKeyC, package.url);
map.insert(packageVendorKeyC, package.vendor);
map.insert(packageVendorNameKeyC, package.vendorName);
map.insert(packageVendorIdKeyC, package.vendorId);
map.insert(packageVersionKeyC, package.version);
// Device.
map.insert(deviceNameKeyC, name);
map.insert(deviceDescrKeyC, desc);
map.insert(deviceFamilyKeyC, family);
map.insert(deviceSubFamilyKeyC, subfamily);
map.insert(deviceVendorKeyC, vendor);
map.insert(deviceVendorNameKeyC, vendorName);
map.insert(deviceVendorIdKeyC, vendorId);
map.insert(deviceSvdKeyC, svd);
// Device CPU.
map.insert(deviceClockKeyC, cpu.clock);
@@ -122,14 +126,16 @@ void DeviceSelection::fromMap(const QVariantMap &map)
package.file = map.value(packageFileKeyC).toString();
package.name = map.value(packageNameKeyC).toString();
package.url = map.value(packageUrlKeyC).toString();
package.vendor = map.value(packageVendorKeyC).toString();
package.vendorName = map.value(packageVendorNameKeyC).toString();
package.vendorId = map.value(packageVendorIdKeyC).toString();
package.version = map.value(packageVersionKeyC).toString();
// Device.
name = map.value(deviceNameKeyC).toString();
desc = map.value(deviceDescrKeyC).toString();
family = map.value(deviceFamilyKeyC).toString();
subfamily = map.value(deviceSubFamilyKeyC).toString();
vendor = map.value(deviceVendorKeyC).toString();
vendorName = map.value(deviceVendorNameKeyC).toString();
vendorId = map.value(deviceVendorIdKeyC).toString();
svd = map.value(deviceSvdKeyC).toString();
// Device CPU.
cpu.clock = map.value(deviceClockKeyC).toString();
@@ -163,7 +169,8 @@ bool DeviceSelection::Package::operator==(const Package &other) const
{
return desc == other.desc && file == other.file
&& name == other.name && url == other.url
&& vendor == other.vendor && version == other.version;
&& vendorName == other.vendorName && vendorId == other.vendorId
&& version == other.version;
}
bool DeviceSelection::Cpu::operator==(const Cpu &other) const
@@ -186,7 +193,8 @@ bool DeviceSelection::operator==(const DeviceSelection &other) const
{
return package == other.package && name == other.name && desc == other.desc
&& family == other.family && subfamily == other.subfamily
&& vendor == other.vendor && svd == other.svd && cpu == other.cpu
&& vendorName == other.vendorName && vendorId == other.vendorId
&& svd == other.svd && cpu == other.cpu
&& memories == other.memories && algorithms == other.algorithms
&& algorithmIndex == other.algorithmIndex;
}

View File

@@ -46,7 +46,8 @@ public:
QString file;
QString name;
QString url;
QString vendor;
QString vendorId;
QString vendorName;
QString version;
bool operator==(const Package &other) const;
@@ -84,7 +85,8 @@ public:
QString desc;
QString family;
QString subfamily;
QString vendor;
QString vendorId;
QString vendorName;
QString svd;
Cpu cpu;
Memories memories;

View File

@@ -105,7 +105,7 @@ static QString trimVendor(const QString &vendor)
void DeviceSelectorDetailsPanel::refresh()
{
m_vendorEdit->setText(trimVendor(m_selection.vendor));
m_vendorEdit->setText(trimVendor(m_selection.vendorName));
m_fimilyEdit->setText(m_selection.family);
m_descEdit->setPlainText(m_selection.desc);
m_memoryView->refresh();