Commit b05ea08b by NitefullWind

1. 实现配置功能。可选配置文件路径。

parent 966690c1
......@@ -11,32 +11,35 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
SOURCES += \
main.cpp \
mainwindow.cpp \
setting.cpp \
selectedwidget.cpp \
productwidget.cpp \
paywidget.cpp \
inputamountdialog.cpp \
session.cpp \
highlighter.cpp \
reqdatabtn.cpp
$$PWD\main.cpp \
$$PWD\mainwindow.cpp \
$$PWD\setting.cpp \
$$PWD\selectedwidget.cpp \
$$PWD\productwidget.cpp \
$$PWD\paywidget.cpp \
$$PWD\inputamountdialog.cpp \
$$PWD\session.cpp \
$$PWD\highlighter.cpp \
$$PWD\reqdatabtn.cpp \
$$PWD\settingdialog.cpp
HEADERS += \
mainwindow.h \
setting.h \
selectedwidget.h \
productwidget.h \
paywidget.h \
session.h \
inputamountdialog.h \
highlighter.h \
reqdatabtn.h
$$PWD\mainwindow.h \
$$PWD\setting.h \
$$PWD\selectedwidget.h \
$$PWD\productwidget.h \
$$PWD\paywidget.h \
$$PWD\session.h \
$$PWD\inputamountdialog.h \
$$PWD\highlighter.h \
$$PWD\reqdatabtn.h \
$$PWD\settingdialog.h
FORMS += \
mainwindow.ui \
productwidget.ui \
paywidget.ui \
inputamountdialog.ui \
reqdatabtn.ui \
selectedwidget.ui
$$PWD\mainwindow.ui \
$$PWD\productwidget.ui \
$$PWD\paywidget.ui \
$$PWD\inputamountdialog.ui \
$$PWD\reqdatabtn.ui \
$$PWD\selectedwidget.ui \
$$PWD\settingdialog.ui
No preview for this file type
......@@ -4,6 +4,12 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qApp->setOrganizationName("Freemud");
qApp->setOrganizationDomain("freemud.cn");
qApp->setApplicationName("FMTestPOS");
qApp->setApplicationDisplayName("非码测试POS");
MainWindow w;
w.show();
......
......@@ -6,6 +6,7 @@
#include "inputamountdialog.h"
#include "highlighter.h"
#include "reqdatabtn.h"
#include "settingdialog.h"
#include <QPushButton>
#include <QDialog>
#include <QTextEdit>
......@@ -25,14 +26,11 @@ MainWindow::MainWindow(QWidget *parent) :
needPayAmount(0)
{
ui->setupUi(this);
InitProductList();
InitPayList();
InitReqPosBtns();
InitReqDataBtns();
highlighter = new Highlighter(ui->console->document());
connect(Setting::Instance(), &Setting::newLog, this, &MainWindow::onNewLog);
resetTransId();
Setting::getSession()->addData("business_date", QDate::currentDate().toString("yyyyMMdd"));
connect(ui->menuBar, &QMenuBar::triggered, this, &MainWindow::onMenuTriggered);
onInitWnd();
}
MainWindow::~MainWindow()
......@@ -42,6 +40,12 @@ MainWindow::~MainWindow()
void MainWindow::InitProductList()
{
foreach (ProductWidget *w, productWidgeVector) {
ui->productLayout->removeWidget(w);
}
qDeleteAll(productWidgeVector);
productWidgeVector.clear();
QList<Setting::Product> productList = Setting::Instance()->getProductList();
foreach(Setting::Product product, productList) {
ProductWidget *pro_widget = new ProductWidget(product, this);
......@@ -86,10 +90,17 @@ void MainWindow::onProductSelectedChanged()
void MainWindow::InitPayList()
{
foreach (PayWidget *w, payWidgetVector) {
ui->payListLayout->removeWidget(w);
}
qDeleteAll(payWidgetVector);
payWidgetVector.clear();
QList<Setting::PayWay> payList = Setting::Instance()->getPayList();
foreach (Setting::PayWay payWay, payList) {
PayWidget *payWidget = new PayWidget(payWay, this);
ui->payListLayout->addWidget(payWidget);
payWidgetVector.append(payWidget);
connect(payWidget, &PayWidget::selected, this, &MainWindow::onPaySelected);
connect(payWidget, &PayWidget::disSelected, this, &MainWindow::onPayDisSelected);
......@@ -110,7 +121,7 @@ void MainWindow::onPaySelected()
QJsonObject rspObj;
doRequest(payWdiget->getPayWay().req_pay, rspObj);
if(rspObj["statusCode"].toInt() != 100) {
if(rspObj["statusCode"].toInt() != 100 && rspObj["status_code"].toInt() != 100) {
consoleShow(QString::fromLocal8Bit("支付失败"), FMLog::Error);
} else {
Setting::Instance()->getSession()->addData("fm_id", rspObj["fm_id"].toString());
......@@ -125,7 +136,7 @@ void MainWindow::onPaySelected()
if(payAmount > 0 && payAmount<=needPayAmount) {
paidAmount += payAmount;
needPayAmount = orderAmount - paidAmount;
payWidgetMap[payWdiget] += payAmount;
usedPayWidgetMap[payWdiget] += payAmount;
}
showAmountInfo();
}
......@@ -134,8 +145,8 @@ void MainWindow::onPayDisSelected()
{
PayWidget *payWdiget = qobject_cast<PayWidget*>(sender());
int refundAmonut = 0;
if(payWidgetMap.contains(payWdiget)) {
refundAmonut = payWidgetMap[payWdiget];
if(usedPayWidgetMap.contains(payWdiget)) {
refundAmonut = usedPayWidgetMap[payWdiget];
}
int payAmount = showPayDialog(refundAmonut, false);
......@@ -143,7 +154,7 @@ void MainWindow::onPayDisSelected()
Setting::Instance()->getSession()->addData("refund_amount", payAmount);
QJsonObject rspObj;
doRequest(payWdiget->getPayWay().req_refund, rspObj);
if(rspObj["statusCode"].toInt() != 100) {
if(rspObj["statusCode"].toInt() != 100 && rspObj["status_code"].toInt() != 100) {
payAmount = 0;
consoleShow(QString::fromLocal8Bit("退款失败"), FMLog::Error);
}
......@@ -152,7 +163,7 @@ void MainWindow::onPayDisSelected()
if(payAmount > 0 && payAmount<=refundAmonut) {
paidAmount -= payAmount;
needPayAmount = orderAmount - paidAmount;
payWidgetMap[payWdiget] -= payAmount;
usedPayWidgetMap[payWdiget] -= payAmount;
}
showAmountInfo();
}
......@@ -161,7 +172,7 @@ void MainWindow::showAmountInfo()
{
ui->orderAmountLab->setText(QString::number(orderAmount/100.0, 'f', 2));
ui->needAmountLab->setText(QString::number(needPayAmount/100.0, 'f', 2));
for(QMap<PayWidget*, int>::const_iterator it=payWidgetMap.begin(); it!=payWidgetMap.end(); it++) {
for(QMap<PayWidget*, int>::const_iterator it=usedPayWidgetMap.begin(); it!=usedPayWidgetMap.end(); it++) {
PayWidget* pw = it.key();
pw->setPayAmount(it.value());
}
......@@ -170,14 +181,14 @@ void MainWindow::showAmountInfo()
Setting::Instance()->getSession()->addData("paid_amount", paidAmount);
QJsonArray payList;
foreach (PayWidget *payWidget, payWidgetMap.keys()) {
if(payWidgetMap[payWidget] <= 0) {
foreach (PayWidget *payWidget, usedPayWidgetMap.keys()) {
if(usedPayWidgetMap[payWidget] <= 0) {
continue;
}
QJsonObject payObj;
payObj["pay_id"] = payWidget->getPayWay().pay_id;
payObj["pay_str"] = payWidget->getPayWay().pay_name;
payObj["pay_amount"] = payWidgetMap[payWidget];
payObj["pay_amount"] = usedPayWidgetMap[payWidget];
payObj["pay_transId"] = payWidget->getPayWay().pay_transId;
payList.append(payObj);
}
......@@ -261,11 +272,11 @@ void MainWindow::on_btn_reset_clicked()
foreach (ProductWidget *proWidget, productWidgeVector) {
proWidget->setSelectedCount(0);
}
for(QMap<PayWidget*, int>::const_iterator it=payWidgetMap.begin(); it!=payWidgetMap.end(); it++) {
for(QMap<PayWidget*, int>::const_iterator it=usedPayWidgetMap.begin(); it!=usedPayWidgetMap.end(); it++) {
PayWidget* pw = it.key();
pw->setPayAmount(0);
}
payWidgetMap.clear();
usedPayWidgetMap.clear();
ui->lineEdit_undisAmount->setText("0");
} else if(ui->tab_raw) {
ui->textEdit_raw->clear();
......@@ -360,6 +371,27 @@ void MainWindow::on_btn_save_req_clicked()
}
}
void MainWindow::onMenuTriggered(QAction *action)
{
if(action->objectName() == "action_setting") {
SettingDialog settingDialog;
int ret = settingDialog.exec();
if(ret) {
onInitWnd();
}
}
}
void MainWindow::onInitWnd()
{
InitProductList();
InitPayList();
InitReqPosBtns();
InitReqDataBtns();
resetTransId();
Setting::getSession()->addData("business_date", QDate::currentDate().toString("yyyyMMdd"));
}
void MainWindow::InitReqDataBtns()
{
int btnsCount = ui->reqData_btns_widget->count();
......
......@@ -58,12 +58,17 @@ private slots:
void on_btn_save_req_clicked();
void onMenuTriggered(QAction*action);
void onInitWnd();
private:
Ui::MainWindow *ui;
Highlighter *highlighter;
QVector<ProductWidget*> productWidgeVector;
QMap<PayWidget*, int> payWidgetMap;
QVector<PayWidget*> payWidgetVector;
QMap<PayWidget*, int> usedPayWidgetMap;
int orderAmount, paidAmount, needPayAmount;
......
......@@ -301,6 +301,13 @@
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>选项</string>
</property>
<addaction name="action_setting"/>
</widget>
<addaction name="menu"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
......@@ -311,6 +318,11 @@
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="action_setting">
<property name="text">
<string>设置</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
......
......@@ -10,8 +10,12 @@
#include <QDate>
#include <QTcpSocket>
#include <QDir>
#include <QSettings>
#include <QApplication>
#include <QDebug>
QString Setting::_settingFilesPath = "";
Setting *Setting::Instance()
{
static Setting setting;
......@@ -27,7 +31,14 @@ Setting::Setting(QObject *parent)
void Setting::readSetting()
{
QFile settingFile(QString("%1/settings.json").arg(CONFIGPATH));
QSettings settings;
QStringList filePaths = settings.value("FilePaths", QStringList("")).toStringList();
if(filePaths.isEmpty()) {
_settingFilesPath = qApp->applicationDirPath();
} else {
_settingFilesPath = filePaths.last();
}
QFile settingFile(QString("%1/settings.json").arg(_settingFilesPath));
if(!settingFile.open(QIODevice::ReadOnly)) {
qDebug() << "Read setting file failed." << settingFile.errorString();
return;
......@@ -47,6 +58,12 @@ QJsonObject *Setting::getSettingJsonObj()
return &Instance()->settingObj;
}
int Setting::getLogLevel()
{
static int level = Instance()->settingObj["Log"].toObject().value("Level").toInt(0);
return level;
}
Session *Setting::getSession()
{
return Instance()->_session;
......@@ -97,7 +114,8 @@ void Setting::setErrorString(const QString &error)
QJsonObject Setting::getPosReqJsonObj(const QString &apiName)
{
QFile apiFile(QString("postest/%1.json").arg(apiName));
qDebug() << _settingFilesPath;
QFile apiFile(QString("%1/%2.json").arg(_settingFilesPath).arg(apiName));
if(!apiFile.open(QIODevice::ReadOnly)) {
Instance()->setErrorString(QString("Open file: %1.json failed. %2").arg(apiName).arg(apiFile.errorString()));
return QJsonObject();
......@@ -172,6 +190,7 @@ QString Setting::CreateReqString(const QString &originString)
}
default:
Log(FMLog(QString("Key: %1 Invalid qvariant type.").arg(apiKeyStr), FMLog::Warning));
keyValue = "\"\"";
break;
}
}
......@@ -244,7 +263,7 @@ bool Setting::doRequest(const QByteArray &reqData, QByteArray &rspData)
int sendDataLen = reqData.length();
// 如果需要,加上消息头
if(Instance()->settingObj["NeedSocketHeader"].toBool() || true) {
if(Instance()->settingObj["NeedSocketHeader"].toBool()) {
char *sendDataWithHeader = new char[sendDataLen + sizeof(FMSOCKHEADER)];
FMSOCKHEADER header = { 0, 0, 0 };
header.flag = 0x4d46;
......@@ -278,14 +297,14 @@ bool Setting::doRequest(const QByteArray &reqData, QByteArray &rspData)
bool Setting::doRequest(const QJsonObject &reqObj, QJsonObject &rspObj)
{
QByteArray reqData = Setting::getJsonValueString(reqObj).toUtf8();
QByteArray reqData = Setting::getJsonValueString(reqObj).toLocal8Bit();
QByteArray recvData;
doRequest(reqData, recvData);
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(QString::fromLocal8Bit(recvData).toUtf8(), &parseError);
QJsonDocument doc = QJsonDocument::fromJson(recvData, &parseError);
if(parseError.error != QJsonParseError::NoError) {
Log(FMLog(QString("Parse json error: %1. \n Error Json: ").arg(parseError.errorString()).arg(recvData.data()), FMLog::Error));
return false;
......@@ -296,7 +315,7 @@ bool Setting::doRequest(const QJsonObject &reqObj, QJsonObject &rspObj)
QStringList Setting::getReqDataBtnsNames(const QString &tag)
{
QDir configDir(CONFIGPATH);
QDir configDir(_settingFilesPath);
QStringList nameFilters;
nameFilters << QString("%1_*.json").arg(tag);
QStringList fileNames = configDir.entryList(nameFilters);
......@@ -311,7 +330,7 @@ QStringList Setting::getReqDataBtnsNames(const QString &tag)
QString Setting::getReqData(const QString &reqName, const QString &tag)
{
QString fileName = QString("%1/%2_%3.json").arg(CONFIGPATH).arg(tag).arg(reqName);
QString fileName = QString("%1/%2_%3.json").arg(_settingFilesPath).arg(tag).arg(reqName);
QFile file(fileName);
if(!file.open(QFile::ReadOnly)) {
Instance()->setErrorString(QString("Open %1 filed. %2").arg(fileName).arg(file.errorString()));
......@@ -325,7 +344,7 @@ QString Setting::getReqData(const QString &reqName, const QString &tag)
bool Setting::setReqData(const QString &reqName, const QString &reqData, const QString &tag)
{
QString fileName = QString("%1/%2_%3.json").arg(CONFIGPATH).arg(tag).arg(reqName);
QString fileName = QString("%1/%2_%3.json").arg(_settingFilesPath).arg(tag).arg(reqName);
QFile file(fileName);
if(!file.open(QFile::WriteOnly)) {
Instance()->setErrorString(QString("Open %1 filed. %2").arg(fileName).arg(file.errorString()));
......@@ -341,7 +360,7 @@ bool Setting::setReqData(const QString &reqName, const QString &reqData, const Q
bool Setting::removeReqData(const QString &reqName, const QString &tag)
{
QString fileName = QString("%1/%2_%3.json").arg(CONFIGPATH).arg(tag).arg(reqName);
QString fileName = QString("%1/%2_%3.json").arg(_settingFilesPath).arg(tag).arg(reqName);
QFile file(fileName);
if(file.remove()) {
return true;
......@@ -357,5 +376,26 @@ void Setting::Log(FMLog log)
void Setting::_Log(FMLog log)
{
if((int)(log.type) <= Setting::getLogLevel()) {
emit newLog(log);
}
}
QString Setting::getSettingFilesPath()
{
return _settingFilesPath;
}
void Setting::setSettingFilesPath(const QString &settingFilesPath)
{
QSettings settings;
QStringList filePaths = settings.value("FilePaths", QStringList()).toStringList();
if(filePaths.contains(settingFilesPath)) {
filePaths.move(filePaths.indexOf(settingFilesPath), filePaths.length()-1);
} else {
filePaths.append(settingFilesPath);
}
settings.setValue("FilePaths", filePaths);
qDebug() << filePaths;
_settingFilesPath = settingFilesPath;
}
......@@ -5,7 +5,6 @@
#include <QJsonObject>
#include "session.h"
#define CONFIGPATH "postest"
#define TagReqData "ReqData"
#define TagReqPos "ReqPOS"
......@@ -13,10 +12,11 @@ class FMLog
{
public:
enum FMLogType {
Info,
Debug,
Off,
Error,
Warning,
Error
Debug,
Info
};
explicit FMLog(const QString &msg, FMLogType type = Info):
......@@ -58,6 +58,8 @@ public:
static void readSetting();
static QJsonObject *getSettingJsonObj();
static int getLogLevel();
static Session *getSession();
static QList<Product> getProductList();
......@@ -86,6 +88,10 @@ public:
static bool doRequest(const QJsonObject &reqObj, QJsonObject &rspObj);
static void Log(FMLog log);
static QString getSettingFilesPath();
static void setSettingFilesPath(const QString &settingFilesPath);
signals:
void hasError();
void newLog(FMLog log);
......@@ -106,6 +112,8 @@ private:
void _Log(FMLog log);
Session *_session;
static QString _settingFilesPath;
};
#endif // SETTING_H
#include "settingdialog.h"
#include "ui_settingdialog.h"
#include "setting.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QDebug>
SettingDialog::SettingDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SettingDialog)
{
ui->setupUi(this);
initSettingWnd();
}
SettingDialog::~SettingDialog()
{
delete ui;
}
void SettingDialog::initSettingWnd()
{
QSettings setting;
QStringList filePaths = setting.value("FilePaths", QStringList()).toStringList();
for(int i=filePaths.length()-1; i>=0; i--) {
ui->comboBox_settingDir->addItem(filePaths[i]);
}
}
void SettingDialog::on_btn_settingOpenDir_clicked()
{
QString settingPath = QFileDialog::getExistingDirectory(this, QString::fromLocal8Bit("打开配置文件夹"), ui->comboBox_settingDir->currentText());
ui->comboBox_settingDir->setCurrentText(settingPath);
on_btn_settingLoad_clicked();
}
void SettingDialog::on_btn_settingLoad_clicked()
{
}
void SettingDialog::on_btn_save_clicked()
{
if(onSaveConfig()) {
this->accept();
}
}
void SettingDialog::on_btn_apply_clicked()
{
onSaveConfig();
}
void SettingDialog::on_btn_quit_clicked()
{
this->reject();
}
bool SettingDialog::onSaveConfig()
{
QDir setDir(ui->comboBox_settingDir->currentText());
if(setDir.exists()) {
Setting::setSettingFilesPath(setDir.absolutePath());
Setting::readSetting();
} else {
QMessageBox::critical(this, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件路径不存在"));
return false;
}
return true;
}
void SettingDialog::on_btn_delCurrentDir_clicked()
{
QString currenText = ui->comboBox_settingDir->currentText();
QSettings setting;
QStringList filePaths = setting.value("FilePaths").toStringList();
if(filePaths.removeOne(currenText)) {
ui->comboBox_settingDir->removeItem(ui->comboBox_settingDir->currentIndex());
setting.setValue("FilePaths", filePaths);
}
}
#ifndef SETTINGDIALOG_H
#define SETTINGDIALOG_H
#include <QDialog>
namespace Ui {
class SettingDialog;
}
class SettingDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingDialog(QWidget *parent = 0);
~SettingDialog();
void initSettingWnd();
private slots:
void on_btn_settingOpenDir_clicked();
void on_btn_settingLoad_clicked();
void on_btn_save_clicked();
void on_btn_apply_clicked();
void on_btn_quit_clicked();
bool onSaveConfig();
void on_btn_delCurrentDir_clicked();
private:
Ui::SettingDialog *ui;
};
#endif // SETTINGDIALOG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingDialog</class>
<widget class="QDialog" name="SettingDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>772</width>
<height>576</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_settingDir">
<property name="text">
<string>配置文件路径:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_settingDir">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_settingOpenDir">
<property name="toolTip">
<string>打开本地配置文件夹</string>
</property>
<property name="whatsThis">
<string>打开本地配置文件夹</string>
</property>
<property name="text">
<string>打开</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_settingLoad">
<property name="text">
<string>加载</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_delCurrentDir">
<property name="text">
<string>删除此记录</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_base">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>752</width>
<height>390</height>
</rect>
</property>
<attribute name="label">
<string>基础信息</string>
</attribute>
</widget>
<widget class="QWidget" name="page_log">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>752</width>
<height>390</height>
</rect>
</property>
<attribute name="label">
<string>日志</string>
</attribute>
</widget>
<widget class="QWidget" name="page_payList">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>752</width>
<height>390</height>
</rect>
</property>
<attribute name="label">
<string>支付方式</string>
</attribute>
</widget>
<widget class="QWidget" name="page_products">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>752</width>
<height>390</height>
</rect>
</property>
<attribute name="label">
<string>商品信息</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_save">
<property name="toolTip">
<string>保存并退出</string>
</property>
<property name="whatsThis">
<string>保存并退出</string>
</property>
<property name="text">
<string>保存</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_quit">
<property name="toolTip">
<string>直接退出不保存</string>
</property>
<property name="whatsThis">
<string>直接退出不保存</string>
</property>
<property name="text">
<string>退出</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_apply">
<property name="toolTip">
<string>保存配置信息</string>
</property>
<property name="whatsThis">
<string>保存配置信息</string>
</property>
<property name="text">
<string>应用</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment