diff --git a/README.md b/README.md index 5d791d8..f99b43e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # RightDrag(框选识别) * 本软件是为了练习Qt开发而在课余时间开发的一个小软件 -* 软件功能为使用鼠标框选屏幕上的内容,并进行OCR识别或进行翻译,可以选择将截图/识别内容/翻译结果自动复制到剪贴板 -### 使用方法见帮助文档 -* [help.md](help.md) +## 软件功能 +* 使用鼠标框选屏幕上的内容进行**截图**,并进行**OCR识别**或进行**翻译** +* 可以选择将截图/识别内容/翻译结果**自动复制到剪贴板** +* 支持组合键Ctrl Shift Alt +* 悬浮窗模式,可将窗口一直悬浮在桌面顶层 +## 使用方法 +* 见帮助文档 [help.md](help.md) diff --git a/RightDrag.pro b/RightDrag.pro index a196882..f0c3898 100644 --- a/RightDrag.pro +++ b/RightDrag.pro @@ -9,7 +9,8 @@ CONFIG += c++11 # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += QT_DEPRECATED_WARNINGS \ + APP_VERSION=\\\"1.0\\\" # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. diff --git a/aboutdialog.cpp b/aboutdialog.cpp index 62fab00..128b846 100644 --- a/aboutdialog.cpp +++ b/aboutdialog.cpp @@ -7,6 +7,7 @@ AboutDialog::AboutDialog(QWidget *parent) : { ui->setupUi(this); setWindowTitle("关于"); + setAttribute(Qt::WA_DeleteOnClose,true);//设置关闭窗口时销毁 } AboutDialog::~AboutDialog() @@ -16,5 +17,5 @@ AboutDialog::~AboutDialog() void AboutDialog::on_btnReturn_clicked() { - hide(); + close(); } diff --git a/aboutdialog.h b/aboutdialog.h index 8a4f4e9..db710c6 100644 --- a/aboutdialog.h +++ b/aboutdialog.h @@ -1,3 +1,4 @@ +/*关于信息窗口*/ #ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H diff --git a/donatedialog.cpp b/donatedialog.cpp index 75fafbd..9f933d2 100644 --- a/donatedialog.cpp +++ b/donatedialog.cpp @@ -6,9 +6,10 @@ DonateDialog::DonateDialog(QWidget *parent) : ui(new Ui::DonateDialog) { ui->setupUi(this); - wechatPixmap=new QPixmap("wechat.png"); - alipayPixmap=new QPixmap("alipay.png"); + wechatPixmap=QPixmap("wechat.png"); + alipayPixmap=QPixmap("alipay.png"); setWindowTitle("捐赠"); + setAttribute(Qt::WA_DeleteOnClose,true); } DonateDialog::~DonateDialog() @@ -16,13 +17,20 @@ DonateDialog::~DonateDialog() delete ui; } +//显示图片 void DonateDialog::setImg() { - ui->labelWechat->setPixmap(wechatPixmap->scaled(ui->labelWechat->size(),Qt::KeepAspectRatio, Qt::SmoothTransformation)); - ui->labelAlipay->setPixmap(alipayPixmap->scaled(ui->labelAlipay->size(),Qt::KeepAspectRatio, Qt::SmoothTransformation)); + ui->labelWechat->setPixmap(wechatPixmap.scaled(ui->scroll_wechat->size(),Qt::KeepAspectRatio, Qt::SmoothTransformation)); + ui->labelAlipay->setPixmap(alipayPixmap.scaled(ui->scroll_aliplay->size(),Qt::KeepAspectRatio, Qt::SmoothTransformation)); } void DonateDialog::on_pushButton_clicked() { - hide(); + close(); +} + +//窗口大小改变事件,重绘图片 +void DonateDialog::resizeEvent(QResizeEvent *) +{ + setImg(); } diff --git a/donatedialog.h b/donatedialog.h index c88d3b7..a3a0f3f 100644 --- a/donatedialog.h +++ b/donatedialog.h @@ -1,3 +1,4 @@ +/*捐赠窗口*/ #ifndef DONATEDIALOG_H #define DONATEDIALOG_H @@ -14,14 +15,17 @@ class DonateDialog : public QDialog public: explicit DonateDialog(QWidget *parent = nullptr); ~DonateDialog(); - void setImg(); + void setImg();//根据控件大小显示图片 private slots: void on_pushButton_clicked(); private: Ui::DonateDialog *ui; - QPixmap *wechatPixmap,*alipayPixmap; + QPixmap wechatPixmap,alipayPixmap;//存两个方式的捐赠二维码图片 + +protected: + void resizeEvent(QResizeEvent *); }; #endif // DONATEDIALOG_H diff --git a/donatedialog.ui b/donatedialog.ui index 0e4ec5c..8378a5d 100644 --- a/donatedialog.ui +++ b/donatedialog.ui @@ -65,77 +65,130 @@ background-color: rgb(255, 255, 255); 10 - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 + + + true + + + background-color: rgb(255, 255, 255); + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 285 + 307 + - - - - - 0 - 0 - - - - QFrame::NoFrame - - - - - - Qt::AlignCenter - - - - + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + + + + Qt::AlignCenter + + + + + - - + + true - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 + + background-color: rgb(255, 255, 255); + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 284 + 307 + - - - - - - - Qt::AlignCenter - - - - + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::AlignCenter + + + + + diff --git a/grab/floatdialog.cpp b/grab/floatdialog.cpp index 6dfc75f..78cdb71 100644 --- a/grab/floatdialog.cpp +++ b/grab/floatdialog.cpp @@ -16,16 +16,17 @@ FloatDialog::~FloatDialog() delete ui; } +//更改选框大小和位置 void FloatDialog::changeShape(int x, int y, int w, int h) { move(x,y); setFixedSize(w,h); - update(); + update();//触发paintEvent } void FloatDialog::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.setPen(QPen(lineColor,lineWidth,lineSytle)); - painter.drawRect(this->rect()); + painter.setPen(QPen(lineColor,lineWidth,lineSytle));//设置笔触样式 + painter.drawRect(this->rect());//画选框占满整个窗口 } diff --git a/grab/floatdialog.h b/grab/floatdialog.h index 5c83852..7766232 100644 --- a/grab/floatdialog.h +++ b/grab/floatdialog.h @@ -1,3 +1,4 @@ +/*选框窗口*/ #ifndef FLOATDIALOG_H #define FLOATDIALOG_H @@ -16,9 +17,9 @@ class FloatDialog : public QDialog ~FloatDialog(); void changeShape(int x,int y,int w,int h); void paintEvent(QPaintEvent*); - QColor lineColor; - Qt::PenStyle lineSytle; - int lineWidth; + QColor lineColor;//选框线颜色 + Qt::PenStyle lineSytle;//选框线样式 + int lineWidth;//选框线粗细 private: Ui::FloatDialog *ui; diff --git a/grab/grabber.cpp b/grab/grabber.cpp index 82459ec..0d70672 100644 --- a/grab/grabber.cpp +++ b/grab/grabber.cpp @@ -4,9 +4,12 @@ #include "qguiapplication.h" #include "qscreen.h" -Grabber *pGrabberForSig; -HHOOK mouseHook=NULL; +Grabber *pGrabberForSig;//指向grabber对象,用来在静态函数中emit +HHOOK mouseHook=NULL;//鼠标钩子 +bool Grabber::mouseBlocking=false;//初始化静态变量 + +//鼠标钩子回调 LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) { Q_UNUSED(nCode); @@ -14,13 +17,17 @@ LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) switch(wParam) { case WM_MOUSEMOVE: - Grabber::sigMouseMoveEmit(); + Grabber::sigMouseMoveEmit();//发送对应的信号 break; case WM_RBUTTONDOWN: Grabber::sigMouseDownEmit(); + if(Grabber::mouseBlocking)//若当前处于拦截状态则返回true + return true; break; case WM_RBUTTONUP: Grabber::sigMouseUpEmit(); + if(Grabber::mouseBlocking) + return true; break; } return false; @@ -28,50 +35,51 @@ LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) Grabber::Grabber(QObject *parent) : QObject(parent) { - pGrabberForSig=this; - mouseHook=SetWindowsHookEx( WH_MOUSE_LL,mouseProc,GetModuleHandle(NULL),0); + pGrabberForSig=this;//全局指针指向自身 + mouseHook=SetWindowsHookEx( WH_MOUSE_LL,mouseProc,GetModuleHandle(NULL),0);//注册鼠标钩子 if(mouseHook==NULL) qDebug("hook null"); - floatDialog=new FloatDialog(); - connect(this,SIGNAL(sigMouseMove()),this,SLOT(slotMouseMove())); + floatDialog=new FloatDialog();//创建选框窗口 + connect(this,SIGNAL(sigMouseMove()),this,SLOT(slotMouseMove()));//进行函数和槽的连接 connect(this,SIGNAL(sigMouseDown()),this,SLOT(slotMouseDown())); connect(this,SIGNAL(sigMouseUp()),this,SLOT(slotMouseUp())); } Grabber::~Grabber() { - UnhookWindowsHookEx(mouseHook); + UnhookWindowsHookEx(mouseHook);//卸载钩子 + delete floatDialog;//销毁选框 + pGrabberForSig=NULL; } +//三个静态函数用于发出信号 void Grabber::sigMouseMoveEmit() { emit pGrabberForSig->sigMouseMove(); } - void Grabber::sigMouseDownEmit() { emit pGrabberForSig->sigMouseDown(); } - void Grabber::sigMouseUpEmit() { emit pGrabberForSig->sigMouseUp(); } +//三个函数用于设置选框样式 void Grabber::setRectColor(QColor &color) { floatDialog->lineColor=color; } - void Grabber::setRectStyle(Qt::PenStyle style) { floatDialog->lineSytle=style; } - void Grabber::setRectWidth(int width) { floatDialog->lineWidth=width; } +//进行截图,结果存入pixmap成员 void Grabber::screenshot() { QRect *rect=pointToRect(dragInfo.start,dragInfo.end); @@ -79,6 +87,7 @@ void Grabber::screenshot() delete rect; } +//两个点转换为矩形 QRect* Grabber::pointToRect(QPoint &p1, QPoint &p2) { int x1=p1.x(),y1=p1.y(); @@ -89,6 +98,7 @@ QRect* Grabber::pointToRect(QPoint &p1, QPoint &p2) return rect; } +//检查组合键是否正确按下 bool Grabber::combineKeyCorrect() { bool res=true; @@ -98,48 +108,60 @@ bool Grabber::combineKeyCorrect() return res; } +//鼠标移动槽函数 void Grabber::slotMouseMove() { - if(!dragInfo.isPressing) return; + if(!dragInfo.isPressing) return;//若未有效按下则直接退出 if(!combineKeyCorrect()) { - if(dragInfo.isDragging) + if(dragInfo.isDragging)//表示正在有效拖拽但组合键变为无效,取消一次拖拽 { - dragInfo.isDragging=false; - dragInfo.end=QCursor::pos(); - floatDialog->hide(); + dragInfo.isDragging=false;//取消拖拽标识 + dragInfo.end=QCursor::pos();//记录结束拖拽位置 + floatDialog->hide();//隐藏选框 } return; } - if(!dragInfo.isDragging) + if(!dragInfo.isDragging)//正在有效拖拽但标识为false,表示刚开始一次拖拽 { - dragInfo.isDragging=true; - dragInfo.start=QCursor::pos(); - floatDialog->changeShape(dragInfo.start.x(),dragInfo.start.y(),1,1); - floatDialog->show(); + dragInfo.isDragging=true;//标识置true + dragInfo.start=QCursor::pos();//记录开始拖拽位置 + floatDialog->changeShape(dragInfo.start.x(),dragInfo.start.y(),1,1);//移动选框窗口到鼠标位置 + floatDialog->show();//显示选框 } + //正在拖拽 QPoint nowPos=QCursor::pos(); QRect *rect=pointToRect(dragInfo.start,nowPos); - floatDialog->changeShape(rect->x(),rect->y(),rect->width(),rect->height()); + floatDialog->changeShape(rect->x(),rect->y(),rect->width(),rect->height());//更新选框形状和位置 delete rect; } +//鼠标按下槽函数 void Grabber::slotMouseDown() { - dragInfo.isPressing=true; - //qDebug("start:%d,%d",dragInfo.start.x(),dragInfo.start.y()); + if(combineKeyCorrect())//组合键正确则算作有效按下 + dragInfo.isPressing=true; + + if(combineKeyCorrect()&&blockMouseEvent)//判定是否拦截本次鼠标事件 + mouseBlocking=true; + else + mouseBlocking=false; } void Grabber::slotMouseUp() { - if(dragInfo.isDragging) + if(dragInfo.isDragging)//若正在有效拖拽,则拖拽正常结束 { - dragInfo.end=QCursor::pos(); - floatDialog->hide(); - screenshot(); - emit sigGrabFinished(pixmap); + dragInfo.end=QCursor::pos();//记录结束位置 + floatDialog->hide();//隐藏选框 + screenshot();//截图 + emit sigGrabFinished(pixmap);//发出消息,传递截图 } - dragInfo.isPressing=false; + dragInfo.isPressing=false;//按下和拖拽标识置false dragInfo.isDragging=false; - //qDebug("end:%d,%d",dragInfo.end.x(),dragInfo.end.y()); + + if(combineKeyCorrect()&&mouseBlocking)//判定是否拦截本次鼠标事件 + mouseBlocking=true; + else + mouseBlocking=false; } diff --git a/grab/grabber.h b/grab/grabber.h index 0c11ebe..6920a74 100644 --- a/grab/grabber.h +++ b/grab/grabber.h @@ -1,3 +1,4 @@ +/*屏幕抓取*/ #ifndef GRABBER_H #define GRABBER_H @@ -11,33 +12,36 @@ class Grabber : public QObject public: struct{ bool ctrl,shift,alt; - }combineKey; + }combineKey;//组合键使能 + bool blockMouseEvent;//是否拦截鼠标事件 + static bool mouseBlocking;//若为true则右键按下和抬起事件都会拦截,由于需要在钩子函数使用故为static explicit Grabber(QObject *parent = nullptr); ~Grabber(); - static void sigMouseMoveEmit(); + static void sigMouseMoveEmit();//三个静态函数用于在钩子中释放信号 static void sigMouseDownEmit(); static void sigMouseUpEmit(); - void setRectColor(QColor &color); + void setRectColor(QColor &color);//设置选框样式 void setRectStyle(Qt::PenStyle style); void setRectWidth(int width); private: - QPixmap pixmap; + QPixmap pixmap;//暂存截到的图片 struct{ - bool isPressing; - bool isDragging; - QPoint start,end; - }dragInfo; - FloatDialog *floatDialog; - void screenshot(); - QRect* pointToRect(QPoint &p1,QPoint &p2); - bool combineKeyCorrect(); + bool isPressing;//右键是否有效按下(组合键也应符合) + bool isDragging;//是否正在有效拖拽 + QPoint start,end;//开始和结束拖拽的坐标 + }dragInfo;//拖拽信息 + FloatDialog *floatDialog;//选框窗口 + + void screenshot();//进行截图 + QRect* pointToRect(QPoint &p1,QPoint &p2);//由两个点生成矩形 + bool combineKeyCorrect();//检查组合键是否正确 signals: void sigMouseMove(); void sigMouseDown(); void sigMouseUp(); - void sigGrabFinished(QPixmap &pixmap); + void sigGrabFinished(QPixmap &pixmap);//截图完成信号 private slots: void slotMouseMove(); diff --git a/help.md b/help.md index 00fd321..f70a694 100644 --- a/help.md +++ b/help.md @@ -14,6 +14,10 @@ * 非悬浮窗模式下,点击关闭窗口软件即会退出,若最小化窗口则自动隐藏到托盘中,点击托盘图标可以恢复 * 悬浮窗模式下,主窗口将会一直悬浮在桌面顶层,此时关闭窗口软件不会退出,点击托盘图标可以再次弹出 * 用户可以在设置中调整悬浮窗的透明度 +### 其他设置项 +* `自动复制结果`:若勾选则会将截图/OCR结果/翻译结果自动复制到剪贴板 +* `拦截鼠标事件`:若勾选,则在框选时阻拦鼠标事件传递到下方的应用中产生误触,只在组合键被正确按下时才会拦截 + > 注意:若不设置组合键并勾选拦截,鼠标右键将会失效 ## 问题处理 * 若发现**软件无法响应框选操作**,请尝试重启软件 diff --git a/mainwindow.cpp b/mainwindow.cpp index 3fb61a7..f34deaa 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -10,33 +10,38 @@ MainWindow::MainWindow(QWidget *parent) { ui->setupUi(this); + //new各个对象 settings=new SettingsDialog(); - about=new AboutDialog(); - donate=new DonateDialog(); - grabber=new Grabber(); baiduOCR=new BaiduOCR(); baiduTrans=new BaiduTrans(); - isFloating=false; + isFloating=false;//初始状态为非悬浮窗模式 - connect(settings,SIGNAL(sigSettingsAccepted()),this,SLOT(slotSettingsAccepted())); - connect(grabber,SIGNAL(sigGrabFinished(QPixmap&)),this,SLOT(slotGrabFinished(QPixmap&))); - connect(baiduOCR,SIGNAL(recvSuccess(const QString&)),this,SLOT(slotBaiduOCRRecv(const QString&))); - connect(baiduOCR,SIGNAL(error(BaiduOCR::Error,const QString&)),this,SLOT(slotBaiduOCRError(BaiduOCR::Error,const QString&))); - connect(baiduTrans,SIGNAL(recvSuccess(const QString&)),this,SLOT(slotBaiduTransRecv(const QString&))); - connect(baiduTrans,SIGNAL(error(BaiduTrans::Error,const QString&)),this,SLOT(slotBaiduTransError(BaiduTrans::Error,const QString&))); + connect(settings,SIGNAL(sigSettingsAccepted()),this,SLOT(slotSettingsAccepted()));//设置确认信号 + connect(grabber,SIGNAL(sigGrabFinished(QPixmap&)),this,SLOT(slotGrabFinished(QPixmap&)));//截图完成信号 + connect(baiduOCR,SIGNAL(recvSuccess(const QString&)),this,SLOT(slotBaiduOCRRecv(const QString&)));//OCR识别成功信号 + connect(baiduOCR,SIGNAL(error(BaiduOCR::Error,const QString&)),this,SLOT(slotBaiduOCRError(BaiduOCR::Error,const QString&)));//OCR错误信号 + connect(baiduTrans,SIGNAL(recvSuccess(const QString&)),this,SLOT(slotBaiduTransRecv(const QString&)));//翻译成功信号 + connect(baiduTrans,SIGNAL(error(BaiduTrans::Error,const QString&)),this,SLOT(slotBaiduTransError(BaiduTrans::Error,const QString&)));//翻译错误信号 - if(!settings->confExist()) + if(!settings->confExist())//若配置文件不存在则使用默认设置 writeDefaultSettings(); else - settings->loadSettings(); - applySettings(); + { + settings->loadSettings();//读取设置 + if(settings->values.version!=QString(APP_VERSION))//若存在的配置文件版本不符则使用默认设置 + { + writeDefaultSettings(); + settings->saveSettings(); + } + } + applySettings();//应用设置 - baiduOCR->sendAuth(); + baiduOCR->sendAuth();//发送OCR认证请求 switchMode(settings->values.sysMode); - initTray(); + initTray();//初始化托盘 } MainWindow::~MainWindow() @@ -48,14 +53,16 @@ MainWindow::~MainWindow() delete settings; } +//将默认设置写入settings中 void MainWindow::writeDefaultSettings() { + settings->values.version=APP_VERSION; settings->values.trans_srcLang="英语"; settings->values.trans_dstLang="中文"; settings->values.ocr_apiKey="8kEopqDXdK8VvDc3pI7AdPX8"; settings->values.ocr_secretKey="ecN4DOkqqPq6QRu7IqM4etmRLmo0SyFT"; settings->values.ocr_lang="中英混合"; - settings->values.cbKey_ctrl=false; + settings->values.cbKey_ctrl=true; settings->values.cbKey_shift=false; settings->values.cbKey_alt=false; settings->values.rectLineStyle=Qt::PenStyle::DotLine; @@ -64,12 +71,17 @@ void MainWindow::writeDefaultSettings() settings->values.autoCopy=true; settings->values.sysMode=SettingsDialog::OCR; settings->values.floatOpacity=0.8; + settings->values.blockMouse=true; } +//应用设置,将settings->values中的值应用到各个模块 void MainWindow::applySettings() { baiduOCR->setKeys(settings->values.ocr_apiKey,settings->values.ocr_secretKey); - baiduOCR->setLanguage(settings->values.ocr_lang); + if(settings->values.sysMode==SettingsDialog::Translate)//翻译模式OCR识别语言也要调整为翻译源语言 + setOCRLang(settings->values.trans_srcLang); + else + setOCRLang(settings->values.ocr_lang); baiduTrans->setSrcLang(settings->values.trans_srcLang); baiduTrans->setDstLang(settings->values.trans_dstLang); grabber->setRectColor(settings->values.rectLineColor); @@ -78,42 +90,35 @@ void MainWindow::applySettings() grabber->combineKey.ctrl=settings->values.cbKey_ctrl; grabber->combineKey.shift=settings->values.cbKey_shift; grabber->combineKey.alt=settings->values.cbKey_alt; + grabber->blockMouseEvent=settings->values.blockMouse; if(isFloating) setWindowOpacity(settings->values.floatOpacity); } +//切换系统模式 void MainWindow::switchMode(SettingsDialog::SysMode mode) { + //设置action勾选情况 ui->actionOCR->setChecked(mode==SettingsDialog::OCR); ui->actionTrans->setChecked(mode==SettingsDialog::Translate); ui->actionGrab->setChecked(mode==SettingsDialog::GrabOnly); - if(mode==SettingsDialog::Translate) - { - if(settings->values.trans_srcLang=="中文"|| - settings->values.trans_srcLang=="文言文"|| - settings->values.trans_srcLang=="繁体中文"|| - settings->values.trans_srcLang=="英语") - { - baiduOCR->setLanguage("中英混合"); - } - else - baiduOCR->setLanguage(settings->values.trans_srcLang); - } - else if(mode==SettingsDialog::OCR) - { - baiduOCR->setLanguage(settings->values.ocr_lang); - } + if(mode==SettingsDialog::Translate)//若切换到翻译模式,则OCR识别语言也要调整为翻译源语言 + setOCRLang(settings->values.trans_srcLang); + else if(mode==SettingsDialog::OCR)//若切换到OCR模式,则识别语言即为设置的识别语言 + setOCRLang(settings->values.ocr_lang); settings->values.sysMode=mode; settings->saveSettings(); } +//初始化托盘 void MainWindow::initTray() { trayIcon=new QSystemTrayIcon(this); trayIcon->setIcon(QIcon("icon.png")); trayIcon->setToolTip("框选识别"); - QMenu *trayMenu=new QMenu(this); + + QMenu *trayMenu=new QMenu(this);//添加托盘菜单 trayMenu->addAction(ui->actionGrab); trayMenu->addAction(ui->actionOCR); trayMenu->addAction(ui->actionTrans); @@ -122,11 +127,22 @@ void MainWindow::initTray() trayMenu->addSeparator(); trayMenu->addAction(ui->actionExit); trayIcon->setContextMenu(trayMenu); + connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(slotActivatedSysTrayIcon(QSystemTrayIcon::ActivationReason))); trayIcon->show(); } +//设置OCR识别语言 +void MainWindow::setOCRLang(const QString &lang) +{ + if(lang=="中文"||lang=="文言文"||lang=="繁体中文"||lang=="英语")//将翻译特有语言种类转为OCR支持的语言 + baiduOCR->setLanguage("中英混合"); + else + baiduOCR->setLanguage(lang); +} + +//最小化自动隐藏 void MainWindow::changeEvent(QEvent *event) { if(event->type()!=QEvent::WindowStateChange) return; @@ -136,6 +152,7 @@ void MainWindow::changeEvent(QEvent *event) } } +//非悬浮窗模式下窗口关闭则程序退出 void MainWindow::closeEvent(QCloseEvent *event) { Q_UNUSED(event); @@ -143,44 +160,52 @@ void MainWindow::closeEvent(QCloseEvent *event) QApplication::quit(); } +//窗口大小改变,若显示的是图片则重绘 +void MainWindow::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + if(tempRes.isPixmap) + ui->labelResult->setPixmap(tempRes.pixmap.scaled(ui->scrollArea->width()-10,ui->scrollArea->height()-10,Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} + +//三个action槽函数,切换系统模式 void MainWindow::on_actionOCR_triggered() { if(settings->values.sysMode!=SettingsDialog::OCR) switchMode(SettingsDialog::OCR); } - void MainWindow::on_actionGrab_triggered() { if(settings->values.sysMode!=SettingsDialog::GrabOnly) switchMode(SettingsDialog::GrabOnly); } - void MainWindow::on_actionTrans_triggered() { if(settings->values.sysMode!=SettingsDialog::Translate) switchMode(SettingsDialog::Translate); } +//显示设置界面 void MainWindow::on_actionSettings_triggered() { settings->display(); } +//截图完成,进行下一步操作 void MainWindow::slotGrabFinished(QPixmap &pixmap) { switch(settings->values.sysMode) { - case SettingsDialog::GrabOnly:{ - QPixmap fitPixmap=pixmap.scaled(ui->scrollArea->width()-10,ui->scrollArea->height()-10,Qt::KeepAspectRatio, Qt::SmoothTransformation); - ui->labelResult->setAlignment(Qt::AlignCenter); - ui->labelResult->setPixmap(fitPixmap); - tempRes.isPixmap=true; + case SettingsDialog::GrabOnly:{//截图模式 + ui->labelResult->setAlignment(Qt::AlignCenter);//在label中显示缩放后的图片 + ui->labelResult->setPixmap(pixmap.scaled(ui->scrollArea->width()-10,ui->scrollArea->height()-10,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + tempRes.isPixmap=true;//原图存入tempRes tempRes.pixmap=pixmap; if(settings->values.autoCopy) - QApplication::clipboard()->setPixmap(pixmap); + QApplication::clipboard()->setPixmap(pixmap);//复制到剪贴板 } break; - case SettingsDialog::OCR: + case SettingsDialog::OCR://OCR模式和翻译模式都需要接着进行OCR识别 baiduOCR->sendPic(pixmap); break; case SettingsDialog::Translate: @@ -189,52 +214,57 @@ void MainWindow::slotGrabFinished(QPixmap &pixmap) } } +//OCR识别结果返回成功 void MainWindow::slotBaiduOCRRecv(const QString &resStr) { - if(settings->values.sysMode==SettingsDialog::OCR) + if(settings->values.sysMode==SettingsDialog::OCR)//OCR模式 { - ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop); + ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop);//在label中显示结果 ui->labelResult->setText(resStr); - tempRes.isPixmap=false; + tempRes.isPixmap=false;//存入tempRes tempRes.text=resStr; if(settings->values.autoCopy) - QApplication::clipboard()->setText(resStr); + QApplication::clipboard()->setText(resStr);//存入剪贴板 } - else if(settings->values.sysMode==SettingsDialog::Translate) + else if(settings->values.sysMode==SettingsDialog::Translate)//翻译模式,将字符串再进行翻译 { baiduTrans->sendTrans(resStr); } } +//翻译结果返回成功 void MainWindow::slotBaiduTransRecv(const QString &resStr) { - ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop); + ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop);//在label中显示结果 ui->labelResult->setText(resStr); - tempRes.isPixmap=false; + tempRes.isPixmap=false;//存入tempRes tempRes.text=resStr; if(settings->values.autoCopy) - QApplication::clipboard()->setText(resStr); + QApplication::clipboard()->setText(resStr);//存入剪贴板 } +//用户确认设置,应用设置 void MainWindow::slotSettingsAccepted() { - applySettings(); - baiduOCR->sendAuth(); + applySettings();//应用 + baiduOCR->sendAuth();//用户可能修改了OCR认证,再次发送认证请求 } +//托盘事件 void MainWindow::slotActivatedSysTrayIcon(QSystemTrayIcon::ActivationReason reason) { switch(reason) { - case QSystemTrayIcon::Trigger: - show(); - setWindowState(Qt::WindowNoState); + case QSystemTrayIcon::Trigger://单击托盘图标 + show();//显示主窗口 + setWindowState(Qt::WindowNoState);//取消窗口状态(如最小化状态) break; default: break; } } +//OCR识别错误处理 void MainWindow::slotBaiduOCRError(BaiduOCR::Error error, const QString &errInfo) { QString displayStr; @@ -257,10 +287,11 @@ void MainWindow::slotBaiduOCRError(BaiduOCR::Error error, const QString &errInfo } if(!errInfo.isEmpty()) displayStr+="\n"+errInfo; - ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop); + ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop);//错误信息显示在label中 ui->labelResult->setText(displayStr); } +//翻译错误处理 void MainWindow::slotBaiduTransError(BaiduTrans::Error error, const QString &errInfo) { QString displayStr; @@ -278,15 +309,17 @@ void MainWindow::slotBaiduTransError(BaiduTrans::Error error, const QString &err } if(!errInfo.isEmpty()) displayStr+="错误信息:"+errInfo; - ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop); + ui->labelResult->setAlignment(Qt::AlignLeft|Qt::AlignTop);//错误信息显示在label中 ui->labelResult->setText(displayStr); } +//退出软件action void MainWindow::on_actionExit_triggered() { QApplication::quit(); } +//"复制到剪贴板"按钮点击 void MainWindow::on_btn_copy_clicked() { if(tempRes.isPixmap) @@ -295,17 +328,17 @@ void MainWindow::on_btn_copy_clicked() QApplication::clipboard()->setText(tempRes.text); } - +//切换悬浮窗模式 void MainWindow::on_actionFloat_triggered(bool checked) { isFloating=checked; - if(checked) + if(checked)//进入悬浮窗模式 { - setWindowFlags(windowFlags()|Qt::Tool|Qt::WindowStaysOnTopHint); - setWindowOpacity(settings->values.floatOpacity); + setWindowFlags(windowFlags()|Qt::Tool|Qt::WindowStaysOnTopHint);//无任务栏图标&保持在顶层 + setWindowOpacity(settings->values.floatOpacity);//设置不透明度 show(); } - else + else//退出悬浮窗模式 { setWindowFlags(windowFlags()&~(Qt::Tool|Qt::WindowStaysOnTopHint)); setWindowOpacity(1); @@ -313,23 +346,26 @@ void MainWindow::on_actionFloat_triggered(bool checked) } } +//打开反馈 void MainWindow::on_actionFeedback_triggered() { - QDesktopServices::openUrl(QUrl("https://support.qq.com/product/172973")); + QDesktopServices::openUrl(QUrl("https://support.qq.com/product/172973"));//使用腾讯兔小巢平台 } - +//显示关于界面 void MainWindow::on_actionAbout_triggered() { + about=new AboutDialog(); about->show(); } - +//显示捐赠界面 void MainWindow::on_actionDonate_triggered() { + donate=new DonateDialog(); donate->show(); donate->setImg(); } - +//显示帮助 void MainWindow::on_actionHelp_triggered() { - QDesktopServices::openUrl(QUrl("https://github.com/BowenLan/RightDrag/blob/master/help.md")); + QDesktopServices::openUrl(QUrl("https://github.com/BowenLan/RightDrag/blob/master/help.md"));//显示github上的help.md } diff --git a/mainwindow.h b/mainwindow.h index 0265385..eee0d71 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,3 +1,4 @@ +/*主窗口*/ #ifndef MAINWINDOW_H #define MAINWINDOW_H @@ -25,35 +26,31 @@ class MainWindow : public QMainWindow private: Ui::MainWindow *ui; - QSystemTrayIcon *trayIcon; - SettingsDialog *settings; - AboutDialog *about; - DonateDialog *donate; - Grabber *grabber; - BaiduOCR *baiduOCR; - BaiduTrans *baiduTrans; + QSystemTrayIcon *trayIcon;//托盘应用管理 + SettingsDialog *settings;//设置 + AboutDialog *about;//关于窗口 + DonateDialog *donate;//捐赠窗口 + Grabber *grabber;//屏幕抓取 + BaiduOCR *baiduOCR;//OCR识别 + BaiduTrans *baiduTrans;//翻译 struct{ - bool isPixmap; + bool isPixmap;//标识当前结果为图像还是文字 true:图像 false:文字 QPixmap pixmap; QString text; - }tempRes; - bool isFloating; - void writeDefaultSettings(); - void applySettings(); - void switchMode(SettingsDialog::SysMode mode); - void initTray(); + }tempRes;//暂存识别结果 + bool isFloating;//是否在悬浮窗模式 + void writeDefaultSettings();//写入默认设置 + void applySettings();//读取设置并应用 + void switchMode(SettingsDialog::SysMode mode);//切换系统模式(截图/OCR/翻译) + void initTray();//初始化托盘 + void setOCRLang(const QString &lang);//设置OCR识别语言 protected: void changeEvent(QEvent *event); void closeEvent(QCloseEvent *event); + void resizeEvent(QResizeEvent *event); private slots: - void on_actionOCR_triggered(); - void on_actionGrab_triggered(); - void on_actionTrans_triggered(); - void on_actionSettings_triggered(); - void on_actionExit_triggered(); - void on_btn_copy_clicked(); void slotGrabFinished(QPixmap &pixmap); void slotBaiduOCRRecv(const QString &resStr); void slotBaiduTransRecv(const QString &resStr); @@ -61,6 +58,12 @@ private slots: void slotActivatedSysTrayIcon(QSystemTrayIcon::ActivationReason); void slotBaiduOCRError(BaiduOCR::Error error,const QString &errInfo); void slotBaiduTransError(BaiduTrans::Error error,const QString &errInfo); + void on_actionOCR_triggered(); + void on_actionGrab_triggered(); + void on_actionTrans_triggered(); + void on_actionSettings_triggered(); + void on_actionExit_triggered(); + void on_btn_copy_clicked(); void on_actionFloat_triggered(bool checked); void on_actionFeedback_triggered(); void on_actionAbout_triggered(); diff --git a/net/ocr.cpp b/net/ocr.cpp index 92ca11d..54dee8a 100644 --- a/net/ocr.cpp +++ b/net/ocr.cpp @@ -6,7 +6,7 @@ #include "qpixmap.h" #include "qbuffer.h" -static const QString defApiKey="8kEopqDXdK8VvDc3pI7AdPX8",defSecretKey="ecN4DOkqqPq6QRu7IqM4etmRLmo0SyFT"; +//语言列表,用于语言名与语言代码的转换 static QString langList[][2]={ {"中英混合","CHN_ENG"}, {"英文","ENG"}, @@ -23,12 +23,18 @@ static QString langList[][2]={ BaiduOCR::BaiduOCR(QObject *parent) : QObject(parent) { manager=new QNetworkAccessManager(this); - connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyHandler(QNetworkReply*))); + connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyHandler(QNetworkReply*)));//连接网络接收槽 addEnter=false; - for(unsigned int i=0;iget(request); } +//发送图片 void BaiduOCR::sendPic(QPixmap &pixmap) { if(pixmap.width()<15||pixmap.height()<15) @@ -50,59 +57,70 @@ void BaiduOCR::sendPic(QPixmap &pixmap) } QNetworkRequest request; + //设置请求头 request.setUrl(QUrl("https://aip.baidubce.com/rest/2.0/ocr/v1/general?access_token="+access_token)); request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/x-www-form-urlencoded")); + //设置请求体 QByteArray postData,imgArray; QBuffer buf(&imgArray); - pixmap.save(&buf,"jpg"); - postData.append("image="+imgArray.toBase64().toPercentEncoding()); + pixmap.save(&buf,"jpg");//图片转存至QByteArray + postData.append("image="+imgArray.toBase64().toPercentEncoding());//图片经过base64编码和urlencode后放入请求 postData.append("&language_type="+language); buf.close(); manager->post(request,postData); } +//设置识别语言(传入语言名) void BaiduOCR::setLanguage(const QString &lang) { - if(langMap.contains(lang)) + if(langMap.contains(lang))//在表中查找语言代码 language=langMap.value(lang); } +//设置keys void BaiduOCR::setKeys(const QString &apiKey, const QString &secretKey) { api_key=apiKey; secret_key=secretKey; } +//网络返回数据处理 void BaiduOCR::replyHandler(QNetworkReply *reply) { - QByteArray array=reply->readAll(); + QByteArray array=reply->readAll();//读取回复 - if(reply->error()==QNetworkReply::NoError&&array.isEmpty()) + if(reply->error()==QNetworkReply::NoError&&array.isEmpty())//网络错误判定 { - qDebug( "network error, code: %d\n", (int)reply->error()); + //qDebug( "network error, code: %d\n", (int)reply->error()); emit error(Err_Network,QString("Error code=%1").arg((int)reply->error())); return; } - qDebug()< langMap; + QMap langMap;//语言代码对照表 enum Error{ Err_Network, Err_JsonParseFailed, @@ -16,13 +17,14 @@ class BaiduOCR : public QObject Err_SizeWrong, Err_Unknown }; - bool addEnter; - QString language; + bool addEnter;//在段落结尾插入\n,若为false则插入空格 + QString language;//需要识别的语言名 explicit BaiduOCR(QObject *parent = nullptr); - void sendAuth(); - void sendPic(QPixmap &pixmap); - void setLanguage(const QString &lang); - void setKeys(const QString &apiKey,const QString &secretKey); + ~BaiduOCR(); + void sendAuth();//进行认证 + void sendPic(QPixmap &pixmap);//发送图片进行识别 + void setLanguage(const QString &lang);//设置语言 + void setKeys(const QString &apiKey,const QString &secretKey);//设置api_key和secret_key private: QString access_token,api_key,secret_key; diff --git a/net/trans.cpp b/net/trans.cpp index 183766b..2404891 100644 --- a/net/trans.cpp +++ b/net/trans.cpp @@ -6,8 +6,9 @@ #include "qpixmap.h" #include "qbuffer.h" +//用于认证 static const QString defAppID="20200625000505739",defSecret="GzR__hiDPx_TxCf1NntD"; - +//语言代码转换表 static QString langList[][2]={ {"中文","zh"}, {"英语","en"}, @@ -43,20 +44,27 @@ BaiduTrans::BaiduTrans(QObject *parent) : QObject(parent) { manager=new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyHandler(QNetworkReply*))); - for(unsigned int i=0;ipost(request,postData); } +//设置源语言 void BaiduTrans::setSrcLang(QString &lang) { if(langMap.contains(lang)) fromLang=langMap.value(lang); } - +//设置目标语言 void BaiduTrans::setDstLang(QString &lang) { if(langMap.contains(lang)) toLang=langMap.value(lang); } +//网络接收信号处理 void BaiduTrans::replyHandler(QNetworkReply *reply) { - QByteArray array=reply->readAll(); + QByteArray array=reply->readAll();//读取回复 - if (reply->error()!=QNetworkReply::NoError&&array.isEmpty()) + if (reply->error()!=QNetworkReply::NoError&&array.isEmpty())//网络错误 { - qDebug( "network error, code: %d\n", (int)reply->error()); + //qDebug( "network error, code: %d\n", (int)reply->error()); emit error(Err_Network,QString("Error code=%1").arg((int)reply->error())); return; } - qDebug()< langMap; - QString fromLang,toLang; + QMap langMap;//语言代码对照表 + QString fromLang,toLang;//目标语言,源语言 QString appId,secret; QNetworkAccessManager *manager; diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 9ce790d..086c0e3 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -18,16 +18,19 @@ SettingsDialog::~SettingsDialog() delete ui; } +//判定配置文件是否存在 bool SettingsDialog::confExist() { QFileInfo file(confFilePath); return file.exists(); } +//加载设置 void SettingsDialog::loadSettings() { QSettings settings(confFilePath,QSettings::IniFormat); settings.beginGroup("settings"); + values.version=settings.value("version").toString(); values.trans_srcLang=settings.value("trans_srcLang").toString(); values.trans_dstLang=settings.value("trans_dstLang").toString(); values.ocr_apiKey=settings.value("ocr_apiKey").toString(); @@ -42,13 +45,16 @@ void SettingsDialog::loadSettings() values.autoCopy=settings.value("autoCopy").toBool(); values.sysMode=(SysMode)settings.value("sysMode").toInt(); values.floatOpacity=settings.value("floatOpacity").toDouble(); + values.blockMouse=settings.value("blockMouse").toBool(); } +//保存设置 void SettingsDialog::saveSettings() { QSettings settings(confFilePath,QSettings::IniFormat); settings.clear(); settings.beginGroup("settings"); + settings.setValue("version",values.version); settings.setValue("trans_srcLang",values.trans_srcLang); settings.setValue("trans_dstLang",values.trans_dstLang); settings.setValue("ocr_apiKey",values.ocr_apiKey); @@ -63,9 +69,11 @@ void SettingsDialog::saveSettings() settings.setValue("autoCopy",values.autoCopy); settings.setValue("sysMode",values.sysMode); settings.setValue("floatOpacity",values.floatOpacity); - settings.sync(); + settings.setValue("blockMouse",values.blockMouse); + settings.sync();//将设置写入文件 } +//显示设置窗口 void SettingsDialog::display() { show(); @@ -83,23 +91,27 @@ void SettingsDialog::display() ui->btn_lineColor->setText(values.rectLineColor.name()); ui->check_autoCopy->setChecked(values.autoCopy); ui->spin_opacity->setValue(values.floatOpacity); + ui->check_blockMouse->setChecked(values.blockMouse); } +//弹出颜色选择框让用户选择选框颜色 void SettingsDialog::on_btn_lineColor_clicked() { QColorDialog colorDialog(this); colorDialog.setWindowTitle("请选择颜色"); colorDialog.setCurrentColor(QColor(ui->btn_lineColor->text())); - if(colorDialog.exec()==QColorDialog::Accepted) + if(colorDialog.exec()==QColorDialog::Accepted)//用户确定了颜色选择 { - QColor color=colorDialog.selectedColor(); + QColor color=colorDialog.selectedColor();//获取用户选择的颜色 ui->btn_lineColor->setStyleSheet("font-weight:bold;color:"+color.name()); ui->btn_lineColor->setText(color.name()); } } +//用户按下按钮确认设置 void SettingsDialog::on_btnAccept_clicked() { + //保存控件信息到values values.ocr_apiKey=ui->txt_apiKey->text(); values.ocr_secretKey=ui->txt_secretKey->text(); values.ocr_lang=ui->combo_ocrLang->currentText(); @@ -113,9 +125,10 @@ void SettingsDialog::on_btnAccept_clicked() values.rectLineColor=QColor(ui->btn_lineColor->text()); values.autoCopy=ui->check_autoCopy->checkState(); values.floatOpacity=ui->spin_opacity->value(); - saveSettings(); - emit sigSettingsAccepted(); - hide(); + values.blockMouse=ui->check_blockMouse->checkState(); + saveSettings();//保存values到文件 + emit sigSettingsAccepted();//发出设置确认信号 + hide();//隐藏设置界面 } void SettingsDialog::on_btnCancel_clicked() diff --git a/settingsdialog.h b/settingsdialog.h index 52893e0..ceba1b7 100644 --- a/settingsdialog.h +++ b/settingsdialog.h @@ -1,3 +1,4 @@ +/*设置*/ #ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H @@ -15,26 +16,28 @@ class SettingsDialog : public QDialog public: explicit SettingsDialog(QWidget *parent = nullptr); ~SettingsDialog(); - enum SysMode{ - GrabOnly, - OCR, - Translate + enum SysMode{//系统模式 + GrabOnly,//框选截图 + OCR,//进行OCR识别 + Translate//翻译 }; - struct{ - QString trans_srcLang,trans_dstLang; - QString ocr_apiKey,ocr_secretKey,ocr_lang; - bool cbKey_ctrl,cbKey_shift,cbKey_alt; - Qt::PenStyle rectLineStyle; + struct{//所有设置 + QString version;//应用版本 + QString trans_srcLang,trans_dstLang;//翻译语言 + QString ocr_apiKey,ocr_secretKey,ocr_lang;//ocr认证key、识别语言 + bool cbKey_ctrl,cbKey_shift,cbKey_alt;//组合键设置 + Qt::PenStyle rectLineStyle;//选框样式 QColor rectLineColor; int rectLineWidth; - bool autoCopy; - double floatOpacity; - SysMode sysMode; + bool autoCopy;//自动复制 + double floatOpacity;//浮窗不透明度 + SysMode sysMode;//系统模式 + bool blockMouse;//是否拦截鼠标 }values; - bool confExist(); - void loadSettings(); - void saveSettings(); - void display(); + bool confExist();//检查是否已有设置 + void loadSettings();//加载设置(到values) + void saveSettings();//保存设置(从values) + void display();//显示设置界面 signals: void sigSettingsAccepted(); diff --git a/settingsdialog.ui b/settingsdialog.ui index be79ef9..3cf9199 100644 --- a/settingsdialog.ui +++ b/settingsdialog.ui @@ -260,7 +260,7 @@ border:2px solid rgb(0, 170, 255); - 英文 + 英语 @@ -545,13 +545,6 @@ border:2px solid rgb(0, 170, 255); 其他设置 - - - - 自动复制结果 - - - @@ -579,6 +572,20 @@ border:2px solid rgb(0, 170, 255); + + + + 自动复制结果 + + + + + + + 拦截鼠标事件 + + +