#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include "base/HGTime.h" #include "base/HGUtility.h" #include "imgproc/HGImgProc.h" #include "imgproc/HGOCR.h" #include "HGUIGlobal.h" #include "dialog_scaninfo.h" #include "form_saveparam.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_dlgAdd(nullptr) , m_dlgScanInfo(nullptr) , m_devHandle(nullptr) , m_scanning(false) , m_dpi(200) , m_scanFileName("") , m_scanImgFmtWriter(nullptr) , m_ocrMsgPump(nullptr) , m_ocrThread(nullptr) { ui->setupUi(this); m_trayIcon = new QSystemTrayIcon(this); m_trayIcon->setIcon(QIcon(":images/image_rsc/png/logo.png")); m_trayIcon->show(); m_trayIcon->setToolTip(tr("Scan Tool")); qRegisterMetaType("QSystemTrayIcon::ActivationReason"); connect(m_trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::on_trayActivated); m_showAction = new QAction(tr("Show"), this); connect(m_showAction, &QAction::triggered, this, &MainWindow::on_showMainWindowDlg); m_quitAction = new QAction(tr("Exit"), this); connect(m_quitAction, &QAction::triggered, this, &QCoreApplication::quit); //应用程序的退出 //创建菜单,添加菜单项 m_trayIconMenu = new QMenu(this); m_trayIconMenu->addAction(m_showAction); m_trayIconMenu->addSeparator(); //分割线 m_trayIconMenu->addAction(m_quitAction); //给系统托盘添加右键菜单 m_trayIcon->setContextMenu(m_trayIconMenu); ui->tableWidget->setColumnCount(4); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tableWidget->setStyleSheet("selection-background-color:rgb(0, 120, 215)"); ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->tableWidget->horizontalHeader()->setFixedHeight(40); ui->tableWidget->horizontalHeader()->setStretchLastSection(true); ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Device Type")); ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Button Type")); ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Device Config")); ui->tableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("Save Param")); ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); ui->tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); ui->tableWidget->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); LoadCfg(); ui->tableWidget->setRowCount((int)m_vScanParams.size()); for (int index = 0; index < (int)m_vScanParams.size(); ++index) { ui->tableWidget->setRowHeight(index, 30); ui->tableWidget->setItem(index, 0, new QTableWidgetItem(QString(m_vScanParams[index].deviceType.c_str()))); ui->tableWidget->item(index, 0)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 0)->setFlags(ui->tableWidget->item(index, 0)->flags() & ~Qt::ItemIsEditable); const char *btnTypeStr[] = {"Manual", "Button 1", "Button 2", "Button 3"}; ui->tableWidget->setItem(index, 1, new QTableWidgetItem(btnTypeStr[m_vScanParams[index].buttonId])); ui->tableWidget->item(index, 1)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 1)->setFlags(ui->tableWidget->item(index, 1)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 2, new QTableWidgetItem(GetDesc(m_vScanParams[index].deviceConfigs))); ui->tableWidget->item(index, 2)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 2)->setFlags(ui->tableWidget->item(index, 2)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 3, new QTableWidgetItem(GetDesc(m_vScanParams[index].saveParam))); ui->tableWidget->item(index, 3)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 3)->setFlags(ui->tableWidget->item(index, 3)->flags() & ~Qt::ItemIsEditable); } ui->tableWidget->selectRow(0); m_dlgScanInfo = new Dialog_ScanInfo(this); connect(this, SIGNAL(deviceArrive(QString)), this, SLOT(on_deviceArrive(QString))); connect(this, SIGNAL(deviceRemove(QString)), this, SLOT(on_deviceRemove(QString))); connect(this, SIGNAL(keyPress(unsigned int)), this, SLOT(on_keyPress(unsigned int))); connect(this, SIGNAL(scanWorking()), this, SLOT(on_scanWorking())); connect(this, SIGNAL(scanInfo(QString, bool)), this, SLOT(on_scanInfo(QString, bool))); connect(this, SIGNAL(scanImage(unsigned int)), this, SLOT(on_scanImage(unsigned int))); connect(this, SIGNAL(scanFinish()), this, SLOT(on_scanFinish())); SANE_Int version_code = 0; sane_init_ex(&version_code, sane_ex_callback, this); } MainWindow::~MainWindow() { assert(nullptr == m_dlgAdd); if (NULL != m_devHandle) { StopScan(); sane_close(m_devHandle); m_devHandle = NULL; m_devName.clear(); } sane_exit(); delete m_dlgScanInfo; delete ui; } bool MainWindow::FindScanParam(const std::string &deviceType, unsigned int buttonId, int ignoreIndex) { for (int i = 0; i < (int)m_vScanParams.size(); ++i) { if (deviceType == m_vScanParams[i].deviceType && buttonId == m_vScanParams[i].buttonId) { if (-1 == ignoreIndex) // 表示均不忽略 { return true; } else if (i != ignoreIndex) { return true; } } } return false; } void MainWindow::StopScan() { if (m_scanning) { assert(NULL != m_devHandle); sane_cancel(m_devHandle); m_scanning = false; m_quitAction->setEnabled(true); ui->pushButtonAdd->setEnabled(true); ui->pushButtonModify->setEnabled(true); ui->pushButtonRemove->setEnabled(true); ui->comboBox->setEnabled(true); ui->pushButtonScan->setEnabled(true); m_dpi = 200; } } void MainWindow::LoadCfg() { // TODO 加载配置文件到m_vScanParams } void MainWindow::SaveCfg() { // TODO 保存m_vScanParams到配置文件 } QString MainWindow::GetDesc(const std::vector &deviceConfigs) { QString desc; return desc; } QString MainWindow::GetDesc(const SaveParam &saveParam) { QString desc; desc += "["; desc += tr("Save path:"); desc += saveParam.m_savePath; desc += "]"; desc += " "; desc += "["; desc += tr("Image format:"); desc += saveParam.m_fileNameExt; desc += "]"; return desc; } void MainWindow::StartScan(unsigned int buttonId) { if (nullptr == m_devHandle) { QMessageBox::information(this, tr("Tips"), tr("Device is offline")); return; } if (m_scanning || nullptr != m_dlgAdd) { return; } std::string deviceType = m_devName.toStdString(); char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x886D, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD == status) { deviceType = v; } ScanParam scanParam; bool find = false; for (int i = 0; i < (int)m_vScanParams.size(); ++i) { if (deviceType == m_vScanParams[i].deviceType && buttonId == m_vScanParams[i].buttonId) { scanParam = m_vScanParams[i]; find = true; } } if (!find) { // 手动扫描一定能找到配置,按键扫描不能提示 return; } // 1.恢复默认 SANE_Int num_dev_options = 0; sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(SANE_STD_OPT_NAME_RESTORE, name) && SANE_TYPE_BUTTON == desp->type) { sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, NULL, NULL); break; } } // 2.设置新的属性 for (int i = 0; i < (int)scanParam.deviceConfigs.size(); ++i) { for (int j = 1; j < num_dev_options; ++j) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, j); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(scanParam.deviceConfigs[i].name.c_str(), name)) { if (SANE_TYPE_STRING == desp->type) { sane_control_option(m_devHandle, j, SANE_ACTION_SET_VALUE, (void*)scanParam.deviceConfigs[i].stringValue.c_str(), NULL); } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = scanParam.deviceConfigs[i].intValue; sane_control_option(m_devHandle, j, SANE_ACTION_SET_VALUE, &value, NULL); } else if (SANE_TYPE_FIXED == desp->type) { SANE_Fixed value = SANE_FIX(scanParam.deviceConfigs[i].doubleValue); sane_control_option(m_devHandle, j, SANE_ACTION_SET_VALUE, &value, NULL); } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = (SANE_Bool)scanParam.deviceConfigs[i].boolValue; sane_control_option(m_devHandle, j, SANE_ACTION_SET_VALUE, &value, NULL); } break; } } } // 3. 获取DPI for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (nullptr == desp) continue; if (SANE_TYPE_INT == desp->type) { SANE_Int value = 0; sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, nullptr); if (0 == strcmp(desp->name, SANE_STD_OPT_NAME_RESOLUTION)) { m_dpi = (HGUInt)value; } } } // 4.保存配置 assert(m_scanFileName.isEmpty()); assert(nullptr == m_scanImgFmtWriter); m_aquireIntoSaveParam = scanParam.saveParam; m_aquireIntoInBlank = true; m_aquireIntoBatchStartIndex = 0; m_aquireIntoPageIndex = 0; m_aquireIntoMultiPageCount = 0; QDateTime dateTime = QDateTime::currentDateTime(); if (m_aquireIntoSaveParam.m_isUseSubfolderByTime) { m_aquireIntoSaveParam.m_savePath = getStdFileName(m_aquireIntoSaveParam.m_savePath + dateTime.toString("yyyy-MM-dd") + "/"); } if (m_aquireIntoSaveParam.m_isOcr) { HGBase_CreateMsgPump(&m_ocrMsgPump); HGBase_OpenThread(ocrThreadFunc, this, &m_ocrThread); } m_scanning = true; m_quitAction->setEnabled(false); ui->pushButtonAdd->setEnabled(false); ui->pushButtonModify->setEnabled(false); ui->pushButtonRemove->setEnabled(false); ui->comboBox->setEnabled(false); ui->pushButtonScan->setEnabled(false); status = sane_start(m_devHandle); if (SANE_STATUS_GOOD != status) { if (NULL != m_ocrMsgPump) { HGBase_ExitMsgPump(m_ocrMsgPump); HGBase_CloseThread(m_ocrThread); m_ocrThread = NULL; HGBase_DestroyMsgPump(m_ocrMsgPump); m_ocrMsgPump = NULL; } m_scanning = false; m_quitAction->setEnabled(true); ui->pushButtonAdd->setEnabled(true); ui->pushButtonModify->setEnabled(true); ui->pushButtonRemove->setEnabled(true); ui->comboBox->setEnabled(true); ui->pushButtonScan->setEnabled(true); m_dpi = 200; emit scanWorking(); emit scanInfo((const char*)sane_strstatus(status), true); emit scanFinish(); return; } } void MainWindow::AddManualScanParam() { assert(NULL != m_devHandle); std::string deviceType = m_devName.toStdString(); char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x886D, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD == status) { deviceType = v; } if (FindScanParam(deviceType, 0, -1)) { return; } ScanParam scanParam; scanParam.deviceType = deviceType; scanParam.buttonId = 0; scanParam.deviceConfigs.clear(); scanParam.saveParam = Form_SaveParam::GetDefSaveParam(); m_vScanParams.push_back(scanParam); SaveCfg(); ui->tableWidget->setRowCount((int)m_vScanParams.size()); int index = (int)m_vScanParams.size() - 1; ui->tableWidget->setRowHeight(index, 30); ui->tableWidget->setItem(index, 0, new QTableWidgetItem(QString(m_vScanParams[index].deviceType.c_str()))); ui->tableWidget->item(index, 0)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 0)->setFlags(ui->tableWidget->item(index, 0)->flags() & ~Qt::ItemIsEditable); const char *btnTypeStr[] = {"Manual", "Button 1", "Button 2", "Button 3"}; ui->tableWidget->setItem(index, 1, new QTableWidgetItem(btnTypeStr[m_vScanParams[index].buttonId])); ui->tableWidget->item(index, 1)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 1)->setFlags(ui->tableWidget->item(index, 1)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 2, new QTableWidgetItem(GetDesc(m_vScanParams[index].deviceConfigs))); ui->tableWidget->item(index, 2)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 2)->setFlags(ui->tableWidget->item(index, 2)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 3, new QTableWidgetItem(GetDesc(m_vScanParams[index].saveParam))); ui->tableWidget->item(index, 3)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 3)->setFlags(ui->tableWidget->item(index, 3)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->selectRow(index); } void MainWindow::SaveImage(HGImage image) { if (m_aquireIntoSaveParam.m_isSaveAsMultiPage) { if (nullptr == m_scanImgFmtWriter) { assert(m_scanFileName.isEmpty()); HGBase_CreateDir(getStdString(m_aquireIntoSaveParam.m_savePath).c_str()); QString scanFileName; while (1) { scanFileName = m_aquireIntoSaveParam.m_savePath + m_aquireIntoSaveParam.m_fileNamePrefix + QString("%1.%2") .arg(m_aquireIntoSaveParam.m_fileNameStartIndex, m_aquireIntoSaveParam.m_fileNameDigits, 10, QLatin1Char('0')) .arg(m_aquireIntoSaveParam.m_fileNameExt); QFileInfo fileInfo(scanFileName); if (fileInfo.isFile()) { ++m_aquireIntoSaveParam.m_fileNameStartIndex; } else { break; } } HGUInt fmtType = 0; if (nullptr != m_ocrMsgPump) { fmtType = HGIMGFMT_TYPE_TIFF; } HGImgFmt_OpenImageWriter(getStdString(getStdFileName(scanFileName)).c_str(), fmtType, &m_scanImgFmtWriter); if (nullptr != m_scanImgFmtWriter) { m_scanFileName = scanFileName; } } if (nullptr != m_scanImgFmtWriter) { HGImgFmtSaveInfo saveInfo; saveInfo.jpegQuality = (HGUInt)m_aquireIntoSaveParam.m_jpegQuality; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; saveInfo.tiffJpegQuality = (HGUInt)m_aquireIntoSaveParam.m_tiffQuality; HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); if (HGBASE_IMGTYPE_BINARY == imgInfo.type) { if (1 == m_aquireIntoSaveParam.m_tiffCompressionBW) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; else if (2 == m_aquireIntoSaveParam.m_tiffCompressionBW) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_CCITTFAX4; } else { if (1 == m_aquireIntoSaveParam.m_tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; else if (2 == m_aquireIntoSaveParam.m_tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_JPEG; } if (nullptr != m_ocrMsgPump) { saveInfo.jpegQuality = 100; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; saveInfo.tiffJpegQuality = 100; } if (HGBASE_ERR_OK == HGImgFmt_SaveImageToWriter(m_scanImgFmtWriter, image, &saveInfo)) { ++m_aquireIntoMultiPageCount; if (1 == m_aquireIntoSaveParam.m_multiPagesType && m_aquireIntoMultiPageCount == m_aquireIntoSaveParam.m_customMultiPages) { HGImgFmt_CloseImageWriter(m_scanImgFmtWriter); m_scanImgFmtWriter = nullptr; if (nullptr != m_ocrMsgPump) { QString *filePath = new QString(m_scanFileName); HGMsg msg; msg.id = 1; msg.data = filePath; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_ocrMsgPump, &msg)) { delete filePath; } } m_scanFileName.clear(); ++m_aquireIntoSaveParam.m_fileNameStartIndex; m_aquireIntoMultiPageCount = 0; } } } } else { assert(nullptr == m_scanImgFmtWriter); QString savePath = m_aquireIntoSaveParam.m_savePath; if (m_aquireIntoSaveParam.m_isUseSubfolderByBlankPages) { HGBool isBlank = HGFALSE; HGImgProc_ImageBlankCheck(image, nullptr, &isBlank); if (isBlank) { m_aquireIntoInBlank = true; } else { if (m_aquireIntoInBlank) { ++m_aquireIntoBatchStartIndex; } m_aquireIntoInBlank = false; } char batchDir[20]; sprintf(batchDir, "batch%d", m_aquireIntoBatchStartIndex); savePath = getStdFileName(savePath + batchDir + "/"); } if (m_aquireIntoSaveParam.m_isUseSubfolderByColor) { QString colorModeName; HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); if (HGBASE_IMGTYPE_BINARY == imgInfo.type) colorModeName = tr("binary"); else if (HGBASE_IMGTYPE_GRAY == imgInfo.type) colorModeName = tr("gray"); else colorModeName = tr("rgb"); savePath = getStdFileName(savePath + colorModeName + "/"); } HGBase_CreateDir(getStdString(savePath).c_str()); while (1) { m_scanFileName = savePath + m_aquireIntoSaveParam.m_fileNamePrefix + QString("%1.%2") .arg(m_aquireIntoSaveParam.m_fileNameStartIndex, m_aquireIntoSaveParam.m_fileNameDigits, 10, QLatin1Char('0')) .arg(m_aquireIntoSaveParam.m_fileNameExt); QFileInfo fileInfo(m_scanFileName); if (fileInfo.isFile()) { ++m_aquireIntoSaveParam.m_fileNameStartIndex; } else { break; } } HGImgFmtSaveInfo saveInfo; saveInfo.jpegQuality = (HGUInt)m_aquireIntoSaveParam.m_jpegQuality; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; saveInfo.tiffJpegQuality = (HGUInt)m_aquireIntoSaveParam.m_tiffQuality; HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); if (HGBASE_IMGTYPE_BINARY == imgInfo.type) { if (1 == m_aquireIntoSaveParam.m_tiffCompressionBW) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; else if (2 == m_aquireIntoSaveParam.m_tiffCompressionBW) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_CCITTFAX4; } else { if (1 == m_aquireIntoSaveParam.m_tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; else if (2 == m_aquireIntoSaveParam.m_tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_JPEG; } HGUInt fmtType = 0; if (nullptr != m_ocrMsgPump) { fmtType = HGIMGFMT_TYPE_TIFF; saveInfo.jpegQuality = 100; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; saveInfo.tiffJpegQuality = 100; } if (HGBASE_ERR_OK == HGImgFmt_SaveImage(image, fmtType, &saveInfo, getStdString(m_scanFileName).c_str())) { if (nullptr != m_ocrMsgPump) { QString *filePath = new QString(m_scanFileName); HGMsg msg; msg.id = 1; msg.data = filePath; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_ocrMsgPump, &msg)) { delete filePath; } } ++m_aquireIntoSaveParam.m_fileNameStartIndex; } m_scanFileName.clear(); } } int MainWindow::sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param) { (void)hdev; (void)len; MainWindow* p = (MainWindow*)param; switch (code) { case SANE_EVENT_DEVICE_ARRIVED: { SANE_Device* sane_dev = (SANE_Device*)data; emit p->deviceArrive(sane_dev->name); } break; case SANE_EVENT_DEVICE_LEFT: { SANE_Device* sane_dev = (SANE_Device*)data; emit p->deviceRemove(sane_dev->name); } break; case SANE_EVENT_WORKING: { emit p->scanWorking(); emit p->scanInfo((const char*)data, false); } break; case SANE_EVENT_SCAN_FINISHED: { emit p->scanInfo((const char*)data, (0 != *len)); emit p->scanFinish(); } break; case SANE_EVENT_STATUS: { //emit p->scanInfo((const char*)data, false); } break; case SANE_EVENT_ERROR: { //emit p->scanInfo((const char*)data, (0 != *len)); } break; case SANE_EVENT_DEV_KEY_PRESSED: { emit p->keyPress(*len); } break; case SANE_EVENT_IMAGE_OK: { ++p->m_aquireIntoPageIndex; emit p->scanImage(p->m_aquireIntoPageIndex); if ((1 == p->m_aquireIntoSaveParam.m_fileNameOddEventType && 1 != p->m_aquireIntoPageIndex % 2) || (2 == p->m_aquireIntoSaveParam.m_fileNameOddEventType && 0 != p->m_aquireIntoPageIndex % 2)) { // 跳过 } else { SANE_Image* sane_img = (SANE_Image*)data; HGUInt imgType = 0; if (sane_img->header.format == SANE_FRAME_GRAY) { if (1 == sane_img->header.depth) imgType = HGBASE_IMGTYPE_BINARY; else if (8 == sane_img->header.depth) imgType = HGBASE_IMGTYPE_GRAY; } else if (sane_img->header.format == SANE_FRAME_RGB) imgType = HGBASE_IMGTYPE_RGB; HGByte* data = sane_img->data; HGImageInfo imgInfo = { (HGUInt)sane_img->header.pixels_per_line, (HGUInt)sane_img->header.lines, imgType, (HGUInt)sane_img->header.bytes_per_line, HGBASE_IMGORIGIN_TOP }; HGImage img = NULL; HGBase_CreateImageFromData(data, &imgInfo, NULL, 0, HGBASE_IMGORIGIN_TOP, &img); if (NULL != img) { HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi); p->SaveImage(img); HGBase_DestroyImage(img); } } } break; } return 0; } void MainWindow::ocrThreadFunc(HGThread thread, HGPointer param) { MainWindow *p = (MainWindow*)param; HGBase_RunMsgPump(p->m_ocrMsgPump, ocrMsgPumpFunc, param); } void MainWindow::ocrMsgPumpFunc(HGMsgPump msgPump, const HGMsg *msg, HGPointer param) { MainWindow *p = (MainWindow*)param; if (msg->id == 1) { QString *filePath = (QString *)msg->data; HGOCRMgr ocrMgr = NULL; HGImgProc_CreateOCRMgr(HGIMGPROC_OCRALGO_DEFAULT, &ocrMgr); if (NULL != ocrMgr) { HGImgFmtReader reader = NULL; HGImgFmt_OpenImageReader(filePath->toLocal8Bit().toStdString().c_str(), 0, &reader); if (NULL != reader) { HGUInt count = 0; HGImgFmt_GetImagePageCount(reader, &count); for (HGUInt i = 0; i < count; ++i) { HGImage image = NULL; HGImgFmt_LoadImageFromReader(reader, i, NULL, 0, 0, &image); if (NULL != image) { HGImgProc_AddToImageOCRList(ocrMgr, image); HGBase_DestroyImage(image); } } HGImgFmt_CloseImageReader(reader); } //HGBase_DeleteFile(filePath->toLocal8Bit().toStdString().c_str()); HGImgProc_ImageListOCRToFile(ocrMgr, 0, filePath->toLocal8Bit().toStdString().c_str(), NULL, NULL); HGImgProc_DestroyOCRMgr(ocrMgr); } delete filePath; } } void MainWindow::closeEvent(QCloseEvent *e) { if (m_trayIcon->isVisible()) //托盘是显示的 { hide(); // 隐藏主窗口 e->ignore(); //忽略关闭事件,这样才不会关闭程序 } } void MainWindow::on_deviceArrive(QString devName) { ui->comboBox->addItem(devName); } void MainWindow::on_deviceRemove(QString devName) { if (devName == m_devName) { assert(nullptr != m_devHandle); StopScan(); if (nullptr != m_dlgAdd) m_dlgAdd->reject(); sane_close(m_devHandle); m_devHandle = NULL; m_devName.clear(); } for (int i = 0; i < ui->comboBox->count(); ++i) { if (ui->comboBox->itemText(i) == devName) { ui->comboBox->removeItem(i); break; } } } void MainWindow::on_keyPress(unsigned int buttonId) { assert(nullptr != m_devHandle); StartScan(buttonId); } void MainWindow::on_scanWorking() { m_dlgScanInfo->Start(); } void MainWindow::on_scanInfo(QString info, bool error) { m_dlgScanInfo->SetScanInfo(info, error); } void MainWindow::on_scanImage(unsigned int count) { m_dlgScanInfo->SetScanCount(count); } void MainWindow::on_scanFinish() { if (nullptr != m_scanImgFmtWriter) { HGImgFmt_CloseImageWriter(m_scanImgFmtWriter); m_scanImgFmtWriter = nullptr; if (nullptr != m_ocrMsgPump) { QString *filePath = new QString(m_scanFileName); HGMsg msg; msg.id = 1; msg.data = filePath; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_ocrMsgPump, &msg)) { delete filePath; } } m_scanFileName.clear(); ++m_aquireIntoSaveParam.m_fileNameStartIndex; m_aquireIntoMultiPageCount = 0; } if (NULL != m_ocrMsgPump) { HGBase_ExitMsgPump(m_ocrMsgPump); HGBase_CloseThread(m_ocrThread); m_ocrThread = NULL; HGBase_DestroyMsgPump(m_ocrMsgPump); m_ocrMsgPump = NULL; } StopScan(); m_dlgScanInfo->Finish(); } void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1) { if (NULL != m_devHandle) { StopScan(); if (nullptr != m_dlgAdd) m_dlgAdd->reject(); sane_close(m_devHandle); m_devHandle = NULL; m_devName.clear(); } SANE_Status status = sane_open(arg1.toStdString().c_str(), &m_devHandle); if (SANE_STATUS_GOOD == status) { m_devName = arg1; AddManualScanParam(); } } void MainWindow::on_pushButtonScan_clicked() { assert(!m_scanning && nullptr == m_dlgAdd); StartScan(0); } void MainWindow::on_trayActivated(QSystemTrayIcon::ActivationReason reason) { if (QSystemTrayIcon::Trigger == reason) { } else if (QSystemTrayIcon::DoubleClick == reason) { show(); raise(); } else if (QSystemTrayIcon::MiddleClick == reason) { } } void MainWindow::on_showMainWindowDlg() { show(); raise(); } void MainWindow::on_pushButtonAdd_clicked() { if (nullptr == m_devHandle) { QMessageBox::information(this, tr("Tips"), tr("Device is offline")); return; } std::string deviceType = m_devName.toStdString(); char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x886D, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD == status) { deviceType = v; } assert(nullptr == m_dlgAdd); m_dlgAdd = new Dialog_Add(m_devHandle, this, deviceType); if (m_dlgAdd->exec()) { ScanParam scanParam = m_dlgAdd->GetScanParam(); m_vScanParams.push_back(scanParam); SaveCfg(); ui->tableWidget->setRowCount((int)m_vScanParams.size()); int index = (int)m_vScanParams.size() - 1; ui->tableWidget->setRowHeight(index, 30); ui->tableWidget->setItem(index, 0, new QTableWidgetItem(QString(m_vScanParams[index].deviceType.c_str()))); ui->tableWidget->item(index, 0)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 0)->setFlags(ui->tableWidget->item(index, 0)->flags() & ~Qt::ItemIsEditable); const char *btnTypeStr[] = {"Manual", "Button 1", "Button 2", "Button 3"}; ui->tableWidget->setItem(index, 1, new QTableWidgetItem(btnTypeStr[m_vScanParams[index].buttonId])); ui->tableWidget->item(index, 1)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 1)->setFlags(ui->tableWidget->item(index, 1)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 2, new QTableWidgetItem(GetDesc(m_vScanParams[index].deviceConfigs))); ui->tableWidget->item(index, 2)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 2)->setFlags(ui->tableWidget->item(index, 2)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->setItem(index, 3, new QTableWidgetItem(GetDesc(m_vScanParams[index].saveParam))); ui->tableWidget->item(index, 3)->setTextAlignment(Qt::AlignCenter); ui->tableWidget->item(index, 3)->setFlags(ui->tableWidget->item(index, 3)->flags() & ~Qt::ItemIsEditable); ui->tableWidget->selectRow(index); } delete m_dlgAdd; m_dlgAdd = nullptr; } void MainWindow::on_pushButtonModify_clicked() { int index = ui->tableWidget->currentRow(); if (-1 == index) { QMessageBox::information(this, tr("Tips"), tr("No item selected")); return; } if (nullptr == m_devHandle) { QMessageBox::information(this, tr("Tips"), tr("Device is offline")); return; } std::string deviceType = m_devName.toStdString(); char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x886D, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD == status) { deviceType = v; } if (deviceType != m_vScanParams[index].deviceType) { QMessageBox::information(this, tr("Tips"), tr("Device type mismatch")); return; } assert(nullptr == m_dlgAdd); m_dlgAdd = new Dialog_Add(m_devHandle, this, m_vScanParams[index], index); if (m_dlgAdd->exec()) { ScanParam scanParam = m_dlgAdd->GetScanParam(); m_vScanParams[index] = scanParam; SaveCfg(); ui->tableWidget->item(index, 0)->setText(QString::fromStdString(m_vScanParams[index].deviceType)); const char *btnTypeStr[] = {"Manual", "Button 1", "Button 2", "Button 3"}; ui->tableWidget->item(index, 1)->setText(QString::fromStdString(btnTypeStr[m_vScanParams[index].buttonId])); ui->tableWidget->item(index, 2)->setText(GetDesc(m_vScanParams[index].deviceConfigs)); ui->tableWidget->item(index, 3)->setText(GetDesc(m_vScanParams[index].saveParam)); } delete m_dlgAdd; m_dlgAdd = nullptr; } void MainWindow::on_pushButtonRemove_clicked() { int index = ui->tableWidget->currentRow(); if (-1 == index) { QMessageBox::information(this, tr("Tips"), tr("No item selected")); return; } if (0 == m_vScanParams[index].buttonId) { QMessageBox::information(this, tr("Tips"), tr("Manual configuration items cannot be deleted")); return; } QMessageBox msg(QMessageBox::Question, tr("Question"), tr("Are you sure you want to remove the item?"), QMessageBox::Yes | QMessageBox::No, this); msg.exec(); if (msg.clickedButton() != msg.button(QMessageBox::Yes)) { return; } m_vScanParams.erase(m_vScanParams.begin() + index); SaveCfg(); ui->tableWidget->removeRow(index); }