This commit is contained in:
Gangphon 2023-08-21 11:21:00 +08:00
parent 26f8cb58ee
commit 0ee263c870
57 changed files with 823 additions and 23129 deletions

4
.gitignore vendored
View File

@ -24,6 +24,6 @@ build-*
*.autosave
*-old/*
*-leyide/*
*OK-*/*
*.DS_Store

View File

@ -1,5 +1,5 @@
#include "expertboxlayoutwin.h"
#include "moduleunit.h"
#include "expertwin.h"
#include "gutil/qgui.h"
#include "gutil/qjson.h"
#include "globalfunc.h"
@ -8,16 +8,21 @@
#include <QMessageBox>
#include <QScrollArea>
#include <QFileDialog>
#include <QPainter>
#include <QMouseEvent>
#include <QToolButton>
#include <QPainterPath>
ExpertBoxLayoutWin::ExpertBoxLayoutWin(QWidget *parent) : BaseWin{parent} {
ExpertBoxLayoutWin::ExpertBoxLayoutWin(ExpertWin *parent) : BaseWin{parent} {
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle("箱体高级布局");
resize(1024, 720);
setStyleSheet("QToolButton {border: none; }");
auto vBox = new VBox(center);
vBox->setContentsMargins(0,0,0,0);
vBox->setSpacing(3);
vBox->addLayout(addBtns(new QHBoxLayout()));
vBox->addLayout(addBtns(new QHBoxLayout));
auto hBox = new HBox(vBox);
vBox = new VBox(hBox);
@ -26,22 +31,53 @@ ExpertBoxLayoutWin::ExpertBoxLayoutWin(QWidget *parent) : BaseWin{parent} {
auto grid = new Grid(vBox);
auto btnAdd = new QPushButton("添加");
connect(btnAdd, &QPushButton::clicked, this, [this] {
connect(btnAdd, &QPushButton::clicked, this, [=] {
auto file = QFileDialog::getOpenFileName(this, tr("打开单元板文件"), gFileHome, tr("单元板文件 (*.module)"));
if(file.isEmpty()) return;
gFileHome = QFileInfo(file).absolutePath();
QFile qFile(file);
if(! qFile.open(QFile::ReadOnly)) {
QMessageBox::critical(this, tr("打开单元板文件失败"), file);
return;
}
QString err;
auto json = JFrom(&qFile, &err).toObj();
auto json = JFrom(&qFile, &err);
qFile.close();
if(! err.isEmpty()) {
QMessageBox::critical(this, tr("解析 json 失败"), err+" "+file);
return;
}
new ModuleUnit(this, "J1", 0, 0, json["ModuleWidth"].toInt(), json["ModuleHeight"].toInt(), box);
QDialog dlg(this);
dlg.setWindowTitle(tr("添加模组"));
auto vBox = new VBox(&dlg);
auto hBox = new HBox(vBox);
hBox->addLabel(tr("横向数量"));
auto fdHNum = new QSpinBox;
fdHNum->setRange(1, 999);
fdHNum->setValue(1);
hBox->addWidget(fdHNum);
hBox->addStretch();
hBox = new HBox(vBox);
hBox->addLabel(tr("纵向数量"));
auto fdVNum = new QSpinBox;
fdVNum->setRange(1, 999);
fdVNum->setValue(1);
hBox->addWidget(fdVNum);
hBox->addStretch();
vBox->addStretch();
connect(vBox->addBtnBox(&dlg), &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
if(dlg.exec()!=QDialog::Accepted) return;
auto hNum = fdHNum->value();
auto vNum = fdVNum->value();
auto width = json["ModuleWidth"].toInt();
auto height = json["ModuleHeight"].toInt();
for(int vv=0; vv < vNum; ++vv) for(int hh=0; hh < hNum; ++hh) {
auto unit = new ModuleUnit(width*hh, height*vv, width, height, json.toObj(), "", box);
unit->show();
}
fdModNum->setNum(box->children().size());
box->fitSize();
});
grid->addWidget(btnAdd, 0, 0);
auto btnDel = new QPushButton("删除");
@ -51,50 +87,532 @@ ExpertBoxLayoutWin::ExpertBoxLayoutWin(QWidget *parent) : BaseWin{parent} {
auto btnRotate = new QPushButton("旋转");
grid->addWidget(btnRotate, 1, 1);
vBox->addWidget(new QLabel("HUB口编辑"));
auto btnDraw = new QPushButton("开始走线");
btnDraw->setCheckable(true);
connect(btnDraw, &QPushButton::clicked, this, [=](bool checked) {
box->isDrawing = checked;
btnDraw->setText(checked ? "结束走线" : "开始走线");
});
grid->addWidget(btnDraw, 2, 0);
auto btnClearLines = new QPushButton("清空所有走线");
connect(btnClearLines, &QPushButton::clicked, this, [=] {
for(auto btn : grpGrp->buttons()) if(btn->property("mods").isValid()) btn->setProperty("mods", QVariant());
for(auto child : box->children()) ((ModuleUnit*)child)->name = QString();
box->update();
});
grid->addWidget(btnClearLines, 3, 0);
auto btnClearLine = new QPushButton("清空当前走线");
connect(btnClearLine, &QPushButton::clicked, this, [=] {
for(auto btn : grpGrp->buttons()) {
auto mods = btn->property("mods").toList();
for(auto mod : mods) if(((ModuleUnit*) mod.value<void*>())->isSel) {
btn->setProperty("mods", QVariant());
for(auto mod : mods) ((ModuleUnit*) mod.value<void*>())->name = QString();
break;
}
}
box->update();
});
grid->addWidget(btnClearLine, 3, 1);
vBox->addLabel("数据组数设置");
auto hh = new HBox(vBox);
hh->addLabel("组数:");
auto fdGNum = new QSpinBox;
fdGNum->setRange(1, 128);
fdGNum->setValue(16);
hh->addWidget(fdGNum);
auto btnSet = new QPushButton("设置");
hh->addWidget(btnSet);
grid = new Grid(vBox);
auto btnPort = new QPushButton("端口");
grid->addWidget(btnPort, 0, 0);
auto btnManual = new QPushButton("手动");
grid->addWidget(btnManual, 0, 1);
auto btnUp = new QPushButton("上移");
grid->addWidget(btnUp, 1, 0);
auto btnDown = new QPushButton("下移");
grid->addWidget(btnDown, 1, 1);
grpGrp = new QButtonGroup(fdGNum);
connect(btnSet, &QPushButton::clicked, this, [=] {
auto newCnt = fdGNum->value();
auto oldCnt = grpGrp->buttons().size();
if(newCnt>oldCnt) for(int i=oldCnt; i<newCnt; ++i) {
auto btn = new QPushButton("G"+QString::number(i+1));
btn->setCheckable(true);
btn->setMaximumWidth(40);
btn->setFixedHeight(24);
grpGrp->addButton(btn, i);
grid->addWidget(btn, i / 4, i % 4);
} else if(newCnt<oldCnt) for(int i=oldCnt-1; i>=newCnt; --i) {
auto btn = grpGrp->button(i);
grpGrp->removeButton(btn);
grid->removeWidget(btn);
delete btn;
}
if(grpGrp->checkedButton()==0) grpGrp->buttons()[0]->setChecked(true);
});
emit btnSet->clicked();
vBox->addWidget(new QLabel("HUB口编辑"));
vBox->addWidget(new QLabel("显示"));
grid = new Grid(vBox);
auto fdHasPos = new QCheckBox("位置");
fdHasPos = new QCheckBox("位置");
fdHasPos->setChecked(true);
grid->addWidget(fdHasPos, 0, 0);
auto fdHasSize = new QCheckBox("大小");
fdHasSize = new QCheckBox("大小");
fdHasSize->setChecked(true);
grid->addWidget(fdHasSize, 0, 1);
auto fdHasConn = new QCheckBox("连接");
fdHasConn = new QCheckBox("连接");
fdHasConn->setChecked(true);
grid->addWidget(fdHasConn, 1, 0);
auto fdHasName = new QCheckBox("名称");
fdHasName = new QCheckBox("名称");
fdHasName->setChecked(true);
grid->addWidget(fdHasName, 1, 1);
auto fdHasOutline = new QCheckBox("轮廓");
fdHasOutline = new QCheckBox("轮廓");
fdHasOutline->setChecked(true);
grid->addWidget(fdHasOutline, 2, 0);
auto fdHasRotate = new QCheckBox("旋转");
grid->addWidget(fdHasRotate, 2, 1);
vBox->addWidget(new QLabel("对齐"));
hh = new HBox(vBox);
QSize imgSize(32,32);
auto bnAlignLeft = new QToolButton;
bnAlignLeft->setIconSize(imgSize);
bnAlignLeft->setIcon(QIcon(":/imgs/align-left.png"));
connect(bnAlignLeft, &QToolButton::clicked, this, [=] {
int bound = INT_MAX;
ModuleUnit* mod;
for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->x() < bound) bound = mod->x();
bool needFit = false;
if(bound != INT_MAX) for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->x() != bound) {
mod->move(bound, mod->y());
mod->mX = qRound(mod->x() / box->rate);
needFit = true;
}
if(needFit) box->fitSize();
});
hh->addWidget(bnAlignLeft);
auto bnAlignRight = new QToolButton;
bnAlignRight->setIconSize(imgSize);
bnAlignRight->setIcon(QIcon(":/imgs/align-right.png"));
connect(bnAlignRight, &QToolButton::clicked, this, [=] {
int bound = INT_MIN, temp;
ModuleUnit* mod;
for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && (temp = mod->x()+mod->width()) > bound) bound = temp;
bool needFit = false;
if(bound != INT_MIN) for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->x() != (temp = bound-mod->width())) {
mod->move(temp, mod->y());
mod->mX = qRound(mod->x() / box->rate);
needFit = true;
}
if(needFit) box->fitSize();
});
hh->addWidget(bnAlignRight);
auto bnAlignTop = new QToolButton;
bnAlignTop->setIconSize(imgSize);
bnAlignTop->setIcon(QIcon(":/imgs/align-top.png"));
connect(bnAlignTop, &QToolButton::clicked, this, [=] {
int bound = INT_MAX;
ModuleUnit* mod;
for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->y() < bound) bound = mod->y();
bool needFit = false;
if(bound != INT_MAX) for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->y() != bound) {
mod->move(mod->x(), bound);
mod->mY = qRound(mod->y() / box->rate);
needFit = true;
}
if(needFit) box->fitSize();
});
hh->addWidget(bnAlignTop);
auto bnAlignBottom = new QToolButton;
bnAlignBottom->setIconSize(imgSize);
bnAlignBottom->setIcon(QIcon(":/imgs/align-bottom.png"));
connect(bnAlignBottom, &QToolButton::clicked, this, [=] {
int bound = INT_MIN, temp;
ModuleUnit* mod;
for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && (temp = mod->y()+mod->height()) > bound) bound = temp;
bool needFit = false;
if(bound != INT_MIN) for(auto child : box->children()) if((mod = (ModuleUnit*)child)->isSel && mod->y() != (temp = bound-mod->height())) {
mod->move(mod->x(), temp);
mod->mY = qRound(mod->y() / box->rate);
needFit = true;
}
if(needFit) box->fitSize();
});
hh->addWidget(bnAlignBottom);
vBox->addWidget(new QLabel("排列"));
hh = new HBox(vBox);
auto bnArrangeLeft = new QToolButton;
bnArrangeLeft->setIconSize(imgSize);
bnArrangeLeft->setIcon(QIcon(":/imgs/arrange-left.png"));
connect(bnArrangeLeft, &QToolButton::clicked, this, [=] {
int bound = INT_MAX;
ModuleUnit* tmod;
std::vector<ModuleUnit*> mods;
for(auto child : box->children()) if((tmod = (ModuleUnit*)child)->isSel) {
auto it = mods.begin();
while(it!=mods.end() && (*it)->y() <= tmod->y()) it++;
mods.insert(it, tmod);
if(tmod->x() < bound) bound = tmod->x();
}
tmod = 0;
for(auto mod : mods) {
mod->move(bound, tmod ? tmod->y()+tmod->height() : mod->y());
tmod = mod;
mod->mX = qRound(mod->x() / box->rate);
mod->mY = qRound(mod->y() / box->rate);
}
if(! mods.empty()) box->fitSize();
});
hh->addWidget(bnArrangeLeft);
auto bnArrangeRight = new QToolButton;
bnArrangeRight->setIconSize(imgSize);
bnArrangeRight->setIcon(QIcon(":/imgs/arrange-right.png"));
connect(bnArrangeRight, &QToolButton::clicked, this, [=] {
int bound = INT_MIN;
ModuleUnit* tmod;
std::vector<ModuleUnit*> mods;
for(auto child : box->children()) if((tmod = (ModuleUnit*)child)->isSel) {
auto it = mods.begin();
while(it!=mods.end() && (*it)->y() <= tmod->y()) it++;
mods.insert(it, tmod);
if(tmod->x()+tmod->width() > bound) bound = tmod->x()+tmod->width();
}
tmod = 0;
for(auto mod : mods) {
mod->move(bound-mod->width(), tmod ? tmod->y()+tmod->height() : mod->y());
tmod = mod;
mod->mX = qRound(mod->x() / box->rate);
mod->mY = qRound(mod->y() / box->rate);
}
if(! mods.empty()) box->fitSize();
});
hh->addWidget(bnArrangeRight);
auto bnArrangeTop = new QToolButton;
bnArrangeTop->setIconSize(imgSize);
bnArrangeTop->setIcon(QIcon(":/imgs/arrange-top.png"));
connect(bnArrangeTop, &QToolButton::clicked, this, [=] {
int bound = INT_MAX;
ModuleUnit* tmod;
std::vector<ModuleUnit*> mods;
for(auto child : box->children()) if((tmod = (ModuleUnit*)child)->isSel) {
auto it = mods.begin();
while(it!=mods.end() && (*it)->x() <= tmod->x()) it++;
mods.insert(it, tmod);
if(tmod->y() < bound) bound = tmod->y();
}
tmod = 0;
for(auto mod : mods) {
mod->move(tmod ? tmod->x()+tmod->width() : mod->x(), bound);
tmod = mod;
mod->mX = qRound(mod->x() / box->rate);
mod->mY = qRound(mod->y() / box->rate);
}
if(! mods.empty()) box->fitSize();
});
hh->addWidget(bnArrangeTop);
auto bnArrangeBottom = new QToolButton;
bnArrangeBottom->setIconSize(imgSize);
bnArrangeBottom->setIcon(QIcon(":/imgs/arrange-bottom.png"));
connect(bnArrangeBottom, &QToolButton::clicked, this, [=] {
int bound = INT_MIN;
ModuleUnit* tmod;
std::vector<ModuleUnit*> mods;
for(auto child : box->children()) if((tmod = (ModuleUnit*)child)->isSel) {
auto it = mods.begin();
while(it!=mods.end() && (*it)->x() <= tmod->x()) it++;
mods.insert(it, tmod);
if(tmod->y()+tmod->height() > bound) bound = tmod->y()+tmod->height();
}
tmod = 0;
for(auto mod : mods) {
mod->move(tmod ? tmod->x()+tmod->width() : mod->x(), bound-mod->height());
tmod = mod;
mod->mX = qRound(mod->x() / box->rate);
mod->mY = qRound(mod->y() / box->rate);
}
if(! mods.empty()) box->fitSize();
});
hh->addWidget(bnArrangeBottom);
vBox->addStretch();
vBox = new VBox(hBox);
hBox = new HBox(vBox);
auto fdRoom = new QComboBox;
fdRoom->setEditable(true);
fdRoom->addItem("1600%");
fdRoom->addItem("800%");
fdRoom->addItem("400%");
fdRoom->addItem("200%");
fdRoom->addItem("100%");
fdRoom->addItem("50%");
fdRoom->addItem("25%");
connect(fdRoom, &QComboBox::currentTextChanged, this, [=](const QString &text) {
if(box==0) return;
box->rate = text.trimmed().replace('%',"").toInt() / 100.0;
auto childs = box->children();
foreach(auto child, childs) {
auto mod = (ModuleUnit*)child;
mod->setGeometry(mod->mX*box->rate, mod->mY*box->rate, mod->mW*box->rate, mod->mH*box->rate);
}
box->fitSize();
});
hBox->addWidget(fdRoom);
hBox->addLabel("模组数量: ");
fdModNum = hBox->addLabel();
hBox->addSpacing(20);
hBox->addLabel("箱体大小: ");
fdBoxSize = hBox->addLabel();
hBox->addStretch();
auto scroll = new QScrollArea;
vBox->addWidget(scroll);
box = new QWidget;
box = new BoxPanel(this);
scroll->setWidget(box);
box->resize(1024, 1024);
box->setAutoFillBackground(true);
auto pal = palette();
pal.setColor(QPalette::Window, QColor(0x222222));
box->setPalette(pal);
SetCurText(fdRoom, "200%");
new ModuleUnit(this, "J1", 0, 0, 128, 128, box);
connect(fdHasPos, &QCheckBox::stateChanged, box, (void(QWidget::*)())&QWidget::update);
connect(fdHasSize, &QCheckBox::stateChanged, box, (void(QWidget::*)())&QWidget::update);
connect(fdHasConn, &QCheckBox::stateChanged, box, (void(QWidget::*)())&QWidget::update);
connect(fdHasName, &QCheckBox::stateChanged, box, (void(QWidget::*)())&QWidget::update);
connect(fdHasOutline, &QCheckBox::stateChanged, box, (void(QWidget::*)())&QWidget::update);
auto ModuleWidth = parent->mModule["ModuleWidth"].toInt();
auto ModuleHeight = parent->mModule["ModuleHeight"].toInt();
new ModuleUnit(0, 0, ModuleWidth, ModuleHeight, parent->mModule, "", box);
new ModuleUnit(ModuleWidth, 0, ModuleWidth, ModuleHeight, parent->mModule, "", box);
new ModuleUnit(0, ModuleHeight, ModuleWidth, ModuleHeight, parent->mModule, "", box);
new ModuleUnit(ModuleWidth, ModuleHeight, ModuleWidth, ModuleHeight, parent->mModule, "", box);
fdModNum->setNum(4);
box->fitSize();
}
void BoxPanel::mousePressEvent(QMouseEvent *event) {
if(event->button() != Qt::LeftButton) return;
if(isDrawing) return;
rect = QRectF(event->localPos(), event->localPos());
for(auto child : children()) ((ModuleUnit*) child)->isSel = false;
update();
}
void BoxPanel::mouseReleaseEvent(QMouseEvent *event) {
if(event->button() != Qt::LeftButton) return;
if(rect.isNull()) return;
rect = QRectF();
update();
}
void BoxPanel::mouseMoveEvent(QMouseEvent *event) {
if(! (event->buttons() & Qt::LeftButton)) return;
if(isDrawing) {
auto mod = (ModuleUnit*) childAt(event->pos());
if(mod && mod->name.isEmpty()) mod->drawed();
return;
}
rect.setBottomRight(event->localPos());
for(auto child : children()) {
auto mod = (ModuleUnit*) child;
mod->isSel = rect.intersects(mod->geometry());
}
update();
}
void BoxPanel::paintEvent(QPaintEvent *) {
QPainter painter(this);
ModuleUnit *mod;
for(auto child : children()) {
mod = (ModuleUnit*) child;
QPointF pos(mod->x(), mod->y());
painter.translate(pos);
painter.fillRect(QRectF(1, 1, mod->width()-2, mod->height()-2), mod->isSel ? QColor(0, 0xaa, 0, 0xaa) : QColor(0, 0x44, 0xff, 0x77));
painter.setPen(QColor(mod->isSel ? 0xffffff : 0xdddddd));
if(boxWin->fdHasOutline->isChecked()) painter.drawRect(QRectF(0.5, 0.5, mod->width()-1, mod->height()-1));
int off = 0;
if(boxWin->fdHasPos->isChecked()) painter.drawText(2, off+=15, QString::number(mod->mX)+", "+QString::number(mod->mY));
if(boxWin->fdHasSize->isChecked()) painter.drawText(2, off+=15, QString::number(mod->mW)+" x "+QString::number(mod->mH));
if(! mod->name.isEmpty()) painter.drawText(2, off+15, mod->name);
painter.translate(-pos);
}
QPen pen(0xff8800);
pen.setCapStyle(Qt::FlatCap);
pen.setDashPattern(QVector<qreal>{4, 4});
painter.setPen(pen);
painter.drawRect(QRectF(boxRect.x()-0.5, boxRect.y()-0.5, boxRect.width()+1, boxRect.height()+1));
if(boxWin->fdHasConn->isChecked()) {
QBrush brush(0x0088ff);
painter.setPen(QPen(brush, 3));
QPainterPath path;
for(auto btn : boxWin->grpGrp->buttons()) {
auto mods = btn->property("mods").toList();
if(mods.isEmpty()) continue;
QPointF last = ((ModuleUnit*) mods[0].value<void*>())->geometry().center();
for(int mm=1; mm<mods.size(); mm++) {
QPointF pos = ((ModuleUnit*) mods[mm].value<void*>())->geometry().center();
painter.drawLine(last, pos);
auto deg = 180 / 3.1415926535 * atan((pos.y()-last.y()) / (pos.x()-last.x()));
if(pos.x()<last.x()) deg += 180;
last = pos;
painter.translate(pos);
painter.rotate(deg);
path.clear();
path.lineTo(-30,6);
path.lineTo(-30,-6);
path.closeSubpath();
painter.fillPath(path, brush);
painter.rotate(-deg);
painter.translate(-pos);
}
}
}
if(rect.isNull()) return;
painter.setPen(0x00aa00);
painter.drawRect(rect);
}
ModuleUnit::ModuleUnit(int x, int y, int w, int h, const JObj &module, const QString &name, QWidget *parent) : QWidget{parent}, mX{x}, mY{y}, mW{w}, mH{h}, mModule{module}, name{name} {
box = (BoxPanel*)parent;
setGeometry(x*box->rate, y*box->rate, w*box->rate, h*box->rate);
}
void ModuleUnit::drawed() {
auto btn = box->boxWin->grpGrp->checkedButton();
if(btn==0) return;
auto mods = btn->property("mods").toList();
mods.append(QVariant::fromValue((void*)this));
btn->setProperty("mods", mods);
name = "G"+QString::number(box->boxWin->grpGrp->id(btn)+1)+"-"+QString::number(mods.size());
box->update();
}
void ModuleUnit::mousePressEvent(QMouseEvent *event) {
QWidget::mousePressEvent(event);
if(event->button() != Qt::LeftButton) return;
event->accept();
if(box->isDrawing) return;
setCursor(Qt::SizeAllCursor);
auto glbPos = event->globalPos();
box->grpRect = geometry();
if(isSel) {
mOtherSels.clear();
ModuleUnit* mod;
for(auto child : box->children()) if(child!=this && (mod = (ModuleUnit*)child)->isSel) {
mod->mPressRel = mod->pos() - pos();
box->grpRect |= mod->geometry();
mOtherSels.emplace_back(mod);
}
}
mPressRel = pos() - box->grpRect.topLeft();
box->grpRect.translate(-glbPos);
}
void ModuleUnit::mouseReleaseEvent(QMouseEvent *event) {
QWidget::mouseReleaseEvent(event);
if(Qt::LeftButton != event->button()) return;
event->accept();
if(box->isDrawing) {
if(name.isEmpty()) drawed();
return;
}
unsetCursor();
mPressRel.setX(INT_MIN);
if(! isSel) {
isSel = true;
update();
for(auto item : box->children()) if(item!=this && ((ModuleUnit*)item)->isSel) {
((ModuleUnit*)item)->isSel = false;
((ModuleUnit*)item)->update();
}
}
for(auto sel : mOtherSels) sel->mPressRel.setX(INT_MIN);
mOtherSels.clear();
}
#define SnapSpace 6
void ModuleUnit::mouseMoveEvent(QMouseEvent *e) {
if(! (e->buttons() & Qt::LeftButton)) return;
if(box->isDrawing) {
if(name.isEmpty()) drawed();
else {
auto mod = (ModuleUnit*) box->childAt(x()+e->x(), y()+e->y());
if(mod && mod!=this && mod->name.isEmpty()) mod->drawed();
}
return;
}
if(mPressRel.x()==INT_MIN) return;
if(! isSel) {
isSel = true;
for(auto child : box->children()) if(child!=this && ((ModuleUnit*)child)->isSel) ((ModuleUnit*)child)->isSel = false;
}
auto mousePos = e->globalPos();
auto dstHor = box->grpRect.x() + mousePos.x();
auto dstVer = box->grpRect.y() + mousePos.y();
dstHor = qMax(0, dstHor);
dstVer = qMax(0, dstVer);
// if(dstHor) for(ModuleUnit *ele : mOtherEles) {//左右
// if(abs(dstHor - ele->x()) < SnapSpace) {
// dstHor = ele->x();
// break;
// }
// auto eleRight = ele->x() + ele->width();
// if(abs(dstHor - eleRight) < SnapSpace) {
// dstHor = eleRight;
// break;
// }
// auto right = dstHor + width();
// if(abs(right - ele->x()) < SnapSpace && ele->x() - width() >= 0) {
// dstHor = ele->x() - width();
// break;
// }
// if(abs(right - eleRight) < SnapSpace && eleRight - width() >= 0) {
// dstHor = eleRight - width();
// break;
// }
// }
// if(dstVer) for(ModuleUnit *ele : mOtherEles) {//上下
// if(abs(dstVer-ele->y()) < SnapSpace) {
// dstVer = ele->y();
// break;
// }
// auto eleBtm = ele->y() + ele->height();
// if(abs(dstVer - eleBtm) < SnapSpace) {
// dstVer = eleBtm;
// break;
// }
// auto btm = dstVer + height();
// if(abs(btm - ele->y()) < SnapSpace && ele->y() - height() >= 0) {
// dstVer = ele->y() - height();
// break;
// }
// if(abs(btm - eleBtm) < SnapSpace && eleBtm - height() >= 0) {
// dstVer = eleBtm - height();
// break;
// }
// }
move(mPressRel.x() + dstHor, mPressRel.y() + dstVer);
mX = qRound(x() / box->rate);
mY = qRound(y() / box->rate);
for(auto sel : mOtherSels) {
if(sel->mPressRel.x()==INT_MIN) continue;
sel->move(sel->mPressRel.x() + x(), sel->mPressRel.y() + y());
sel->mX = qRound(sel->x() / box->rate);
sel->mY = qRound(sel->y() / box->rate);
}
box->fitSize();
}

