总体思路:
用Xml记录寄存器地址信息,解析xml后在QtableView中显示出来;
QtableView使用模型视图,自定义模型,设置代理
.pro文件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
RegisterItem.cpp \
RegisterMapWdgt.cpp \
RegisterTableModel.cpp \
main.cpp \
MainWindow.cpp
HEADERS += \
MainWindow.h \
RegisterItem.h \
RegisterMapWdgt.h \
RegisterTableModel.h
FORMS += \
MainWindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
MainWindow.h
#pragma once
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class RegisterMapWdgt;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
RegisterMapWdgt *m_pRegisterMapWdgt = nullptr;
};
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "RegisterMapWdgt.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pRegisterMapWdgt = new RegisterMapWdgt(this);
this->setCentralWidget(m_pRegisterMapWdgt);
}
MainWindow::~MainWindow()
{
delete ui;
}
RegisterItem.h
#pragma once
#include <QVariant>
#include <QVector>
class RegisterItem
{
public:
typedef QMap<int,QVariant> Data;
RegisterItem();
int columnCount() const;
QVariant data(int column, int role) const;
bool setData(int column, const QVariant& value, int role = Qt::DisplayRole);
private:
QVector<Data> mColumns;
};
inline int RegisterItem::columnCount() const {
return mColumns.size();
}
RegisterItem.cpp
#include "RegisterItem.h"
RegisterItem::RegisterItem()
{
}
QVariant RegisterItem::data(int column, int role) const
{
Q_ASSERT(column >= 0 && column < columnCount());
return mColumns[column][role];
}
bool RegisterItem::setData(int column, const QVariant& value, int role)
{
#if 1
if(column < 0)
return false;
while (columnCount() <= column) {
mColumns << Data();
}
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
mColumns[column][Qt::DisplayRole] = value;
mColumns[column][Qt::EditRole] = value;
return true;
}
mColumns[column][role] = value;
return true;
#endif
}
RegisterTableModel.h
#pragma once
#include <QAbstractTableModel>
#include "RegisterItem.h"
class RegisterTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
RegisterTableModel();
enum Columns { RegisterName , Address , Default, Size, Value };
public: // QAbstractItemModel interface
int rowCount(const QModelIndex& parent) const;
int columnCount(const QModelIndex& parent) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex& index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
void AddElement(const RegisterItem & item);
public:
void initModel(const QVector<RegisterItem>& rows);
private:
QVector<RegisterItem> mRows;
};
RegisterTableModel.cpp
#include "RegisterTableModel.h"
RegisterTableModel::RegisterTableModel()
{
}
int RegisterTableModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return mRows.size();
}
int RegisterTableModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return mRows.size() ? mRows[0].columnCount() : 0;
}
QVariant RegisterTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
switch (section)
{
case RegisterName:
return "Register Name";
case Address:
return "Address";
case Default:
return "Default";
case Size:
return "Size";
case Value:
return "Value";
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
QVariant RegisterTableModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= mRows.size()) {
return QVariant();
}
const int row = index.row();
return mRows[row].data(index.column(), role);
}
bool RegisterTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= mRows.count())
{
return false;
}
bool bResult = mRows[index.row()].setData(index.column(),value,role);
if(!bResult)
{
return false;
}
emit dataChanged(index, index);
return true;
}
Qt::ItemFlags RegisterTableModel::flags(const QModelIndex &index) const
{
if (index.column() == RegisterName)
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable ;
}
else if (index.column() == Address)
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
return QAbstractTableModel::flags(index);
}
void RegisterTableModel::initModel(const QVector<RegisterItem>& rows)
{
beginResetModel();
mRows.clear();
mRows = rows;
endResetModel();
}
void RegisterTableModel::AddElement(const RegisterItem & item)
{
const int count = mRows.size();
beginInsertRows(QModelIndex(), count, count);
mRows.append(item);
endInsertRows();
}
RegisterMapWdgt.h
#pragma once
#include <QWidget>
class QPushButton;
class RegisterTableModel;
class QSortFilterProxyModel;
class QTableView;
class RegisterMapWdgt :public QWidget
{
public:
explicit RegisterMapWdgt(QWidget *parent = nullptr);
~RegisterMapWdgt();
private:
RegisterTableModel *m_pRegisterTableModel = nullptr;
QSortFilterProxyModel *m_pSortFilterModel = nullptr;
QPushButton *m_pCreatBtn = nullptr;
QTableView *m_pRegistMapTableView = nullptr;
private:
void InitCtr(void);
void CreateRegisterItems(int count);
bool OnParseRegsXml(const QString &filePath);
};
RegisterMapWdgt.cpp
#include "RegisterMapWdgt.h"
#include "qpushbutton.h"
#include "qtableview.h"
#include <QSortFilterProxyModel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDebug>
#include <QXmlStreamReader>
#include <QFile>
#include "RegisterTableModel.h"
RegisterMapWdgt::RegisterMapWdgt(QWidget *parent): QWidget(parent)
{
InitCtr();
}
RegisterMapWdgt::~RegisterMapWdgt()
{
delete m_pRegisterTableModel;
delete m_pSortFilterModel;
delete m_pRegistMapTableView;
}
void RegisterMapWdgt::InitCtr(void)
{
m_pRegisterTableModel = new RegisterTableModel();
m_pSortFilterModel = new QSortFilterProxyModel();
m_pCreatBtn = new QPushButton(tr("Creat"),this);
m_pRegistMapTableView = new QTableView(this);
m_pSortFilterModel->setSourceModel(m_pRegisterTableModel);
m_pRegistMapTableView->setModel(m_pSortFilterModel);
// m_pRegistMapTableView->setModel(m_pRegisterTableModel);
m_pRegistMapTableView->setSortingEnabled(true);
m_pRegistMapTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pRegisterTableModel->setHeaderData(0,Qt::Horizontal,tr("Register Name"));
m_pRegisterTableModel->setHeaderData(1,Qt::Horizontal,tr("Address"));
QVBoxLayout *vertlayout = new QVBoxLayout();
vertlayout->addWidget(m_pCreatBtn);
vertlayout->addWidget(m_pRegistMapTableView);
setLayout(vertlayout);
// CreateRegisterItems(20);
QString regsFile ("../myxmlstream/Registers.xml");
OnParseRegsXml(regsFile);
}
void RegisterMapWdgt::CreateRegisterItems(int count)
{
// QStringList listOne = QStringLiteral("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z")
// .split(QLatin1Char(' '));
char addr = 0;
QVector<RegisterItem> rows;
RegisterItem newRow;
newRow.setData( 0, QStringLiteral("VERSION"));
newRow.setData( 1, QString("%1h").arg(addr++,2,10, QLatin1Char('0')));
newRow.setData( 2, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
newRow.setData( 3, QString("%1").arg(32,2,10, QLatin1Char('0')));
newRow.setData( 4, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
m_pRegisterTableModel->AddElement(newRow);
newRow.setData( 0, QStringLiteral("PKT_CTL"));
newRow.setData( 1, QString("%1h").arg(addr++,2,10, QLatin1Char('0')));
newRow.setData( 2, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
newRow.setData( 4, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
m_pRegisterTableModel->AddElement(newRow);
newRow.setData( 0, QStringLiteral("PLL_CTL"));
newRow.setData( 1, QString("%1h").arg(addr++,2,10, QLatin1Char('0')));
newRow.setData( 2, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
newRow.setData( 4, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
m_pRegisterTableModel->AddElement(newRow);
newRow.setData( 0, QStringLiteral("LVDS_CTL"));
newRow.setData( 1, QString("%1h").arg(addr++,2,10, QLatin1Char('0')));
newRow.setData( 2, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
newRow.setData( 4, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
m_pRegisterTableModel->AddElement(newRow);
newRow.setData( 0, QStringLiteral("LVDS_DAT"));
newRow.setData( 1, QString("%1h").arg(addr++,2,10, QLatin1Char('0')));
newRow.setData( 2, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
newRow.setData( 4, QString("0x%1").arg(addr,4,16, QLatin1Char('0')));
m_pRegisterTableModel->AddElement(newRow);
}
bool RegisterMapWdgt::OnParseRegsXml(const QString &filePath)
{
QFile file(filePath);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
qDebug()<<"Error: cannot open file";
return 1;
}
QXmlStreamReader reader;
// 设置文件,这时会将流设置为初始状态
reader.setDevice(&file);
RegisterItem newRow;
// 如果没有读到文档结尾,而且没有出现错误
while (!reader.atEnd()) {
// 读取下一个记号,它返回记号的类型
QXmlStreamReader::TokenType type = reader.readNext();
// 下面便根据记号的类型来进行不同的输出
if (type == QXmlStreamReader::StartDocument)
qDebug() << reader.documentEncoding() << reader.documentVersion();
if (type == QXmlStreamReader::StartElement) {
qDebug() << "<" << reader.name() << ">";
if (reader.attributes().hasAttribute("id"))
qDebug() << reader.attributes().value("id");
if(reader.name() == "Reg_Name")
{
newRow.setData( 0, reader.readElementText());
}else if(reader.name() == "Address")
{
newRow.setData( 1,reader.readElementText());
}else if(reader.name() == "Default_Value")
{
newRow.setData( 2,reader.readElementText());
}else if(reader.name() == "Size")
{
newRow.setData( 3,reader.readElementText());
}else if(reader.name() == "Value")
{
newRow.setData( 4,reader.readElementText());
}
}
if (type == QXmlStreamReader::EndElement)
{
qDebug() << "</" << reader.name() << ">";
m_pRegisterTableModel->AddElement(newRow);
}
if (type == QXmlStreamReader::Characters && !reader.isWhitespace())
{
qDebug() << "text"<<reader.text();
}
}
// 如果读取过程中出现错误,那么输出错误信息
if (reader.hasError()) {
qDebug() << "error: " << reader.errorString();
}
file.close();
}