From 5f89e6d8b8316f3173956b830bb0c59a3dc8e6b2 Mon Sep 17 00:00:00 2001 From: gangphon Date: Fri, 16 Dec 2022 15:08:53 +0800 Subject: [PATCH] =?UTF-8?q?ledset=E5=A2=9E=E5=8A=A0=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ledset/basewin.cpp | 14 +- ledset/brightwin.cpp | 6 +- ledset/expertscreenconnwin.cpp | 70 +- ledset/expertscreenconnwin.h | 3 + ledset/expertsmartpointsetwin.cpp | 231 +++--- ledset/expertsmartpointsetwin.h | 7 +- ledset/expertwin.cpp | 754 ++++++++++++++---- ledset/expertwin.h | 51 ++ ledset/globalfunc.cpp | 119 +++ ledset/globalfunc.h | 9 + ledset/imgs/checkbox-check.png | Bin 0 -> 254 bytes ledset/imgs/checkbox-un.png | Bin 0 -> 962 bytes ledset/imgs/close.png | Bin 0 -> 2282 bytes ledset/imgs/macos-minimize.png | Bin 0 -> 745 bytes ledset/imgs/menu-squared-2.png | Bin 0 -> 349 bytes ledset/imgs/negative_minimize_icon_208693.png | Bin 0 -> 2182 bytes ledset/imgs/vcsconflicting_93497.png | Bin 0 -> 2981 bytes ledset/imgs/xbox-menu.png | Bin 0 -> 2998 bytes ledset/ledset.pro | 2 + ledset/main.cpp | 77 +- ledset/mainwin.cpp | 170 +++- ledset/mainwin.h | 27 + ledset/pcapwin.cpp | 175 +--- ledset/pcapwin.h | 6 +- ledset/res.qrc | 24 +- ledset/table.cpp | 9 +- ledset/table.h | 138 ++-- ledset/translations/app_en.ts | 676 +++++++++++++++- ledset/videowin.cpp | 165 ++-- ledset/videowin.h | 12 +- 30 files changed, 2042 insertions(+), 703 deletions(-) create mode 100644 ledset/globalfunc.cpp create mode 100644 ledset/globalfunc.h create mode 100644 ledset/imgs/checkbox-check.png create mode 100644 ledset/imgs/checkbox-un.png create mode 100644 ledset/imgs/close.png create mode 100644 ledset/imgs/macos-minimize.png create mode 100644 ledset/imgs/menu-squared-2.png create mode 100644 ledset/imgs/negative_minimize_icon_208693.png create mode 100644 ledset/imgs/vcsconflicting_93497.png create mode 100644 ledset/imgs/xbox-menu.png diff --git a/ledset/basewin.cpp b/ledset/basewin.cpp index 23e2a87..d78557f 100644 --- a/ledset/basewin.cpp +++ b/ledset/basewin.cpp @@ -20,12 +20,18 @@ BaseWinBase::BaseWinBase(QWidget *that) : that(that) { QBoxLayout *BaseWinBase::addBtns(QBoxLayout *hBox) { if(hBox->count()==0) hBox->addStretch(); - auto btn = new QPushButton("--"); - btn->setProperty("ss", "min"); + auto btn = new QPushButton(""); + btn->setIcon(QIcon(":/imgs/macos-minimize.png")); + btn->setIconSize(QSize(20,20)); + btn->setStyleSheet("padding: 1;border:none;"); + //btn->setProperty("ss", "min"); that->connect(btn, &QPushButton::clicked, that, &BaseWin::showMinimized); hBox->addWidget(btn); - btn = new QPushButton("X"); - btn->setProperty("ss", "close"); + btn = new QPushButton(""); + btn->setIcon(QIcon(":/imgs/close.png")); + btn->setIconSize(QSize(20,20)); + btn->setStyleSheet("padding: 1;border:none;"); + //btn->setProperty("ss", "close"); that->connect(btn, &QPushButton::clicked, that, &BaseWin::close); hBox->addWidget(btn); return hBox; diff --git a/ledset/brightwin.cpp b/ledset/brightwin.cpp index 3b0b890..972cbb6 100644 --- a/ledset/brightwin.cpp +++ b/ledset/brightwin.cpp @@ -12,7 +12,7 @@ BrightWin::BrightWin(QWidget *parent) : BaseWin{parent} { setWindowModality(Qt::WindowModal); setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle("亮度控制"); + setWindowTitle(tr("亮度控制")); resize(620, 700); auto vBox = new QVBoxLayout(center); @@ -74,7 +74,7 @@ BrightWin::BrightWin(QWidget *parent) : BaseWin{parent} { hBox = new QHBoxLayout(); hBox->addStretch(); - auto btnSave = new QPushButton("固化"); + auto btnSave = new QPushButton(tr("固化")); btnSave->setMinimumWidth(80); hBox->addWidget(btnSave); @@ -157,7 +157,7 @@ BrightWin::BrightWin(QWidget *parent) : BaseWin{parent} { hBox = new QHBoxLayout(); hBox->addStretch(); - btnSave = new QPushButton("固化"); + btnSave = new QPushButton(tr("固化")); btnSave->setMinimumWidth(80); hBox->addWidget(btnSave); diff --git a/ledset/expertscreenconnwin.cpp b/ledset/expertscreenconnwin.cpp index ebd2c36..4bfec97 100644 --- a/ledset/expertscreenconnwin.cpp +++ b/ledset/expertscreenconnwin.cpp @@ -9,7 +9,8 @@ #include #include #include - +#include +#define M_PI 3.14159265358979323846 QColor cardColors[] {QColor(0xff2222), QColor(0xffaa00), QColor(0x00bb00), QColor(0x00bbcc), QColor(0x0044ff), QColor(0xffffff), QColor(0xffff00)}; ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { @@ -28,7 +29,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { auto vvv = new QVBoxLayout(leftWgt); vvv->setContentsMargins(0,0,0,0); - auto gBox = new QGroupBox("起始位置"); + auto gBox = new QGroupBox(tr("起始位置")); vvv->addWidget(gBox); auto fdX = new QSpinBox; @@ -36,14 +37,14 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { { auto hhh = new QHBoxLayout(gBox); - auto lb = new QLabel("X坐标: "); + auto lb = new QLabel(tr("X坐标: ")); hhh->addWidget(lb); fdX->setRange(0, 99999); fdX->setValue(0); hhh->addWidget(fdX); - lb = new QLabel("Y坐标: "); + lb = new QLabel(tr("Y坐标: ")); hhh->addWidget(lb); fdY->setRange(0, 99999); @@ -51,7 +52,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { hhh->addWidget(fdY); } - gBox = new QGroupBox("接收卡设置"); + gBox = new QGroupBox(tr("接收卡设置")); vvv->addWidget(gBox); auto fdCardColNum = new QSpinBox; @@ -61,7 +62,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { auto hhh = new QHBoxLayout; vBox->addLayout(hhh); - auto lb = new QLabel("卡列数: "); + auto lb = new QLabel(tr("卡列数: ")); hhh->addWidget(lb); fdCardColNum->setRange(0, 9999); @@ -71,7 +72,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { // }); hhh->addWidget(fdCardColNum); - lb = new QLabel("卡行数: "); + lb = new QLabel(tr("卡行数: ")); hhh->addWidget(lb); fdCardRowNum->setRange(0, 9999); @@ -81,7 +82,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { vBox->addLayout(hhh = new QHBoxLayout); - lb = new QLabel("卡宽度: "); + lb = new QLabel(tr("卡宽度: ")); hhh->addWidget(lb); fdCardWidth = new QSpinBox; @@ -89,7 +90,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { fdCardWidth->setValue(128); hhh->addWidget(fdCardWidth); - lb = new QLabel("卡高度: "); + lb = new QLabel(tr("卡高度: ")); hhh->addWidget(lb); fdCardHeight = new QSpinBox; @@ -98,7 +99,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { hhh->addWidget(fdCardHeight); } - gBox = new QGroupBox("网口选择"); + gBox = new QGroupBox(tr("网口选择")); vvv->addWidget(gBox); auto hhh = new QHBoxLayout(gBox); @@ -115,7 +116,7 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { fdNet->addButton(bn, i); } - gBox = new QGroupBox("快速串线:"); + gBox = new QGroupBox(tr("快速串线:")); gBox->setStyleSheet("QToolButton {border: none; }"); vvv->addWidget(gBox); { @@ -169,14 +170,14 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { vvv->addLayout(hhh = new QHBoxLayout); - auto bnRefresh = new QPushButton("重新开始"); + auto bnRefresh = new QPushButton(tr("重新开始")); connect(bnRefresh, &QPushButton::clicked, this, [this] { table->clearContents(); for(int i=0; iaddWidget(bnRefresh); - auto bnBack = new QPushButton("后退"); + auto bnBack = new QPushButton(tr("后退")); connect(bnBack, &QPushButton::clicked, this, &ExpertScreenConnWin::connBack); hhh->addWidget(bnBack); @@ -189,8 +190,10 @@ ExpertScreenConnWin::ExpertScreenConnWin(QWidget *parent) : QWidget{parent} { table->setEditTriggers(QAbstractItemView::NoEditTriggers); table->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); table->horizontalHeader()->setDefaultSectionSize(90); + table->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); table->verticalHeader()->setDefaultAlignment(Qt::AlignCenter); table->verticalHeader()->setDefaultSectionSize(90); + table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); table->verticalHeader()->setMinimumWidth(30); table->setSelectionMode(QTableWidget::NoSelection); connect(table, &QTableWidget::currentCellChanged, this, &ExpertScreenConnWin::conn); @@ -205,9 +208,11 @@ void ExpertScreenConnWin::conn(int row, int column) { if(item) return; auto netIdx = fdNet->checkedId(); netss[netIdx].append(QPoint(column, row)); - item = new QTableWidgetItem("网口: "+QString::number(netIdx+1)+"\n接收卡: "+QString::number(netss[netIdx].size())+"\n宽度: "+QString::number(fdCardWidth->value())+"\n高度: "+QString::number(fdCardHeight->value())); + item = new QTableWidgetItem("网口: "+QString::number(netIdx+1)+"\n"+tr("接收卡: ")+QString::number(netss[netIdx].size())+"\n"+tr("宽度: ")+QString::number(fdCardWidth->value())+"\n高度: "+QString::number(fdCardHeight->value())); auto color = cardColors[netIdx % (sizeof(cardColors)/sizeof(cardColors[0]))]; - item->setForeground(color); + item->setForeground(QColor(255,255,255)); + color.setAlpha(100); + item->setBackground(color); item->setData(Qt::UserRole, netIdx); table->setItem(row, column, item); table->update(); @@ -227,13 +232,18 @@ void CardTable::paintEvent(QPaintEvent *event) { for(int i=0; inetss.size(); i++) { auto size = win->netss[i].size(); if(size < 2) continue; - painter.setPen(QPen(cardColors[i % (sizeof(cardColors)/sizeof(cardColors[0]))], 2)); + QColor a=cardColors[i % (sizeof(cardColors)/sizeof(cardColors[0]))]; + //QColor b=QColor(255-a.red(),255-a.green(),255-a.blue(),200); + QColor b=QColor(a.red(),a.green(),a.blue(),255); + + QPen pen=QPen(b); + int off = 45 + (i+1)/2 * (i%2 ? -4 : 4); for(int j=1; jnetss[i][j-1]; auto point2 = win->netss[i][j]; - painter.drawLine(point1.x()*90+off, point1.y()*90+off, point2.x()*90+off, point2.y()*90+off); - } + DrawLineWithArrow(painter,pen,QPoint(point1.x()*90+off, point1.y()*90+off), QPoint(point2.x()*90+off, point2.y()*90+off)); + } } } void CardTable::mousePressEvent(QMouseEvent *event) { @@ -243,3 +253,27 @@ void CardTable::mouseReleaseEvent(QMouseEvent *event) { QTableWidget::mouseReleaseEvent(event); if(event->button() == Qt::RightButton) win->connBack(); } + +void CardTable::DrawLineWithArrow(QPainter& painter, QPen pen, QPoint start, QPoint end) +{ + painter.setRenderHint(QPainter::Antialiasing, true); + + qreal arrowSize = 15; + pen.setWidth(2); + painter.setPen(pen); + painter.setBrush(pen.color()); + + QLineF line(end, start); + + double angle = atan2(-line.dy(), line.dx()); + QPointF arrowP1 = line.p1() + QPointF(sin(angle + M_PI / 3) * arrowSize, + cos(angle + M_PI / 3) * arrowSize); + QPointF arrowP2 = line.p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize, + cos(angle + M_PI - M_PI / 3) * arrowSize); + + QPolygonF arrowHead; + arrowHead.clear(); + arrowHead << line.p1() << arrowP1 << arrowP2; + painter.drawLine(line); + painter.drawPolygon(arrowHead); +} diff --git a/ledset/expertscreenconnwin.h b/ledset/expertscreenconnwin.h index c56072d..f9ec6b1 100644 --- a/ledset/expertscreenconnwin.h +++ b/ledset/expertscreenconnwin.h @@ -24,6 +24,9 @@ public: explicit CardTable(QWidget *parent = nullptr) : QTableWidget{parent} {} CardTable(int rows, int columns, QWidget *parent = nullptr) : QTableWidget{rows, columns, parent} {} ExpertScreenConnWin *win; +private: + void DrawLineWithArrow(QPainter& painter, QPen pen, QPoint start, QPoint end); + protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; diff --git a/ledset/expertsmartpointsetwin.cpp b/ledset/expertsmartpointsetwin.cpp index 99f2e61..1e652a8 100644 --- a/ledset/expertsmartpointsetwin.cpp +++ b/ledset/expertsmartpointsetwin.cpp @@ -14,12 +14,20 @@ #include #include -ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent} { +ExpertSmartPointSetWin::ExpertSmartPointSetWin(ExpertWin *expertWin) : BaseWin{expertWin}, expertWin(expertWin) { setWindowModality(Qt::WindowModal); setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle("智能走点参数配置"); + setWindowTitle(tr("智能走点参数配置")); resize(900, 600); + ModuleWidth = expertWin->mModule["ModuleWidth"].toInt(); + ModuleHeight = expertWin->mModule["ModuleHeight"].toInt(); + GroupNum = expertWin->mModule["GroupNum"].toInt(); + ScanNum = expertWin->mModule["ScanNum"].toInt(); + ChipType = expertWin->mModule["ChipType"].toString(); + DecodeMode = expertWin->mModule["DecodeMode"].toString(); + GroupMode = expertWin->mModule["GroupMode"].toString(); + auto vBox = new QVBoxLayout(center); vBox->setContentsMargins(0,0,0,0); vBox->setSpacing(3); @@ -35,7 +43,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vBox = new QVBoxLayout(page); vBox->setContentsMargins(50, 50, 6, 6); - auto lb = new QLabel("基本参数"); + auto lb = new QLabel(tr("基本参数")); bkBlue = lb->palette(); bkBlue.setColor(QPalette::WindowText, QColor(0x5599ff)); lb->setPalette(bkBlue); @@ -48,7 +56,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vvv = new QVBoxLayout; auto hhhh = new QHBoxLayout; - lb = new QLabel("模组宽度: "); + lb = new QLabel(tr("模组宽度: ")); hhhh->addWidget(lb); fdModuleWidth = new QSpinBox; @@ -60,7 +68,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent vvv->addSpacing(30); hhhh = new QHBoxLayout; - lb = new QLabel("模组高度: "); + lb = new QLabel(tr("模组高度: ")); hhhh->addWidget(lb); fdModuleHeight = new QSpinBox; @@ -72,7 +80,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent vvv->addSpacing(30); hhhh = new QHBoxLayout; - lb = new QLabel("数据组数: "); + lb = new QLabel(tr("数据组数: ")); hhhh->addWidget(lb); fdGroupNum = new QSpinBox; @@ -90,7 +98,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vvv = new QVBoxLayout; auto hhhh = new QHBoxLayout; - lb = new QLabel("驱动芯片: "); + lb = new QLabel(tr("驱动芯片: ")); hhhh->addWidget(lb); fdChipType = new QComboBox; @@ -101,25 +109,25 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent vvv->addSpacing(30); hhhh = new QHBoxLayout; - lb = new QLabel("译码方式: "); + lb = new QLabel(tr("译码方式: ")); hhhh->addWidget(lb); fdDecodeMode = new QComboBox; - fdDecodeMode->addItem("138译码"); + fdDecodeMode->addItem(tr("138译码")); hhhh->addWidget(fdDecodeMode); vvv->addLayout(hhhh); vvv->addSpacing(30); hhhh = new QHBoxLayout; - lb = new QLabel("分组方式: "); + lb = new QLabel(tr("分组方式: ")); hhhh->addWidget(lb); fdGroupMode = new QComboBox; - fdGroupMode->addItem("三线并行"); - fdGroupMode->addItem("三色1点串"); - fdGroupMode->addItem("三色8点串"); - fdGroupMode->addItem("三色16点串"); + fdGroupMode->addItem(tr("三线并行")); + fdGroupMode->addItem(tr("三色1点串")); + fdGroupMode->addItem(tr("三色8点串")); + fdGroupMode->addItem(tr("三色16点串")); hhhh->addWidget(fdGroupMode); vvv->addLayout(hhhh); @@ -137,7 +145,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vBox = new QVBoxLayout(page); vBox->setContentsMargins(50, 50, 6, 6); - auto lb = new QLabel("扫描行数"); + auto lb = new QLabel(tr("扫描行数")); lb->setPalette(bkBlue); vBox->addWidget(lb); vBox->addSpacing(50); @@ -149,16 +157,16 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vvv = new QVBoxLayout; hBox->addLayout(vvv); - lb = new QLabel("根据亮线的行/列数确定扫描行/列数: "); + lb = new QLabel(tr("根据亮线的行/列数确定扫描行/列数: ")); vvv->addWidget(lb); vvv->addSpacing(30); auto hhhh = new QHBoxLayout; hhhh->addStretch(); - auto fdRow = new QRadioButton("行"); + auto fdRow = new QRadioButton(tr("行")); hhhh->addWidget(fdRow); hhhh->addStretch(); - auto fdCol = new QRadioButton("列"); + auto fdCol = new QRadioButton(tr("列")); hhhh->addWidget(fdCol); hhhh->addStretch(); vvv->addLayout(hhhh); @@ -167,7 +175,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent hhhh = new QHBoxLayout; hhhh->addStretch(); - lb = new QLabel("亮线的行/列数: "); + lb = new QLabel(tr("亮线的行/列数: ")); hhhh->addWidget(lb); auto fdNum = new QSpinBox; @@ -185,7 +193,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent vvv = new QVBoxLayout; hBox->addLayout(vvv); - lb = new QLabel("芯片245版本: "); + lb = new QLabel(tr("芯片245版本: ")); vvv->addWidget(lb); vvv->addSpacing(30); @@ -209,36 +217,36 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent auto vBox = new QVBoxLayout(page); vBox->setContentsMargins(50, 50, 6, 6); - auto lb = new QLabel("数据线颜色"); + auto lb = new QLabel(tr("数据线颜色")); lb->setPalette(bkBlue); vBox->addWidget(lb); vBox->addSpacing(50); - lb = new QLabel("依次点击以下状态, 根据模组颜色选择对应颜色"); + lb = new QLabel(tr("依次点击以下状态, 根据模组颜色选择对应颜色")); vBox->addWidget(lb, 0, Qt::AlignCenter); vBox->addSpacing(30); auto hhhh = new QHBoxLayout; hhhh->addStretch(); - auto fdSta1 = new QRadioButton("状态1"); + auto fdSta1 = new QRadioButton(tr("状态1")); fdSta1->setChecked(true); hhhh->addWidget(fdSta1); hhhh->addStretch(); - auto fdR1 = new QRadioButton("红"); + auto fdR1 = new QRadioButton(tr("红")); fdR1->setChecked(true); hhhh->addWidget(fdR1); hhhh->addSpacing(20); - auto fdG1 = new QRadioButton("绿"); + auto fdG1 = new QRadioButton(tr("绿")); hhhh->addWidget(fdG1); hhhh->addSpacing(20); - auto fdB1 = new QRadioButton("蓝"); + auto fdB1 = new QRadioButton(tr("蓝")); hhhh->addWidget(fdB1); hhhh->addSpacing(20); - auto fdNo1 = new QRadioButton("黑"); + auto fdNo1 = new QRadioButton(tr("黑")); hhhh->addWidget(fdNo1); hhhh->addStretch(); @@ -247,24 +255,24 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent hhhh = new QHBoxLayout; hhhh->addStretch(); - auto fdSta2 = new QRadioButton("状态2"); + auto fdSta2 = new QRadioButton(tr("状态2")); hhhh->addWidget(fdSta2); hhhh->addStretch(); - auto fdR2 = new QRadioButton("红"); + auto fdR2 = new QRadioButton(tr("红")); hhhh->addWidget(fdR2); hhhh->addSpacing(20); - auto fdG2 = new QRadioButton("绿"); + auto fdG2 = new QRadioButton(tr("绿")); fdG2->setChecked(true); hhhh->addWidget(fdG2); hhhh->addSpacing(20); - auto fdB2 = new QRadioButton("蓝"); + auto fdB2 = new QRadioButton(tr("蓝")); hhhh->addWidget(fdB2); hhhh->addSpacing(20); - auto fdNo2 = new QRadioButton("黑"); + auto fdNo2 = new QRadioButton(tr("黑")); hhhh->addWidget(fdNo2); hhhh->addStretch(); @@ -273,24 +281,24 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent hhhh = new QHBoxLayout; hhhh->addStretch(); - auto fdSta3 = new QRadioButton("状态3"); + auto fdSta3 = new QRadioButton(tr("状态3")); hhhh->addWidget(fdSta3); hhhh->addStretch(); - auto fdR3 = new QRadioButton("红"); + auto fdR3 = new QRadioButton(tr("红")); hhhh->addWidget(fdR3); hhhh->addSpacing(20); - auto fdG3 = new QRadioButton("绿"); + auto fdG3 = new QRadioButton(tr("绿")); hhhh->addWidget(fdG3); hhhh->addSpacing(20); - auto fdB3 = new QRadioButton("蓝"); + auto fdB3 = new QRadioButton(tr("蓝")); fdB3->setChecked(true); hhhh->addWidget(fdB3); hhhh->addSpacing(20); - auto fdNo3 = new QRadioButton("黑"); + auto fdNo3 = new QRadioButton(tr("黑")); hhhh->addWidget(fdNo3); hhhh->addStretch(); @@ -348,19 +356,18 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent }); hhh->addWidget(btnUndo); - auto btnAddVoid = new QPushButton("插入虚点"); + auto btnAddVoid = new QPushButton(tr("插入虚点")); btnAddVoid->setMinimumSize(90, 30); connect(btnAddVoid, &QPushButton::clicked, this, [this] { virtualCnt++; auto cnt = tableRow->columnCount(); tableRow->setColumnCount(cnt+1); tableRow->setItem(0, cnt, new QTableWidgetItem(QString::number(cnt+1))); - auto item = new QTableWidgetItem("×"); - tableRow->setItem(1, cnt, item); + tableRow->setItem(1, cnt, new QTableWidgetItem("×")); }); hhh->addWidget(btnAddVoid); - auto btnReset = new QPushButton("重新走点"); + auto btnReset = new QPushButton(tr("重新走点")); btnReset->setMinimumSize(90, 30); connect(btnReset, &QPushButton::clicked, this, [this] { table->clearContents(); @@ -369,7 +376,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent }); hhh->addWidget(btnReset); - auto btnOK = new QPushButton("完成"); + auto btnOK = new QPushButton(tr("完成")); btnOK->setMinimumSize(90, 30); connect(btnOK, &QPushButton::clicked, this, &ExpertSmartPointSetWin::save); hhh->addWidget(btnOK); @@ -384,7 +391,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent table->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); table->verticalHeader()->setMinimumWidth(40); table->verticalHeader()->setDefaultAlignment(Qt::AlignCenter); - connect(table, &QTableWidget::currentCellChanged, this, [this](int row, int col) { + connect(table, &QTableWidget::currentCellChanged, this, [=](int row, int col) { if(row < 0) return; auto item = table->item(row, col); if(item) return; @@ -400,19 +407,22 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent table->setItem(row, col, item); if(realCnt==ModuleWidth) { scans.append({col, row}); - QMessageBox::information(this, "提示", "列走完"); + QMessageBox::information(this, tr("提示"), tr("列走完")); } } else if(scans.size() < ScanNum) { scans.append({col, row}); auto size = scans.size(); item = new QTableWidgetItem("S"+QString::number(size)); table->setItem(row, col, item); + if(size==ScanNum) { - QMessageBox::information(this, "提示", "行走完"); + QMessageBox::information(this, tr("提示"), tr("行走完")); save(); } } }); + + vBox->addWidget(table); tableRow = new PointTable(2, 0); @@ -425,10 +435,10 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent tableRow->setMaximumHeight(80); auto item = tableRow->verticalHeaderItem(0); if(item==0) tableRow->setVerticalHeaderItem(0, item = new QTableWidgetItem()); - item->setText("第一扫灯数:"); + item->setText(tr("第一扫灯数:")); item = tableRow->verticalHeaderItem(1); if(item==0) tableRow->setVerticalHeaderItem(1, item = new QTableWidgetItem()); - item->setText("实: 虚:"); + item->setText(tr("实: 虚:")); vBox->addWidget(tableRow); } @@ -437,11 +447,11 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent hBox->addStretch(); - auto btnPrev = new QPushButton("上一步"); + auto btnPrev = new QPushButton(tr("上一步")); btnPrev->setMinimumSize(90, 30); hBox->addWidget(btnPrev); - auto btnNext = new QPushButton("下一步"); + auto btnNext = new QPushButton(tr("下一步")); btnNext->setMinimumSize(90, 30); hBox->addWidget(btnNext); @@ -451,7 +461,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent btnPrev->setEnabled(idx > 0); btnNext->setEnabled(idx < stack->count()-1); }); - connect(btnNext, &QPushButton::clicked, this, [this, stack, btnPrev, btnNext] { + connect(btnNext, &QPushButton::clicked, this, [=] { auto idx = stack->currentIndex(); if(idx==0) { ModuleWidth = fdModuleWidth->value(); @@ -478,10 +488,12 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(QWidget *parent) : BaseWin{parent } void ExpertSmartPointSetWin::save() { - auto file = QFileDialog::getSaveFileName(this, "保存文件", QApplication::applicationDirPath()+QString("/ModuleFiles/1X2_3扫.module").arg(ModuleWidth).arg(ModuleHeight).arg(ScanNum)); - if(file.isEmpty()) return; + auto file = QApplication::applicationDirPath()+"/temp.module"; QFile qFile(file); - if(! qFile.open(QFile::WriteOnly)) return; + if(! qFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file)); + return; + } QJsonObject obj; obj.insert("ModuleWidth", ModuleWidth); obj.insert("ModuleHeight", ModuleHeight); @@ -490,77 +502,54 @@ void ExpertSmartPointSetWin::save() { obj.insert("ChipType", ChipType); obj.insert("DecodeMode", DecodeMode); obj.insert("GroupMode", GroupMode); - QJsonArray Points; - for(int i=0; icolumnCount(); i++) { - auto data = tableRow->item(1, i)->data(Qt::UserRole); - if(! data.isValid()) Points.append(-1); - Points.append(data.toPoint().x()); + QJsonArray points; + auto cnt = tableRow->columnCount(); + if(cnt > ModuleWidth) { + auto add = (cnt+ModuleWidth-1) / ModuleWidth * ModuleWidth - cnt; + for(int i=0; i=0; i--) { + auto data = tableRow->item(1, i)->data(Qt::UserRole); + points.append(data.isValid() ? data.toPoint().x() : -1); + } + obj.insert("Points", points); QJsonArray Scans; foreach(QPoint scan, scans) Scans.append(scan.y()); obj.insert("Scans", Scans); - qFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented)); + auto data = QJsonDocument(obj).toJson(QJsonDocument::Indented); + auto res = qFile.write(data); qFile.close(); - QMessageBox::information(this, "保存成功", "保存成功"); -} - -void ExpertSmartPointSetWin::save2() { - auto dlg = new BaseDlg(this); - dlg->setWindowTitle("保存设置"); - - auto vBox = new VBox(dlg->center); - vBox->setContentsMargins(0,0,0,0); - - auto hBox = new HBox(vBox); - dlg->addBtns(hBox); - - vBox->addSpacing(20); - hBox = new HBox(vBox); - hBox->addWidget(new QLabel("文件名称: ")); - hBox->addWidget(new QLineEdit(QString("1X2_3扫").arg(ModuleWidth).arg(ModuleHeight).arg(ScanNum))); - - vBox->addSpacing(20); - hBox = new HBox(vBox); - hBox->addWidget(new QLabel("保存路径: ")); - - auto dir = QApplication::applicationDirPath()+"/ModuleFiles"; - QDir(dir).mkpath("."); - auto fdDir = new QLineEdit(dir); - fdDir->setMinimumWidth(400); - hBox->addWidget(fdDir); - - auto btnChoose = new QPushButton("选择路径"); - connect(btnChoose, &QPushButton::clicked, this, [this, fdDir] { - QFileInfo info(fdDir->text()); - QFileDialog dlg(this, "选择存储文件的目录", info.path()); - auto font = dlg.font(); - font.setPixelSize(12); - dlg.setFont(font); - dlg.setFileMode(QFileDialog::Directory); - dlg.setOptions(QFileDialog::ShowDirsOnly); - dlg.selectFile(info.fileName()); - dlg.exec(); - auto dir = dlg.selectedFiles(); - if(! dir.isEmpty()) fdDir->setText(dir[0]); - //auto dir = QFileDialog::getExistingDirectory(this, "选择存储文件的目录", fdDir->text()); - //if(! dir.isEmpty()) fdDir->setText(dir); - }); - hBox->addWidget(btnChoose); - - vBox->addSpacing(20); - hBox = new HBox(vBox); - hBox->addStretch(); - - auto btnOK = new QPushButton("完成"); - btnOK->setMinimumSize(90, 30); - connect(btnOK, &QPushButton::clicked, dlg, &BaseDlg::accept); - hBox->addWidget(btnOK); - - auto btnBack = new QPushButton("返回"); - btnBack->setMinimumSize(90, 30); - connect(btnBack, &QPushButton::clicked, dlg, &BaseDlg::reject); - hBox->addWidget(btnBack); - - dlg->exec(); + if(res < 0) { + QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file)); + return; + } + expertWin->mModule = obj; + + expertWin->fdModuleWidth->setText(QString::number(ModuleWidth)); + expertWin->fdModuleHeight->setText(QString::number(ModuleHeight)); + expertWin->fdGroupNum->setText(QString::number(GroupNum)); + expertWin->fdScanNum->setText(QString::number(ScanNum)); + expertWin->fdChipType->setText(ChipType); + expertWin->fdDecodeMode->setText(DecodeMode); + + expertWin->fdCardWidth->setValue(ModuleWidth); + expertWin->fdCardHeight->setValue(ModuleHeight); + + auto appDir = QApplication::applicationDirPath(); + QDir(appDir).mkdir("ModuleFiles"); + file = QFileDialog::getSaveFileName(this, tr("保存文件"), appDir+QString("/ModuleFiles/%1X%2_%3扫.module").arg(ModuleWidth).arg(ModuleHeight).arg(ScanNum), tr("Module file (*.module)")); + if(file.isEmpty()) return; + QFile qFile2(file); + if(! qFile2.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file)); + return; + } + res = qFile2.write(data); + qFile2.close(); + if(res < 0) { + QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file)); + return; + } + QMessageBox::information(this, tr("保存成功"), tr("保存成功")); + close(); } diff --git a/ledset/expertsmartpointsetwin.h b/ledset/expertsmartpointsetwin.h index a5fead4..0b0293a 100644 --- a/ledset/expertsmartpointsetwin.h +++ b/ledset/expertsmartpointsetwin.h @@ -2,6 +2,7 @@ #define EXPERTSMARTPOINTSETWIN_H #include "basewin.h" +#include "expertwin.h" #include #include #include @@ -19,9 +20,10 @@ public: class ExpertSmartPointSetWin : public BaseWin { Q_OBJECT public: - explicit ExpertSmartPointSetWin(QWidget *parent = nullptr); + explicit ExpertSmartPointSetWin(ExpertWin *parent = nullptr); void save(); - void save2(); + + ExpertWin *expertWin; PointTable *table, *tableRow; int virtualCnt = 0; @@ -29,7 +31,6 @@ public: QSpinBox *fdModuleWidth, *fdModuleHeight, *fdGroupNum; QComboBox *fdChipType, *fdDecodeMode, *fdGroupMode; - int ModuleWidth{16}, ModuleHeight{8}, GroupNum{2}, ScanNum{4}; QString ChipType, DecodeMode, GroupMode; }; diff --git a/ledset/expertwin.cpp b/ledset/expertwin.cpp index 0cbd29f..8b19cd2 100644 --- a/ledset/expertwin.cpp +++ b/ledset/expertwin.cpp @@ -1,17 +1,24 @@ #include "expertwin.h" #include "gqt.h" #include "table.h" +#include "crc.h" #include "screenunit.h" #include "expertsmartpointsetwin.h" #include "expertscreenconnwin.h" #include -#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include QColor colors[] {QColor(0xdd0000), QColor(0xdd6600), QColor(0x008800), QColor(0x008888), QColor(0x0000ff), QColor(0x777777), QColor(0xaaaaaa)}; @@ -78,12 +85,12 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou auto table = new Table{ {"face", "网口", 40}, - {"x", "X", Table::Stretch}, - {"y", "Y", Table::Stretch}, - {"w", "宽度", Table::Stretch}, - {"h", "高度", Table::Stretch}, - {"audio", "音频开关", Table::Stretch}, - {"backup", "备份开关", Table::Stretch} + {"x", "X", 0, QHeaderView::Stretch}, + {"y", "Y", 0, QHeaderView::Stretch}, + {"w", "宽度", 0, QHeaderView::Stretch}, + {"h", "高度", 0, QHeaderView::Stretch}, + {"audio", "音频开关", 0, QHeaderView::Stretch}, + {"backup", "备份开关", 0, QHeaderView::Stretch} }; table->setDefs(); vLeft->addWidget(table); @@ -128,7 +135,30 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou } - + { + auto file = QApplication::applicationDirPath()+"/temp.screen"; + QFile qFile(file); + if(qFile.open(QFile::ReadOnly)) { + auto data = qFile.readAll(); + qFile.close(); + QJsonParseError err; + auto json = QJsonDocument::fromJson(data, &err); + if(err.error==QJsonParseError::NoError && json.isObject() && ! json.isEmpty()) { + mBox = json["ModuleConnectionInfo"].toObject(); + mModule = mBox["ModuleInfo"].toObject(); + } + } else { + auto file = QApplication::applicationDirPath()+"/temp.module"; + QFile qFile(file); + if(qFile.open(QFile::ReadOnly)) { + auto data = qFile.readAll(); + qFile.close(); + QJsonParseError err; + auto json = QJsonDocument::fromJson(data, &err); + if(err.error==QJsonParseError::NoError && json.isObject() && ! json.isEmpty()) mModule = json.object(); + } + } + } auto receivePanel = new QWidget; tab->addTab(receivePanel, "接收卡"); @@ -136,179 +166,406 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou auto vBox = new VBox(receivePanel); auto gBox = new QGroupBox("模组信息"); vBox->addWidget(gBox); + { + auto hh = new HBox(gBox); + hh->addSpacing(20); + auto vvv = new VBox(hh); - auto hh = new HBox(gBox); - auto vvv = new VBox(hh); + auto lb = new QLabel("驱动芯片: "); + vvv->addWidget(lb); - auto lb = new QLabel("驱动芯片: "); - vvv->addWidget(lb); + lb = new QLabel("译码方式: "); + vvv->addWidget(lb); - lb = new QLabel("译码方式: "); - vvv->addWidget(lb); + vvv = new VBox(hh); - vvv = new VBox(hh); + fdChipType = new QLabel(mModule["ChipType"].toString()); + vvv->addWidget(fdChipType); - lb = new QLabel("驱动芯片"); - vvv->addWidget(lb); + fdDecodeMode = new QLabel(mModule["DecodeMode"].toString());//译码方式 + vvv->addWidget(fdDecodeMode); - lb = new QLabel("译码方式"); - vvv->addWidget(lb); + hh->addSpacing(20); + vvv = new VBox(hh); - hh->addSpacing(20); - vvv = new VBox(hh); + lb = new QLabel("模组宽度: "); + vvv->addWidget(lb); - lb = new QLabel("模组宽度: "); - vvv->addWidget(lb); + lb = new QLabel("模组高度: "); + vvv->addWidget(lb); - lb = new QLabel("模组高度: "); - vvv->addWidget(lb); + vvv = new VBox(hh); - vvv = new VBox(hh); + fdModuleWidth = new QLabel(QString::number(mModule["ModuleWidth"].toInt())); + vvv->addWidget(fdModuleWidth); - lb = new QLabel("模组宽度"); - vvv->addWidget(lb); + fdModuleHeight = new QLabel(QString::number(mModule["ModuleHeight"].toInt())); + vvv->addWidget(fdModuleHeight); - lb = new QLabel("模组高度"); - vvv->addWidget(lb); + hh->addSpacing(20); + vvv = new VBox(hh); - hh->addSpacing(20); - vvv = new VBox(hh); + lb = new QLabel("扫描数: "); + vvv->addWidget(lb); - lb = new QLabel("扫描数: "); - vvv->addWidget(lb); + lb = new QLabel("数据数组: "); + vvv->addWidget(lb); - lb = new QLabel("数据数组: "); - vvv->addWidget(lb); + vvv = new VBox(hh); - vvv = new VBox(hh); + fdScanNum = new QLabel(QString::number(mModule["ScanNum"].toInt())); + vvv->addWidget(fdScanNum); - lb = new QLabel("扫描数"); - vvv->addWidget(lb); + fdGroupNum = new QLabel(QString::number(mModule["GroupNum"].toInt())); + vvv->addWidget(fdGroupNum); - lb = new QLabel("数据数组"); - vvv->addWidget(lb); + hh->addSpacing(20); + vvv = new VBox(hh); - hh->addSpacing(20); - vvv = new VBox(hh); + auto btn = new QPushButton(tr("数据线颜色")); + btn->setStyleSheet("QPushButton {border: none; }"); + vvv->addWidget(btn); - lb = new QLabel("数据线颜色: "); - vvv->addWidget(lb); + btn = new QPushButton(tr("模组抽行设置")); + btn->setStyleSheet("QPushButton {border: none; }"); + vvv->addWidget(btn); - lb = new QLabel("模组抽行设置"); - vvv->addWidget(lb); - vvv = new VBox(hh); + hh->addStretch(); + vvv = new VBox(hh); - lb = new QLabel("数据线颜色"); - vvv->addWidget(lb); - - hh->addStretch(); - vvv = new VBox(hh); - - auto btn = new QPushButton("模组选择"); - vvv->addWidget(btn); - - btn = new QPushButton("智能设置"); - connect(btn, &QPushButton::clicked, this, [this] { - (new ExpertSmartPointSetWin(this))->show(); - }); - vvv->addWidget(btn); + btn = new QPushButton("模组选择"); + btn->setProperty("ss","blue"); + vvv->addWidget(btn); + btn = new QPushButton("智能设置"); + btn->setProperty("ss","blue"); + connect(btn, &QPushButton::clicked, this, [this] { + (new ExpertSmartPointSetWin(this))->show(); + }); + vvv->addWidget(btn); + } gBox = new QGroupBox("单卡带载"); vBox->addWidget(gBox); - - hh = new HBox(gBox); - vvv = new VBox(hh); - - vvv->addWidget(new QRadioButton("常规设计")); - vvv->addWidget(new QRadioButton("高级设计")); - - hh->addSpacing(20); - - auto line = new QFrame; - line->setFrameShadow(QFrame::Sunken); - line->setFrameShape(QFrame::VLine); - hh->addWidget(line); - - auto stack = new QStackedWidget; - auto poli = stack->sizePolicy(); - poli.setVerticalPolicy(QSizePolicy::Maximum); - stack->setSizePolicy(poli); - hh->addWidget(stack); - - auto normalPanel = new QWidget; - stack->addWidget(normalPanel); { - auto hh = new HBox(normalPanel); + auto hh = new HBox(gBox); + hh->addSpacing(20); auto vvv = new VBox(hh); - lb = new QLabel("宽度"); - vvv->addWidget(lb); + auto fdNormal = new QRadioButton("常规设计"); + fdNormal->setChecked(true); + vvv->addWidget(fdNormal); - lb = new QLabel("高度"); - vvv->addWidget(lb); + auto fdAdvacned = new QRadioButton("高级设计"); + vvv->addWidget(fdAdvacned); + hh->addSpacing(20); + + auto line = new QFrame; + line->setFrameShadow(QFrame::Sunken); + line->setFrameShape(QFrame::VLine); + hh->addWidget(line); + + auto stack = new QStackedWidget; + auto poli = stack->sizePolicy(); + poli.setVerticalPolicy(QSizePolicy::Maximum); + stack->setSizePolicy(poli); + hh->addWidget(stack); + + auto normalPanel = new QWidget; + stack->addWidget(normalPanel); + { + auto hh = new HBox(normalPanel); + hh->setContentsMargins(0,0,0,0); + auto vvv = new VBox(hh); + + auto lb = new QLabel(tr("宽度")); + vvv->addWidget(lb); + + lb = new QLabel(tr("高度")); + vvv->addWidget(lb); + + vvv = new VBox(hh); + + fdCardWidth = new QSpinBox; + fdCardWidth->setRange(0, 99999); + fdCardWidth->setValue(mBox["ModuleRow"].toInt() * mModule["ModuleWidth"].toInt()); + vvv->addWidget(fdCardWidth); + + fdCardHeight = new QSpinBox; + fdCardHeight->setRange(0, 99999); + fdCardHeight->setValue(mBox["ModuleCol"].toInt() * mModule["ModuleHeight"].toInt()); + vvv->addWidget(fdCardHeight); + hh->addSpacing(20); + + vvv = new VBox(hh); + + lb = new QLabel(tr("多开设置")); + vvv->addWidget(lb); + + lb = new QLabel(tr("级联方向")); + vvv->addWidget(lb); + + vvv = new VBox(hh); + + fdSectorCount = new QComboBox; + fdSectorCount->addItem(tr("无"), 1); + fdSectorCount->addItem(tr("双开"), 2); + fdSectorCount->addItem(tr("三开"), 3); + fdSectorCount->addItem(tr("四开"), 4); + fdSectorCount->addItem(tr("五开"), 5); + fdSectorCount->addItem(tr("六开"), 6); + fdSectorCount->addItem(tr("七开"), 7); + fdSectorCount->addItem(tr("八开"), 8); + select(fdSectorCount, mBox["SectorCount"].toInt()); + vvv->addWidget(fdSectorCount); + + fdDirection = new QComboBox(); + fdDirection->addItem(tr("从左到右")); + fdDirection->addItem(tr("从右到左")); + fdDirection->addItem(tr("从上到下")); + fdDirection->addItem(tr("从下到上")); + fdDirection->setCurrentIndex(mBox["ModuleDirection"].toInt()); + vvv->addWidget(fdDirection); + + hh->addStretch(); + + vvv = new VBox(hh); + + auto cb = new QCheckBox(tr("旋转180°")); + vvv->addWidget(cb); + + auto btn = new QPushButton(tr("数据交换")); + btn->setProperty("ss","blue"); + vvv->addWidget(btn); + } + + auto advacnedPanel = new QWidget; + stack->addWidget(advacnedPanel); + { + auto hh = new HBox(advacnedPanel); + hh->setContentsMargins(0,0,0,0); + vvv = new VBox(hh); + + auto btn = new QPushButton(tr("平面造型")); + btn->setProperty("ss","blue"); + btn->setMaximumWidth(100); + vvv->addWidget(btn); + } + connect(fdNormal, &QRadioButton::toggled, this, [=](bool checked) { + stack->setCurrentWidget(checked ? normalPanel : advacnedPanel); + }); + } + + gBox = new QGroupBox(tr("效果测试")); + vBox->addWidget(gBox); + { + auto hh = new HBox(gBox); + hh->addSpacing(20); + + auto vvv = new VBox(hh); + auto hhh = new HBox(vvv); + auto lb = new QLabel(tr("视觉刷新率:")); + hhh->addWidget(lb); + + auto cbFresh = new QComboBox(); + cbFresh->addItem("960"); + cbFresh->addItem("1920"); + cbFresh->addItem("2880"); + cbFresh->addItem("3840"); + hhh->addWidget(cbFresh); + + hhh = new HBox(vvv); + lb = new QLabel(tr("DCLK频率:")); + hhh->addWidget(lb); + auto cbDCLKf = new QComboBox(); + cbDCLKf->addItem("25M"); + cbDCLKf->addItem("20.83M"); + cbDCLKf->addItem("17.86M"); + cbDCLKf->addItem("15.63M"); + cbDCLKf->addItem("13.89M"); + cbDCLKf->addItem("12.5M"); + cbDCLKf->addItem("11.36M"); + cbDCLKf->addItem("10.42M"); + cbDCLKf->addItem("9.62M"); + hhh->addWidget(cbDCLKf); + + hhh = new HBox(vvv); + lb = new QLabel(tr("DCLK相位:")); + hhh->addWidget(lb); + auto spinDclkXw = new QSpinBox; + spinDclkXw->setRange(0, 99999); + hhh->addWidget(spinDclkXw); + + hhh = new HBox(vvv); + lb = new QLabel(tr("DCLK占空比:")); + hhh->addWidget(lb); + auto spinDclkZkb = new QSpinBox; + spinDclkZkb->setRange(20, 80); + hhh->addWidget(spinDclkZkb); + + hhh = new HBox(vvv); + lb = new QLabel(tr("换行时间(ns):")); + hhh->addWidget(lb); + auto spinLineNs = new QSpinBox; + spinLineNs->setRange(2, 9999); + hhh->addWidget(spinLineNs); + + hh->addSpacing(20); vvv = new VBox(hh); + hhh = new HBox(vvv); + lb = new QLabel(tr("亮度有效率:")); + hhh->addWidget(lb); + lb = new QLabel(tr("100%")); + hhh->addWidget(lb); - auto fdCardWidth = new QSpinBox; - fdCardWidth->setRange(0, 99999); - vvv->addWidget(fdCardWidth); + hhh = new HBox(vvv); + lb = new QLabel(tr("GCLK频率:")); + hhh->addWidget(lb); + auto cbGCLKf = new QComboBox(); + cbGCLKf->addItem("25M"); + cbGCLKf->addItem("20.83M"); + cbGCLKf->addItem("17.86M"); + cbGCLKf->addItem("15.63M"); + cbGCLKf->addItem("13.89M"); + cbGCLKf->addItem("12.5M"); + cbGCLKf->addItem("11.36M"); + cbGCLKf->addItem("10.42M"); + cbGCLKf->addItem("9.62M"); + hhh->addWidget(cbGCLKf); - auto fdCardHeight = new QSpinBox; - fdCardHeight->setRange(0, 99999); - vvv->addWidget(fdCardHeight); + hhh = new HBox(vvv); + lb = new QLabel(tr("灰度级数:")); + hhh->addWidget(lb); + auto cbGryLevel = new QComboBox(); + cbGryLevel->addItem("256"); + cbGryLevel->addItem("1024"); + cbGryLevel->addItem("4096"); + cbGryLevel->addItem("8192"); + cbGryLevel->addItem("16384"); + cbGryLevel->addItem("32768"); + cbGryLevel->addItem("65536"); + hhh->addWidget(cbGryLevel); - vvv = new VBox(hh); + hhh = new HBox(vvv); + lb = new QLabel(tr("GCLK占空比:")); + hhh->addWidget(lb); + auto spinGclkZkb = new QSpinBox; + spinGclkZkb->setRange(20, 80); + hhh->addWidget(spinGclkZkb); - lb = new QLabel("多开宽度"); - vvv->addWidget(lb); - - lb = new QLabel("级联方向"); - vvv->addWidget(lb); - - vvv = new VBox(hh); - - auto fdMulti = new QComboBox(); - fdMulti->addItem("无"); - fdMulti->addItem("双开"); - fdMulti->addItem("三开"); - fdMulti->addItem("四开"); - vvv->addWidget(fdMulti); - - auto fdDirection = new QComboBox(); - fdDirection->addItem("从左到右"); - fdDirection->addItem("从右到左"); - fdDirection->addItem("从上到下"); - fdDirection->addItem("从下到上"); - vvv->addWidget(fdDirection); - - vvv = new VBox(hh); - - lb = new QLabel("插头顺序"); - vvv->addWidget(lb); - vvv->addStretch(); - - vvv = new VBox(hh); - - auto fdSord = new QComboBox(); - fdSord->addItem("正序"); - fdSord->addItem("逆序"); - vvv->addWidget(fdSord); - - vvv->addStretch(); + hhh = new HBox(vvv); + lb = new QLabel(tr("换行位置(ns):")); + hhh->addWidget(lb); + auto spinLineWz = new QSpinBox; + spinLineWz->setRange(2, 9999); + hhh->addWidget(spinLineWz); hh->addStretch(); + + vvv = new VBox(hh); + hhh = new HBox(vvv); + + auto btn = new QPushButton(tr("更多设置")); + btn->setProperty("ss","blue"); + hhh->addWidget(btn); + } - auto advacnedPanel = new QWidget; - stack->addWidget(advacnedPanel); + vBox->addStretch(); + +//保存,发送,固话,回读区 + auto hBox = new HBox(vBox); + hBox->addSpacing(20); + + auto btn = new QPushButton(tr("打开配置")); + btn->setProperty("ss","blue"); + hBox->addWidget(btn); + hBox->addSpacing(20); + + btn = new QPushButton(tr("保存配置")); + btn->setProperty("ss","blue"); + connect(btn, &QPushButton::clicked, this, [=] { + auto dir = QApplication::applicationDirPath()+"/BoxFiles"; + QDir(dir).mkdir("."); + auto file = QFileDialog::getSaveFileName(this, tr("保存文件"), dir, tr("Box file (*.box)")); + if(file.isEmpty()) return; + QFile qFile(file); + if(! qFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file)); + return; + } + auto res = qFile.write(savedData()); + qFile.close(); + if(res < 0) { + QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file)); + return; + } + QMessageBox::information(this, tr("保存成功"), tr("保存成功")); + }); + hBox->addWidget(btn); + hBox->addStretch(); + + btn = new QPushButton(tr("保存Map")); + btn->setProperty("ss","blue"); + connect(btn, &QPushButton::clicked, this, [=] { + auto dir = QApplication::applicationDirPath(); + auto file = QFileDialog::getSaveFileName(this, tr("保存文件"), dir); + if(file.isEmpty()) return; + QFile qFile(file); + if(! qFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file)); + return; + } + QByteArray data; + addMapData(data); + auto res = qFile.write(data); + qFile.close(); + if(res < 0) { + QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file)); + return; + } + QMessageBox::information(this, tr("保存成功"), tr("保存成功")); + + }); + hBox->addWidget(btn); + hBox->addSpacing(20); + + btn = new QPushButton(tr("发送数据")); + btn->setProperty("ss","blue"); + connect(btn, &QPushButton::clicked, this, [=] { + QByteArray data; + addMapData(data); + QMessageBox::information(this, tr("发送成功"), tr("发送成功")); + }); + hBox->addWidget(btn); + hBox->addSpacing(20); + + btn = new QPushButton(tr("固化数据")); + btn->setProperty("ss","blue"); + hBox->addWidget(btn); + hBox->addSpacing(20); + + btn = new QPushButton(tr("回读数据")); + btn->setProperty("ss","blue"); + hBox->addWidget(btn); vBox->addStretch(); + +//状态栏 + auto statusWgt = new QWidget; + statusWgt->setStyleSheet("QWidget{background-color:#222;}"); + vBox->addWidget(statusWgt); + { + auto hh = new HBox(statusWgt); + auto lb = new QLabel(tr("状态:")); + hh->addWidget(lb); + } } auto connPanel = new QWidget; - tab->addTab(connPanel, "显示屏连接(正面看屏)"); + tab->addTab(connPanel, tr("显示屏连接(正面看屏)")); { auto vBox = new QVBoxLayout(connPanel); vBox->setContentsMargins(4, 4, 4, 4); @@ -335,3 +592,230 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou stack->addWidget(new ExpertScreenConnWin()); } } +void ExpertWin::closeEvent(QCloseEvent *event) { + BaseWin::closeEvent(event); + QFile qFile(QApplication::applicationDirPath()+"/temp.screen"); + if(! qFile.open(QFile::WriteOnly)) return; + qFile.write(savedData()); + qFile.close(); +} +QByteArray ExpertWin::savedData() { + mBox.insert("ModuleInfo", mModule); + auto ModuleWidth = mModule["ModuleWidth"].toInt(); + auto ModuleHeight = mModule["ModuleHeight"].toInt(); + mBox.insert("ModuleRow", (fdCardWidth->value() + ModuleWidth - 1) / ModuleWidth); + mBox.insert("ModuleCol", (fdCardHeight->value() + ModuleHeight - 1) / ModuleHeight); + mBox.insert("ModuleDirection", fdDirection->currentIndex()); + mBox.insert("SectorCount", fdSectorCount->currentData().toInt()); + QJsonObject obj{{"ModuleConnectionInfo", mBox}}; + return QJsonDocument(obj).toJson(QJsonDocument::Indented); +} +void ExpertWin::addMapData(QByteArray &data) { + auto ModuleWidth = mModule["ModuleWidth"].toInt(); + auto ModuleHeight = mModule["ModuleHeight"].toInt(); + auto ModuleRow = (fdCardWidth->value() + ModuleWidth - 1) / ModuleWidth; + auto ModuleCol = (fdCardHeight->value() + ModuleHeight - 1) / ModuleHeight; + auto CardWidth = ModuleRow * ModuleWidth; + auto CardHeight = ModuleCol * ModuleHeight; + auto ModuleDirection = fdDirection->currentIndex(); + //auto SectorCount = fdSectorCount->currentData().toInt(); + QMap map; + int memY = 0, memX = 0; + for(int boxY=0; boxY 255) { + memX = 0; + memY++; + } + map.insert(boxY<<16|boxX, memY<<16|memX); + memX++; + } + memX = 0; + memY++; + } + + auto points = mModule["Points"].toArray(); + auto scans = mModule["Scans"].toArray(); + auto GroupNum = mModule["GroupNum"].toInt(); + auto jCnt = ModuleCol * GroupNum; + + foreach(auto scan, scans) { + QList> chunkses; + for(int j=0; j chunks; + QByteArray chunk; + QString chstr; + for(int mm=0; mm> 16; + memX = mem & 0xffff; + } + if(memY==lastMemY && ttl < 64 && qAbs(memX-lastMemX)==1) { + if(cnt==1) { + isAnti = memX < lastMemX; + cnt++; + ttl++; + lastMemX = memX; + continue; + } else if(memX < lastMemX == isAnti) { + cnt++; + ttl++; + lastMemX = memX; + continue; + } + } + if(lastMemY > INT_MIN) { + uint y = lastMemY==-1 ? 0 : lastMemY; + uint x = isAnti ? lastMemX : lastMemX-cnt+1; + chunk.append((j << 2) + (y >> 8)).append(y).append(x).append((isAnti << 7)+cnt); + chstr += QString("j%1 行%2 列%3 序%4 长%5").arg(j).arg(y).arg(x).arg(isAnti).arg(cnt); + } + if(ttl>=64) { + chunks.append(chunk); + chunk = QByteArray(); + qDebug() << chstr; + chstr.clear(); + ttl = 1; + } + cnt = 1; + lastMemY = memY; + lastMemX = lastMemY==-1 ? 0 : memX; + } + } + uint y = lastMemY==-1 ? 0 : lastMemY; + uint x = isAnti ? lastMemX : lastMemX-cnt+1; + chunk.append((j << 2) + (y >> 8)).append(y).append(x).append((isAnti << 7)+cnt); + chstr += QString("j%1 行%2 列%3 序%4 长%5").arg(j).arg(y).arg(x).arg(isAnti).arg(cnt); + chunks.append(chunk); + chunkses.append(chunks); + qDebug() << chstr; + } + data.append(0xAA).append(scan.toInt()).append(2, 0); + auto chend = chunkses[0].size()-1; + auto start = data.size(); + for(int ch=0; ch<=chend; ch++) { + data.append(0x55).append(ch==chend ? (char)(1<<7) : 0).append(2, 0); + auto start = data.size(); + foreach(auto chunks, chunkses) data.append(chunks[ch]); + auto num = (data.size() - start) / 4; + data[start-2] = num; + data[start-3] = num>>8; + } + auto len = data.size() - start; + data[start-1] = len; + data[start-2] = len>>8; + } +} + +#define MAX_ONCE 1482 +void run() { +// quint32 idx = 0; +// while(2) { +// QByteArray bytes; +// bytes.append("\x55\x55\x9a\x3d"); //前导, 版本号, 服务类型 +// bytes.append("\0\x4", 2); //数据长度 +// bytes.append(4, '\xff'); //目的地址 +// bytes.append(4, 0); //源地址 +// bytes.append("\x35\0\xc\xbb", 4); //内存指针 +// bytes.append(2, 0); //应答填充项 +// auto crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2); +// bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); +// crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-4, 4); +// bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); +// //发送帧开始指令包 +// auto queue = pcap_sendqueue_alloc(img.width()*img.height()*4); +// { +// struct pcap_pkthdr pktheader; +// pktheader.len = pktheader.caplen = bytes.size(); +// if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) { +// onErr(QString("添加开始失败: ")+pcap_geterr(pcap)); +// goto end; +// } +// idx = 0; +// //按行发送图像数据包 +// for(int i=0; i once) dataLen = once; +// dataLen += 4; +// bytes.clear(); +// bytes.append("\x55\x55\x1\x33"); //前导, 版本号, 服务类型 +// bytes.append(dataLen>>8).append(dataLen); //数据长度 +// bytes.append(4, '\xff'); //目的地址 +// bytes.append(4, 0); //源地址 +// bytes.append(i>>8).append(i).append(j>>8).append(j); //内存指针 +// bytes.append(2, 0); //应答填充项 +// crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2); +// bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); +// bytes.append(idx>>24).append(idx>>16).append(idx>>8).append(idx);//包序号 +// idx++; +// bytes.append((const char*)bits + i * bytesPerLine + j, dataLen - 4); +// crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-dataLen, dataLen); +// bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); +// pktheader.len = pktheader.caplen = bytes.size(); +// if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) { +// onErr(QString("添加数据失败: ")+pcap_geterr(pcap)); +// goto end; +// } +// } +// bytes.clear(); +// bytes.append("\x55\x55\x9a\x3d"); //前导, 版本号, 服务类型 +// bytes.append(2, 0); //数据长度 +// bytes.append(4, '\xff'); //目的地址 +// bytes.append(4, 0); //源地址 +// bytes.append("\x35\0\xc\xcc", 4); //内存指针 +// bytes.append(2, 0); //应答填充项 +// crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2); +// bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); +// pktheader.len = pktheader.caplen = bytes.size(); +// //发送帧结束指令包 +// if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) { +// onErr(QString("添加结束失败: ")+pcap_geterr(pcap)); +// goto end; +// } +// u_int res; +// if((res = pcap_sendqueue_transmit(pcap, queue, 0)) < queue->len) { +// onErr(QString::asprintf("发送包出错: %s. 仅发了 %d / %d bytes", pcap_geterr(pcap), res, queue->len)); +// goto end; +// } +// } +// end: +// pcap_sendqueue_destroy(queue); +// } +} + +ReceThread::ReceThread(pcap_t *pcap) : pcap(pcap) { + connect(this, &QThread::finished, this, &QThread::deleteLater); +} +void ReceThread::run() { + pcap_pkthdr *header; + const u_char *data; + int res; + while((res = pcap_next_ex(pcap, &header, &data)) >= 0) { + if(status==2) return; + if(status==1 || res == 0 || !showImg) continue; //超时 + if(header->caplen<24) continue; + if(data[0]!=0x55 || data[1]!=0x55) continue; + if(data[2]==0x9a && data[3]==0x3d) { +// if(data[17]==0xBB) { +// emit onMsg(((int)data[24] << 8) + data[25], ((int)data[26] << 8) + data[27]); +// } else if(data[17]==0xCC) emit onMsg(img); + continue; + } + } + emit onErr(pcap_geterr(pcap)); +} diff --git a/ledset/expertwin.h b/ledset/expertwin.h index b6873ec..9954859 100644 --- a/ledset/expertwin.h +++ b/ledset/expertwin.h @@ -2,14 +2,65 @@ #define EXPERTWIN_H #include "basewin.h" +#define HAVE_REMOTE +#include +#include "pcap.h" +#include +#include +#include +#include +#include + +class ReceThread : public QThread { + Q_OBJECT +public: + explicit ReceThread(pcap *pcap); + ~ReceThread() { + pcap_close(pcap); + } + pcap *pcap; + std::atomic status{0}; + bool showImg{true}; +protected: + void run(); +signals: + void onMsg(QByteArray); + void onErr(char *); +}; class ExpertWin : public BaseWin { Q_OBJECT public: explicit ExpertWin(QWidget *parent = nullptr); + QByteArray savedData(); + void addMapData(QByteArray &); + int screenWidth{1280}, screenHeight{720}; double rate{1}; + + QLabel *fdModuleWidth, *fdModuleHeight, *fdGroupNum, *fdScanNum; + QLabel *fdChipType, *fdDecodeMode; + QJsonObject mModule { + {"ModuleWidth", 16}, + {"ModuleHeight", 8}, + {"GroupNum", 2}, + {"ScanNum", 4}, + {"ChipType", "通用"}, + {"DecodeMode", "138译码"}, + {"GroupMode", "三线并行"} + }; + QJsonObject mBox { + {"ModuleRow", 1}, + {"ModuleCol", 1}, + {"Direction", 1}, + {"SectorCount", 1} + }; + + QSpinBox *fdCardWidth, *fdCardHeight; + QComboBox *fdDirection, *fdSectorCount; +protected: + void closeEvent(QCloseEvent *) override; }; #endif // EXPERTWIN_H diff --git a/ledset/globalfunc.cpp b/ledset/globalfunc.cpp new file mode 100644 index 0000000..34ac7c7 --- /dev/null +++ b/ledset/globalfunc.cpp @@ -0,0 +1,119 @@ +#include "globalfunc.h" +#include "table.h" +#include "basewin.h" +#define HAVE_REMOTE +#include "pcap.h" +#include +#include + +QByteArray getNetDev(QWidget *parent, QByteArray def) { + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *devs; + if(pcap_findalldevs(&devs, errbuf) == -1) { + QMessageBox::critical(parent, "Error", QString("寻找网卡失败")+errbuf); + return QByteArray(); + } + auto table = new Table{ + {"name", "网卡名称", 400}, + {"desc", "网卡描述", 300}, + {"loopback","Loopback"}, + {"ip","IP"}, + {"netmask","Netmask"}, + {"broadaddr","Broad Addr"}, + {"dstaddr","Dst Addr"} + }; + + pcap_if_t *device = 0; + for(pcap_if_t *dev = devs; dev; dev = dev->next) { + pcap_addr_t *a; + for(a=dev->addresses; a; a=a->next) { + auto sa_family = a->addr->sa_family; + if(sa_family==AF_INET) { + if(! def.isEmpty() && dev->name == def) { + pcap_freealldevs(devs); + table->deleteLater(); + return def; + } + auto rr = table->rowCount(); + table->setRowCount(rr+1); + table->setValue(rr, "name", dev->name); + table->setValue(rr, "desc", dev->description); + table->setValue(rr, "loopback", (dev->flags & PCAP_IF_LOOPBACK)?"True":"False"); + auto ip = (u_char *) &((sockaddr_in *) a->addr)->sin_addr.s_addr; + table->setValue(rr, "ip", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); + if(a->netmask) { + ip = (u_char *) &((sockaddr_in *) a->netmask)->sin_addr.s_addr; + table->setValue(rr, "netmask", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); + } + if(a->broadaddr) { + ip = (u_char *) &((sockaddr_in *) a->broadaddr)->sin_addr.s_addr; + table->setValue(rr, "broadaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); + } + if(a->dstaddr) { + ip = (u_char *) &((sockaddr_in *) a->dstaddr)->sin_addr.s_addr; + table->setValue(rr, "dstaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); + } + if(device==0) device = dev; + } + } + } + pcap_freealldevs(devs); + + auto rowCnt = table->rowCount(); + if(rowCnt==0) { + table->deleteLater(); + QMessageBox::critical(parent, "Error", "没找到 internet 设备"); + return QByteArray(); + } else if(rowCnt==1) { + table->deleteLater(); + return table->item(0, "name")->text().toLocal8Bit(); + } else { + auto dlg = new BaseDlg(parent); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->setWindowTitle("选择网卡"); + dlg->resize(900, 300); + + auto vBox = new QVBoxLayout(dlg->center); + vBox->setContentsMargins(0,0,0,0); + vBox->setSpacing(3); + vBox->addSpacing(30); + + table->setDefs(); + table->setSelectionMode(QAbstractItemView::SingleSelection); + table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + table->selectRow(0); + QByteArray name; + dlg->connect(table, &Table::cellDoubleClicked, dlg, [dlg, table, &name](int row) { + name = table->item(row, "name")->text().toLocal8Bit(); + dlg->accept(); + }); + vBox->addWidget(table); + + auto hBox = new QHBoxLayout; + hBox->addStretch(); + auto btnOk = new QPushButton("确定"); + btnOk->setMinimumWidth(80); + dlg->connect(btnOk, &QPushButton::clicked, dlg, [dlg, table, &name] { + auto sels = table->selectedRanges(); + if(sels.isEmpty()) { + QMessageBox::warning(dlg, "Warning", "请选择网卡"); + return; + } + name = table->item(sels[0].topRow(), "name")->text().toLocal8Bit(); + dlg->accept(); + }); + hBox->addWidget(btnOk); + + hBox->addStretch(); + + auto btnClose = new QPushButton("关闭"); + btnClose->setMinimumWidth(80); + dlg->connect(btnClose, &QPushButton::clicked, dlg, &QDialog::reject); + hBox->addWidget(btnClose); + hBox->addStretch(); + + vBox->addLayout(hBox); + dlg->exec(); + return name; + } +} diff --git a/ledset/globalfunc.h b/ledset/globalfunc.h new file mode 100644 index 0000000..c77b3ee --- /dev/null +++ b/ledset/globalfunc.h @@ -0,0 +1,9 @@ +#ifndef GLOBALFUNC_H +#define GLOBALFUNC_H + +#include +#include + +QByteArray getNetDev(QWidget *parent, QByteArray); + +#endif // GLOBALFUNC_H diff --git a/ledset/imgs/checkbox-check.png b/ledset/imgs/checkbox-check.png new file mode 100644 index 0000000000000000000000000000000000000000..d64dcfd9a2246d505e518a12bdc98511d6157935 GIT binary patch literal 254 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 Ef@e%ozyJUM literal 0 HcmV?d00001 diff --git a/ledset/imgs/macos-minimize.png b/ledset/imgs/macos-minimize.png new file mode 100644 index 0000000000000000000000000000000000000000..0d86cdc850da35c391e28f379935c1d173be9bd7 GIT binary patch literal 745 zcmVa^R1riCxNST{z*nK2k5oXP)3d~#P^rOrJepyytb&%+kAMF1q zS{@o~yYxI^T6qX~ZJE<%nFnlGRvu%l>!gah^e3CQ5-FvG*8~y?#YbI1k??{*BB6L& z=B5D-+2r9H@Xq4J#Ks~j_kA(_hhO^5B?wMAXB>Vp=i0+|ARM&)E z{}IEHhgosU922NtL1@`60(4^?BZU2WuMoj%>QU6eG|AR(9Zc&D=iOV(@hJb6Mw<&;$U(gmuIK literal 0 HcmV?d00001 diff --git a/ledset/imgs/negative_minimize_icon_208693.png b/ledset/imgs/negative_minimize_icon_208693.png new file mode 100644 index 0000000000000000000000000000000000000000..e8e4343df5135f0229043edd10ad549b7d091588 GIT binary patch literal 2182 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 k=#WT0PsooBl0L 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 #include #include @@ -15,6 +14,13 @@ #include #include #include +#include "table.h" +#include "globalfunc.h" +#include +#include "basewin.h" +#include +#include +#include class ImgBtn : public QToolButton { public: @@ -61,7 +67,7 @@ ImgBtn *addImg(QHBoxLayout *parent, const QIcon &icon, const QString &text) { } MainWin::MainWin() { - setWindowTitle("Led Set"); + setWindowTitle("LedSet Express"); resize(860, 540); auto vBox = new QVBoxLayout(center); @@ -73,50 +79,164 @@ MainWin::MainWin() { auto btnImg = addImg(imgsBar, QPixmap(":/imgs/fast.png").scaledToWidth(128, Qt::SmoothTransformation), "快速调屏"); connect(btnImg, &ImgBtn::clicked, this, [=](){ (new Fast(this))->show(); -// if(win==0) { -// win = new QWidget; -// win->setWindowFlag(Qt::FramelessWindowHint); -// win->resize(600,100); -// win->show(); -// } else { -// win->move(win->x()-100, win->y()); -// } }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/expert.png").scaledToWidth(128, Qt::SmoothTransformation), "专家调屏"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/expert.png").scaledToWidth(128, Qt::SmoothTransformation), tr("专家调屏")); connect(btnImg, &ImgBtn::clicked, this, [=](){ (new ExpertWin(this))->show(); }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/bright.png").scaledToWidth(128, Qt::SmoothTransformation), "亮度控制"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/bright.png").scaledToWidth(128, Qt::SmoothTransformation), tr("亮度控制")); connect(btnImg, &ImgBtn::clicked, this, [=](){ (new BrightWin(this))->show(); }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/correct.png").scaledToWidth(128, Qt::SmoothTransformation), "相机矫正"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/correct.png").scaledToWidth(128, Qt::SmoothTransformation), tr("相机矫正")); connect(btnImg, &ImgBtn::clicked, this, [=](){ }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/monitor.png").scaledToWidth(128, Qt::SmoothTransformation), "屏体监控"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/monitor.png").scaledToWidth(128, Qt::SmoothTransformation), tr("屏体监控")); connect(btnImg, &ImgBtn::clicked, this, [=](){ }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/multi.png").scaledToWidth(128, Qt::SmoothTransformation), "多功能卡"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/multi.png").scaledToWidth(128, Qt::SmoothTransformation), tr("多功能卡")); connect(btnImg, &ImgBtn::clicked, this, [=](){ //win->move(win->x()-1, win->y()); }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/video.png").scaledToWidth(128, Qt::SmoothTransformation), "网口通信"); + btnImg = addImg(imgsBar, QPixmap(":/imgs/video.png").scaledToWidth(128, Qt::SmoothTransformation), tr("协议调试")); connect(btnImg, &ImgBtn::clicked, this, [=](){ - auto ins = PcapWin::newIns(this); + if(pcapRe != 0 && pcapSend != 0) + { + auto ins = new PcapWin(pcapRe, pcapSend, this); + if(ins) ins->show(); + } + }); + btnImg = addImg(imgsBar, QPixmap(":/imgs/idea.png").scaledToWidth(128, Qt::SmoothTransformation), tr("模拟同步")); + connect(btnImg, &ImgBtn::clicked, this, [=](){ + auto ins = VideoWin::newIns(net_name, this); if(ins) ins->show(); }); - btnImg = addImg(imgsBar, QPixmap(":/imgs/idea.png").scaledToWidth(128, Qt::SmoothTransformation), "视频传输"); - connect(btnImg, &ImgBtn::clicked, this, [=](){ - auto ins = VideoWin::newIns(this); - ins->show(); - }); vBox->addLayout(imgsBar); - - vBox->addSpacing(16); + vBox->addSpacing(9); vBox->addWidget(new QLabel(" 硬件信息")); + table = new Table{ + {"type", "发送卡型号"}, + {"name", "名称"}, + {"link", "连接方式"}, + {"vcs", "接收卡数量"}, + {"Pinfo", "网口统计P1~Pn"}, + {"Oinfo", "其他信息", QHeaderView::Stretch}, + }; + vBox->addWidget(table); - vBox->addStretch(); + auto hstatus = new QHBoxLayout; + hstatus->addWidget(new QLabel(tr("版本:221114"))); + hstatus->addStretch(); + + auto btnNetSelect = new QPushButton("通讯选择"); + btnNetSelect->setMinimumWidth(80); + connect(btnNetSelect, &QPushButton::clicked, this, [this] { + auto name = getNetDev(this, ""); + if(name.isEmpty()) return; + //PCAP_OPENFLAG_DATATX_UDP:2,它定义了数据传输(假如是远程抓包)是否用UDP协议来处理。 + //PCAP_OPENFLAG_NOCAPTURE_RPCAP:4,它定义了远程探测器是否捕获它自己产生的数据包。 + char errbuf[PCAP_ERRBUF_SIZE]{'\0'}; + auto pcapR = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS|4|8|16, 50, errbuf); + if(pcapR == 0) { + QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf); + return; + } + auto pcapS = pcap_open_live(name.data(), 65536, 0, 50, errbuf); + if(pcapS == 0) { + QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf); + return; + } + if(pcapRe) pcap_close(pcapRe); + if(pcapSend) pcap_close(pcapSend); + pcapRe = pcapR; + pcapSend = pcapS; + QSettings config(QApplication::applicationDirPath()+"/ledset.config", QSettings::IniFormat);//QDir::currentPath()为exe位置 + config.beginGroup("GLOBAL"); + config.setValue("net_name", net_name = name); + config.endGroup(); + }); + hstatus->addWidget(btnNetSelect); + + auto btnRefresh = new QPushButton(tr("刷新")); + btnRefresh->setMinimumWidth(80); + connect(btnRefresh, &QPushButton::clicked, this, [this] { + auto bytes = QByteArray::fromHex("55 55 01 AD 00 01 FF FF FF FF 00 00 00 00 B0 00 01 00 00 00 3B 11 0A 6C 00 00 00 00 21 44 DF 1C"); + if(pcap_sendpacket(pcapSend, (u_char*)bytes.data(), bytes.size())) { + QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+pcap_geterr(pcapSend)); + return; + } + }); + hstatus->addWidget(btnRefresh); + + vBox->addLayout(hstatus); + + QSettings config(QApplication::applicationDirPath()+"/ledset.config", QSettings::IniFormat); + config.beginGroup("GLOBAL");//保存数据 + auto name = config.value("net_name").toByteArray(); + name = getNetDev(this, name); + if(! name.isEmpty()) { + char errbuf[PCAP_ERRBUF_SIZE]{'\0'}; + pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS|4|8|16, 50, errbuf); + if(pcapRe == 0) QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf); + else { + pcapSend = pcap_open_live(name.data(), 65536, 0, 50, errbuf); + if(pcapSend == 0) QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf); + else config.setValue("net_name", net_name = name); + } + } + config.endGroup(); } + +MainPcapThread::MainPcapThread(pcap_t *pcap) : pcap(pcap) { + connect(this, &QThread::finished, this, &QThread::deleteLater); +} + +void MainPcapThread::run() { + pcap_pkthdr *header; + const u_char *data; + int res; + while((res = pcap_next_ex(pcap, &header, &data)) >= 0) { + if(status==2) return; + if(status==1 || res == 0) continue; //超时 + //if(data[0]!=0x55 || data[1]!=0x55 || (data[6] ==0xff && data[7] ==0xff && data[8] == 0xff && data[9] == 0xff)) continue; + if(data[0]!=0x55 || data[1]!=0x55 ) + continue; + emit onMsg(data,header->caplen); + } + emit onError(pcap_geterr(pcap)); +} +void MainWin::ProNetData(const u_char *data,int len) +{ + if(table != nullptr) + { + uint32_t pio=data[14] << 24 | data[15] <<16 | data[16] <<8 | data[17] ; + uint8_t srv = data[3]; + if(srv == 0xEA && pio == 0xB0000101 ) + { + table->setRowCount(1); + uint16_t pIndex = data[10]<<8 | data[11]; + uint32_t virtualVCM = pIndex ; + uint32_t vcsNum = data[24] << 24 | data[25] <<16 | data[26] <<8 | data[27] ; + table->setValue(0, "type", tr("虚拟设备")); + table->setValue(0, "name", tr("网口:")+QString::number(virtualVCM)); + table->setValue(0, "link", "千兆网直连"); + table->setValue(0, "vcs", QString::number(vcsNum)); + table->setValue(0, "Pinfo", "P:"+QString::number(virtualVCM)); + table->setValue(0, "Oinfo", "备注:可直接配屏,无需发送卡"); + } + else + { + QString data_str; + for(uint i=0; i status{0}; +protected: + void run(); +signals: + void onMsg(const u_char *data,int len); + void onError(char *); +}; class MainWin : public BaseWin { Q_OBJECT public: MainWin(); QWidget *win{0}; + QByteArray net_name; + pcap_t *pcapRe{0}; + pcap_t *pcapSend{0}; + MainPcapThread *thd{0}; + Table *table = nullptr; +protected slots: + void ProNetData(const u_char *data,int len); + }; #endif // MAINWIN_H diff --git a/ledset/pcapwin.cpp b/ledset/pcapwin.cpp index 6b142f5..bb8effe 100644 --- a/ledset/pcapwin.cpp +++ b/ledset/pcapwin.cpp @@ -1,5 +1,4 @@ #include "pcapwin.h" -#include "table.h" #include #include #include @@ -7,150 +6,28 @@ #include #include #include - -PcapWin *PcapWin::newIns(QWidget *parent) { - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *devs; - if(pcap_findalldevs(&devs, errbuf) == -1) { - QMessageBox::critical(parent, "Error", QString("寻找网卡失败")+errbuf); - return 0; - } - auto table = new Table{ - {"name", "网卡名称", 400}, - {"desc", "网卡描述", 300}, - {"loopback","Loopback"}, - {"ip","IP"}, - {"netmask","Netmask"}, - {"broadaddr","Broad Addr"}, - {"dstaddr","Dst Addr"} - }; - - pcap_if_t *device = 0; - for(pcap_if_t *dev = devs; dev; dev = dev->next) { - pcap_addr_t *a; - for(a=dev->addresses; a; a=a->next) { - auto sa_family = a->addr->sa_family; - if(sa_family==AF_INET) { - auto rr = table->rowCount(); - table->setRowCount(rr+1); - table->setValue(rr, "name", dev->name); - table->setValue(rr, "desc", dev->description); - table->setValue(rr, "loopback", (dev->flags & PCAP_IF_LOOPBACK)?"True":"False"); - auto ip = (u_char *) &((sockaddr_in *) a->addr)->sin_addr.s_addr; - table->setValue(rr, "ip", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - if(a->netmask) { - ip = (u_char *) &((sockaddr_in *) a->netmask)->sin_addr.s_addr; - table->setValue(rr, "netmask", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(a->broadaddr) { - ip = (u_char *) &((sockaddr_in *) a->broadaddr)->sin_addr.s_addr; - table->setValue(rr, "broadaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(a->dstaddr) { - ip = (u_char *) &((sockaddr_in *) a->dstaddr)->sin_addr.s_addr; - table->setValue(rr, "dstaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(device==0) device = dev; - } - } - } - pcap_freealldevs(devs); - - auto rowCnt = table->rowCount(); - if(rowCnt==0) { - table->deleteLater(); - QMessageBox::critical(parent, "Error", "没找到 internet 设备"); - return 0; - } else if(rowCnt==1) { - table->deleteLater(); - auto name = table->item(0, "name")->text().toLocal8Bit(); - auto pcapRe = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapRe == 0) { - QMessageBox::critical(parent, "Error", QString("打开网卡失败")+errbuf); - return 0; - } - auto pcapSe = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapSe == 0) { - QMessageBox::critical(parent, "Error", QString("打开网卡失败")+errbuf); - return 0; - } - return new PcapWin(pcapRe, pcapSe, parent); - } else { - auto dlg = new BaseDlg(parent); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->setWindowTitle("选择网卡"); - dlg->resize(1200, 300); - - auto vBox = new QVBoxLayout(dlg->center); - vBox->setContentsMargins(0,0,0,0); - vBox->setSpacing(3); - vBox->addSpacing(30); - - table->setDefs(); - table->setSelectionMode(QAbstractItemView::SingleSelection); - table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - table->selectRow(0); - pcap_t *pcapRece; - pcap_t *pcapSend; - connect(table, &Table::cellDoubleClicked, dlg, [dlg, table, &pcapRece, &pcapSend, &errbuf](int row) { - auto name = table->item(row, "name")->text().toLocal8Bit(); - pcapRece = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapRece == 0) { - QMessageBox::critical(dlg, "Error", QString("打开网卡失败")+errbuf); - return; - } - pcapSend = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapSend == 0) { - QMessageBox::critical(dlg, "Error", QString("打开网卡失败")+errbuf); - return; - } - dlg->accept(); - }); - vBox->addWidget(table); - - auto hBox = new QHBoxLayout; - hBox->addStretch(); - auto btnOk = new QPushButton("确定"); - btnOk->setMinimumWidth(80); - connect(btnOk, &QPushButton::clicked, dlg, [dlg, table, &pcapRece, &pcapSend, &errbuf] { - auto sels = table->selectedRanges(); - if(sels.isEmpty()) { - QMessageBox::warning(dlg, "Warning", "请选择网卡"); - return; - } - auto name = table->item(sels[0].topRow(), "name")->text().toLocal8Bit(); - pcapRece = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapRece == 0) { - QMessageBox::critical(dlg, "Error", QString("打开网卡失败")+errbuf); - return; - } - pcapSend = pcap_open(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, 0, errbuf); - if(pcapSend == 0) { - QMessageBox::critical(dlg, "Error", QString("打开网卡失败")+errbuf); - return; - } - dlg->accept(); - }); - hBox->addWidget(btnOk); - - hBox->addStretch(); - - auto btnClose = new QPushButton("关闭"); - btnClose->setMinimumWidth(80); - connect(btnClose, &QPushButton::clicked, dlg, &QDialog::reject); - hBox->addWidget(btnClose); - hBox->addStretch(); - - vBox->addLayout(hBox); - if(QDialog::Accepted==dlg->exec()) return new PcapWin(pcapRece, pcapSend, parent); - return 0; - } -} +#include "globalfunc.h" +//PcapWin *PcapWin::newIns(QWidget *parent) { +// auto name = getNetDev(parent); +// if(name.isEmpty()) return 0; +// char errbuf[PCAP_ERRBUF_SIZE]{'\0'}; +// auto pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS, 50, errbuf); +// if(pcapRe == 0) { +// QMessageBox::critical(parent, "Error", QString(tr("打开网卡失败"))+errbuf); +// return 0; +// } +// auto pcapSend = pcap_open_live(name.data(), 65536, 0, 50, errbuf); +// if(pcapSend == 0) { +// QMessageBox::critical(parent, "Error", QString(tr("打开网卡失败"))+errbuf); +// return 0; +// } +// return new PcapWin(pcapRe, pcapSend, parent); +//} PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{parent}, pcap(pcapSend) { setWindowModality(Qt::WindowModal); setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle("网口通信"); + setWindowTitle(tr("网口通信")); resize(1024, 720); auto vBox = new QVBoxLayout(center); @@ -161,17 +38,17 @@ PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{ auto fdReceive = new QTextEdit; fdReceive->setFontFamily("Consolas"); fdReceive->setReadOnly(true); - fdReceive->document()->setMaximumBlockCount(1000); + fdReceive->document()->setMaximumBlockCount(200); auto hBox = new QHBoxLayout; { auto vBox = new QVBoxLayout; auto hBox2 = new QHBoxLayout; - hBox2->addWidget(new QLabel("接收:")); + hBox2->addWidget(new QLabel(tr("接收:"))); hBox2->addStretch(); - auto fdStart = new QRadioButton("开始"); + auto fdStart = new QRadioButton(tr("开始")); fdStart->setChecked(true); connect(fdStart, &QPushButton::toggled, this, [this](bool checked) { thd->status = checked ? 0 : 1; @@ -179,12 +56,12 @@ PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{ hBox2->addWidget(fdStart); hBox2->addSpacing(20); - auto fdEnd = new QRadioButton("暂停"); + auto fdEnd = new QRadioButton(tr("暂停")); hBox2->addWidget(fdEnd); hBox2->addStretch(); - auto btnClear = new QPushButton("清除"); + auto btnClear = new QPushButton(tr("清除")); btnClear->setMinimumWidth(120); connect(btnClear, &QPushButton::clicked, fdReceive, &QTextEdit::clear); hBox2->addWidget(btnClear); @@ -208,13 +85,13 @@ PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{ auto hBox2 = new QHBoxLayout; hBox2->addStretch(); - auto btnSend = new QPushButton("发送"); + auto btnSend = new QPushButton(tr("发送")); btnSend->setMinimumWidth(120); hBox2->addWidget(btnSend); hBox2->addStretch(); - auto btnClear = new QPushButton("清除"); + auto btnClear = new QPushButton(tr("清除")); btnClear->setMinimumWidth(120); hBox2->addWidget(btnClear); hBox2->addStretch(); @@ -236,7 +113,7 @@ PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{ if(bytes.size() % 2) bytes.append('0'); bytes = QByteArray::fromHex(bytes); if(pcap_sendpacket(pcap, (u_char*)bytes.data(), bytes.size())) { - QMessageBox::critical(this, "Error", QString("发送失败: ")+pcap_geterr(pcap)); + QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+pcap_geterr(pcap)); return; } }); diff --git a/ledset/pcapwin.h b/ledset/pcapwin.h index d7548e9..fb086fe 100644 --- a/ledset/pcapwin.h +++ b/ledset/pcapwin.h @@ -10,7 +10,7 @@ class PcapThread : public QThread { public: explicit PcapThread(pcap *pcap); ~PcapThread() { - pcap_close(pcap); + //pcap_close(pcap); } pcap *pcap; std::atomic status{0}; @@ -24,11 +24,11 @@ signals: class PcapWin : public BaseWin { Q_OBJECT public: - static PcapWin *newIns(QWidget *); +// static PcapWin *newIns(QWidget *); explicit PcapWin(pcap *, pcap *, QWidget *parent = nullptr); ~PcapWin() { - pcap_close(pcap); + //pcap_close(pcap); thd->status = 2; } PcapThread *thd{0}; diff --git a/ledset/res.qrc b/ledset/res.qrc index ed08cdb..7270d14 100644 --- a/ledset/res.qrc +++ b/ledset/res.qrc @@ -1,9 +1,11 @@ 128.ico + imgs/checkbox-check.png + imgs/checkbox-un.png + imgs/radio-check.png imgs/radio-un.png - imgs/radio-check.png - imgs/bright.png + imgs/bright.png imgs/correct.png imgs/expert.png imgs/fast.png @@ -11,13 +13,15 @@ imgs/multi.png imgs/idea.png imgs/video.png - imgs/conn1.png - imgs/conn2.png - imgs/conn3.png - imgs/conn4.png - imgs/conn5.png - imgs/conn6.png - imgs/conn7.png - imgs/conn8.png + imgs/conn1.png + imgs/conn2.png + imgs/conn3.png + imgs/conn4.png + imgs/conn5.png + imgs/conn6.png + imgs/conn7.png + imgs/conn8.png + imgs/macos-minimize.png + imgs/close.png diff --git a/ledset/table.cpp b/ledset/table.cpp index 799cb1e..8fc506f 100644 --- a/ledset/table.cpp +++ b/ledset/table.cpp @@ -8,10 +8,7 @@ Table::Table(std::initializer_list colAttrs, QWidget *parent) : QTableW item->setText(it->text); item->setData(0x99, it->width); if(it->width > 0) horizontalHeader()->resizeSection(i, it->width); - else if(it->width < 0) { - if(it->width == Stretch) horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch); - if(it->width == ResizeToContents) horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); - } + if(it->resizeMode != QHeaderView::Interactive) horizontalHeader()->setSectionResizeMode(i, it->resizeMode); mFieldMap.insert(it->field, i++); } } @@ -21,11 +18,11 @@ int Table::sizeHintForColumn(int column) const { int width = item->data(0x99).toInt(); if(width==0) return QTableWidget::sizeHintForColumn(column); auto header = horizontalHeader(); - if(header->sectionResizeMode(column)!=QHeaderView::ResizeToContents) return QTableWidget::sizeHintForColumn(column); + if(header->sectionResizeMode(column) != QHeaderView::ResizeToContents) return QTableWidget::sizeHintForColumn(column); int colCnt = columnCount(); int remainWidth = header->width(), stretchWidth = width; for(int cc=0; ccsectionResizeMode(cc)==QHeaderView::ResizeToContents) stretchWidth += item->data(0x99).toInt(); + if(header->sectionResizeMode(cc) == QHeaderView::ResizeToContents) stretchWidth += item->data(0x99).toInt(); else remainWidth -= item->data(0x99).toInt(); } if(remainWidth<=0) return QTableWidget::sizeHintForColumn(column); diff --git a/ledset/table.h b/ledset/table.h index 7fadef6..01e3669 100644 --- a/ledset/table.h +++ b/ledset/table.h @@ -1,66 +1,72 @@ -#ifndef TABLE_H -#define TABLE_H - -#include -#include - -struct ColAttr { - QString field; - QString text; - int width{0}; -}; -class Table : public QTableWidget { - Q_OBJECT -public: - enum ResizeMode { - Stretch = -0x1000000, - ResizeToContents - }; - explicit Table(QWidget *parent = nullptr) : QTableWidget{parent} {} - Table(std::initializer_list colAttrs, QWidget *parent = nullptr); - - inline Table *setDefs() { - setSelectionBehavior(QTableWidget::SelectRows); - setEditTriggers(QAbstractItemView::NoEditTriggers); - setAlternatingRowColors(true); - horizontalHeader()->setBackgroundRole(QPalette::Window); - return this; - } - inline Table *setStretch() { - horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - return this; - } - inline Table *setResizeToContents() { - horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - return this; - } - - auto item(int row, QString column) { - auto col = mFieldMap[column]; - return QTableWidget::item(row, col); - } - void setItem(int row, QString column, QTableWidgetItem *item) { - auto col = mFieldMap[column]; - QTableWidget::setItem(row, col, item); - } - void setValue(int row, QString column, const QString &text) { - auto col = mFieldMap[column]; - QTableWidget::setItem(row, col, new QTableWidgetItem(text)); - } - - auto cellWidget(int row, QString column) { - auto col = mFieldMap[column]; - return QTableWidget::cellWidget(row, col); - } - void setCellWidget(int row, QString column, QWidget *widget) { - auto col = mFieldMap[column]; - QTableWidget::setCellWidget(row, col, widget); - } - - QMap mFieldMap; - -protected: - int sizeHintForColumn(int column) const override; -}; - -#endif // TABLE_H +#ifndef TABLE_H +#define TABLE_H + +#include +#include + +struct ColAttr { + ColAttr(QString field, QString text, int width = 0, QHeaderView::ResizeMode resizeMode = QHeaderView::Interactive) : field(field), text(text), width(width), resizeMode(resizeMode) {} + ColAttr(QString field, QString text, QHeaderView::ResizeMode resizeMode) : field(field), text(text), resizeMode(resizeMode) {} + QString field; + QString text; + int width{0}; + QHeaderView::ResizeMode resizeMode{QHeaderView::Interactive}; +}; +class Table : public QTableWidget { + Q_OBJECT +public: + explicit Table(QWidget *parent = nullptr) : QTableWidget{parent} {} + Table(std::initializer_list colAttrs, QWidget *parent = nullptr); + + inline Table *setDefs() { + setSelectionBehavior(QTableWidget::SelectRows); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setAlternatingRowColors(true); + horizontalHeader()->setBackgroundRole(QPalette::Window); + return this; + } + inline Table *setStretch() { + horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + return this; + } + inline Table *setResizeToContents() { + horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + return this; + } + + void setHeaderText(QString column, QString text) { + auto col = mFieldMap[column]; + auto item = horizontalHeaderItem(col); + if(item==0) setHorizontalHeaderItem(col, item = new QTableWidgetItem()); + item->setText(text); + } + + auto item(int row, QString column) { + auto col = mFieldMap[column]; + return QTableWidget::item(row, col); + } + void setItem(int row, QString column, QTableWidgetItem *item) { + auto col = mFieldMap[column]; + QTableWidget::setItem(row, col, item); + } + void setValue(int row, QString column, const QString &text) { + auto col = mFieldMap[column]; + QTableWidget::setItem(row, col, new QTableWidgetItem(text)); + } + + auto cellWidget(int row, QString column) { + auto col = mFieldMap[column]; + return QTableWidget::cellWidget(row, col); + } + void setCellWidget(int row, QString column, QWidget *widget) { + auto col = mFieldMap[column]; + QTableWidget::setCellWidget(row, col, widget); + } + + QMap mFieldMap; + +protected: + int sizeHintForColumn(int column) const override; +}; + +#endif // TABLE_H diff --git a/ledset/translations/app_en.ts b/ledset/translations/app_en.ts index edd0d34..06847c5 100644 --- a/ledset/translations/app_en.ts +++ b/ledset/translations/app_en.ts @@ -1,3 +1,677 @@ - + + + BrightWin + + + 亮度控制 + + + + + 亮度设置 + + + + + 亮度 + + + + + 对比度 + + + + + + 固化 + + + + + 色彩调整 + + + + + 红 + + + + + 绿 + + + + + 蓝 + + + + + Gamma 调节 + + + + + ExpertScreenConnWin + + + 起始位置 + + + + + X坐标: + + + + + Y坐标: + + + + + 接收卡设置 + + + + + 卡列数: + + + + + 卡行数: + + + + + 卡宽度: + + + + + 卡高度: + + + + + 网口选择 + + + + + 快速串线: + + + + + 重新开始 + + + + + 后退 + + + + + 接收卡: + + + + + 宽度: + + + + + ExpertSmartPointSetWin + + + 智能走点参数配置 + + + + + 基本参数 + + + + + 模组宽度: + + + + + 模组高度: + + + + + 数据组数: + + + + + 驱动芯片: + + + + + 译码方式: + + + + + 138译码 + + + + + 分组方式: + + + + + 三线并行 + + + + + 三色1点串 + + + + + 三色8点串 + + + + + 三色16点串 + + + + + 扫描行数 + + + + + 根据亮线的行/列数确定扫描行/列数: + + + + + 行 + + + + + 列 + + + + + 亮线的行/列数: + + + + + 芯片245版本: + + + + + 数据线颜色 + + + + + 依次点击以下状态, 根据模组颜色选择对应颜色 + + + + + 状态1 + + + + + + + 红 + + + + + + + 绿 + + + + + + + 蓝 + + + + + + + 黑 + + + + + 状态2 + + + + + 状态3 + + + + + 插入虚点 + + + + + 重新走点 + + + + + + 完成 + + + + + + 提示 + + + + + 列走完 + + + + + 行走完 + + + + + 第一扫灯数: + + + + + 实: 虚: + + + + + 上一步 + + + + + 下一步 + + + + + 保存文件 + + + + + 保存成功 + + + + + 保存设置 + + + + + 文件名称: + + + + + 1X2_3扫 + + + + + 保存路径: + + + + + 选择路径 + + + + + 选择存储文件的目录 + + + + + 返回 + + + + + ExpertWin + + + 数据线颜色 + + + + + 模组抽行设置 + + + + + 宽度 + + + + + 高度 + + + + + 多开设置 + + + + + 级联方向 + + + + + 无 + + + + + 双开 + + + + + 三开 + + + + + 四开 + + + + + 从左到右 + + + + + 从右到左 + + + + + 从上到下 + + + + + 从下到上 + + + + + 选择180度 + + + + + 数据交换 + + + + + 平面造型 + + + + + 效果测试 + + + + + 视觉刷新率: + + + + + DCLK频率: + + + + + DCLK相位: + + + + + DCLK占空比: + + + + + 换行时间(ns): + + + + + 亮度有效率: + + + + + 100% + + + + + GCLK频率: + + + + + 灰度级数: + + + + + GCLK占空比: + + + + + 换行位置(ns): + + + + + 更多设置 + + + + + 打开配置 + + + + + 保存配置 + + + + + 发送数据 + + + + + 固化数据 + + + + + 回读数据 + + + + + 状态: + + + + + 显示屏连接(正面看屏) + + + + + MainWin + + + 专家调屏 + + + + + 亮度控制 + + + + + 相机矫正 + + + + + 屏体监控 + + + + + 多功能卡 + + + + + 协议调试 + + + + + 模拟同步 + + + + + 版本:221114 + + + + + + + + 打开网卡失败 + + + + + 刷新 + + + + + 发送失败: + + + + + 虚拟设备 + + + + + 网口: + + + + + PcapWin + + + 网口通信 + + + + + 接收: + + + + + 开始 + + + + + 暂停 + + + + + + 清除 + + + + + 发送 + + + + + 发送失败: + + + + diff --git a/ledset/videowin.cpp b/ledset/videowin.cpp index 495f0f9..c1241e0 100644 --- a/ledset/videowin.cpp +++ b/ledset/videowin.cpp @@ -1,5 +1,4 @@ #include "videowin.h" -#include "table.h" #include "gqt.h" #include "crc.h" #include @@ -15,115 +14,7 @@ using namespace std; -QByteArray getNetDev(QWidget *parent) { - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *devs; - if(pcap_findalldevs(&devs, errbuf) == -1) { - QMessageBox::critical(parent, "Error", QString("寻找网卡失败")+errbuf); - return QByteArray(); - } - auto table = new Table{ - {"name", "网卡名称", 400}, - {"desc", "网卡描述", 300}, - {"loopback","Loopback"}, - {"ip","IP"}, - {"netmask","Netmask"}, - {"broadaddr","Broad Addr"}, - {"dstaddr","Dst Addr"} - }; - - pcap_if_t *device = 0; - for(pcap_if_t *dev = devs; dev; dev = dev->next) { - pcap_addr_t *a; - for(a=dev->addresses; a; a=a->next) { - auto sa_family = a->addr->sa_family; - if(sa_family==AF_INET) { - auto rr = table->rowCount(); - table->setRowCount(rr+1); - table->setValue(rr, "name", dev->name); - table->setValue(rr, "desc", dev->description); - table->setValue(rr, "loopback", (dev->flags & PCAP_IF_LOOPBACK)?"True":"False"); - auto ip = (u_char *) &((sockaddr_in *) a->addr)->sin_addr.s_addr; - table->setValue(rr, "ip", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - if(a->netmask) { - ip = (u_char *) &((sockaddr_in *) a->netmask)->sin_addr.s_addr; - table->setValue(rr, "netmask", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(a->broadaddr) { - ip = (u_char *) &((sockaddr_in *) a->broadaddr)->sin_addr.s_addr; - table->setValue(rr, "broadaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(a->dstaddr) { - ip = (u_char *) &((sockaddr_in *) a->dstaddr)->sin_addr.s_addr; - table->setValue(rr, "dstaddr", QString::asprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])); - } - if(device==0) device = dev; - } - } - } - pcap_freealldevs(devs); - - auto rowCnt = table->rowCount(); - if(rowCnt==0) { - table->deleteLater(); - QMessageBox::critical(parent, "Error", "没找到 internet 设备"); - return QByteArray(); - } else if(rowCnt==1) { - table->deleteLater(); - return table->item(0, "name")->text().toLocal8Bit(); - } else { - auto dlg = new BaseDlg(parent); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->setWindowTitle("选择网卡"); - dlg->resize(900, 300); - - auto vBox = new QVBoxLayout(dlg->center); - vBox->setContentsMargins(0,0,0,0); - vBox->setSpacing(3); - vBox->addSpacing(30); - - table->setDefs(); - table->setSelectionMode(QAbstractItemView::SingleSelection); - table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - table->selectRow(0); - QByteArray name; - dlg->connect(table, &Table::cellDoubleClicked, dlg, [dlg, table, &name](int row) { - name = table->item(row, "name")->text().toLocal8Bit(); - dlg->accept(); - }); - vBox->addWidget(table); - - auto hBox = new QHBoxLayout; - hBox->addStretch(); - auto btnOk = new QPushButton("确定"); - btnOk->setMinimumWidth(80); - dlg->connect(btnOk, &QPushButton::clicked, dlg, [dlg, table, &name] { - auto sels = table->selectedRanges(); - if(sels.isEmpty()) { - QMessageBox::warning(dlg, "Warning", "请选择网卡"); - return; - } - name = table->item(sels[0].topRow(), "name")->text().toLocal8Bit(); - dlg->accept(); - }); - hBox->addWidget(btnOk); - - hBox->addStretch(); - - auto btnClose = new QPushButton("关闭"); - btnClose->setMinimumWidth(80); - dlg->connect(btnClose, &QPushButton::clicked, dlg, &QDialog::reject); - hBox->addWidget(btnClose); - hBox->addStretch(); - - vBox->addLayout(hBox); - dlg->exec(); - return name; - } -} - -VideoWin *VideoWin::newIns(QWidget *parent) { - auto name = getNetDev(parent); +VideoWin *VideoWin::newIns(QByteArray &name, QWidget *parent) { if(name.isEmpty()) return 0; char errbuf[PCAP_ERRBUF_SIZE]{'\0'}; auto pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS, 50, errbuf); @@ -164,13 +55,38 @@ VideoWin::VideoWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWi fdHeight->setValue(360); hBox->addWidget(fdHeight); + + hBox->addWidget(new QLabel("截图间隔(ms)")); + fdMsecCapScr = new QSpinBox; + fdMsecCapScr->setRange(1, 1000); + fdMsecCapScr->setValue(17); + hBox->addWidget(fdMsecCapScr); + hBox->addSpacing(20); + + fdShowImg = new QRadioButton("关闭显示"); + fdShowImg->setChecked(showImg); + hBox->addWidget(fdShowImg); + + hBox->addSpacing(20); + + hBox->addWidget(new QLabel("接收线程优先级")); + fdYxj = new QSpinBox; + fdYxj->setRange(0, 7); + fdYxj->setValue(6); + + connect(fdYxj, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, [=](int value) { + if(thdRece) thdRece->setPriority(QThread::Priority(value)); + }); + hBox->addWidget(fdYxj); + + hBox->addSpacing(20); auto fdStart = new QRadioButton("发送"); connect(fdStart, &QRadioButton::toggled, this, [this](bool checked) { if(! checked) return; screen = QGuiApplication::primaryScreen(); - if(timerId==0) timerId = startTimer(17); + if(timerId==0) timerId = startTimer(fdMsecCapScr->value()); }); hBox->addWidget(fdStart); hBox->addSpacing(20); @@ -206,11 +122,22 @@ VideoWin::VideoWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWi auto fdCanvas = new Canvas; vBox->addWidget(fdCanvas, 1); + connect(fdShowImg, &QRadioButton::toggled, [=](bool checked) { + qDebug()<<"fdShowImg"<showImg = checked; + if(! checked) { + fdCanvas->img = QImage(); + fdCanvas->update(); + } + }); + thdRece = new VideoRecThread(pcapRece); connect(thdRece, &QThread::finished, this, [this] { thdRece = 0; }); connect(thdRece, &VideoRecThread::onMsg, fdCanvas, [this, fdCanvas](QImage img, int lostTimes, int lostPkts) { + if(! showImg) return; fdCanvas->img = img; fdCanvas->update(); if(lostPkts==0) return; @@ -219,7 +146,7 @@ VideoWin::VideoWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWi fdLostTimes->setText(QString::number(this->lostTimes)); fdLostPkts->setText(QString::number(this->lostPkts)); }); - thdRece->start(QThread::TimeCriticalPriority); + thdRece->start(QThread::Priority(fdYxj->value()));//HighestPriority //InheritPriority //TimeCriticalPriority sendThd = new VideoSendThread(pcapSend); connect(sendThd, &QThread::finished, this, [this] { @@ -283,6 +210,7 @@ void VideoSendThread::run() { bytes.append(img.width()>>8).append(img.width()).append(img.height()>>8).append(img.height()); crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-4, 4); bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); + //发送帧开始指令包 auto queue = pcap_sendqueue_alloc(img.width()*img.height()*4); { struct pcap_pkthdr pktheader; @@ -300,6 +228,7 @@ void VideoSendThread::run() { auto bytesPerLine = img.bytesPerLine(); auto bits = img.constBits(); idx = 0; + //按行发送图像数据包 for(int i=0; i once) dataLen = once; @@ -313,7 +242,7 @@ void VideoSendThread::run() { bytes.append(2, 0); //应答填充项 crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2); bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); - bytes.append(idx>>24).append(idx>>16).append(idx>>8).append(idx); + bytes.append(idx>>24).append(idx>>16).append(idx>>8).append(idx);//包序号 idx++; bytes.append((const char*)bits + i * bytesPerLine + j, dataLen - 4); crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-dataLen, dataLen); @@ -334,6 +263,7 @@ void VideoSendThread::run() { crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2); bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); pktheader.len = pktheader.caplen = bytes.size(); + //发送帧结束指令包 if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) { onErr(QString("添加结束失败: ")+pcap_geterr(pcap)); goto end; @@ -348,11 +278,10 @@ void VideoSendThread::run() { pcap_sendqueue_destroy(queue); } } - /* Callback function invoked by libpcap for every incoming packet */ -void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { +//void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { -} +//} VideoRecThread::VideoRecThread(pcap_t *pcap) : pcap(pcap) { connect(this, &QThread::finished, this, &QThread::deleteLater); @@ -366,7 +295,7 @@ void VideoRecThread::run() { int lostTimes{0}, lostPkts{0}; while((res = pcap_next_ex(pcap, &header, &data)) >= 0) { if(status==2) return; - if(status==1 || res == 0) continue; //超时 + if(status==1 || res == 0 || !showImg) continue; //超时 if(header->caplen<24) continue; if(data[0]!=0x55 || data[1]!=0x55) continue; if(data[2]==0x9a && data[3]==0x3d) { @@ -396,7 +325,7 @@ void VideoRecThread::run() { emit onErr(pcap_geterr(pcap)); } -void Canvas::paintEvent(QPaintEvent *event) { +void Canvas::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawImage(0, 0, img); } diff --git a/ledset/videowin.h b/ledset/videowin.h index 88ad00f..c7fcd77 100644 --- a/ledset/videowin.h +++ b/ledset/videowin.h @@ -9,13 +9,12 @@ #include #include #include +#include #include "Win32-Extensions.h" #pragma comment(lib, "wpcap.lib") #pragma comment(lib, "Ws2_32.lib") -QByteArray getNetDev(QWidget *parent); - class VideoSendThread : public QThread { Q_OBJECT public: @@ -41,6 +40,7 @@ public: } pcap *pcap; std::atomic status{0}; + bool showImg{true}; protected: void run(); signals: @@ -58,9 +58,8 @@ protected: class VideoWin : public BaseWin { Q_OBJECT public: - static VideoWin *newIns(QWidget *); + static VideoWin *newIns(QByteArray &, QWidget *); - explicit VideoWin(pcap *, pcap *, QWidget *parent = nullptr); ~VideoWin() { if(thdRece) thdRece->status = 2; if(sendThd) sendThd->status = 2; @@ -70,13 +69,16 @@ public: VideoSendThread *sendThd{0}; QScreen *screen; int timerId{0}; - QSpinBox *fdWidth, *fdHeight; + QSpinBox *fdWidth, *fdHeight, *fdMsecCapScr,*fdYxj; + QRadioButton *fdShowImg; + bool showImg{true}; QRadioButton *fdEnd; QLabel *fdInfo, *fdLostTimes, *fdLostPkts; QString info; qint64 last_epoch{0}; int lostTimes{0}, lostPkts{0}; protected: + explicit VideoWin(pcap *, pcap *, QWidget *parent = nullptr); void timerEvent(QTimerEvent *event) override; };