View File

@ -2,16 +2,69 @@
#define EXPERTBOXLAYOUTWIN_H
#include "basewin.h"
#include "gutil/qjson.h"
#include <QLabel>
#include <QSpinBox>
#include <QComboBox>
#include <QButtonGroup>
#include <QCheckBox>
class ExpertWin;
class BoxPanel;
class ExpertBoxLayoutWin : public BaseWin {
Q_OBJECT
public:
explicit ExpertBoxLayoutWin(QWidget *parent = 0);
explicit ExpertBoxLayoutWin(ExpertWin *parent = 0);
QCheckBox *fdHasPos, *fdHasSize, *fdHasConn, *fdHasName, *fdHasOutline;
QButtonGroup *grpGrp;
BoxPanel *box{0};
QLabel *fdModNum, *fdBoxSize;
};
class ModuleUnit;
class BoxPanel : public QWidget {
Q_OBJECT
public:
explicit BoxPanel(ExpertBoxLayoutWin *boxWin) : boxWin(boxWin) {}
void fitSize() {
boxRect = childrenRect();
auto www = qMax(1000, boxRect.x()+boxRect.width()+1);
auto hhh = qMax(1000, boxRect.y()+boxRect.height()+1);
if(www!=width() || hhh!=height()) resize(www, hhh);
else update();
boxWin->fdBoxSize->setText(QString("%1 x %2").arg(boxRect.width()).arg(boxRect.height()));
}
QRect boxRect, grpRect;
ExpertBoxLayoutWin *boxWin;
double rate{1};
QWidget *box;
QRectF rect;
bool isDrawing{false};
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
};
class ModuleUnit : public QWidget {
Q_OBJECT
public:
explicit ModuleUnit(int, int, int, int, const JObj &module, const QString &name, QWidget *parent = nullptr);
void drawed();
int mX, mY, mW, mH;
JObj mModule;
QString name;
BoxPanel *box;
QPoint mPressRel{INT_MIN, INT_MIN};
bool isSel{false};
protected:
void mousePressEvent(QMouseEvent *) override;
void mouseReleaseEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
std::vector<ModuleUnit *> mOtherSels;
};
#endif // EXPERTBOXLAYOUTWIN_H

