使用json配置
This commit is contained in:
parent
9aa354ffbc
commit
fbd1be96d8
|
@ -0,0 +1,163 @@
|
||||||
|
#include "JsonTreeItem.h"
|
||||||
|
|
||||||
|
JsonTreeItem::JsonTreeItem(JsonTreeItem *parent)
|
||||||
|
:theParentItem(parent)
|
||||||
|
,theItemType(JsonTreeItem::None)
|
||||||
|
,theItemDatas({{0,"[Key]"},{1,"[Value]"}}) //默认两行
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem::JsonTreeItem(const QHash<int, QVariant> &datas, JsonTreeItem::JsonItemType type, JsonTreeItem *parent)
|
||||||
|
:theParentItem(parent)
|
||||||
|
,theItemType(type)
|
||||||
|
,theItemDatas(datas)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem::~JsonTreeItem()
|
||||||
|
{
|
||||||
|
deleteAllChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeItem::insertChild(int row, JsonTreeItem *child)
|
||||||
|
{
|
||||||
|
if(row<0||row>theChildItems.count())
|
||||||
|
return false;
|
||||||
|
theChildItems.insert(row,child);
|
||||||
|
child->setParentItem(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeItem::removeChild(int row)
|
||||||
|
{
|
||||||
|
if(row<0||row+1>theChildItems.count())
|
||||||
|
return false;
|
||||||
|
delete theChildItems.takeAt(row);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeItem::insertChildren(int row, int count)
|
||||||
|
{
|
||||||
|
if(row<0||row>theChildItems.count())
|
||||||
|
return false;
|
||||||
|
for(int i=0;i<count;i++){
|
||||||
|
JsonTreeItem *item=new JsonTreeItem(this);
|
||||||
|
//目前还没有delegate来自定义操作,所以new item默认为json Value类型
|
||||||
|
item->setType(JsonTreeItem::Value);
|
||||||
|
//这里新增的次序无所谓row+i
|
||||||
|
theChildItems.insert(row,item);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeItem::removeChildren(int row, int count)
|
||||||
|
{
|
||||||
|
if (row<0||row+count>theChildItems.count())
|
||||||
|
return false;
|
||||||
|
for(int i=0;i<count;i++){
|
||||||
|
delete theChildItems.takeAt(row+i);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::appendChild(JsonTreeItem *child)
|
||||||
|
{
|
||||||
|
theChildItems.append(child);
|
||||||
|
child->setParentItem(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::deleteAllChild()
|
||||||
|
{
|
||||||
|
qDeleteAll(theChildItems);
|
||||||
|
theChildItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem *JsonTreeItem::childItem(int row)
|
||||||
|
{
|
||||||
|
return theChildItems.value(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem *JsonTreeItem::parentItem()
|
||||||
|
{
|
||||||
|
return theParentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::setParentItem(JsonTreeItem *parent)
|
||||||
|
{
|
||||||
|
theParentItem=parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JsonTreeItem::childCount() const
|
||||||
|
{
|
||||||
|
return theChildItems.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int JsonTreeItem::columnCount() const
|
||||||
|
{
|
||||||
|
return theItemDatas.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant JsonTreeItem::data(int column) const
|
||||||
|
{
|
||||||
|
return theItemDatas.value(column,QVariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::setData(int column, const QVariant &val)
|
||||||
|
{
|
||||||
|
theItemDatas.insert(column,val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int JsonTreeItem::row() const
|
||||||
|
{
|
||||||
|
if(theParentItem)
|
||||||
|
return theParentItem->theChildItems.indexOf(const_cast<JsonTreeItem*>(this));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeItem::editable(int column) const
|
||||||
|
{
|
||||||
|
//在保留默认结构的情况下
|
||||||
|
//root的key-value都不可编辑
|
||||||
|
//-->parent:nullptr
|
||||||
|
//array下级的key不可编辑
|
||||||
|
//-->parent:array
|
||||||
|
//array或object的value不可编辑
|
||||||
|
//-->type()
|
||||||
|
//此外,如果希望key不可变,column==0返回false即可
|
||||||
|
if((!theParentItem||!theParentItem->parentItem())||
|
||||||
|
((0==column)&&(theParentItem->type()==JsonTreeItem::Array))||
|
||||||
|
((1==column)&&((type()==JsonTreeItem::Array)||(type()==JsonTreeItem::Object))))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString JsonTreeItem::key() const
|
||||||
|
{
|
||||||
|
return theItemDatas.value(0,"").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::setKey(const QString &key)
|
||||||
|
{
|
||||||
|
theItemDatas[0]=key;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant JsonTreeItem::value() const
|
||||||
|
{
|
||||||
|
return theItemDatas.value(1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::setValue(const QVariant &value)
|
||||||
|
{
|
||||||
|
theItemDatas[1]=value;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem::JsonItemType JsonTreeItem::type() const
|
||||||
|
{
|
||||||
|
return theItemType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeItem::setType(JsonTreeItem::JsonItemType type)
|
||||||
|
{
|
||||||
|
theItemType=type;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef JSONTREEITEM_H
|
||||||
|
#define JSONTREEITEM_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
//对于多种结构,可以写一个item抽象父类
|
||||||
|
//我这个Item比较简单,基本都是靠外部来设置
|
||||||
|
class JsonTreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//item的类型,None为无效的类型
|
||||||
|
enum JsonItemType{
|
||||||
|
None,
|
||||||
|
Object,
|
||||||
|
Array,
|
||||||
|
Value
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
explicit JsonTreeItem(JsonTreeItem *parent=nullptr);
|
||||||
|
explicit JsonTreeItem(const QHash<int,QVariant> &datas,JsonTreeItem::JsonItemType type,JsonTreeItem *parent=nullptr);
|
||||||
|
~JsonTreeItem();
|
||||||
|
|
||||||
|
//增删操作
|
||||||
|
bool insertChild(int row,JsonTreeItem *child);
|
||||||
|
bool removeChild(int row);
|
||||||
|
bool insertChildren(int row,int count);
|
||||||
|
bool removeChildren(int row,int count);
|
||||||
|
void appendChild(JsonTreeItem *child);
|
||||||
|
void deleteAllChild();
|
||||||
|
|
||||||
|
//用于Model结构
|
||||||
|
JsonTreeItem *childItem(int row);
|
||||||
|
JsonTreeItem *parentItem();
|
||||||
|
void setParentItem(JsonTreeItem *parent);
|
||||||
|
int childCount() const;
|
||||||
|
int columnCount() const;
|
||||||
|
QVariant data(int column) const;
|
||||||
|
void setData(int column,const QVariant &val);
|
||||||
|
int row() const;
|
||||||
|
bool editable(int column) const;
|
||||||
|
//QHash<int,QByteArray> roleNames() const;
|
||||||
|
|
||||||
|
//便于Json操作
|
||||||
|
QString key() const;
|
||||||
|
void setKey(const QString &key);
|
||||||
|
QVariant value() const;
|
||||||
|
void setValue(const QVariant &value);
|
||||||
|
JsonTreeItem::JsonItemType type() const;
|
||||||
|
void setType(JsonTreeItem::JsonItemType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonTreeItem *theParentItem; //构造函数来初始化parent
|
||||||
|
QList<JsonTreeItem*> theChildItems; //append来添加child
|
||||||
|
JsonItemType theItemType;
|
||||||
|
//hash内容
|
||||||
|
//1:key
|
||||||
|
//2:value
|
||||||
|
//用hash是为了便于扩展,比如增加勾选列等
|
||||||
|
//如果只是简单的key+value两行数据,就用QString+QVariant就行了
|
||||||
|
QHash<int,QVariant> theItemDatas; //存放每列(角色)的内容(qml的tree使用角色)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JSONTREEITEM_H
|
|
@ -0,0 +1,313 @@
|
||||||
|
#include "JsonTreeModel.h"
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
JsonTreeModel::JsonTreeModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent),theRootItem(new JsonTreeItem(nullptr))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeModel::~JsonTreeModel()
|
||||||
|
{
|
||||||
|
delete theRootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeModel::loadJson(const QString &filepath)
|
||||||
|
{
|
||||||
|
//判断路径以及是否正常打开
|
||||||
|
if(filepath.isEmpty())
|
||||||
|
return false;
|
||||||
|
QFile file(filepath);
|
||||||
|
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//读取数据后关闭文件
|
||||||
|
const QByteArray raw_data=file.readAll();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
//解析为Json文档
|
||||||
|
QJsonParseError json_error;
|
||||||
|
QJsonDocument json_doc=QJsonDocument::fromJson(raw_data,&json_error);
|
||||||
|
|
||||||
|
//是否正常解析Json数据
|
||||||
|
if(json_doc.isNull()||json_doc.isEmpty()||json_error.error!=QJsonParseError::NoError)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
emit beginResetModel();
|
||||||
|
theRootItem->deleteAllChild();//清空之前的model
|
||||||
|
|
||||||
|
//判断是object{}还是array[]的Json
|
||||||
|
if(json_doc.isObject()){
|
||||||
|
//解析文档中的Object
|
||||||
|
parseObject("[Root]",json_doc.object(),theRootItem);
|
||||||
|
}else if(json_doc.isArray()){
|
||||||
|
//解析文档中的Array
|
||||||
|
parseArray("[Root]",json_doc.array(),theRootItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit endResetModel();
|
||||||
|
|
||||||
|
qDebug()<<"load json file";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeModel::dumpJson(const QString &filepath)
|
||||||
|
{
|
||||||
|
if(filepath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//root 的child最多也只有一个
|
||||||
|
if(!theRootItem||theRootItem->childCount()==0)
|
||||||
|
return false;
|
||||||
|
JsonTreeItem *top_level_item=theRootItem->childItem(0);
|
||||||
|
if(!top_level_item)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//遍历Tree生成JsonDocument
|
||||||
|
QJsonDocument json_doc;
|
||||||
|
switch (top_level_item->type()) {
|
||||||
|
case JsonTreeItem::Object:
|
||||||
|
json_doc=QJsonDocument::fromVariant(dumpObject(top_level_item));
|
||||||
|
break;
|
||||||
|
case JsonTreeItem::Array:
|
||||||
|
json_doc=QJsonDocument::fromVariant(dumpArray(top_level_item));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//导出Json
|
||||||
|
QFile file(filepath);
|
||||||
|
if(!file.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||||
|
return false;
|
||||||
|
//转换为bytearray,Compact没有换行,Indented有换行可读性更强
|
||||||
|
file.write(json_doc.toJson(QJsonDocument::Indented));
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
qDebug()<<"dump json file";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex JsonTreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
JsonTreeItem *parentItem=getItem(parent);
|
||||||
|
JsonTreeItem *childItem = parentItem->childItem(row);
|
||||||
|
if (childItem)
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
else
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex JsonTreeModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
JsonTreeItem *childItem = getItem(index);
|
||||||
|
JsonTreeItem *parentItem = childItem->parentItem();
|
||||||
|
|
||||||
|
if (parentItem == theRootItem)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int JsonTreeModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
JsonTreeItem *parentItem = getItem(parent);
|
||||||
|
return parentItem->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int JsonTreeModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
JsonTreeItem *parentItem = getItem(parent);
|
||||||
|
return parentItem->columnCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant JsonTreeModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole && role != Qt::EditRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
JsonTreeItem *item = getItem(index);
|
||||||
|
return item->data(index.column());
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags JsonTreeModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
JsonTreeItem *item = getItem(index);
|
||||||
|
return (item->editable(index.column())?Qt::ItemIsEditable:Qt::NoItemFlags)
|
||||||
|
|QAbstractItemModel::flags(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if (role != Qt::EditRole)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JsonTreeItem *item = getItem(index);
|
||||||
|
item->setData(index.column(), value);
|
||||||
|
emit dataChanged(index, index, {role});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
JsonTreeItem *parentItem=getItem(parent);
|
||||||
|
|
||||||
|
beginInsertRows(parent, row, row+count-1);
|
||||||
|
const bool result=parentItem->insertChildren(row,count);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTreeModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
JsonTreeItem *parentItem=getItem(parent);
|
||||||
|
|
||||||
|
beginRemoveRows(parent, row, row+count-1);
|
||||||
|
const bool result=parentItem->removeChildren(row,count);
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonTreeItem *JsonTreeModel::getItem(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.isValid()) {
|
||||||
|
JsonTreeItem *item = static_cast<JsonTreeItem*>(index.internalPointer());
|
||||||
|
if (item)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return theRootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeModel::parseObject(const QString &key, const QJsonObject &obj, JsonTreeItem *&item)
|
||||||
|
{
|
||||||
|
//构造Object节点
|
||||||
|
JsonTreeItem *child=new JsonTreeItem({{0,key},{1,"[Object]"}},JsonTreeItem::Object,item);
|
||||||
|
item->appendChild(child);
|
||||||
|
|
||||||
|
//遍历Object的keys
|
||||||
|
const QStringList keys=obj.keys();
|
||||||
|
for(const QString &item_key:keys){
|
||||||
|
//qDebug()<<"key:"<<item_key;
|
||||||
|
parseValue(item_key,obj.value(item_key),child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeModel::parseArray(const QString &key, const QJsonArray &arr, JsonTreeItem *&item)
|
||||||
|
{
|
||||||
|
//构造Array节点
|
||||||
|
JsonTreeItem *child=new JsonTreeItem({{0,key},{1,"[Array]"}},JsonTreeItem::Array,item);
|
||||||
|
item->appendChild(child);
|
||||||
|
|
||||||
|
//遍历Array
|
||||||
|
for(int i=0;i<arr.count();i++){
|
||||||
|
parseValue("-",arr.at(i),child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonTreeModel::parseValue(const QString &key, const QJsonValue &val, JsonTreeItem *&item)
|
||||||
|
{
|
||||||
|
QVariant the_val;
|
||||||
|
//根据Value的类型进行下一步处理
|
||||||
|
//如果是Object或Array就继续递归
|
||||||
|
//如果是值就添加一个节点
|
||||||
|
switch (val.type()) {
|
||||||
|
case QJsonValue::Object:
|
||||||
|
parseObject(key,val.toObject(),item);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case QJsonValue::Array:
|
||||||
|
parseArray(key,val.toArray(),item);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case QJsonValue::Bool:
|
||||||
|
the_val=val.toBool();
|
||||||
|
break;
|
||||||
|
case QJsonValue::Double:
|
||||||
|
the_val=val.toDouble();
|
||||||
|
break;
|
||||||
|
case QJsonValue::String:
|
||||||
|
the_val=val.toString();
|
||||||
|
break;
|
||||||
|
case QJsonValue::Null: break;
|
||||||
|
case QJsonValue::Undefined: break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//构造子节点
|
||||||
|
JsonTreeItem *child=new JsonTreeItem({{0,key},{1,the_val}},JsonTreeItem::Value,item);
|
||||||
|
item->appendChild(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonTreeModel::dumpObject(JsonTreeItem *&item) const
|
||||||
|
{
|
||||||
|
QVariantMap json_obj; //QVariantMap对应QJsonObject
|
||||||
|
const int child_count=item->childCount();
|
||||||
|
for(int i=0;i<child_count;i++){
|
||||||
|
JsonTreeItem *child=item->childItem(i);
|
||||||
|
if(!child) continue;
|
||||||
|
//为什么不用一个返回QVariant的函数之类的封装下?
|
||||||
|
switch (child->type()) {
|
||||||
|
case JsonTreeItem::Object:
|
||||||
|
json_obj.insert(child->key(),dumpObject(child));
|
||||||
|
break;
|
||||||
|
case JsonTreeItem::Array:
|
||||||
|
json_obj.insert(child->key(),dumpArray(child));
|
||||||
|
break;
|
||||||
|
case JsonTreeItem::Value:
|
||||||
|
json_obj.insert(child->key(),dumpValue(child));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList JsonTreeModel::dumpArray(JsonTreeItem *&item) const
|
||||||
|
{
|
||||||
|
QVariantList json_arr; //QVariantList对应QJsonArray
|
||||||
|
const int child_count=item->childCount();
|
||||||
|
for(int i=0;i<child_count;i++){
|
||||||
|
JsonTreeItem *child=item->childItem(i);
|
||||||
|
if(!child) continue;
|
||||||
|
switch (child->type()) {
|
||||||
|
case JsonTreeItem::Object:
|
||||||
|
json_arr.append(dumpObject(child));
|
||||||
|
break;
|
||||||
|
case JsonTreeItem::Array:
|
||||||
|
json_arr.append(dumpArray(child));
|
||||||
|
break;
|
||||||
|
case JsonTreeItem::Value:
|
||||||
|
json_arr.append(dumpValue(child));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant JsonTreeModel::dumpValue(JsonTreeItem *&item) const
|
||||||
|
{
|
||||||
|
//QVariant对应QJsonValue
|
||||||
|
return item->value();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef JSONTREEMODEL_H
|
||||||
|
#define JSONTREEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include "JsonTreeItem.h"
|
||||||
|
|
||||||
|
class JsonTreeModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit JsonTreeModel(QObject *parent = nullptr);
|
||||||
|
~JsonTreeModel();
|
||||||
|
|
||||||
|
//导入导出数据
|
||||||
|
bool loadJson(const QString &filepath);
|
||||||
|
bool dumpJson(const QString &filepath);
|
||||||
|
|
||||||
|
//tree数据展示
|
||||||
|
QModelIndex index(int row, int column,
|
||||||
|
const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
//支持编辑
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value,
|
||||||
|
int role = Qt::EditRole) override;
|
||||||
|
|
||||||
|
bool insertRows(int row, int count,
|
||||||
|
const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
bool removeRows(int row, int count,
|
||||||
|
const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
|
||||||
|
//QHash<int,QByteArray> roleNames() const override; //qml中需要,widget不用
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonTreeItem *getItem(const QModelIndex &index) const;
|
||||||
|
//解析并生成tree
|
||||||
|
void parseObject(const QString &key,const QJsonObject& obj,JsonTreeItem *&item);
|
||||||
|
void parseArray(const QString &key,const QJsonArray& arr,JsonTreeItem *&item);
|
||||||
|
void parseValue(const QString &key,const QJsonValue& val,JsonTreeItem *&item);
|
||||||
|
//生成json节点
|
||||||
|
QVariantMap dumpObject(JsonTreeItem *&item) const;
|
||||||
|
QVariantList dumpArray(JsonTreeItem *&item) const;
|
||||||
|
QVariant dumpValue(JsonTreeItem *&item) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonTreeItem *theRootItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JSONTREEMODEL_H
|
|
@ -20,10 +20,14 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
JsonTreeItem.cpp \
|
||||||
|
JsonTreeModel.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
JsonTreeItem.h \
|
||||||
|
JsonTreeModel.h \
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.12.2, 2025-01-10T18:18:42. -->
|
<!-- Written by QtCreator 4.12.2, 2025-01-11T17:55:05. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|
|
@ -24,8 +24,32 @@ MainWindow::~MainWindow()
|
||||||
|
|
||||||
void MainWindow::openFile()
|
void MainWindow::openFile()
|
||||||
{
|
{
|
||||||
QString s = QFileDialog::getOpenFileName(this,"选择文件","/", "Files(*.json)");
|
static QString loadpath;
|
||||||
qDebug() << s << endl;
|
if (ui->openFile->text() == "打开文件") {
|
||||||
|
//选择导入的文件路径
|
||||||
|
loadpath = QFileDialog::getOpenFileName(this,"选择文件","/", "Files(*.json)");
|
||||||
|
qDebug() << loadpath << endl;
|
||||||
|
|
||||||
|
if(loadpath.isEmpty()) return;
|
||||||
|
jsonModel->loadJson(loadpath);
|
||||||
|
ui->treeView->expandAll();
|
||||||
|
|
||||||
|
ui->openFile->setText("保存文件");
|
||||||
|
|
||||||
|
openFileFlag = true;
|
||||||
|
|
||||||
|
if (openFileFlag && openSerialPortFlag) {
|
||||||
|
ui->readConfigFile->setEnabled(true);
|
||||||
|
ui->writeConfigFile->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
ui->readConfigFile->setEnabled(false);
|
||||||
|
ui->writeConfigFile->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(loadpath.isEmpty()) return;
|
||||||
|
jsonModel->dumpJson(loadpath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::scanSerialPort()
|
void MainWindow::scanSerialPort()
|
||||||
|
@ -50,13 +74,28 @@ void MainWindow::parityItemInit()
|
||||||
|
|
||||||
void MainWindow::Init()
|
void MainWindow::Init()
|
||||||
{
|
{
|
||||||
|
ui->readConfigFile->setEnabled(false);
|
||||||
|
ui->writeConfigFile->setEnabled(false);
|
||||||
|
|
||||||
scanSerialPort();
|
scanSerialPort();
|
||||||
parityItemInit();
|
parityItemInit();
|
||||||
serialPort = new QSerialPort(this);
|
serialPort = new QSerialPort(this);
|
||||||
|
|
||||||
|
jsonModel = new JsonTreeModel(this);
|
||||||
|
ui->treeView->setModel(jsonModel);
|
||||||
|
|
||||||
|
openSerialPortFlag = false;
|
||||||
|
openFileFlag = false;
|
||||||
|
|
||||||
|
|
||||||
connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile()));
|
connect(ui->openFile,SIGNAL(clicked()),this,SLOT(openFile()));
|
||||||
|
|
||||||
connect(ui->SerialPortPushButton,SIGNAL(clicked())
|
connect(ui->SerialPortPushButton,SIGNAL(clicked())
|
||||||
,this,SLOT(openSerialPortPushButtonClicked()));
|
,this,SLOT(openSerialPortPushButtonClicked()));
|
||||||
|
connect(ui->readConfigFile,SIGNAL(clicked())
|
||||||
|
,this,SLOT(readCfgFile()));
|
||||||
|
connect(ui->writeConfigFile,SIGNAL(clicked())
|
||||||
|
,this,SLOT(writeCfgFile()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +172,16 @@ void MainWindow::openSerialPortPushButtonClicked()
|
||||||
ui->SerialPortPushButton->setText("关闭串口");
|
ui->SerialPortPushButton->setText("关闭串口");
|
||||||
ui->label_6->setStyleSheet("color: red;");
|
ui->label_6->setStyleSheet("color: red;");
|
||||||
// pushButton[0]->setEnabled(true);
|
// pushButton[0]->setEnabled(true);
|
||||||
|
|
||||||
|
openSerialPortFlag = true;
|
||||||
|
|
||||||
|
if (openFileFlag && openSerialPortFlag) {
|
||||||
|
ui->readConfigFile->setEnabled(true);
|
||||||
|
ui->writeConfigFile->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
ui->readConfigFile->setEnabled(false);
|
||||||
|
ui->writeConfigFile->setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -144,5 +193,26 @@ void MainWindow::openSerialPortPushButtonClicked()
|
||||||
ui->comboBox_5->setEnabled(true);
|
ui->comboBox_5->setEnabled(true);
|
||||||
ui->label_6->setStyleSheet("color: block;");
|
ui->label_6->setStyleSheet("color: block;");
|
||||||
ui->SerialPortPushButton->setText("打开串口");
|
ui->SerialPortPushButton->setText("打开串口");
|
||||||
|
|
||||||
|
openSerialPortFlag = false;
|
||||||
|
|
||||||
|
if (openFileFlag && openSerialPortFlag) {
|
||||||
|
ui->readConfigFile->setEnabled(true);
|
||||||
|
ui->writeConfigFile->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
ui->readConfigFile->setEnabled(false);
|
||||||
|
ui->writeConfigFile->setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::readCfgFile()
|
||||||
|
{
|
||||||
|
qDebug(" in readCfgFile ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::writeCfgFile()
|
||||||
|
{
|
||||||
|
qDebug(" in writeCfgFile ");
|
||||||
|
}
|
||||||
|
|
11
mainwindow.h
11
mainwindow.h
|
@ -8,6 +8,8 @@
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
|
||||||
|
#include "JsonTreeModel.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class MainWindow; }
|
namespace Ui { class MainWindow; }
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -25,8 +27,14 @@ private:
|
||||||
|
|
||||||
/* 串口对象 */
|
/* 串口对象 */
|
||||||
QSerialPort *serialPort;
|
QSerialPort *serialPort;
|
||||||
|
|
||||||
QLineEdit *fileLineEdit;
|
QLineEdit *fileLineEdit;
|
||||||
|
|
||||||
|
JsonTreeModel *jsonModel;
|
||||||
|
|
||||||
|
bool openSerialPortFlag;
|
||||||
|
bool openFileFlag;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void scanSerialPort();
|
void scanSerialPort();
|
||||||
void parityItemInit();
|
void parityItemInit();
|
||||||
|
@ -34,6 +42,7 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
void openFile();
|
void openFile();
|
||||||
void openSerialPortPushButtonClicked();
|
void openSerialPortPushButtonClicked();
|
||||||
|
void readCfgFile();
|
||||||
|
void writeCfgFile();
|
||||||
};
|
};
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>841</width>
|
<width>834</width>
|
||||||
<height>665</height>
|
<height>666</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -171,7 +171,14 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QComboBox" name="SerialPort"/>
|
<widget class="QComboBox" name="SerialPort">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>117</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
|
@ -461,7 +468,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>841</width>
|
<width>834</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|
Loading…
Reference in New Issue