From bedfe3c2c7f77a362dad2d7b9f579688ef18c5be Mon Sep 17 00:00:00 2001 From: Gangphon Date: Mon, 23 Oct 2023 11:44:22 +0800 Subject: [PATCH] ledok --- LedOK/LedOK Express.pro | 5 - LedOK/device/upgradeapkdialog.cpp | 730 +++++++------- LedOK/device/upgradeapkdialog.h | 33 +- LedOK/deviceitem.cpp | 197 +--- LedOK/deviceitem.h | 40 +- LedOK/devicepanel.cpp | 293 ++++-- LedOK/devicepanel.h | 16 +- LedOK/globaldefine.h | 2 +- LedOK/gutil/cpp.h | 2 +- LedOK/gutil/qgui.cpp | 47 +- LedOK/gutil/qgui.h | 4 +- LedOK/gutil/qjson.cpp | 99 +- LedOK/gutil/qjson.h | 38 +- LedOK/gutil/qnetwork.cpp | 16 + LedOK/gutil/qnetwork.h | 70 +- LedOK/gutil/qwaitingdlg.h | 8 - LedOK/main.cpp | 10 +- LedOK/mainwindow.cpp | 24 +- LedOK/program/progeditorwin.cpp | 116 ++- LedOK/program/progeditorwin.h | 2 + LedOK/program/sendprogramdialog.cpp | 5 +- LedOK/program/sendprogthread.cpp | 22 +- LedOK/tools.h | 1 - LedOK/ts/app_en.ts | 1404 ++++++++++++++------------- LedOK/ts/app_ja.ts | 1374 +++++++++++++------------- LedOK/ts/app_pt.ts | 1372 +++++++++++++------------- LedOK/ts/app_zh_CN.ts | 1368 +++++++++++++------------- LedOK/ts/app_zh_TW.ts | 1372 +++++++++++++------------- 28 files changed, 4410 insertions(+), 4260 deletions(-) diff --git a/LedOK/LedOK Express.pro b/LedOK/LedOK Express.pro index 83760bc..570a104 100644 --- a/LedOK/LedOK Express.pro +++ b/LedOK/LedOK Express.pro @@ -29,11 +29,6 @@ msvc { contains(QT_ARCH, i386) { QMAKE_LFLAGS += /LARGEADDRESSAWARE } -# lessThan(QT_MAJOR_VERSION, 6) { -# QMAKE_CXXFLAGS += -execution-charset:utf-8 -# QMAKE_CXXFLAGS += -source-charset:utf-8 -# } - CONFIG += force_debug_info CONFIG += separate_debug_info } diff --git a/LedOK/device/upgradeapkdialog.cpp b/LedOK/device/upgradeapkdialog.cpp index 81ddf89..426681e 100644 --- a/LedOK/device/upgradeapkdialog.cpp +++ b/LedOK/device/upgradeapkdialog.cpp @@ -2,7 +2,7 @@ #include "gutil/qcore.h" #include "gutil/qgui.h" #include "gutil/qnetwork.h" -#include "base/waitingdlg.h" +#include "gutil/qwaitingdlg.h" #include "devicepanel.h" #include "deviceitem.h" #include @@ -14,55 +14,55 @@ #include #include #include +#include +#include UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { resize(1280, 720); setWindowFlag(Qt::WindowMaximizeButtonHint); - setWindowState(Qt::WindowMaximized); setWindowTitle(tr("Update APK")); auto vBox = new VBox(this); + vBox->setContentsMargins(6, 0, 6, 0); auto hBox = new HBox(vBox); auto btnSelectOnlineApk = new QPushButton(tr("Select Online APK")); - btnSelectOnlineApk->setMinimumSize(QSize(100, 30)); - btnSelectOnlineApk->setProperty("ssType", "progManageTool"); hBox->addWidget(btnSelectOnlineApk); auto btnSelectApk = new QPushButton(tr("Select apk")); - btnSelectApk->setMinimumSize(QSize(100, 30)); - btnSelectApk->setProperty("ssType", "progManageTool"); hBox->addWidget(btnSelectApk); auto btnSelectFpga = new QPushButton(tr("Select Fpga")); - btnSelectFpga->setMinimumSize(QSize(100, 30)); - btnSelectFpga->setProperty("ssType", "progManageTool"); hBox->addWidget(btnSelectFpga); - auto fdFileName = new QLabel; - fdFileName->setMinimumSize(200, 30); - fdFileName->setStyleSheet("background-color: #fff;"); + auto fdFileName = new QLineEdit; + fdFileName->setReadOnly(true); + fdFileName->setMinimumWidth(200); hBox->addWidget(fdFileName); connect(btnSelectApk, &QPushButton::clicked, this, [=] { - filePath = QFileDialog::getOpenFileName(this, "Open file", QString(), "apk package (*.apk *.zip)"); - if(filePath.isEmpty()) return; + auto aaa = QFileDialog::getOpenFileName(this, "Open file", gApkHome, "apk package (*.apk *.zip)"); + if(aaa.isEmpty()) return; + QFileInfo info(filePath = aaa); + gApkHome = info.absolutePath(); + fdFileName->setText(info.fileName()); fileId = ""; - fdFileName->setText(QFileInfo(filePath).fileName()); }); connect(btnSelectFpga, &QPushButton::clicked, this, [=] { - filePath = QFileDialog::getOpenFileName(this, "Open File", QString(), "rpd package (*.rpd)"); - if(filePath.isEmpty()) return; + auto aaa = QFileDialog::getOpenFileName(this, "Open File", gApkHome, "rpd package (*.rpd)"); + if(aaa.isEmpty()) return; + QFileInfo info(filePath = aaa); + gApkHome = info.absolutePath(); + fdFileName->setText(info.fileName()); fileId = ""; - fdFileName->setText(QFileInfo(filePath).fileName()); }); connect(btnSelectOnlineApk, &QPushButton::clicked, this, [=] { NetReq req("https://www.ledokcloud.com/aips4/screen/upgrade/getGeneric?type=0&page=1&limit=10"); req.setRawHeader("token","e183653f716cb150ebf3b4f8a83c95e7"); auto reply = req.timeout(60000).post(""); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; + ConnReply(reply, this) [=] { + JValue json; auto err = errStrWithData(reply, &json); if(! err.isEmpty()) { QMessageBox::critical(this, "Error", err); @@ -73,7 +73,7 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { return; } auto files = json["page"]["list"].toArray(); - if(files.isEmpty()) { + if(files.empty()) { QMessageBox::critical(this, "Error", tr("No Files")); return; } @@ -87,23 +87,24 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { auto vBox = new VBox(&dlg); vBox->setContentsMargins(0,0,0,0); - auto table = new Table{ - {"name", tr("Name"), 200, QHeaderView::Stretch}, - {"size", tr("Size"), 80}, - {"createTime", tr("Create Time"), 150} - }; - table->setDefs(); - table->setSelectionMode(QAbstractItemView::SingleSelection); - foreach(QJsonValue file, files) { - auto rr = table->appendRow(); - table->setText(rr, "name", file["fileName"].toString()+"."+file["suffix"].toString()); - table->setText(rr, "size", byteSizeStr(file["fileSize"].toInt()))->setTextAlignment(AlignRight); - table->setText(rr, "createTime", file["createTime"].toString()); - table->setData(rr, 0, file["fileId"].toString()); + auto table = new TreeWidget; + table->addCol("#", "", 20); + table->addCol("name", tr("Name"), 200, QHeaderView::Stretch); + table->addCol("size", tr("Size"), 80).alignR().margin(4); + table->addCol("createTime", tr("Create Time"), 150).margin(2); + table->setDefs()->setHeaderAlignC(); + table->minRowHeight = 28; + for(auto &file : files) { + auto item = new TreeWidgetItem(table); + item->setText("name", file["fileName"].toString()+"."+file["suffix"].toString()); + item->setText("size", byteSizeStr(file["fileSize"].toInt())); + item->setText("createTime", file["createTime"].toString()); + item->setData(0, file["fileId"].toString()); } - connect(table, &Table::cellDoubleClicked, &dlg, [=, &dlg](int row) { - fdFileName->setText(table->text(row, "name")); - fileId = table->data(row, 0).toString(); + connect(table, &TreeWidget::itemDoubleClicked, &dlg, [=, &dlg](QTreeWidgetItem *itm) { + auto item = (TreeWidgetItem*) itm; + fdFileName->setText(item->text("name")); + fileId = item->data(0).toString(); filePath = ""; dlg.accept(); }); @@ -113,14 +114,13 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close); connect(btnBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); connect(btnBox, &QDialogButtonBox::accepted, &dlg, [=, &dlg] { - auto sels = table->selectedRanges(); - if(sels.isEmpty()) { + auto item = table->selectedItem(); + if(item==0) { QMessageBox::warning(&dlg, "Warning", tr("Please select a file")); return; } - auto row = sels[0].topRow(); - fdFileName->setText(table->text(row, "name")); - fileId = table->data(row, 0).toString(); + fdFileName->setText(item->text("name")); + fileId = item->data(0).toString(); filePath = ""; dlg.accept(); }); @@ -130,25 +130,16 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { }); }); - auto btnUpgread = new QPushButton(tr("Upgrade")); - btnUpgread->setMinimumSize(QSize(80, 30)); - btnUpgread->setProperty("ssType", "progManageTool"); - connect(btnUpgread, &QPushButton::clicked, this, [=] { + auto btnUpdate = new QPushButton(tr("Upgrade")); + connect(btnUpdate, &QPushButton::clicked, this, [=] { auto fileName = fdFileName->text(); if(fileName.length() < 3) return; int cnt = table->topLevelItemCount(); - QList items; - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { - auto item = static_cast(table->topLevelItem(i)); - if(item->isUpdating) { - QMessageBox::information(this, tr("Tip"), tr("Is upgrading now. Please wait")); - return; - } - if(item->mCard.hasPassword && item->mCard.isLocked && item->m_lockFlag) { - item->setResult(tr("This screen is encrypted"), Qt::red); - return; - } - items.append(item); + QList items; + UpdateApkItem *item; + for(int rr=0; rrtopLevelItem(rr))->isHidden() && item->checkState("id") == Qt::Checked && ! item->isUpdating) { + if(item->isLocked) item->setResult(tr("This screen is encrypted"), Qt::red); + else items.append(item); } if(items.isEmpty()) { QMessageBox::information(this, tr("Tip"), tr("NoSelectedController")); @@ -161,17 +152,19 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { if(! file.open(QIODevice::ReadOnly)) return; fileData = file.readAll(); file.close(); + if(fileData.size() != file.size()) { + QMessageBox::information(this, tr("Tip"), tr("File Read Fail")); + return; + } } else if(! fileId.isEmpty()) { auto waitingDlg = new WaitingDlg(this, tr("Downloading Online File")+" ..."); waitingDlg->show(); - auto reply = NetReq("https://www.ledokcloud.com/aips4/sys/file/download/"+fileId).timeout(120000).get(); - QEventLoop loop; - connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + auto reply = NetReq("https://www.ledokcloud.com/aips4/sys/file/download/"+fileId).timeout(60000).get(); connect(reply, &QNetworkReply::downloadProgress, waitingDlg, [=](qint64 bytesReceived, qint64 bytesTotal) { if(bytesTotal==0) return; waitingDlg->fdText->setText(tr("Downloading Online File")+" "+QString::number(bytesReceived*100/bytesTotal)+" %"); }); - loop.exec(QEventLoop::ExcludeUserInputEvents); + if(waitFinished(reply, waitingDlg)) return; waitingDlg->close(); auto err = errStr(reply); fileData = reply->readAll(); @@ -184,6 +177,9 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { QMessageBox::critical(this, tr("Error"), tr("Online file is empty")); return; } + } else { + QMessageBox::critical(this, tr("Error"), tr("File is empty")); + return; } auto nameBytes = fileName.toUtf8(); auto Boundary = "----QtLedOK_.oOo._"+QUuid::createUuid().toByteArray(QUuid::WithoutBraces); @@ -192,24 +188,24 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { data.append("--").append(Boundary).append("\r\nContent-Disposition: form-data; name=\"").append(nameBytes).append("\"; filename=\"").append(nameBytes).append("\"\r\n\r\n").append(fileData).append("\r\n"); data.append("--").append(Boundary).append("--\r\n"); bool isApk = ! fileName.endsWith(".rpd", Qt::CaseInsensitive); - foreach(auto item, items) { - item->setResult(tr("Uploading")+" ..."); - item->mProgress->setValue(0); + for(auto item : items) { item->isUpdating = true; - NetReq req("http://"+item->mCard.ip+":2016/upload?type="+(isApk ? "software":"hardware")); - auto reply = req.timeout(120000).type("multipart/form-data; boundary="+Boundary).post(data); - connect(reply, &QNetworkReply::uploadProgress, item->mProgress, [item](qint64 bytesSent, qint64 bytesTotal) { + item->setResult(tr("Uploading")+" ..."); + item->fdProgress->setValue(0); + NetReq req("http://"+item->text("ip")+":2016/upload?type="+(isApk ? "software":"hardware")); + auto reply = req.timeout(60000).type("multipart/form-data; boundary="+Boundary).post(data); + connect(reply, &QNetworkReply::uploadProgress, item->fdProgress, [item](qint64 bytesSent, qint64 bytesTotal) { if(bytesTotal==0) return; - item->mProgress->setValue(bytesSent*100/bytesTotal); + item->fdProgress->setValue(bytesSent*100/bytesTotal); }); - connect(reply, &QNetworkReply::finished, item->mProgress, [=] { + ConnReply(reply, item->fdProgress) [=] { QString err = errStrWithData(reply); if(! err.isEmpty()) { item->setResult(tr("Upload error")+": "+err, Qt::red); item->isUpdating = false; return; } - item->mProgress->setValue(100); + item->fdProgress->setValue(100); auto info = tr("Installing")+" ..."; QJsonObject json; if(isApk) { @@ -218,33 +214,40 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { json.insert("fileName", fileName); json.insert("isCustom", true); } else { - info += tr("Don't power off during this process"); + info += " ("+tr("Don't power off during this process")+")"; json.insert("_id", "SynchronousHardwareVersion"); json.insert("_type", "SynchronousHardwareVersion"); } item->setResult(info); - auto reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, item->mProgress, [=] { - item->isUpdating = false; - QString err = errStrWithData(reply); + auto reply = NetReq("http://"+item->text("ip")+":2016/settings").timeout(60000).post(json); + ConnReply(reply, item->fdProgress) [=] { + if(item->treeWidget()==0) return; + QJsonDocument json; + auto err = checkReplyForJson(reply, &json); if(! err.isEmpty()) { + item->isUpdating = false; item->setResult(tr("Install error")+": "+err, Qt::red); return; } - item->setResult(tr("Install success"), Qt::darkGreen); - if(isApk) item->OnCheckSoftVersions(); - else item->OnCheckFpgaVersions(); + if(isApk || ! json["hasProgress"].toBool()) { + item->isUpdating = false; + item->setResult(tr("Install Success"), Qt::darkGreen); + if(isApk) item->OnCheckSoftVersions(); + else item->OnCheckFpgaVersions(); + } else { + sendProgress(item); + item->fdProgress->setValue(0); + } }); }); } }); - hBox->addWidget(btnUpgread); + hBox->addWidget(btnUpdate); hBox->addStretch(); hBox->addWidget(new QLabel("APK:")); auto fdApk = new QComboBox; - fdApk->setMinimumWidth(200); fdApk->setEditable(true); fdApk->addItem("com.xixun.xixunplayer"); fdApk->addItem("com.xixun.joey.cardsystem"); @@ -258,8 +261,6 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { hBox->addWidget(fdApk); auto btnUninstall = new QPushButton(tr("Uninstall")); - btnUninstall->setMinimumSize(80, 30); - btnUninstall->setProperty("ssType", "progManageTool"); connect(btnUninstall, &QPushButton::clicked, this, [this, fdApk] { auto strApkName = fdApk->currentText(); if(strApkName.isEmpty()) { @@ -268,15 +269,15 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { } if(! strApkName.endsWith(".xixunplayer") && ! strApkName.endsWith(".taxiapp") && QMessageBox::warning(this, tr("Reminder"), tr("Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution!")+"\n"+tr("Do you want to continue?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) return; int cnt = table->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { - auto item = static_cast(table->topLevelItem(i)); + for(int i=0; iitem(i)->checkState("id") == Qt::Checked) { + auto item = (UpdateApkItem *) table->topLevelItem(i); item->setResult(tr("Uninstalling")+" ..."); QJsonObject json; json.insert("_id", "UninstallSoftware"); json.insert("_type", "UninstallSoftware"); json.insert("packageName", strApkName); - auto reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [reply, item, strApkName] { + auto reply = NetReq("http://"+item->text("ip")+":2016/settings").timeout(60000).post(json); + ConnReply(reply, item->fdOnline) [reply, item, strApkName] { QString err = checkReplyForJson(reply, "error"); if(! err.isEmpty()) { item->setResult(tr("Uninstall error")+": "+err, Qt::red); @@ -289,22 +290,20 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { hBox->addWidget(btnUninstall); auto btnCheck = new QPushButton(tr("check running state")); - btnCheck->setMinimumSize(QSize(140, 30)); - btnCheck->setProperty("ssType", "progManageTool"); connect(btnCheck, &QPushButton::clicked, this, [this, fdApk] { QString strApkName = fdApk->currentText(); int cnt = table->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { - auto item = static_cast(table->topLevelItem(i)); + for(int i=0; iitem(i)->checkState("id") == Qt::Checked) { + auto item = (UpdateApkItem *) table->topLevelItem(i); item->setResult(tr("Check apk running status")); QJsonObject json; json.insert("_id", "IsSoftwareRunning"); json.insert("_type", "IsSoftwareRunning"); json.insert("packageName", strApkName); - auto reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [reply, item, strApkName] { + auto reply = NetReq("http://"+item->text("ip")+":2016/settings").timeout(60000).post(json); + ConnReply(reply, item->fdOnline) [reply, item, strApkName] { QJsonDocument json; - QString err = errStrWithData(reply, &json); + auto err = errStrWithData(reply, &json); if(! err.isEmpty()) { item->setResult(tr("Check error")+": "+err, Qt::red); return; @@ -324,323 +323,260 @@ UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { hBox->addStretch(); auto btnRefresh = new QPushButton(tr("Refresh")); - btnRefresh->setMinimumSize(QSize(0, 30)); - btnRefresh->setProperty("ssType", "progManageTool"); - connect(btnRefresh, &QPushButton::clicked, this, [this, label] { + connect(btnRefresh, &QPushButton::clicked, this, [=] { table->clear(); - table->onCheckAll(false); + table->fdCheckAll->setCheckState(Qt::Unchecked); int cnt = gDevicePanel->mDeviceTable->topLevelItemCount(); - for(int i=0; i(gDevicePanel->mDeviceTable->topLevelItem(i))->mCard); - label->setText(tr("All")+":"+QString::number(cnt)); + for(int cc=0; ccmDeviceTable->topLevelItem(cc))->mCard; + int cnt = table->topLevelItemCount(); + UpdateApkItem* item; + for(int rr=0; rrtopLevelItem(rr))->text("id") == card.id) goto end; + item = new UpdateApkItem(table); + item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable); + item->setCheckState("id", Qt::Unchecked); + item->setText("id", card.id); + { + item->fdOnline = new QLabel; + item->fdOnline->setScaledContents(true); + item->fdOnline->setFixedSize(24, 24); + auto wgt = new QWidget; + auto hhh = new HBox(wgt); + hhh->setContentsMargins(0,0,0,0); + hhh->addWidget(item->fdOnline); + item->setCellWidget("online", wgt); + } + item->fdProgress = new QProgressBar; + item->fdProgress->setAlignment(Qt::AlignCenter); + item->fdProgress->setStyleSheet("QProgressBar {margin-top: 6px; margin-bottom: 6px;}"); + item->setCellWidget("progress", item->fdProgress); + end: + item->setText("ip", card.ip); + item->setText("alias", card.alias); + item->fdOnline->setPixmap({card.isOnline ? ":/res/online.png" : ":/res/offline.png"}); + item->OnCheckSoftVersions(); + item->OnCheckFpgaVersions(); + if(! card.hasPassword) { + item->isLocked = false; + item->setCellWidget("encrypt", item->btnUnlock = 0); + } else { + item->isLocked = card.isLocked; + if(item->btnUnlock==0) { + item->btnUnlock = new QPushButton; + item->btnUnlock->setMaximumHeight(36); + item->setCellWidget("encrypt", item->btnUnlock); + connect(item->btnUnlock, &QPushButton::clicked, item->btnUnlock, [=] { + if(! item->isLocked) return; + bool ok; + auto pwd = QInputDialog::getText(this, tr("Input password"), tr("Input password"), QLineEdit::Password, QString(), &ok); + if(! ok) return; + QJsonObject json; + json.insert("_id", "VerifyPassword"); + json.insert("_type", "VerifyPassword"); + json.insert("pwd", pwd); + auto waitingDlg = new WaitingDlg(item->btnUnlock, tr("VerifyPassword")+" ..."); + waitingDlg->show(); + auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(30000).post(json); + ConnReply(reply, waitingDlg) [=] { + QJsonDocument json; + auto err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(this, tr("Error"), err); + return; + } + if(! json["result"].toBool()) { + waitingDlg->close(); + QMessageBox::warning(this, tr("Tip Info"), tr("password is wrong")); + return; + } + waitingDlg->success(); + item->isLocked = false; + item->btnUnlock->setIcon(QIcon(":/res/UnLock.png")); + auto item = findItem(card.id); + if(item) { + item->mCard.isLocked = false; + item->btnUnlock->setIcon(QIcon(":/res/UnLock.png")); + } + }); + }); + } + item->btnUnlock->setIcon(QIcon(card.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); //已验证显示绿色 没验证蓝色 + } + } + label->setText(tr("All")+": "+QString::number(cnt)); }); hBox->addWidget(btnRefresh); - auto txtSearch = new QLineEdit(); - txtSearch->setClearButtonEnabled(true); - txtSearch->setMaximumWidth(200); - txtSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), ""), QLineEdit::LeadingPosition); - connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &))); - hBox->addWidget(txtSearch); + auto fdSearch = new QLineEdit; + fdSearch->setClearButtonEnabled(true); + fdSearch->setMaximumWidth(160); + fdSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), ""), QLineEdit::LeadingPosition); + connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &text) { + auto cnt = table->topLevelItemCount(); + if(text.isEmpty()) { + for(int rr=0; rritem(rr)->setHidden(false); + return; + } + bool isEmpty = true; + for(int rr=0; rritem(rr); + bool contain = item->text("id").contains(text) || item->text("alias").contains(text) || item->text("remarks").contains(text) || item->text("ip").contains(text); + item->setHidden(! contain); + if(contain) isEmpty = false; + } + if(isEmpty) for(int rr=0; rritem(rr); + item->setHidden(! (item->text("xixunplayer").contains(text) + || item->text("cardsystem").contains(text) + || item->text("starter").contains(text) + || item->text("taxiapp").contains(text) + || item->text("displayer").contains(text) + || item->text("fpga").contains(text) + || item->text("connection").contains(text) + || item->text("update").contains(text) + )); + } + }); + hBox->addWidget(fdSearch); - - table = new LoQTreeWidget(); - table->setProperty("ssType", "topList"); + table = new LoQTreeWidget; + table->addCol("#", "", 20); + table->addCol("id", "ID", 125).margin(4); + table->addCol("online", tr("Online"), 40); + table->addCol("ip", "IP", 95); + table->addCol("alias", tr("Alias"), 80); + table->addCol("encrypt", tr("Security"), 40); + table->addCol("progress", tr("Progress"), 100); + table->addCol("remarks", tr("State"), 200, QHeaderView::Stretch); + table->addCol("xixunplayer", "xixunplayer", 70); + table->addCol("cardsystem", "cardsystem", 70); + table->addCol("starter", "starter", 70); + table->addCol("taxiapp", "taxiapp", 70); + table->addCol("displayer", "displayer", 70); + table->addCol("fpga", "FPGA", 70); + table->addCol("connection", "connection", 70); + table->addCol("update", "update", 40); + table->setDefs()->setHeaderAlignC(); + table->addFd(); + table->setSelectionMode(QAbstractItemView::NoSelection); + table->setSortingEnabled(true); vBox->addWidget(table); - hBox = new HBox(vBox); - hBox->addStretch(); + auto sortField = gDevicePanel->mDeviceTable->sortField(); + if(sortField=="id" || sortField=="ip" || sortField=="alias") table->sortItems(sortField, gDevicePanel->mDeviceTable->header()->sortIndicatorOrder()); + else table->sortItems("id"); - auto pushButtonCancel = new QPushButton(tr("Cancel")); - pushButtonCancel->setMinimumSize(QSize(0, 30)); - pushButtonCancel->setProperty("ssType", "progManageTool"); - connect(pushButtonCancel, &QPushButton::clicked, this, &UpgradeApkDialog::reject); - hBox->addWidget(pushButtonCancel); + setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + show(); - - m_headerItem = new QTreeWidgetItem(); - for(int i=1; isetTextAlignment(i, Qt::AlignCenter); - m_headerItem->setText(Upgrade_Check, ""); - m_headerItem->setText(Upgrade_SCREEN_ID, tr("Screen ID")); - m_headerItem->setText(Upgrade_ONLINE, tr("Online")); - m_headerItem->setText(Upgrade_SCREEN_IP, tr("Screen IP")); - m_headerItem->setText(Upgrade_ENCRYPT, tr("Security")); - m_headerItem->setText(Upgrade_REMARK_NAME, tr("Alias")); - m_headerItem->setText(Upgrade_PROGRESS, tr("Progress")); - m_headerItem->setText(Upgrade_Remark, tr("State")); - m_headerItem->setText(Upgrade_XIXUNPLAYER_VERSION, tr("xixunplayer")); - m_headerItem->setText(Upgrade_CARDSYSTEM_VERSION, tr("cardsystem")); - m_headerItem->setText(Upgrade_STARTER_VERSION, tr("starter")); - m_headerItem->setText(Upgrade_TAXIAPP_VERSION, tr("taxiapp")); - m_headerItem->setText(Upgrade_DISPLAYER_VERSION, tr("displayer")); - m_headerItem->setText(Upgrade_FPAG_VERSION, tr("FPGA")); - m_headerItem->setText(Upgrade_CONNECTION_VERSION, tr("connection")); - m_headerItem->setText(Upgrade_UPDATE_VERSION, tr("update")); - - table->setHeaderItem(m_headerItem); - table->header()->setSectionResizeMode(Upgrade_Check, QHeaderView::Fixed); - table->setColumnWidth(Upgrade_Check, 40); - table->header()->setSectionResizeMode(Upgrade_SCREEN_ID, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_ONLINE, QHeaderView::Fixed); - table->setColumnWidth(Upgrade_ONLINE, 40); - table->header()->setSectionResizeMode(Upgrade_SCREEN_IP, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_ENCRYPT, QHeaderView::Fixed); - table->setColumnWidth(Upgrade_ENCRYPT, 40); - table->header()->setSectionResizeMode(Upgrade_PROGRESS, QHeaderView::Fixed); - table->setColumnWidth(Upgrade_PROGRESS, 100); - table->header()->setSectionResizeMode(Upgrade_XIXUNPLAYER_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_CARDSYSTEM_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_STARTER_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_TAXIAPP_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_DISPLAYER_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_FPAG_VERSION, QHeaderView::Fixed); - table->setColumnWidth(Upgrade_FPAG_VERSION, 100); - table->header()->setSectionResizeMode(Upgrade_Remark, QHeaderView::Stretch); - table->header()->setSectionResizeMode(Upgrade_REMARK_NAME, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_CONNECTION_VERSION, QHeaderView::ResizeToContents); - table->header()->setSectionResizeMode(Upgrade_UPDATE_VERSION, QHeaderView::ResizeToContents); - - int cnt = gDevicePanel->mDeviceTable->topLevelItemCount(); - for(int i=0; i(gDevicePanel->mDeviceTable->topLevelItem(i))->mCard); - label->setText(tr("All")+":"+QString::number(cnt)); -} - -void UpgradeApkDialog::onAddLedCard(LedCard card) { - int iExistFlg=0; - int cnt = table->topLevelItemCount(); - for(int i=0; i(table->topLevelItem(i))->mCard.id; - if(strTempCardId == card.id) { - iExistFlg=1; - static_cast(table->topLevelItem(i))->SetItemParam(card); - break; - } - } - if(iExistFlg) return; - new wUpgradeApkItem(card, table); -} - -void UpgradeApkDialog::keyPressEvent(QKeyEvent *ev) { - if(ev->key() == Qt::Key_F3) { - QMessageBox::warning(this, "Tip", tr("The encrypted control card can be upgraded directly")); - int cnt = table->topLevelItemCount(); - for(int i=0; i(table->topLevelItem(i))->m_lockFlag = false; + emit btnRefresh->clicked(); + int ccs[]{"taxiapp"**table, "fpga"**table}; + for(auto cc : ccs) { + auto size = table->sizeHintForColumn(cc); + if(size==0) { + int cnt = 8; + do { + wait(50); + size = table->sizeHintForColumn(cc); + } while(size==0 && --cnt); + } + if(size>table->header()->sectionSize(cc)) table->header()->resizeSection(cc, size); } } -void UpgradeApkDialog::FilterProgram(const QString &strtemp) -{ - if (strtemp.isEmpty()) //显示全部 - { - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); - } - } - else - { - QList resultList = table->findItems(strtemp, Qt::MatchContains,Upgrade_SCREEN_ID); //搜索结果 - if (resultList.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList6 = table->findItems(strtemp, Qt::MatchContains,Upgrade_REMARK_NAME); //搜索结果 - if (resultList6.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList6.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - - - //QMessageBox::warning(this, "Export", "FilterProgram"); - QList resultList1 = table->findItems(strtemp, Qt::MatchContains,Upgrade_XIXUNPLAYER_VERSION); //搜索结果 - if (resultList1.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList1.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_SCREEN_IP); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_XIXUNPLAYER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_CARDSYSTEM_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_TAXIAPP_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_DISPLAYER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_STARTER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_CONNECTION_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_UPDATE_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_FPAG_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_Remark); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - if (resultList2.contains(topItem)) - table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - for (int i = 0; i< table->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = table->topLevelItem(i); - table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - } - } - } - } - } - } - } - } - } - } - } +void UpgradeApkDialog::sendProgress(UpdateApkItem *item) { + QJsonObject json; + json.insert("_id", "GetFpgaUpdateProgress"); + json.insert("_type", "GetFpgaUpdateProgress"); + auto reply = NetReq("http://"+item->text("ip")+":2016/settings").timeout(30000).post(json); + ConnReply(reply, item->fdProgress) [=] { + if(item->treeWidget()==0) return; + QJsonDocument json; + auto err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + item->isUpdating = false; + item->setResult("GetFpgaUpdateProgress "+tr("Error")+": "+err, Qt::red); + return; } + auto progre = json["progress"].toInt(); + if(progre >= 100) { + item->isUpdating = false; + item->fdProgress->setValue(100); + item->setResult(tr("Install Success"), Qt::darkGreen); + item->OnCheckFpgaVersions(); + } else if(progre == -1) { + item->isUpdating = false; + item->fdProgress->setValue(100); + item->setResult(tr("Same version, needn't update"), Qt::darkGreen); + } else if(progre == -2) { + item->isUpdating = false; + item->setResult(tr("Install Failed")+" (-2)", Qt::red); + } else { + item->fdProgress->setValue(progre); + wait(250); + sendProgress(item); + } + }); +} +void UpgradeApkDialog::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_F3) { + QMessageBox::warning(this, "Tip", tr("The encrypted control card can be upgraded directly")); + auto cnt = table->topLevelItemCount(); + for(int i=0; itopLevelItem(i))->isLocked = false; } } + + +void UpdateApkItem::OnCheckFpgaVersions() { + QJsonObject json; + json.insert("_id", "CheckHardwareVersions"); + json.insert("_type", "CheckHardwareVersions"); + auto reply = NetReq("http://"+text("ip")+":2016/settings").timeout(60000).post(json); + ConnReply(reply, fdProgress) [=] { + if(treeWidget()==0) return; + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + return; + } + QString strBuf; + auto vers = json["versions"].toArray(); + for(int i=0; imCard.HardVersion = strBuf; + } + }); +} +void UpdateApkItem::OnCheckSoftVersions() { + QJsonObject json; + json.insert("_id", "CheckSoftVersions"); + json.insert("_type", "CheckSoftVersions"); + auto reply = NetReq("http://"+text("ip")+":2016/settings").timeout(60000).post(json); + ConnReply(reply, fdProgress) [=] { + if(treeWidget()==0) return; + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + return; + } + auto apps = json["apps"].toArray(); + foreach(QJsonValue app, apps) { + QString packageName = app["packageName"].toString(); + QString verName = app["versionName"].toString(); + if(packageName=="com.xixun.xixunplayer") setText("xixunplayer", verName); + else if(packageName=="com.xixun.joey.cardsystem") setText("cardsystem", verName); + else if(packageName=="net.sysolution.starter") setText("starter", verName); + else if(packageName=="net.sysolution.taxiapp") setText("taxiapp", verName); + else if(packageName=="com.xixun.display") setText("displayer", verName); + else if(packageName=="com.xixun.xy.conn") setText("connection", verName); + else if(packageName=="com.xixun.xy.update") setText("update", verName); + } + }); +} diff --git a/LedOK/device/upgradeapkdialog.h b/LedOK/device/upgradeapkdialog.h index 9e1d2c4..dc3d8a3 100644 --- a/LedOK/device/upgradeapkdialog.h +++ b/LedOK/device/upgradeapkdialog.h @@ -1,25 +1,40 @@ #ifndef UPGRADEAPKDIALOG_H #define UPGRADEAPKDIALOG_H +#include "base/loqtreewidget.h" #include -#include -#include "wupgradeapkitem.h" +#include +class UpdateApkItem; class UpgradeApkDialog : public QDialog { Q_OBJECT public: explicit UpgradeApkDialog(QWidget *parent = nullptr); + void sendProgress(UpdateApkItem *item); + QString filePath, fileId; protected: virtual void keyPressEvent(QKeyEvent *ev); -protected slots: - void FilterProgram(const QString &strtemp); - -private: - void onAddLedCard(LedCard p); - LoQTreeWidget *table; - QTreeWidgetItem *m_headerItem=nullptr; +}; + +class UpdateApkItem : public TreeWidgetItem { +public: + using TreeWidgetItem::TreeWidgetItem; + void setResult(QString tip, QColor color = Qt::blue) { + auto remarks = "remarks"**treeWidget(); + setText(remarks, tip); + setToolTip(remarks, tip); + setForeground(remarks, color); + } + void OnCheckSoftVersions(); + void OnCheckFpgaVersions(); + + QLabel *fdOnline; + QProgressBar *fdProgress; + QPushButton *btnUnlock = 0; + bool isUpdating = false; + bool isLocked = true; }; #endif // UpgradeApkDialog_H diff --git a/LedOK/deviceitem.cpp b/LedOK/deviceitem.cpp index 710f19e..efba5e4 100644 --- a/LedOK/deviceitem.cpp +++ b/LedOK/deviceitem.cpp @@ -1,6 +1,7 @@ #include "deviceitem.h" +#include "devicepanel.h" #include "globaldefine.h" -#include "base/waitingdlg.h" +#include "gutil/qwaitingdlg.h" #include "gutil/qgui.h" #include "gutil/qnetwork.h" #include @@ -8,86 +9,73 @@ #include #include -DeviceItem::DeviceItem(LoQTreeWidget *parent) : QObject(parent), QTreeWidgetItem(UserType), m_parent(parent) { - setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - setCheckState(0, Qt::Unchecked); - m_parent->addTopLevelItem(this); +DeviceItem::DeviceItem(LoQTreeWidget *parent) : TreeWidgetItem(parent) { + setFlags(flags() & ~Qt::ItemIsUserCheckable); + setCheckState("check", Qt::Unchecked); + auto ft = treeWidget()->font(); + ft.setPixelSize(14); + for(int i=2; icolumnCount()-2; i++) setFont(i, ft); - m_bnCardDetailInfo = new QPushButton(); - m_bnCardDetailInfo->setToolTip(tr("GetScreenDetailInfo")); - m_bnCardDetailInfo->setCursor(QCursor(Qt::PointingHandCursor)); - m_bnCardDetailInfo->setStyleSheet(R"rrr( -QPushButton { - border-radius: 4px; - image: url(:/res/bnDetail.png); -} -QPushButton:hover{background-color: #ccc;} -)rrr"); - m_parent->setItemWidget(this, DeviceTable_Info, m_bnCardDetailInfo); - - m_bnReadbackPic = new QPushButton(); - m_bnReadbackPic->setToolTip(tr("ReadbackPic")); - m_bnReadbackPic->setCursor(QCursor(Qt::PointingHandCursor)); - m_bnReadbackPic->setStyleSheet(R"rrr( -QPushButton { - border-radius: 4px; - image: url(:/res/deviceReadbackPic.png); -} -QPushButton:hover{background-color: #ccc;} -)rrr"); - connect(m_bnReadbackPic, &QPushButton::clicked, this, [this] { + auto btnGetCapture = new QPushButton; + btnGetCapture->setCursor(QCursor(Qt::PointingHandCursor)); + btnGetCapture->setIcon(QIcon(":/res/deviceReadbackPic.png")); + btnGetCapture->setIconSize({28, 28}); + QObject::connect(btnGetCapture, &QPushButton::clicked, btnGetCapture, [=] { QJsonObject json; json.insert("_id", "GetScreenshotFull"); json.insert("_type", "GetScreenshotFull"); - auto waitingDlg = new WaitingDlg(treeWidget(), tr("GetScreenshotFull")+" ..."); + auto waitingDlg = new WaitingDlg(btnGetCapture, DevicePanel::tr("Getting ")+DevicePanel::tr("Screenshot")+" ..."); waitingDlg->show(); auto reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - waitingDlg->connAbort(reply); - connect(reply, &QNetworkReply::finished, this, [=] { + ConnReply(reply, waitingDlg) [=] { waitingDlg->close(); QJsonDocument json; QString err = checkReplyForJson(reply, &json); if(! err.isEmpty()) { - QMessageBox::critical(treeWidget(), tr("Error"), err); + QMessageBox::critical(treeWidget(), DevicePanel::tr("Error"), err); return; } ImgDlg dlg(QByteArray::fromBase64(json["data"].toString().toLatin1()), treeWidget()); dlg.exec(); }); }); - m_parent->setItemWidget(this, DeviceTable_Screenshot, m_bnReadbackPic); + setCellWidget("screenshot", btnGetCapture); - m_ImageOnline = new QLabel; - m_ImageOnline->setPixmap(QPixmap(":/res/O_Online.png")); - m_ImageOnline->setAlignment(Qt::AlignCenter); - m_parent->setItemWidget(this, DeviceTable_Online, m_ImageOnline); + fdOnline = new QLabel; + fdOnline->setPixmap({":/res/online.png"}); + fdOnline->setScaledContents(true); + fdOnline->setFixedSize(24, 24); + auto wgt = new QWidget; + auto hhh = new HBox(wgt); + hhh->setContentsMargins(0,0,0,0); + hhh->addWidget(fdOnline); + setCellWidget("online", wgt); btnUnlock = new QPushButton; btnUnlock->setMaximumHeight(40); - connect(btnUnlock, &QPushButton::clicked, this, [this] { + QObject::connect(btnUnlock, &QPushButton::clicked, btnUnlock, [this] { if(! mCard.isLocked) return; bool ok; - auto pwd = QInputDialog::getText(treeWidget(), tr("Input password"), tr("Input password"), QLineEdit::Password, QString(), &ok); + auto pwd = QInputDialog::getText(treeWidget(), DevicePanel::tr("Input password"), DevicePanel::tr("Input password"), QLineEdit::Password, QString(), &ok); if(! ok) return; QJsonObject json; json.insert("_id", "VerifyPassword"); json.insert("_type", "VerifyPassword"); json.insert("pwd", pwd); - auto waitingDlg = new WaitingDlg(treeWidget(), tr("VerifyPassword")+" ..."); + auto waitingDlg = new WaitingDlg(btnUnlock, DevicePanel::tr("VerifyPassword")+" ..."); waitingDlg->show(); auto reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(60000).post(json); - waitingDlg->connAbort(reply); - connect(reply, &QNetworkReply::finished, this, [=] { + ConnReply(reply, waitingDlg) [=] { QJsonDocument json; QString err = checkReplyForJson(reply, &json); if(! err.isEmpty()) { waitingDlg->close(); - QMessageBox::critical(treeWidget(), tr("Error"), err); + QMessageBox::critical(treeWidget(), DevicePanel::tr("Error"), err); return; } if(! json["result"].toBool()) { waitingDlg->close(); - QMessageBox::critical(treeWidget(), tr("Tip Info"), tr("password is wrong")); + QMessageBox::critical(treeWidget(), DevicePanel::tr("Tip Info"), DevicePanel::tr("password is wrong")); return; } waitingDlg->success(); @@ -95,122 +83,17 @@ QPushButton:hover{background-color: #ccc;} btnUnlock->setIcon(QIcon(":/res/UnLock.png")); }); }); - auto wgt = new QWidget; - auto hBox = new HBox(wgt); - hBox->setContentsMargins(0,0,0,0); - hBox->addWidget(btnUnlock); - m_parent->setItemWidget(this, DeviceTable_Password, wgt); - - auto ft = font(0); - ft.setPixelSize(14); - for(int i=1; isetContentsMargins(0,0,0,0); + hhh->addWidget(btnUnlock); + setCellWidget("password", wgt); } void DeviceItem::init() { - setData(DeviceTable_ID, 0, mCard.id); - setData(DeviceTable_IP, 0, mCard.ip); - setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(mCard.mWidth).arg(mCard.mHeight)); + setText("id", mCard.id); + setText("ip", mCard.ip); + setText("screenSize", QString("%1 x %2").arg(mCard.mWidth).arg(mCard.mHeight)); if(mCard.hasPassword) btnUnlock->setIcon(QIcon(mCard.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); else btnUnlock->hide(); } -void DeviceItem::DeviceItemHttpPost() { - QJsonObject json; - json.insert("_id", "GetBuildInformation"); - json.insert("_type", "GetBuildInformation"); - auto reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.BrightnessLevel = json["BrightnessLevel"].toInt(); - mCard.FirmwareVersion = json["FirmwareVersion"].toString(); - mCard.HardVersion = json["HardVersion"].toString(); - mCard.ScreenResolution = json["ScreenResolution"].toString(); - mCard.IMEI = json["IMEI"].toString(); - auto androidVersion = json["AndroidVersion"].toString(); - if(! androidVersion.isEmpty()) mCard.androidVersion = androidVersion; - }); - - if(mCard.mWidth==0 || mCard.mHeight==0) { - json = QJsonObject(); - json.insert("_id", "GetScreenSize"); - json.insert("_type", "GetScreenSize"); - reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.mWidth = json["width"].toInt(); - mCard.mHeight = json["height"].toInt(); - setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(mCard.mWidth).arg(mCard.mHeight)); - }); - } - - json = QJsonObject(); - json.insert("_id", "GetBrightness"); - json.insert("_type", "GetBrightness"); - reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.bright = json["brightnessPercentage"].toInt(-1); - if(mCard.bright==-1) mCard.bright = qRound(json["brightness"].toInt() * 100.0 / mCard.BrightnessLevel); - setData(DeviceTable_Brightness, 0, QString::number(mCard.bright)+"%"); - }); - json = QJsonObject(); - json.insert("_id", "IsScreenOn"); - json.insert("_type", "IsScreenOn"); - reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.isScreenOn = json["on"].toBool(); - setForeground(DeviceTable_Power, mCard.isScreenOn ? Qt::green : Qt::red); - setData(DeviceTable_Power, 0, mCard.isScreenOn ? tr("On") : tr("Off")); - }); - json = QJsonObject(); - json.insert("_id", "GetCardAlias"); - json.insert("_type", "GetCardAlias"); - reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.alias = QString::fromUtf8(QByteArray::fromBase64(json["alias"].toString().toLatin1())); - setData(DeviceTable_Remark, 0, mCard.alias); - }); - - json = QJsonObject(); - json.insert("_id", "HasControllerPassword"); - json.insert("_type", "HasControllerPassword"); - reply = NetReq("http://"+mCard.ip+":2016/settings").timeout(120000).post(json); - connect(reply, &QNetworkReply::finished, this, [=] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) return; - mCard.hasPassword = json["result"].toBool(); - if(mCard.hasPassword) {//加过密 - btnUnlock->show(); - btnUnlock->setIcon(QIcon(mCard.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); - } else btnUnlock->hide(); - }); -} -ImgDlg::ImgDlg(const QByteArray &data, QWidget *parent) : QDialog(parent) { - setWindowFlag(Qt::WindowContextHelpButtonHint, 0); - setWindowTitle(tr("Screenshot")); - mImg.loadFromData(data); - auto www = mImg.width(); - auto hhh = mImg.height(); - if(www <= 1600 && hhh <= 900) resize(www, hhh); - else if(www > hhh) resize(900 * www / hhh, 900); - else resize(1600, 1600 * hhh / www); -} -void ImgDlg::paintEvent(QPaintEvent *) { - QPainter painter(this); - painter.drawImage(rect(), mImg); -} diff --git a/LedOK/deviceitem.h b/LedOK/deviceitem.h index a216cfc..d9bb999 100644 --- a/LedOK/deviceitem.h +++ b/LedOK/deviceitem.h @@ -2,48 +2,18 @@ #define DEVICEITEM_H #include -#include +#include "base/loqtreewidget.h" #include "globaldefine.h" #include #include -enum DeviceTableField { - DeviceTable_Check = 0, - DeviceTable_ID, - DeviceTable_Online, - DeviceTable_IP, - DeviceTable_ScreenSize, - DeviceTable_Remark, - DeviceTable_Brightness, - DeviceTable_Power, - DeviceTable_Password, - DeviceTable_Info, - DeviceTable_Screenshot, - DeviceTable_End, -}; - -class DeviceItem : public QObject, public QTreeWidgetItem { - friend class DevicePanel; - Q_OBJECT +class DeviceItem : public TreeWidgetItem { public: - explicit DeviceItem(LoQTreeWidget *parent); + explicit DeviceItem(LoQTreeWidget *); void init(); - void DeviceItemHttpPost(); LedCard mCard; - QPushButton *btnUnlock = nullptr; -private: - QPushButton *m_bnCardDetailInfo = nullptr; - QPushButton *m_bnReadbackPic = nullptr; - QLabel *m_ImageOnline=nullptr; - LoQTreeWidget *m_parent = nullptr; + QLabel *fdOnline; + QPushButton *btnUnlock = 0; }; -class ImgDlg : public QDialog { - Q_OBJECT -public: - explicit ImgDlg(const QByteArray &, QWidget *parent = 0); - QImage mImg; -public: - void paintEvent(QPaintEvent *) override; -}; #endif // DEVICEITEM_H diff --git a/LedOK/devicepanel.cpp b/LedOK/devicepanel.cpp index 236fb1e..375f08c 100644 --- a/LedOK/devicepanel.cpp +++ b/LedOK/devicepanel.cpp @@ -19,6 +19,7 @@ #include #include #include +#include DevicePanel *gDevicePanel; QTextEdit *gFdResInfo; @@ -57,21 +58,27 @@ DevicePanel::DevicePanel(QSettings &settings, QWidget *parent) : QWidget(parent) label_3 = new QLabel(tr("All")); hBox->addWidget(label_3); - nDeviceNum = new QLabel(); + nDeviceNum = new QLabel; nDeviceNum->setFixedSize(40, 20); hBox->addWidget(nDeviceNum); - auto fdSearch = new QLineEdit(); + auto fdSearch = new QLineEdit; fdSearch->setClearButtonEnabled(true); fdSearch->setFixedSize(220, 30); fdSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition); fdSearch->setStyleSheet("border: 1px solid #aaaaaa;"); - connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &search) { + connect(fdSearch, &QLineEdit::textChanged, this, [=](const QString &text) { auto cnt = mDeviceTable->topLevelItemCount(); - if(search.isEmpty()) for(int i=0; itopLevelItem(i)->setHidden(false); - else for(int i=0; itopLevelItem(i); - item->setHidden(! (item->text(DeviceTable_ID).contains(search) || item->text(DeviceTable_Remark).contains(search) || item->text(DeviceTable_IP).contains(search))); + int sel = 0, unsel = 0; + for(int i=0; iitem(i); + item->setHidden(! (text.isEmpty() || item->text("id").contains(text) || item->text("alias").contains(text) || item->text("ip").contains(text))); + if(item->isHidden()) item->setCheckState("check", Qt::Unchecked); + else (item->checkState("check")==Qt::Checked ? sel : unsel)++; + mDeviceTable->fdCheckAll->blockSignals(true); + mDeviceTable->fdCheckAll->setCheckState(sel==0 ? Qt::Unchecked : unsel ? Qt::PartiallyChecked : Qt::Checked); + mDeviceTable->fdCheckAll->blockSignals(false); + emit mDeviceTable->selChanged(); } }); hBox->addWidget(fdSearch); @@ -116,8 +123,8 @@ QComboBox QAbstractItemView::item:selected {background-color: #09c;} btnRefresh = new QPushButton(tr("Refresh"), areaFlash); btnRefresh->setGeometry(0, 0, 75, areaFlash->height()); connect(btnRefresh, &QPushButton::clicked, this, [this] { - mDeviceTable->onCheckAll(false); mDeviceTable->clear(); + mDeviceTable->fdCheckAll->setCheckState(Qt::Unchecked); nDeviceNum->setText("0"); sendGetInfo(); }); @@ -132,48 +139,37 @@ QPushButton:hover {background-color: #08b;} hBox->addWidget(areaFlash); - mHBox = new QHBoxLayout(); + mHBox = new HBox(vBox); - mDeviceTable = new LoQTreeWidget(this); - mDeviceTable->setSelectionMode(QAbstractItemView::NoSelection); - mDeviceTable->setIndentation(0); - mDeviceTable->setSortingEnabled(true); - mHBox->addWidget(mDeviceTable); + auto table = new LoQTreeWidget; + table->addCol("#", "", 20); + table->addCol("check", "", 28).margin(2); + table->addCol("id", "ID", 130, QHeaderView::Stretch).alignC(); + table->addCol("online", "", 40); + table->addCol("ip", "IP", 130, QHeaderView::Stretch).alignC(); + table->addCol("screenSize", "", 100, QHeaderView::Stretch).alignC(); + table->addCol("alias", "", 130, QHeaderView::Stretch).alignC(); + table->addCol("brightness", "", 80).alignC(); + table->addCol("power", "", 80).alignC(); + table->addCol("password", "", 72); + table->addCol("info", "", 72); + table->addCol("screenshot", "", 72); + table->setDefs()->setHeaderAlignC(); + table->addFd(); + table->setSelectionMode(QAbstractItemView::NoSelection); + table->minRowHeight = 36; + table->setSortingEnabled(true); - vBox->addLayout(mHBox); - - m_headerItem = new QTreeWidgetItem(); - for(int i=1; isetTextAlignment(i, Qt::AlignCenter); - mDeviceTable->setHeaderItem(m_headerItem); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Check, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Check, 36); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Online, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Online, 48); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_ID, QHeaderView::Stretch); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_IP, QHeaderView::Stretch); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_ScreenSize, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_ScreenSize, 108); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Remark, QHeaderView::Stretch); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Brightness, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Brightness, 108); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Power, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Power, 84); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Password, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Password, 72); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Info, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Info, 72); - mDeviceTable->header()->setSectionResizeMode(DeviceTable_Screenshot, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Screenshot, 72); - - connect(mDeviceTable, &LoQTreeWidget::sigCheckStateChanged, this, [=] { + table->hideColumn("check"); + table->fdCheckAll->hide(); + table->sortItems("id", Qt::AscendingOrder); + connect(table, &LoQTreeWidget::selChanged, table, [=] { gSelCards.clear(); - int cnt = mDeviceTable->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) gSelCards.append(static_cast(mDeviceTable->topLevelItem(i))->mCard); + int cnt = table->topLevelItemCount(); + for(int i=0; iitem(i)->checkState("check") == Qt::Checked) gSelCards.append(static_cast(table->topLevelItem(i))->mCard); emit sigSelectedDeviceList(); }); - mDeviceTable->hideColumn(0); - mDeviceTable->fdIsSelAll->hide(); - mDeviceTable->sortItems(DeviceTable_ID, Qt::AscendingOrder); + mHBox->addWidget(mDeviceTable = table); connect(&mUdpTimer, &QTimer::timeout, this, &DevicePanel::sendGetInfo); connect(&mUdpSocket, &QUdpSocket::readyRead, this, [this] { @@ -218,45 +214,49 @@ QPushButton:hover {background-color: #08b;} item->mCard.id = packet->serialCode; item->mCard.ip = addr; } - connect(item->m_bnCardDetailInfo, &QPushButton::clicked, item, [=] { - QString msgpre; - msgpre.append(tr("Current Brightness")).append(": ").append(QString::number(item->mCard.bright)).append("%").append("\n"); - msgpre.append(tr("Brightness Level")).append(": ").append(QString::number(item->mCard.BrightnessLevel)).append("\n"); - msgpre.append(tr("Android OS Resolution")).append(": ").append(item->mCard.ScreenResolution).append("\n"); - msgpre.append(tr("Android Version")).append(": ").append(item->mCard.androidVersion).append("\n"); - msgpre.append(tr("FPGA Version")).append(": ").append(item->mCard.HardVersion).append("\n"); - msgpre.append(tr("Firmware Version")).append(": ").append(item->mCard.FirmwareVersion).append("\n"); - msgpre.append("IMEI: ").append(item->mCard.IMEI).append("\n"); - QMessageBox msgBox(QMessageBox::Information, item->mCard.id+" "+tr("Detail Info"), msgpre + tr("Player Version")+": "+tr("Getting")+" ..."); - QJsonObject json; - json.insert("_id", "CheckSoftVersions"); - json.insert("_type", "CheckSoftVersions"); - auto card = item->mCard; - auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(120000).post(json); - connect(&msgBox, &QMessageBox::finished, reply, [reply] { - abortSilence(reply); - }); - connect(reply, &QNetworkReply::finished, &msgBox, [=, &msgBox] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - msgBox.setText(msgpre + tr("Player Version")+": "+err); - return; - } - auto apps = json["apps"].toArray(); - foreach(QJsonValue value, apps) { - QJsonObject app = value.toObject(); - if(app["packageName"].toString().contains("xixunplayer")) { - msgBox.setText(msgpre + tr("Player Version")+": "+app["versionName"].toString()); + item->init(); + { + auto btn = new QPushButton; + btn->setCursor(QCursor(Qt::PointingHandCursor)); + btn->setIcon(QIcon(":/res/info.png")); + btn->setIconSize({26, 26}); + item->setCellWidget("info", btn); + connect(btn, &QPushButton::clicked, btn, [=] { + QString msgpre; + msgpre.append(tr("Current Brightness")).append(": ").append(QString::number(item->mCard.bright)).append("%").append("\n"); + msgpre.append(tr("Brightness Level")).append(": ").append(QString::number(item->mCard.BrightnessLevel)).append("\n"); + msgpre.append(tr("Android OS Resolution")).append(": ").append(item->mCard.ScreenResolution).append("\n"); + msgpre.append(tr("Android Version")).append(": ").append(item->mCard.androidVersion).append("\n"); + msgpre.append(tr("FPGA Version")).append(": ").append(item->mCard.HardVersion).append("\n"); + msgpre.append(tr("Firmware Version")).append(": ").append(item->mCard.FirmwareVersion).append("\n"); + msgpre.append("IMEI: ").append(item->mCard.IMEI).append("\n"); + QMessageBox msgBox(QMessageBox::Information, item->mCard.id+" "+tr("Detail Info"), msgpre + tr("Player Version")+": "+tr("Getting")+" ..."); + QJsonObject json; + json.insert("_id", "CheckSoftVersions"); + json.insert("_type", "CheckSoftVersions"); + auto card = item->mCard; + auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, &msgBox) [=, &msgBox] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + msgBox.setText(msgpre + tr("Player Version")+": "+err); return; } - } - msgBox.setText(msgpre + tr("Player Version")+":"); + auto apps = json["apps"].toArray(); + foreach(QJsonValue value, apps) { + QJsonObject app = value.toObject(); + if(app["packageName"].toString().contains("xixunplayer")) { + msgBox.setText(msgpre + tr("Player Version")+": "+app["versionName"].toString()); + return; + } + } + msgBox.setText(msgpre + tr("Player Version")+":"); + }); + msgBox.exec(); }); - msgBox.exec(); - }); - item->init(); - item->DeviceItemHttpPost(); + } + init(item); nDeviceNum->setText(QString::number(mDeviceTable->topLevelItemCount())); { QJsonObject json; @@ -291,7 +291,7 @@ QPushButton:hover {background-color: #08b;} hBox->addStretch(); auto bnSearch = new QPushButton(tr("Search")); - connect(bnSearch, &QPushButton::clicked, this, [this] { + connect(bnSearch, &QPushButton::clicked, fdIP, [this] { QString ipsStr = fdIP->toPlainText(); if(ipsStr.isEmpty()) { QMessageBox::warning(this, tr("Attention"), tr("Please input IP address!")); @@ -359,21 +359,20 @@ void DevicePanel::transUi() { bnSpecifyIP->setItemText(0,tr("Specify IP")); label_3->setText(tr("All")); - m_headerItem->setText(DeviceTable_Online, tr("Online")); - m_headerItem->setText(DeviceTable_ID, tr("Screen ID")); - m_headerItem->setText(DeviceTable_IP, tr("Screen IP")); - m_headerItem->setText(DeviceTable_ScreenSize, tr("Screen Size")); - m_headerItem->setText(DeviceTable_Remark, tr("Alias")); - m_headerItem->setText(DeviceTable_Screenshot, tr("readback pic")); - m_headerItem->setText(DeviceTable_Brightness, tr("Screen Brightness")); - m_headerItem->setText(DeviceTable_Power, tr("Power Status")); - m_headerItem->setText(DeviceTable_Password, tr("Security")); - m_headerItem->setText(DeviceTable_Info, tr("More Info")); + mDeviceTable->setHeaderText("online", tr("Online")); + mDeviceTable->setHeaderText("id", tr("Screen ID")); + mDeviceTable->setHeaderText("screenSize", tr("Screen Size")); + mDeviceTable->setHeaderText("alias", tr("Alias")); + mDeviceTable->setHeaderText("brightness", tr("Screen Brightness")); + mDeviceTable->setHeaderText("power", tr("Power Status")); + mDeviceTable->setHeaderText("password", tr("Security")); + mDeviceTable->setHeaderText("info", tr("More Info")); + mDeviceTable->setHeaderText("screenshot", tr("Screenshot")); auto cnt = mDeviceTable->topLevelItemCount(); for(int i=0; itopLevelItem(i); - item->setData(DeviceTable_Power, 0, item->mCard.isScreenOn ? tr("On") : tr("Off")); + auto item = (DeviceItem*) mDeviceTable->item(i); + item->setText("power", item->mCard.isScreenOn ? tr("On") : tr("Off")); } transCtrl(); } @@ -452,9 +451,9 @@ void DevicePanel::newCtrl() { line->setFrameShadow(QFrame::Sunken); vBox->addWidget(line); - hBox = new QHBoxLayout(); + hBox = new QHBoxLayout; - scrollArea = new QScrollArea(); + scrollArea = new QScrollArea; scrollArea->setWidgetResizable(true); hBox->addWidget(scrollArea); @@ -479,7 +478,7 @@ void DevicePanel::newCtrl() { fdInfo->hide(); btnClear->hide(); - connect(this, &DevicePanel::sigSelectedDeviceList, this, [this] { + connect(this, &DevicePanel::sigSelectedDeviceList, fdInfo, [this] { if(gSelCards.count() < 2) { if(gSelCards.count()==1) fdCardNumInfo->setText(tr("Current Screen")+": "+gSelCards[0].id); else fdCardNumInfo->setText(tr("Current Screen")+": "+tr("none")); @@ -497,3 +496,103 @@ void DevicePanel::newCtrl() { transCtrl(); } + +void DevicePanel::init(DeviceItem *item) { + QJsonObject json; + json.insert("_id", "GetBuildInformation"); + json.insert("_type", "GetBuildInformation"); + auto reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.BrightnessLevel = json["BrightnessLevel"].toInt(); + item->mCard.FirmwareVersion = json["FirmwareVersion"].toString(); + item->mCard.HardVersion = json["HardVersion"].toString(); + item->mCard.ScreenResolution = json["ScreenResolution"].toString(); + item->mCard.IMEI = json["IMEI"].toString(); + auto androidVersion = json["AndroidVersion"].toString(); + if(! androidVersion.isEmpty()) item->mCard.androidVersion = androidVersion; + }); + + if(item->mCard.mWidth==0 || item->mCard.mHeight==0) { + json = QJsonObject(); + json.insert("_id", "GetScreenSize"); + json.insert("_type", "GetScreenSize"); + reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.mWidth = json["width"].toInt(); + item->mCard.mHeight = json["height"].toInt(); + item->setText("screenSize", QString("%1 x %2").arg(item->mCard.mWidth).arg(item->mCard.mHeight)); + }); + } + + json = QJsonObject(); + json.insert("_id", "GetBrightness"); + json.insert("_type", "GetBrightness"); + reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.bright = json["brightnessPercentage"].toInt(-1); + if(item->mCard.bright==-1) item->mCard.bright = qRound(json["brightness"].toInt() * 100.0 / item->mCard.BrightnessLevel); + item->setText("brightness", QString::number(item->mCard.bright)+"%"); + }); + json = QJsonObject(); + json.insert("_id", "IsScreenOn"); + json.insert("_type", "IsScreenOn"); + reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.isScreenOn = json["on"].toBool(); + item->setForeground("power"**mDeviceTable, item->mCard.isScreenOn ? Qt::green : Qt::red); + item->setText("power", item->mCard.isScreenOn ? tr("On") : tr("Off")); + }); + json = QJsonObject(); + json.insert("_id", "GetCardAlias"); + json.insert("_type", "GetCardAlias"); + reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.alias = QString::fromUtf8(QByteArray::fromBase64(json["alias"].toString().toLatin1())); + item->setText("alias", item->mCard.alias); + }); + + json = QJsonObject(); + json.insert("_id", "HasControllerPassword"); + json.insert("_type", "HasControllerPassword"); + reply = NetReq("http://"+item->mCard.ip+":2016/settings").timeout(120000).post(json); + ConnReply(reply, item->fdOnline) [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + item->mCard.hasPassword = json["result"].toBool(); + if(item->mCard.hasPassword) {//加过密 + item->btnUnlock->show(); + item->btnUnlock->setIcon(QIcon(item->mCard.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); + } else item->btnUnlock->hide(); + }); +} + +ImgDlg::ImgDlg(const QByteArray &data, QWidget *parent) : QDialog(parent) { + setWindowFlag(Qt::WindowContextHelpButtonHint, 0); + setWindowTitle(tr("Screenshot")); + mImg.loadFromData(data); + auto www = mImg.width(); + auto hhh = mImg.height(); + if(www <= 1600 && hhh <= 900) resize(www, hhh); + else if(www > hhh) resize(900 * www / hhh, 900); + else resize(1600, 1600 * hhh / www); +} +void ImgDlg::paintEvent(QPaintEvent *) { + QPainter painter(this); + painter.drawImage(rect(), mImg); +} diff --git a/LedOK/devicepanel.h b/LedOK/devicepanel.h index 2c0acb8..152ebcd 100644 --- a/LedOK/devicepanel.h +++ b/LedOK/devicepanel.h @@ -3,7 +3,7 @@ #include "base/loqtreewidget.h" #include "globaldefine.h" -#include +#include "gutil/qgui.h" #include #include #include @@ -12,7 +12,6 @@ #include #include #include -#include class DevicePanel : public QWidget { Q_OBJECT @@ -22,6 +21,7 @@ public: void sendGetInfo(); void newCtrl(); + void init(DeviceItem *item); QLabel *fdCardNumInfo; LoQTreeWidget *mDeviceTable; @@ -34,8 +34,7 @@ public: QLabel *label_3, *nDeviceNum; QComboBox *bnSpecifyIP; QPushButton *btnRefresh; - QTreeWidgetItem *m_headerItem; - QHBoxLayout *mHBox{0}; + HBox *mHBox{0}; QTextEdit *fdInfo; QButtonGroup *mBtnGrp; @@ -51,6 +50,15 @@ signals: void sigSelectedDeviceList(); }; +class ImgDlg : public QDialog { + Q_OBJECT +public: + explicit ImgDlg(const QByteArray &, QWidget *parent = 0); + QImage mImg; +public: + void paintEvent(QPaintEvent *) override; +}; + struct UDPPacket { unsigned char SyncHead[3]; unsigned char ucCommType; diff --git a/LedOK/globaldefine.h b/LedOK/globaldefine.h index 4841758..bd970a8 100644 --- a/LedOK/globaldefine.h +++ b/LedOK/globaldefine.h @@ -93,7 +93,7 @@ QString checkReplyForJson(QNetworkReply *, QString errField); waitingDlg->show();\ auto card = gSelCards[0];\ auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(120000).post(json);\ - waitingDlg->connAbort(reply); + connect(waitingDlg, &WaitingDlg::rejected, reply, &QNetworkReply::deleteLater); #define Def_CtrlSetReqAfter \ QString err = checkReplyForJson(reply);\ diff --git a/LedOK/gutil/cpp.h b/LedOK/gutil/cpp.h index 2ec20ec..2b333c0 100644 --- a/LedOK/gutil/cpp.h +++ b/LedOK/gutil/cpp.h @@ -47,7 +47,7 @@ public: } SharedPtr &operator=(SharedPtr &&other) noexcept { auto aaa = ptr; - ptr = other._pri; + ptr = other.ptr; other.ptr = aaa; return *this; } diff --git a/LedOK/gutil/qgui.cpp b/LedOK/gutil/qgui.cpp index 7ab4f56..9d777e1 100644 --- a/LedOK/gutil/qgui.cpp +++ b/LedOK/gutil/qgui.cpp @@ -6,7 +6,7 @@ const Qt::Alignment AlignRight = Qt::AlignRight | Qt::AlignVCenter; ColItem TreeWidget::addCol(const QString& field, const QString& text, int width, QHeaderView::ResizeMode resizeMode) { - int i = fdmap.size(); + int i = (int) fdmap.size(); auto item = headerItem(); item->setText(i, text); item->setData(i, FieldRole, field); @@ -106,8 +106,40 @@ bool TreeWidget::adjSections(int index, int size) { class TreeItemMarginStyle : public QProxyStyle { public: - using QProxyStyle::QProxyStyle; - TreeItemMarginStyle(QWidget *wgt) : QProxyStyle(wgt->style()), _wgt(wgt) {} + TreeItemMarginStyle(TreeWidget *wgt) : QProxyStyle(wgt->style()), _wgt(wgt) {} +#if(QT_VERSION_MAJOR > 5) + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override { //draw big indicator and cell focus mask + if(option && option->type==QStyleOption::SO_ViewItem && ((QStyleOptionViewItem*) option)->features & QStyleOptionViewItem::HasCheckIndicator && widget==_wgt) { //PE_PanelItemViewItem PE_IndicatorItemViewItemCheck + auto opt = (QStyleOptionViewItem*) option; + auto add = _wgt->headerItem()->data(opt->index.column(), MarginRole).toInt(); + if(add) { + if(element==PE_IndicatorItemViewItemCheck) opt->rect.translate(add, 0); //move big indicator + else if((opt->features & QStyleOptionViewItem::HasDisplay)==0) opt->rect.setLeft(opt->rect.right() + 1); //remove cell focus mask + else { + opt->rect.setLeft(opt->rect.x() + (add << 1)); //move cell focus mask + if(opt->rect.width() < 0) opt->rect.setWidth(0); + } + } + } + QProxyStyle::drawPrimitive(element, option, painter, widget); + } + void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override { //draw text, small indicator and focus mask around text + if(option && widget==_wgt) { + auto opt = (QStyleOptionViewItem*) option; + opt->state &= ~State_HasFocus; //remove focus mask around text + if(element==CE_ItemViewItem && option->type==QStyleOption::SO_ViewItem) { + auto add = _wgt->headerItem()->data(opt->index.column(), MarginRole).toInt(); + if(add) { //move text and small indicator + if(opt->displayAlignment & Qt::AlignRight) opt->rect.setRight(opt->rect.right() - add); + if(opt->features & QStyleOptionViewItem::HasCheckIndicator) opt->rect.setLeft(opt->rect.x() + (add<<1)); + else if((opt->displayAlignment & (Qt::AlignHCenter | Qt::AlignRight))==0) opt->rect.setLeft(opt->rect.x() + add); + if(opt->rect.width() < 0) opt->rect.setWidth(0); + } + } + } + QProxyStyle::drawControl(element, option, painter, widget); + } +#else QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override { auto res = QProxyStyle::subElementRect(element, option, widget); auto width = res.width(); @@ -125,9 +157,11 @@ public: } } } else if(((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator) { - auto add = ((TreeWidget*)widget)->headerItem()->data(((QStyleOptionViewItem*)option)->index.column(), MarginRole).toInt(); + auto index = ((QStyleOptionViewItem*)option)->index; + auto add = ((TreeWidget*)widget)->headerItem()->data(index.column(), MarginRole).toInt(); if(add) { - add += add>>1; + if(width < (add+3)<<1) add = width; + else add += add>>1; res.setLeft(res.x() + add); if(width < add) res.setWidth(0); } @@ -140,7 +174,8 @@ public: if(metric==PM_FocusFrameHMargin && option && option->type==QStyleOption::SO_ViewItem && ((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator && widget==_wgt) res += ((TreeWidget*)widget)->headerItem()->data(((QStyleOptionViewItem*)option)->index.column(), MarginRole).toInt(); return res; } - QWidget *_wgt = 0; +#endif + TreeWidget *_wgt = 0; }; ColItem &ColItem::margin(int margin) { diff --git a/LedOK/gutil/qgui.h b/LedOK/gutil/qgui.h index 5195209..62e8032 100644 --- a/LedOK/gutil/qgui.h +++ b/LedOK/gutil/qgui.h @@ -293,11 +293,11 @@ protected: }; inline int operator*(const QString& key, QTreeView &table) { - if((size_t)&table==0) return 0; + if((size_t)&table==0) return -1; return ((TreeWidget&)table).fdmap.at(key); } inline int operator*(const char *key, QTreeView &table) { - if((size_t)&table==0) return 0; + if((size_t)&table==0) return -1; return ((TreeWidget&)table).fdmap.at(key); } diff --git a/LedOK/gutil/qjson.cpp b/LedOK/gutil/qjson.cpp index 0156b4e..ed6e8c4 100644 --- a/LedOK/gutil/qjson.cpp +++ b/LedOK/gutil/qjson.cpp @@ -8,11 +8,6 @@ QDebug operator<<(QDebug debug, const JValue &val) { return debug; } -inline QChar readOne(QTextStream &in) { - QChar ch; - in >> ch; - return ch; -} JValue JParser::readValue() { if(ch=='{') { JObj obj; @@ -22,14 +17,14 @@ JValue JParser::readValue() { if(ch=='}') return obj; QString key; if(ch == '"') key = readStr(); - else if(ch!='n' || in.read(3)!="ull") throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting double-quote to start field name or null"; + else if(ch!='n' || readOne()!='u' || readOne()!='l' || readOne()!='l') throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting double-quote to start field name or null"; skipSpace(); - if(ch != ':') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting a colon to separate field name and value"; + if(ch != ':') throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting a colon to separate field name and value"; skipSpace(); obj.insert(key, readValue()); skipSpace(); //ch有两种可能 if(ch=='}') return obj; - if(ch!=',') throw QString("Unexpected char ")+ch+"' (code "+ch+"): was expecting } to end Object or comma to separate Object entries"; + if(ch!=',') throw QString("Unexpected char ")+(char)ch+"' (code "+QString::number(ch)+"): was expecting } to end Object or comma to separate Object entries"; } } if(ch=='[') { @@ -41,15 +36,15 @@ JValue JParser::readValue() { list->push_back(readValue()); skipSpace(); //ch有两种可能 if(ch==']') return list; - if(ch!=',') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting ] to end Array or comma to separate Array entries"; + if(ch!=',') throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting ] to end Array or comma to separate Array entries"; } } if(ch=='"') return readStr(); if((ch>='0' && ch<='9') || ch=='-') { - QString buf; + QByteArray buf; buf += ch; bool isInt = true; - while(0 != (ch = readOne(in))) { + while(readOne()) { if((ch>'*' && ch<':' && ch!=',' && ch!='/') || ch=='e' || ch=='E') { buf.append(ch); if(isInt && ch=='.') isInt = false; @@ -70,26 +65,34 @@ JValue JParser::readValue() { } } if(ch=='n') { - if(in.read(3)=="ull") return JValue(); - else throw "Unexpected char n: expected null"; + if(readOne()=='u' && readOne()=='l' && readOne()=='l') return JValue(); + else throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting null"; } if(ch=='t') { - if(in.read(3)=="rue") return true; - else throw "Unexpected char t: expected true"; + if(readOne()=='r' && readOne()=='u' && readOne()=='e') return true; + else throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting true"; } if(ch=='f') { - if(in.read(4)=="alse") return false; - else throw "Unexpected char f: expected false"; + if(readOne()=='a' && readOne()=='l' && readOne()=='s' && readOne()=='e') return false; + else throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting false"; } - throw QString("Unexpected char ")+ch+" (code "+ch+"): expected {}, [], \"string\", number, null, true or false"; + throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting {}, [], \"string\", number, null, true or false"; +} +inline int toHex(unsigned char ch) { + if(ch<'0') return -1; + if(ch<='9') return ch-'0'; + if(ch<'A') return -1; + if(ch<='F') return ch-55; + if(ch<'a') return -1; + if(ch<='f') return ch-87; + return -1; } QString JParser::readStr() { - QString buf; - while((ch = readOne(in)) != '"') { + QByteArray buf; + while(readOne() != '"') { if(ch==0) throw "Unexpected end-of-input: was expecting closing quote for string"; if(ch=='\\') { - in>>ch; - if(ch==0) throw "Unexpected end-of-input in char escape sequence"; + if(readOne()==0) throw "Unexpected end-of-input in char escape sequence"; if(ch=='"' || ch=='\\' || ch=='/') buf.append(ch); else if(ch=='n') buf.append('\n'); else if(ch=='r') buf.append('\r'); @@ -97,24 +100,50 @@ QString JParser::readStr() { else if(ch=='f') buf.append('\f'); else if(ch=='b') buf.append('\b'); else if(ch=='u') { - auto hex = in.read(4); - if(hex.size()<4) throw "Unexpected end-of-input in char escape sequence"; - bool ok; - buf.append(hex.toUShort(&ok, 16)); - if(! ok) throw "Illegal hex-digits in char escape sequence: \\u"+hex; - } else throw QString("Unrecognized char-escape ")+ch+" (code "+ch+")"; + uint hex = 0; + for(int i=3; i>=0; i--) { + if(readOne()==0) throw "Unexpected end-of-input in char escape sequence"; + auto h = toHex(ch); + if(h==-1) throw "Illegal hex-digits in char escape sequence: \\u"+(hex==0?"":QString::number(hex, 16)+(char)ch); + hex |= h<<(i<<2); + } + buf.append(QString(QChar(hex)).toUtf8()); + } else throw QString("Unrecognized char-escape ")+(char)ch+" (code "+QString::number(ch)+") after '\\'"; } else buf.append(ch); } - return buf; + return QString::fromUtf8(buf); } void JParser::skipSpace() { - if(bk.unicode()) { - bk = QChar::Null; - if(! ch.isSpace()) return; + if(bk) { + bk = 0; + if(ch>=33) return; + } + do { + in >> ch; + if(ch==0) throw "Unexpected end-of-input"; + } while(ch < 33); // || ch==65279 + if(ch=='/') { + in >> ch; + if(ch=='/') { //skipComment + do { + in >> ch; + if(ch==0) throw "Unexpected end-of-input"; + } while(ch!='\n' && ch!='\r'); + skipSpace(); + return; + } + if(ch=='*') { //skipMultiComment + int last; + do { + last = ch; + in >> ch; + if(ch==0) throw "Unexpected end-of-input"; + } while(ch!='/' || last!='*'); + skipSpace(); + return; + } + throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+")"; } - in.skipWhiteSpace(); - in >> ch; - if(ch==0) throw "Unexpected end-of-input"; } void JOut::write(const JValue &value) { diff --git a/LedOK/gutil/qjson.h b/LedOK/gutil/qjson.h index 0f09435..be89662 100644 --- a/LedOK/gutil/qjson.h +++ b/LedOK/gutil/qjson.h @@ -3,12 +3,14 @@ #include "cpp.h" #include "QtCore/qhashfunctions.h" +#include #include - class JValue; using JObj = LinkedMap; using JArray = Vector; +QDebug operator<<(QDebug debug, const JValue &val); + class JValue { public: long long data = 0; @@ -127,6 +129,11 @@ public: JArray::iterator end() const noexcept { return type==Array ? ((const JArray*) &data)->end() : JArray::iterator(); } + bool empty() const noexcept { + if(type==Array) return ((const JArray*) &data)->empty(); + else if(type==Obj) return ((const JObj*) &data)->empty(); + return 0; + } size_t size() const noexcept { if(type==Array) return ((const JArray*) &data)->size(); else if(type==Obj) return ((const JObj*) &data)->size(); @@ -157,31 +164,30 @@ private: JValue(const void *) = delete; // avoid implicit conversions from char * to bool }; -QDebug operator<<(QDebug debug, const JValue &val); - class JParser { public: - JParser(QTextStream &in) : in(in) { -#if(QT_VERSION_MAJOR < 6) - in.setCodec("UTF-8"); -#endif - } - - inline JValue read() { - skipSpace(); + JParser(QDataStream &in) : in(in) {} + JValue read() { + in >> ch; + if(ch==0) throw "Unexpected end-of-input"; + if(ch==0xEF && (readOne()!=0xBB || readOne()!=0xBF)) throw QString("Unexpected char ")+(char)ch+" (code "+QString::number(ch)+"): was expecting an UTF-8 BOM"; + if(ch<33) skipSpace(); return readValue(); } protected: JValue readValue(); QString readStr(); void skipSpace(); - - QTextStream ∈ - QChar ch{0}, bk{0}; + unsigned char readOne() { + in >> ch; + return ch; + } + QDataStream ∈ + unsigned char ch{0}, bk{0}; }; inline JValue JFrom(const QByteArray &json, QString *err = 0) { - QTextStream in(json); + QDataStream in(json); try { return JParser(in).read(); } catch (QString anerr) { @@ -194,7 +200,7 @@ inline JValue JFrom(const QByteArray &json, QString *err = 0) { return JValue(); } inline JValue JFrom(QIODevice *device, QString *err = 0) { - QTextStream in(device); + QDataStream in(device); try { return JParser(in).read(); } catch (QString anerr) { diff --git a/LedOK/gutil/qnetwork.cpp b/LedOK/gutil/qnetwork.cpp index 279d728..fc2b5c0 100644 --- a/LedOK/gutil/qnetwork.cpp +++ b/LedOK/gutil/qnetwork.cpp @@ -22,6 +22,22 @@ QString errStr(QNetworkReply *reply) { if(status != 200) return QString::number(status)+" "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); return ""; } +QString errStrWithData(QNetworkReply *reply, JValue *outJson) { + auto err = errStr(reply); + if(! err.isEmpty()) { + auto data = reply->readAll(); + if(! data.isEmpty()) err += "\n"+data; + return err; + } + if(outJson) { + auto data = reply->readAll(); + QString error; + *outJson = JFrom(data, &error); + if(! error.isEmpty()) return "JSON "+QCoreApplication::translate("Net","Error")+": "+error+"\n"+data; + } + return ""; +} + QString errStrWithData(QNetworkReply *reply, QJsonDocument *outJson) { auto err = errStr(reply); if(! err.isEmpty()) { diff --git a/LedOK/gutil/qnetwork.h b/LedOK/gutil/qnetwork.h index 6505721..b47264b 100644 --- a/LedOK/gutil/qnetwork.h +++ b/LedOK/gutil/qnetwork.h @@ -93,20 +93,23 @@ public: }; QString errStr(QNetworkReply *); -QString errStrWithData(QNetworkReply *, QJsonDocument * = 0); +QString errStrWithData(QNetworkReply *, JValue * = 0); +QString errStrWithData(QNetworkReply *, QJsonDocument *); -inline int waitFinished(QNetworkReply *reply, bool excludeUser = false) { +inline int waitFinished(QNetworkReply *reply, QObject *context, bool excludeUser = false) { if(reply->isFinished()) return 0; QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + if(context) QObject::connect(context, &QObject::destroyed, &loop, [&] { + reply->deleteLater(); + loop.exit(1); + }); return excludeUser ? loop.exec(QEventLoop::ExcludeUserInputEvents) : loop.exec(); } -inline void abortSilence(QNetworkReply *reply) { - reply->blockSignals(true); - reply->abort(); - reply->blockSignals(false); - reply->deleteLater(); -} + +#define ConnReply(reply, context)\ + QObject::connect(context, &QObject::destroyed, reply, &QNetworkReply::deleteLater);\ + QObject::connect(reply, &QNetworkReply::finished, context, const char* socketErrKey(int value); @@ -154,4 +157,55 @@ protected: bool connAndExec(int msecs, QEventLoop *loop); }; +struct NetReplyData { + QNetworkReply* reply; + size_t cnt = 1; + bool isDeleted = false; +}; +class NetReply { +public: + NetReply(QNetworkReply *reply) : ptr{new NetReplyData{reply}} {} + ~NetReply() { + if(ptr->cnt > 1) ptr->cnt--; + else { + if(! ptr->isDeleted) ptr->reply->deleteLater(); + delete ptr; + } + } + + NetReply(const NetReply &other) : ptr{other.ptr} { + ptr->cnt++; + } + NetReply &operator=(const NetReply &other) { + NetReply ooo(other); + auto aaa = ptr; + ptr = ooo.ptr; + ooo.ptr = aaa; + return *this; + } + NetReply(NetReply &&other) noexcept : ptr(other.ptr) { + other.ptr = 0; + } + NetReply &operator=(NetReply &&other) noexcept { + auto aaa = ptr; + ptr = other.ptr; + other.ptr = aaa; + return *this; + } + + void deleteLater() { + if(ptr->isDeleted) return; + ptr->reply->deleteLater(); + ptr->isDeleted = true; + } + + QNetworkReply *operator*() const { + return ptr->reply; + } + QNetworkReply *operator->() const { + return ptr->reply; + } + NetReplyData *ptr; +}; + #endif // QNETWORK_H diff --git a/LedOK/gutil/qwaitingdlg.h b/LedOK/gutil/qwaitingdlg.h index 477c203..efc5651 100644 --- a/LedOK/gutil/qwaitingdlg.h +++ b/LedOK/gutil/qwaitingdlg.h @@ -25,14 +25,6 @@ class WaitingDlg : public QDialog { public: explicit WaitingDlg(QWidget *parent = nullptr, QString text = 0, QString sucText = 0); - inline void connAbort(QNetworkReply *reply) { - connect(this, &WaitingDlg::rejected, reply, [reply] { - reply->blockSignals(true); - reply->abort(); - reply->blockSignals(false); - reply->deleteLater(); - }); - } QLabel *fdText; QString sucText; WaitingIndicator *mIndicator; diff --git a/LedOK/main.cpp b/LedOK/main.cpp index f6b70c5..56a0cc3 100644 --- a/LedOK/main.cpp +++ b/LedOK/main.cpp @@ -4,6 +4,9 @@ #include #include #include +#if(QT_VERSION_MAJOR > 5) +#include +#endif #ifdef _MSC_VER //MSVC编译器 #include @@ -27,11 +30,14 @@ LONG WINAPI handleException(_EXCEPTION_POINTERS *excep) { } #endif -QString css; int main(int argc, char *argv[]) { +#if(QT_VERSION_MAJOR > 5) + QImageReader::setAllocationLimit(0); +#else QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif QApplication::setOrganizationName("Shanghai Xixun Electronic Technology Co., Ltd."); QApplication::setOrganizationDomain("www.ledok.cn"); QApplication::setApplicationName("LedOK Express"); @@ -44,7 +50,7 @@ int main(int argc, char *argv[]) { QFile file(":/css.css"); if(file.exists() && file.open(QFile::ReadOnly)) { - a.setStyleSheet(css = file.readAll()); + a.setStyleSheet(file.readAll()); file.close(); } QFont font; diff --git a/LedOK/mainwindow.cpp b/LedOK/mainwindow.cpp index 1641f80..560ba7c 100644 --- a/LedOK/mainwindow.cpp +++ b/LedOK/mainwindow.cpp @@ -207,7 +207,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { fdAntiTip->setWordWrap(true); hBox->addWidget(fdAntiTip, 1); - auto fdWidthSplit = new QCheckBox(tr("Width Split")); + auto fdWidthSplit = new QCheckBox(tr("Ultra-Long Screen Split")); fdWidthSplit->setChecked(gWidthSplit); vBox->addWidget(fdWidthSplit); @@ -278,7 +278,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { vBox->addWidget(fdUpdLog); auto reply = NetReq(updates["changelog_zh_CN"].toString()).timeout(60000).get(); - connect(reply, &QNetworkReply::finished, this, [=] { + ConnReply(reply, fdUpdLog) [=] { auto err = errStr(reply); if(! err.isEmpty()) { qCritical()<<"Check Updates"<readAll()); - }); - connect(reply, &QNetworkReply::finished, &msgBox, [&, reply] { + auto pfile = &qFile; + ConnReply(reply, &msgBox) [=, &msgBox] { auto err = errStr(reply); if(! err.isEmpty()) { msgBox.setIcon(QMessageBox::Critical); @@ -330,6 +323,11 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { } msgBox.accept(); }); + connect(reply, &QNetworkReply::downloadProgress, &msgBox, [=, &msgBox](qint64 bytesReceived, qint64 bytesTotal) { + if(bytesTotal==0) return; + msgBox.setText(tr("Downloading updates")+": "+QString::number(bytesReceived*100/bytesTotal)+"% "); + pfile->write(reply->readAll()); + }); auto res = msgBox.exec(); qFile.close(); if(res != QDialog::Accepted) return; @@ -339,7 +337,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { menu_setting->addAction(act_update); auto reply = NetReq(UpdVerUrl).timeout(60000).get(); - connect(reply, &QNetworkReply::finished, this, [=] { + ConnReply(reply, this) [=] { auto err = errStr(reply); if(! err.isEmpty()) { qCritical()<<"Check Updates"< #include #include #include -#include #include #include #include @@ -97,7 +95,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare action = new QAction(QIcon(":/res/program/Setting.png"), tr("Setting")); connect(action, &QAction::triggered, this, [this] { QString widthsStr; - foreach(auto width, mProgItem->mSplitWidths) { + for(auto &width : mProgItem->mSplitWidths) { if(! widthsStr.isEmpty()) widthsStr.append(" "); widthsStr.append(QString::number(width)); } @@ -108,28 +106,29 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare mProgItem->mRemark = dlg.fdRemark->toPlainText(); mProgItem->mSplitWidths.clear(); mProgItem->mMaxWidth = 0; - auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts); - int ttl = 0; - foreach(auto splitWidth, splitWidths) { - int val = splitWidth.toInt(); - if(val==0) continue; - if(mProgItem->mMaxWidth < val) mProgItem->mMaxWidth = val; - ttl += val; - mProgItem->mSplitWidths.append(val); - } - if(mProgItem->mMaxWidth) { - while(ttl < mProgItem->mWidth) { - mProgItem->mSplitWidths.append(mProgItem->mMaxWidth); - ttl += mProgItem->mMaxWidth; + if(dlg.fdIsUltraLong->isChecked()) { + auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts); + int ttl = 0; + for(auto &splitWidth : splitWidths) { + int val = splitWidth.toInt(); + if(val==0) continue; + if(mProgItem->mMaxWidth < val) mProgItem->mMaxWidth = val; + mProgItem->mSplitWidths.append(val); + ttl += val; + if(ttl>=mProgItem->mWidth) break; + } + if(mProgItem->mMaxWidth) { + while(ttl < mProgItem->mWidth) { + mProgItem->mSplitWidths.append(mProgItem->mMaxWidth); + ttl += mProgItem->mMaxWidth; + } + if(ttl > mProgItem->mWidth) mProgItem->mSplitWidths.last() -= ttl - mProgItem->mWidth; } - if(ttl > mProgItem->mWidth) mProgItem->mSplitWidths.last() -= ttl - mProgItem->mWidth; } - mProgItem->m_last = QDateTime::currentDateTime(); mProgItem->m_fsize = dirFileSize(mProgItem->mProgDir); mProgItem->onSetProgram(); - int cnt = listPage->count(); - for(int i=0; icount(); i++) { auto page = (PageListItem*) listPage->item(i); page->mScene->setSceneRect(0, 0, mProgItem->mWidth, mProgItem->mHeight); page->mGraView->resetTransform(); @@ -137,8 +136,8 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare page->mGraView->scale(scale, scale); auto items = page->mScene->items(); - foreach(auto item, items) { - auto element = static_cast(item); + for(auto item : items) { + auto element = (EBase*) item; if(element->mMultiWin == 0) element->fitProgSize(); } page->mScene->update(); @@ -184,20 +183,35 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare action->setData(EBase::Timer); toolBar->addAction(action); } - action = new QAction(QIcon(":/res/program/demo-video.png"), tr("Demo Video")); + action = new QAction(QIcon(":/res/program/demo-video.png"), tr("Demos")); connect(action, &QAction::triggered, this, [this] { + auto file = QFileDialog::getOpenFileName(this, tr("Open Demo"), "Demos"); + if(file.isEmpty()) return; auto scene = mPageEditor->graphicsView->scene(); if(scene==0) return; - auto eVideo = EVideo::create(mProgItem->mWidth>1280 && mProgItem->mHeight>720 ? "files/demo-video.mp4" : "files/demo-video-720.mp4", mPageItem); - if(eVideo==0) return; - auto rect = Tools::centerRect(eVideo->mCoverImg.width(), eVideo->mCoverImg.height(), mProgItem->mWidth, mProgItem->mHeight); - eVideo->setPos(rect.topLeft()); - eVideo->setSize(rect.width(), rect.height()); - eVideo->setZValue(mPageEditor->sortedEles().count()); - scene->addItem(eVideo); - auto sels = scene->selectedItems(); - if(sels.count() == 1) sels.at(0)->setSelected(false); - eVideo->setSelected(true); + if(file.endsWith("png", Qt::CaseInsensitive)) { + auto ePhoto = EPhoto::create(file, mPageItem); + if(ePhoto==0) return; + auto rect = Tools::centerRect(ePhoto->img.width(), ePhoto->img.height(), mProgItem->mWidth, mProgItem->mHeight); + ePhoto->setPos(rect.topLeft()); + ePhoto->setSize(rect.width(), rect.height()); + ePhoto->setZValue(mPageEditor->sortedEles().count()); + scene->addItem(ePhoto); + auto sels = scene->selectedItems(); + if(sels.count() == 1) sels.at(0)->setSelected(false); + ePhoto->setSelected(true); + } else { + auto eVideo = EVideo::create(file, mPageItem); + if(eVideo==0) return; + auto rect = Tools::centerRect(eVideo->mCoverImg.width(), eVideo->mCoverImg.height(), mProgItem->mWidth, mProgItem->mHeight); + eVideo->setPos(rect.topLeft()); + eVideo->setSize(rect.width(), rect.height()); + eVideo->setZValue(mPageEditor->sortedEles().count()); + scene->addItem(eVideo); + auto sels = scene->selectedItems(); + if(sels.count() == 1) sels.at(0)->setSelected(false); + eVideo->setSelected(true); + } }); toolBar->addAction(action); @@ -218,11 +232,11 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare waitingDlg->exec(); QFile file(mProgItem->mProgDir+"_tmp/program"); if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return; - QString value = file.readAll(); + auto value = file.readAll(); file.close(); - QJsonParseError jsErr; - auto prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object(); - if(jsErr.error) return; + QString jsErr; + auto prog = JFrom(value, &jsErr); + if(! jsErr.isEmpty()) return; int www = mProgItem->mWidth, hhh = mProgItem->mHeight; if(mProgItem->mMaxWidth) { www = mProgItem->mMaxWidth; @@ -539,11 +553,7 @@ bool ProgEditorWin::isProgChanged() { auto page = (PageListItem*) listPage->item(i); if(page->mAttrWgt==0) continue; page->updateJson(); - if(page->mAttr != mPageJsons[i]) { - qDebug()<mAttr; - qDebug()<mAttr != mPageJsons[i]) return true; } return false; } @@ -643,13 +653,13 @@ ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remark #endif setWindowTitle(tr("Solution Information")); auto vBox = new VBox(this); + vBox->setContentsMargins(6,0,6,6); auto hBox = new HBox(vBox); auto label = new QLabel(tr("Solution Name")); label->setMinimumWidth(90); label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); hBox->addWidget(label); - hBox->addSpacing(6); fdName = new QLineEdit; if(name.isEmpty()) name = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"); @@ -689,21 +699,31 @@ ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remark label->setMinimumWidth(90); label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); hBox->addWidget(label); - hBox->addSpacing(6); fdRemark = new QTextEdit(remarks); fdRemark->setFixedSize(300, 80); hBox->addWidget(fdRemark); - hBox = new HBox(vBox); + vBox->addSpacing(6); - auto lbSplitWidth = new QLabel(tr("每段打折宽度 (用空格分隔)")); + hBox = new HBox(vBox); + hBox->addSpacing(72); + + fdIsUltraLong = new QCheckBox(tr("Ultra-Long Screen Split")); + if(! widths.isEmpty()) fdIsUltraLong->setChecked(true); + hBox->addWidget(fdIsUltraLong); + + hBox = new HBox(vBox); + auto lbSplitWidth = new QLabel(tr("Part Width")); + lbSplitWidth->setMinimumWidth(90); + lbSplitWidth->setAlignment(Qt::AlignRight | Qt::AlignVCenter); hBox->addWidget(lbSplitWidth); - fdSplitWidths = new QLineEdit(widths); - fdSplitWidths->setPlaceholderText("256 256 256 ..."); + fdSplitWidths = new QLineEdit(widths.isEmpty() ? "1920" : widths); + fdSplitWidths->setPlaceholderText("1920"); hBox->addWidget(fdSplitWidths); if(! gWidthSplit) { + fdIsUltraLong->setVisible(false); lbSplitWidth->setVisible(false); fdSplitWidths->setVisible(false); } diff --git a/LedOK/program/progeditorwin.h b/LedOK/program/progeditorwin.h index e9b7fc4..71e43ed 100644 --- a/LedOK/program/progeditorwin.h +++ b/LedOK/program/progeditorwin.h @@ -1,6 +1,7 @@ #ifndef PROGEDITORWIN_H #define PROGEDITORWIN_H #include "program/pageeditor.h" +#include #include #include #include @@ -40,6 +41,7 @@ public: QSpinBox *fdWidth; QSpinBox *fdHeight; QTextEdit *fdRemark; + QCheckBox *fdIsUltraLong; QLineEdit *fdSplitWidths; }; diff --git a/LedOK/program/sendprogramdialog.cpp b/LedOK/program/sendprogramdialog.cpp index 1b69e54..130d44e 100644 --- a/LedOK/program/sendprogramdialog.cpp +++ b/LedOK/program/sendprogramdialog.cpp @@ -121,11 +121,10 @@ SendProgramDialog::SendProgramDialog(QString progName, QWidget *parent) : QDialo json.insert("_id", "VerifyPassword"); json.insert("_type", "VerifyPassword"); json.insert("pwd", pwd); - auto waitingDlg = new WaitingDlg(this, tr("VerifyPassword")+" ..."); + auto waitingDlg = new WaitingDlg(item->btnUnlock, tr("VerifyPassword")+" ..."); waitingDlg->show(); auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(30000).post(json); - waitingDlg->connAbort(reply); - connect(reply, &QNetworkReply::finished, item->btnUnlock, [=] { + ConnReply(reply, waitingDlg) [=] { QJsonDocument json; auto err = checkReplyForJson(reply, &json); if(! err.isEmpty()) { diff --git a/LedOK/program/sendprogthread.cpp b/LedOK/program/sendprogthread.cpp index 083d869..50fab34 100644 --- a/LedOK/program/sendprogthread.cpp +++ b/LedOK/program/sendprogthread.cpp @@ -44,6 +44,7 @@ void SendProgThread::run() { req.insert("zVer", "xixun1"); auto requ = QJsonDocument(req).toJson(QJsonDocument::Compact); auto resNum = tcp.write(requ); + tcp.flush(); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'consult'. size"+QString::number(requ.size())); tcp.close(); @@ -89,8 +90,8 @@ void SendProgThread::run() { if(res["_type"].toString()=="consult") { fileInfos.clear(); fileInfos.append(QFileInfo(prog_dir+"/program")); - QJsonArray ids = res["idList"].toArray(); - foreach(auto id, ids) fileInfos.append(QFileInfo(prog_dir+"/"+id.toString())); + auto ids = res["idList"].toArray(); + for(auto id : ids) fileInfos.append(QFileInfo(prog_dir+"/"+id.toString())); } } if(stoped) { @@ -121,7 +122,8 @@ void SendProgThread::run() { } //4.发送协商列表应答里的文件 long long sentBytes = 0; - foreach(auto info, fileInfos) if(info.isFile()) { + char buf[8192]; + for(auto &info : fileInfos) if(info.isFile()) { auto baseName = info.baseName(); auto remain = info.size(); req = QJsonObject(); @@ -143,8 +145,8 @@ void SendProgThread::run() { return; } while(remain > 0) { - auto readed = file->read(qMin(4*4096LL, remain)); - if(readed.isEmpty()) { + resNum = file->read(buf, qMin(8192LL, remain)); + if(resNum <= 0) { emit emErr(tr("Read file failed")+" "+file->errorString()); tcp.close(); file->close(); @@ -155,15 +157,15 @@ void SendProgThread::run() { file->close(); return; }; - resNum = tcp.write(readed); - if(resNum == -1) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write file: "+file->fileName()); + if(! tcp.waitForBytesWritten(60000)) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForWritten file: "+file->fileName()); tcp.close(); file->close(); return; } - if(! tcp.waitForBytesWritten(60000)) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForWritten file: "+file->fileName()); + resNum = tcp.write(buf, resNum); + if(resNum <= 0) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write file: "+file->fileName()); tcp.close(); file->close(); return; diff --git a/LedOK/tools.h b/LedOK/tools.h index 26f382f..9cff685 100644 --- a/LedOK/tools.h +++ b/LedOK/tools.h @@ -16,7 +16,6 @@ const QString str0_9[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; extern QTextEdit *gFdResInfo; extern ProgItem *gProgItem; -extern QString css; class Tools : public QObject { Q_OBJECT diff --git a/LedOK/ts/app_en.ts b/LedOK/ts/app_en.ts index 09b4ac3..7b21d67 100644 --- a/LedOK/ts/app_en.ts +++ b/LedOK/ts/app_en.ts @@ -39,8 +39,8 @@ - Please enter a password with more than 6 characters - Please enter a password with more than 6 characters + Please enter a password with more than 3 characters + @@ -56,156 +56,156 @@ CtrlAdvancedPanel - + Advanced Advanced - + Screen Width(pixel) Screen Width(pixel) - + Width Width - - + + Height Height - - - - + + + + + + - - - - - - - + + + + + + - + - - - + + Set Set - + Alias Alias - + Web Server Address: Web Server Address: - + MCU Uploading - + Setting - + Traffic screen settings - + Setting protocol ... - + Set protocol - + Getting protocol ... - + Get protocol - - + + Port - + Realtimer Server Address: Realtimer Server Address: - + Firmware Management - + update or uninstall - + Clear Clear - + Check Apk Check Apk - + Uninstall Uninstall - + Running check Running check - + Restart Restart - + Check Log Check Log - + Start LedSet4 Start LedSet4.0 (Apk Display2.0 and higher) - + Open ADB Open ADB debugging function - + Post Custom JSON Post Custom JSON @@ -215,7 +215,7 @@ - + Clear Program Clear Program @@ -225,66 +225,66 @@ - + Config Config - + Refresh Refresh - + Restore to default Restore to default - + Taxi top screen configuration Taxi top screen configuration - - + + Service:High Out of service:Low Service:High Out of service:Low - - + + Service:Low Out of service:High Service:Low Out of service:High - + Binding *.ic account indentity voucher Binding *.ic account indentity voucher - + Rotate Rotate - + Min brightness Min brightness - - - + + + Readback Readback - + Send Send - + Max brightness Max brightness @@ -296,20 +296,20 @@ - - - - + + + + Success Success - + Compant ID: Company ID - + Compant ID Company ID @@ -382,28 +382,28 @@ - - + + OpenAdb Open ADB debugging function - + indentity voucher (*.ic) indentity voucher (*.ic) - - - + + + + - InvokeTaxiAppFunction Binding certificate - - + + AliIotSetting @@ -434,16 +434,16 @@ - - + + Timeout Timeout - - + + Failed @@ -455,53 +455,53 @@ - - - - - - - - - - - + + + + + + + + + + + Error Error - + Setting Timing Reboot - + Set Timing Reboot - + Getting Timing Reboot - + Get Timing Reboot - + totalResolution FPGA total resoltuion - + strCurDisplayResolution Cur display resolution - - + + File not exist @@ -513,7 +513,7 @@ - + Get Player State @@ -534,368 +534,368 @@ - - + + Cannot Open File - + Uploading - + Update Update - - + + Set Display Mode - - + + Get Display Mode - - + + Set Screen Offset - - + + Get Screen Offset - + Open file Failed Open file Failed - + Setting Wallpaper - - + + Set Wallpaper - + System Updating - - + + System Update - + Getting MCU Version - - + + MCU Version - + Select File Select File - + Setting player background - - + + Set player background - + Clearing player background - - - - - - - - + + + + + + + + Clear player background - - + + GetScreenRotation Get Screen Rotation - - - + + + Charging Station - + Setting Baud Rate - + Set Baud Rate - + Getting Baud Rate - + Get Baud Rate - - + + Text is empty + + + + Json Parse Error + + - Json Parse Error - - - - - Json isn't an Object - + Info - + Setting card work mode ... - + Set card work mode - + Getting card work mode ... - + Get card work mode - + Input password Input password - + Change Password Change Password - + Resolution Config - + Full screen - + Part - + Display Mode - + Screen Position - + Offset - + Hidden Settings - + Click right button to hide - - + + Update MCU - + Get MCU Version - + Baud Config - + Model - + Uart - + Baud - - - + + + + - - - - + + + Get - + Timing Reboot - + Protocol - + Server - + Client - - + + SetScreenRotation Set screen rotation - - + + SetMinBrightness Set min brightness value - - + + SetMaxBrightness Set maximum brightness value - - + + GetMinBrightness Get min brightness - - + + GetMaxBrightness Get maximum brightness - - + + Card work mode - - + + SetSpecialResolution Set Special Resolution - - + + GetSpecialResolution Get Special Resolution - - + + CleanDisplayScreenSize Restore to default relolution - - + + SetHighForBusy Set level for busy - - + + GetStateForBusy Get level of busy @@ -928,59 +928,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + Tip Tip @@ -997,41 +997,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController Please select screen first @@ -1046,7 +1046,7 @@ Please enter the correct height pixel value - + Password is error Password is error @@ -1526,151 +1526,151 @@ CtrlNetworkPanel - + Wire Enther(RJ45) Configuration Wire Enther(RJ45) Configuration - + DHCP - + Specify IP Specify IP - + IP Address IP Address - + Gateway Gateway - + DNS Address DNS Address + - - + Set Set + - - - + + Readback Readback - + WIFI Configuration WiFi Configuration - + WiFi Mode WiFi Mode - + Cellular Config Cellular Config - + Enable Cellular Data Enable Cellular Data - + Get cellular network status information Get cellular network status information - + Through the check status button Through the "check status" button, you can automatically match the country code MCC, and then select "operator" to get the corresponding APN information. - + Country ID(mcc): Country ID(mcc): - - + + Carrier Name Carrier Name - + APN(Required) APN(Required) - + Flight Mode Flight Mode - + WiFi name WiFi name - - - + + + Password Password + - Input password Input password - + Scan Scan - + Ap Mode AP - + OFF OFF - + ON ON - + AP name AP name - + Subnet mask Subnet mask - + Input ap name Input AP name @@ -1679,14 +1679,14 @@ - - - - - - - - + + + + + + + + Tip Tip @@ -1695,13 +1695,13 @@ - - - - - - - + + + + + + + NoSelectedController Please select screen first @@ -1757,14 +1757,14 @@ - - + + ConfigurationWiFi Configuration WiFi - - + + IsPortableHotSpot Get AP or WiFi @@ -1774,45 +1774,45 @@ Scan WiFi list - - + + ConfigurationHotSpot Configuration AP HotSpot - + success success - + WifiName WifiName - + ApName Ap Name - - + + GetCurrentAPN Get Current Apn - + GetSIMStatus Get SIM Status - - + + SetAPN Set APN - + 状态: Status: @@ -1822,265 +1822,265 @@ Error - + 未知 unknown - + 锁定状态,需要用户的PIN码解锁 Lock status, need user's pin code to unlock - + 锁定状态,需要用户的PUK码解锁 In the locked state, the PUK code of the user is required to be unlocked - + 锁定状态,需要网络的PIN码解锁 In the locked state, the PIN code of the user is required to be unlocked - + 就绪 be ready - + no checked sim card no checked sim card - + 国家码: MCC: - + 号码: number: - + 用户: User name: - + 信号: Signal: - + 信号正常 Signal OK - + 不在服务区 Not in service area - + 仅限紧急呼叫 Emergency call only - + 射频已经关闭 RF off - + 网络: Network type: - + 网络类型未知 unKnown - + GPRS网络 GPRS - + EDGE网络 EDGE - + UMTS网络 UMTS - + CDMA网络,IS95A 或 IS95B. CDM - + EVDO网络, revision 0. EVDO,revision 0. - + EVDO网络, revision A. EVDO,revision A. - + 1xRTT网络 1xRTT - + HSDPA网络 HSDPA - + HSUPA网络 HSUPA - + HSPA网络 HSPA - + 漫游: roam: - + Yes Yes - + No No - + 数据连接状态: Data connection status: - + 断开 OFF - + 正在连接 connecting - + 已连接 Connected - + 暂停 suspend - + 数据活动休眠状态: Data active sleep state: - + 活动,但无数据发送和接收 Active, but no data sent and received - + 活动,正在接收数据 Activity, receiving data - + 活动,正在发送数据 Activity, sending data - + 活动,正在接收和发送数据 Activity, receiving and sending data - + 休眠状态 Sleep state - + 信号强度: Signal strength: - + Set APN Info - + User - + Type - + Server - + Port - + Proxy - + MMS Port - + MMS Proxy - - + + SetSwitchSimData SetSwitchSimData - - + + ContrFlightMode Set flight mode - - + + GetFlightModeState Readback flight mode state @@ -3110,8 +3110,8 @@ - - + + Success @@ -3128,45 +3128,45 @@ DevicePanel - + All ALL ALL - + Online Online Online - + Refresh Refresh Refresh - - + + Specify IP Specify IP Specify IP - - - - + + + + Current Screen Current screen - - + + none none @@ -3202,9 +3202,9 @@ - - - + + + Player Version @@ -3219,145 +3219,145 @@ - + Specify IP list - + Search Search - - + + Attention Attention - - + + Please input IP address! Please input IP address! - + Cancel Cancel - + Screen ID Screen ID - + Screen Size Screen Size - + Alias - + Screenshot Screenshot - - + + On ON - - + + Off OFF - + Brightness Adj. Brightness Adj. - + Power Control Power Control - + Net Config Network Config - + Time Sync Time Sync - + Video source Video Source - + Password Password - + Advanced Advanced - + Volume Adj. Volume - + Test Test - - + + Multi screen operation Multi screen operation - - + + selected num Selected number - - + + Clear Clear - + More Info More Info - + Screen Brightness Screen Brightness - + Power Status Power Status - + Security encryption @@ -3367,28 +3367,28 @@ - - + + Error Error - + Input password Input password - + VerifyPassword Verify Password - + Tip Info Tip Info - + password is wrong password is wrong @@ -3720,74 +3720,74 @@ EEnviron - - + - + - + + north north - - + + east east - - + + south south - - + + west west @@ -3817,67 +3817,87 @@ Wind Direction - + + Pressure + + + + + Rainfall + + + + + Radiation + + + + + Beam + + + + Basic Properties Basic properties - + Title Title - + Compensation Compensation - + Left Left - + Center Center - + Right Right - + Single scroll Single scroll - + Speed Speed - + ms/pixel ms/pixel - + Back Color Back Color - + Play Properties - + Play Duration Play Duration - + s s @@ -4044,63 +4064,63 @@ - Alpha_In - ALPHA_IN + Alpha In + Moving to left - MOVING_TO_LEFT + Moving to right - MOVE_TO_RIGHT + Moving to top - MOVING_TO_TOP + Move to bottom - MOVE_TO_BOTTOM + - Zoom in - ZOOM_IN + Zoom In + - Zoom in to left_bottom - ZOOM_IN_LEFT_BOTTOM + Zoom In to left_bottom + - Zoom in to left_top - ZOOM_IN_LEFT_TOP + Zoom In to left_top + - Zoom in to right_top - ZOOM_IN_RIGHT_TOP + Zoom In to right_top + - Zoom in to right bottom - ZOOM_IN_RIGHT_BOTTOM + Zoom In to right bottom + Rotate to right - ROTATE_TO_RIGHT + Rotate to left - ROTATE_TO_LEFT + @@ -4479,22 +4499,22 @@ EleTimer - + day Days - + hour Hours - + min Mins - + sec Secs @@ -4570,7 +4590,7 @@ ImgDlg - + Screenshot @@ -4621,50 +4641,50 @@ MainWindow - + Language Language - + Help Help - + Check for updates Check for updates - + firmware manager Firmware management - + Preferences - - + + Info - - - + + + About About - + Setting Setting @@ -4715,7 +4735,7 @@ - Width Split + Ultra-Long Screen Split @@ -4751,47 +4771,47 @@ - + Downloading updates Downloading updates - + Error Error - + Device Terminals - + Program Solutions - + Control Terminal Control - + Lora Screen - + Check card Detect - + Tip Info Tip Info - + RestoreLedCardIpByUdpTip This operation will fix all the control cards in the LAN that are not in the same network segment as the computer IP. Please be careful! @@ -5038,17 +5058,17 @@ PlayWin - + Move to Top Left Move to Top Left - + Set Position - + Close Close @@ -5056,12 +5076,12 @@ PlayerBackSendThread - + Open file failed Open file failed - + Read file failed Read file failed @@ -5082,230 +5102,240 @@ ProgCreateDlg - + Resolution Resolution - + Solution Information Solution Information - + Solution Name Solution Name - + Width Width - + Height Height - + Remarks Remarks - - 每段打折宽度 (用空格分隔) - Each part width (split with space) + + Ultra-Long Screen Split + + + + + Part Width + ProgEditorWin - + Save Save - + Setting Setting - + Text Text - + Photo Photo - + Video Video - + Gif Gif - + Clock Clock - + Analog Clock Analog Clock - + Environment Environmental Monitoring - + Web Web page - + MuliContentWindow Multi material window - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; In this window, a plurality of different program materials can be added and played according to the order of joining the list - + Timer Timer - - Demo Video - - - - + Play - + Stop Stop - + Publish Publish - - - + + + Select File Select File - + program Program - + Add page Add page - + Copy page Copy page - + Delete page Delete page - - + + Tip Info Tip Info - + Are you sure you want to delete this program page? Are you sure you want to delete this program page? - + Move up Move up - + Move down Move down - + widget properties Widget properties - + Page properties Program properties - + Do you want to save the modifications? Do you want to save the modifications? - + Create Dir failed - + Saving... Saving... - + Success Success - + Convertering Convertering - + + Demos + + + + + Open Demo + + + + Generate preview data Generate preview data - - - + + + Error Error - + Rename fail when saving - + Remove Recursively fail when saving @@ -5313,124 +5343,124 @@ ProgPanel - - + + New New - - + + Edit Edit - - + + Delete Delete - - - + + + Import Import - - - + + + Export Export - - + + Send Send - + Publish Publish - + Name Name - - + + Choose Directory Choose Directory - + Tip Tip - + The imported directory is already in the working directory, so there is no need to import it again! The imported directory is already in the working directory, so there is no need to import it again! - + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - - + + Play - - + + Stop Stop - + Resolution Resolution - + File Size File Size - + Last Modify Last Modified - + USB Update - + Program name conflicted Program name conflicted - + Warning Warning - + You will delete the selected solution(s),are you sure? You will delete the selected solution(s),are you sure? - - + + Tip Info Tip Info @@ -5456,7 +5486,7 @@ QAbstractSocket - + Socket operation timed out @@ -5474,7 +5504,7 @@ Input password - + Error Error @@ -5515,17 +5545,17 @@ SendProgThread - + Program is empty Program is empty - + Open file failed Open file failed - + Read file failed Read file failed @@ -5549,32 +5579,32 @@ Refresh - + Alias - + Online Online - + Screen Size Screen Size - + Security encryption - + Progress Progress - + Remarks Remarks @@ -5599,17 +5629,17 @@ Verify Password - + Tip Info Tip Info - + password is wrong password is wrong - + All ALL @@ -5632,12 +5662,12 @@ Upgrade - + Uninstall Uninstall - + check running state check running state @@ -5647,42 +5677,42 @@ Select Fpga - + Installing - + Refresh Refresh - + Alias - + Online Online - + Security encryption - + Progress Progress - + State State - + All ALL @@ -5725,7 +5755,7 @@ - + Tip Tip @@ -5741,137 +5771,137 @@ - + Downloading Online File - - - - - + + + + + Error Error - + Online file is empty - + File is empty - + Uploading - + Upload error - + Don't power off during this process - + Install error - - + + Install Success - + Reminder - + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! - + Do you want to continue? - + Uninstalling Uninstalling - + Uninstall error - + Uninstall success - + Check apk running status - + Check error - + Running Running - + Not running - + Input password Input password - + VerifyPassword Verify Password - + Tip Info Tip Info - + password is wrong password is wrong - + Same version, needn't update - + Install Failed - + The encrypted control card can be upgraded directly The encrypted control card can be upgraded directly diff --git a/LedOK/ts/app_ja.ts b/LedOK/ts/app_ja.ts index 9396dd6..7ce851e 100644 --- a/LedOK/ts/app_ja.ts +++ b/LedOK/ts/app_ja.ts @@ -39,8 +39,8 @@ - Please enter a password with more than 6 characters - 6文字以上のパスワードを入力してください + Please enter a password with more than 3 characters + 3 文字以上のパスワードを入力してください @@ -56,156 +56,156 @@ CtrlAdvancedPanel - + Advanced 上級パラメータ - + Screen Width(pixel) 画面幅(ピクセル) - + Width - - + + Height 高さ - - - - + + + + + + - - - - - - - + + + + + + - + - - - + + Set セット - + Alias 別名 - + Web Server Address: Webサーバのアドレス: - + MCU Uploading - + Setting - + Traffic screen settings - + Setting protocol ... - + Set protocol - + Getting protocol ... - + Get protocol - - + + Port ポート - + Realtimer Server Address: Realtimerアドレス: - + Firmware Management ファームウェア管理 - + update or uninstall 更新またはアンインストール - + Clear クリア - + Check Apk APKを検出 - + Uninstall アンマウント - + Running check 運転状態モニタ - + Restart 再起動 - + Check Log ログを見る - + Start LedSet4 - + Open ADB ADBデバッグ機能を開く - + Post Custom JSON Post Custom JSON @@ -215,7 +215,7 @@ - + Clear Program 番組をクリア @@ -225,66 +225,66 @@ - + Config の設定 - + Refresh 更新 - + Restore to default 標準の値を復元 - + Taxi top screen configuration タクシートップ画面の設定 - - + + Service:High Out of service:Low 客がいます:高 客がいません:低 - - + + Service:Low Out of service:High 客がいます:低 客がいません:高 - + Binding *.ic account indentity voucher テーピングtaxihubプラットフォームのユーザーID証明書 - + Rotate 回転 - + Min brightness 最低輝度 - - - + + + Readback 読み戻し - + Send 送信 - + Max brightness 最高輝度 @@ -296,20 +296,20 @@ - - - - + + + + Success 成功 - + Compant ID: 会社ID: - + Compant ID 会社ID @@ -382,28 +382,28 @@ APK運転状態監視 - - + + OpenAdb ADBデバッグ機能を開く - + indentity voucher (*.ic) 身分証明書(*.ic) - - - + + + + - InvokeTaxiAppFunction 証明書をバインド - - + + AliIotSetting @@ -434,16 +434,16 @@ プログラムクリア - - + + Timeout タイムアウト - - + + Failed 失敗 @@ -455,53 +455,53 @@ - - - - - - - - - - - + + + + + + + + + + + Error エラー - + Setting Timing Reboot スケジュール再起動を設定中 - + Set Timing Reboot スケジュール再起動の設定 - + Getting Timing Reboot スケジュール再起動を取得中 - + Get Timing Reboot スケジュール再起動の取得 - + totalResolution トータル解像度 - + strCurDisplayResolution 表示解像度 - - + + File not exist ファイルが存在しません @@ -513,7 +513,7 @@ - + Get Player State プレーヤーの状態の取得 @@ -534,368 +534,368 @@ 続行しますか? - - + + Cannot Open File ファイルのオープンに失敗しました - + Uploading アップロード中 - + Update 更新 - - + + Set Display Mode - - + + Get Display Mode - - + + Set Screen Offset - - + + Get Screen Offset - + Open file Failed ファイルのオープンに失敗しました - + Setting Wallpaper - - + + Set Wallpaper - + System Updating - - + + System Update - + Getting MCU Version - - + + MCU Version - + Select File ファイルを選択 - + Setting player background - - + + Set player background - + Clearing player background - - - - - - - - + + + + + + + + Clear player background - - + + GetScreenRotation 画面回転の取得 - - - + + + Charging Station じゅうでんぐい - + Setting Baud Rate - + Set Baud Rate - + Getting Baud Rate - + Get Baud Rate - - + + Text is empty + + + + Json Parse Error + + - Json Parse Error - - - - - Json isn't an Object - + Info 情報 - + Setting card work mode ... - + Set card work mode - + Getting card work mode ... - + Get card work mode - + Input password パスワードを入力 - + Change Password パスワード変更 - + Resolution Config 解像度設定 - + Full screen フルスクリーン - + Part セクション - + Display Mode 表示モード - + Screen Position - + Offset - + Hidden Settings - + Click right button to hide - - + + Update MCU - + Get MCU Version - + Baud Config - + Model - + Uart - + Baud - - - + + + + - - - - + + + Get 得る - + Timing Reboot スケジュール再起動 - + Protocol プロトコル - + Server サービス - + Client クライアント - - + + SetScreenRotation 画面の回転を設定する - - + + SetMinBrightness 最小輝度値を設定します - - + + SetMaxBrightness 輝度最大値を設定 - - + + GetMinBrightness 輝度最小値を取得 - - + + GetMaxBrightness 輝度最大値を取得 - - + + Card work mode - - + + SetSpecialResolution 解像度を設定 - - + + GetSpecialResolution 読み込み解像度 - - + + CleanDisplayScreenSize デフォルトの解像度を復元 - - + + SetHighForBusy 客レベルの設定 - - + + GetStateForBusy ゲストレベルを取得 @@ -928,59 +928,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + Tip 提示 @@ -997,41 +997,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 先に大きいスクリーンを選んでください @@ -1046,7 +1046,7 @@ 正しい高さのピクセル値を入力してください - + Password is error パスワード @@ -1526,156 +1526,156 @@ CtrlNetworkPanel - + Wire Enther(RJ45) Configuration 有線ネットワークの設定 - + DHCP - + Specify IP 指定IP - + IP Address IPアドレス - + Gateway ゲートウェイ - + DNS Address DNSアドレス + - - + Set セット + - - - + + Readback 読み戻し - + WIFI Configuration WiFiの設定 - + WiFi Mode WiFi機能 - + Cellular Config セルラーデータ構成 - + Enable Cellular Data セルラーデータを有効にする - + Get cellular network status information セルラーネットワーク状態情報を取得する - + Through the check status button 「ステータスを取得」ボタンを使用すると、国コードに自動的に一致し、対応するAPN情報を取得するには「事業者」を選択します。 - + Set APN Info APN情報を設定する - + Country ID(mcc): 国号(mcc): - - + + Carrier Name 運営者 - + APN(Required) APN(必ず記入) - + Flight Mode 飛行モード - + WiFi name WiFiの名前 - - - + + + Password パスワード + - Input password パスワードを入力 - + Scan スキャン - + Ap Mode APエネルギー - + OFF オフ - + ON オン - + AP name AP名 - + Subnet mask サブネットマスク - + Input ap name APの名前を入力 @@ -1684,14 +1684,14 @@ - - - - - - - - + + + + + + + + Tip 提示 @@ -1700,13 +1700,13 @@ - - - - - - - + + + + + + + NoSelectedController 先に大きいスクリーンを選んでください @@ -1762,14 +1762,14 @@ - - + + ConfigurationWiFi WiFiの設定 - - + + IsPortableHotSpot ホットスポットとWiFiモードの取得 @@ -1779,45 +1779,45 @@ スキャンWiFi - - + + ConfigurationHotSpot ホットスポットの設定 - + success 成功 - + WifiName Wifiの名前 - + ApName AP名前 - - + + GetCurrentAPN APN情報の取得 - + GetSIMStatus SIM状態を取得 - - + + SetAPN APNの設定 - + 状态: 状態: @@ -1827,260 +1827,260 @@ エラー - + 未知 不明 - + 锁定状态,需要用户的PIN码解锁 ロック状態は、ユーザのPINコードのロック解除が必要です - + 锁定状态,需要用户的PUK码解锁 ロック状態は、ユーザのPUKコードのアンロックが必要です - + 锁定状态,需要网络的PIN码解锁 ロック状態は、ユーザのPINコードのアンロックが必要です - + 就绪 準備完了 - + no checked sim card simカードが検出されませんでした - + 国家码: 国号: - + 号码: 番号: - + 用户: ユーザ: - + 信号: 信号: - + 信号正常 信号が正常である - + 不在服务区 サービスエリアにはいません - + 仅限紧急呼叫 緊急呼び出しのみ - + 射频已经关闭 無線周波数はすでに閉鎖されました - + 网络: ネットワークタイプ: - + 网络类型未知 不明 - + GPRS网络 GPRS - + EDGE网络 EDGE - + UMTS网络 UMTS - + CDMA网络,IS95A 或 IS95B. CDM - + EVDO网络, revision 0. EVDO,revision 0. - + EVDO网络, revision A. EVDO,revision A. - + 1xRTT网络 1xRTT - + HSDPA网络 HSDPA - + HSUPA网络 HSUPA - + HSPA网络 HSPA - + 漫游: ローミング: - + Yes - + No いいえ - + 数据连接状态: データ接続状態: - + 断开 切断 - + 正在连接 接続中 - + 已连接 接続済み - + 暂停 一時停止 - + 数据活动休眠状态: データアクティビティの休止状態: - + 活动,但无数据发送和接收 アクティブですが、データ送信と受信はありません - + 活动,正在接收数据 アクティブ、データ受信中 - + 活动,正在发送数据 イベント、データ送信中 - + 活动,正在接收和发送数据 イベント、データ受信と送信中 - + 休眠状态 スリープ状態 - + 信号强度: 信号の強度: - + User ユーザー - + Type タイプ - + Server サービス - + Port ポート - + Proxy プロキシ - + MMS Port MMS ポート - + MMS Proxy MMS プロキシ - - + + SetSwitchSimData 4G/5Gスイッチの設定 - - + + ContrFlightMode 飛行モードの設定 - - + + GetFlightModeState 飛行モード状態を取得 @@ -3110,8 +3110,8 @@ - - + + Success @@ -3128,44 +3128,44 @@ DevicePanel - + All トータル トータル - + Online オンライン中 - + Refresh 更新 更新 - - + + Specify IP 指定IP 指定IP - - - - + + + + Current Screen 現在のスクリーン - - + + none なし @@ -3201,9 +3201,9 @@ - - - + + + Player Version プレーヤーファームウェアバージョン @@ -3218,145 +3218,145 @@ 取得中 - + Specify IP list 指定 IP リスト - + Search 検索 - - + + Attention 注意 - - + + Please input IP address! IPアドレスを入力してください! - + Cancel キャンセル - + Screen ID ターミナルID - + Screen Size スクリーンサイズ - + Alias 別名 - + Screenshot スクリーンショット - - + + On オン - - + + Off オフ - + Brightness Adj. 輝度設定 - + Power Control 電源コントロール - + Net Config ネット配置 - + Time Sync タイマ配置 - + Video source ビデオソース - + Password ひそかに言う - + Advanced 上級パラメータ - + Volume Adj. 音量調節 - + Test テスト - - + + Multi screen operation マルチスクリーン操作 - - + + selected num 選択された数 - - + + Clear クリア - + More Info 詳細 - + Screen Brightness 画面の明るさ - + Power Status 画面切り替えステータス - + Security 暗号化 @@ -3366,28 +3366,28 @@ 取得中 - - + + Error エラー - + Input password パスワードを入力 - + VerifyPassword パスワードの検証 - + Tip Info ヒント - + password is wrong パスワードエラー @@ -3719,74 +3719,74 @@ EEnviron - - + - + - + + north 北の方 - - + + east - - + + south 南の方 - - + + west 西の方 @@ -3816,83 +3816,87 @@ 風向 + Pressure - 気圧 + 気圧 + Rainfall - うりょう + うりょう + Radiation - ふく射 + ふく射 + Beam - ひかりのつよさ + ひかりのつよさ - + Basic Properties 基本的な属性 - + Title タイトル - + Compensation 補償 - + Left 左に寄る - + Center 中央にある - + Right 右に寄る - + Single scroll 1行スクロール - + Speed スピード - + ms/pixel ミリ秒/ピクセル - + Back Color 背景色 - + Play Properties 再生方法 - + Play Duration 再生時間 - + s @@ -4059,7 +4063,7 @@ - Alpha_In + Alpha In 淡入 @@ -4084,27 +4088,27 @@ - Zoom in + Zoom In 拡大 - Zoom in to left_bottom + Zoom In to left_bottom 左下の拡大 - Zoom in to left_top + Zoom In to left_top 左上の角を大きく - Zoom in to right_top + Zoom In to right_top 右上拡大 - Zoom in to right bottom + Zoom In to right bottom 右下隅を大きく @@ -4494,22 +4498,22 @@ EleTimer - + day - + hour - + min - + sec @@ -4585,7 +4589,7 @@ ImgDlg - + Screenshot スクリーンショット @@ -4636,50 +4640,50 @@ MainWindow - + Language 言語 - + Help ヘルプ - + Check for updates アップデートをチェック - + firmware manager ファームウェア管理 - + Preferences プリファレンス設定 - - + + Info 情報 - - - + + + About 当ソフトウェアについて - + Setting 設置 @@ -4730,8 +4734,8 @@ - Width Split - + Ultra-Long Screen Split + 超ロングスクリーン分割 @@ -4766,47 +4770,47 @@ - + Downloading updates 更新をダウンロード - + Error エラー - + Device 端末管理 - + Program コンテンツ管理 - + Control ターミナルコントロール - + Lora Screen - + Check card ワンタッチ修復 - + Tip Info ヒント - + RestoreLedCardIpByUdpTip この操作はLAN内のすべてのコンピュータIPと同じセグメントにないコントロールカードを固定IPに修正します。慎重に操作してください。 @@ -5053,17 +5057,17 @@ PlayWin - + Move to Top Left 左上隅に移動 - + Set Position 設定位置 - + Close 閉じる @@ -5071,12 +5075,12 @@ PlayerBackSendThread - + Open file failed ファイルのオープンに失敗しました - + Read file failed ファイルの読み込みに失敗しました @@ -5097,230 +5101,240 @@ ProgCreateDlg - + Resolution 解像度 - + Solution Information スケジュール情報 - + Solution Name リスト名 - + Width - + Height 高さ - + Remarks 備考 - - 每段打折宽度 (用空格分隔) - + + Ultra-Long Screen Split + 超ロングスクリーン分割 + + + + Part Width + ProgEditorWin - + Save 保存 - + Setting 設置 - + Text テキスト - + Photo 写真 - + Video ビデオ - + Gif アニメーション - + Clock デジタル時計 - + Analog Clock アナログ時計 - + Environment 環境モニタリング - + Web ウェブページ - + MuliContentWindow マルチ素材ウィンドウ - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; このウィンドウには、複数の異なる番組素材を追加して、リストに追加した順に再生することができます - + Timer タイマー - - Demo Video - テストビデオ - - - + Play 再生 - + Stop 停止 - + Publish 転送 - - - + + + Select File ファイルを選択 - + program 番組リスト - + Add page ページを追加 - + Copy page コピーページ - + Delete page ページを削除 - - + + Tip Info ヒント - + Are you sure you want to delete this program page? 本当にこの番組ページを削除しますか? - + Move up 前へ - + Move down 次頁 - + widget properties パッケージプロパティ - + Page properties プログラムのプロパティ - + Do you want to save the modifications? 変更された内容を保存してもよろしいですか? - + Create Dir failed ディレクトリの作成に失敗しました - + Saving... 保存中、少々お待ちください... - + Success 成功 - + Convertering データを整理する - + + Demos + テスト素材 + + + + Open Demo + テスト素材を開く + + + Generate preview data プレビューデータの生成 - - - + + + Error エラー - + Rename fail when saving - + Remove Recursively fail when saving @@ -5328,124 +5342,124 @@ ProgPanel - - + + New 新規 - - + + Edit 編集 - - + + Delete 削除 - - - + + + Import インポート - - - + + + Export 出力 - - + + Send 送信 - + Publish 転送 - + Name 名前 - - + + Choose Directory ディレクトリを選択 - + Tip 提示 - + The imported directory is already in the working directory, so there is no need to import it again! このインポートしたディレクトリはすでにワークディレクトリの下にあります。再インポートする必要はありません! - + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? 解決策は既に存在します。既存の解決策を上書きしたいと思いますか? - - + + Play 再生 - - + + Stop 停止 - + Resolution 解像度 - + File Size サイズ - + Last Modify 最終更新日 - + USB Update USB更新 - + Program name conflicted 番組名が重なる - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否确认删除选中的节目? - - + + Tip Info ヒント @@ -5471,7 +5485,7 @@ QAbstractSocket - + Socket operation timed out @@ -5489,7 +5503,7 @@ パスワードを入力 - + Error エラー @@ -5530,17 +5544,17 @@ SendProgThread - + Program is empty プログラムは空です - + Open file failed ファイルのオープンに失敗しました - + Read file failed ファイルの読み込みに失敗しました @@ -5564,32 +5578,32 @@ 更新 - + Alias 別名 - + Online オンライン中 - + Screen Size スクリーンサイズ - + Security 暗号化 - + Progress 程度 - + Remarks 備考 @@ -5614,17 +5628,17 @@ パスワードの検証 - + Tip Info ヒント - + password is wrong パスワードエラー - + All トータル @@ -5647,12 +5661,12 @@ アップグレード - + Uninstall アンマウント - + check running state 運転状態を検出 @@ -5662,42 +5676,42 @@ FPGAファイルを選択 - + Installing インストール中 - + Refresh 更新 - + Alias 別名 - + Online オンライン中 - + Security 暗号化 - + Progress 程度 - + State 状態 - + All トータル @@ -5740,7 +5754,7 @@ - + Tip 提示 @@ -5756,137 +5770,137 @@ - + Downloading Online File オンラインファイルをダウンロード中 - - - - - + + + + + Error エラー - + Online file is empty オンラインファイルが空です - + File is empty - + Uploading アップロード中 - + Upload error アップロード エラー - + Don't power off during this process アップグレード中は電源を切らないでください - + Install error インストール エラー - - + + Install Success インストールに成功しました - + Reminder ヒント - + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! ヒント:このプログラムをアンインストールすると、プラットフォームがオフラインになり、デバイスが見つかりません。構成パラメータが失われ、黒画面の問題が発生します。慎重にアンインストールしてください。 - + Do you want to continue? 続行しますか? - + Uninstalling アンマウント中 - + Uninstall error アンインストール エラー - + Uninstall success アンインストールに成功しました - + Check apk running status APK運転状態監視 - + Check error チェック エラー - + Running 実行中 - + Not running 実行されていません - + Input password パスワードを入力 - + VerifyPassword パスワードの検証 - + Tip Info ヒント - + password is wrong パスワードエラー - + Same version, needn't update 同じバージョン、更新不要 - + Install Failed インストールに失敗しました - + The encrypted control card can be upgraded directly 暗号化されたコントロールカードを直接アップグレードすることができます diff --git a/LedOK/ts/app_pt.ts b/LedOK/ts/app_pt.ts index 9d8c074..2879d85 100644 --- a/LedOK/ts/app_pt.ts +++ b/LedOK/ts/app_pt.ts @@ -39,8 +39,8 @@ - Please enter a password with more than 6 characters - Entre com senha de mais de 6 caracteres + Please enter a password with more than 3 characters + Entre com senha de mais de 3 caracteres @@ -56,161 +56,161 @@ CtrlAdvancedPanel - + Advanced Avançado - + Screen Width(pixel) Largura do display(pixel) - + Width Largura - - + + Height Altura - - - - + + + + + + - - - - - - - + + + + + + - + - - - + + Set Config - + Alias Apelido - + Web Server Address: Endereço do Web Server: - + MCU Uploading - + Setting - + Getting Baud Rate - + Traffic screen settings - + Setting protocol ... - + Set protocol - + Getting protocol ... - + Get protocol - - + + Port - + Model - + Realtimer Server Address: Servidor de horário: - + update or uninstall - + Clear Limpar - + Check Apk Conferi Apk - + Uninstall Desinstalar - + Running check Conferir - + Restart Reiniciar - + Check Log Conferir Log - + Start LedSet4 Iniciar LedSet4.0 (Apk Display2.0 and higher) - + Open ADB Abri ADB debug - + Post Custom JSON Publicar JSON @@ -220,7 +220,7 @@ - + Clear Program Limpar Programa @@ -230,66 +230,66 @@ - + Config Config - + Refresh Atualizar - + Restore to default Restaurar padrão - + Taxi top screen configuration Taxi top screen configuration - - + + Service:High Out of service:Low Service:Altura fora do pardão:Diminuir - - + + Service:Low Out of service:High Service:Altura fora do padrão:Aumentar - + Binding *.ic account indentity voucher Vincular *.identificação da conta - + Rotate Rotacionar - + Min brightness Brilho minimo - - - + + + Readback Ler - + Send Enviar - + Max brightness Brilho Maximo @@ -301,20 +301,20 @@ - - - - + + + + Success Successo - + Compant ID: ID da empresa - + Compant ID ID da empresa @@ -387,28 +387,28 @@ Checar status do APK - - + + OpenAdb Abrir o debug - + indentity voucher (*.ic) Comprovante de ID (*.ic) - - - + + + + - InvokeTaxiAppFunction Vincular certificado - - + + AliIotSetting @@ -439,16 +439,16 @@ - - + + Timeout Tempo esgotado - - + + Failed Falhou @@ -460,17 +460,17 @@ - - - - - - - - - - - + + + + + + + + + + + Error Erro @@ -488,55 +488,55 @@ - + Get Player State - + Setting Timing Reboot Config tempo de reiniciar - + Set Timing Reboot Config tempo de reiniciar - + Getting Timing Reboot Config tempo de reiniciar - + Get Timing Reboot Obtendo tempo de reinicialização - - + + Get Display Mode - - + + Set Screen Offset - + totalResolution Resolução total de FPGA - + strCurDisplayResolution Resolução do display - - + + File not exist Arquivo não encontrado @@ -551,351 +551,351 @@ Continuar? - - + + Cannot Open File Não pode abrir arquivo - + Uploading Atualizando - + Update Atualizar - - + + Set Display Mode Config Display - - + + Get Screen Offset Obter display Offset - + Open file Failed Falaha em abrir - + Setting Wallpaper Config plano fundo - - + + Set Wallpaper Config plano fundo - + System Updating Atualizando - - + + System Update Sistema atualizado - + Getting MCU Version Obtendo versão - - + + MCU Version Verão de MCU - + Select File Arquivo selecionado - + Setting player background Config plano de fundo - - + + Set player background Config plano de fundo - + Clearing player background Apagar plano de fundo - - - - - - - - + + + + + + + + Clear player background Apagar plano de fundo - - + + GetScreenRotation Rotação do display - - - + + + Charging Station - + Setting Baud Rate Config Baud Rate - + Set Baud Rate Config Baud Rate - + Get Baud Rate Config Baud Rate - - + + Text is empty Testo em branco - - + + Json Parse Error Erro Json - - + + Json isn't an Object - + Info Info - + Setting card work mode ... - + Set card work mode - + Getting card work mode ... - + Get card work mode - + Input password Entre com a senha - + Change Password Troque a senha - + Resolution Config Config de resolução - + Full screen Full screen - + Part Parte - + Display Mode Modo do display - + Screen Position Posição da tela - + Offset Offset - + Hidden Settings Esconder Config - + Click right button to hide Clique com o botão direito para esconder - - + + Update MCU - + Get MCU Version Versão de MCU - + Baud Config Config Baudrate - + Uart Uart - + Baud Baud - - - + + + + - - - - + + + Get Obter - + Firmware Management - + Timing Reboot Reiniciando - + Protocol Protocolo - + Server Servidor - + Client Cliente - - + + SetScreenRotation Config a rotação do display - - + + SetMinBrightness Config brilho minimo - - + + SetMaxBrightness Config brilho maximo - - + + GetMinBrightness Obter bilho - - + + GetMaxBrightness Obter brilho - - + + Card work mode - - + + SetSpecialResolution Config resolução especial - - + + GetSpecialResolution Ler resolução especial - - + + CleanDisplayScreenSize Restaurar resolução - - + + SetHighForBusy Set level for busy - - + + GetStateForBusy Get level of busy @@ -928,59 +928,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + Tip Dica @@ -997,41 +997,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController Selecionar o display @@ -1046,7 +1046,7 @@ Entre com a correta altura - + Password is error Senha esta errada @@ -1526,146 +1526,146 @@ CtrlNetworkPanel - + Wire Enther(RJ45) Configuration Wire Enther(RJ45) Configuração - + DHCP DHCP - + Specify IP IP - + IP Address Endereço IP - + Gateway Gateway + - - + Set Config + - - - + + Readback Ler - + WIFI Configuration Config WiFi - + WiFi Mode Modo WiFi - + Cellular Config Config Celular - + Enable Cellular Data Habilitar celular - + Get cellular network status information Obter informação da rede - + Through the check status button Atraves do botão de status, voce pode escolher automaticamente o codigo MCC do pais;selecione para obtera correta informação de APN . - + Country ID(mcc): ID do país(mcc): - - + + Carrier Name Operadora - + APN(Required) APN(requerida) - + Flight Mode Modo avião - + WiFi name Nome WiFi - - - + + + Password Senha + - Input password Entre com a senha - + Scan Escanear - + Ap Mode AP - + OFF Desligar - + ON Ligar - + AP name Nome do AP - + Subnet mask Mascara subnet - + Input ap name Entre com nome do AP @@ -1674,14 +1674,14 @@ - - - - - - - - + + + + + + + + Tip Dica @@ -1690,13 +1690,13 @@ - - - - - - - + + + + + + + NoSelectedController Selecione o display @@ -1752,14 +1752,14 @@ - - + + ConfigurationWiFi Configuração WiFi - - + + IsPortableHotSpot Obter AP ou WiFi @@ -1769,45 +1769,45 @@ Escanear lista WiFi - - + + ConfigurationHotSpot Configuração do AP - + success successo - + WifiName Nome Wifi - + ApName Nome Ap - - + + GetCurrentAPN Obter APN atual - + GetSIMStatus Obter estatus do SIM - - + + SetAPN Config APN - + 状态: Estatus: @@ -1817,270 +1817,270 @@ Erro - + 未知 Desconhecido - + 锁定状态,需要用户的PIN码解锁 Travar; necessita de pin para alterar - + 锁定状态,需要用户的PUK码解锁 Travado, necessário PUK para destravar - + 锁定状态,需要网络的PIN码解锁 Travado, necessário PUK para destravar - + 就绪 Lendo - + no checked sim card SIM card não checado - + 国家码: MCC: - + 号码: numero: - + 用户: Nome de usuário: - + 信号: Sinal: - + 信号正常 Sinal OK - + 不在服务区 Fora da area de serviço - + 仅限紧急呼叫 Apenas chamadas de emergencia - + 射频已经关闭 RF desligado - + 网络: Tipo de network: - + 网络类型未知 desconhecido - + GPRS网络 GPRS - + EDGE网络 EDGE - + UMTS网络 UMTS - + CDMA网络,IS95A 或 IS95B. CDM - + EVDO网络, revision 0. EVDO,revision 0. - + EVDO网络, revision A. EVDO,revision A. - + 1xRTT网络 1xRTT - + HSDPA网络 HSDPA - + HSUPA网络 HSUPA - + HSPA网络 HSPA - + 漫游: roam: - + Yes Sim - + No Não - + 数据连接状态: Status: - + 断开 Desligado - + 正在连接 conectando - + 已连接 Conectado - + 暂停 Suspenso - + 数据活动休眠状态: Dados ativo, estado suspenso : - + 活动,但无数据发送和接收 Ativo, mas sen enviar / receber dados - + 活动,正在接收数据 Ativo, recebendo dados - + 活动,正在发送数据 Ativo enviando ddos - + 活动,正在接收和发送数据 Ativo, enviando e recebendo dados - + 休眠状态 Modo suspenso - + 信号强度: Nível de sinal: - + DNS Address Endereço DNS - + Set APN Info Config APN - + User Usuario - + Type Tipo - + Server Server - + Port Porta - + Proxy Proxy - + MMS Port Porta - + MMS Proxy Proxy - - + + SetSwitchSimData Selec SIM - - + + ContrFlightMode Selec modo avião - - + + GetFlightModeState Ler estado modo avião @@ -3110,8 +3110,8 @@ - - + + Success @@ -3128,45 +3128,45 @@ DevicePanel - + All ALL Todos - + Online Online Online - + Refresh Refresh Atializar - - + + Specify IP Specify IP Definir IP - - - - + + + + Current Screen Display atual - - + + none none @@ -3202,9 +3202,9 @@ - - - + + + Player Version Versão do player @@ -3219,145 +3219,145 @@ Obtendo info - + Specify IP list Definir IP - + Search Procurar - - + + Attention Atenção - - + + Please input IP address! Entre com endereço IP! - + Cancel Cancelar - + Screen ID ID do display - + Screen Size Tamanho do display - + Screenshot Capturar tela - - + + On Ligado - - + + Off Desligado - + Brightness Adj. Brilho Adj. - + Power Control Controle de energia - + Net Config Config de rede - + Time Sync Hora Sinc - + Video source Entrada video - + Password Senha - + Advanced Avançado - + Volume Adj. Volume - + Test Teste - - + + Multi screen operation Operação de multi display - - + + selected num Selecionar numero - - + + Clear Limpar - + More Info Mais Info - + Alias Apelido - + Screen Brightness Brilho do display - + Power Status Estatus de funcionam - + Security encriptação @@ -3367,28 +3367,28 @@ Obter - - + + Error Erro - + Input password Introduzir a senha - + VerifyPassword Verifique a senha - + Tip Info Dica - + password is wrong A senha esta errada @@ -3720,74 +3720,74 @@ EEnviron - - + - + - + + north north - - + + east leste - - + + south sul - - + + west west @@ -3817,83 +3817,87 @@ Direção do vento + Pressure - Pressão + Pressão + Rainfall - Chuva + Chuva + Radiation - Radiação + Radiação + Beam - Luminosa + Luminosa - + Basic Properties Basic properties - + Title Titulo - + Compensation Compensação - + Left Esquerda - + Center Centro - + Right Direita - + Single scroll Rolar simples - + Speed Velocidade - + ms/pixel ms/pixel - + Back Color Cor fundo - + Play Properties Propriedades - + Play Duration Duração - + s s @@ -4060,8 +4064,8 @@ - Alpha_In - ALPHA_IN + Alpha In + @@ -4085,27 +4089,27 @@ - Zoom in + Zoom In ZOOM_IN - Zoom in to left_bottom + Zoom In to left_bottom ZOOM_IN_esquerda_inferior - Zoom in to left_top + Zoom In to left_top ZOOM_IN_esquerda superior - Zoom in to right_top + Zoom In to right_top ZOOM_IN_direita superior - Zoom in to right bottom + Zoom In to right bottom ZOOM_IN_direita inferior @@ -4495,22 +4499,22 @@ EleTimer - + day Dias - + hour Horas - + min Mins - + sec Segs @@ -4586,7 +4590,7 @@ ImgDlg - + Screenshot Captura da tela @@ -4637,50 +4641,50 @@ MainWindow - + Language Idioma - + Help Ajuda - + Check for updates Checar atualizações - + firmware manager Gerenciador Firmware - + Preferences Preferencias - - + + Info Info - - - + + + About Sobre - + Setting Config @@ -4731,8 +4735,8 @@ - Width Split - + Ultra-Long Screen Split + Dividir o Ecrã Ultralongo @@ -4767,47 +4771,47 @@ - + Downloading updates Atualizando - + Error Erro - + Device Painéis - + Program Editor - + Control Config - + Lora Screen Display LORA - + Check card Detectar - + Tip Info Info - + RestoreLedCardIpByUdpTip Esta operação irá fixar todos os painéis na LAN que não estão na mesma faixa de IP do seu PC. Atenção! @@ -5054,17 +5058,17 @@ PlayWin - + Move to Top Left Mover superior esquerdo - + Set Position Config posição - + Close Fechar @@ -5072,12 +5076,12 @@ PlayerBackSendThread - + Open file failed Abrir aqrquivo - + Read file failed Ler arquivo @@ -5098,230 +5102,240 @@ ProgCreateDlg - + Resolution Resolução - + Solution Information ID - + Solution Name Nome - + Width Largura - + Height Altura - + Remarks Observações - - 每段打折宽度 (用空格分隔) - Largura de cada parte + + Ultra-Long Screen Split + Dividir o Ecrã Ultralongo + + + + Part Width + Largura da Parte ProgEditorWin - + Save Salvar - + Setting Configuração - + Text Texto - + Photo Foto - + Video Video - + Gif Gif - + Clock Relógio - + Analog Clock Relógio analogico - + Environment Monitoramento ambiente - + Web Web page - + MuliContentWindow Janela para varias midias - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; Nesta janela, podem ser adicionados varios tipos de midia, sendo apresentados de acordo com a ordem da lista - + Timer Timer - - Demo Video - Demo - - - + Play Tocar - + Stop Parar - + Publish Publicar - - - + + + Select File Selecionar arquivo - + program Programa - + Add page Adicionar pag - + Copy page Copiar pag - + Delete page Deletar pag - - + + Tip Info Info - + Are you sure you want to delete this program page? Você quer deletar esta pagina? - + Move up Mover para cima - + Move down Mover para baixo - + widget properties Propriedade - + Page properties Propriedades do programa - + Do you want to save the modifications? Você quer salvar esta modificação? - + Create Dir failed Criação falhou - + Saving... Salvando... - + Success Successo - + Convertering Convertendo - + + Demos + + + + + Open Demo + + + + Generate preview data Gerar dados de visualização - - - + + + Error Erro - + Rename fail when saving Falha em renomear - + Remove Recursively fail when saving Falha ao remover @@ -5329,124 +5343,124 @@ ProgPanel - - + + New Novo - - + + Edit Editar - - + + Delete Deletar - - - + + + Import Importar - - - + + + Export Exportar - - + + Send Enviar - + USB Update - + Publish Publicar - + Name Nome - - + + Choose Directory Escolha o diretorio - + Tip Dica - + The imported directory is already in the working directory, so there is no need to import it again! Este aquivo ja foi importado, não precisa realizar novamente! - + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? :Arquivo ja criado.Você quer sobrescrever? - - + + Play Tocar - - + + Stop Parar - + Resolution Resolução - + File Size Tamanho do arquivo - + Last Modify Ultima modificação - + Program name conflicted Conflito de nome - + Warning Aviso - + You will delete the selected solution(s),are you sure? Você quer deletar este arquivo? - - + + Tip Info Info @@ -5472,7 +5486,7 @@ QAbstractSocket - + Socket operation timed out @@ -5490,7 +5504,7 @@ Digite a senha - + Error Erro @@ -5531,17 +5545,17 @@ SendProgThread - + Program is empty Programa em branco - + Open file failed Falaha ao abrir - + Read file failed Ler arquivo com falha @@ -5565,32 +5579,32 @@ Atualizar - + Online Online - + Screen Size Tamanho do display - + Alias Apelido - + Security Encriptado - + Progress Progresso - + Remarks Observações @@ -5615,17 +5629,17 @@ Verifique a senha - + Tip Info Info - + password is wrong A senha esta errada - + All Todos @@ -5648,12 +5662,12 @@ Atualizar - + Uninstall Desinstalar - + check running state Checando estatus @@ -5663,37 +5677,37 @@ Selecionar FPGA - + Installing Instalando - + Refresh Atualizar - + Online Online - + Security Encriptação - + Progress Progresso - + State Estado - + All Todos @@ -5736,7 +5750,7 @@ - + Tip Dica @@ -5752,142 +5766,142 @@ - + Downloading Online File Atualizando arquivo - - - - - + + + + + Error Erro - + Online file is empty Arquivo em branco - + File is empty - + Uploading Baixando - + Upload error Erro ao atualizar - + Don't power off during this process Desligou durante o processo - + Install error Erro de instalação - - + + Install Success Sucesso - + Reminder Lembrete - + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! Desinstalar o programa pode deixar o painel offline, perder as configurações e ficar com tela preta. Cuidado! - + Do you want to continue? Continuar? - + Uninstalling Desinstalando... - + Uninstall error Erro ao desinstalar - + Uninstall success Sucesso - + Check apk running status Checar APK estatus - + Check error Erro ao checar - + Running Funcionando - + Not running Parado - + Input password Introduzir a senha - + VerifyPassword Verifique a senha - + Tip Info Dica - + password is wrong A senha esta errada - + Alias Apelido - + Same version, needn't update A mesma versão, não é necessária actualização - + Install Failed A instalação falhou - + The encrypted control card can be upgraded directly O upograde pode ser realizado automaticamente diff --git a/LedOK/ts/app_zh_CN.ts b/LedOK/ts/app_zh_CN.ts index 7b2f481..43f9ba6 100644 --- a/LedOK/ts/app_zh_CN.ts +++ b/LedOK/ts/app_zh_CN.ts @@ -39,8 +39,8 @@ - Please enter a password with more than 6 characters - 请输入超过6个字符的密码 + Please enter a password with more than 3 characters + 请输入超过 3 个字符的密码 @@ -56,156 +56,156 @@ CtrlAdvancedPanel - + Advanced 高级设置 - + Screen Width(pixel) 屏幕宽(像素) - + Width - - + + Height - - - - + + + + + + - - - - - - - + + + + + + - + - - - + + Set 设置 - + Alias 别名 - + Web Server Address: Web服务器地址: - + MCU Uploading 正在上传单片机 - + Setting 正在设置 - + Traffic screen settings 交通屏设置 - + Setting protocol ... 正在设置协议 ... - + Set protocol 设置协议 - + Getting protocol ... 正在回读协议 ... - + Get protocol 回读协议 - - + + Port 端口 - + Realtimer Server Address: Realtimer地址: - + Firmware Management 固件管理 - + update or uninstall 更新或卸载 - + Clear 清空 - + Check Apk 检查Apk - + Uninstall 卸载 - + Running check 运行状态监测 - + Restart 重启 - + Check Log 查看日志 - + Start LedSet4 使用 LedSet4.0 配置LED模组(Apk Display2.0以上版本) - + Open ADB 打开ADB调试功能 - + Post Custom JSON Post Custom JSON @@ -215,7 +215,7 @@ - + Clear Program 清除节目 @@ -225,66 +225,66 @@ - + Config 配置 - + Refresh 刷新 - + Restore to default 恢复默认值 - + Taxi top screen configuration 车顶有无客电平配置 - - + + Service:High Out of service:Low 有客:高电平 无客:低电平 - - + + Service:Low Out of service:High 有客:低电平 无客:高电平 - + Binding *.ic account indentity voucher 绑定taxihub平台用户身份凭证 - + Rotate 旋转 - + Min brightness 最低亮度 - - - + + + Readback 回读 - + Send 发送 - + Max brightness 最高亮度 @@ -296,20 +296,20 @@ - - - - + + + + Success 成功 - + Compant ID: 公司ID: - + Compant ID 公司ID @@ -382,28 +382,28 @@ 监测APK运行状态 - - + + OpenAdb 打开ADB调试功能 - + indentity voucher (*.ic) 身份凭证(*.ic) - - - + + + + - InvokeTaxiAppFunction 绑定证书 - - + + AliIotSetting @@ -434,16 +434,16 @@ 正在清除节目 - - + + Timeout 超时 - - + + Failed 失败 @@ -455,53 +455,53 @@ - - - - - - - - - - - + + + + + + + + + + + Error 错误 - + Setting Timing Reboot 正在设置定时重启 - + Set Timing Reboot 设置定时重启 - + Getting Timing Reboot 正在获取定时重启 - + Get Timing Reboot 获取定时重启 - + totalResolution 包括行场数的分辨率 - + strCurDisplayResolution 当前显示屏分辨率 - - + + File not exist 文件不存在 @@ -513,7 +513,7 @@ - + Get Player State 获取播放器状态 @@ -534,368 +534,368 @@ 是否继续? - - + + Cannot Open File 文件打开失败 - + Uploading 正在上传 - + Update 更新 - - + + Set Display Mode 设置显示模式 - - + + Get Display Mode 获取显示模式 - - + + Set Screen Offset 设置屏幕偏移 - - + + Get Screen Offset 获取屏幕偏移 - + Open file Failed 文件打开失败 - + Setting Wallpaper 正在设置系统桌面背景 - - + + Set Wallpaper 设置系统桌面背景 - + System Updating 系统升级中 - - + + System Update 系统升级 - + Getting MCU Version 正在获取单片机版本 - - + + MCU Version 单片机版本 - + Select File 选择文件 - + Setting player background 正在设置播放器背景 - - + + Set player background 设置播放器背景 - + Clearing player background 正在清除播放器背景 - - - - - - - - + + + + + + + + Clear player background 清除播放器背景 - - + + GetScreenRotation 获取屏幕旋转 - - - + + + Charging Station 充电桩 - + Setting Baud Rate 正在设置波特率 - + Set Baud Rate 设置波特率 - + Getting Baud Rate 正在获取波特率 - + Get Baud Rate 获取波特率 - - + + Text is empty 文本为空 - - + + Json Parse Error - - + + Json isn't an Object - + Info 信息 - + Setting card work mode ... 正在设置控制卡工作模式 ... - + Set card work mode 设置控制卡工作模式 - + Getting card work mode ... 正在回读控制卡工作模式 ... - + Get card work mode 回读控制卡工作模式 - + Input password 输入密码 - + Change Password 修改密码 - + Resolution Config 分辨率配置 - + Full screen 全屏 - + Part 局部 - + Display Mode 显示模式 - + Screen Position 屏幕位置 - + Offset 偏移 - + Hidden Settings 隐藏的设置 - + Click right button to hide 点击右键隐藏 - - + + Update MCU 更新单片机 - + Get MCU Version 获取单片机版本 - + Baud Config 波特率配置 - + Model 设备型号 - + Uart 串口节点 - + Baud 波特率 - - - + + + + - - - - + + + Get 获取 - + Timing Reboot 定时重启 - + Protocol 协议 - + Server 服务端 - + Client 客户端 - - + + SetScreenRotation 设置屏幕旋转 - - + + SetMinBrightness 设置最小的亮度值 - - + + SetMaxBrightness 设置亮度最大值 - - + + GetMinBrightness 获取亮度最小值 - - + + GetMaxBrightness 获取亮度最大值 - - + + Card work mode 控制卡工作模式 - - + + SetSpecialResolution 设置分辨率 - - + + GetSpecialResolution 读取分辨率 - - + + CleanDisplayScreenSize 恢复默认分辨率 - - + + SetHighForBusy 设置有无客电平 - - + + GetStateForBusy 获取有无客电平 @@ -928,59 +928,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + Tip 提示 @@ -997,41 +997,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 请先选择大屏幕 @@ -1046,7 +1046,7 @@ 请输入正确的高度像素值 - + Password is error 密码错误 @@ -1526,156 +1526,156 @@ CtrlNetworkPanel - + Wire Enther(RJ45) Configuration 有线网配置 - + DHCP - + Specify IP 指定IP - + IP Address IP地址 - + Gateway 网关 - + DNS Address DNS地址 + - - + Set 设置 + - - - + + Readback 回读 - + WIFI Configuration WiFi配置 - + WiFi Mode 使用WiFi - + Cellular Config 蜂窝数据配置 - + Enable Cellular Data 启用蜂窝数据 - + Get cellular network status information 获取蜂窝网络状态信息 - + Through the check status button 通过“获取状态”按钮可以自动匹配国家码,然后选择“运营商”可获取到相应的APN信息。 - + Set APN Info 设置APN信息 - + Country ID(mcc): 国家码(mcc): - - + + Carrier Name 运营商 - + APN(Required) APN(必填) - + Flight Mode 飞行模式 - + WiFi name WiFi名称 - - - + + + Password 密码 + - Input password 输入密码 - + Scan 扫描 - + Ap Mode 使用热点 - + OFF - + ON - + AP name 热点名称 - + Subnet mask 子网掩码 - + Input ap name 输入AP名称 @@ -1684,14 +1684,14 @@ - - - - - - - - + + + + + + + + Tip 提示 @@ -1700,13 +1700,13 @@ - - - - - - - + + + + + + + NoSelectedController 请先选择大屏幕 @@ -1762,14 +1762,14 @@ - - + + ConfigurationWiFi 配置WiFi - - + + IsPortableHotSpot 获取热点和WiFi模式 @@ -1779,45 +1779,45 @@ 扫描WiFi - - + + ConfigurationHotSpot 配置热点 - + success 成功 - + WifiName Wifi名称 - + ApName 热点名称 - - + + GetCurrentAPN 获取APN信息 - + GetSIMStatus 获取SIM状态 - - + + SetAPN 设置APN - + 状态: 状态: @@ -1827,260 +1827,260 @@ 错误 - + 未知 未知 - + 锁定状态,需要用户的PIN码解锁 锁定状态,需要用户的PIN码解锁 - + 锁定状态,需要用户的PUK码解锁 锁定状态,需要用户的PUK码解锁 - + 锁定状态,需要网络的PIN码解锁 锁定状态,需要网络的PIN码解锁 - + 就绪 就绪 - + no checked sim card 检测不到sim卡 - + 国家码: 国家码: - + 号码: 号码: - + 用户: 用户: - + 信号: 信号: - + 信号正常 信号正常 - + 不在服务区 不在服务区 - + 仅限紧急呼叫 仅限紧急呼叫 - + 射频已经关闭 射频已经关闭 - + 网络: 网络: - + 网络类型未知 未知 - + GPRS网络 GPRS - + EDGE网络 EDGE - + UMTS网络 UMTS - + CDMA网络,IS95A 或 IS95B. CDM - + EVDO网络, revision 0. EVDO,revision 0. - + EVDO网络, revision A. EVDO,revision A. - + 1xRTT网络 1xRTT - + HSDPA网络 HSDPA - + HSUPA网络 HSUPA - + HSPA网络 HSPA - + 漫游: 漫游: - + Yes - + No - + 数据连接状态: 数据连接状态: - + 断开 断开 - + 正在连接 正在连接 - + 已连接 已连接 - + 暂停 暂停 - + 数据活动休眠状态: 数据活动休眠状态: - + 活动,但无数据发送和接收 活动,但无数据发送和接收 - + 活动,正在接收数据 活动,正在接收数据 - + 活动,正在发送数据 活动,正在发送数据 - + 活动,正在接收和发送数据 活动,正在接收和发送数据 - + 休眠状态 休眠状态 - + 信号强度: - + User 用户 - + Type 类型 - + Server 服务端 - + Port 端口 - + Proxy 代理 - + MMS Port 彩信端口 - + MMS Proxy 彩信代理 - - + + SetSwitchSimData 设置4G/5G开关 - - + + ContrFlightMode 配置飞行模式 - - + + GetFlightModeState 获取飞行模式状态 @@ -3110,8 +3110,8 @@ - - + + Success @@ -3128,44 +3128,44 @@ DevicePanel - + All 总数 总数 - + Online 在线 在线 - + Refresh 刷新 刷新 - - - - + + + + Current Screen 当前屏幕 - - + + none - - + + Specify IP 指定IP 指定IP @@ -3202,9 +3202,9 @@ - - - + + + Player Version 播放器固件版本 @@ -3219,145 +3219,145 @@ 正在获取 - + Specify IP list 指定IP列表 - + Search 搜索 - - + + Attention 注意 - - + + Please input IP address! 请输入IP地址! - + Cancel 取消 - + Screen ID 屏幕ID - + Screen Size 屏幕像素 - + Alias 别名 - + Screenshot 回读画面 - - + + On - - + + Off - + Brightness Adj. 亮度调节 - + Power Control 电源控制 - + Net Config 网络配置 - + Time Sync 对时管理 - + Video source 同异步配置 - + Password 设置密码 - + Advanced 高级设置 - + Volume Adj. 音量调节 - + Test 测试 - - + + Multi screen operation 多屏操作 - - + + selected num 选中数目 - - + + Clear 清空 - + More Info 更多信息 - + Screen Brightness 屏幕亮度 - + Power Status 屏幕开关状态 - + Security 加密 @@ -3367,28 +3367,28 @@ 正在获取 - - + + Error 错误 - + Input password 输入密码 - + VerifyPassword 验证密码 - + Tip Info 提示 - + password is wrong 密码错误 @@ -3720,74 +3720,74 @@ EEnviron - - + - + - + + north - - + + east - - + + south - - + + west 西 @@ -3817,83 +3817,87 @@ 风向 + Pressure - 气压 + 气压 + Rainfall - 雨量 + 雨量 + Radiation - 辐射 + 辐射 + Beam - 光照强度 + 光照强度 - + Basic Properties 基本属性 - + Title 标题 - + Compensation 补偿 - + Left 靠左 - + Center 居中 - + Right 靠右 - + Single scroll 单行滚动 - + Speed 速度 - + ms/pixel 毫秒/像素 - + Back Color 背景色 - + Play Properties 播放方式 - + Play Duration 播放时长 - + s @@ -4060,7 +4064,7 @@ - Alpha_In + Alpha In 淡入 @@ -4085,27 +4089,27 @@ - Zoom in + Zoom In 放大 - Zoom in to left_bottom + Zoom In to left_bottom 左下角放大 - Zoom in to left_top + Zoom In to left_top 左上角放大 - Zoom in to right_top + Zoom In to right_top 右上角放大 - Zoom in to right bottom + Zoom In to right bottom 右下角放大 @@ -4495,22 +4499,22 @@ EleTimer - + day - + hour - + min - + sec @@ -4586,7 +4590,7 @@ ImgDlg - + Screenshot 屏幕截图 @@ -4637,50 +4641,50 @@ MainWindow - + Language 语言 - + Help 帮助 - + Check for updates 检查更新 - + firmware manager 固件管理 - + Preferences 偏好设置 - - + + Info 信息 - - - + + + About 关于 - + Setting 设置 @@ -4731,7 +4735,7 @@ - Width Split + Ultra-Long Screen Split 超长屏打折 @@ -4767,47 +4771,47 @@ - + Downloading updates 正在下载更新 - + Error 错误 - + Device 设备管理 - + Program 节目管理 - + Control 终端控制 - + Lora Screen 光影屏 - + Check card 一键找卡 - + Tip Info 提示 - + RestoreLedCardIpByUdpTip 该操作会把局域网内的所有与计算机IP不在同一网段的控制卡修复成固定IP,请谨慎操作! @@ -5054,17 +5058,17 @@ PlayWin - + Move to Top Left 移动到左上角 - + Set Position 设置位置 - + Close 关闭 @@ -5072,12 +5076,12 @@ PlayerBackSendThread - + Open file failed 文件读取失败 - + Read file failed 文件读取失败 @@ -5098,230 +5102,240 @@ ProgCreateDlg - + Resolution 分辨率 - + Solution Information 节目信息 - + Solution Name 节目名称 - + Width - + Height - + Remarks 备注 - - 每段打折宽度 (用空格分隔) - + + Ultra-Long Screen Split + 超长屏打折 + + + + Part Width + 打折宽度 ProgEditorWin - + Save 保存 - + Setting 设置 - + Text 文本 - + Photo 图片 - + Video 视频 - + Gif 动画 - + Clock 数字时钟 - + Analog Clock 模拟时钟 - + Environment 环境监测 - + Web 网页 - + MuliContentWindow 多素材窗口 - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; 该窗口中可以加入多个不同是节目素材,并按照加入列表的先后顺序播放 - + Timer 计时器 - - Demo Video - 测试视频 - - - + Play 播放 - + Stop 停止 - + Publish 发布 - - - + + + Select File 选择文件 - + program 节目列表 - + Add page 添加页面 - + Copy page 复制页面 - + Delete page 删除页面 - - + + Tip Info 提示 - + Are you sure you want to delete this program page? 确定要删除该节目页吗? - + Move up 向上移动一个页面 - + Move down 向下移动一个页面 - + widget properties 组件属性 - + Page properties 节目属性 - + Do you want to save the modifications? 是否保存修改? - + Create Dir failed 创建目录失败 - + Saving... 正在保存... - + Success 成功 - + Convertering 整理数据中 - + + Demos + 测试素材 + + + + Open Demo + 打开测试素材 + + + Generate preview data 生成预览数据 - - - + + + Error 错误 - + Rename fail when saving 重命名文件夹失败 - + Remove Recursively fail when saving @@ -5329,124 +5343,124 @@ ProgPanel - - + + New 新建 - - + + Edit 编辑 - - + + Delete 删除 - - - + + + Import 导入 - - - + + + Export 导出 - - + + Send 发送 - + Publish 发布 - + Name 名称 - - + + Choose Directory 选择目录 - + Tip 提示 - + The imported directory is already in the working directory, so there is no need to import it again! 该导入的目录已经在工作目录下,无需再次导入! - + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? :节目已存在。是否确实要覆盖现有节目? - - + + Play 播放 - - + + Stop 停止 - + Resolution 分辨率 - + File Size 文件大小 - + Last Modify 最后修改时间 - + USB Update USB更新 - + Program name conflicted 节目名称重复 - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否确认删除选中的节目? - - + + Tip Info 提示 @@ -5472,7 +5486,7 @@ QAbstractSocket - + Socket operation timed out @@ -5490,7 +5504,7 @@ 输入密码 - + Error 错误 @@ -5531,17 +5545,17 @@ SendProgThread - + Program is empty 节目为空 - + Open file failed 文件打开失败 - + Read file failed 文件读取失败 @@ -5565,32 +5579,32 @@ 刷新 - + Alias 别名 - + Online 在线 - + Screen Size 屏幕像素 - + Security 加密 - + Progress 进度 - + Remarks 备注 @@ -5615,17 +5629,17 @@ 验证密码 - + Tip Info 提示 - + password is wrong 密码错误 - + All 总数 @@ -5648,12 +5662,12 @@ 升级 - + Uninstall 卸载 - + check running state 检测运行状态 @@ -5663,42 +5677,42 @@ 选择FPGA文件 - + Installing 正在安装 - + Refresh 刷新 - + Alias 别名 - + Online 在线 - + Security 加密 - + Progress 进度 - + State 状态 - + All 总数 @@ -5741,7 +5755,7 @@ - + Tip 提示 @@ -5757,137 +5771,137 @@ - + Downloading Online File 正在下载在线文件 - - - - - + + + + + Error 错误 - + Online file is empty 在线文件为空 - + File is empty 文件为空 - + Uploading 正在上传 - + Upload error 上传错误 - + Don't power off during this process 这个过程请勿断电 - + Install error 安装错误 - - + + Install Success 安装成功 - + Reminder 提示 - + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! 提示:卸载此程序会导致平台掉线,找不到设备,配置参数丢失和黑屏问题,请谨慎卸载! - + Do you want to continue? 是否继续? - + Uninstalling 正在卸载 - + Uninstall error 卸载错误 - + Uninstall success 卸载成功 - + Check apk running status 监测APK运行状态 - + Check error 检查错误 - + Running 正在运行 - + Not running 没有运行 - + Input password 输入密码 - + VerifyPassword 验证密码 - + Tip Info 提示 - + password is wrong 密码错误 - + Same version, needn't update 相同版本, 不需要更新 - + Install Failed 安装失败 - + The encrypted control card can be upgraded directly 加密控制卡可以直接升级 diff --git a/LedOK/ts/app_zh_TW.ts b/LedOK/ts/app_zh_TW.ts index d42507b..32c4ec6 100644 --- a/LedOK/ts/app_zh_TW.ts +++ b/LedOK/ts/app_zh_TW.ts @@ -39,8 +39,8 @@ - Please enter a password with more than 6 characters - 請輸入超過6個字元的密碼 + Please enter a password with more than 3 characters + 請輸入超過 3 個字元的密碼 @@ -56,156 +56,156 @@ CtrlAdvancedPanel - + Advanced 高級設定 - + Screen Width(pixel) 螢幕寬(點數) - + Width - - + + Height - - - - + + + + + + - - - - - - - + + + + + + - + - - - + + Set 設定 - + Alias 別名 - + Web Server Address: Web伺服器地址: - + MCU Uploading 正在上傳單片機 - + Setting 正在設定 - + Traffic screen settings 交通屏設定 - + Setting protocol ... 正在設定協定 - + Set protocol 設定協定 - + Getting protocol ... 正在回讀協定 ... - + Get protocol 回讀協定 - - + + Port - + Realtimer Server Address: Realtimer地址: - + Firmware Management 固件管理 - + update or uninstall 更新或卸載 - + Clear 清空 - + Check Apk 檢查Apk - + Uninstall 卸載 - + Running check 運行狀態監測 - + Restart 重啓 - + Check Log 查看日誌 - + Start LedSet4 - + Open ADB 打開ADB調試功能 - + Post Custom JSON Post Custom JSON @@ -215,7 +215,7 @@ - + Clear Program 清除節目 @@ -225,66 +225,66 @@ - + Config 配寘 - + Refresh 檢測 - + Restore to default 恢復預設值 - + Taxi top screen configuration 車頂有無客電平配寘 - - + + Service:High Out of service:Low 有客:高電平無客:低電平 - - + + Service:Low Out of service:High 有客:低電平 無客:高電平 - + Binding *.ic account indentity voucher 綁定taxihub平臺用戶身份憑證 - + Rotate 旋轉 - + Min brightness 最低亮度 - - - + + + Readback 回讀 - + Send 發送 - + Max brightness 最高亮度 @@ -296,20 +296,20 @@ - - - - + + + + Success 成功 - + Compant ID: 公司ID: - + Compant ID 公司ID @@ -326,41 +326,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 請先選擇大螢幕 @@ -433,28 +433,28 @@ 監測APK運行狀態 - - + + OpenAdb 打開ADB調試功能 - + indentity voucher (*.ic) 身份憑證(*.ic) - - - + + + + - InvokeTaxiAppFunction 綁定證書 - - + + AliIotSetting @@ -485,16 +485,16 @@ 正在清除節目 - - + + Timeout 超時 - - + + Failed 失敗 @@ -506,53 +506,53 @@ - - - - - - - - - - - + + + + + + + + + + + Error 錯誤 - + Setting Timing Reboot 正在設定定時重啓 - + Set Timing Reboot 設定定時重啓 - + Getting Timing Reboot 正在獲取定時重啓 - + Get Timing Reboot 獲取定時重啓 - + totalResolution 行数を含む解像度 - + strCurDisplayResolution 當前顯示分辯率 - - + + File not exist 檔案不存在 @@ -564,7 +564,7 @@ - + Get Player State 獲取播放機狀態 @@ -585,368 +585,368 @@ 是否繼續? - - + + Cannot Open File 檔案打開失敗 - + Uploading 正在上傳 - + Update 更新 - - + + Set Display Mode 設定顯示模式 - - + + Get Display Mode 獲取顯示模式 - - + + Set Screen Offset 設定螢幕偏移 - - + + Get Screen Offset 獲取螢幕偏移 - + Open file Failed 檔案打開失敗 - + Setting Wallpaper 正在設定系統桌面背景 - - + + Set Wallpaper 設定系統桌面背景 - + System Updating 系統升級中 - - + + System Update 系統升級 - + Getting MCU Version 正在獲取單片機版本 - - + + MCU Version 單片機版本 - + Select File 選擇檔案 - + Setting player background 正在設定播放機背景 - - + + Set player background 設定播放機背景 - + Clearing player background 正在清除播放機背景 - - - - - - - - + + + + + + + + Clear player background 清除播放機背景 - - + + GetScreenRotation 獲取荧幕旋轉 - - - + + + Charging Station 充電樁 - + Setting Baud Rate 正在設定串列傳輸速率 - + Set Baud Rate 設定串列傳輸速率 - + Getting Baud Rate 正在讀取串列傳輸速率 - + Get Baud Rate 讀取串列傳輸速率 - - + + Text is empty + + + + Json Parse Error + + - Json Parse Error - - - - - Json isn't an Object - + Info 資訊 - + Setting card work mode ... 正在設定控制卡工作模式 ... - + Set card work mode 設定控制卡工作模式 - + Getting card work mode ... 正在回讀控制卡工作模式 ... - + Get card work mode 回讀控制卡工作模式 - + Input password 輸入密碼 - + Change Password 修改密碼 - + Resolution Config 分辯率配寘 - + Full screen 全屏 - + Part 局部 - + Display Mode 顯示模式 - + Screen Position 螢幕位置 - + Offset 偏移 - + Hidden Settings 隱藏的設定 - + Click right button to hide 點擊右鍵隱藏 - - + + Update MCU 更新單片機 - + Get MCU Version 獲取單片機版本 - + Baud Config 串列傳輸速率配寘 - + Model 設備型號 - + Uart 串口節點 - + Baud 串列傳輸速率 - - - + + + + - - - - + + + Get 讀取 - + Timing Reboot 定時重啓 - + Protocol 協定 - + Server 服務端 - + Client 用戶端 - - + + SetScreenRotation 設定螢幕旋轉 - - + + SetMinBrightness 設定最小的亮度值 - - + + SetMaxBrightness 設定亮度最大值 - - + + GetMinBrightness 獲取亮度最小值 - - + + GetMaxBrightness 獲取亮度最大值 - - + + Card work mode 控制卡工作模式 - - + + SetSpecialResolution 設定分辯率 - - + + GetSpecialResolution 讀取分辯率 - - + + CleanDisplayScreenSize 恢復默認分辯率 - - + + SetHighForBusy 設定有無客電平 - - + + GetStateForBusy 獲取有無客電平 @@ -979,59 +979,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + Tip 提示 @@ -1046,7 +1046,7 @@ 請輸入正確的高度點數值 - + Password is error 密碼錯誤 @@ -1531,156 +1531,156 @@ CtrlNetworkPanel - + Wire Enther(RJ45) Configuration 有線網配寘 - + DHCP - + Specify IP 指定IP - + IP Address IP地址 - + Gateway 閘道 - + DNS Address DNS地址 + - - + Set 設定 + - - - + + Readback 回讀 - + WIFI Configuration WiFi配寘 - + WiFi Mode 使用WiFi - + Cellular Config 蜂窩數據配寘 - + Enable Cellular Data 啟用蜂窩數據 - + Get cellular network status information 獲取蜂窩網絡狀態資訊 - + Through the check status button 通過“獲取狀態”按鈕可以自動匹配國家碼,然後選擇“運營商”可獲取到相應的APN資訊。 - + Set APN Info 設定APN資訊 - + Country ID(mcc): 国家码(mcc):國家碼(mcc): - - + + Carrier Name 運營商 - + APN(Required) APN(必填) - + Flight Mode 飛行模式 - + WiFi name WiFi名稱 - - - + + + Password 密碼 + - Input password 輸入密碼 - + Scan 掃描 - + Ap Mode 使用熱點 - + OFF - + ON - + AP name 熱點名稱 - + Subnet mask 子網路遮罩 - + Input ap name 輸入AP名稱 @@ -1689,14 +1689,14 @@ - - - - - - - - + + + + + + + + Tip 提示 @@ -1705,13 +1705,13 @@ - - - - - - - + + + + + + + NoSelectedController 請先選擇大螢幕 @@ -1767,14 +1767,14 @@ - - + + ConfigurationWiFi 配寘WiFi - - + + IsPortableHotSpot 獲取熱點和WiFi模式 @@ -1784,45 +1784,45 @@ 掃描WiFi - - + + ConfigurationHotSpot 配寘熱點 - + success 成功 - + WifiName Wifi名稱 - + ApName 熱點名稱 - - + + GetCurrentAPN 獲取APN資訊 - + GetSIMStatus 獲取SIM狀態 - - + + SetAPN 設定APN - + 状态: 狀態: @@ -1832,260 +1832,260 @@ 錯誤 - + 未知 未知 - + 锁定状态,需要用户的PIN码解锁 鎖定狀態,需要用戶的PIN碼解鎖 - + 锁定状态,需要用户的PUK码解锁 鎖定狀態,需要用戶的PUK碼解鎖 - + 锁定状态,需要网络的PIN码解锁 鎖定狀態,需要網絡的PIN碼解鎖 - + 就绪 就緒 - + no checked sim card 檢測不到sim卡 - + 国家码: 國家碼: - + 号码: 號碼: - + 用户: 用戶: - + 信号: 信号: - + 信号正常 訊號正常 - + 不在服务区 不在服務區 - + 仅限紧急呼叫 僅限緊急呼叫 - + 射频已经关闭 射頻已經關閉 - + 网络: 網絡: - + 网络类型未知 未知 - + GPRS网络 GPRS - + EDGE网络 EDGE - + UMTS网络 UMTS - + CDMA网络,IS95A 或 IS95B. CDM - + EVDO网络, revision 0. EVDO,revision 0. - + EVDO网络, revision A. EVDO,revision A. - + 1xRTT网络 1xRTT - + HSDPA网络 HSDPA - + HSUPA网络 HSUPA - + HSPA网络 HSPA - + 漫游: 漫遊: - + Yes - + No - + 数据连接状态: 數據連接狀態: - + 断开 斷開 - + 正在连接 正在連接 - + 已连接 已連接 - + 暂停 暫停 - + 数据活动休眠状态: 數據活動休眠狀態: - + 活动,但无数据发送和接收 活動,但無數據發送和接收 - + 活动,正在接收数据 活動,正在接收數據 - + 活动,正在发送数据 活動,正在發送數據 - + 活动,正在接收和发送数据 活動,正在接收和發送數據 - + 休眠状态 休眠狀態 - + 信号强度: 信號強度: - + User 用戶 - + Type 型態 - + Server 服務端 - + Port - + Proxy 代理 - + MMS Port 彩信埠 - + MMS Proxy 彩信代理 - - + + SetSwitchSimData 設定4G/5G開關 - - + + ContrFlightMode 配寘飛行模式 - - + + GetFlightModeState 獲取飛行模式狀態 @@ -3115,8 +3115,8 @@ - - + + Success @@ -3133,43 +3133,43 @@ DevicePanel - + All 總數 - + Online 在线 線上 - + Refresh 檢測 - - + + Specify IP 指定IP 指定IP - - - - + + + + Current Screen 当前屏幕 - - + + none @@ -3205,9 +3205,9 @@ - - - + + + Player Version 播放機固件版本 @@ -3222,145 +3222,145 @@ 正在獲取 - + Specify IP list 指定IP清單 - + Search 蒐索 - - + + Attention 注意 - - + + Please input IP address! 請輸入IP地址! - + Cancel 取消 - + Screen ID 螢幕ID - + Screen Size 螢幕點數 - + Alias 別名 - + Screenshot 回讀畫面 - - + + On - - + + Off - + Brightness Adj. 亮度調節 - + Power Control 電源控制 - + Net Config 網絡配寘 - + Time Sync 對時管理 - + Video source 同異步配寘 - + Password 設寘密碼 - + Advanced 高級設定 - + Volume Adj. 音量調節 - + Test 測試 - - + + Multi screen operation 多屏操作 - - + + selected num 選中數目 - - + + Clear 清空 - + More Info 更多資訊 - + Screen Brightness 螢幕亮度 - + Power Status 螢幕開關狀態 - + Security 加密 @@ -3370,28 +3370,28 @@ 正在獲取 - - + + Error 錯誤 - + Input password 輸入密碼 - + VerifyPassword 驗證密碼 - + Tip Info 提示 - + password is wrong 密碼錯誤 @@ -3723,74 +3723,74 @@ EEnviron - - + - + - + + north - - + + east - - + + south - - + + west 西 @@ -3820,83 +3820,87 @@ 風向 + Pressure - 氣壓 + 氣壓 + Rainfall - 雨量 + 雨量 + Radiation - 輻射 + 輻射 + Beam - 光照強度 + 光照強度 - + Basic Properties 基本屬性 - + Title 標題 - + Compensation 補償 - + Left 靠左 - + Center 居中 - + Right 靠右 - + Single scroll 單行滾動 - + Speed 速度 - + ms/pixel 毫秒/點數 - + Back Color 背景色 - + Play Properties 播放管道 - + Play Duration 播放時長 - + s @@ -4063,7 +4067,7 @@ - Alpha_In + Alpha In 淡入 @@ -4088,27 +4092,27 @@ - Zoom in + Zoom In 放大 - Zoom in to left_bottom + Zoom In to left_bottom 左下角放大 - Zoom in to left_top + Zoom In to left_top 左上角放大 - Zoom in to right_top + Zoom In to right_top 右上角放大 - Zoom in to right bottom + Zoom In to right bottom 右下角放大 @@ -4498,22 +4502,22 @@ EleTimer - + day - + hour - + min - + sec @@ -4589,7 +4593,7 @@ ImgDlg - + Screenshot 螢幕截圖 @@ -4640,50 +4644,50 @@ MainWindow - + Language 語言 - + Help 幫助 - + Check for updates 檢查更新 - + firmware manager 固件管理 - + Preferences 偏好設定 - - + + Info 資訊 - - - + + + About 關於 - + Setting 設定 @@ -4734,7 +4738,7 @@ - Width Split + Ultra-Long Screen Split 超長屏打折 @@ -4770,47 +4774,47 @@ - + Downloading updates 下載更新 - + Error 錯誤 - + Device 設備管理 - + Program 節目管理 - + Control 終端控制 - + Lora Screen 光影屏 - + Check card 一鍵找卡 - + Tip Info 提示 - + RestoreLedCardIpByUdpTip 該操作會把局域網內的所有與電腦IP不在同一網段的控制卡修復成固定IP,請謹慎操作! @@ -5057,17 +5061,17 @@ PlayWin - + Move to Top Left 移動到左上角 - + Set Position 設定位置 - + Close 關閉 @@ -5075,12 +5079,12 @@ PlayerBackSendThread - + Open file failed 檔案打開失敗 - + Read file failed 檔案讀取失敗 @@ -5101,230 +5105,240 @@ ProgCreateDlg - + Resolution 分辯率 - + Solution Information 節目資訊 - + Solution Name 節目名稱 - + Width - + Height - + Remarks 備註 - - 每段打折宽度 (用空格分隔) - 每段讓利寬度(用空格分隔) + + Ultra-Long Screen Split + 超長屏打折 + + + + Part Width + 打折寬度 ProgEditorWin - + Save 保存 - + Setting 設定 - + Text 文字 - + Photo 圖片 - + Video 視頻 - + Gif 動畫 - + Clock 數位時鐘 - + Analog Clock 圓形時鐘 - + Environment 環境監測 - + Web 網頁 - + MuliContentWindow 多素材視窗 - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; 該視窗中可以加入多個不同是節目素材,並按照加入列表的先後順序播放 - + Timer 計時器 - - Demo Video - 測試視頻 - - - + Play 播放 - + Stop 停止 - + Publish 發佈 - - - + + + Select File 選擇檔案 - + program 節目清單 - + Add page 添加頁面 - + Copy page 複製頁面 - + Delete page 删除頁面 - - + + Tip Info 提示 - + Are you sure you want to delete this program page? 確定要删除該節目頁嗎? - + Move up 向上移動一個頁面 - + Move down 向下移動一個頁面 - + widget properties 組件内容 - + Page properties 節目内容 - + Do you want to save the modifications? 是否保存修改? - + Create Dir failed 創建目錄失敗 - + Saving... 正在保存… - + Success 成功 - + Convertering 整理數據中 - + + Demos + 測試素材 + + + + Open Demo + 打開測試素材 + + + Generate preview data 生成預覽數據 - - - + + + Error 錯誤 - + Rename fail when saving - + Remove Recursively fail when saving @@ -5332,124 +5346,124 @@ ProgPanel - - + + New 新建 - - + + Edit 編輯 - - + + Delete 删除 - - - + + + Import 導入 - - - + + + Export 匯出 - - + + Send 發送 - + Publish 發佈 - + Name 名稱 - - + + Choose Directory 選擇目錄 - + Tip 提示 - + The imported directory is already in the working directory, so there is no need to import it again! 該導入的目錄已經在工作目錄下,無需再次導入! - + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? :節目已存在。是否確實要覆蓋現有節目? - - + + Play 播放 - - + + Stop 停止 - + Resolution 分辯率 - + File Size 文件大小 - + Last Modify 最後修改時間 - + USB Update USB更新 - + Program name conflicted 節目名稱重複 - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否確認删除選中的節目? - - + + Tip Info 提示 @@ -5475,7 +5489,7 @@ QAbstractSocket - + Socket operation timed out @@ -5493,7 +5507,7 @@ 輸入密碼 - + Error 錯誤 @@ -5534,17 +5548,17 @@ SendProgThread - + Program is empty 節目為空 - + Open file failed 檔案打開失敗 - + Read file failed 檔案讀取失敗 @@ -5568,32 +5582,32 @@ 檢測 - + Alias 別名 - + Online 線上 - + Screen Size 螢幕點數 - + Security 加密 - + Progress 進度 - + Remarks 備註 @@ -5618,17 +5632,17 @@ 驗證密碼 - + Tip Info 提示 - + password is wrong 密碼錯誤 - + All 總數 @@ -5651,12 +5665,12 @@ 陞級 - + Uninstall 卸載 - + check running state 檢測運行狀態 @@ -5666,42 +5680,42 @@ 選擇FPGA檔案 - + Installing 正在安裝 - + Refresh 檢測 - + Alias 別名 - + Online 線上 - + Security 加密 - + Progress 進度 - + State 陳述 - + All 總數 @@ -5744,7 +5758,7 @@ - + Tip 提示 @@ -5760,137 +5774,137 @@ - + Downloading Online File 正在下載線上檔案 - - - - - + + + + + Error 錯誤 - + Online file is empty 線上檔案為空 - + File is empty 檔案為空 - + Uploading - + Upload error 上傳錯誤 - + Don't power off during this process 這個過程請勿斷電 - + Install error 安裝錯誤 - - + + Install Success 安裝成功 - + Reminder 提示 - + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! 提示:卸載此程式會導致平臺掉線,找不到設備,配寘參數遺失和黑屏問題,請謹慎卸載! - + Do you want to continue? 是否繼續? - + Uninstalling 正在卸載 - + Uninstall error 卸載錯誤 - + Uninstall success 卸載成功 - + Check apk running status 監測APK運行狀態 - + Check error 檢查錯誤 - + Running 正在運行 - + Not running 沒有運行 - + Input password 輸入密碼 - + VerifyPassword 驗證密碼 - + Tip Info 提示 - + password is wrong 密碼錯誤 - + Same version, needn't update 相同版本,不需要更新 - + Install Failed 安裝失敗 - + The encrypted control card can be upgraded directly 加密控制卡可以直接陞級