View File

@ -709,7 +709,8 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(ExpertWin *expertWin) : BaseWin{e
vBox->addLayout(hhh);
table = new Table;
table->setNoEdit()->setSelectionMode(QTableWidget::SingleSelection);
table->setEditTriggers(Table::NoEditTriggers);
table->setSelectionMode(QTableWidget::SingleSelection);
table->setColWidth(35)->setRowHeight(24, QHeaderView::Fixed);
table->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
table->verticalHeader()->setMinimumWidth(35);
@ -750,7 +751,7 @@ ExpertSmartPointSetWin::ExpertSmartPointSetWin(ExpertWin *expertWin) : BaseWin{e
vBox->addWidget(table);
tableRow = new Table(2, 0);
tableRow->setNoEdit();
tableRow->setEditTriggers(Table::NoEditTriggers);
tableRow->setSelectionMode(QTableWidget::NoSelection);
tableRow->setColWidth(35);
tableRow->setRowHeight(24);

View File

@ -134,6 +134,7 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou
qFile.close();
auto json = JFrom(data).toObj();
if(! json.empty()) {
cfg = json;
mBox = json["ModuleConnectionInfo"].toObj();
mModule = mBox["ModuleInfo"].toObj();
}
@ -247,7 +248,7 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou
fdNormal->setChecked(true);
vvv->addWidget(fdNormal);
auto fdAdvacned = new QRadioButton("高级设计");
fdAdvacned = new QRadioButton("高级设计");
vvv->addWidget(fdAdvacned);
hh->addSpacing(20);
@ -308,7 +309,7 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou
fdSectorCount->addItem(tr("六开"), 6);
fdSectorCount->addItem(tr("七开"), 7);
fdSectorCount->addItem(tr("八开"), 8);
setCurrentData(fdSectorCount, mBox["SectorCount"].toInt());
SetCurData(fdSectorCount, mBox["SectorCount"].toInt());
vvv->addWidget(fdSectorCount);
fdDirection = new QComboBox();
@ -344,12 +345,15 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou
connect(btn, &QPushButton::clicked, this, [=] {
auto win = new ExpertBoxLayoutWin(this);
win->show();
win->raise();
win->activateWindow();
});
vvv->addWidget(btn);
}
connect(fdNormal, &QRadioButton::toggled, this, [=](bool checked) {
stack->setCurrentWidget(checked ? normalPanel : advacnedPanel);
});
if(cfg["is_irr"].toBool()) fdAdvacned->setChecked(true);
}
gBox = new QGroupBox(tr("效果测试"));
@ -589,7 +593,7 @@ QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; backgrou
}
void ExpertWin::closeEvent(QCloseEvent *event) {
BaseWin::closeEvent(event);
QFile qFile(QApplication::applicationDirPath()+"/temp.screen");
QFile qFile("temp.screen");
if(! qFile.open(QFile::WriteOnly)) return;
qFile.write(savedData());
qFile.close();
@ -602,7 +606,10 @@ QByteArray ExpertWin::savedData() {
mBox.insert("ModuleCol", (fdCardHeight->value() + ModuleHeight - 1) / ModuleHeight);
mBox.insert("ModuleDirection", fdDirection->currentIndex());
mBox.insert("SectorCount", fdSectorCount->currentData().toInt());
JObj obj{{"ModuleConnectionInfo", mBox}};
JObj obj{
{"ModuleConnectionInfo", mBox},
{"is_irr", fdAdvacned->isChecked()},
};
return JToBytes(obj, " ");
}
void ExpertWin::addMapData(QByteArray &data) {
@ -716,80 +723,3 @@ void ExpertWin::addMapData(QByteArray &data) {
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("\xB1\x04\0\0", 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<img.height(); i++) for(int j=0; j<lineLen; j+=once) {
// int dataLen = lineLen - j;
// if(dataLen > 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);
// }
}

View File

@ -6,7 +6,7 @@
#include <QLabel>
#include <QSpinBox>
#include <QComboBox>
#include <QJsonObject>
#include <QRadioButton>
class ExpertWin : public BaseWin {
Q_OBJECT
@ -21,6 +21,13 @@ public:
QLabel *fdModuleWidth, *fdModuleHeight, *fdGroupNum, *fdScanNum;
QLabel *fdChipType, *fdDecodeMode;
JObj cfg;
JObj mBox {
{"ModuleRow", 1},
{"ModuleCol", 1},
{"Direction", 1},
{"SectorCount", 1}
};
JObj mModule {
{"ModuleWidth", 32},
{"ModuleHeight", 16},
@ -30,15 +37,10 @@ public:
{"DecodeMode", "138译码"},
{"GroupMode", "三线并行"}
};
JObj mBox {
{"ModuleRow", 1},
{"ModuleCol", 1},
{"Direction", 1},
{"SectorCount", 1}
};
QSpinBox *fdCardWidth, *fdCardHeight;
QComboBox *fdDirection, *fdSectorCount;
QRadioButton *fdAdvacned;
protected:
void closeEvent(QCloseEvent *) override;
};

View File

@ -73,6 +73,10 @@ public:
Vector(std::initializer_list<V> _Ilist) {
this->ptr = new SharedData<std::vector<V>>{_Ilist, 1};
}
bool empty() const noexcept {
return this->ptr ? this->ptr->data.empty() : true;
}
uint64_t size() const noexcept {
return this->ptr ? this->ptr->data.size() : 0;
}

View File

@ -16,7 +16,7 @@ Table::Table(std::initializer_list<ColAttr> colAttrs, int rows, QWidget *parent)
noStretch = false;
} else horizontalHeader()->setSectionResizeMode(i, (QHeaderView::ResizeMode)it->resizeMode);
}
mFieldMap.insert(it->field, i++);
mFieldMap.emplace(it->field, i++);
}
}
@ -31,9 +31,14 @@ void Table::resizeSec() {
int colCnt = columnCount(), remainWidth = header->width(), stretchWidth = 0, secWidth;
QTableWidgetItem *item;
for(int cc=0; cc<colCnt; cc++) if((item = horizontalHeaderItem(cc))) {
if((secWidth = item->data(0x99).toInt()) > 0) stretchWidth += secWidth;
else remainWidth -= header->sectionSize(cc);
}
if((secWidth = item->data(0x99).toInt()) > 0) stretchWidth += secWidth;
else remainWidth -= header->sectionSize(cc);
}
if(remainWidth<=0 || stretchWidth==0) return;
for(int cc=0; cc<colCnt; cc++) if((item = horizontalHeaderItem(cc)) && (secWidth = item->data(0x99).toInt()) > 0) header->resizeSection(cc, secWidth * remainWidth / stretchWidth);
}
void Table::updateGeometries() {
QTableWidget::updateGeometries();
emit updGeos();
}

