1042版本发行

This commit is contained in:
2026-07-30 08:24:45 +08:00
parent 241367e8d6
commit dea3229996
23 changed files with 3127 additions and 3303 deletions
+2
View File
@@ -2756,6 +2756,8 @@ int DevOp::writeFpgaPrintPara(bool ignoreWarn){
writeSyncAndDelayPrintCount(sysPara->para.enbSyncAndTimeTriggerLimit, sysPara->para.syncAndTimeTriggerLimit); writeSyncAndDelayPrintCount(sysPara->para.enbSyncAndTimeTriggerLimit, sysPara->para.syncAndTimeTriggerLimit);
LogInfo::setRunStatusText(QString("Sync and time trigger limit: %1, num: %2")
.arg(sysPara->para.enbSyncAndTimeTriggerLimit).arg(sysPara->para.syncAndTimeTriggerLimit));
/*---------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------*/
setOscillatorVoltage(sysPara->para.oscillatorVoltage); //因为经过调整参数,所以开机也要多发送一次 setOscillatorVoltage(sysPara->para.oscillatorVoltage); //因为经过调整参数,所以开机也要多发送一次
+42 -11
View File
@@ -801,7 +801,7 @@ void InkJetPrinter::timerHandler(void){
if((QTime::currentTime()>=QTime(00,00,00))&&(QTime::currentTime()<=QTime(00,00,02))&&sysPara->para.Reciclar){ if((QTime::currentTime()>=QTime(00,00,00))&&(QTime::currentTime()<=QTime(00,00,02))&&sysPara->para.Reciclar){
if(m_MainWidget->getCurrPrintStatus() != 1){ if(m_MainWidget->getCurrPrintStatus() != 1){
m_MainWidget->_on_pushButtonPowerOff_pressed(false); m_MainWidget->_on_pushButtonPowerOff_pressed(false);
LogInfo::setRunStatusText(tr("测试时间结束,准备关机")); LogInfo::setRunStatusText(tr("定时开机循环完成,准备关机"));
} }
} }
if(sysPara->status.selfCheckDone && sysPara->para.Reciclar && test_flag){ if(sysPara->status.selfCheckDone && sysPara->para.Reciclar && test_flag){
@@ -871,6 +871,23 @@ void InkJetPrinter::timerHandler(void){
if(sysPara->status.delay10s == 10){ if(sysPara->status.delay10s == 10){
pulse_100s = 1; pulse_100s = 1;
sysPara->status.delay10s = 0; sysPara->status.delay10s = 0;
// if(sysPara->status.flagOfPowerOnMode && (ui->tabMainWindow->getCurrPrintStatus() != 1))
if(sysPara->status.flagOfPowerOnMode)
{
qDebug()<<"waitPowerOffTime: "<<sysPara->status.waitPowerOffTime;
LogInfo::setRunStatusText(tr("waitPowerOffTime: %1").arg(sysPara->status.waitPowerOffTime));
if(sysPara->status.waitPowerOffTime)
{
sysPara->status.waitPowerOffTime--;
if(!sysPara->status.waitPowerOffTime)
{
m_MainWidget->_on_pushButtonPowerOff_pressed(false);
LogInfo::setRunStatusText(tr("定时开机循环完成,准备关机"));
m_MainWidget->setRunStatus(tr("准备关机"));
}
}
}
} }
} }
@@ -956,9 +973,7 @@ void InkJetPrinter::timerHandler(void){
// byons: 变量类图元现在优化为局部更新,避免每次都要把整个打印内容发送给FPGA,现在只发送被更新的列区间 2026年7月16日 // byons: 变量类图元现在优化为局部更新,避免每次都要把整个打印内容发送给FPGA,现在只发送被更新的列区间 2026年7月16日
auto updateAreas = m_MainWidget->variableItemsUpdate(); auto updateAreas = m_MainWidget->variableItemsUpdate();
if(sysPara->status.isPrinting && !updateAreas.isEmpty()){ if(sysPara->status.isPrinting && !updateAreas.isEmpty()){
for(const auto& area : updateAreas) { m_MainWidget->SendPrintDataToFpga(0, true);
m_MainWidget->SendPrintDataToFpga(0, area.left(), area.width());
}
} }
if (!updateAreas.isEmpty() && m_StackedWidget->currentWidget() == m_MainWidget) { if (!updateAreas.isEmpty() && m_StackedWidget->currentWidget() == m_MainWidget) {
@@ -1804,6 +1819,7 @@ void InkJetPrinter::saveFPGAStatus(unsigned char *data){
if(sysPara->status.dummy != sysPara->status.isPrinting && sysPara->status.selfCheckDone){ if(sysPara->status.dummy != sysPara->status.isPrinting && sysPara->status.selfCheckDone){
sysPara->status.isPrinting = sysPara->status.dummy; sysPara->status.isPrinting = sysPara->status.dummy;
m_MainWidget->updatePrintDisplayLabel(); m_MainWidget->updatePrintDisplayLabel();
emit printStatusChanged(sysPara->status.isPrinting);
} }
} }
@@ -1915,19 +1931,23 @@ void InkJetPrinter::savePulseCntVal(unsigned char *data){
} }
} }
void InkJetPrinter::saveSTM32Version(unsigned char *data){ void InkJetPrinter::saveSTM32Version(unsigned char *data)
{
qDebug()<<"saveSTM32Version"; qDebug()<<"saveSTM32Version";
static unsigned char STM32Verion[3] = {0}; //时间间隔内的脉冲累计数 static unsigned char STM32Verion[3] = {0}; //时间间隔内的脉冲累计数
unsigned char *target= ((unsigned char *)&sysPara->status.stm32Verion); unsigned char *target= ((unsigned char *)&sysPara->status.stm32Verion);
for(int i=0;i<data[3];i++){ for(int i=0;i<data[3];i++){
target[i]=data[4+i]; target[i]=data[4+i];
} }
sysPara->status.flagOfPowerOnMode = (sysPara->status.stm32Verion>>23) & 0x01;
QString STM32Ver = QString("%1.%2.%3").arg((sysPara->status.stm32Verion>>16)&0xFF) if(sysPara->status.flagOfPowerOnMode)
sysPara->status.waitPowerOffTime = 18;//半个小时
else
sysPara->status.waitPowerOffTime = 0;
LogInfo::setRunStatusText(tr("flagOfPowerOnMode: %1").arg(sysPara->status.flagOfPowerOnMode));
QString STM32Ver = QString("%1.%2.%3").arg((sysPara->status.stm32Verion>>16)&0x7F)
.arg((sysPara->status.stm32Verion>>8) & 0xFF).arg(sysPara->status.stm32Verion&0xFF); .arg((sysPara->status.stm32Verion>>8) & 0xFF).arg(sysPara->status.stm32Verion&0xFF);
qDebug()<<"STM32Ver:"<<STM32Ver; qDebug()<<"STM32Ver:"<<STM32Ver;
LogInfo::setRunStatusText(QString("STM32Ver: %1").arg(STM32Ver));
} }
void InkJetPrinter::saveSTM32Time(unsigned char *data){ void InkJetPrinter::saveSTM32Time(unsigned char *data){
@@ -2659,6 +2679,15 @@ bool InkJetPrinter::loadLastWorkAndPreparePrint()
return loadWorkFileAndPreparePrint(lastFilename); return loadWorkFileAndPreparePrint(lastFilename);
} }
void InkJetPrinter::restartPrintWhenSwitchedWorkFile(bool isPrinting)
{
if(!isPrinting) {
m_MainWidget->on_m_StartBtn_clicked();
auto ret = disconnect(this, &InkJetPrinter::printStatusChanged, this, &InkJetPrinter::restartPrintWhenSwitchedWorkFile);
LogInfo::setRunStatusText(QString("Printing has restarted: %1").arg(ret));
}
}
bool InkJetPrinter::loadWorkFileAndPreparePrint(const QString &filename) bool InkJetPrinter::loadWorkFileAndPreparePrint(const QString &filename)
{ {
auto u8Filename = filename.toUtf8(); auto u8Filename = filename.toUtf8();
@@ -2678,7 +2707,10 @@ bool InkJetPrinter::loadWorkFileAndPreparePrint(const QString &filename)
bool rePrint = false; bool rePrint = false;
if(sysPara->status.isPrinting && sysPara->status.selfCheckDone) { if(sysPara->status.isPrinting && sysPara->status.selfCheckDone) {
// connect(this, &InkJetPrinter::printStatusChanged,
// this, &InkJetPrinter::restartPrintWhenSwitchedWorkFile, Qt::ConnectionType(Qt::DirectConnection | Qt::UniqueConnection));
m_MainWidget->on_m_StopBtn_clicked(); m_MainWidget->on_m_StopBtn_clicked();
LogInfo::setRunStatusText("Pause printing first, then write to the new file");
rePrint = true; rePrint = true;
} }
@@ -2713,7 +2745,6 @@ bool InkJetPrinter::loadWorkFileAndPreparePrint(const QString &filename)
return true; return true;
} }
static int highPressureCnt = 0; static int highPressureCnt = 0;
static unsigned int logCnt = 0; static unsigned int logCnt = 0;
@@ -3226,4 +3257,4 @@ void InkJetPrinter::onDlgFileOpen(const QString& filename)
} }
loadWorkFileAndPreparePrint(filename); loadWorkFileAndPreparePrint(filename);
} }
+4
View File
@@ -156,6 +156,8 @@ private:
private slots: private slots:
void onDlgFileOpen(const QString& filename); void onDlgFileOpen(const QString& filename);
void restartPrintWhenSwitchedWorkFile(bool isPrinting);
void slt_showMsg(QString msg); void slt_showMsg(QString msg);
void timerHandler(); void timerHandler();
void getMainWidgetButtonClickedSlot(int index); void getMainWidgetButtonClickedSlot(int index);
@@ -221,6 +223,8 @@ private slots:
signals: signals:
void maintenanceShow(); void maintenanceShow();
void printStatusChanged(bool isPrinting);
protected: protected:
void showEvent(QShowEvent* e) override; void showEvent(QShowEvent* e) override;
+4
View File
@@ -202,7 +202,11 @@ void Logger::log(const QtMsgType type, const QString& message, const QString &fi
mutex.lock(); mutex.lock();
LogMessage* logMessage=new LogMessage(type,message,logVars.localData(),file,function,line); LogMessage* logMessage=new LogMessage(type,message,logVars.localData(),file,function,line);
#ifndef BNS_DEBUG
std::cout << qPrintable(logMessage->toString(msgFormat,"hh:mm:ss.zzz")) << std::flush; std::cout << qPrintable(logMessage->toString(msgFormat,"hh:mm:ss.zzz")) << std::flush;
#endif
if (bufferSize>0) if (bufferSize>0)
{ {
+1 -1
View File
@@ -146,7 +146,7 @@ void LogInfo::showVerionInformation(QString Mac,QString VernonBachVer, QString F
if(!flag){ if(!flag){
QString machInfo; QString machInfo;
machInfo = "Mac:" + Mac + "\n"; machInfo = "Mac:" + Mac + "\n";
machInfo += "VernonBach Ver:" + VernonBachVer +"|"+STM32Ver+ "\n"; machInfo += "QtUI Ver:" + VernonBachVer +"|"+STM32Ver+ "\n";
machInfo += "FPGA Ver: NO" + FpgaVer + "\n"; machInfo += "FPGA Ver: NO" + FpgaVer + "\n";
// machInfo += "PowerOnMode: " + QString::number(powerOnMode) + "\n"; // machInfo += "PowerOnMode: " + QString::number(powerOnMode) + "\n";
textEditMachInfo->append(machInfo); textEditMachInfo->append(machInfo);
+1
View File
@@ -78,6 +78,7 @@ linux-aarch64-gnu-g++ {
bns-linux-aarch64-gnu-g++ { bns-linux-aarch64-gnu-g++ {
DEFINES += ARCH_AARCH64_GNU DEFINES += ARCH_AARCH64_GNU
DEFINES += ARCH_AARCH64 DEFINES += ARCH_AARCH64
DEFINES += BNS_DEBUG
} }
HEADERS += Public.h \ HEADERS += Public.h \
-6
View File
@@ -27,8 +27,6 @@
#define VNLG #define VNLG
SysPara::SysPara(void): SysPara::SysPara(void):
devOp(new DevOp(this)){ devOp(new DevOp(this)){
memset(&para,0,sizeof(para)); memset(&para,0,sizeof(para));
memset(&status,0,sizeof(status)); memset(&status,0,sizeof(status));
//qDebug("start to loadParaFromFile."); //qDebug("start to loadParaFromFile.");
@@ -113,10 +111,6 @@ void SysPara::loadParaFromFile(){
if(para.gearPumpSpeedAlarm < 1000 || para.gearPumpSpeedAlarm > 2000) if(para.gearPumpSpeedAlarm < 1000 || para.gearPumpSpeedAlarm > 2000)
para.gearPumpSpeedAlarm = 1500; para.gearPumpSpeedAlarm = 1500;
// 将flagOfReclaimPumEnable强制设置为0。该参数影响的是压力控制算法,但现在已经不使用 byons@2026年5月12日
if(!para.flagOfReclaimPumEnable)
para.flagOfReclaimPumEnable = true;
if (DeviceCodefile.isOpen()) { if (DeviceCodefile.isOpen()) {
DeviceCodefile.close(); DeviceCodefile.close();
} }
+2
View File
@@ -1266,6 +1266,8 @@ typedef struct{
unsigned int showInkWarningNumber; unsigned int showInkWarningNumber;
unsigned int showSolventWarningNumber; unsigned int showSolventWarningNumber;
bool needMaintenanceRemind; bool needMaintenanceRemind;
bool flagOfPowerOnMode;
unsigned int waitPowerOffTime;
}sysStatus_t; }sysStatus_t;
#include <stdint.h> #include <stdint.h>
+1 -1
View File
@@ -6,7 +6,7 @@
*/ */
#define UP_PRINTER_MAJOR_VER 6 #define UP_PRINTER_MAJOR_VER 6
#define UP_PRINTER_MINOR_VER 7 #define UP_PRINTER_MINOR_VER 7
#define UP_PRINTER_RIVISION_VER 4 #define UP_PRINTER_RIVISION_VER 6
#define SUB_VERSION "_KOR" #define SUB_VERSION "_KOR"
#ifdef __RFID_OLD #ifdef __RFID_OLD
#define SUB_RFID "_RO" #define SUB_RFID "_RO"
+328 -330
View File
File diff suppressed because it is too large Load Diff
+190 -87
View File
@@ -15,8 +15,8 @@
3. [整体架构](#3-整体架构) 3. [整体架构](#3-整体架构)
4. [目录结构](#4-目录结构) 4. [目录结构](#4-目录结构)
5. [核心模块详解](#5-核心模块详解) 5. [核心模块详解](#5-核心模块详解)
6. [数据流与通信机制](#6-数据流与通信机制) 6. [场景与打印渲染系统](#6-场景与打印渲染系统)
7. [场景与打印渲染系统](#7-场景与打印渲染系统) 7. [数据流与通信机制](#7-数据流与通信机制)
8. [RFID刷卡模块](#8-rfid刷卡模块) 8. [RFID刷卡模块](#8-rfid刷卡模块)
9. [编译构建系统](#9-编译构建系统) 9. [编译构建系统](#9-编译构建系统)
10. [关键配置与宏定义](#10-关键配置与宏定义) 10. [关键配置与宏定义](#10-关键配置与宏定义)
@@ -65,25 +65,25 @@
``` ```
┌─────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────┐
│ UI 表现层 │ │ UI 表现层 │
│ InkJetPrinter (主窗口) + MainWidget (打印主界面) │ │ InkJetPrinter (主窗口) + MainWidget (打印主界面) │
│ 各功能页面: SystemManage, SystemSetting, LogInfo, ... │ │ 各功能页面: SystemManage, SystemSetting, LogInfo, ... │
│ 场景编辑器: TestPrintWidget, PicScene │ │ 场景编辑器: TestPrintWidget, PicScene │
├─────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────┤
│ 业务逻辑层 │ │ 业务逻辑层 │
│ SysPara (系统参数管理) │ │ SysPara (系统参数管理) │
│ DevOp (设备操作) │ │ DevOp (设备操作) │
│ RunTimeCtrl (运行时间统计) │ │ RunTimeCtrl (运行时间统计) │
│ RFIDManager (刷卡管理) │ │ RFIDManager (刷卡管理) │
├─────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────┤
│ 通信层 │ │ 通信层 │
│ Serial (串口通信封装) │ │ Serial (串口通信封装) │
│ Modbus (Modbus协议) │ │ Modbus (Modbus协议) │
├─────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────┤
│ 硬件抽象层 │ │ 硬件抽象层 │
│ FPGA (喷印控制、充电电压、相位检测) │ │ FPGA (喷印控制、充电电压、相位检测) │
│ STM32 (墨路控制、传感器采集) │ │ STM32 (墨路控制、传感器采集) │
│ RFID读卡器 (IC卡读写) │ │ RFID读卡器 (IC卡读写) │
└─────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────┘
``` ```
@@ -302,11 +302,7 @@ RunTimeCtrl (运行时间控制)
- 计数器读写: 产品计数、同步计数 - 计数器读写: 产品计数、同步计数
**FPGA地址空间**: **FPGA地址空间**:
通信地址与定义位于[连续墨点喷码机通信协议](连续墨点喷码机通信地址.xlsx),大致内存分布如下 通信地址与定义位于[连续墨点喷码机通信协议](连续墨点喷码机通信地址.xlsx)
- `0x0000-0x01FF`: 状态读取区
- `0xA400-0xA5FF`: 打印控制寄存器
- `0xB000-0xCFFF`: 数据写入区(DAC表、打印数据、日历数据等)
- `0xE000-0xFFFF`: 数字字符点阵数据
### 5.6 串口通信 (Serial) ### 5.6 串口通信 (Serial)
@@ -328,7 +324,14 @@ RunTimeCtrl (运行时间控制)
### 5.7 日志系统 (Log) ### 5.7 日志系统 (Log)
**职责**: 提供分级日志记录功能。 #### 5.7.1 基于LogInfo的用户日志系统
**主要类**:
- `LogInfo` - 用户日志的核心类,提供日志记录、显示和保存功能,跟踪用户操作和系统事件。
#### 5.7.2 基于QDebug的日志系统
**职责**: 提供程序运行时的日志记录功能,用于开发调试和问题排查。
**类层次**: **类层次**:
- `Logger` - 日志基类,定义日志格式、级别过滤 - `Logger` - 日志基类,定义日志格式、级别过滤
@@ -356,20 +359,164 @@ qCritical() << "error"; // 错误日志
--- ---
## 6. 数据流与通信机制
### 6.1 打印数据流 ## 6. 场景与打印渲染系统
### 6.1 架构概述
场景系统基于 Qt Graphics View 框架,用于编辑和预览喷码内容。
```
PicScene (QGraphicsScene) # 场景,管理所有图元
├── 图元基类
│ ├── PicTextItem # 普通文本
│ ├── PicDateItem # 日期变量 (yyyy-MM-dd HH:mm:ss...)
│ ├── PicCounterItem # 计数器 (可变数字)
│ ├── PicImageItem # 图片 (Logo)
│ ├── PicCodeItem # 条码/二维码
│ └── PicScheduleShiftItem # 班次 (班次代码替换)
│
├── 图元编辑器
│ ├── ItemEditor # 普通文本编辑器
│ ├── DateVarSet # 日期变量编辑器
│ ├── CounterCarSet # 计数器编辑器
│ ├── ImageLoader # 图片读取器
│ ├── BarcodeEditor # 条码/二维码编辑器
│ └── ScheduleShiftsEditor # 班次 (班次代码替换)编辑器
│
├── 图元模型
│ ├── ItemEditor # 普通文本编辑器
│ ├── DateVarSet # 日期变量编辑器
│ ├── CounterCarSet # 计数器编辑器
│ ├── ImageLoader # 图片读取器
│ ├── BarcodeEditor # 条码/二维码编辑器
│ └── ScheduleShiftsEditor # 班次 (班次代码替换)编辑器
```
### 6.2 作业文件格式
作业文件使用XML格式(VBfiles结构),保存场景内容和打印设置:
```xml
<VBfiles>
<!-- 打印设置 -->
<PrintSettings timeTriggerPrintMode="0" triggerInterval="90" ... />
<!-- 文本图元 -->
<VBfile>
<pointer_x>55</pointer_x>
<pointer_y>0</pointer_y>
...
<itemAttrs sourceType="1" dir="0" letterSpace="1" fontFamilay="WenQuanYi7" source="FGJ" ... />
</VBfile>
<!-- 日期图元 -->
<VBfile>
<pointer_x>55</pointer_x>
<pointer_y>0</pointer_y>
...
<itemAttrs sourceType="3" datetimePattern="HH:mm:ss" ... />
</VBfile>
<!-- 计数器图元 -->
<VBfile>
<pointer_x>83</pointer_x>
<pointer_y>17</pointer_y>
...
<itemAttrs sourceType="6" counter_type="7" digital_num="8" ... />
</VBfile>
<!-- 条码/二维码图元 -->
<VBfile>
<pointer_x>0</pointer_x>
<pointer_y>0</pointer_y>
...
<itemAttrs sourceType="5" dir="0" barcodeContentPattern="dr66re{t}{c}" barcodeType="2" qrcodeFormat="0" ... />
</VBfile>
<!-- 图片图元 -->
<VBfile>
<pointer_x>0</pointer_x>
<pointer_y>0</pointer_y>
...
<itemAttrs sourceType="2" dir="0" source="/home/plg/doc/scene.png" ... />
</VBfile>
</VBfiles>
```
### 6.3 关键类说明
- **PicSceneLoader** - 场景文件的加载/保存/预览,负责XML序列化/反序列化
- **ViewModels** - 定义 `DateItemModel`、`CounterViewModel` 等视图模型,用于编辑器与图元之间的数据传递
- **ItemCommon** - 图元工具函数,如根据日期模型生成文本字符串
- **打印设置** - `PrintSettingModel` 与作业文件绑定,包含触发模式、字宽、同步器参数等
- **TestPrintWidget** - 场景编辑器,提供图元的创建、编辑、删除、预览功能
---
## 7. 数据流与通信机制
### 7.1 打印内容数据流
``` ```
用户编辑场景 (PicScene) 用户编辑场景 (PicScene)
└── 图元 (PicTextItem, PicDateItem, PicCodeItem, ...) ├── 普通静态图元 (PicTextItem, PicImageItem, ...)
└── 渲染为 QImage │ └─── onPreviewScene() 静态文本或图片渲染为 QImage
└── imageToPrintData() 转换为点阵数据 │ └── imageToPrintData() 转换为点阵数据
└── SendPrintDataToFpga() 通过 Serial 发送 │ └── SendPrintDataToFpga() 在打印开始前一次性发送所有静态打印内容
└── FPGA 接收并驱动喷头喷印 │ └── FPGA 接收并驱动喷头喷印
│
├─── PicCounterItem 计数器图元
│ └── onPreviewScene() 构建变量控制结构体(位置、大小、类型等)
│ └── DevOp::writeFpgaVariCtrl() 发送至FPGA,由FPGA直接硬件控制
│
└─── 软解动态图元 (PicDateItem PicScheduleShiftItem PicCodeItem)
└── onPreviewScene() 与静态图元一样,进入onPreviewScene()
└── variableItemsUpdate() 动态检查图元是否发生变化,更新数据
└── SendPrintDataToFpga() 局部发送更新后的点阵数据至FPGA
``` ```
### 6.2 设备状态轮询 **打印内容相关的几个重要的函数:**
[SendPrintDataToFpga()](../mainwidget.cpp#L935) 负责将打印数据、打印设置和变量控制通过串口发送给FPGA,FPGA接收后驱动喷头进行喷印。该函数被设计成支持全量更新与局部更新,静态图元在打印开始前一次性发送,而动态图元则在每次变化时局部更新。局部更新时,SendPrintDataToFpga不会发送打印设置和变量控制数据,只会按列为单位更新打印缓冲区的点阵数据。
[imageToPrintData()](../mainwidget.cpp#L675) 将 QImage 转换为点阵数据,该函数可将图像填充至打印缓冲区的指定位置,随后由 SendPrintDataToFpga() 发送至FPGA。动态软解图元(如日期、计数器、二维码)在每次变化时调用该函数刷新打印缓冲区。
[onPreviewScene()](../mainwidget.cpp#L1888) 是场景预览的核心函数,负责将场景中的所有图元渲染为 QImage,并调用 imageToPrintData() 全量写入打印缓冲区。
[variableItemsUpdate()](../mainwidget.cpp#L1024) 动态检查图元是否发生变化,配合 imageToPrintData()、SendPrintDataToFpga() 实现局部更新打印数据。
### 7.2 从文件到打印的数据流向
本节中 *发送打印设置与打印内容到FPGA* 的术语基本可以代指调用[MainWidget::SendPrintDataToFpga](../mainwidget.cpp#L933)函数。
区别于标准VX5,此韩国定制版中,明确了发送打印内容与打印设置到FPGA的时机与作用范围,所有发送打印内容与打印设置的动作只在[MainWidget::on_m_StartBtn_clicked()](../mainwidget.cpp#L756)中进行,除此之外其它时机发送打印内容与设置的行为继承自标准VX5,实际在韩国定制版中属于冗余设计。
QtUI 按工作文件为单位对喷码内容进行管理,工作文件使用 XML 格式保存场景内容和打印设置。用户在编辑界面(TestPrintWidget)中创建或修改工作文件后,点击“保存”按钮将场景数据序列化为 XML 文件。随后,用户在打印主界面(MainWidget)中选择工作文件并点击“打印”。
重要的工作流程位于[InkjetPrinter::loadWorkFileAndPreparePrint](../InkJetPrinter.cpp#L12684)函数中,流程如下:
```
用户点击 [MainWidget::m_AddBtn](../MainWidget.cpp#L143) (调入文件喷印) 发送 sendButtonClickedSignal(2) 信号
└── InkJetPrinter::getMainWidgetButtonClickedSlot() 接收信号打开 DialogFileOperation 对话框
└── InkjetPrinter::loadWorkFileAndPreparePrint() 通过对话框输入的文件名打开文件
└── PicSceneLoader::loadSceneFromFile() 解析 XML 文件,恢复场景内容和打印设置
└── MainWidget::generatePrintContent() 将场景渲染为打印数据并写入缓冲区
└── 等待用户按下 开始打印
└── MainWidget::SendPrintDataToFpga() 全量发送打印数据与设置到FPGA,并开始打印
```
注意打开并解析工作文件的过程中不会直接发送打印数据到FPGA,只有在用户点击“打印”按钮后,才会调用 SendPrintDataToFpga() 将打印数据发送至FPGA。
### 7.3 工作文件编辑
韩国QtUI中,*工作文件编辑* 被解耦为一个独立模块,它只负责对工作文件进行新建、编辑和调用[PicSceneLoader](../scene/PicSceneLoader.h)模块保存,其主要实现基本位于[TestPrintWidget](../testprintwidget.h),[TestPrintWidget](../testprintwidget.h)通过读取指定工作文件(或新建),在编辑完成后可以对文件进行保存。
```
用户点击 (新建文件) (编辑文件) 发送信号到InjkectPrinter
└── InkJetPrinter判断当前文件名,将文件名传给TestPrintWidget,并切换到TestPrintWidget视图
└── TestPrintWidget完成编辑后询问用户是否保存已编辑的工作文件
├── 用户选择保存,TestPrintWidget 使用 PicSceneLoader 写入xml工作文件
│ └─ 保存文件后发出信号通知 InjkectPrinter
│ └─ InkjectPrinter 切换到 MainWidget 并调用 loadWorkFileAndPreparePrint 载入刚刚保存的文件
│ └─ 之后的流程与 7.2 小节一致
│
└── 用户选择不保存,TestPrintWidget 直接发出信号通知 InjkectPrinter
└─ InkjectPrinter 切换到 MainWidget,然后什么也不做
```
### 7.4 设备状态轮询
``` ```
timerHandler() timerHandler()
@@ -387,7 +534,7 @@ timerHandler()
└── autoControlValvePump() # 自动控制执行 └── autoControlValvePump() # 自动控制执行
``` ```
### 6.3 信号槽通信概览 ### 7.5 信号槽通信概览
``` ```
Serial::receivedFromFPGA ──→ InkJetPrinter::saveFPGAStatus() Serial::receivedFromFPGA ──→ InkJetPrinter::saveFPGAStatus()
@@ -398,56 +545,7 @@ RunTimeCtrl::sig_alertTimeout ──→ InkJetPrinter::slt_warningMaintenance()
RFIDManager::sig_showMsg ──→ InkJetPrinter::slt_showMsg() RFIDManager::sig_showMsg ──→ InkJetPrinter::slt_showMsg()
``` ```
---
## 7. 场景与打印渲染系统
### 7.1 架构概述
场景系统基于 Qt Graphics View 框架,用于编辑和预览喷码内容。
```
PicScene (QGraphicsScene) # 场景,管理所有图元
└── myView (QGraphicsView) # 视图,提供缩放和交互
└── 图元基类
├── PicTextItem # 普通文本
├── PicDateItem # 日期变量 (yyyy-MM-dd HH:mm:ss...)
├── PicCounterItem # 计数器 (可变数字)
├── PicImageItem # 图片 (Logo)
├── PicCodeItem # 条码/二维码
└── PicScheduleShiftItem # 班次 (班次代码替换)
```
### 7.2 作业文件格式
作业文件使用XML格式(VBfiles结构),保存场景内容和打印设置:
```xml
<VBfiles>
<VBfile>
<!-- 打印设置 -->
<PrintSettings triggerMode="0" ... />
<!-- 文本图元 -->
<VB itemType="text" x="10" y="20" text="ABC" ... />
<!-- 日期图元 -->
<VB itemType="date" x="50" y="20" pattern="yyyy-MM-dd" ... />
<!-- 计数器图元 -->
<VB itemType="counter" x="100" y="20" counterType="7" ... />
<!-- 条码/二维码图元 -->
<VB itemType="code" x="10" y="50" codeType="QR" ... />
<!-- 图片图元 -->
<VB itemType="image" x="200" y="0" ... />
</VBfile>
</VBfiles>
```
### 7.3 关键类说明
- **PicSceneLoader** - 场景文件的加载/保存/预览,负责XML序列化/反序列化
- **ViewModels** - 定义 `DateItemModel`、`CounterViewModel` 等视图模型,用于编辑器与图元之间的数据传递
- **ItemCommon** - 图元工具函数,如根据日期模型生成文本字符串
- **ItemEditor** - 图元通用编辑器(字体、颜色、位置等)
- **打印设置** - `PrintSettingModel` 与作业文件绑定,包含触发模式、字宽、同步器参数等
--- ---
@@ -464,6 +562,7 @@ PicScene (QGraphicsScene) # 场景,管理所有图元
- 保养卡识别与提醒 - 保养卡识别与提醒
- 自动扣减卡内余额 - 自动扣减卡内余额
- 卡片使用标记(防重复使用) - 卡片使用标记(防重复使用)
- 超级卡的识别与处理
**加密**: 使用SM3(哈希)+ SM4(对称加密)国密算法保护卡片数据。 **加密**: 使用SM3(哈希)+ SM4(对称加密)国密算法保护卡片数据。
@@ -541,10 +640,12 @@ make
```cpp ```cpp
#define UP_PRINTER_MAJOR_VER 6 #define UP_PRINTER_MAJOR_VER 6
#define UP_PRINTER_MINOR_VER 7 #define UP_PRINTER_MINOR_VER 7
#define UP_PRINTER_RIVISION_VER 4 #define UP_PRINTER_RIVISION_VER 5
#define SUB_VERSION "_KOR" #define SUB_VERSION "_KOR"
``` ```
版本号分为年、月、本月第几次编译,SUB_VERSION表示是否是标准版,"_Std" 表示标准版,"_KOR" 表示韩国定制版、"_RFID" 表示是标准版基础上增加了刷卡功能,如果客户定制版本包含了刷卡功能,则显示客户后缀。
--- ---
## 11. 上手指南 ## 11. 上手指南
@@ -552,15 +653,15 @@ make
### 11.1 开发环境搭建 ### 11.1 开发环境搭建
1. **安装Qt**: 推荐 Qt 5.12+ 用于桌面开发调试 1. **安装Qt**: 推荐 Qt 5.12+ 用于桌面开发调试
2. **获取代码**: 通过SVN或Git获取项目源码 2. **获取代码**: 找到你的领导,通过SVN获取源码
3. **编译运行**: 3. **编译运行**:
```bash 1. 直接使用 InkjetUbuntu-T1 虚拟机中的 QtCreator 打开此项目,然后编译调试。
cd 项目目录 2. 使用 VSCode ssh 连接 InkjetUbuntu-T2(从T1升级至Ubuntu20.04,以支持VSCode SSH连接) 虚拟机,然后直接在windows上远程开发,此方式需要自行配置编译环境,编译为ARM版本的命令为:
qmake ```bash
make $ /home/inkjet/QtSDK/bin/qmake ./QtUI.pro -spec linux-aarch64-gnu-g++ CONFIG+=release
./QtUI $ make -j8
``` ```
4. **注意事项**: x86桌面版仅用于UI调试,硬件相关功能(串口、FPGA通信)不可用 4. **注意事项**: x86桌面版仅用于UI调试,硬件相关功能(串口、FPGA通信)不可用。
### 11.2 代码阅读顺序建议 ### 11.2 代码阅读顺序建议
@@ -581,6 +682,7 @@ make
| 修改FPGA通信 | `DevOp.h/cpp` + `Serial/` | 注意地址空间分配和CRC校验 | | 修改FPGA通信 | `DevOp.h/cpp` + `Serial/` | 注意地址空间分配和CRC校验 |
| 修改UI样式 | `.ui` 文件 | 使用 Qt Designer 编辑 | | 修改UI样式 | `.ui` 文件 | 使用 Qt Designer 编辑 |
| 添加新功能页面 | 仿照现有页面模式 | 创建 .h/.cpp/.ui 三件套 | | 添加新功能页面 | 仿照现有页面模式 | 创建 .h/.cpp/.ui 三件套 |
| 添加网络通信 ||
### 11.4 关键设计模式 ### 11.4 关键设计模式
@@ -591,9 +693,9 @@ make
### 11.5 调试技巧 ### 11.5 调试技巧
1. **日志**: 使用 `qInfo()/qWarning()/qCritical()` 输出,日志文件位于 `/home/plg/conf/` 1. **日志**: Debug模式下使用 `qInfo()/qWarning()/qCritical()` 输出,日志文件位于 `/home/plg/conf/`,发行版使用`LogInfo::setRunStatus()`
2. **崩溃分析**: `dump.h/cpp` 安装了信号处理器,崩溃时会生成core dump 2. **崩溃分析**: `dump.h/cpp` 安装了信号处理器,崩溃时会生成core dump
3. **FPGA调试**: 可通过 `SystemManage` 界面手动控制阀门和泵 3. **泵阀手动控制**: 可通过 `SystemManage` 界面手动控制阀门和泵
4. **模拟模式**: 设置 `SIMULATE_PRINTING_MODE 1` 可在无硬件环境调试打印逻辑 4. **模拟模式**: 设置 `SIMULATE_PRINTING_MODE 1` 可在无硬件环境调试打印逻辑
### 11.6 注意事项 ### 11.6 注意事项
@@ -611,5 +713,6 @@ make
**文档更新记录** **文档更新记录**
- 2026-07-23: 创建此文档 — 卜永仕 - 2026-07-29:继续完善了此文档 - 卜永仕
- 2026-07-23:创建此文档 — 卜永仕
+328 -330
View File
File diff suppressed because it is too large Load Diff
+328 -330
View File
File diff suppressed because it is too large Load Diff
+326 -312
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -1,5 +1,16 @@
#include "loginfoctrl.h" #include "loginfoctrl.h"
LogInfoCtrl *LogInfoCtrl::instance()
{
static LogInfoCtrl* ins = nullptr;
if (!ins) {
ins = new LogInfoCtrl();
}
return ins;
}
void LogInfoCtrl::emitSigClean() void LogInfoCtrl::emitSigClean()
{ {
emit sig_clean(); emit sig_clean();
+1 -4
View File
@@ -8,10 +8,7 @@ class LogInfoCtrl : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
static LogInfoCtrl* instance() { static LogInfoCtrl* instance();
static LogInfoCtrl ins;
return &ins;
}
void emitSigClean(); void emitSigClean();
void emitSigCleanOver(bool flag); void emitSigCleanOver(bool flag);
+239 -566
View File
@@ -31,6 +31,7 @@
#include "scene/PicDateItem.h" #include "scene/PicDateItem.h"
#include "scene/PicScheduleShiftItem.h" #include "scene/PicScheduleShiftItem.h"
#include "scene/piccodeitem.h" #include "scene/piccodeitem.h"
#include "scene/PicCounterItem.h"
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QScroller> #include <QScroller>
@@ -530,6 +531,8 @@ QList<QRect> MainWidget::variableItemsUpdate()
return QList<QRect>(); return QList<QRect>();
} }
/*
旧实现:
int totalOfProcessedDots = 0; int totalOfProcessedDots = 0;
int totalOfDatetimeNumber = 0; int totalOfDatetimeNumber = 0;
int nbInvaliedDatetimePreview = 0; int nbInvaliedDatetimePreview = 0;
@@ -537,6 +540,38 @@ QList<QRect> MainWidget::variableItemsUpdate()
QList<QRect> updateAreas; QList<QRect> updateAreas;
auto items = pPicScene->items();
for(auto i : items) {
PicTextItem* item = dynamic_cast<PicTextItem*>(i);
if(!item)
continue;
...
auto boundingRect = pPicScene->itemsBoundingRect().toRect();
QRect itemRect(item->pos().x() - boundingRect.x(), item->pos().y() - boundingRect.y(), img.width(), img.height());
...
QRect intersectRect = itemRect.intersected(sceneRect);
...
}
*/
int totalOfProcessedDots = 0;
int totalOfDatetimeNumber = 0;
int nbInvaliedDatetimePreview = 0;
int nbClipDatetimePreview = 0;
QList<QRect> updateAreas;
const QRectF contentRect = pPicScene->itemsBoundingRect();
if(contentRect.isEmpty())
return updateAreas;
const int maxPicWidth = sysPara->status.flagOfNo67FPGA ? MAX_PRINT_COL_NUM_Normal : MAX_PRINT_COL_NUM_Wide;
const int maxPicHeight = MAX_PRINT_ROW_NUM;
const QRectF outputRect(0, 0, maxPicWidth, maxPicHeight);
auto items = pPicScene->items(); auto items = pPicScene->items();
for(auto i : items) { for(auto i : items) {
PicTextItem* item = dynamic_cast<PicTextItem*>(i); PicTextItem* item = dynamic_cast<PicTextItem*>(i);
@@ -570,8 +605,8 @@ QList<QRect> MainWidget::variableItemsUpdate()
auto codeItem = dynamic_cast<PicCodeItem*>(item); auto codeItem = dynamic_cast<PicCodeItem*>(item);
if(!codeItem) if(!codeItem)
continue; continue;
QVector<int> counterValus{QString::number(sysPara->status.calandar_and_dat.cnt1CurrValue,16).toInt(), QVector<int> counterValus{QString::number(sysPara->status.calandar_and_dat.cnt1CurrValue,16).toInt(),
QString::number(sysPara->status.calandar_and_dat.cnt2CurrValue,16).toInt()}; QString::number(sysPara->status.calandar_and_dat.cnt2CurrValue,16).toInt()};
auto b = codeItem->updateVariants(counterValus); auto b = codeItem->updateVariants(counterValus);
if(!b) if(!b)
@@ -584,34 +619,24 @@ QList<QRect> MainWidget::variableItemsUpdate()
continue; continue;
} }
auto sceneRect = pPicScene->sceneRect().toRect(); const QRectF itemSceneRect = item->sceneBoundingRect();
auto boundingRect = pPicScene->itemsBoundingRect().toRect(); const QRectF itemBufferRect = itemSceneRect.translated(-contentRect.topLeft());
QRect itemRect(item->pos().x() - boundingRect.x(), item->pos().y() - boundingRect.y(), img.width(), img.height()); const QRectF clippedBufferRect = itemBufferRect.intersected(outputRect);
totalOfDatetimeNumber++; if(clippedBufferRect.isEmpty())
continue;
// 裁剪item位置, 确保item位于场景内
// 如果item超出了场景范围,则裁剪img并更新itemRect,只显示场景内的部分
QRect intersectRect = itemRect.intersected(sceneRect);
if(!intersectRect.isEmpty() && intersectRect != itemRect) {
// 计算裁剪区域在原图中的偏移
int cropX = qMax(0, (int)(intersectRect.left() - itemRect.left()));
int cropY = qMax(0, (int)(intersectRect.top() - itemRect.top()));
int cropWidth = (int)intersectRect.width();
int cropHeight = (int)intersectRect.height();
// 裁剪图像
img = img.copy(cropX, cropY, cropWidth, cropHeight);
// 更新itemRect为裁剪后的区域
itemRect = intersectRect;
QRect targetRect = clippedBufferRect.toAlignedRect();
totalOfDatetimeNumber++;
if(targetRect != itemBufferRect.toAlignedRect()) {
const int cropX = qMax(0, targetRect.left() - itemBufferRect.toAlignedRect().left());
const int cropY = qMax(0, targetRect.top() - itemBufferRect.toAlignedRect().top());
img = img.copy(cropX, cropY, targetRect.width(), targetRect.height());
++nbClipDatetimePreview; ++nbClipDatetimePreview;
} }
totalOfProcessedDots += imageToPrintData(img, (int)itemRect.left(), (int)itemRect.top()); totalOfProcessedDots += imageToPrintData(img, targetRect.left(), targetRect.top());
updateAreas.append(targetRect);
updateAreas.append(itemRect);
} }
if(updateAreas.isEmpty()) if(updateAreas.isEmpty())
@@ -667,12 +692,15 @@ int MainWidget::imageToPrintData(QImage &image, int startX, int startY)
for(int k = 0; k < height; k++) for(int k = 0; k < height; k++)
{ {
QRgb rgb = image.pixel(j, k); QRgb rgb = image.pixel(j, k);
if(((rgb >> 24) & 0xff) > 0x80) if (rgb & 0x80000000) { // 判断 alpha
{ // 灰度计算:Y = 0.299*R + 0.587*G + 0.114*B
c |= (1 << (hStart % 8)); int y = int((((rgb & 0xff) * 299 + ((rgb >> 8) & 0xff) * 587 + ((rgb >> 16) & 0xff) * 114)) / 1000.0f);
} if (y < 125) {
else c |= (1 << (hStart % 8));
{ } else {
c &= ~(1 << (hStart % 8));
}
} else {
c &= ~(1 << (hStart % 8)); c &= ~(1 << (hStart % 8));
} }
@@ -795,6 +823,7 @@ void MainWidget::on_m_StartBtn_clicked()
sysPara->saveParaToFile(); sysPara->saveParaToFile();
} }
// onPreviewScene 没有必要再次调用,评估后删除 byons@2026年7月28日
if(sysPara->para.EditMode == SCENE) if(sysPara->para.EditMode == SCENE)
onPreviewScene(); onPreviewScene();
@@ -899,19 +928,16 @@ void MainWidget::on_m_StopBtn_clicked()
} }
unsigned char blankDat1[BLANK_COL_NUM*MAX_PRINT_ROW_BYTE_NUM]={0}; unsigned char blankDat1[BLANK_COL_NUM*MAX_PRINT_ROW_BYTE_NUM]={0};
void MainWidget::SendPrintDataToFpga(unsigned char alterMode, int startCol, int size) void MainWidget::SendPrintDataToFpga(unsigned char alterEnable, bool isUpdate)
{ {
if(!sysPara) return ; if(!sysPara) return ;
// fileChange=false; // fileChange=false;
Q_UNUSED(alterMode); Q_UNUSED(alterEnable);
// 看清楚,最后取反,也就是说,如果不是局部更新,则写入打印设置和变量控制 if(!isUpdate) {
if(!(startCol >= 0 && size > 0)) {
sysPara->devOp->writeFpgaPrintPara(1); sysPara->devOp->writeFpgaPrintPara(1);
sysPara->devOp->writeFpgaVariCtrl(); sysPara->devOp->writeFpgaVariCtrl();
startCol = 0;
size = sysPara->status.currPrintCol;
} }
sysPara->devOp->fpgaWr(0,blankDat1,sizeof(blankDat1));//...所加的空白偏移地址 sysPara->devOp->fpgaWr(0,blankDat1,sizeof(blankDat1));//...所加的空白偏移地址
@@ -930,14 +956,11 @@ void MainWidget::SendPrintDataToFpga(unsigned char alterMode, int startCol, int
dat =sysPara->status.printDat; dat =sysPara->status.printDat;
sizeofdat = sizeof(sysPara->status.printDat); sizeofdat = sizeof(sysPara->status.printDat);
} }
if(sysPara->status.currPrintCol* MAX_PRINT_ROW_BYTE_NUM <= 20000)
sysPara->devOp->fpgaWr(sizeof(blankDat1),dat, sysPara->status.currPrintCol* MAX_PRINT_ROW_BYTE_NUM);
else
sysPara->devOp->fpgaWrD2(sizeof(blankDat1),dat, sysPara->status.currPrintCol* MAX_PRINT_ROW_BYTE_NUM);
dat = dat + startCol * MAX_PRINT_ROW_BYTE_NUM;
size = size * MAX_PRINT_ROW_BYTE_NUM;
if(size <= 20000)
sysPara->devOp->fpgaWr(sizeof(blankDat1), dat, size);
else
sysPara->devOp->fpgaWrD2(sizeof(blankDat1), dat, size);
static QElapsedTimer bnsTimer; static QElapsedTimer bnsTimer;
static uint64_t nbRestartCount = 0; static uint64_t nbRestartCount = 0;
@@ -1822,8 +1845,30 @@ int MainWidget::getMaxSpeedCalcPara(){
return pulseNum; return pulseNum;
} }
QRect clipBottom(const QImage& img, const QRect& region)
{
for(int y = region.bottom() - 1; y >= region.top(); --y) {
auto line = img.scanLine(y);
for(int x = region.left(); x < region.right(); ++x) {
auto rgb = *((const uint32_t*)(x * 4 + line));
int y = int((((rgb & 0xff) * 299 + ((rgb >> 8) & 0xff) * 587 + ((rgb >> 16) & 0xff) * 114)) / 1000.0f);
if((rgb & 0x80000000) && y < 125) {
return QRect(QPoint(region.topLeft()), QPoint(region.right(), y + 1));
}
}
}
return QRect(region.topLeft(), QSize(region.width(), 0));
}
void MainWidget::onPreviewScene() void MainWidget::onPreviewScene()
{ {
if(!sysPara){
qCritical() << "SysPara is empty!";
return;
}
sysPara->para.EditMode = SCENE; sysPara->para.EditMode = SCENE;
if(!pPicScene) { if(!pPicScene) {
@@ -1831,547 +1876,176 @@ void MainWidget::onPreviewScene()
} }
pPicScene->clearSelection(); pPicScene->clearSelection();
pPicScene->update();
QRect sceneRect = pPicScene->itemsBoundingRect().toRect(); bool MaxCol4000;
QSize size = sceneRect.size(); if(sysPara->status.flagOfNo67FPGA)
MaxCol4000 = true;
else
MaxCol4000 = false;
unsigned char *dat;
if(MaxCol4000){
dat = sysPara->status.printDat_Normal;
memset(dat,0,sizeof(sysPara->status.printDat_Normal));
}else{
dat = sysPara->status.printDat;
memset(dat,0,sizeof(sysPara->status.printDat));
}
const QRectF contentRect = pPicScene->itemsBoundingRect();
const QRect sceneRect = contentRect.toAlignedRect();
qDebug() << "sceneRect: " << sceneRect;
// 限定最大高度和宽度
int coldot = qMin(sceneRect.width(), MaxCol4000 ? MAX_PRINT_COL_NUM_Normal : MAX_PRINT_COL_NUM_Wide);
int maxPicHeight = qMin(sceneRect.height(), int(sysPara->para.canvasHeight));
QSize size(coldot,maxPicHeight);
if(size.isEmpty()) { if(size.isEmpty()) {
//场景为空时,渲染空场景并刷新界面 //场景为空时,渲染空场景并刷新界面
handleEmptySize(); handleEmptySize();
return; return;
} }
QImage image(size,QImage::Format_ARGB32);
QImage image(size, QImage::Format_ARGB32);
image.fill(0x00ffffff);//填充白色 image.fill(0x00ffffff);//填充白色
//image.save("./printScene.jpg");//图片
QPainter painter(&image); QPainter painter(&image);
pPicScene->render(&painter,QRectF(), sceneRect);
int coldot=0; int firstRow = 0;
if(sysPara){
bool MaxCol4000;
if(sysPara->status.flagOfNo67FPGA)
MaxCol4000 = true;
else
MaxCol4000 = false;
previewFlag=1;
sysPara->status.currPrintRow = 0;
sysPara->status.variNum = 0;
sysPara->status.QRvariNum = 0;
unsigned char *dat;
if(MaxCol4000){
dat =sysPara->status.printDat_Normal;
memset(dat,0,sizeof(sysPara->status.printDat_Normal));
}else{
dat =sysPara->status.printDat;
memset(dat,0,sizeof(sysPara->status.printDat));
}
//qDebug()<<"Preview:";
{ int myvariNum=0;
sysPara->status.addSpace = sysPara->para.checkSpace; int expiryVarNum = 0;
coldot = sceneRect.width(); sysPara->status.variNum = 0;
if(coldot > (MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide)) sysPara->status.QRvariNum = 0;
coldot = MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide; sysPara->status.addSpace = sysPara->para.checkSpace; // 空列已经弃用 __attribute__((deprecated))
int maxPicHeight = MAX_PRINT_ROW_NUM + 12; sysPara->status.currPrintRow = 0;
QSize size(coldot,maxPicHeight); sysPara->status.currPrintCol = coldot;
sysPara->status.ExpiryVarNum = 0;
sysPara->print.ExpiryVar.startColPos = 0;
sysPara->print.ExpiryVar.endRowPos = 0;
sysPara->print.ExpiryVar.letterSpace =0;
sysPara->print.CurDateVar.startColPos = 0;
sysPara->print.CurDateVar.endRowPos = 0;
sysPara->print.CurDateVar.letterSpace = 0;
sysPara->status.CurrDateVariNum = 0;
sysPara->status.currPrintRow =0; qDebug() << "Loading scene items: \r\n\r\n\r\n";
sysPara->status.currPrintCol = coldot + ( sysPara->status.addSpace?coldot:0) ; //checkSpace
QImage image(size,QImage::Format_ARGB32); QList<QGraphicsItem *> items = pPicScene->items();
image.fill(0x00ffffff);//填充白色 foreach (QGraphicsItem *item, items) {
QPainter painter(&image);
QRectF validRectF(sceneRect.x(),sceneRect.y(),coldot,maxPicHeight);
pPicScene->render(&painter,QRectF(),validRectF);
int firstRow = 0;
int lastRow = firstRow + MAX_PRINT_ROW_NUM;
int TempVarNum=0;
int varLastRow=0;
lastRow = (lastRow>maxPicHeight)?maxPicHeight:lastRow;
// 接下来就是要把打印到数据data填充以及确认变量的个数,变量对应的开始列和结束行 PicTextItem *picText = qgraphicsitem_cast<PicTextItem*>(item);
for(int j = 0; j < lastRow - firstRow; j++){ // Y if(!picText)
for(int i = 0; i < coldot; i++){ // continue;
QRgb rgb = image.pixel(i,j + firstRow);
if(rgb&0x80000000){ //判断alpha
if((rgb & 0xf0f0ff) == 0xf0f000){ //处理变量, 查找左下角,因为同一行的左下角是对齐的 看起来这个颜色是黄色
bool foundvar=0;
if(j>0){
QRgb r_rgb = image.pixel(i,j + firstRow+1);
if((r_rgb & 0xf0f0ff) != 0xf0f000 ){foundvar =1;}
//QRgb r_rgb = image.pixel(i,j + firstRow-1);if((r_rgb & 0xf0f0ff) == 0xf0f000 )foundvar =0;
}
if(foundvar){
if(sysPara->status.variNum < MAX_VARI_NUM){
sysPara->status.vars[sysPara->status.variNum].startColPos = i+(sysPara->status.addSpace?i:0);
sysPara->status.vars[sysPara->status.variNum].endRowPos = j;
//if(varLastRow<j+1) varLastRow=j+1;
//sysPara->status.variNum ++;TempVarNum++;
//i+=5;//scene 每一行可能都包含变量
//qDebug()<<"VARr:"<<TempVarNum<<i<<j;
}
else TempVarNum++;
//dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] |= 1 << (j%8); //画黑点
}
}
else if( ((rgb & 0xfffff0) == 0x00ff10) || ((rgb & 0xfffff0) == 0x00ff20) ||((rgb & 0xfffff0) == 0x00ff30) ){
// 0xff00ff01(DMT) 0xff00ff02(QR) 0xff00ff03(BAR)
//qDebug()<<"FLAG:"<<i<<j+1<<QString().sprintf("%08X", rgb);
if(sysPara->status.QRvariNum>=4)continue;
if((rgb & 0x00ffff0) == 0x00ff10) { //MDT
sysPara->print.QRvars[sysPara->status.QRvariNum].type=MDT;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0);
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
else if((rgb & 0x00ffff0) == 0x00ff20) { //QR
sysPara->print.QRvars[sysPara->status.QRvariNum].type=QR;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0);
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
else if((rgb & 0x00fffff0) == 0x00ff30) { //BAR
sysPara->print.QRvars[sysPara->status.QRvariNum].type=BAR;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0);
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
if(sysPara->status.QRvariNum>=4)sysPara->status.QRvariNum=4;
}
else if((rgb & 0x00ffffff)==EXPIRY_VARI_RECONISE)
{ // 有效期变量 : 处理变量, 查找左下角,因为同一行的左下角是对齐的
bool foundExVar=0;
if(j>0){
QRgb r_rgb = image.pixel(i,j + firstRow+1);
if((r_rgb & 0x00ffffff) != EXPIRY_VARI_RECONISE ){foundExVar =1;}
}
if(foundExVar)
{
if(sysPara->status.ExpiryVarNum <2)
{
sysPara->print.ExpiryVar.startColPos = i+(sysPara->status.addSpace?i:0);
sysPara->print.ExpiryVar.endRowPos = j;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.ExpiryVarNum ++;
i+=5;
}
//else TempVarNum++;
//dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] |= 1 << (j%8); //画黑点
}
}
else if((rgb & 0xfffff0)==0xff0cf0)
{ // 有效期变量 : 处理变量, 查找左下角,因为同一行的左下角是对齐的
bool foundExVar=0;
if(j>0){
QRgb r_rgb = image.pixel(i,j + firstRow+1);
if((r_rgb & 0xfffff0) != 0xff0cf0 ){foundExVar =1;}
}
if(foundExVar)
{
if(sysPara->status.ExpiryVarNum <2)
{
sysPara->print.CurDateVar.startColPos = i+(sysPara->status.addSpace?i:0);
sysPara->print.CurDateVar.endRowPos = j;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.CurrDateVariNum ++;
i+=5;
}
//else TempVarNum++;
//dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] |= 1 << (j%8); //画黑点
}
}
else if((rgb & 0xffffff)==0xff00ff)
{ // 有效期变量 : 处理变量, 查找左下角,因为同一行的左下角是对齐的
{
if(sysPara->status.classVariNum <3) {
EXPIRYVAR_t *currCLass = &sysPara->print.ClassVari ;
currCLass->day = QDateTime::currentDateTime().date().day();
currCLass->startColPos = i+(sysPara->status.addSpace?i:0);
currCLass->endRowPos = j;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.classVariNum ++;
i+=5;
}
}
}
else
{ //Y = 0.299*R' + 0.587*G' + 0.114*B //非变量
int y = (((rgb&0xff)*299 + ((rgb>>8)&0xff)*587 + ((rgb>>16)&0xff)*114))/1000;
if(y < 125 ){
dat[MAX_PRINT_ROW_BYTE_NUM*(i+(sysPara->status.addSpace?i:0)) + j/8] |= 1 << (j%8); //画黑点
if((j+1) > sysPara->status.currPrintRow) {
sysPara->status.currPrintRow = j+1;
}
}
}
}/*判断alpha end*/
}
}
if(TempVarNum>MAX_VARI_NUM){
setRunStatus(tr("变量数大于8个,某些变量将不起作用!!!"));
strTitle= tr("变量数大于8个,某些变量将不起作用!!!");
strTitle.append("\r\n");
strTitle.append(tr("请减少信息中的变量(或计数器)数量."));
QMessageBox::warning(this, tr("警告"),strTitle,QMessageBox::Ok);
}
sysPara->status.variNum = 0;
sysPara->status.ExpiryVarNum = 0;
sysPara->print.ExpiryVar.startColPos = 0;
sysPara->print.ExpiryVar.endRowPos = 0;
sysPara->print.ExpiryVar.letterSpace =0;
sysPara->print.CurDateVar.startColPos = 0;
sysPara->print.CurDateVar.endRowPos = 0;
sysPara->print.CurDateVar.letterSpace = 0;
sysPara->status.CurrDateVariNum = 0;
sysPara->status.QRvariNum=0;//lch add
int myvariNum=0;
int expiryVarNum = 0;
QList<QGraphicsItem *> items = pPicScene->items();
foreach (QGraphicsItem *item, items) {
PicTextItem *picText = qgraphicsitem_cast<PicTextItem*>(item);
bool ok;
int textvariNum=0;
int textColdot=0;
textColdot = picText->boundingRect().width();
if(textColdot > (MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide))
textColdot = MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide;
int maxTextHeight = MAX_PRINT_ROW_NUM + 12;
QSize textSize(textColdot, maxTextHeight);
QImage textImage(textSize,QImage::Format_ARGB32);
textImage.fill(0x00ffffff);//填充白色
//image.fill(0x00f0f000);//填充白色
QPainter textPainter(&textImage);
//textImage.save("./textImage.jpg");
//QRectF validtextRectF(picText->pos().x(),picText->pos().y(),textColdot,maxTextHeight);
QRectF validtextRectF(picText->pos().x(),picText->pos().y(),textColdot,picText->document()->size().height());
pPicScene->render(&textPainter,QRectF(),validtextRectF);
//qDebug()<<"validtextRectF:"<<validtextRectF;
//textImage.save("./textImage.bmp");
int textFirstRow = 0;
//qDebug()<<"textFirstRow:"<<textFirstRow;
int textLastRow = textFirstRow + MAX_PRINT_ROW_NUM;
int textItemPosX;
int textItemPosY;
textItemPosX = picText->pos().x() - sceneRect.x();
textItemPosY = picText->pos().y() - sceneRect.y();
//接下来就是要把打印到数据data填充以及确认变量的个数,变量对应的开始列和结束行
for(int j = 0; j < textLastRow - textFirstRow; j++){ // Y
for(int i = 0; i < textColdot; i++){ //
QRgb rgb = textImage.pixel(i,j + textFirstRow);
if((rgb&0x80000000)){ //判断alpha
if((rgb & 0xf0f0ff) == 0xf0f000){ //处理变量, 查找左下角,因为同一行的左下角是对齐的 看起来这个颜色是黄色
bool textfoundvar = 0;
if(j>0){
QRgb r_rgb = textImage.pixel(i,j + textFirstRow+1);
if((r_rgb & 0xf0f0ff) != 0xf0f000 )
{
textfoundvar =1;
}
}
if(textfoundvar){
if(sysPara->status.variNum < MAX_VARI_NUM){
sysPara->status.vars[sysPara->status.variNum].startColPos = i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->status.vars[sysPara->status.variNum].endRowPos = j+textItemPosY;
//qDebug()<<"sysPara->status.variNum:"<<sysPara->status.variNum;
//qDebug()<<"startColPos:"<<sysPara->status.vars[sysPara->status.variNum].startColPos;
//qDebug()<<"endRowPos:"<<sysPara->status.vars[sysPara->status.variNum].endRowPos;
if(varLastRow<j+1)
varLastRow=j+1;
sysPara->status.variNum ++;
textvariNum++;
i+=5;//scene 每一行可能都包含变量
//qDebug()<<"VARr:"<<TempVarNum<<i<<j;
//gItem = pPicScene->itemAt(i,j+firstRow);
//picText_var[i]= (PicTextItem*) gItem;
//picText_var_hash.insert(picText_var[i],i);
}
else
{
textvariNum++;
}
}
}
else if( ((rgb & 0xfffff0) == 0x00ff10) || ((rgb & 0xfffff0) == 0x00ff20) ||((rgb & 0xfffff0) == 0x00ff30) ){
// 0xff00ff01(DMT) 0xff00ff02(QR) 0xff00ff03(BAR)
//qDebug()<<"FLAG:"<<i<<j+1<<QString().sprintf("%08X", rgb);
if(sysPara->status.QRvariNum>=4)continue;
if((rgb & 0x00ffff0) == 0x00ff10) { //MDT
sysPara->print.QRvars[sysPara->status.QRvariNum].type=MDT;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1+textItemPosY;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
else if((rgb & 0x00ffff0) == 0x00ff20) { //QR
sysPara->print.QRvars[sysPara->status.QRvariNum].type=QR;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1+textItemPosY;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
else if((rgb & 0x00fffff0) == 0x00ff30) { //BAR
sysPara->print.QRvars[sysPara->status.QRvariNum].type=BAR;
sysPara->print.QRvars[sysPara->status.QRvariNum].countEn=1;
sysPara->print.QRvars[sysPara->status.QRvariNum].Counter=sysPara->status.productCnt;
sysPara->print.QRvars[sysPara->status.QRvariNum].startColPos=i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->print.QRvars[sysPara->status.QRvariNum].endRowPos=j+1+textItemPosY;
if(varLastRow<j+1) varLastRow=j+1;
sysPara->status.QRvariNum++;
}
if(sysPara->status.QRvariNum>=4)sysPara->status.QRvariNum=4;
}
//else if((rgb & 0xfffff0)==0xff00f0)
else if((rgb & 0x0000ffff)==EXPIRY_VARI_RECONISE)
{ // 有效期变量 : 处理变量, 查找左下角,因为同一行的左下角是对齐的
//qDebug()<<"found EXPIRY_VARI_RECONISE";
bool foundExVar=0;
if(j>0){
QRgb r_rgb = textImage.pixel(i,j + firstRow+1);
if(((r_rgb & 0x0000ffff) != EXPIRY_VARI_RECONISE )){foundExVar =1;}
}
if(foundExVar)
{
//if(sysPara->status.ExpiryVarNum <2)
{
//if(sysPara->print.ExpiryVar.endRowPos==0)
if(sysPara->status.ExpiryVarNum == 0)
{
sysPara->status.ExpiryVarNum ++;
}
sysPara->print.ExpiryVar.startColPos = i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->print.ExpiryVar.endRowPos = j+textItemPosY;
if(varLastRow<j+1) varLastRow=j+1;
i+=10;
//qDebug()<<"ExpiryVar ixj:"<<i<<"x"<<j + firstRow;
//qDebug()<<"qqqq textItemPosY:"<<textItemPosY;
//qDebug()<<"qqqq sysPara->print.ExpiryVar.endRowPos:"<<sysPara->print.ExpiryVar.endRowPos;
}
//else TempVarNum++;
//dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] |= 1 << (j%8); //画黑点
}
}
else if((rgb & 0xfffff0)==0xff0cf0)
{ // 有效期变量 : 处理变量, 查找左下角,因为同一行的左下角是对齐的
bool foundExVar=0;
if(j>0){
QRgb r_rgb = textImage.pixel(i,j + firstRow+1);
if((r_rgb & 0xfffff0) != 0xff0cf0 ){foundExVar =1;}
}
if(foundExVar)
{
//qDebug()<<"found CurDateVar";
//if(sysPara->status.ExpiryVarNum <2)
{
//if(sysPara->print.CurDateVar.endRowPos==0)
if(sysPara->status.CurrDateVariNum == 0)
{
sysPara->status.CurrDateVariNum ++;
//setRunStatus(QString("CurrDateVariNum(%1)").arg(sysPara->status.CurrDateVariNum));
}
sysPara->print.CurDateVar.startColPos = i+(sysPara->status.addSpace?i:0)+textItemPosX;
sysPara->print.CurDateVar.endRowPos = j + textItemPosY;
//qDebug()<<"CurDateVar ixj:"<<i<<"x"<<j + firstRow;
//qDebug()<<"sysPara->print.CurDateVar.endRowPos:"<<sysPara->print.CurDateVar.endRowPos;
if(varLastRow<j+1) varLastRow=j+1;
i+=10;
//j++;
}
//else TempVarNum++;
//dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] |= 1 << (j%8); //画黑点
}
}
if(j > sysPara->status.currPrintRow) {
sysPara->status.currPrintRow = j+textItemPosY;
}
}/*判断alpha end*/
}
}
//qDebug()<<"ExpiryVarNum:"<<sysPara->status.ExpiryVarNum;
//===================一般变量=====================
//myvariNum = 0;
QString textVariPattern = "<img src=\":/(\\d*)/(\\d*)/../image/digitalWidth(\\d*).bmp\" width=\"(\\d*)\" height=\"(\\d*)\" />";
QRegExp textrx(textVariPattern);
QString textHtml = picText->toHtml();
int from = 0;
//int myvariNum=0;
while(from < textHtml.size() && from != -1){
from = textHtml.indexOf(textrx,from);
if(from != -1){//找到匹配的
//qDebug()<<"found variable";
from ++;
//if(myvariNum < textvariNum)
if(myvariNum < sysPara->status.variNum)
{
sysPara->status.vars[myvariNum].digitalNum = textrx.cap(3).toInt(&ok);//第二个匹配,数字到个数
sysPara->status.vars[myvariNum].bold = (sysPara->status.vars[myvariNum].digitalNum%100) == 75;
if(sysPara->status.vars[myvariNum].bold)
sysPara->status.vars[myvariNum].digitalNum = sysPara->status.vars[myvariNum].digitalNum/100;
sysPara->status.vars[myvariNum].type = textrx.cap(2).toInt(&ok);//第一个匹配
sysPara->status.vars[myvariNum].width = textrx.cap(4).toInt(&ok)*(sysPara->status.addSpace?2:1);
sysPara->status.vars[myvariNum].height = textrx.cap(5).toInt(&ok);
//qDebug()<<"myvariNum endRowPos:"<<sysPara->status.vars[myvariNum].endRowPos;
//qDebug()<<"myvariNum height:"<<sysPara->status.vars[myvariNum].height;
sysPara->status.vars[myvariNum].startRowPos = sysPara->status.vars[myvariNum].endRowPos - sysPara->status.vars[myvariNum].height+1;
//sysPara->status.vars[myvariNum].startRowPos = sysPara->status.vars[myvariNum].endRowPos - sysPara->status.vars[myvariNum].height;
//qDebug()<<"start row:"<<sysPara->status.vars[myvariNum].startRowPos;
if(sysPara->status.vars[myvariNum].startRowPos<0)
sysPara->status.vars[myvariNum].startRowPos=0;
int item_x_start_pos = sysPara->status.vars[myvariNum].startColPos;
int item_x_end_pos = item_x_start_pos + sysPara->status.vars[myvariNum].width ;
if(item_x_end_pos > (MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide))
item_x_end_pos = MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide;
int item_y_start_pos = sysPara->status.vars[myvariNum].startRowPos;
int item_y_end_pos = sysPara->status.vars[myvariNum].endRowPos+1 ;
if(item_y_start_pos < 0)
item_y_start_pos = 0;
for(int i = item_x_start_pos; i < item_x_end_pos; i++){
for(int j = item_y_start_pos; j < item_y_end_pos; j++){
dat[MAX_PRINT_ROW_BYTE_NUM*(i+(sysPara->status.addSpace?0:0)) + j/8] &= ~(1 << (j%8)); //将画点取消掉
dat[MAX_PRINT_ROW_BYTE_NUM*(i+(sysPara->status.addSpace?0:0)) + j/8] &= ~(1 << (j%8));
}
}
sysPara->status.vars[myvariNum].height = textrx.cap(5).toInt(&ok)-1;
if(sysPara->status.vars[myvariNum].height>16 ){
if(sysPara->status.vars[myvariNum].height==24)
;
else {
if(sysPara->status.vars[myvariNum].startRowPos)
{
sysPara->status.vars[myvariNum].endRowPos--;
sysPara->status.vars[myvariNum].startRowPos--;
}
}
}
if(sysPara->status.vars[myvariNum].type == RANDOMNUM)
{
//qDebug()<<"RAND:"<<sysPara->status.vars[myvariNum].type<< sysPara->status.vars[myvariNum].digitalNum;
sysPara->status.RandomDigitNum = sysPara->status.vars[myvariNum].digitalNum;
}
int pixelSize = Public::derivePixelSizeFromHeight(sysPara->status.vars[myvariNum].height);
//qDebug()<<"MainWindows"<<sysPara->status.vars[myvariNum].height<<pixelSize;
sysPara->status.vars[myvariNum].letterSpace = 0;
if(sysPara->status.vars[myvariNum].digitalNum){ //算出letterspace
QFont font;
//font.setFamily(Public::getFontFamily(pixelSize));
font.setFamily(Public::getFontFamily(pixelSize,sysPara->status.vars[myvariNum].type )); // 20160812
//pixelSize==7? font.setFamily(ui->textEditOption->getLabelFontFamily()->text()):font.setFamily(Public::getFontFamily(pixelSize, 0));
font.setPixelSize(pixelSize);
font.setWeight(sysPara->status.vars[myvariNum].bold?QFont::Bold:QFont::Normal);
//font.setLetterSpacing(QFont::AbsoluteSpacing,sysPara->para.textEditCharSpace);
QFontMetrics fontMetrics(font);
int charWidth = (fontMetrics.width("0123456789"))/10 ;
// sysPara->status.vars[myvariNum].letterSpace = sysPara->para.textEditCharSpace;
sysPara->status.vars[myvariNum].letterSpace = picText->letterSpace();
//sysPara->status.vars[myvariNum].letterSpace =
//sysPara->status.vars[myvariNum].width/sysPara->status.vars[myvariNum].digitalNum/(sysPara->status.addSpace?2:1) - charWidth;
}
myvariNum++;
}
}
}
//==========================一般变量结束=======================
}
/*--------------------------------------------------------------------------*/
generateCharRamData();
if(sysPara->status.currPrintRow>MAX_PRINT_ROW_NUM-1)sysPara->status.currPrintRow=MAX_PRINT_ROW_NUM-1;
bool found=0;
lastRow = sysPara->status.currPrintRow;
//qDebug()<<"lastRow:"<<lastRow;
for(int j = sysPara->status.currPrintRow; j >2 ; j--){ //计算首行位置
for(int i = 0; i < coldot; i++){
if(dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] & (1 << (j%8))){
lastRow = j+1;
found=1;//qDebug()<<"fOUND:"<<i<<j<<dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8]<<sysPara->status.currPrintRow;
break;
}
}
if(found)
break;
}
if(lastRow>MAX_PRINT_ROW_NUM-1)lastRow = MAX_PRINT_ROW_NUM-1;
if(lastRow<varLastRow)lastRow= varLastRow-1;//在场景模式下,变量的最低一行并不一定是打印的最后一行
if(lastRow<1) lastRow =1;
sysPara->status.currPrintRow =lastRow;
qDebug() << "Item propertices: ";
qDebug() << picText->pos();
qDebug() << picText->boundingRect();
QXmlStreamAttributes attrs;
picText->saveAttrs(attrs);
for(auto attr : attrs) {
qDebug() << attr.name() << ": " << attr.value();
} }
if(sysPara->status.QRvariNum) { const QRectF itemSceneRect = item->sceneBoundingRect();
// onUpdateDispQRCode(1); const QRectF clippedSceneRect = itemSceneRect.intersected(contentRect);
if(clippedSceneRect.isEmpty())
continue;
const QRect itemRect = clippedSceneRect.translated(-contentRect.topLeft()).toAlignedRect();
const QRectF sourceRect = clippedSceneRect;
if(picText && picText->sourceType() == SourceType::COUNTER) {
PicCounterItem* counterItem = qgraphicsitem_cast<PicCounterItem*>(picText);
if(!counterItem)
continue;
if(sysPara->status.variNum >= 8)
continue;
int varI = sysPara->status.variNum;
auto& varPara = sysPara->status.vars[varI];
varPara.type = int(counterItem->counterType());
varPara.digitalNum = counterItem->digitalNum();
varPara.width = itemRect.width();
varPara.height = itemRect.height();
varPara.startColPos = itemRect.left();
varPara.endRowPos = itemRect.bottom() + 1;
varPara.startRowPos = itemRect.top();
varPara.currVal = 0;
varPara.bold = 0;
varPara.letterSpace = counterItem->letterSpace();
++sysPara->status.variNum;
// // 将变量序号、类型、数字个数、大小位置打印到日志
// LogInfo::setRunStatusText("Variable " + QString::number(varI) + ": type=" + QString::number(varPara.type) +
// "\n digitalNum=" + QString::number(varPara.digitalNum) +
// "\n width=" + QString::number(varPara.width) +
// "\n height=" + QString::number(varPara.height) +
// "\n startColPos=" + QString::number(varPara.startColPos) +
// "\n endRowPos=" + QString::number(varPara.endRowPos) +
// "\n startRowPos=" + QString::number(varPara.startRowPos) +
// "\n letterSpace=" + QString::number(varPara.letterSpace));
} }
int wmax = sysPara->status.currPrintRow;
sysPara->status.currAlterPrintRow = sysPara->status.currPrintRow/2;
if(sysPara->para.alterPrint.enable<1) sysPara->para.AlterMode=0;
else { else {
if(sysPara->para.AlterMode==0)sysPara->para.AlterMode=1; pPicScene->render(&painter, itemRect, sourceRect);
wmax = sysPara->status.currAlterPrintRow;
} }
/*-------------------------------切换到显示窗口-----------------------------------*/
qDebug() << "currPrintCol: " << sysPara->status.currPrintCol;
LogInfo::setRunStatusText("currPrintCol: " + QString::number(sysPara->status.currPrintCol));
LogInfo::setRunStatusText("currPrintRow: " + QString::number(sysPara->status.currPrintRow));
LogInfo::setRunStatusText(QString("Items bounding rect: {%1, %2}").arg(sceneRect.width()).arg(sceneRect.height()));
// sysPara->status.currPrintRow = sceneRect.height();
sysPara->status.currPrintCol = sceneRect.width();
auto rows = sysPara->para.AlterMode?sysPara->status.currAlterPrintRow : sysPara->status.currPrintRow;
rows = std::max(rows, (m_PrintDisplay->parentWidget()->height() / m_PrintDisplay->currScaleRatio()));
auto cols = sysPara->status.currPrintCol;
cols = std::max(cols, (m_PrintDisplay->parentWidget()->width() / m_PrintDisplay->currScaleRatio()));
m_PrintDisplay->setDisplaySize(cols, rows);
m_PrintDisplay->update();
} }
previewFlag=0;
sysPara->status.currPrintRow = sceneRect.height();
sysPara->status.currPrintCol = sceneRect.width();
imageToPrintData(image, 0, 0);
// /*--------------------------------------------------------------------------*/
generateCharRamData();
if(sysPara->status.currPrintRow>MAX_PRINT_ROW_NUM-1)sysPara->status.currPrintRow=MAX_PRINT_ROW_NUM-1;
sysPara->status.currPrintRow = qMin(sysPara->status.currPrintRow, MAX_PRINT_ROW_NUM-1);
// 计算末行位置
bool found = false;
int lastRow = sysPara->status.currPrintRow;
for(int j = sysPara->status.currPrintRow; j > 2 ; j--){
for(int i = 0; i < coldot; i++){
if(dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8] & (1 << (j%8))){
lastRow = j+1;
found = true;//qDebug()<<"fOUND:"<<i<<j<<dat[MAX_PRINT_ROW_BYTE_NUM*i + j/8]<<sysPara->status.currPrintRow;
break;
}
}
if(found)
break;
}
sysPara->status.currPrintRow = qBound(1, lastRow, MAX_PRINT_ROW_NUM - 1);
int wmax = sysPara->status.currPrintRow;
sysPara->status.currAlterPrintRow = sysPara->status.currPrintRow/2;
if(sysPara->para.alterPrint.enable<1) sysPara->para.AlterMode=0;
else {
if(sysPara->para.AlterMode==0)sysPara->para.AlterMode=1;
wmax = sysPara->status.currAlterPrintRow;
}
/*-------------------------------切换到显示窗口-----------------------------------*/
qDebug() << "currPrintCol: " << sysPara->status.currPrintCol;
LogInfo::setRunStatusText("currPrintCol: " + QString::number(sysPara->status.currPrintCol));
LogInfo::setRunStatusText("currPrintRow: " + QString::number(sysPara->status.currPrintRow));
LogInfo::setRunStatusText(QString("Items bounding rect: {%1, %2}").arg(sceneRect.width()).arg(sceneRect.height()));
// sysPara->status.currPrintRow = sceneRect.height();
sysPara->status.currPrintCol = sceneRect.width();
auto rows = sysPara->para.AlterMode?sysPara->status.currAlterPrintRow : sysPara->status.currPrintRow;
rows = std::max(rows, (m_PrintDisplay->parentWidget()->height() / m_PrintDisplay->currScaleRatio()));
auto cols = sysPara->status.currPrintCol;
cols = std::max(cols, (m_PrintDisplay->parentWidget()->width() / m_PrintDisplay->currScaleRatio()));
m_PrintDisplay->setDisplaySize(cols, rows);
m_PrintDisplay->update();
} }
void MainWidget::handleEmptySize() void MainWidget::handleEmptySize()
@@ -2387,7 +2061,6 @@ void MainWidget::handleEmptySize()
// pPicScene->render(&emptyPainter, QRectF(), QRectF(0, 0, emptySize.width(), emptySize.height())); // pPicScene->render(&emptyPainter, QRectF(), QRectF(0, 0, emptySize.width(), emptySize.height()));
// 初始化打印参数,避免空场景导致的参数异常 // 初始化打印参数,避免空场景导致的参数异常
previewFlag = 1;
sysPara->status.currPrintRow = 0; sysPara->status.currPrintRow = 0;
sysPara->status.currPrintCol = 0; // emptySize.width(); sysPara->status.currPrintCol = 0; // emptySize.width();
sysPara->status.variNum = 0; sysPara->status.variNum = 0;
@@ -2405,7 +2078,6 @@ void MainWidget::handleEmptySize()
rows = std::max(rows, (m_PrintDisplay->parentWidget()->height() / m_PrintDisplay->currScaleRatio())); rows = std::max(rows, (m_PrintDisplay->parentWidget()->height() / m_PrintDisplay->currScaleRatio()));
m_PrintDisplay->setDisplaySize(m_PrintDisplay->parentWidget()->width() / m_PrintDisplay->currScaleRatio(), rows); m_PrintDisplay->setDisplaySize(m_PrintDisplay->parentWidget()->width() / m_PrintDisplay->currScaleRatio(), rows);
m_PrintDisplay->update(); m_PrintDisplay->update();
previewFlag = 0;
return; return;
} }
@@ -2873,6 +2545,7 @@ void MainWidget::UpdateUIVersion(){
QString VernonBach; QString VernonBach;
VernonBach.sprintf("A%d.%d.%02d%s%s", UP_PRINTER_MAJOR_VER, UP_PRINTER_MINOR_VER,UP_PRINTER_RIVISION_VER,SUB_VERSION,SUB_RFID); VernonBach.sprintf("A%d.%d.%02d%s%s", UP_PRINTER_MAJOR_VER, UP_PRINTER_MINOR_VER,UP_PRINTER_RIVISION_VER,SUB_VERSION,SUB_RFID);
VernonBach = VernonBach + (QString) Public::DateToString(__DATE__)+"_"+ QString(__TIME__)+"_";
QString Mac = QString::number(sysPara->status.machineMac); QString Mac = QString::number(sysPara->status.machineMac);
LogInfo::setRunStatusText(QString("Mac:%1").arg(Mac)); LogInfo::setRunStatusText(QString("Mac:%1").arg(Mac));
+1 -3
View File
@@ -123,7 +123,7 @@ public:
QTimer *timerShowItem,*timerPowerOff; QTimer *timerShowItem,*timerPowerOff;
void SendPrintDataToFpga(unsigned char alterMode, int startCols = -1, int size = -1); void SendPrintDataToFpga(unsigned char alterEnable, bool isUpdate = false);
void updatePrintDisplayLabel(); void updatePrintDisplayLabel();
@@ -155,8 +155,6 @@ private:
QToolButton* m_LeftBtn; QToolButton* m_LeftBtn;
PrintTextDisplay* m_PrintDisplay; PrintTextDisplay* m_PrintDisplay;
bool previewFlag;
int r_ExpiryDay; int r_ExpiryDay;
QTimer *airPushTimer; QTimer *airPushTimer;
+328 -330
View File
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -444,6 +444,8 @@ void TestPrintWidget::openWorkFile(QString filePath){
} }
} }
pViewer->centerOn(0, 0);
if(m_printSetting) { if(m_printSetting) {
m_printSetting->setModel(m_printSettingModel); m_printSetting->setModel(m_printSettingModel);
} }
@@ -661,10 +663,12 @@ void TestPrintWidget::showEvent(QShowEvent *event)
pPicScene->update(); pPicScene->update();
auto sceneRect = pPicScene->sceneRect(); auto sceneRect = pPicScene->sceneRect();
// qreal sceneHeight = boundingRect.height() > (qreal)(sysPara->para.canvasHeight) ? SCENE_MAX_HEIGHT : (qreal)(sysPara->para.canvasHeight); // qreal sceneHeight = boundingRect.height() > (qreal)(sysPara->para.canvasHeight) ? SCENE_MAX_HEIGHT : (qreal)(sysPara->para.canvasHeight);
qreal sceneHeight = qMin(qreal(SCENE_MAX_HEIGHT), (qreal)(sysPara->para.canvasHeight)); int sceneHeight = qMin(int(SCENE_MAX_HEIGHT), (int)(sysPara->para.canvasHeight));
sceneRect.setHeight(sceneHeight); sceneRect.setHeight((qreal)(sceneHeight));
pPicScene->setSceneRect(sceneRect); pPicScene->setSceneRect(sceneRect);
// TODO:: 添加代码,只在sceneHeight高度为32时,才显示 字体大小选择框中的 32 dot选项
// 以高度为基准 最大化显示场景到 视口 // 以高度为基准 最大化显示场景到 视口
auto viewportHeight = pViewer->viewport()->height(); auto viewportHeight = pViewer->viewport()->height();
QTransform transform = pViewer->transform(); QTransform transform = pViewer->transform();
+328 -330
View File
File diff suppressed because it is too large Load Diff
+328 -330
View File
File diff suppressed because it is too large Load Diff
+328 -330
View File
File diff suppressed because it is too large Load Diff