//msgmaincontrol.h
#ifndef MSGMAINCONTROL_H
#define MSGMAINCONTROL_H
#include <QQuickView>
#include <QObject>
#include <QVector>
#include <QTimer>
struct msgInfo{
QString msgName;
QString api;
QStringList defaultparm;
};
struct msg_type_info{
QString typeName;
QList<msgInfo> msg;
};
class MsgMainControl : public QObject
{
Q_OBJECT
public:
explicit MsgMainControl(QObject *parent = 0);
static MsgMainControl *getInstance();
void Initcontrol(QObject*obj);
signals:
public slots:
void openConfigfile();
void openlogFile();
void updatelistMsg(int);
void udateParms(int);
void addToselmsgList();
void delFromselmsgList(int);
void clearSelmsg();
void beginConnect();
void disConnect();
void allStop();
void beginSend();
void cycleStop();
void logClear();
void logSave();
void sendOnce();
void sendCycle(int,int);
void sendListcycle(int);
void getOpposize(int);
void updateIndexparm(int,int);
private:
void addTolog(QString);
private:
static MsgMainControl *instance;
QObject *rootView;
QList<QObject*>filedParms;
QList<QObject*>btnParm;
QObject *m_msgType;
QObject *m_listMsg;
QObject *m_connect;
QObject *m_logArea;
int msgTypeCurIndex;
QStringList msgType;
QStringList msgapiList;
QString msgApi;
QStringList msgParms;
QString logString;
int sendMode; //0-sendOnce 1-sendCycle 2-sendListcycle
int sendCount;
int sendTime;
int callCount;
QStringList selmsgList;
QVector<QStringList>seltotalParms;
int curcycleIndex;
QList<msg_type_info> msgTotallist;//message
QTimer *mytimer;
QTimer *listtimer;
};
#endif // MSGMAINCONTROL_H
//msgmaincontrol.cpp
#include "msgmaincontrol.h"
#include <QDebug>
#include <QProcess>
#include <QList>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include <QJsonValue>
#include <QFile>
#include <QDate>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QSslError>
MsgMainControl *MsgMainControl::instance=new MsgMainControl();
MsgMainControl::MsgMainControl(QObject *parent) : QObject(parent)
{
sendCount=5;
sendMode=0;
}
MsgMainControl* MsgMainControl::getInstance()
{
if(instance==NULL)
{
instance=new MsgMainControl();
}
return instance;
}
void MsgMainControl::Initcontrol(QObject *obj)
{
rootView=obj;
m_msgType=rootView->findChild<QObject*>("msgType");
QFile file("../msgconfig.json");
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"open file failed";
}
QByteArray byte_array=file.readAll();
file.close();
QJsonParseError json_error;
QJsonDocument doc = QJsonDocument::fromJson(byte_array, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
if(doc.isObject())
{
QJsonObject obj = doc.object();
if(obj.contains("msgModule"))
{
QJsonValue val=obj.take("msgModule");
if(val.isArray())
{
QJsonArray arry= val.toArray();
for(auto it=arry.begin();it!=arry.end();it++)
{
msgType<<(*it).toObject().keys();
QString msgTypeName=msgType.back();
QJsonArray msgArry=(*it).toObject().take(msgTypeName).toArray();
QList<msgInfo>msgList;
for(auto iterator=msgArry.begin();iterator!=msgArry.end();iterator++)
{
msgInfo msg;
msg.msgName=(*iterator).toObject().take("msgName").toString();
msg.api=(*iterator).toObject().take("api").toString();
QJsonArray parm=(*iterator).toObject().take("defaultparm").toArray();
for(auto itParm=parm.begin();itParm!=parm.end();itParm++)
{
msg.defaultparm<<(*itParm).toString();
}
msgList.push_back(msg);
}
msg_type_info type_info;
type_info.typeName=msgTypeName;
type_info.msg=msgList;
msgTotallist.push_back(type_info);
}
}
}
}
}
m_msgType->setProperty("model",msgType);
updatelistMsg(0);
connect(m_msgType,SIGNAL(activated(int)),this,SLOT(updatelistMsg(int)));
connect(rootView,SIGNAL(curIndexChange(int)),this,SLOT(udateParms(int)));
connect(rootView,SIGNAL(selmsgIndex()),this,SLOT(addToselmsgList()));
connect(rootView,SIGNAL(delmsgIndex(int)),this,SLOT(delFromselmsgList(int)));
connect(rootView,SIGNAL(clearSelmsg()),this,SLOT(clearSelmsg()));
connect(rootView,SIGNAL(beginConnect()),this,SLOT(beginConnect()));
connect(rootView,SIGNAL(disConnect()),this,SLOT(disConnect()));
connect(rootView,SIGNAL(allStop()),this,SLOT(allStop()));
connect(rootView,SIGNAL(beginSend()),this,SLOT(beginSend()));
connect(rootView,SIGNAL(cycleStop()),this,SLOT(cycleStop()));
connect(rootView,SIGNAL(clearLog()),this,SLOT(logClear()));
connect(rootView,SIGNAL(saveLog()),this,SLOT(logSave()));
connect(rootView,SIGNAL(sendOnce()),this,SLOT(sendOnce()));
connect(rootView,SIGNAL(sendCycle(int,int)),this,SLOT(sendCycle(int,int)));
connect(rootView,SIGNAL(sendListcycle(int)),this,SLOT(sendListcycle(int)));
connect(rootView,SIGNAL(getOpposite(int)),this,SLOT(getOpposize(int)));
connect(rootView,SIGNAL(updateIndexparm(int,int)),this,SLOT(updateIndexparm(int,int)));
mytimer=new QTimer(this);
connect(mytimer, &QTimer::timeout,[=](){
if(callCount--)
{
QString nowtime=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz ddd");
addTolog(nowtime+" "+msgApi+": "+msgParms.join(" "));
qDebug()<<"mytimer timeout";
}
else
{
mytimer->stop();
qDebug()<<"mytimer stop";
}
});
listtimer=new QTimer(this);
connect(listtimer, &QTimer::timeout,[=](){
if(callCount--)
{
QString apiName=selmsgList.at(curcycleIndex);
QStringList apiParms=seltotalParms.at(curcycleIndex);
QString nowtime=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz ddd");
addTolog(nowtime+" "+apiName+": "+apiParms.join(" "));
curcycleIndex++;
qDebug()<<"listtimer timeout";
}
else
{
callCount=selmsgList.length();
curcycleIndex=0;
qDebug()<<"listtimer stop";
}
});
}
void MsgMainControl::openConfigfile()
{
QProcess myprocess;
QString fileName="../msgconfig.json";
QFile file(fileName);
if(!file.exists())
{
qDebug()<<"the 'msconfig.json' is not exist,please first create it."<<endl;
return;
}
myprocess.startDetached("gedit",QStringList(fileName));
}
void MsgMainControl::openlogFile()
{
QProcess myprocess;
QString date = QDate::currentDate().toString(Qt::ISODate);
QString fileName=QString("../log/%1.txt").arg(date);
QFile file(fileName);
if(!file.exists())
{
qDebug()<<"the '"+fileName+"' is not exist."<<endl;
return;
}
myprocess.startDetached("gedit",QStringList(fileName));
}
void MsgMainControl::updatelistMsg(int index)
{
msgTypeCurIndex=index;
m_listMsg=rootView->findChild<QObject*>("msgList");
QStringList msgnameList;
QList<msgInfo> msg=msgTotallist.at(index).msg;
for(auto it=msg.begin();it!=msg.end();it++)
{
msgnameList<<(*it).msgName;
msgapiList<<(*it).api;
}
m_listMsg->setProperty("msgArry",msgnameList);
m_listMsg->setProperty("model",msgnameList);
udateParms(0);
}
void MsgMainControl::udateParms(int index)
{
const msgInfo *msginfo =&msgTotallist.at(msgTypeCurIndex).msg.at(index);
msgParms=msginfo->defaultparm;
msgApi=msginfo->api;
int number=9-msgParms.length();
QStringList temp=msgParms;
for(int i=0;i<number;i++)
{
temp<<" ";
}
rootView->setProperty("parmArry",temp);
}
void MsgMainControl::addToselmsgList()
{
selmsgList<<msgApi;
seltotalParms<<msgParms;
qDebug()<<"addToselmsgList is called";
}
void MsgMainControl::delFromselmsgList(int index)
{
selmsgList.removeAt(index);
seltotalParms.removeAt(index);
qDebug()<<"del"<<index;
}
void MsgMainControl::clearSelmsg()
{
selmsgList.clear();
seltotalParms.clear();
qDebug()<<"clearSelmsg is called";
}
void MsgMainControl::beginConnect()
{
qDebug()<<"now is building connect";
}
void MsgMainControl::disConnect()
{
qDebug()<<"now is release connect";
}
void MsgMainControl::allStop()
{
listtimer->stop();
mytimer->stop();
qDebug()<<"allStop is called";
}
void MsgMainControl::beginSend()
{
QString nowtime=QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz ddd");
if(sendMode==1) callCount=sendCount;
if(sendMode==2) callCount=selmsgList.length();
curcycleIndex=0;
switch (sendMode) {
case 0:
addTolog(nowtime+" "+msgApi+": "+msgParms.join(" "));
break;
case 1:
mytimer->start(sendTime);
break;
case 2:
if(callCount>0)
{
listtimer->start(sendTime);
}
else
{
qDebug()<<"please add msg to list!!!";
}
break;
default:
break;
}
qDebug()<<"beginSend is called";
}
void MsgMainControl::cycleStop()
{
mytimer->stop();
qDebug()<<"cycleStop is called";
}
void MsgMainControl::logClear()
{
logString.clear();
qDebug()<<"logClear is called";
}
void MsgMainControl::logSave()
{
QString date = QDate::currentDate().toString(Qt::ISODate);
QString fileName=QString("../log/%1.txt").arg(date);
QFile logfile(fileName);
if(!logfile.open(QIODevice::Append))
{
qDebug()<<"save log to file is failed";
}
logfile.write(logString.toUtf8());
logfile.close();
qDebug()<<"save log to file is success";
}
void MsgMainControl::sendOnce()
{
sendCount=1;
sendMode=0;
qDebug()<<"sendOnce is called:"<<sendCount;
}
void MsgMainControl::sendCycle(int count,int time)
{
sendCount=count;
sendTime=time;
sendMode=1;
qDebug()<<"sendCycle is called:"<<sendCount<<" "<<sendTime;
}
void MsgMainControl::sendListcycle(int time)
{
sendMode=2;
sendTime=time;
qDebug()<<"sendListcycle is called:"<<sendMode;
}
void MsgMainControl::getOpposize(int index)
{
qDebug()<<"getOpposize is called:"<<index;
if(index>=msgParms.length() && index<9 ||index>=msgParms.length()+9)
{
qDebug()<<"have't this parm,please again checked.";
return;
}
if(index<9)
{
QString str=msgParms[index];
msgParms[index]=QString("%1").arg(str.toInt()-1);
}
else
{
int inx=index-9;
QString str=msgParms[inx];
msgParms[inx]=QString("%1").arg(str.toInt()+1);
}
int number=9-msgParms.length();
QStringList temp=msgParms;
for(int i=0;i<number;i++)
{
temp<<" ";
}
rootView->setProperty("parmArry",temp);
}
void MsgMainControl::updateIndexparm(int index, int val)
{
qDebug()<<"updateIndexparm is called:"<<index<<":"<<val;
if(index>=msgParms.length() && val>0)
{
msgParms.push_back(QString("%1").arg(val));
}
else if(val>0)
{
msgParms[index]=QString("%1").arg(val);
}
else
{
msgParms.removeAt(index);
}
}
void MsgMainControl::addTolog(QString str)
{
logString+=(str+"\n");
m_logArea=rootView->findChild<QObject*>("dislogArea");
m_logArea->setProperty("text",logString);
qDebug()<<"addTolog is called";
}
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "msgmaincontrol.h"
#include <QDebug>
#include <QProcess>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject*root= engine.rootObjects().at(0);
QObject::connect(root, SIGNAL(configSignal()),MsgMainControl::getInstance(),SLOT(openConfigfile()));
QObject::connect(root, SIGNAL(openlogFile()),MsgMainControl::getInstance(),SLOT(openlogFile()));
QObject *obj=root->findChild<QObject*>("msgMain");
MsgMainControl::getInstance()->Initcontrol(obj);
return app.exec();
}
msgmain.qml
import QtQuick 2.0
import QtQuick.Controls.Styles 1.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.1
Rectangle {
id:root
// color: "while"
anchors.fill: parent
//--------------------------------------------
property variant parmArry:["","","","","","","","",""]
property variant selMsg:[]
signal curIndexChange(int index)
signal selmsgIndex()
signal delmsgIndex(int index)
signal clearSelmsg();
signal beginConnect()
signal disConnect()
signal allStop()
signal beginSend()
signal cycleStop()
signal clearLog()
signal saveLog()
signal sendOnce()
signal sendCycle(int count,int time)
signal sendListcycle(int time);
signal getOpposite(int index)
signal updateIndexparm(int index,int val)
//--------------------------------------------
Rectangle{
id:rect1
width: parent.width-20*2
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
height: 50
//color: "gray"
border.width: 1
border.color: "#bdcbc0"
//visible: false
Text{
x:10
y:12
text: "自定义:"
}
Row{
x:70
spacing: 25
Repeater{
model: 12
Button{
y:10
width: 50
height: 30
Text{
anchors.centerIn: parent
text:index
}
// onClicked: dosomthing(index)
}
}
}
}
//--------------------------------------------
Column{
x:20
spacing: 5
anchors.top: rect1.bottom
anchors.topMargin: 10
width: 170
height: 480
Text{
text: "消息类型:"
}
ComboBox{
id:msgType
objectName:"msgType"
height: 25
width: 137
}
Text{
text: "消息列表:"
}
Rectangle{
height: 400
width: 137
border.color: "#bdcbc0"
border.width: 1
ListView{
id:msgList
property variant msgArry:[]
objectName: "msgList"
anchors.fill: parent
clip:true
focus: true
delegate:wordscomponent
highlight:highcomponent
highlightFollowsCurrentItem :true
onCurrentIndexChanged: {
curIndexChange(currentIndex)
}
}
Component{
id:wordscomponent
Rectangle{
id:delegateitem
width:msgList.width-1
height: 25
opacity: 0.6
color:"gray"
border.color: "gray"
Text{
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
font.pixelSize: 15
text:modelData
}
MouseArea {
id:item
anchors.fill: parent
acceptedButtons: Qt.LeftButton|Qt.RightButton
onPressed: {
msgList.currentIndex=index
msgList.focus=true
if(mouse.button===Qt.RightButton)
{
console.log("Qt.RightButton")
}
}
onDoubleClicked:{
console.log("onDoubleClicked")
}
}
}
}
Component{
id:highcomponent
Rectangle{
id:clicked
width:msgList.width-1
height: 25
opacity: 0.9
color:"gray"
border.color: "black"
}
}
}
}
//--------------------------------------------
Text {
id: name
x:204
y:70
color: "red"
text: qsTr("提示:若页面无数据请检查配置文件是否正常,然后\n点击后面的按钮进行连接!!!")
}
Button{
id:connect
x:563
y:70
width: 60
height: 50
property bool flag: false
Text{
anchors.centerIn: parent
text:!connect.flag?"连接":"断开"
}
onClicked:{
flag=!flag
if(flag)
{
//connect
beginConnect()
console.log("beginConnect")
}
else
{
//disconnect
disConnect()
console.log("disConnect")
}
}
}
Text {
x:190
y:128
text: qsTr("参数:")
}
//-------------------------------------------
Column{
id:param
x:174
y:164
width: 180
height: 400
spacing: 20
Repeater{
model: 9
Row{
spacing: 8
Text {
y:3
text: index
}
Rectangle{
width: 76
height: 25
border.width: 1
border.color: "#bdcbc0"
TextInput{
width: 72
height: 25
selectByMouse :true
anchors.centerIn: parent
verticalAlignment: TextInput.AlignVCenter
color:"red"
clip: true
text: root.parmArry[index]
onAccepted: {
updateIndexparm(index,text)
}
}
}
Button{
width: 25
height: 25
text:"-"
onClicked: {
getOpposite(index)
}
}
Button{
width: 25
height: 25
text:"+"
onClicked: {
getOpposite(index+9)
}
}
}
}
}
//-------------------------------------------
Rectangle{
id:group
y:130
anchors.left: param.right
width: 270
height: 127
border.color: "#bdcbc0"
Text {
x:10
y:5
text: qsTr("发送模式:")
font.pixelSize: 18
font.family: "Times"
}
Column{
id:col1
x:10
y:30
width:106
height: 95
spacing: 5
ExclusiveGroup{id:sendmodel}
RadioButton{
id:sendone
text: "单次发送"
exclusiveGroup: sendmodel
checked: true
onClicked:{
sendOnce();
countVal.enabled=false
timeVal.enabled=false
}
}
RadioButton{
id:sendcycle
text: "循环发送"
exclusiveGroup: sendmodel
onClicked:{
sendCycle(countVal.text,timeVal.text);
countVal.enabled=true
timeVal.enabled=true
}
}
RadioButton{
id:sendlistcycle
text: "队列循环"
exclusiveGroup: sendmodel
onClicked:
{
sendListcycle(timeVal.text);
countVal.enabled=false
timeVal.enabled=true
}
}
}
Rectangle{
anchors.left: col1.right
anchors.leftMargin: -10
y:12
width: 150
height: 103
border.width: 1
border.color: "#bdcbc0"
Text {
x:10
text: qsTr("发送次数:")
}
TextField {
id:countVal
x:10
y:22
width: 70
text: "1"
onAccepted:{
sendCycle(countVal.text,timeVal.text)
}
enabled: false
}
Text {
x:90+10
y:22
text: qsTr("次")
}
Text {
x:10
y:45
text: qsTr("间隔时间:")
}
TextField {
id:timeVal
x:10
y:68
width: 70
text: "1000"
onAccepted:{
if(sendcycle.checked)
{
sendCycle(countVal.text,timeVal.text)
}
else if(sendlistcycle.checked)
{
sendListcycle(timeVal.text)
}
}
enabled: false
}
Text {
x:90
y:68
text: qsTr("毫秒/次")
}
}
}
//-------------------------------------------
Text {
x:group.x
y:group.y+group.height+20
text: qsTr("发送队列:")
}
Column{
id:select
x:group.x
y:310
function dosomething(index)
{
switch(index)
{
case 0:
var msg=msgList.msgArry[msgList.currentIndex];
selMsg.push(msg);
mymodel.insert(selMsg.length-1,{"cursel":msg});
selmsgIndex();
break;
case 1:
if(selMsg.length<1) return;
mymodel.remove(sendList.currentIndex,1);
selMsg.splice(sendList.currentIndex,1);
delmsgIndex(sendList.currentIndex);
break;
case 2:
mymodel.clear();
selMsg=[];
clearSelmsg();
break;
case 3:
default:
break;
}
}
property variant arry:[">>","<<","清空","绑定"]
spacing: 10
Repeater{
model: 4
Button{
width: 50
height: 35
Text{
anchors.centerIn: parent
text:select.arry[index]
}
onClicked: select.dosomething(index)
}
}
}
Rectangle{
x:select.x+select.width+30
y:select.y-30
height: 210
width: 190
border.color: "#bdcbc0"
border.width: 1
ListView{
id:sendList
anchors.fill: parent
clip:true
model: mymodel
focus: true
delegate:del
highlight:hig
highlightFollowsCurrentItem :true
}
ListModel{
id:mymodel
}
Component{
id:del
Rectangle{
id:delegateitem
width:sendList.width-1
height: 25
opacity: 0.6
color:"gray"
border.color: "gray"
Text{
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
font.pixelSize: 15
text:cursel
}
MouseArea {
anchors.fill: parent
onPressed: {
sendList.currentIndex=index
sendList.focus=true
}
}
}
}
Component{
id:hig
Rectangle{
width:sendList.width-1
height: 25
opacity: 0.9
color:"gray"
border.color: "black"
}
}
}
//-------------------------------------------
Row{
spacing: 16
id:control
x:group.x
y:510
property variant arry:["全部停止","开始发送","循环停止"]
function delButton(index)
{
switch(index)
{
case 0:
allStop();
break;
case 1:
beginSend();
break;
case 2:
cycleStop();
break;
default:
break;
}
}
Repeater{
model: 3
Button{
width: 80
height: 38
Text{
anchors.centerIn: parent
text:control.arry[index]
}
onClicked:control.delButton(index)
}
}
}
//-------------------------------------------
Item{
id:logArea
x:600
y:80
Text {
id:txtlog
x:50 //650
y:10 //100
text: qsTr("操作日志:")
}
Button{
x:255 //855
y:5 //95
width: 54
height: 25
Text{
anchors.centerIn: parent
text:"清空"
}
onClicked: {
dislogArea.text="";
clearLog();
}
}
Button{
x:325 //925
y:5 //95
width: 54
height: 25
Text{
anchors.centerIn: parent
text:"保存"
}
onClicked: {
console.log("save log to file");
saveLog();
}
}
Rectangle{
x:txtlog.x
y:txtlog.y+30
height: 430
width: 330
border.color:"#bdcbc0"
border.width: 1
TextArea {
id:dislogArea
objectName: "dislogArea"
anchors.centerIn: parent
width: 324
height: 424
wrapMode: TextEdit.Wrap
// enabled: false
}
}
}
//-------------------------------------------
Rectangle{
id:bottomArea
x:20
y:root.height-100
width: 960
height: 80
border.width: 1
border.color: "#bdcbc0"
property variant list:["水温","油温","转速","车速"]
function selmometer(index)
{
switch(index)
{
case 0:
slider.maximumValue=125;
slider.minimumValue=50;
slider.value=87.5;
break;
case 1:
slider.maximumValue=56;
slider.minimumValue=0;
slider.value=28;
break;
case 2:
slider.maximumValue=8000;
slider.minimumValue=0;
slider.value=4000;
break;
case 3:
slider.maximumValue=240;
slider.minimumValue=0;
slider.value=120;
break;
default:
break;
}
}
Rectangle{
id:curModel
x:20
y:15
height: 52
width: 300
border.color: "#bdcbc0"
border.width: 1
Row{
anchors.verticalCenter: parent.verticalCenter
x:20
spacing: 10
ExclusiveGroup { id: exclusive }
Repeater{
model: 4
RadioButton{
anchors.verticalCenter: parent.verticalCenter
text:bottomArea.list[index]
exclusiveGroup: exclusive
onClicked: {
bottomArea.selmometer(index);
}
}
}
}
}
Row{
x:slider.x+5
y:curModel.y-18
spacing: 420
Text {
text: qsTr("-")
font.pixelSize: 40
}
Text {
y:5
text: qsTr("+")
font.pixelSize: 30
}
}
Slider{
id:slider
x:curModel.x+curModel.width+20
y:curModel.y
width: 455
height: 50
stepSize: 1
onValueChanged: {
curVal.placeholderText =value
}
}
Row{
x:slider.x
y:curModel.y+35
spacing: 395
Text {
text: qsTr("最小")
}
Text {
text: qsTr("最大")
}
}
Text{
id:curslederVal
anchors.left: slider.right
anchors.leftMargin: 15
anchors.verticalCenter: parent.verticalCenter
text: "当前值:"
}
TextField{
anchors.right: parent.right
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
id:curVal
width: 70
height: 30
enabled: false
}
}
}
//main.qml
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
ApplicationWindow {
id:root
visible: true
maximumHeight: 700
maximumWidth: 1000
minimumHeight: 700
minimumWidth:1000
x:Screen.desktopAvailableWidth/5
y:Screen.desktopAvailableHeight/5
title: qsTr("消息模拟器")
// QML 信号
signal configSignal()
signal openlogFile()
menuBar:MenuBar {
Menu {
id:menu
objectName: "menu"
title: "文件"
MenuItem {
text: "项目配置"
onTriggered:{
configSignal();
}
}
MenuItem {
text: "打开日志"
onTriggered:{
openlogFile();
}
}
}
}
MsgMain{
id:msgMain
objectName: "msgMain"
anchors.fill: parent
}
}