View File

@ -2,12 +2,14 @@
#define QGUI_H
#include <QComboBox>
#include <QStackedLayout>
#include <QSplitter>
#include <QListWidget>
#include <QTableWidget>
#include <QDialog>
#include <QDialogButtonBox>
#include <QHeaderView>
#include <QLabel>
#include <QListWidget>
#include <QSplitter>
#include <QStackedLayout>
#include <QTableWidget>
#include <QTextEdit>
#define MainMust \
@ -22,11 +24,28 @@
extern const int AlignRight;
inline int setCurrentData(QComboBox *combo, const QVariant &data) {
inline QWidget *parentWgt(QObject *obj) {
while(obj && ! obj->isWidgetType()) obj = obj->parent();
return (QWidget*) obj;
}
inline QWidget *parentWin(QObject *obj) {
while(obj) {
if(obj->isWidgetType()) return ((QWidget*) obj)->window();
obj = obj->parent();
}
return (QWidget*) obj;
}
inline int SetCurData(QComboBox *combo, const QVariant &data) {
auto idx = combo->findData(data);
if(idx>-1) combo->setCurrentIndex(idx);
return idx;
}
inline int SetCurText(QComboBox *combo, const QString &text) {
auto idx = combo->findText(text);
if(idx>-1) combo->setCurrentIndex(idx);
return idx;
}
inline void gFont(QWidget *wgt, int size, bool bold = false, bool italic = false) {
auto ft = wgt->font();
ft.setPixelSize(size);
@ -70,11 +89,22 @@ public:
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline QLabel *addLabel() {
auto lb = new QLabel;
addWidget(lb);
return lb;
}
inline QLabel *addLabel(const QString &text) {
auto lb = new QLabel(text);
addWidget(lb);
return lb;
}
inline QDialogButtonBox *addBtnBox(QDialog *dlg = 0) {
auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
if(dlg) connect(btnBox, &QDialogButtonBox::rejected, dlg, &QDialog::reject);
addWidget(btnBox);
return btnBox;
}
};
class HBox : public QBoxLayout {
public:
@ -90,6 +120,11 @@ public:
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline QLabel *addLabel() {
auto lb = new QLabel;
addWidget(lb);
return lb;
}
inline QLabel *addLabel(const QString &text) {
auto lb = new QLabel(text);
addWidget(lb);
@ -143,10 +178,6 @@ public:
Table() {}
Table(std::initializer_list<ColAttr> colAttrs, int rows = 0, QWidget *parent = 0);
inline auto setNoEdit() {
setEditTriggers(QAbstractItemView::NoEditTriggers);
return this;
}
inline auto setDefs() {
setSelectionBehavior(QTableWidget::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
@ -279,13 +310,15 @@ public:
setCellWidget(row, col, widget);
}
std::map<QString, int> mFieldMap;
public Q_SLOTS:
inline void clearRows() {setRowCount(0);}
signals:
void updGeos();
protected:
void resizeEvent(QResizeEvent *event) override;
void updateGeometries() override;
void resizeSec();
QMap<QString,int> mFieldMap;
bool noStretch{true};
};

View File

@ -94,13 +94,23 @@ public:
if(type==Array) return *(JArray*) data;
return JArray();
}
const JValue operator[](const QString &key) const {
return type==Obj ? (*(JObj*) data)[key] : JValue();
}
const JValue operator[](int i) const {
return type==Array ? (*(JArray*) data)[i] : JValue();
}
private:
JValue(const void *) = delete; // avoid implicit conversions from char * to bool
};
class JParser {
public:
JParser(QTextStream &in) : in(in) {}
JParser(QTextStream &in) : in(in) {
#if(QT_VERSION_MAJOR < 6)
in.setCodec("UTF-8");
#endif
}
inline JValue read() {
skipSpace();
@ -144,7 +154,11 @@ inline JValue JFrom(QIODevice *device, QString *err = 0) {
class JOut {
public:
JOut(QTextStream &out, QString indent = "") : out(out), indent(indent) {}
JOut(QTextStream &out, QString indent = "") : out(out), indent(indent) {
#if(QT_VERSION_MAJOR < 6)
out.setCodec("UTF-8");
#endif
}
void write(const JValue &obj);
void writeStr(const QString &str);

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

BIN
ledset/imgs/align-left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

BIN
ledset/imgs/align-right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
ledset/imgs/align-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

BIN
ledset/imgs/arrange-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@ -10,6 +10,7 @@ CONFIG += embed_translations
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
TARGET = $$quote(LedSet Express)
DEFINES += __VER__=\\\"0.0.1\\\"
msvc {
contains(QT_ARCH, i386) {
@ -29,6 +30,22 @@ win32 {
RC_ICONS = 128.ico
}
copydir.files += translations
win32 {
EXE_SUFFIX = .exe
copydir.path = $$OUT_PWD
CONFIG += file_copies
COPIES += copydir
}
osx {
DIR_SUFFIX = -mac
copydir.path = Contents/MacOS
QMAKE_BUNDLE_DATA += copydir
}
INCLUDEPATH += $$PWD/npcap-sdk-1.13/Include
LIBS += -L$$PWD/npcap-sdk-1.13/Lib/\
-lwpcap\
@ -51,7 +68,6 @@ SOURCES += \
gutil/qjson.cpp \
main.cpp \
mainwin.cpp \
moduleunit.cpp \
pcaprethread.cpp \
screenunit.cpp \
testwin.cpp \
@ -72,7 +88,6 @@ HEADERS += \
gutil/qgui.h \
gutil/qjson.h \
mainwin.h \
moduleunit.h \
pcaprethread.h \
screenunit.h \
testwin.h \
@ -80,14 +95,7 @@ HEADERS += \
waitingdlg.h
TRANSLATIONS += \
translations/app_en.ts
EXTRA_TRANSLATIONS += \
translations/qt_zh_CN.ts \
translations/qt_zh_TW.ts \
translations/qt_ja.ts \
translations/qt_en.ts
ts/app_en.ts
# Default rules for deployment.

View File

@ -1,31 +1,29 @@
#include "mainwin.h"
#include <QApplication>
#include <QLocale>
#include <QTranslator>
#include <QIcon>
#include <QLocale>
#include <QMessageBox>
#include <QStyleFactory>
#include <QDebug>
#include <QTranslator>
#ifdef _MSC_VER //MSVC编译器
#define _WINSOCKAPI_
#include <windows.h>
#include <DbgHelp.h>
LONG WINAPI handleException(_EXCEPTION_POINTERS *excep) {
QString errCode = QString::number(excep->ExceptionRecord->ExceptionCode, 16);
QString errAddr = QString::number((uint)excep->ExceptionRecord->ExceptionAddress, 16);
HANDLE hDumpFile = CreateFile(L"c:/ledset-crash.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hDumpFile == INVALID_HANDLE_VALUE) return EXCEPTION_CONTINUE_SEARCH; //未处理异常, 让 windows 弹出错误框并结束 (Qt会卡死一段时间)
auto errCode = QString::number(excep->ExceptionRecord->ExceptionCode, 16);
auto errAddr = QString::number((uint)excep->ExceptionRecord->ExceptionAddress, 16);
auto hDumpFile = CreateFile(L"ledset-crash.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hDumpFile == INVALID_HANDLE_VALUE) {
qCritical()<<"CreateFile ledset-crash.dmp Failed! ExceptionCode"<<errCode<<"ExceptionAddress"<<errAddr;
return EXCEPTION_CONTINUE_SEARCH;
}
MINIDUMP_EXCEPTION_INFORMATION dumpInfo{GetCurrentThreadId(), excep, TRUE};
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);//写入Dump文件内容
CloseHandle(hDumpFile);
QMessageBox::critical(nullptr, "程序出错", "<b>程序出错!</b> (code: "+errCode+". addr: "+errAddr+")<br/>请将C盘下的 ledok-crash.dmp 文件发送到 gangphon@qq.com 邮箱, 研发人员会尽快处理.");
QMessageBox::critical(0, "程序出错 (V" __VER__" - " __DATE__", Code: "+errCode+")", "<b>程序出错!</b><br/>请将安装目录下的 ledok-crash.dmp 文件发送到 gangphon@qq.com 邮箱, 研发人员会尽快处理.");
return EXCEPTION_EXECUTE_HANDLER; //已处理异常, 让 windows 正常结束
// EXCEPTION_CONTINUE_EXECUTION 已修复错误, 让 windows 从异常发生处继续执行
}
#endif
void test();
int main(int argc, char *argv[]) {
qputenv("QT_QPA_PLATFORM", "windows:darkmode=2");
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -35,7 +33,7 @@ int main(int argc, char *argv[]) {
QApplication::setOrganizationDomain("ledok.cn");
QApplication::setApplicationName("LedSet Express");
QApplication a(argc, argv);
a.setStyle(QStyleFactory::create("Fusion"));
QApplication::setStyle("Fusion");
a.setWindowIcon(QIcon(":/128.ico"));
a.setStyleSheet(R"rrr(
QLineEdit {border: 1px solid #777; border-radius: 2px; padding: 2px;}
@ -49,6 +47,7 @@ QRadioButton::indicator:checked {border-image: url(:/imgs/radio-check.png);}
QCheckBox::indicator {border-image: url(:/imgs/checkbox-un.png); width: 1em; height: 1em;}
QCheckBox::indicator:checked {border-image: url(:/imgs/checkbox-check.png);}
QPushButton:checked {border: 2px solid #0a0; border-radius: 3px; padding-top: 2px; padding-bottom: 2px; }
QPushButton:disabled {color: #777;}
QPushButton[ss="min"]{padding: 0; width: 30px; height: 25px; }
@ -59,8 +58,6 @@ QPushButton[ss="blue"] {background: #059;}
QGroupBox {border: 1px solid #777; border-radius: 3px; margin-top: 0.5em; padding-top: 0.4em;}
QGroupBox::title {color: #fff; subcontrol-origin: margin; left: 0.5em;}
)rrr");
/*
*/
QFont font;
font.setFamilies(QStringList{"Arial","Microsoft YaHei UI"});
a.setFont(font);
@ -84,18 +81,13 @@ QGroupBox::title {color: #fff; subcontrol-origin: margin; left: 0.5em;}
a.setPalette(plt);
QTranslator translator;
if(translator.load(QLocale::system(), "app", "_", ":/i18n")) a.installTranslator(&translator);
if(translator.load(QLocale(), "app", "_", ":/i18n")) a.installTranslator(&translator);
QTranslator qtTrans;
if(qtTrans.load(QLocale::system(), "qt", "_", ":/i18n")) a.installTranslator(&qtTrans);
if(qtTrans.load(QLocale(), "qt", "_", "translations")) a.installTranslator(&qtTrans);
MainWin w;
#ifdef _MSC_VER
SetUnhandledExceptionFilter(handleException);
#endif
//test();
return a.exec();
}
void test() {
}

View File

@ -1,4 +1,5 @@
#include "mainwin.h"
#include "gutil/qjson.h"
#include "pcaprethread.h"
#include "fast.h"
#include "expertwin.h"
@ -21,6 +22,8 @@
#include <QApplication>
#include <QtEndian>
#include <QStandardPaths>
#include <QNetworkDatagram>
#include <QNetworkInterface>
class ImgBtn : public QToolButton {
public:
@ -132,9 +135,9 @@ MainWin::MainWin() {
table->setDefs();
vBox->addWidget(table);
auto hstatus = new QHBoxLayout;
hstatus->addWidget(new QLabel(tr("编译日期")+": "+__DATE__));
hstatus->addStretch();
auto hBox = new HBox(vBox);
hBox->addLabel("V" __VER__" - " __DATE__);
hBox->addStretch();
auto btnNetSelect = new QPushButton("通讯选择");
connect(btnNetSelect, &QPushButton::clicked, this, [this] {
@ -160,13 +163,11 @@ MainWin::MainWin() {
reThd->start();
QSettings().setValue("net_name", net_name = name);
});
hstatus->addWidget(btnNetSelect);
hBox->addWidget(btnNetSelect);
auto btnRefresh = new QPushButton(tr("刷新"));
connect(btnRefresh, &QPushButton::clicked, this, &MainWin::getCard);
hstatus->addWidget(btnRefresh);
vBox->addLayout(hstatus);
hBox->addWidget(btnRefresh);
show();
@ -189,10 +190,53 @@ MainWin::MainWin() {
}
}
}
connect(&mUdpSocket, &QUdpSocket::readyRead, this, [this] {
while(mUdpSocket.hasPendingDatagrams()) {
auto gram = mUdpSocket.receiveDatagram();
auto data = gram.data();
if(data.isEmpty()) continue;
auto senderAddress = gram.senderAddress();
bool ok = true;
if(senderAddress.protocol()==QUdpSocket::IPv6Protocol) senderAddress.setAddress(senderAddress.toIPv4Address(&ok));
auto addr = ok ? senderAddress.toString() : "";
int cnt = table->rowCount();
if(data.startsWith("{\"")) {
QString error;
auto json = JFrom(gram.data(), &error);
if(! error.isEmpty()) {
qDebug()<<"Json Error: "+error;
continue;
}
auto cardId = json["cardId"].toStr();
for(int rr=0; rr<cnt; rr++) if(table->text(rr, "name")==cardId) {
table->setText(rr, "link", addr);
goto end;
}
table->setRowCount(cnt+1);
//table->setText(cnt, "type", tr("虚拟设备"));
table->setText(cnt, "name", cardId);
table->setText(cnt, "link", addr);
//table->setText(cnt, "vcsNum", QString::number(*(quint32_be*)(data.data()+headMap.body)));
//table->setText(cnt, "netPorts", "P:"+QString::number(virtualVCM));
//table->setText(cnt, "info", "备注:可直接配屏,无需发送卡");
} else {
auto bytes = gram.data();
auto packet = (UDPPacket *)bytes.data();
for(int rr=0; rr<cnt; rr++) if(table->text(rr, "name")==packet->serialCode) {
table->setText(rr, "link", addr);
goto end;
}
table->setRowCount(cnt+1);
table->setText(cnt, "name", packet->serialCode);
table->setText(cnt, "link", addr);
}
end:;
}
});
getCard();
}
MainWin::~MainWin() {
mUdpSocket.close();
QSettings config;
config.setValue("FileHome", gFileHome);
}
@ -212,7 +256,28 @@ void MainWin::getCard() {
table->setText(rr, "netPorts", "P:"+QString::number(virtualVCM));
table->setText(rr, "info", "备注:可直接配屏,无需发送卡");
});
if(res) QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+QString::fromLocal8Bit(pcap_geterr(pcapSend)));
if(res) {
QString err = pcap_geterr(pcapSend);
if(! err.endsWith("(2150891551)")) QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+QString::fromLocal8Bit(pcap_geterr(pcapSend)));
}
auto data = JToBytes(JObj{{"action", "getInfo"}});
uchar ccc[]{0x7E, 0x7E, 0x7E, 0x90, 0x42, 0x72, 0x6F, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x21,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x9F};
if(mUdpSocket.writeDatagram(data, QHostAddress("255.255.255.255"), 22222) != data.length()) qDebug() << "getInfo write to 255.255.255.255 failed";
if(mUdpSocket.writeDatagram((char *)ccc, sizeof(ccc), QHostAddress("255.255.255.255"), 31296) != sizeof(ccc)) qDebug() << "getInfo write to 255.255.255.255 failed";
auto networkinterfaces = QNetworkInterface::allInterfaces();
foreach(auto face, networkinterfaces) {
auto flags = face.flags();
bool can = (flags & QNetworkInterface::IsRunning) && (flags & QNetworkInterface::CanBroadcast) && ! (flags & QNetworkInterface::IsLoopBack);
if(! can) continue;
auto addrEntries = face.addressEntries();
foreach(QNetworkAddressEntry addrEntry, addrEntries) {
auto ip = addrEntry.ip();
if(ip.protocol()!=QAbstractSocket::IPv4Protocol) continue;
auto broadcast = addrEntry.broadcast();
if(mUdpSocket.writeDatagram(data, broadcast, 22222) != data.length()) qDebug() << "getInfo write failed." << ip.toString() << "->" << broadcast.toString();
}
}
}

View File

@ -3,6 +3,7 @@
#include "basewin.h"
#include "gutil/qgui.h"
#include <QUdpSocket>
class MainWin : public BaseWin {
Q_OBJECT
@ -12,9 +13,17 @@ public:
QWidget *win{0};
QByteArray net_name;
Table *table{0};
QUdpSocket mUdpSocket;
public slots:
void getCard();
};
struct UDPPacket {
unsigned char SyncHead[3];
unsigned char ucCommType;
char serialCode[20];
unsigned int iLength;
};
#endif // MAINWIN_H

View File

@ -1,198 +0,0 @@
#include "moduleunit.h"
#include "expertboxlayoutwin.h"
#include <QDirIterator>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QJsonArray>
#include <QJsonObject>
#include <QLabel>
#include <QPainter>
#include <QSpinBox>
#include <QMouseEvent>
ModuleUnit::ModuleUnit(ExpertBoxLayoutWin *expertWin, const QString &name, int x, int y, int w, int h, QWidget *parent) : QWidget{parent}, expertWin{expertWin}, name{name}, mX{x}, mY{y}, mW{w}, mH{h} {
setGeometry(x, y, w, h);
setMouseTracking(true);
auto font = this->font();
font.setPixelSize(12);
setFont(font);
mSidePen.setCapStyle(Qt::FlatCap);
mSidePen.setDashPattern(QVector<qreal>{2,2});
}
void ModuleUnit::paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.setPen(mSidePen);
painter.drawRect(QRectF(0.5, 0.5, width()-1, height()-1));
painter.drawText(2, 16, name);
painter.drawText(2, 32, "位置: "+QString::number(mX)+", "+QString::number(mY));
painter.drawText(2, 48, "大小: "+QString::number(mW)+" x "+QString::number(mH));
//磁条吸附时两化吸附的边
static QPen snapPen(QColor(0x00ff00), 2);
painter.setPen(snapPen);
if(mLRSnap==1) painter.drawLine(QPointF(1, 0), QPointF(1, height()));
else if(mLRSnap==2) painter.drawLine(QPointF(width()-1, 0), QPointF(width()-1, height()));
if(mTBSnap==1) painter.drawLine(QPointF(0, 1), QPointF(width(), 1));
else if(mTBSnap==2) painter.drawLine(QPointF(0, height()-1), QPointF(width(), height()-1));
}
void ModuleUnit::setFrmSec(const QPoint &pos) {
if(isMaximized()) return;
if(pos.y()<8) {
if(pos.x()<16) setFrmSecIfNeed(Qt::TopLeftSection, Qt::SizeFDiagCursor);
else if(pos.x()<width()-16) setFrmSecIfNeed(Qt::TopSection, Qt::SizeVerCursor);
else setFrmSecIfNeed(Qt::TopRightSection, Qt::SizeBDiagCursor);
} else if(pos.y()>=height()-8) {
if(pos.x()<16) setFrmSecIfNeed(Qt::BottomLeftSection, Qt::SizeBDiagCursor);
else if(pos.x()<width()-16) setFrmSecIfNeed(Qt::BottomSection, Qt::SizeVerCursor);
else setFrmSecIfNeed(Qt::BottomRightSection, Qt::SizeFDiagCursor);
} else if(pos.x()<8) {
if(pos.y()<16) setFrmSecIfNeed(Qt::TopLeftSection, Qt::SizeFDiagCursor);
else if(pos.y()<height()-16) setFrmSecIfNeed(Qt::LeftSection, Qt::SizeHorCursor);
else setFrmSecIfNeed(Qt::BottomLeftSection, Qt::SizeBDiagCursor);
} else if(pos.x()>=width()-8) {
if(pos.y()<16) setFrmSecIfNeed(Qt::TopRightSection, Qt::SizeBDiagCursor);
else if(pos.y()<height()-16) setFrmSecIfNeed(Qt::RightSection, Qt::SizeHorCursor);
else setFrmSecIfNeed(Qt::BottomRightSection, Qt::SizeFDiagCursor);
} else setFrmSecIfNeed(Qt::TitleBarArea, Qt::SizeAllCursor);
}
void ModuleUnit::mousePressEvent(QMouseEvent *e) {
QWidget::mousePressEvent(e);
if(e->button() != Qt::LeftButton) return;
setFrmSec(e->pos());
if(mFrmSec==Qt::TitleBarArea || mFrmSec==Qt::TopSection || mFrmSec==Qt::LeftSection || mFrmSec==Qt::TopLeftSection) mPressRel = mPressRel = pos() - e->globalPos();
else if(mFrmSec==Qt::BottomRightSection) mPressRel = QPoint(width() - e->globalX(), height() - e->globalY());
else if(mFrmSec==Qt::RightSection ) mPressRel = QPoint(width() - e->globalX(), height() );
else if(mFrmSec==Qt::BottomSection ) mPressRel = QPoint(width() , height() - e->globalY());
else if(mFrmSec==Qt::TopRightSection ) mPressRel = geometry().topRight() - e->globalPos();
else if(mFrmSec==Qt::BottomLeftSection ) mPressRel = geometry().bottomLeft() - e->globalPos();
else if(mFrmSec==Qt::NoSection) mPressRel.setX(INT_MIN);
if(mPressRel.x()!=INT_MIN) {
mOtherEles.clear();
auto parent = this->parentWidget();
if(0 == parent) return;
auto items = parent->children();
foreach(auto item, items) {
if(item==this) continue;
auto ele = static_cast<ModuleUnit*>(item);
mOtherEles.append(ele);
}
}
}
void ModuleUnit::mouseReleaseEvent(QMouseEvent *event) {
QWidget::mouseReleaseEvent(event);
if(Qt::LeftButton == event->button()) {
mPressRel.setX(INT_MIN);
clearSnap();
foreach(auto ele, mOtherEles) ele->clearSnap();
}
}
#define SnapSpace 6
void ModuleUnit::mouseMoveEvent(QMouseEvent *e){
if(! (e->buttons() & Qt::LeftButton)) {
setFrmSec(e->pos());
return;
}
if(mFrmSec==Qt::NoSection || mPressRel.x()==INT_MIN) return;
auto mousePos = e->globalPos();
auto dstHor = mPressRel.x() + mousePos.x();
auto dstVer = mPressRel.y() + mousePos.y();
mLRSnap = mTBSnap = 0;
foreach(auto ele, mOtherEles) ele->clearSnap();
if(mFrmSec==Qt::TitleBarArea) {
dstHor = qMax(0, dstHor);
dstVer = qMax(0, dstVer);
auto needw = qMax(1024, dstHor+width());
auto needh = qMax(1024, dstVer+height());
if(needw != expertWin->box->width() || needh != expertWin->box->height()) expertWin->box->resize(needw, needh);
if(dstHor==0) mLRSnap = 1;
if(dstVer==0) mTBSnap = 1;
if(mLRSnap==0) foreach(ModuleUnit *ele, mOtherEles) {//左右
if(abs(dstHor - ele->x()) < SnapSpace) {
dstHor = ele->x();
mLRSnap = 1;
ele->mLRSnap = 1;
ele->update();
break;
}
auto eleRight = ele->x() + ele->width();
if(abs(dstHor - eleRight) < SnapSpace) {
dstHor = eleRight;
mLRSnap = 1;
ele->mLRSnap = 2;
ele->update();
break;
}
auto right = dstHor + width();
if(abs(right - ele->x()) < SnapSpace && ele->x() - width() >= 0) {
dstHor = ele->x() - width();
mLRSnap = 2;
ele->mLRSnap = 1;
ele->update();
break;
}
if(abs(right - eleRight) < SnapSpace && eleRight - width() >= 0) {
dstHor = eleRight - width();
mLRSnap = 2;
ele->mLRSnap = 2;
ele->update();
break;
}
}
if(mTBSnap==0) foreach(ModuleUnit *ele, mOtherEles) {//上下
if(abs(dstVer-ele->y()) < SnapSpace) {
dstVer = ele->y();
mTBSnap = 1;
ele->mTBSnap = 1;
ele->update();
break;
}
auto eleBtm = ele->y() + ele->height();
if(abs(dstVer - eleBtm) < SnapSpace) {
dstVer = eleBtm;
mTBSnap = 1;
ele->mTBSnap = 2;
ele->update();
break;
}
auto btm = dstVer + height();
if(abs(btm - ele->y()) < SnapSpace && ele->y() - height() >= 0) {
dstVer = ele->y() - height();
mTBSnap = 2;
ele->mTBSnap = 1;
ele->update();
break;
}
if(abs(btm - eleBtm) < SnapSpace && eleBtm - height() >= 0) {
dstVer = eleBtm - height();
mTBSnap = 2;
ele->mTBSnap = 2;
ele->update();
break;
}
}
move(dstHor, dstVer);
mX = qRound(dstHor / expertWin->rate);
mY = qRound(dstVer / expertWin->rate);
update();
}
}
void ModuleUnit::leaveEvent(QEvent *) {
setFrmSecIfNeed(Qt::NoSection, Qt::ArrowCursor);
mPressRel.setX(INT_MIN);
}
void ModuleUnit::setFrmSecIfNeed(Qt::WindowFrameSection frmSec, Qt::CursorShape cursor) {
if(mFrmSec==frmSec) return;
mFrmSec = frmSec;
if(cursor==Qt::ArrowCursor) unsetCursor();
else setCursor(cursor);
}
void ModuleUnit::clearSnap() {
if(mLRSnap==0 && mTBSnap==0) return;
mLRSnap = mTBSnap = 0;
update();
}

View File

@ -1,37 +0,0 @@
#ifndef MODULEUNIT_H
#define MODULEUNIT_H
#include <QWidget>
#include <QVBoxLayout>
#include <QPen>
#define m_handleLen 10
class ExpertBoxLayoutWin;
class ModuleUnit : public QWidget {
Q_OBJECT
public:
explicit ModuleUnit(ExpertBoxLayoutWin *, const QString &name, int x, int y, int w, int h, QWidget *parent = nullptr);
ExpertBoxLayoutWin *expertWin{0};
QString name;
int mX, mY, mW, mH;
protected:
void paintEvent(QPaintEvent *) override;
void mousePressEvent(QMouseEvent *) override;
void mouseReleaseEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
void leaveEvent(QEvent *) override;
void setFrmSec(const QPoint &);
void setFrmSecIfNeed(Qt::WindowFrameSection frmSec, Qt::CursorShape cursor);
void clearSnap();
QPen mSidePen{Qt::white};
QPoint mPressRel{INT_MIN, INT_MIN};
Qt::WindowFrameSection mFrmSec{Qt::NoSection};
char mLRSnap{0}, mTBSnap{0};
QList<ModuleUnit *> mOtherEles;
};
#endif // MODULEUNIT_H

View File

@ -1,6 +1,14 @@
<RCC>
<qresource prefix="/">
<file>128.ico</file>
<file>imgs/align-left.png</file>
<file>imgs/align-right.png</file>
<file>imgs/align-top.png</file>
<file>imgs/align-bottom.png</file>
<file>imgs/arrange-left.png</file>
<file>imgs/arrange-right.png</file>
<file>imgs/arrange-top.png</file>
<file>imgs/arrange-bottom.png</file>
<file>imgs/checkbox-check.png</file>
<file>imgs/checkbox-un.png</file>
<file>imgs/radio-check.png</file>

View File

@ -62,7 +62,7 @@ void ScreenUnit::mousePressEvent(QMouseEvent *e) {
QWidget::mousePressEvent(e);
if(e->button() != Qt::LeftButton) return;
setFrmSec(e->pos());
if(mFrmSec==Qt::TitleBarArea || mFrmSec==Qt::TopSection || mFrmSec==Qt::LeftSection || mFrmSec==Qt::TopLeftSection) mPressRel = mPressRel = pos() - e->globalPos();
if(mFrmSec==Qt::TitleBarArea || mFrmSec==Qt::TopSection || mFrmSec==Qt::LeftSection || mFrmSec==Qt::TopLeftSection) mPressRel = pos() - e->globalPos();
else if(mFrmSec==Qt::BottomRightSection) mPressRel = QPoint(width() - e->globalX(), height() - e->globalY());
else if(mFrmSec==Qt::RightSection ) mPressRel = QPoint(width() - e->globalX(), height() );
else if(mFrmSec==Qt::BottomSection ) mPressRel = QPoint(width() , height() - e->globalY());

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_TW">
</TS>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@ public:
reply->deleteLater();
});
}
QPushButton *btnAbort;
QLabel *fdText;
QString sucText;
WaitingIndicator *mIndicator;