此文是讀取和存儲已知結構的xml,對於未知結構的xml,可以用遞歸方法讀取和遍歷。可參考文章:Qt遍歷不規則樹的節點。
1、QTreewidget設置
//折疊圖標(三角圖標)換成自定義圖標
ui->treeWidget->setStyleSheet("QTreeView::branch:has-children:!has-siblings:closed,\
QTreeView::branch:closed:has-children:has-siblings{border-image: none; image: url(:/images/plus.png);}\
QTreeView::branch:open:has-children:!has-siblings,\
QTreeView::branch:open:has-children:has-siblings{border-image: none; image: url(:/images/minus.png);}");
2、顯示保存xml
頭文件
#ifndef PROCESSDEVICEXML_H
#define PROCESSDEVICEXML_H
#include <QObject>
#include <QDomElement>
#include <QTreeWidget>
#include "public.h"
#define ManageDeviceStr "ManageDevice"
#define SystemStr "System"
#define SubSystemStr "SubSystem"
#define DeviceStr "Device"
#define NameStr "name"
#define TypeStr "type"
#define DeviceXmlName "DeviceItem.xml"
class ProcessDeviceXml : public QObject
{
Q_OBJECT
public:
explicit ProcessDeviceXml(QObject *parent = nullptr);
bool OpenXml(QString fileName, QList<DeviceInfo>& listDev, QTreeWidget* pTreeWg = NULL);
void ShowXml(QDomElement &docElem, QList<DeviceInfo> &listDev, QTreeWidget *treeWg);
bool SaveXML(QString fileName, QTreeWidget *pTreeWg);
bool AddTreeItem(QTreeWidget *pTreeWg, QTreeWidgetItem *clickedItem, int itemType);
bool delTreeItem(QTreeWidget *pTreeWg, QTreeWidgetItem *clickedItem, int nType);
signals:
public slots:
private:
};
#endif // PROCESSDEVICEXML_H
源文件:
顯示圖標時,要換成自己的圖標路徑;如果出現編譯不通過,需要根據情況修改一下。
#include "processdevicexml.h"
#include <QTextStream>
#include <QMessageBox>
#include <QFile>
#include <QDebug>
#include "public.h"
#include "adddevicedlg.h"
#include "extern.h"
ProcessDeviceXml::ProcessDeviceXml(QObject *parent) : QObject(parent)
{
}
bool ProcessDeviceXml::OpenXml(QString fileName, QList<DeviceInfo>& listDeviceName, QTreeWidget* pTreeWg)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly))
{
QDomDocument dom;
QString errorStr;
int errorLine;
int errorCol;
if (!dom.setContent(&file, true, &errorStr, &errorLine, &errorCol))
{
qDebug() << errorStr << "line: " << errorLine << "col: " << errorCol;
file.close();
return false;
}
else
{
pTreeWg->clear();
QDomElement docElem = dom.documentElement();
ShowXml(docElem, listDeviceName, pTreeWg);
pTreeWg->expandAll();
}
file.close();
return true;
}
else {
file.close();
return false;
}
}
void ProcessDeviceXml::ShowXml(QDomElement& docElem, QList<DeviceInfo>& listDev, QTreeWidget* treeWg)
{
//根節點
QTreeWidgetItem *projectItem = new QTreeWidgetItem(treeWg);
QString projectName = docElem.attribute(NameStr);
projectItem->setText(0, projectName);
projectItem->setData(0, Qt::UserRole, QString::number(TypeProject));
projectItem->setIcon(0, QIcon(QStringLiteral(":/image/system.png")));
projectItem->setWhatsThis(0, SystemStr);
listDev.clear();
QDomNode systemNode = docElem.firstChild();
while (!systemNode.isNull())
{
DeviceInfo devInfo;
devInfo.listDevName.clear();
QDomElement elementSystem = systemNode.toElement(); // try to convert the node to an element.
if (elementSystem.tagName() == QStringLiteral(SystemStr))
{
QTreeWidgetItem *systemItem = new QTreeWidgetItem(projectItem);
//系統節點
QString strSystemName = elementSystem.attribute(NameStr);
devInfo.qstrSystemName = strSystemName;
systemItem->setText(0, strSystemName);
systemItem->setData(0, Qt::UserRole, QString::number(TypeSystem));
systemItem->setIcon(0, QIcon(QStringLiteral(":/image/system.png")));
systemItem->setWhatsThis(0, SystemStr);
//子系統節點
QDomNode subsystemNode = systemNode.firstChild();
while (!subsystemNode.isNull())
{
QDomElement elementDev = subsystemNode.toElement();
if (elementDev.tagName() == QStringLiteral(SubSystemStr))
{
QString strDevName = elementDev.attribute(NameStr);
QTreeWidgetItem *subsystemItem = new QTreeWidgetItem(systemItem);
subsystemItem->setText(0, strDevName);
subsystemItem->setIcon(0, QIcon(QStringLiteral(":/image/subSystem.png")));
subsystemItem->setData(0, Qt::UserRole, QString::number(TypeSubsystem));
subsystemItem->setWhatsThis(0, SubSystemStr);
QDomNode devNode = subsystemNode.firstChild();
while (!devNode.isNull())
{
QDomElement elementDev = devNode.toElement();
if (elementDev.tagName() == QStringLiteral(DeviceStr))
{
QString strDevName = elementDev.attribute(NameStr);
QTreeWidgetItem *devItem = new QTreeWidgetItem(subsystemItem);
devItem->setText(0, strDevName);
devItem->setIcon(0, QIcon(QStringLiteral(":/Qimage/device.png")));
devItem->setWhatsThis(0, DeviceStr);
devItem->setData(0, Qt::UserRole, QString::number(TypeDevice));
devInfo.listDevName.push_back(strDevName);
}
devNode = devNode.nextSibling();
}
}
subsystemNode = subsystemNode.nextSibling();
}
}
//下一個分組節點
listDev.push_back(devInfo);
systemNode = systemNode.nextSibling();
}
return;
}
bool ProcessDeviceXml::SaveXML(QString fileName, QTreeWidget* pTreeWg)
{
QTreeWidgetItem *rootItem = pTreeWg->invisibleRootItem(); //樹的根節點
int countSystem = rootItem->childCount();
if (countSystem <= 0) //列表樹沒有項
{
return false;
}
QFile db(fileName);
if (!db.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false;
//只寫方式打開,並清空以前的信息
QDomDocument doc;
QDomProcessingInstruction instruction;
instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
QDomElement root = doc.createElement(ManageDeviceStr);
QString projectName = p_globalObject->getProjectName();
QDomAttr elementProjAttr = doc.createAttribute(NameStr);
elementProjAttr.setValue(projectName);
root.setAttributeNode(elementProjAttr);
doc.appendChild(root); //添加根元素
QTreeWidgetItem* projectItem = rootItem->child(0);
countSystem = projectItem->childCount();
for (int i = 0; i < countSystem; i++)
{
QTreeWidgetItem *systemItem = projectItem->child(i);
QString systemName = systemItem->text(0);
QDomElement elementSystem = doc.createElement(SystemStr);
QDomAttr elementSystemAttr = doc.createAttribute(NameStr);
elementSystemAttr.setValue(systemName);
elementSystem.setAttributeNode(elementSystemAttr);
root.appendChild(elementSystem);
int countSubsystem = systemItem->childCount();
for (int j = 0; j < countSubsystem; j++)
{
QTreeWidgetItem *subsystemItem = systemItem->child(j);
QDomElement elementSubsystem = doc.createElement(SubSystemStr);
//子系統項屬性name
QString subsystemName = subsystemItem->text(0);
QDomAttr elementSubsystemNameAttr = doc.createAttribute(NameStr);
elementSubsystemNameAttr.setValue(subsystemName);
elementSubsystem.setAttributeNode(elementSubsystemNameAttr);
elementSystem.appendChild(elementSubsystem);
int coutDev = subsystemItem->childCount();
for (int k = 0; k < coutDev; k++)
{
QTreeWidgetItem *devItem = subsystemItem->child(k);
QString devName = devItem->text(0);
QDomElement elementChn = doc.createElement(DeviceStr);
QDomAttr elementChnAttr = doc.createAttribute(NameStr);
elementChnAttr.setValue(devName);
elementChn.setAttributeNode(elementChnAttr);
elementSubsystem.appendChild(elementChn);
}
}
}
QTextStream out(&db);
out.setCodec("UTF-8");
doc.save(out, 4);
db.close();
return true;
}
bool ProcessDeviceXml::AddTreeItem(QTreeWidget* pTreeWg, QTreeWidgetItem* clickedItem, int itemType)
{
QString qstrCaption;
int nType = TypeDevice;
switch (itemType) {
case TypeProject://添加系統
qstrCaption = "添加系統";
nType = TypeSystem;
break;
case TypeSystem://添加分系統
qstrCaption = "添加子系統";
nType = TypeSubsystem;
break;
case TypeSubsystem://添加設備
case TypeDevice:
qstrCaption = "添加設備";
nType = TypeDevice;
break;
default:
break;
}
AddDeviceDlg dlg;
dlg.SetCaption(qstrCaption);
if(dlg.exec() == QDialog::Rejected){
return false;
}
QString txt = dlg.GetTxt();
QTreeWidgetItem *item = new QTreeWidgetItem(clickedItem);
item->setText(0, txt);
item->setData(0, Qt::UserRole, QString::number(nType));
item->setIcon(0, QIcon(QStringLiteral(":image/group.png")));
item->setWhatsThis(0, qstrCaption);
pTreeWg->expandItem(clickedItem);
return true;
}
