diff --git a/SerialTool/SerialTool.pro b/SerialTool/SerialTool.pro index 728e992..44fbc86 100644 --- a/SerialTool/SerialTool.pro +++ b/SerialTool/SerialTool.pro @@ -34,7 +34,6 @@ SOURCES += \ source/main.cpp \ source/optionsbox.cpp \ source/portsetbox.cpp \ - source/serialtool.cpp\ source/textedit.cpp \ source/wavedecode.cpp \ source/oscilloscope.cpp \ @@ -48,14 +47,14 @@ SOURCES += \ source/terminalview.cpp \ source/serialport.cpp \ source/pointdatabuffer.cpp \ - source/valuedisplay.cpp + source/valuedisplay.cpp \ + source/mainwindow.cpp HEADERS += \ include/aboutbox.h \ include/channelitem.h \ include/optionsbox.h \ include/portsetbox.h \ - include/serialtool.h \ include/textedit.h \ include/version.h \ include/wavedecode.h \ @@ -71,7 +70,8 @@ HEADERS += \ include/terminalview.h \ include/serialport.h \ include/pointdatabuffer.h \ - include/valuedisplay.h + include/valuedisplay.h \ + include/mainwindow.h DISTFILES += \ resource/images/clear.png \ @@ -92,13 +92,13 @@ FORMS += \ ui/aboutbox.ui \ ui/optionsbox.ui \ ui/portsetbox.ui \ - ui/serialtool.ui \ ui/oscilloscope.ui \ ui/filetransferview.ui \ ui/vediobox.ui \ ui/tcpudpport.ui \ ui/terminalview.ui \ + ui/valuedisplay.ui \ ui/serialport.ui \ - ui/valuedisplay.ui + ui/mainwindow.ui LIBS += -lqscintilla2_qt5 diff --git a/SerialTool/include/aboutbox.h b/SerialTool/include/aboutbox.h index 8a431ef..70fe3fd 100644 --- a/SerialTool/include/aboutbox.h +++ b/SerialTool/include/aboutbox.h @@ -1,14 +1,18 @@ #ifndef __ABOUTBOX_H #define __ABOUTBOX_H -#include "ui_aboutbox.h" #include +namespace Ui { + class AboutBox; +} + class AboutBox : public QDialog { public: AboutBox(QWidget *parent); + ~AboutBox(); private: - Ui_AboutBox ui; + Ui::AboutBox *ui; }; #endif diff --git a/SerialTool/include/filethread.h b/SerialTool/include/filethread.h index 013c02a..87ab316 100644 --- a/SerialTool/include/filethread.h +++ b/SerialTool/include/filethread.h @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include class FileThread : public QThread { @@ -29,8 +31,8 @@ public : void setFileName(const QString &fileName); void setProtocol(Protocol mode); void setTransMode(TransMode mode); - bool startTransfer(); - bool cancelTransfer(); + void startTransmit(); + void cancelTransmit(); qint64 fileSize(); qint64 filePos(); char progress(); @@ -44,17 +46,42 @@ public slots: signals: void sendData(const QByteArray &); void transFinsh(void); + void fileError(); + void timeout(); protected: void run(); +private slots: + void onTimerUpdate(); + +private: + enum Status { + None = 0, + StartTrans, + CancelTrans, + ReadData + }; + + void setStatus(Status status); + void startTransmit_p(); + void receivePack_p(const QByteArray &array); + void cancelTransmit_p(); + void closeFile(); + private: Protocol protocol; TransMode transMode; qint64 fSize, fPos; - QByteArray receiveArray; // ջ + QMutex m_mutex; + QSemaphore m_sem; + QByteArray receiveArray; // 接收缓冲区 QString fileName; - QFile *file; + QFile *m_file; + Status m_status = None; + QByteArray m_rxbuffer; + QTimer m_timer; + int m_timeoutCount; }; #endif diff --git a/SerialTool/include/filetransferview.h b/SerialTool/include/filetransferview.h index 9a6334c..e47e06f 100644 --- a/SerialTool/include/filetransferview.h +++ b/SerialTool/include/filetransferview.h @@ -1,16 +1,21 @@ #ifndef __FILETRANSFERVIEW_H #define __FILETRANSFERVIEW_H -#include "ui_filetransferview.h" -#include +#include #include "filethread.h" +namespace Ui { + class FileTransferView; +} +class QSettings; + class FileTransferView : public QWidget { Q_OBJECT public: FileTransferView(QWidget *parent = Q_NULLPTR); + ~FileTransferView(); void retranslate(); void loadConfig(QSettings *config); void saveConfig(QSettings *config); @@ -28,12 +33,13 @@ private slots: void portSendData(const QByteArray &array); void sendFile(); void onTransFinsh(); + void onTimeoutError(); signals: void sendData(const QByteArray &); private: - Ui_FileTransferView ui; + Ui::FileTransferView *ui; FileThread thread; QByteArray receiveArray; // 接收缓冲区 }; diff --git a/SerialTool/include/serialtool.h b/SerialTool/include/mainwindow.h similarity index 64% rename from SerialTool/include/serialtool.h rename to SerialTool/include/mainwindow.h index e5b3a6e..5053256 100644 --- a/SerialTool/include/serialtool.h +++ b/SerialTool/include/mainwindow.h @@ -1,20 +1,23 @@ -#ifndef __SERIALTOOL_H -#define __SERIALTOOL_H +#ifndef __MAINWINDOW_H +#define __MAINWINDOW_H #include -#include "ui_serialtool.h" -#include -#include #include -#include "channelitem.h" -#include "vediobox.h" +#include +namespace Ui { +class MainWindow; +} +class QSettings; class TcpUdpPort; class WaveDecode; class SerialPort; +class VedioBox; class ValueDisplay; +class QTranslator; +class QActionGroup; -class SerialTool : public QMainWindow +class MainWindow : public QMainWindow { Q_OBJECT @@ -24,12 +27,12 @@ class SerialTool : public QMainWindow }; public: - SerialTool(QWidget *parent = Q_NULLPTR); - ~SerialTool(); + MainWindow(QWidget *parent = Q_NULLPTR); + ~MainWindow(); void loadSettings(); void saveConfig(); - QSettings *getConfig() { return config; } + QSettings *getConfig() { return m_config; } void setLanguage(const QString &string); void setStyleSheet(const QString &string); @@ -68,21 +71,20 @@ private slots: void setWindowStaysOnTop(bool enabled); private: - Ui_SerialTool ui; - QString docPath; - QTimer secTimer; // 秒定时器 - TcpUdpPort *tcpUdpPort; // TCP/UDP端口 - QSettings *config; - bool runFlag = true; - QActionGroup *tabActionGroup; - int rxCount, txCount; - QLabel *rxCntLabel, *txCntLabel, *portInfoLabel; - QVector translator; + Ui::MainWindow *ui; + QString m_docPath; + QTimer m_timer; // 秒定时器 + TcpUdpPort *m_tcpUdpPort; // TCP/UDP端口 + QSettings *m_config; + bool m_runFlag = true; + QActionGroup *m_tabActionGroup; + int m_rxCount, m_txCount; + QLabel *m_rxCntLabel, *m_txCntLabel, *m_portInfoLabel; + QVector m_translator; VedioBox *m_vedioBox = NULL; ValueDisplay *m_valueDisplay = NULL; - PortType portType; - WaveDecode* waveDecode; - SerialPort *serialPort; + PortType m_portType; + SerialPort *m_serialPort; }; -#endif // SERIALTOOL_H +#endif // __MAINWINDOW_H diff --git a/SerialTool/include/optionsbox.h b/SerialTool/include/optionsbox.h index b716ed5..ab79f75 100644 --- a/SerialTool/include/optionsbox.h +++ b/SerialTool/include/optionsbox.h @@ -1,16 +1,19 @@ #ifndef __OPTIONSBOX_H #define __OPTIONSBOX_H -#include "ui_optionsbox.h" #include -class SerialTool; +namespace Ui { +class OptionsBox; +} +class MainWindow; +class QAbstractButton; class OptionsBox : public QDialog { Q_OBJECT public: - OptionsBox(SerialTool *parent = Q_NULLPTR); + OptionsBox(MainWindow *parent = Q_NULLPTR); ~OptionsBox(); private: @@ -36,8 +39,8 @@ private slots: void setLanguage(int index); private: - Ui_OptionsBox ui; - SerialTool *serialTool; + Ui::OptionsBox *ui; + MainWindow *m_parent; QString fontFamily, fontStyle; int fontSize; QString rxColor, txColor, bgColor, axColor; diff --git a/SerialTool/include/oscilloscope.h b/SerialTool/include/oscilloscope.h index 3b0e3fc..69e0446 100644 --- a/SerialTool/include/oscilloscope.h +++ b/SerialTool/include/oscilloscope.h @@ -1,18 +1,19 @@ #ifndef __OSCILLOSCOPE_H #define __OSCILLOSCOPE_H -#include "ui_oscilloscope.h" - -#include +#include #ifndef CH_NUM #define CH_NUM 16 #endif -struct WaveDataType; +namespace Ui { +class Oscilloscope; +} class OscopeTimeStamp; class PointDataBuffer; class ChannelItem; +class WaveDecode; class QSettings; namespace QtCharts { class QLineSeries; @@ -39,7 +40,7 @@ class Oscilloscope : public QWidget { void setBackground(QColor color); void setGridColor(QColor color); void setUpdateInterval(int msec); - void addData(const WaveDataType& data); + void append(const QByteArray &array); void clear(); void savePng(const QString &fileName); @@ -54,9 +55,7 @@ class Oscilloscope : public QWidget { QStringList csvSplitLine(const QString &line) { return line.split(", "); } - ChannelItem* channelWidget(int channel) { - return (ChannelItem *)(ui.channelList->itemWidget(ui.channelList->item(channel))); - } + ChannelItem* channelWidget(int channel); private slots: void yOffsetChanged(double offset); @@ -67,14 +66,15 @@ private slots: void timeUpdata(); private: - Ui_Oscilloscope ui; + Ui::Oscilloscope *ui; bool replotFlag = 1; QVector m_series; QtCharts::QChart *m_chart; int m_count, m_xRange; - QTimer updataTimer; - OscopeTimeStamp* timeStamp; + QTimer *m_timer; + OscopeTimeStamp *m_timeStamp; PointDataBuffer *m_buffer; + WaveDecode *m_decode; }; #endif diff --git a/SerialTool/include/oscopetimestamp.h b/SerialTool/include/oscopetimestamp.h index 8f71c01..87ea458 100644 --- a/SerialTool/include/oscopetimestamp.h +++ b/SerialTool/include/oscopetimestamp.h @@ -1,19 +1,17 @@ #ifndef __OSCOPE_TIME_STAMP_H #define __OSCOPE_TIME_STAMP_H - #include #include - -struct WaveDataType; +#include "wavedecode.h" class OscopeTimeStamp { public: - OscopeTimeStamp() { timeStamp.clear(); } + OscopeTimeStamp() { m_timeStampVector.clear(); } void printTextStream(QTextStream &stream, uint64_t count); - void append(const WaveDataType &data, uint64_t count); + void append(const WaveDecode::DataType &data, uint64_t count); void append(const QString &string, uint64_t count); - void clear() { timeStamp.clear(); } + void clear() { m_timeStampVector.clear(); } private: struct TimeStamp_p { @@ -28,7 +26,7 @@ class OscopeTimeStamp { uint32_t sampleRate; }; - QVector timeStamp; + QVector m_timeStampVector; }; #endif diff --git a/SerialTool/include/portsetbox.h b/SerialTool/include/portsetbox.h index 5c0ed15..ca01776 100644 --- a/SerialTool/include/portsetbox.h +++ b/SerialTool/include/portsetbox.h @@ -1,11 +1,14 @@ #ifndef __PORTSETBOX_H #define __PORTSETBOX_H -#include "ui_portsetbox.h" #include #include #include +namespace Ui { +class PortSetBox; +} + class PortSetBox : public QDialog { Q_OBJECT @@ -19,7 +22,7 @@ private slots: void setStopBits(int index); void setFlowControl(int index); private: - Ui_PortSetBox ui; + Ui::PortSetBox *ui; QSerialPort *serialPort; }; diff --git a/SerialTool/include/textedit.h b/SerialTool/include/textedit.h index 6aaeb78..d86ded7 100644 --- a/SerialTool/include/textedit.h +++ b/SerialTool/include/textedit.h @@ -9,7 +9,6 @@ class TextEdit : public QsciScintilla public: TextEdit(QWidget *parent = NULL); - void setText(const QString &text); void append(const QString &text); void setFonts(QString fonts, int size, QColor color = Qt::black, QString style = ""); void setHighLight(bool mode); diff --git a/SerialTool/include/valuedisplay.h b/SerialTool/include/valuedisplay.h index c57ea8c..f72c62c 100644 --- a/SerialTool/include/valuedisplay.h +++ b/SerialTool/include/valuedisplay.h @@ -14,7 +14,7 @@ class ValueDisplay : public QDialog public: explicit ValueDisplay(QWidget *parent = 0); ~ValueDisplay(); - void addData(const QByteArray &array); + void append(const QByteArray &array); private: Ui::ValueDisplay *ui; diff --git a/SerialTool/include/vediobox.h b/SerialTool/include/vediobox.h index f893958..be46643 100644 --- a/SerialTool/include/vediobox.h +++ b/SerialTool/include/vediobox.h @@ -1,16 +1,20 @@ #ifndef __VEDIOBOX_H #define __VEDIOBOX_H -#include "ui_vediobox.h" #include +namespace Ui { + class VedioBox; +} + class VedioBox : public QDialog { Q_OBJECT public: VedioBox(QWidget *parent = NULL); - void addData(const QByteArray &arr); + ~VedioBox(); + void append(const QByteArray &arr); void setFilePath(const QString &path); private slots: @@ -18,7 +22,7 @@ private slots: void copyImage(); private: - Ui_VedioBox ui; + Ui::VedioBox *ui; QByteArray array; QPixmap image; char imageData[600]; diff --git a/SerialTool/include/version.h b/SerialTool/include/version.h index 66fc685..68cd529 100644 --- a/SerialTool/include/version.h +++ b/SerialTool/include/version.h @@ -1,7 +1,7 @@ #ifndef __VERSION_H #define __VERSION_H -#define MAIN_VERSION 1.2.1 +#define MAIN_VERSION 1.2.2 #define SOFTWARE_NAME "SerialTool" #define COPYRIGHT "Copyleft 2017 by Wenliang" @@ -9,7 +9,7 @@ #define _STR_(s) #s #define __STR(s) _STR_(s) -#define BUILD_VERSION _STR_(4191bM) +#define BUILD_VERSION _STR_(45248M) #define SOFTWARE_VERSION __STR(MAIN_VERSION) #endif diff --git a/SerialTool/include/wavedecode.h b/SerialTool/include/wavedecode.h index dbfa094..286ef5b 100644 --- a/SerialTool/include/wavedecode.h +++ b/SerialTool/include/wavedecode.h @@ -1,36 +1,38 @@ #ifndef __WAVEDECODE_H #define __WAVEDECODE_H -#include +#include -enum WaveDataMode { - WaveValueMode, - WaveTimeStampMode -}; - -struct WaveDataType { - WaveDataMode mode; - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - uint16_t msec; - uint32_t sampleRate; - double value; - uint8_t channel; -}; +class QByteArray; class WaveDecode { public: + enum DataMode { + ValueMode, + TimeStampMode + }; + struct DataType { + DataMode mode; + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint16_t msec; + uint32_t sampleRate; + double value; + uint8_t channel; + }; + WaveDecode(); - bool frameDecode(WaveDataType &data, uint8_t byte); + QVector frameDecode(const QByteArray &array); private: double data2Double(uint32_t value, int type); - int pointData(WaveDataType &dst, uint8_t byte); - void timeStamp(WaveDataType &dst, uint8_t* buffer); + int pointData(DataType &dst, uint8_t byte); + void timeStamp(DataType &dst, uint8_t* buffer); + bool frameDecode_p(DataType &data, uint8_t byte); private: uint32_t data; diff --git a/SerialTool/include/xmodem.h b/SerialTool/include/xmodem.h index 7e34d0d..d96ac58 100644 --- a/SerialTool/include/xmodem.h +++ b/SerialTool/include/xmodem.h @@ -17,7 +17,7 @@ public : int receive(const QByteArray &arr, qint64 &bytes); void startTransmit(); void startReceive(); - bool cancelTrans(); + void cancelTrans(); private: char calcVerifi(const char *frame); @@ -26,10 +26,10 @@ public : bool transMode; char status; char lastCount; - uint8_t packCount; // - char frame[132]; // ֡ + uint8_t packCount; // 包计数 + char frame[132]; // 数据帧 FileThread *thread; - QByteArray rxBuf; // ջ + QByteArray rxBuf; // 接收缓冲 }; #endif diff --git a/SerialTool/language/serialtool_zh_CN.ts b/SerialTool/language/serialtool_zh_CN.ts index 79f45b1..ddec93b 100644 --- a/SerialTool/language/serialtool_zh_CN.ts +++ b/SerialTool/language/serialtool_zh_CN.ts @@ -17,14 +17,6 @@ 修改绘制线条的颜色 - - DocmentDialog - - Docment - 文档 - - - FileTransferView @@ -103,39 +95,244 @@ 浏览... - + Start transmit file: " 开始传输文件: " - + Can not open the file: " 无法打开文件: " - + + Error: 错误: - + + Error 错误 - + Cancel transfer. 取消传输. - + Transmit finished. 传输完成. + + + Transmission timeout. + 传输超时。 + + + + MainWindow + + + + Terminal + 终端 + + + + + Plot + 波形绘制 + + + + + File Transmit + 文件传输 + + + + File + 文件 + + + + Tools + 工具 + + + + Edit + 编辑 + + + + View + 视图 + + + + Help + 帮助 + + + + + Tool Bar + 工具栏 + + + + + Save + 保存 + + + + Ctrl+S + + + + + Options + 选项 + + + + + Open Port + 打开端口 + + + + Alt+S + + + + + + Pause Tx/Rx + 暂停发送/接收 + + + + Alt+R + + + + + Clear Buffer + 清空缓冲 + + + + Alt+C + + + + + Port Settings + 端口设置 + + + + Close + 关闭 + + + + Tester + 调试助手 + + + + Status Bar + 状态栏 + + + + About + 关于 + + + + F1 + + + + + Vedio Box + 视频图传 + + + + + Wiki + + + + + + + Open + 打开 + + + + Ctrl+O + + + + + Value Display + 数值显示器 + + + + Stays On Top + 置于顶层 + + + + + Portable Network Graphic Format (*.png) + 图像文件存储格式 (*.png) + + + + + Bitmap (*.bmp) + 位图文件 (*.bmp) + + + + + + Wave Plain Text File (*.txt) + 波形纯文本文件 (*.txt) + + + + + Terminal Text File (*.txt) + 终端文本文件 (*.txt) + + + + Start Tx/Rx + 开始发送/接收 + + + + Close Port + 关闭端口 + OptionsBox @@ -322,22 +519,22 @@ 保持接收 - + Warning 警告 - + The current window has data not saved, Still open the file? 当前窗口数据未保存,仍然打开文件? - + Error 错误 - + File parsing error. 文件解析错误。 @@ -395,212 +592,6 @@ Port may be occupied or configured incorrectly! 端口可能被占用或者配置错误! - - SerialTool - - - - Portable Network Graphic Format (*.png) - 图像文件存储格式 (*.png) - - - - - Bitmap (*.bmp) - 位图文件 (*.bmp) - - - - - - Wave Plain Text File (*.txt) - 波形纯文本文件 (*.txt) - - - - - Terminal Text File (*.txt) - 终端文本文件 (*.txt) - - - - Start Tx/Rx - 开始发送/接收 - - - - - Pause Tx/Rx - 暂停发送/接收 - - - - - Open Port - 打开端口 - - - - Close Port - 关闭端口 - - - - - Terminal - 终端 - - - - Tester - 调试助手 - - - - - Plot - 波形绘制 - - - - File - 文件 - - - - Tools - 工具 - - - - Edit - 编辑 - - - - View - 视图 - - - - Help - 帮助 - - - Port Tool Bar - 端口工具栏 - - - - - Save - 保存 - - - - Ctrl+S - - - - - Options - 选项 - - - - Alt+S - - - - - Alt+R - - - - - Clear Buffer - 清空缓冲 - - - - Alt+C - - - - - Port Settings - 端口设置 - - - - Close - 关闭 - - - - Vedio Box - 视频图传 - - - - - Wiki - - - - - Stays On Top - 置于顶层 - - - Docment - 文档 - - - - - - Open - 打开 - - - - Ctrl+O - - - - - Value Display - 数值显示器 - - - - - Tool Bar - 工具栏 - - - - - File Transmit - 文件传输 - - - - Status Bar - 状态栏 - - - - About - 关于 - - - - F1 - - - TcpUdpPort diff --git a/SerialTool/language/zh_cn/serialtool.qm b/SerialTool/language/zh_cn/serialtool.qm index c4a67b8..41d4e49 100644 Binary files a/SerialTool/language/zh_cn/serialtool.qm and b/SerialTool/language/zh_cn/serialtool.qm differ diff --git a/SerialTool/resource/images/clear.ico b/SerialTool/resource/images/clear.ico new file mode 100644 index 0000000..d809e57 Binary files /dev/null and b/SerialTool/resource/images/clear.ico differ diff --git a/SerialTool/resource/images/clear.png b/SerialTool/resource/images/clear.png deleted file mode 100644 index cf4cff9..0000000 Binary files a/SerialTool/resource/images/clear.png and /dev/null differ diff --git a/SerialTool/resource/images/close.ico b/SerialTool/resource/images/close.ico new file mode 100644 index 0000000..6763636 Binary files /dev/null and b/SerialTool/resource/images/close.ico differ diff --git a/SerialTool/resource/images/close.png b/SerialTool/resource/images/close.png deleted file mode 100644 index df22c20..0000000 Binary files a/SerialTool/resource/images/close.png and /dev/null differ diff --git a/SerialTool/resource/images/connect.ico b/SerialTool/resource/images/connect.ico new file mode 100644 index 0000000..8f77c11 Binary files /dev/null and b/SerialTool/resource/images/connect.ico differ diff --git a/SerialTool/resource/images/connect.png b/SerialTool/resource/images/connect.png deleted file mode 100644 index 8c862d4..0000000 Binary files a/SerialTool/resource/images/connect.png and /dev/null differ diff --git a/SerialTool/resource/images/pin_down.ico b/SerialTool/resource/images/pin_down.ico new file mode 100644 index 0000000..b2aefa3 Binary files /dev/null and b/SerialTool/resource/images/pin_down.ico differ diff --git a/SerialTool/resource/images/pin_down.png b/SerialTool/resource/images/pin_down.png deleted file mode 100644 index ab6a463..0000000 Binary files a/SerialTool/resource/images/pin_down.png and /dev/null differ diff --git a/SerialTool/resource/images/pin_up.ico b/SerialTool/resource/images/pin_up.ico new file mode 100644 index 0000000..c749af9 Binary files /dev/null and b/SerialTool/resource/images/pin_up.ico differ diff --git a/SerialTool/resource/images/pin_up.png b/SerialTool/resource/images/pin_up.png deleted file mode 100644 index 4f73369..0000000 Binary files a/SerialTool/resource/images/pin_up.png and /dev/null differ diff --git a/SerialTool/resource/images/port config.ico b/SerialTool/resource/images/port config.ico new file mode 100644 index 0000000..089c655 Binary files /dev/null and b/SerialTool/resource/images/port config.ico differ diff --git a/SerialTool/resource/images/port config.png b/SerialTool/resource/images/port config.png deleted file mode 100644 index 7c32880..0000000 Binary files a/SerialTool/resource/images/port config.png and /dev/null differ diff --git a/SerialTool/resource/serialtool.qrc b/SerialTool/resource/serialtool.qrc index b0caf09..904af0a 100644 --- a/SerialTool/resource/serialtool.qrc +++ b/SerialTool/resource/serialtool.qrc @@ -1,18 +1,18 @@ - images/clear.png - images/close.png images/config.ico - images/connect.png images/exit.ico images/icon.ico images/pause.ico - images/port config.png images/save.ico images/start.ico images/open.ico - images/pin_down.png - images/pin_up.png + images/connect.ico + images/pin_down.ico + images/pin_up.ico + images/clear.ico + images/close.ico + images/port config.ico license.html diff --git a/SerialTool/source/aboutbox.cpp b/SerialTool/source/aboutbox.cpp index 492978a..f8fa923 100644 --- a/SerialTool/source/aboutbox.cpp +++ b/SerialTool/source/aboutbox.cpp @@ -1,14 +1,17 @@ #include "aboutbox.h" +#include "ui_aboutbox.h" #include #include "version.h" -AboutBox::AboutBox(QWidget *parent) : QDialog(parent) +AboutBox::AboutBox(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutBox) { // 不显示问号 Qt::WindowFlags flags = Qt::Dialog; flags |= Qt::WindowCloseButtonHint; setWindowFlags(flags); - ui.setupUi(this); + ui->setupUi(this); setFixedSize(400, 400); // 不能伸缩的对话框 QPalette pal(palette()); @@ -16,13 +19,13 @@ AboutBox::AboutBox(QWidget *parent) : QDialog(parent) setAutoFillBackground(true); setPalette(pal); - ui.buttonBox->setCenterButtons(true); // 按钮居中 - ui.textBrowser->setFrameStyle(QFrame::NoFrame); // 无边框 + ui->buttonBox->setCenterButtons(true); // 按钮居中 + ui->textBrowser->setFrameStyle(QFrame::NoFrame); // 无边框 QPixmap pix(":/SerialTool/images/icon.ico"); pix = pix.scaledToWidth(64, Qt::SmoothTransformation); - ui.label1->setPixmap(pix); - ui.label2->setText( + ui->label1->setPixmap(pix); + ui->label2->setText( "SerialTool
" "Version: " SOFTWARE_VERSION " (" BUILD_VERSION ")
" "Email: 2269610337@qq.com
" @@ -30,10 +33,15 @@ AboutBox::AboutBox(QWidget *parent) : QDialog(parent) "Build Date: " __DATE__ "
" // 编译时间 COPYRIGHT ); - ui.label2->setOpenExternalLinks(true); // 允许访问链接 + ui->label2->setOpenExternalLinks(true); // 允许访问链接 QFile lic(":/license/license.html"); lic.open(QFile::ReadOnly); - ui.textBrowser->setHtml(lic.readAll()); - ui.textBrowser->setOpenExternalLinks(true); // 允许访问链接 + ui->textBrowser->setHtml(lic.readAll()); + ui->textBrowser->setOpenExternalLinks(true); // 允许访问链接 lic.close(); } + +AboutBox::~AboutBox() +{ + delete ui; +} diff --git a/SerialTool/source/filethread.cpp b/SerialTool/source/filethread.cpp index 245f450..67d68a5 100644 --- a/SerialTool/source/filethread.cpp +++ b/SerialTool/source/filethread.cpp @@ -1,5 +1,7 @@ #include "filethread.h" #include "xmodem.h" +#include +#include static XModemClass xmodem; @@ -7,89 +9,56 @@ FileThread::FileThread() { xmodem.setThread(this); transMode = StopMode; + start(); + + connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimerUpdate())); + + m_timer.setInterval(500); } -// ļ +// 发送文件 void FileThread::setFileName(const QString &fileName) { this->fileName = fileName; } -// ôЭ +// 设置传输协议 void FileThread::setProtocol(Protocol mode) { protocol = mode; } -// շģʽ +// 设置收发模式 void FileThread::setTransMode(TransMode mode) { transMode = mode; } -// -bool FileThread::startTransfer() +// 启动传输 +void FileThread::startTransmit() { - bool res; - file = new QFile(fileName); - if (transMode == SendMode) { - res = file->open(QFile::ReadOnly); - switch (protocol) { - case XModem: - xmodem.startTransmit(); - break; - default: - break; - } - } else { - res = file->open(QFile::WriteOnly); - switch (protocol) { - case XModem: - xmodem.startReceive(); - break; - default: - break; - } - } - fSize = file->size(); - fPos = 0; - return res; + setStatus(StartTrans); } -// ȡ -bool FileThread::cancelTransfer() +// 取消传输 +void FileThread::cancelTransmit() { - bool res = true; - - switch (protocol) { - case XModem: - res = xmodem.cancelTrans(); - break; - default: - break; - } - if (res) { - file->close(); - delete file; - file = nullptr; - transMode = StopMode; - } - return res; + setStatus(CancelTrans); } -// ȡļС +// 获取文件大小 qint64 FileThread::fileSize() { return fSize; } -// ȡļƫ +// 获取文件偏移 qint64 FileThread::filePos() { return fPos; } -// ȡ +// 获取传输进度 char FileThread::progress() { if (fSize == 0) { @@ -98,12 +67,74 @@ char FileThread::progress() return (char)(fPos * 100 / fSize); } -// ȡݲۺ +// 读取数据槽函数 void FileThread::readData(const QByteArray &array) +{ + m_mutex.lock(); + m_rxbuffer = array; + m_mutex.unlock(); + setStatus(ReadData); +} + +void FileThread::setStatus(Status status) +{ + m_mutex.lock(); + m_status = status; + m_mutex.unlock(); + m_sem.release(); +} + +// 发送数据 +void FileThread::sendPortData(const QByteArray &array) +{ + emit sendData(array); +} + +// 线程函数 +void FileThread::run() +{ + forever { + m_sem.acquire(); + m_mutex.lock(); + Status status = m_status; + QByteArray array = m_rxbuffer; + m_status = None; + m_mutex.unlock(); + + QTimer::singleShot(0, &m_timer,SLOT(stop())); + + switch (status) { + case ReadData: + receivePack_p(array); + break; + case StartTrans: + m_timeoutCount = 0; + startTransmit_p(); + break; + case CancelTrans: + cancelTransmit_p(); + break; + default: + break; + } + } +} + +void FileThread::writeFile(const char* buffer, int size) +{ + m_file->write(buffer, size); +} + +int FileThread::readFile(char* buffer, int size) +{ + return m_file->read(buffer, size); +} + +void FileThread::receivePack_p(const QByteArray &array) { char result = 0; - if (transMode == SendMode) { // ģʽ + if (transMode == SendMode) { // 发送模式 switch (protocol) { case XModem: result = xmodem.transmit(array[0], fPos); @@ -111,7 +142,7 @@ void FileThread::readData(const QByteArray &array) default: break; } - } else if (transMode == ReceiveMode) { // ģʽ + } else if (transMode == ReceiveMode) { // 接收模式 switch (protocol) { case XModem: result = xmodem.receive(array, fPos); @@ -121,33 +152,76 @@ void FileThread::readData(const QByteArray &array) } fSize = fPos; } - if (result) { // - file->close(); - delete file; - file = nullptr; + if (result) { // 传输结束 + closeFile(); transMode = StopMode; emit transFinsh(); } } -// -void FileThread::sendPortData(const QByteArray &array) +void FileThread::startTransmit_p() { - emit sendData(array); + bool res; + m_file = new QFile(fileName); + if (transMode == SendMode) { + res = m_file->open(QFile::ReadOnly); + if (res) { + switch (protocol) { + case XModem: + xmodem.startTransmit(); + break; + default: + break; + } + } + } else { + res = m_file->open(QFile::WriteOnly); + if (res) { + switch (protocol) { + case XModem: + xmodem.startReceive(); + QTimer::singleShot(0, &m_timer,SLOT(start())); + break; + default: + break; + } + } + } + if (res) { + fSize = m_file->size(); + fPos = 0; + } else { + emit fileError(); // connot open file + } } -// ̺߳ -void FileThread::run() +// 取消传输(私有) +void FileThread::cancelTransmit_p() { - exec(); + switch (protocol) { + case XModem: + xmodem.cancelTrans(); + break; + default: + break; + } + closeFile(); + transMode = StopMode; } -void FileThread::writeFile(const char* buffer, int size) +void FileThread::onTimerUpdate() { - file->write(buffer, size); + if (m_timeoutCount++ >= 10) { + closeFile(); + m_timer.stop(); + emit timeout(); + } else { + startTransmit_p(); + } } -int FileThread::readFile(char* buffer, int size) -{ - return file->read(buffer, size); +void FileThread::closeFile() { + m_file->close(); + delete m_file; + m_file = nullptr; } diff --git a/SerialTool/source/filetransferview.cpp b/SerialTool/source/filetransferview.cpp index 4189488..2110465 100644 --- a/SerialTool/source/filetransferview.cpp +++ b/SerialTool/source/filetransferview.cpp @@ -1,38 +1,48 @@ #include "filetransferview.h" +#include "ui_filetransferview.h" +#include #include #include #include #include "xmodem.h" // 构造函数 -FileTransferView::FileTransferView(QWidget *parent) : QWidget(parent) +FileTransferView::FileTransferView(QWidget *parent) : + QWidget(parent), + ui(new Ui::FileTransferView) { - ui.setupUi(this); + ui->setupUi(this); connect(&thread, &FileThread::sendData, this, &FileTransferView::portSendData); - connect(ui.stopButton, SIGNAL(clicked()), this, SLOT(cancelTransfer())); - connect(ui.browseButton, SIGNAL(clicked()), this, SLOT(browseButtonClicked())); - connect(ui.startButton, SIGNAL(clicked()), this, SLOT(sendFile())); + connect(ui->stopButton, SIGNAL(clicked()), this, SLOT(cancelTransfer())); + connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseButtonClicked())); + connect(ui->startButton, SIGNAL(clicked()), this, SLOT(sendFile())); connect(&thread, SIGNAL(transFinsh()), this, SLOT(onTransFinsh())); + connect(&thread, SIGNAL(timeout()), this, SLOT(onTimeoutError())); +} + +FileTransferView::~FileTransferView() +{ + delete ui; } void FileTransferView::retranslate() { - ui.retranslateUi(this); + ui->retranslateUi(this); } /* 读取配置文件 */ void FileTransferView::loadConfig(QSettings *config) { config->beginGroup("FileTransmit"); - ui.beforeSendEdit->setText(config->value("BeforeSendText").toString()); - ui.enableBerforSendBox->setChecked(config->value("BeforeSend").toBool()); - ui.pathBox->setText(config->value("FileName").toString()); - ui.protocolBox->setCurrentText(config->value("Protocol").toString()); + ui->beforeSendEdit->setText(config->value("BeforeSendText").toString()); + ui->enableBerforSendBox->setChecked(config->value("BeforeSend").toBool()); + ui->pathBox->setText(config->value("FileName").toString()); + ui->protocolBox->setCurrentText(config->value("Protocol").toString()); if (config->value("SendMode").toBool()) { - ui.sendButton->setChecked(true); + ui->sendButton->setChecked(true); } else { - ui.receiveButton->setChecked(true); + ui->receiveButton->setChecked(true); } config->endGroup(); } @@ -41,11 +51,11 @@ void FileTransferView::loadConfig(QSettings *config) void FileTransferView::saveConfig(QSettings *config) { config->beginGroup("FileTransmit"); - config->setValue("BeforeSendText", QVariant(ui.beforeSendEdit->toPlainText())); - config->setValue("BeforeSend", QVariant(ui.enableBerforSendBox->isChecked())); - config->setValue("FileName", QVariant(ui.pathBox->text())); - config->setValue("Protocol", QVariant(ui.protocolBox->currentText())); - config->setValue("SendMode", QVariant(ui.sendButton->isChecked())); + config->setValue("BeforeSendText", QVariant(ui->beforeSendEdit->toPlainText())); + config->setValue("BeforeSend", QVariant(ui->enableBerforSendBox->isChecked())); + config->setValue("FileName", QVariant(ui->pathBox->text())); + config->setValue("Protocol", QVariant(ui->protocolBox->currentText())); + config->setValue("SendMode", QVariant(ui->sendButton->isChecked())); config->endGroup(); } @@ -53,13 +63,13 @@ void FileTransferView::saveConfig(QSettings *config) void FileTransferView::browseButtonClicked() { QString fname; - if (ui.sendButton->isChecked()) { - fname = QFileDialog::getOpenFileName(this, "Open File", ui.pathBox->text()); + if (ui->sendButton->isChecked()) { + fname = QFileDialog::getOpenFileName(this, "Open File", ui->pathBox->text()); } else { - fname = QFileDialog::getSaveFileName(this, "Open File", ui.pathBox->text()); + fname = QFileDialog::getSaveFileName(this, "Open File", ui->pathBox->text()); } if (!fname.isEmpty()) { // 文件名有效 - ui.pathBox->setText(fname); + ui->pathBox->setText(fname); } } @@ -71,9 +81,9 @@ void FileTransferView::sendFile() FileThread::SendMode, FileThread::ReceiveMode }; - QFile file(ui.pathBox->text()); + QFile file(ui->pathBox->text()); - if (ui.sendButton->isChecked()) { // 发送模式要求文件可以以只读方式打开 + if (ui->sendButton->isChecked()) { // 发送模式要求文件可以以只读方式打开 res = file.open(QFile::ReadOnly); if (res) { file.close(); @@ -85,19 +95,19 @@ void FileTransferView::sendFile() } } if (res) { - thread.setFileName(ui.pathBox->text()); + thread.setFileName(ui->pathBox->text()); thread.setProtocol(FileThread::XModem); - thread.setTransMode(mode[!ui.sendButton->isChecked()]); + thread.setTransMode(mode[!ui->sendButton->isChecked()]); beforceSend(); // 预发送文本 - thread.startTransfer(); - ui.startButton->setEnabled(false); - ui.stopButton->setEnabled(true); + thread.startTransmit(); + ui->startButton->setEnabled(false); + ui->stopButton->setEnabled(true); QString string(tr("Start transmit file: \"") - + ui.pathBox->text() + "\"."); + + ui->pathBox->text() + "\"."); logOut(string, Qt::blue); } else { // 无法打开文件 QString string(tr("Can not open the file: \"") - + ui.pathBox->text() + "\".\n"); + + ui->pathBox->text() + "\".\n"); logOut(tr("Error: ") + string, Qt::red); QMessageBox err(QMessageBox::Critical, @@ -114,7 +124,7 @@ void FileTransferView::portSendData(const QByteArray &array) QString string; emit sendData(array); - ui.progressBar->setValue(thread.progress()); + ui->progressBar->setValue(thread.progress()); } // 接收数据 @@ -126,11 +136,10 @@ void FileTransferView::readData(const QByteArray &array) // 取消发送 void FileTransferView::cancelTransfer() { - if (thread.cancelTransfer()) { - logOut(tr("Cancel transfer.\n"), Qt::darkGray); - ui.startButton->setEnabled(true); - ui.stopButton->setEnabled(false); - } + thread.cancelTransmit(); + logOut(tr("Cancel transfer.\n"), Qt::darkGray); + ui->startButton->setEnabled(true); + ui->stopButton->setEnabled(false); } // 显示一条log @@ -138,15 +147,15 @@ void FileTransferView::logOut(const QString &string, QColor color) { QString time = QDateTime::currentDateTime().toString("hh:mm:ss"); - ui.textEdit->setTextColor(color); - ui.textEdit->append("[" + time + "] " + string); + ui->textEdit->setTextColor(color); + ui->textEdit->append("[" + time + "] " + string); } // 传输完成槽 void FileTransferView::onTransFinsh() { - ui.startButton->setEnabled(true); - ui.stopButton->setEnabled(false); + ui->startButton->setEnabled(true); + ui->stopButton->setEnabled(false); logOut(tr("Transmit finished.\n"), Qt::darkGreen); } @@ -154,10 +163,24 @@ void FileTransferView::onTransFinsh() void FileTransferView::beforceSend() { // 只有在发送模式下才可以使用预发送模式 - if (ui.sendButton->isChecked() && ui.enableBerforSendBox->isChecked()) { + if (ui->sendButton->isChecked() && ui->enableBerforSendBox->isChecked()) { QTextCodec *code = QTextCodec::codecForName("GB-2312"); - QByteArray arr = code->fromUnicode(ui.beforeSendEdit->toPlainText()); + QByteArray arr = code->fromUnicode(ui->beforeSendEdit->toPlainText()); emit sendData(arr); } } + +void FileTransferView::onTimeoutError() +{ + QString string(tr("Transmission timeout.")); + + ui->startButton->setEnabled(true); + ui->stopButton->setEnabled(false); + logOut(tr("Error: ") + string, Qt::red); + QMessageBox err(QMessageBox::Critical, + tr("Error"), + string, + QMessageBox::Cancel, this); + err.exec(); +} diff --git a/SerialTool/source/main.cpp b/SerialTool/source/main.cpp index 57a5a4a..77d3ba1 100644 --- a/SerialTool/source/main.cpp +++ b/SerialTool/source/main.cpp @@ -1,11 +1,11 @@ -#include "serialtool.h" +#include "mainwindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); - SerialTool w; + MainWindow w; w.show(); return a.exec(); diff --git a/SerialTool/source/mainwindow.cpp b/SerialTool/source/mainwindow.cpp new file mode 100644 index 0000000..99bbbe9 --- /dev/null +++ b/SerialTool/source/mainwindow.cpp @@ -0,0 +1,628 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include +#include +#include +#include +#include +#include +#include +#include "portsetbox.h" +#include "optionsbox.h" +#include "aboutbox.h" +#include "version.h" +#include "tcpudpport.h" +#include "defaultconfig.h" +#include "serialport.h" +#include "valuedisplay.h" +#include "vediobox.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + QString configPath(QStandardPaths::writableLocation( + QStandardPaths::AppConfigLocation) + "/m_config.ini"); + syncDefaultConfig(configPath); + m_config = new QSettings(configPath, QSettings::IniFormat); + + ui->setupUi(this); + setWindowTitle(SOFTWARE_NAME " V" SOFTWARE_VERSION); + + // 互斥动作 + m_tabActionGroup = new QActionGroup(this); + m_tabActionGroup->addAction(ui->actionVisibleTab0); + m_tabActionGroup->addAction(ui->actionVisibleTab1); + m_tabActionGroup->addAction(ui->actionVisibleTab2); + + m_serialPort = new SerialPort(this); + m_tcpUdpPort = new TcpUdpPort(this); + ui->toolBar1->insertWidget(ui->portSetAction, m_tcpUdpPort); + ui->toolBar1->insertWidget(ui->portSetAction, m_serialPort); + + m_rxCount = 0; + m_txCount = 0; + // 状态栏设置 + m_rxCntLabel = new QLabel("RX: 0Bytes", this); + m_txCntLabel = new QLabel("TX: 0Bytes", this); + m_portInfoLabel = new QLabel("", this); + m_rxCntLabel->setMinimumWidth(120); + m_txCntLabel->setMinimumWidth(120); + m_portInfoLabel->setMinimumWidth(120); + ui->statusBar->addWidget(m_portInfoLabel); + ui->statusBar->addWidget(m_rxCntLabel); + ui->statusBar->addWidget(m_txCntLabel); + + loadConfig(); // 加载配置 + + // create connection between axes and scroll bars: + connect(ui->portRunAction, SIGNAL(triggered()), this, SLOT(changeRunFlag())); + connect(ui->portSwitchAction, SIGNAL(triggered()), this, SLOT(onPortSwitchActionTriggered())); + connect(ui->terminal, &TerminalView::sendDataRequest, this, &MainWindow::writePort); + connect(ui->clearAction, SIGNAL(triggered()), this, SLOT(cleanData())); + QObject::connect(&m_timer, &QTimer::timeout, this, &MainWindow::onSecTimerTimeout); + connect(ui->portSetAction, SIGNAL(triggered()), this, SLOT(openSetPortInfoBox())); + connect(ui->actionOption, SIGNAL(triggered()), this, SLOT(setOptions())); + connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveFile())); + connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(openFile())); + connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(close())); + connect(ui->actionVisibleToolbar, SIGNAL(triggered(bool)), ui->toolBar1, SLOT(setVisible(bool))); + connect(ui->actionVisibleStatusBar, SIGNAL(triggered(bool)), ui->statusBar, SLOT(setVisible(bool))); + connect(ui->toolBar1, SIGNAL(visibilityChanged(bool)), ui->actionVisibleToolbar, SLOT(setChecked(bool))); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabIndexChanged(int))); + connect(m_tabActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(tabActionGroupTriggered(QAction*))); + connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); + connect(ui->actionWiki, SIGNAL(triggered()), this, SLOT(openWiki())); + connect(ui->fileTransfer, &FileTransferView::sendData, this, &MainWindow::writePort); + connect(ui->actionVedioBox, SIGNAL(triggered()), this, SLOT(onVedioBoxTriggered())); + connect(ui->actionValueDisplay, SIGNAL(triggered()), this, SLOT(onValueDisplayTriggered())); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); + connect(m_serialPort, SIGNAL(portChanged()), this, SLOT(dispPortStatus())); + connect(m_serialPort, SIGNAL(portError()), this, SLOT(closePort())); + connect(m_tcpUdpPort, SIGNAL(protocolChanged()), this, SLOT(dispPortStatus())); + connect(m_tcpUdpPort, SIGNAL(connectionError()), this, SLOT(closePort())); + connect(ui->actionStaysOnTop, SIGNAL(triggered()), this, SLOT(onStaysOnTopTriggered())); + + m_timer.start(1000); +} + +MainWindow::~MainWindow() +{ + delete ui; + delete m_config; + delete m_tabActionGroup; + delete m_tcpUdpPort; + delete m_rxCntLabel; + delete m_txCntLabel; + delete m_portInfoLabel; + delete m_serialPort; +} + +// 关闭事件 +void MainWindow::closeEvent(QCloseEvent *event) +{ + saveConfig(); + QMainWindow::closeEvent(event); +} + +// 加载语言 +void MainWindow::setLanguage(const QString &string) +{ + // 首先卸载翻译 + if (!m_translator.isEmpty()) { + for (int i = 0; i < m_translator.size(); ++i) { + qApp->removeTranslator(m_translator[i]); // 卸载翻译环境 + delete m_translator[i]; + } + m_translator.clear(); + } + // 遍历文件 + QDir dir("language/" + string); + foreach(QFileInfo mfi ,dir.entryInfoList()) { + if (mfi.isFile() && mfi.suffix() == "qm") { // 是翻译文件 + QTranslator* ts = new QTranslator; + ts->load(mfi.absoluteFilePath()); + qApp->installTranslator(ts); // 安装翻译环境 + m_translator.append(ts); + } + } + // 重新翻译界面 + ui->retranslateUi(this); + ui->terminal->retranslate(); + ui->oscPlot->retranslate(); + ui->fileTransfer->retranslate(); + m_tcpUdpPort->retranslate(); + m_serialPort->retranslate(); +} + +// 加载样式表 +void MainWindow::setStyleSheet(const QString &string) +{ + // 样式表 + QFile qss("themes/" + string + "/style.css"); + qss.open(QFile::ReadOnly); + qApp->setStyleSheet(qss.readAll()); + qss.close(); +} + +// 读取系统设置 +void MainWindow::loadSettings() +{ + // 系统设置 + m_config->beginGroup("Settings"); + + QString fontFamily("'" + + m_config->value("FontFamily").toString().replace("+", "','") + "'"); + QString fontStyle(m_config->value("FontStyle").toString()); + int fontSize = m_config->value("FontSize").toInt(); + fontSize = fontSize < 6 ? 10 : fontSize; + ui->terminal->setFontFamily(fontFamily, fontSize, fontStyle); + + ui->oscPlot->setBackground(QColor(m_config->value("PlotBackground").toString())); + ui->oscPlot->setGridColor(QColor(m_config->value("AxisColor").toString())); + // 绘制使用OpenGL加速 + ui->oscPlot->setUseOpenGL(m_config->value("UseOpenGL").toBool()); + // 绘制时抗锯齿 + ui->oscPlot->setUseAntialiased(m_config->value("UseAntialias").toBool()); + // 示波器刷新速度 + ui->oscPlot->setUpdateInterval(m_config->value("UpdateInterval").toInt()); + PortType type = (PortType)m_config->value("PortType").toInt(); + + // 窗口透明度 + int opacity = m_config->value("WindowOpacity").toInt(); + opacity = opacity < 30 ? 100 : opacity <= 100 ? opacity : 100; + setWindowOpacity(opacity / 100.0); + if (m_valueDisplay != NULL) { + m_valueDisplay->setWindowOpacity(windowOpacity()); + } + if (m_vedioBox != NULL) { + m_vedioBox->setWindowOpacity(windowOpacity()); + } + + // 语言设置 + setLanguage(m_config->value("Language").toString()); + setStyleSheet(m_config->value("Theme").toString()); + + m_config->endGroup(); + + if (type != m_portType) { + closePort(); // 端口改变时关闭之前的端口 + m_portType = type; + } + dispPortStatus(); // 更新端口状态显示 + loadPortTool(); +} + +// 控件数据初始化, 在构造函数中初始化各种控件的初始值 +void MainWindow::loadConfig() +{ + // 路经 + m_config->beginGroup("Path"); + m_docPath = m_config->value("DocumentPath").toString(); + m_config->endGroup(); + + // 串口设置 + m_serialPort->loadConfig(m_config); + + // TCP/UDP设置 + m_tcpUdpPort->loadConfig(m_config); + + // 打开页面配置 + m_config->beginGroup("Workspace"); + ui->tabWidget->setCurrentIndex(m_config->value("TabIndex").toInt()); + setTabActionIndex(ui->tabWidget->currentIndex()); + ui->toolBar1->setVisible(m_config->value("ToolBarVisible").toBool()); + ui->actionVisibleToolbar->setChecked(ui->toolBar1->isVisible()); + ui->statusBar->setVisible(m_config->value("StatusBarVisible").toBool()); + // 这里如果直接速读取ui->statusBar->isVisible()会是false,原因不明 + ui->actionVisibleStatusBar->setChecked(m_config->value("StatusBarVisible").toBool()); + setWindowStaysOnTop(m_config->value("WindowStaysOnTop").toBool()); + m_config->endGroup(); + + // 调试终端配置 + ui->terminal->loadConfig(m_config); + + // 串口示波器 + ui->oscPlot->loadConfig(m_config); + + // 读取文件传输功能的设置 + ui->fileTransfer->loadConfig(m_config); + + // 最后读取系统设置 + loadSettings(); +} + +// 保存配置 +void MainWindow::saveConfig() +{ + // 保存串口设置 + m_serialPort->saveConfig(m_config); + + // 保存TCP/UDP设置 + m_tcpUdpPort->saveConfig(m_config); + + // 打开页面配置 + m_config->beginGroup("Workspace"); + m_config->setValue("TabIndex", + QVariant(ui->tabWidget->currentIndex())); + m_config->setValue("ToolBarVisible", QVariant(ui->toolBar1->isVisible())); + m_config->setValue("StatusBarVisible", QVariant(ui->statusBar->isVisible())); + m_config->setValue("WindowStaysOnTop", QVariant(windowFlags() & Qt::WindowStaysOnTopHint)); + m_config->endGroup(); + + // 调试终端配置 + ui->terminal->saveConfig(m_config); + // 串口示波器 + ui->oscPlot->saveConfig(m_config); + + // 路经 + m_config->beginGroup("Path"); + m_config->setValue("DocumentPath", QVariant(m_docPath)); + m_config->endGroup(); + + // 文件传输配置 + ui->fileTransfer->saveConfig(m_config); +} + +void MainWindow::setOptions() +{ + OptionsBox option(this); + option.exec(); +} + +// 保存文件 +void MainWindow::saveFile() +{ + QString filter; + QString fname = QFileDialog::getSaveFileName(this, tr("Save"), m_docPath, + tr("Portable Network Graphic Format (*.png)") + ";;" + + tr("Bitmap (*.bmp)") + ";;" + + tr("Wave Plain Text File (*.txt)") + ";;" + + tr("Terminal Text File (*.txt)"), &filter, + QFileDialog::HideNameFilterDetails); + if (fname.isNull()) { + return; + } + m_docPath = QFileInfo(fname).path(); + if (filter == tr("Portable Network Graphic Format (*.png)")) { + ui->oscPlot->savePng(fname); + } else if (filter == tr("Bitmap (*.bmp)")) { + ui->oscPlot->saveBmp(fname); + } else if (filter == tr("Wave Plain Text File (*.txt)")) { + ui->oscPlot->saveWave(fname); + } else if (filter == tr("Terminal Text File (*.txt)")) { + ui->terminal->saveText(fname); + } +} + +// 打开文件 +void MainWindow::openFile() +{ + QString filter; + QString fname = QFileDialog::getOpenFileName(this, tr("Open"), m_docPath, + tr("Wave Plain Text File (*.txt)"), &filter, + QFileDialog::HideNameFilterDetails); + if (fname.isNull()) { + return; + } + m_docPath = QFileInfo(fname).path(); + if (filter.indexOf("(*.txt)", 0) != -1) { + ui->oscPlot->loadWave(fname); + } +} + +void MainWindow::tabIndexChanged(int index) +{ + setTabActionIndex(index); + if (index == 0) { // terminal + if (m_runFlag) { // 暂停按钮没有按下时继续发送 + ui->terminal->setPaused(false); + } + } else { // 其他选项卡下暂停发送 + ui->terminal->setPaused(true); + } +} + +void MainWindow::setTabActionIndex(int index) +{ + switch (index) { + case 0: + ui->actionVisibleTab0->setChecked(true); + break; + case 1: + ui->actionVisibleTab1->setChecked(true); + break; + case 2: + ui->actionVisibleTab2->setChecked(true); + break; + default: + ui->actionVisibleTab0->setChecked(true); + break; + } +} + +void MainWindow::tabActionGroupTriggered(QAction *action) +{ + if (action == ui->actionVisibleTab0) { + ui->tabWidget->setCurrentIndex(0); + } else if (action == ui->actionVisibleTab1) { + ui->tabWidget->setCurrentIndex(1); + } else if (action == ui->actionVisibleTab2) { + ui->tabWidget->setCurrentIndex(2); + } +} + +void MainWindow::changeRunFlag() +{ + if (m_runFlag == true) { + m_runFlag = false; + QIcon icon(":/SerialTool/images/start.ico"); + ui->portRunAction->setIcon(icon); + ui->portRunAction->setText(tr("Start Tx/Rx")); + ui->terminal->setPaused(true); // terminal transmission pause + ui->oscPlot->stop(); + } else { + m_runFlag = true; + QIcon icon(":/SerialTool/images/pause.ico"); + ui->portRunAction->setIcon(icon); + ui->portRunAction->setText(tr("Pause Tx/Rx")); + ui->terminal->setPaused(false); // terminal transmission continue + if (ui->tabWidget->widget(ui->tabWidget->currentIndex()) == ui->tabOsc) { + ui->oscPlot->start(); + } + } +} + +// 状态栏显示端口状态 +void MainWindow::dispPortStatus() +{ + bool status = false; + QString string; + QPalette palette; + + if (m_portType == ComPort) { + status = m_serialPort->portStatus(string); + } else if (m_portType == NetworkPort) { + status = m_tcpUdpPort->portStatus(string); + } + palette.setColor(QPalette::WindowText, status ? Qt::darkGreen : Qt::red); + m_portInfoLabel->setText(string); + m_portInfoLabel->setPalette(palette); +} + +// 秒定时器溢出槽函数 +void MainWindow::onSecTimerTimeout() +{ + QString str; + + // 更新显示信息 + str = "RX: " + QString::number(m_rxCount) + "Bytes"; + m_rxCntLabel->setText(str); + str = "TX: " + QString::number(m_txCount) + "Bytes"; + m_txCntLabel->setText(str); +} + +// 打开串口端口 +bool MainWindow::openComPort() +{ + if (m_serialPort->open()) { + connect(m_serialPort, &SerialPort::readyRead, this, &MainWindow::readPortData); + return true; + } + return false; +} + +// 打开TCP/UDP端口 +bool MainWindow::openTcpUdpPort() +{ + if (m_tcpUdpPort->open()) { + connect(m_tcpUdpPort, &TcpUdpPort::readyRead, this, &MainWindow::readPortData); + return true; + } + return false; +} + +// 打开端口 +void MainWindow::openPort() +{ + bool status = false; + + if (m_portType == ComPort) { + status = openComPort(); + } else if (m_portType == NetworkPort) { + status = openTcpUdpPort(); + } + if (status) { + QIcon icon(":/SerialTool/images/close.ico"); + ui->portSwitchAction->setIcon(icon); + ui->portSwitchAction->setText(tr("Close Port")); + ui->terminal->setEnabled(true); + ui->portRunAction->setEnabled(true); + if (m_runFlag && ui->tabWidget->widget(ui->tabWidget->currentIndex()) == ui->tabOsc) { + ui->oscPlot->start(); // 启动串口示波器 + } + dispPortStatus(); // 更新端口状态显示 + } +} + +void MainWindow::closePort() +{ + if (m_serialPort->isOpen()) { + m_serialPort->close(); // 关闭串口 + } + if (m_tcpUdpPort->isOpen()) { + m_tcpUdpPort->close(); + } + ui->oscPlot->stop(); // 串口示波器结束运行 + QIcon icon(":/SerialTool/images/connect.ico"); + ui->portSwitchAction->setIcon(icon); + ui->portSwitchAction->setText(tr("Open Port")); + ui->terminal->setEnabled(false); + ui->portRunAction->setEnabled(false); + dispPortStatus(); // 更新端口状态显示 +} + +// 打开串口槽函数 +void MainWindow::onPortSwitchActionTriggered() +{ + if (ui->portRunAction->isEnabled() == true) { // 现在需要关闭端口 + closePort(); + } else { // 端口关闭时打开端口 + openPort(); + } +} + +// 打开串口设置对话框 +void MainWindow::openSetPortInfoBox() +{ + m_serialPort->portSetDialog(); +} + +//读取接收到的数据 +void MainWindow::readPortData() +{ + // 读取串口数据 + if (!m_runFlag) { + return; + } + QByteArray buf; + if (m_portType == ComPort) { + buf = m_serialPort->readAll(); // 读取串口数据 + } else if (m_portType == NetworkPort) { + buf = m_tcpUdpPort->readAll(); // 读取TCP/UDP数据 + } + m_rxCount += buf.length(); // 接收计数 + if (!buf.isEmpty()) { + if (ui->tabWidget->currentIndex() == 0) { // 串口调试助手 + ui->terminal->append(buf); + } + // 串口示波器接收数据 + if (ui->tabWidget->currentIndex() == 1 || ui->oscPlot->holdReceive()) { + ui->oscPlot->append(buf); + } + // 串口文件传输 + if (ui->tabWidget->currentIndex() == 2) { + ui->fileTransfer->readData(buf); + } + if (m_vedioBox != NULL) { + m_vedioBox->append(buf); + } + if (m_valueDisplay != NULL) { + m_valueDisplay->append(buf); + } + } + buf.clear(); +} + +// 向端口发送数据,带参数 +void MainWindow::writePort(const QByteArray &array) +{ + m_txCount += array.length(); // 发送计数 + if (m_portType == ComPort) { + m_serialPort->write(array); + } else if (m_portType == NetworkPort) { + m_tcpUdpPort->write(array); + } +} + +void MainWindow::cleanData() +{ + switch (ui->tabWidget->currentIndex()) { + case 0: // 串口调试助手 + ui->terminal->clear(); + break; + case 1: + ui->oscPlot->clear(); + break; + } + // 计数清零 + m_rxCount = 0; + m_txCount = 0; +} + +void MainWindow::about() +{ + AboutBox aboutBox(this); + + aboutBox.exec(); +} + +void MainWindow::onValueDisplayTriggered() +{ + if (m_valueDisplay == NULL) { + m_valueDisplay = new ValueDisplay(this); + m_valueDisplay->setModal(false); + m_valueDisplay->setAttribute(Qt::WA_DeleteOnClose); + m_valueDisplay->setWindowOpacity(windowOpacity()); + connect(m_valueDisplay, SIGNAL(destroyed()), this, SLOT(onValueDisplayDelete())); + m_valueDisplay->show(); + } +} + +void MainWindow::onValueDisplayDelete() +{ + m_valueDisplay = NULL; +} + +void MainWindow::loadPortTool() +{ + if (m_portType == ComPort) { + m_serialPort->setVisibleWidget(true); + ui->portSetAction->setVisible(true); + m_tcpUdpPort->setVisibleWidget(false); + } else if (m_portType == NetworkPort) { + m_serialPort->setVisibleWidget(false); + ui->portSetAction->setVisible(false); + m_tcpUdpPort->setVisibleWidget(true); + } +} + +void MainWindow::onVedioBoxTriggered() +{ + if (m_vedioBox == NULL) { // 当对话框没有创建时创建 + m_vedioBox = new VedioBox(this); + connect(m_vedioBox, SIGNAL(destroyed()), this, SLOT(onVedioBoxDelete())); + m_vedioBox->setModal(false); // 非模态对话框 + m_vedioBox->setAttribute(Qt::WA_DeleteOnClose); + m_vedioBox->setWindowOpacity(windowOpacity()); + m_vedioBox->setFilePath(m_docPath); + m_vedioBox->show(); + } +} + +void MainWindow::onVedioBoxDelete() +{ + m_vedioBox = NULL; +} + +void MainWindow::setWindowStaysOnTop(bool enabled) +{ + Qt::WindowFlags flags = enabled ? + Qt::WindowStaysOnTopHint : Qt::Window; + QString str = enabled ? ":/SerialTool/images/pin_down.ico" + : ":/SerialTool/images/pin_up.ico"; + + hide(); + setWindowFlags(flags); + ui->actionStaysOnTop->setIcon(QIcon(str)); + show(); +} + +void MainWindow::onStaysOnTopTriggered() +{ + setWindowStaysOnTop(!(windowFlags() & Qt::WindowStaysOnTopHint)); +} + +void MainWindow::openWiki() +{ + QDesktopServices::openUrl(QUrl("https://github.com/Le-Seul/Serial/wiki")); +} + +void MainWindow::currentTabChanged(int index) +{ + if (m_runFlag && ui->tabWidget->widget(index) == ui->tabOsc) { // 只有在串口示波器选项卡下面才会启动示波器 + ui->oscPlot->start(); + } else { + ui->oscPlot->stop(); + } +} diff --git a/SerialTool/source/optionsbox.cpp b/SerialTool/source/optionsbox.cpp index 063c4fd..634cf7b 100644 --- a/SerialTool/source/optionsbox.cpp +++ b/SerialTool/source/optionsbox.cpp @@ -1,11 +1,13 @@ #include "optionsbox.h" +#include "ui_optionsbox.h" #include #include #include #include #include #include -#include "serialtool.h" +#include +#include "mainwindow.h" static QString languageName(const QString &path) { @@ -48,50 +50,52 @@ static void scanThemesPath(const QString &path, QComboBox *comboBox) } } -OptionsBox::OptionsBox(SerialTool *parent) : QDialog(parent) +OptionsBox::OptionsBox(MainWindow *parent) : + QDialog(parent), + ui(new Ui::OptionsBox) { // 不显示问号 Qt::WindowFlags flags = Qt::Dialog; flags |= Qt::WindowCloseButtonHint; setWindowFlags(flags); - ui.setupUi(this); + ui->setupUi(this); setFixedSize(400, 300); // 不能伸缩的对话框 - serialTool = parent; + m_parent = parent; - scanLanguagePath("language", languageList, ui.languageBox); - scanThemesPath("themes", ui.themeBox); + scanLanguagePath("language", languageList, ui->languageBox); + scanThemesPath("themes", ui->themeBox); loadCommand(); setup(); // 配置界面初始化 - connect(ui.fontAnsiSetButton, SIGNAL(clicked()), this, SLOT(setTextFontAnsi())); - connect(ui.fontMultiSetButton, SIGNAL(clicked()), this, SLOT(setTextFontMulti())); - connect(ui.rxColorButton, SIGNAL(clicked()), this, SLOT(setRxFontColor())); - connect(ui.txColorButton, SIGNAL(clicked()), this, SLOT(setTxFontColor())); - connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), + connect(ui->fontAnsiSetButton, SIGNAL(clicked()), this, SLOT(setTextFontAnsi())); + connect(ui->fontMultiSetButton, SIGNAL(clicked()), this, SLOT(setTextFontMulti())); + connect(ui->rxColorButton, SIGNAL(clicked()), this, SLOT(setRxFontColor())); + connect(ui->txColorButton, SIGNAL(clicked()), this, SLOT(setTxFontColor())); + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(processOptions(QAbstractButton *))); - connect(ui.plotBgColorButton, SIGNAL(clicked()), this, SLOT(setPlotBackgroundColor())); - connect(ui.axisColorButton, SIGNAL(clicked()), this, SLOT(setAxisColor())); - connect(ui.cmdNew, SIGNAL(clicked()), this, SLOT(onCmdNewClick())); - connect(ui.cmdEdit, SIGNAL(clicked()), this, SLOT(onCmdEditClick())); - connect(ui.cmdDelete, SIGNAL(clicked()), this, SLOT(onCmdDeleteClick())); - connect(ui.cmdList, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(setCmdItemColor())); - connect(ui.languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setLanguage(int))); - connect(ui.useOpenGLBox, SIGNAL(clicked(bool)), this, SLOT(onUseOpenGLClick(bool))); - connect(ui.opacitySlider, SIGNAL(valueChanged(int)), this, SLOT(onOpacitySilderChanged(int))); - connect(ui.opacitySpinBox, SIGNAL(editingFinished()), this, SLOT(onOpacitySpinBoxEdited())); + connect(ui->plotBgColorButton, SIGNAL(clicked()), this, SLOT(setPlotBackgroundColor())); + connect(ui->axisColorButton, SIGNAL(clicked()), this, SLOT(setAxisColor())); + connect(ui->cmdNew, SIGNAL(clicked()), this, SLOT(onCmdNewClick())); + connect(ui->cmdEdit, SIGNAL(clicked()), this, SLOT(onCmdEditClick())); + connect(ui->cmdDelete, SIGNAL(clicked()), this, SLOT(onCmdDeleteClick())); + connect(ui->cmdList, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(setCmdItemColor())); + connect(ui->languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setLanguage(int))); + connect(ui->useOpenGLBox, SIGNAL(clicked(bool)), this, SLOT(onUseOpenGLClick(bool))); + connect(ui->opacitySlider, SIGNAL(valueChanged(int)), this, SLOT(onOpacitySilderChanged(int))); + connect(ui->opacitySpinBox, SIGNAL(editingFinished()), this, SLOT(onOpacitySpinBoxEdited())); } OptionsBox::~OptionsBox() { - + delete ui; } // 初始化设置 void OptionsBox::setup() { - QSettings *config = serialTool->getConfig(); + QSettings *config = m_parent->getConfig(); // 字体和颜色设置 config->beginGroup("Settings"); @@ -103,42 +107,42 @@ void OptionsBox::setup() txColor = config->value("TransmitTextColor").toString(); bgColor = config->value("PlotBackground").toString(); axColor = config->value("AxisColor").toString(); - ui.opacitySlider->setValue(config->value("WindowOpacity").toInt()); - ui.opacitySpinBox->setValue(ui.opacitySlider->value()); - ui.useOpenGLBox->setChecked(config->value("UseOpenGL").toBool()); - ui.useAntiBox->setChecked(config->value("UseAntialias").toBool()); - ui.updateIntervalBox->setValue(config->value("UpdateInterval").toInt()); - ui.portTypeBox->setCurrentIndex(config->value("PortType").toInt()); + ui->opacitySlider->setValue(config->value("WindowOpacity").toInt()); + ui->opacitySpinBox->setValue(ui->opacitySlider->value()); + ui->useOpenGLBox->setChecked(config->value("UseOpenGL").toBool()); + ui->useAntiBox->setChecked(config->value("UseAntialias").toBool()); + ui->updateIntervalBox->setValue(config->value("UpdateInterval").toInt()); + ui->portTypeBox->setCurrentIndex(config->value("PortType").toInt()); language = config->value("Language").toString(); theme = config->value("Theme").toString(); config->endGroup(); if (!fontFamily.isEmpty()) { - ui.lineEditFontAnsi->setText(fontFamily.section(",", 0, 0).trimmed() + ui->lineEditFontAnsi->setText(fontFamily.section(",", 0, 0).trimmed() + "," + fontStyle + "," + QString::number(fontSize)); - ui.lineEditFontMulti->setText(fontFamily.section(",", 1, 1).trimmed()); + ui->lineEditFontMulti->setText(fontFamily.section(",", 1, 1).trimmed()); } - ui.lineEditRxColor->setText(rxColor); - ui.lineEditTxColor->setText(txColor); - ui.lineEditPlotColor->setText(bgColor); - ui.lineEditAxisColor->setText(axColor); + ui->lineEditRxColor->setText(rxColor); + ui->lineEditTxColor->setText(txColor); + ui->lineEditPlotColor->setText(bgColor); + ui->lineEditAxisColor->setText(axColor); - ui.languageBox->setCurrentText(languageName("language/" + language)); - ui.themeBox->setCurrentText(theme); + ui->languageBox->setCurrentText(languageName("language/" + language)); + ui->themeBox->setCurrentText(theme); // 使用OpenGL时不能使用抗锯齿 - if (ui.useOpenGLBox->isChecked()) { - ui.useAntiBox->setEnabled(false); + if (ui->useOpenGLBox->isChecked()) { + ui->useAntiBox->setEnabled(false); } } // 保存配置 void OptionsBox::processOptions(QAbstractButton *button) { - QDialogButtonBox::StandardButton btn = ui.buttonBox->standardButton(button); + QDialogButtonBox::StandardButton btn = ui->buttonBox->standardButton(button); if (btn == QDialogButtonBox::Ok || btn == QDialogButtonBox::Apply) { - QSettings *config = serialTool->getConfig(); + QSettings *config = m_parent->getConfig(); // 字体和颜色设置 config->beginGroup("Settings"); fontFamily.replace(",", "+"); @@ -150,17 +154,17 @@ void OptionsBox::processOptions(QAbstractButton *button) config->setValue("TransmitTextColor", QVariant(txColor)); config->setValue("PlotBackground", QVariant(bgColor)); config->setValue("AxisColor", QVariant(axColor)); - config->setValue("WindowOpacity", QVariant(ui.opacitySpinBox->value())); - config->setValue("UseOpenGL", QVariant(ui.useOpenGLBox->isChecked())); - config->setValue("UseAntialias", QVariant(ui.useAntiBox->isChecked())); - config->setValue("UpdateInterval", QVariant(ui.updateIntervalBox->value())); - config->setValue("PortType", QVariant(ui.portTypeBox->currentIndex())); + config->setValue("WindowOpacity", QVariant(ui->opacitySpinBox->value())); + config->setValue("UseOpenGL", QVariant(ui->useOpenGLBox->isChecked())); + config->setValue("UseAntialias", QVariant(ui->useAntiBox->isChecked())); + config->setValue("UpdateInterval", QVariant(ui->updateIntervalBox->value())); + config->setValue("PortType", QVariant(ui->portTypeBox->currentIndex())); config->setValue("Language", QVariant(language)); - config->setValue("Theme", QVariant(ui.themeBox->currentText())); + config->setValue("Theme", QVariant(ui->themeBox->currentText())); config->endGroup(); saveCommand(); // 保存命令 - serialTool->loadSettings(); // 配置生效 - ui.retranslateUi(this); + m_parent->loadSettings(); // 配置生效 + ui->retranslateUi(this); setup(); // 重新初始化OptionBox设置 } } @@ -185,7 +189,7 @@ void OptionsBox::setTextFontAnsi() } else { fontStyle = "normal"; } - ui.lineEditFontAnsi->setText(font.family() + ui->lineEditFontAnsi->setText(font.family() + "," + fontStyle + "," + QString::number(fontSize)); } } @@ -200,7 +204,7 @@ void OptionsBox::setTextFontMulti() if (ok) { fontFamily = fontFamily.section(',', 0, 0).trimmed() + "," + font.family(); - ui.lineEditFontMulti->setText(font.family()); + ui->lineEditFontMulti->setText(font.family()); } } @@ -210,7 +214,7 @@ void OptionsBox::setRxFontColor() if (color.isValid()) { rxColor = color.name(); - ui.lineEditRxColor->setText(rxColor); + ui->lineEditRxColor->setText(rxColor); } } @@ -220,7 +224,7 @@ void OptionsBox::setTxFontColor() if (color.isValid()) { txColor = color.name(); - ui.lineEditTxColor->setText(txColor); + ui->lineEditTxColor->setText(txColor); } } @@ -230,7 +234,7 @@ void OptionsBox::setPlotBackgroundColor() if (color.isValid()) { bgColor = color.name(); - ui.lineEditPlotColor->setText(bgColor); + ui->lineEditPlotColor->setText(bgColor); } } @@ -240,7 +244,7 @@ void OptionsBox::setAxisColor() if (color.isValid()) { axColor = color.name(); - ui.lineEditAxisColor->setText(axColor); + ui->lineEditAxisColor->setText(axColor); } } @@ -250,42 +254,42 @@ void OptionsBox::onCmdNewClick() // 设置新建项为可以编辑的项目 item->setFlags(item->flags() | Qt::ItemIsEditable); - ui.cmdList->addItem(item); - ui.cmdList->setCurrentItem(item); + ui->cmdList->addItem(item); + ui->cmdList->setCurrentItem(item); setCmdItemColor(); // 上色 } void OptionsBox::onCmdEditClick() { - QListWidgetItem *item = ui.cmdList->currentItem(); + QListWidgetItem *item = ui->cmdList->currentItem(); if (item) { - ui.cmdList->editItem(item); + ui->cmdList->editItem(item); } } void OptionsBox::onCmdDeleteClick() { - delete ui.cmdList->currentItem(); + delete ui->cmdList->currentItem(); setCmdItemColor(); // 上色 } void OptionsBox::onUseOpenGLClick(bool status) { - ui.useAntiBox->setEnabled(!status); + ui->useAntiBox->setEnabled(!status); } void OptionsBox::setCmdItemColor() { - int i, count = ui.cmdList->count(); + int i, count = ui->cmdList->count(); QRegExp regExp("^[_A-Za-z][_0-9A-Za-z]{0,}$"); // 匹配正确的命令名格式 for (i = 0; i < count; ++i) { QColor color; - QListWidgetItem *item = ui.cmdList->item(i); + QListWidgetItem *item = ui->cmdList->item(i); QString str = item->text(); if (!str.isEmpty() && (!regExp.exactMatch(str) - || ui.cmdList->findItems(str, Qt::MatchExactly).count() > 1)) { + || ui->cmdList->findItems(str, Qt::MatchExactly).count() > 1)) { color = QColor(0xFF7000); } else { color = i & 0x01 ? QColor(0xD6F3FF) : QColor(0xBDECFF); @@ -310,13 +314,13 @@ void OptionsBox::loadCommand() if (!str.isEmpty()) { QListWidgetItem *item = new QListWidgetItem(str); item->setFlags(item->flags() | Qt::ItemIsEditable); - ui.cmdList->addItem(item); + ui->cmdList->addItem(item); } } file.close(); // 设置选中行 - if (ui.cmdList->count() > 0) { - ui.cmdList->setCurrentRow(0); + if (ui->cmdList->count() > 0) { + ui->cmdList->setCurrentRow(0); setCmdItemColor(); // 上色 } } @@ -324,12 +328,12 @@ void OptionsBox::loadCommand() void OptionsBox::onOpacitySilderChanged(int value) { - ui.opacitySpinBox->setValue(value); + ui->opacitySpinBox->setValue(value); } void OptionsBox::onOpacitySpinBoxEdited() { - ui.opacitySlider->setValue(ui.opacitySpinBox->value()); + ui->opacitySlider->setValue(ui->opacitySpinBox->value()); } void OptionsBox::saveCommand() @@ -338,11 +342,11 @@ void OptionsBox::saveCommand() (QStandardPaths::AppConfigLocation) + "/keywords"); if (file.open(QIODevice::Text | QIODevice::WriteOnly)) { - int i, count = ui.cmdList->count(); + int i, count = ui->cmdList->count(); QTextStream text(&file); for (i = 0; i < count; ++i) { - QString str = ui.cmdList->item(i)->text(); + QString str = ui->cmdList->item(i)->text(); // 不是空行就插入 if (!str.isEmpty()) { text << str << '\n'; // 写入文件 diff --git a/SerialTool/source/oscilloscope.cpp b/SerialTool/source/oscilloscope.cpp index bb14632..00a095a 100644 --- a/SerialTool/source/oscilloscope.cpp +++ b/SerialTool/source/oscilloscope.cpp @@ -1,4 +1,5 @@ #include "oscilloscope.h" +#include "ui_oscilloscope.h" #include #include #include @@ -7,9 +8,10 @@ #include #include #include +#include #include "channelitem.h" -#include "wavedecode.h" #include "oscopetimestamp.h" +#include "wavedecode.h" #include "pointdatabuffer.h" #define SCALE (1000.0 / _xRange) @@ -18,60 +20,64 @@ QT_CHARTS_USE_NAMESPACE Oscilloscope::Oscilloscope(QWidget *parent) : QWidget(parent), - m_chart(0) + ui(new Ui::Oscilloscope), + m_chart(0), + m_timer(new QTimer(this)), + m_decode(new WaveDecode) { m_chart = new QChart; - ui.setupUi(parent); + ui->setupUi(parent); - timeStamp = new OscopeTimeStamp(); + m_timeStamp = new OscopeTimeStamp(); m_xRange = 0; setupPlot(); listViewInit(); QRegExpValidator *pReg = new QRegExpValidator(QRegExp("^\\d{2,7}$")); - ui.xRangeBox->lineEdit()->setValidator(pReg); + ui->xRangeBox->lineEdit()->setValidator(pReg); - updataTimer.setInterval(25); + m_timer->setInterval(25); - connect(ui.horizontalScrollBar, &QAbstractSlider::sliderMoved, this, &Oscilloscope::horzScrollBarChanged); - connect(ui.yOffsetBox, static_cast + connect(ui->horizontalScrollBar, &QAbstractSlider::sliderMoved, this, &Oscilloscope::horzScrollBarChanged); + connect(ui->yOffsetBox, static_cast (&QDoubleSpinBox::valueChanged), this, &Oscilloscope::yOffsetChanged); - connect(ui.yRangeBox, static_cast + connect(ui->yRangeBox, static_cast (&QDoubleSpinBox::valueChanged), this, &Oscilloscope::yRangeChanged); - connect(ui.xRangeBox, &QComboBox::currentTextChanged, this, &Oscilloscope::xRangeChanged); - connect(&updataTimer, &QTimer::timeout, this, &Oscilloscope::timeUpdata); + connect(ui->xRangeBox, &QComboBox::currentTextChanged, this, &Oscilloscope::xRangeChanged); + connect(m_timer, &QTimer::timeout, this, &Oscilloscope::timeUpdata); clear(); } Oscilloscope::~Oscilloscope() { - delete timeStamp; + delete ui; + delete m_timeStamp; delete m_chart; } // 重新设置语言 void Oscilloscope::retranslate() { - ui.retranslateUi(this); + ui->retranslateUi(this); } -// load settings +// load config void Oscilloscope::loadConfig(QSettings *config) { config->beginGroup("Oscillograph"); QString xRange = config->value("XRange").toString(); double yRange = config->value("YRange").toDouble(); double yOffset = config->value("YOffset").toDouble(); - ui.xRangeBox->setCurrentIndex(ui.xRangeBox->findText(xRange)); - ui.xRangeBox->setCurrentText(xRange); - ui.yRangeBox->setValue(yRange); - ui.yOffsetBox->setValue(yOffset); + ui->xRangeBox->setCurrentIndex(ui->xRangeBox->findText(xRange)); + ui->xRangeBox->setCurrentText(xRange); + ui->yRangeBox->setValue(yRange); + ui->yOffsetBox->setValue(yOffset); xRangeChanged(xRange); yRangeChanged(yRange); yOffsetChanged(yOffset); - ui.holdReceiveBox->setChecked(config->value("HoldReceive").toBool()); + ui->holdReceiveBox->setChecked(config->value("HoldReceive").toBool()); // load channels settings config->beginReadArray("Channels"); for (int i = 0; i < CH_NUM; ++i) { @@ -86,14 +92,14 @@ void Oscilloscope::loadConfig(QSettings *config) config->endGroup(); } -// save settings +// save config void Oscilloscope::saveConfig(QSettings *config) { config->beginGroup("Oscillograph"); - config->setValue("YOffset", QVariant(ui.yOffsetBox->value())); - config->setValue("YRange", QVariant(ui.yRangeBox->value())); - config->setValue("XRange", QVariant(ui.xRangeBox->currentText())); - config->setValue("HoldReceive", QVariant(ui.holdReceiveBox->isChecked())); + config->setValue("YOffset", QVariant(ui->yOffsetBox->value())); + config->setValue("YRange", QVariant(ui->yRangeBox->value())); + config->setValue("XRange", QVariant(ui->xRangeBox->currentText())); + config->setValue("HoldReceive", QVariant(ui->holdReceiveBox->isChecked())); // save channels settings config->beginWriteArray("Channels"); for (int i = 0; i < CH_NUM; ++i) { @@ -108,7 +114,7 @@ void Oscilloscope::saveConfig(QSettings *config) // 初始化示波器界面 void Oscilloscope::setupPlot() { - ui.chartView->setChart(m_chart); + ui->chartView->setChart(m_chart); m_chart->createDefaultAxes(); QValueAxis *xAxis = new QValueAxis; QValueAxis *yAxis = new QValueAxis; @@ -136,35 +142,41 @@ void Oscilloscope::setupPlot() // 通道列表初始化 void Oscilloscope::listViewInit() { - ui.channelList->setModelColumn(2); // 两列 + ui->channelList->setModelColumn(2); // 两列 for (int i = 0; i < CH_NUM; ++i) { QListWidgetItem *item = new QListWidgetItem; - ui.channelList->addItem(item); + ui->channelList->addItem(item); ChannelItem *chItem = new ChannelItem("CH" + QString::number(i + 1)); - ui.channelList->setItemWidget(item, chItem); + ui->channelList->setItemWidget(item, chItem); chItem->setChannel(i); channelStyleChanged(chItem); connect(chItem, &ChannelItem::changelChanged, this, &Oscilloscope::channelStyleChanged); } - ui.channelList->editItem(ui.channelList->item(0)); + ui->channelList->editItem(ui->channelList->item(0)); +} + +// 获取通道Widget +inline ChannelItem* Oscilloscope::channelWidget(int channel) +{ + return (ChannelItem *)(ui->channelList->itemWidget(ui->channelList->item(channel))); } // 开始运行 void Oscilloscope::start() { - updataTimer.start(); + m_timer->start(); } // 结束运行 void Oscilloscope::stop() { - updataTimer.stop(); + m_timer->stop(); } // 返回保持接收状态 bool Oscilloscope::holdReceive() { - return ui.holdReceiveBox->isChecked(); + return ui->holdReceiveBox->isChecked(); } // 设置是否使用OpenGL加速 @@ -182,7 +194,7 @@ void Oscilloscope::setUseOpenGL(bool status) void Oscilloscope::setUseAntialiased(bool status) { status &= !m_series[0]->useOpenGL(); // 不适用OpenGL时才可以打开抗锯齿 - ui.chartView->setRenderHint(QPainter::Antialiasing, status); + ui->chartView->setRenderHint(QPainter::Antialiasing, status); } // 设置背景颜色 @@ -208,16 +220,20 @@ void Oscilloscope::setGridColor(QColor color) // 设置更新时间 void Oscilloscope::setUpdateInterval(int msec) { - updataTimer.setInterval(msec); + m_timer->setInterval(msec); } // 添加数据 -void Oscilloscope::addData(const WaveDataType& data) +void Oscilloscope::append(const QByteArray &array) { - if (data.mode == WaveValueMode) { - m_buffer->append(data.channel, data.value); // 先将数据暂存到缓冲区 - } else { // Wave Time StampMode - timeStamp->append(data, m_buffer->maximumCount()); + QVector vector = m_decode->frameDecode(array); + + for (WaveDecode::DataType data : vector) { + if (data.mode == WaveDecode::ValueMode) { + m_buffer->append(data.channel, data.value); // 先将数据暂存到缓冲区 + } else { // Wave Time StampMode + m_timeStamp->append(data, m_buffer->maximumCount()); + } } } @@ -225,8 +241,8 @@ void Oscilloscope::addData(const WaveDataType& data) void Oscilloscope::clear() { m_buffer->clear(); - timeStamp->clear(); - ui.horizontalScrollBar->setMaximum(0); + m_timeStamp->clear(); + ui->horizontalScrollBar->setMaximum(0); m_chart->axisX()->setRange(0, m_xRange); } @@ -235,7 +251,7 @@ void Oscilloscope::savePng(const QString &fileName) { QScreen *screen = QGuiApplication::primaryScreen(); - QPixmap p = screen->grabWindow(ui.chartView->winId()); + QPixmap p = screen->grabWindow(ui->chartView->winId()); QImage image = p.toImage(); image.save(fileName); } @@ -245,7 +261,7 @@ void Oscilloscope::saveBmp(const QString &fileName) { QScreen *screen = QGuiApplication::primaryScreen(); - QPixmap p = screen->grabWindow(ui.chartView->winId()); + QPixmap p = screen->grabWindow(ui->chartView->winId()); QImage image = p.toImage(); image.save(fileName); } @@ -261,7 +277,7 @@ void Oscilloscope::channelStyleChanged(ChannelItem *item) // 滚动条滑块移动时触发 void Oscilloscope::horzScrollBarChanged(int value) { - if (ui.horizontalScrollBar->maximum() == value) { + if (ui->horizontalScrollBar->maximum() == value) { replotFlag = true; } else { replotFlag = false; @@ -272,7 +288,7 @@ void Oscilloscope::horzScrollBarChanged(int value) // Y轴偏置改变 void Oscilloscope::yOffsetChanged(double offset) { - double range = ui.yRangeBox->value(); + double range = ui->yRangeBox->value(); m_chart->axisY()->setRange(offset - range * 0.5, offset + range * 0.5); } @@ -280,7 +296,7 @@ void Oscilloscope::yOffsetChanged(double offset) // Y轴范围改变 void Oscilloscope::yRangeChanged(double range) { - double offset = ui.yOffsetBox->value(); + double offset = ui->yOffsetBox->value(); m_chart->axisY()->setRange(offset - range * 0.5, offset + range * 0.5); } @@ -290,21 +306,21 @@ void Oscilloscope::xRangeChanged(const QString &str) { m_count = m_buffer->update(); m_xRange = str.toDouble(); - ui.horizontalScrollBar->setPageStep(m_xRange); + ui->horizontalScrollBar->setPageStep(m_xRange); int count = m_count - 1; if (count > m_xRange) { int lower = count - m_xRange; m_chart->axisX()->setRange(lower, count); - bool req = ui.horizontalScrollBar->value() - == ui.horizontalScrollBar->maximum(); - ui.horizontalScrollBar->setMaximum(lower); + bool req = ui->horizontalScrollBar->value() + == ui->horizontalScrollBar->maximum(); + ui->horizontalScrollBar->setMaximum(lower); if (req) { - ui.horizontalScrollBar->setValue(lower); + ui->horizontalScrollBar->setValue(lower); } } else { m_chart->axisX()->setRange(0, m_xRange); - ui.horizontalScrollBar->setMaximum(0); + ui->horizontalScrollBar->setMaximum(0); } } @@ -321,11 +337,11 @@ void Oscilloscope::timeUpdata() } // update scroll bar int lower = count - m_xRange - 1; - bool req = ui.horizontalScrollBar->value() - == ui.horizontalScrollBar->maximum(); - ui.horizontalScrollBar->setMaximum(lower); + bool req = ui->horizontalScrollBar->value() + == ui->horizontalScrollBar->maximum(); + ui->horizontalScrollBar->setMaximum(lower); if (req) { - ui.horizontalScrollBar->setValue(lower); + ui->horizontalScrollBar->setValue(lower); } } m_count = count; @@ -354,7 +370,7 @@ void Oscilloscope::saveWave(const QString &fname) out.setRealNumberPrecision(8); for (int i = 0; i < dataCountMax; ++i) { - timeStamp->printTextStream(out, i); + m_timeStamp->printTextStream(out, i); out << i; for (int j = 0; j < CH_NUM; ++j) { if (i < count[j]) { @@ -398,7 +414,7 @@ bool Oscilloscope::loadWave_p(const QString &fname) line = file.readLine(); lineList = csvSplitLine(line); if (lineList[0][0] == '#') { // time stamp - timeStamp->append(lineList[0].mid(2), lineCount); + m_timeStamp->append(lineList[0].mid(2), lineCount); } else if (lineList.size() == listSize) { if (lineList[0].toInt() == lineCount++) { // 行号检查 for (int i = 1; i < listSize && ok; ++i) { @@ -422,11 +438,11 @@ bool Oscilloscope::loadWave_p(const QString &fname) if ((int)lineCount > m_xRange) { int lower = lineCount - m_xRange - 1; - ui.horizontalScrollBar->setMaximum(lower); - ui.horizontalScrollBar->setValue(lower); + ui->horizontalScrollBar->setMaximum(lower); + ui->horizontalScrollBar->setValue(lower); m_chart->axisX()->setRange(lower, lineCount - 1); } else { - ui.horizontalScrollBar->setMaximum(0); + ui->horizontalScrollBar->setMaximum(0); m_chart->axisX()->setRange(0, m_xRange); } } @@ -435,7 +451,7 @@ bool Oscilloscope::loadWave_p(const QString &fname) return ok; } -// d打开波形文件, 公有函数 +// 打开波形文件, 公有函数 void Oscilloscope::loadWave(const QString &fname) { if (m_buffer->maximumCount() > 0) { diff --git a/SerialTool/source/oscopetimestamp.cpp b/SerialTool/source/oscopetimestamp.cpp index 32d00f3..1e7e42b 100644 --- a/SerialTool/source/oscopetimestamp.cpp +++ b/SerialTool/source/oscopetimestamp.cpp @@ -1,9 +1,8 @@ #include "oscopetimestamp.h" -#include "wavedecode.h" #include #include -void OscopeTimeStamp::append(const WaveDataType &data, uint64_t count) +void OscopeTimeStamp::append(const WaveDecode::DataType &data, uint64_t count) { TimeStamp_p ts; @@ -17,7 +16,7 @@ void OscopeTimeStamp::append(const WaveDataType &data, uint64_t count) ts.msec = data.msec; ts.sampleRate = data.sampleRate; - timeStamp.append(ts); + m_timeStampVector.append(ts); } @@ -38,15 +37,15 @@ void OscopeTimeStamp::append(const QString &string, uint64_t count) ts.day = (uint8_t)(time.msec()); ts.sampleRate = (uint32_t)strList[2].replace("bps", "").toInt(); - timeStamp.append(ts); + m_timeStampVector.append(ts); } void OscopeTimeStamp::printTextStream(QTextStream &stream, uint64_t count) { - size_t i, size = timeStamp.size(); + size_t i, size = m_timeStampVector.size(); for (i = 0; i < size; ++i) { - TimeStamp_p &ts = timeStamp[i]; + TimeStamp_p &ts = m_timeStampVector[i]; if (ts.count == count) { char str[100]; diff --git a/SerialTool/source/portsetbox.cpp b/SerialTool/source/portsetbox.cpp index 7bc0305..a5d4644 100644 --- a/SerialTool/source/portsetbox.cpp +++ b/SerialTool/source/portsetbox.cpp @@ -1,4 +1,5 @@ -#include "portsetbox.h" +#include "portsetbox.h" +#include "ui_portsetbox.h" #define _size(x) (sizeof(x) / sizeof(x[0])) @@ -29,7 +30,9 @@ static const QSerialPort::FlowControl FlowControl[] = { QSerialPort::SoftwareControl }; -PortSetBox::PortSetBox(QSerialPort *port, QWidget *parent) : QDialog(parent) +PortSetBox::PortSetBox(QSerialPort *port, QWidget *parent) : + QDialog(parent), + ui(new Ui::PortSetBox) { unsigned int i; @@ -38,29 +41,29 @@ PortSetBox::PortSetBox(QSerialPort *port, QWidget *parent) : QDialog(parent) flags |= Qt::WindowCloseButtonHint; setWindowFlags(flags); - ui.setupUi(this); + ui->setupUi(this); setFixedSize(200, 150); // 不能伸缩的对话框 serialPort = port; for (i = 0; port->dataBits() != DataBits[i] && i < _size(DataBits); ++i); - ui.dataBitsBox->setCurrentIndex(i); + ui->dataBitsBox->setCurrentIndex(i); for (i = 0; port->parity() != Parity[i] && i < _size(Parity); ++i); - ui.paritBox->setCurrentIndex(i); + ui->paritBox->setCurrentIndex(i); for (i = 0; port->stopBits() != StopBits[i] && i < _size(StopBits); ++i); - ui.stopBitsBox->setCurrentIndex(i); + ui->stopBitsBox->setCurrentIndex(i); for (i = 0; port->flowControl() != FlowControl[i] && i < _size(StopBits); ++i); - ui.flowControlBox->setCurrentIndex(i); + ui->flowControlBox->setCurrentIndex(i); - connect(ui.dataBitsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setDataBits(int))); - connect(ui.paritBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setParity(int))); - connect(ui.stopBitsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setStopBits(int))); - connect(ui.flowControlBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setFlowControl(int))); + connect(ui->dataBitsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setDataBits(int))); + connect(ui->paritBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setParity(int))); + connect(ui->stopBitsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setStopBits(int))); + connect(ui->flowControlBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setFlowControl(int))); } PortSetBox::~PortSetBox() { - + delete ui; } void PortSetBox::setDataBits(int index) diff --git a/SerialTool/source/serialtool.cpp b/SerialTool/source/serialtool.cpp deleted file mode 100644 index 0a5e5a1..0000000 --- a/SerialTool/source/serialtool.cpp +++ /dev/null @@ -1,634 +0,0 @@ -#include "serialtool.h" -#include -#include -#include -#include -#include -#include -#include "portsetbox.h" -#include "optionsbox.h" -#include "aboutbox.h" -#include "wavedecode.h" -#include "version.h" -#include "tcpudpport.h" -#include "defaultconfig.h" -#include "serialport.h" -#include "valuedisplay.h" - -SerialTool::SerialTool(QWidget *parent) - : QMainWindow(parent) -{ - QString configPath(QStandardPaths::writableLocation( - QStandardPaths::AppConfigLocation) + "/config.ini"); - syncDefaultConfig(configPath); - config = new QSettings(configPath, QSettings::IniFormat); - - ui.setupUi(this); - setWindowTitle(SOFTWARE_NAME " V" SOFTWARE_VERSION); - - // 串口示波器波形解码器 - waveDecode = new WaveDecode(); - - // 互斥动作 - tabActionGroup = new QActionGroup(this); - tabActionGroup->addAction(ui.actionVisibleTab0); - tabActionGroup->addAction(ui.actionVisibleTab1); - tabActionGroup->addAction(ui.actionVisibleTab2); - - serialPort = new SerialPort(this); - tcpUdpPort = new TcpUdpPort(this); - ui.toolBar1->insertWidget(ui.portSetAction, tcpUdpPort); - ui.toolBar1->insertWidget(ui.portSetAction, serialPort); - - rxCount = 0; - txCount = 0; - // 状态栏设置 - rxCntLabel = new QLabel("RX: 0Bytes", this); - txCntLabel = new QLabel("TX: 0Bytes", this); - portInfoLabel = new QLabel("", this); - rxCntLabel->setMinimumWidth(120); - txCntLabel->setMinimumWidth(120); - portInfoLabel->setMinimumWidth(120); - ui.statusBar->addWidget(portInfoLabel); - ui.statusBar->addWidget(rxCntLabel); - ui.statusBar->addWidget(txCntLabel); - - loadConfig(); // 加载配置 - - // create connection between axes and scroll bars: - connect(ui.portRunAction, SIGNAL(triggered()), this, SLOT(changeRunFlag())); - connect(ui.portSwitchAction, SIGNAL(triggered()), this, SLOT(onPortSwitchActionTriggered())); - connect(ui.terminal, &TerminalView::sendDataRequest, this, &SerialTool::writePort); - connect(ui.clearAction, SIGNAL(triggered()), this, SLOT(cleanData())); - QObject::connect(&secTimer, &QTimer::timeout, this, &SerialTool::onSecTimerTimeout); - connect(ui.portSetAction, SIGNAL(triggered()), this, SLOT(openSetPortInfoBox())); - connect(ui.actionOption, SIGNAL(triggered()), this, SLOT(setOptions())); - connect(ui.actionSave, SIGNAL(triggered()), this, SLOT(saveFile())); - connect(ui.actionOpen, SIGNAL(triggered()), this, SLOT(openFile())); - connect(ui.actionClose, SIGNAL(triggered()), this, SLOT(close())); - connect(ui.actionVisibleToolbar, SIGNAL(triggered(bool)), ui.toolBar1, SLOT(setVisible(bool))); - connect(ui.actionVisibleStatusBar, SIGNAL(triggered(bool)), ui.statusBar, SLOT(setVisible(bool))); - connect(ui.toolBar1, SIGNAL(visibilityChanged(bool)), ui.actionVisibleToolbar, SLOT(setChecked(bool))); - connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabIndexChanged(int))); - connect(tabActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(tabActionGroupTriggered(QAction*))); - connect(ui.actionAbout, SIGNAL(triggered()), this, SLOT(about())); - connect(ui.actionWiki, SIGNAL(triggered()), this, SLOT(openWiki())); - connect(ui.fileTransfer, &FileTransferView::sendData, this, &SerialTool::writePort); - connect(ui.actionVedioBox, SIGNAL(triggered()), this, SLOT(onVedioBoxTriggered())); - connect(ui.actionValueDisplay, SIGNAL(triggered()), this, SLOT(onValueDisplayTriggered())); - connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); - connect(serialPort, SIGNAL(portChanged()), this, SLOT(dispPortStatus())); - connect(serialPort, SIGNAL(portError()), this, SLOT(closePort())); - connect(tcpUdpPort, SIGNAL(protocolChanged()), this, SLOT(dispPortStatus())); - connect(tcpUdpPort, SIGNAL(connectionError()), this, SLOT(closePort())); - connect(ui.actionStaysOnTop, SIGNAL(triggered()), this, SLOT(onStaysOnTopTriggered())); - - secTimer.start(1000); -} - -SerialTool::~SerialTool() -{ - delete config; - delete tabActionGroup; - delete tcpUdpPort; - delete rxCntLabel; - delete txCntLabel; - delete portInfoLabel; - delete waveDecode; - delete serialPort; -} - -// 关闭事件 -void SerialTool::closeEvent(QCloseEvent *event) -{ - saveConfig(); - QMainWindow::closeEvent(event); -} - -// 加载语言 -void SerialTool::setLanguage(const QString &string) -{ - // 首先卸载翻译 - if (!translator.isEmpty()) { - for (int i = 0; i < translator.size(); ++i) { - qApp->removeTranslator(translator[i]); // 卸载翻译环境 - delete translator[i]; - } - translator.clear(); - } - // 遍历文件 - QDir dir("language/" + string); - foreach(QFileInfo mfi ,dir.entryInfoList()) { - if (mfi.isFile() && mfi.suffix() == "qm") { // 是翻译文件 - QTranslator* ts = new QTranslator; - ts->load(mfi.absoluteFilePath()); - qApp->installTranslator(ts); // 安装翻译环境 - translator.append(ts); - } - } - // 重新翻译界面 - ui.retranslateUi(this); - ui.terminal->retranslate(); - ui.oscPlot->retranslate(); - ui.fileTransfer->retranslate(); - tcpUdpPort->retranslate(); - serialPort->retranslate(); -} - -// 加载样式表 -void SerialTool::setStyleSheet(const QString &string) -{ - // 样式表 - QFile qss("themes/" + string + "/style.css"); - qss.open(QFile::ReadOnly); - qApp->setStyleSheet(qss.readAll()); - qss.close(); -} - -// 读取系统设置 -void SerialTool::loadSettings() -{ - // 系统设置 - config->beginGroup("Settings"); - - QString fontFamily("'" - + config->value("FontFamily").toString().replace("+", "','") + "'"); - QString fontStyle(config->value("FontStyle").toString()); - int fontSize = config->value("FontSize").toInt(); - fontSize = fontSize < 6 ? 10 : fontSize; - ui.terminal->setFontFamily(fontFamily, fontSize, fontStyle); - - ui.oscPlot->setBackground(QColor(config->value("PlotBackground").toString())); - ui.oscPlot->setGridColor(QColor(config->value("AxisColor").toString())); - // 绘制使用OpenGL加速 - ui.oscPlot->setUseOpenGL(config->value("UseOpenGL").toBool()); - // 绘制时抗锯齿 - ui.oscPlot->setUseAntialiased(config->value("UseAntialias").toBool()); - // 示波器刷新速度 - ui.oscPlot->setUpdateInterval(config->value("UpdateInterval").toInt()); - PortType type = (PortType)config->value("PortType").toInt(); - - // 窗口透明度 - int opacity = config->value("WindowOpacity").toInt(); - opacity = opacity < 30 ? 100 : opacity <= 100 ? opacity : 100; - setWindowOpacity(opacity / 100.0); - if (m_valueDisplay != NULL) { - m_valueDisplay->setWindowOpacity(windowOpacity()); - } - if (m_vedioBox != NULL) { - m_vedioBox->setWindowOpacity(windowOpacity()); - } - - // 语言设置 - setLanguage(config->value("Language").toString()); - setStyleSheet(config->value("Theme").toString()); - - config->endGroup(); - - if (type != portType) { - closePort(); // 端口改变时关闭之前的端口 - portType = type; - } - dispPortStatus(); // 更新端口状态显示 - loadPortTool(); -} - -// 控件数据初始化, 在构造函数中初始化各种控件的初始值 -void SerialTool::loadConfig() -{ - // 路经 - config->beginGroup("Path"); - docPath = config->value("DocumentPath").toString(); - config->endGroup(); - - // 串口设置 - serialPort->loadConfig(config); - - // TCP/UDP设置 - tcpUdpPort->loadConfig(config); - - // 打开页面配置 - config->beginGroup("Workspace"); - ui.tabWidget->setCurrentIndex(config->value("TabIndex").toInt()); - setTabActionIndex(ui.tabWidget->currentIndex()); - ui.toolBar1->setVisible(config->value("ToolBarVisible").toBool()); - ui.actionVisibleToolbar->setChecked(ui.toolBar1->isVisible()); - ui.statusBar->setVisible(config->value("StatusBarVisible").toBool()); - // 这里如果直接速读取ui.statusBar->isVisible()会是false,原因不明 - ui.actionVisibleStatusBar->setChecked(config->value("StatusBarVisible").toBool()); - setWindowStaysOnTop(config->value("WindowStaysOnTop").toBool()); - config->endGroup(); - - // 调试终端配置 - ui.terminal->loadConfig(config); - - // 串口示波器 - ui.oscPlot->loadConfig(config); - - // 读取文件传输功能的设置 - ui.fileTransfer->loadConfig(config); - - // 最后读取系统设置 - loadSettings(); -} - -// 保存配置 -void SerialTool::saveConfig() -{ - // 保存串口设置 - serialPort->saveConfig(config); - - // 保存TCP/UDP设置 - tcpUdpPort->saveConfig(config); - - // 打开页面配置 - config->beginGroup("Workspace"); - config->setValue("TabIndex", - QVariant(ui.tabWidget->currentIndex())); - config->setValue("ToolBarVisible", QVariant(ui.toolBar1->isVisible())); - config->setValue("StatusBarVisible", QVariant(ui.statusBar->isVisible())); - config->setValue("WindowStaysOnTop", QVariant(windowFlags() & Qt::WindowStaysOnTopHint)); - config->endGroup(); - - // 调试终端配置 - ui.terminal->saveConfig(config); - // 串口示波器 - ui.oscPlot->saveConfig(config); - - // 路经 - config->beginGroup("Path"); - config->setValue("DocumentPath", QVariant(docPath)); - config->endGroup(); - - // 文件传输配置 - ui.fileTransfer->saveConfig(config); -} - -void SerialTool::setOptions() -{ - OptionsBox option(this); - option.exec(); -} - -// 保存文件 -void SerialTool::saveFile() -{ - QString filter; - QString fname = QFileDialog::getSaveFileName(this, tr("Save"), docPath, - tr("Portable Network Graphic Format (*.png)") + ";;" + - tr("Bitmap (*.bmp)") + ";;" + - tr("Wave Plain Text File (*.txt)") + ";;" + - tr("Terminal Text File (*.txt)"), &filter, - QFileDialog::HideNameFilterDetails); - if (fname.isNull()) { - return; - } - docPath = QFileInfo(fname).path(); - if (filter == tr("Portable Network Graphic Format (*.png)")) { - ui.oscPlot->savePng(fname); - } else if (filter == tr("Bitmap (*.bmp)")) { - ui.oscPlot->saveBmp(fname); - } else if (filter == tr("Wave Plain Text File (*.txt)")) { - ui.oscPlot->saveWave(fname); - } else if (filter == tr("Terminal Text File (*.txt)")) { - ui.terminal->saveText(fname); - } -} - -// 打开文件 -void SerialTool::openFile() -{ - QString filter; - QString fname = QFileDialog::getOpenFileName(this, tr("Open"), docPath, - tr("Wave Plain Text File (*.txt)"), &filter, - QFileDialog::HideNameFilterDetails); - if (fname.isNull()) { - return; - } - docPath = QFileInfo(fname).path(); - if (filter.indexOf("(*.txt)", 0) != -1) { - ui.oscPlot->loadWave(fname); - } -} - -void SerialTool::tabIndexChanged(int index) -{ - setTabActionIndex(index); - if (index == 0) { // terminal - if (runFlag) { // 暂停按钮没有按下时继续发送 - ui.terminal->setPaused(false); - } - } else { // 其他选项卡下暂停发送 - ui.terminal->setPaused(true); - } -} - -void SerialTool::setTabActionIndex(int index) -{ - switch (index) { - case 0: - ui.actionVisibleTab0->setChecked(true); - break; - case 1: - ui.actionVisibleTab1->setChecked(true); - break; - case 2: - ui.actionVisibleTab2->setChecked(true); - break; - default: - ui.actionVisibleTab0->setChecked(true); - break; - } -} - -void SerialTool::tabActionGroupTriggered(QAction *action) -{ - if (action == ui.actionVisibleTab0) { - ui.tabWidget->setCurrentIndex(0); - } else if (action == ui.actionVisibleTab1) { - ui.tabWidget->setCurrentIndex(1); - } else if (action == ui.actionVisibleTab2) { - ui.tabWidget->setCurrentIndex(2); - } -} - -void SerialTool::changeRunFlag() -{ - if (runFlag == true) { - runFlag = false; - QIcon icon(":/SerialTool/images/start.ico"); - ui.portRunAction->setIcon(icon); - ui.portRunAction->setText(tr("Start Tx/Rx")); - ui.terminal->setPaused(true); // terminal transmission pause - ui.oscPlot->stop(); - } else { - runFlag = true; - QIcon icon(":/SerialTool/images/pause.ico"); - ui.portRunAction->setIcon(icon); - ui.portRunAction->setText(tr("Pause Tx/Rx")); - ui.terminal->setPaused(false); // terminal transmission continue - if (ui.tabWidget->widget(ui.tabWidget->currentIndex()) == ui.tabOsc) { - ui.oscPlot->start(); - } - } -} - -// 状态栏显示端口状态 -void SerialTool::dispPortStatus() -{ - bool status = false; - QString string; - QPalette palette; - - if (portType == ComPort) { - status = serialPort->portStatus(string); - } else if (portType == NetworkPort) { - status = tcpUdpPort->portStatus(string); - } - palette.setColor(QPalette::WindowText, status ? Qt::darkGreen : Qt::red); - portInfoLabel->setText(string); - portInfoLabel->setPalette(palette); -} - -// 秒定时器溢出槽函数 -void SerialTool::onSecTimerTimeout() -{ - QString str; - - // 更新显示信息 - str = "RX: " + QString::number(rxCount) + "Bytes"; - rxCntLabel->setText(str); - str = "TX: " + QString::number(txCount) + "Bytes"; - txCntLabel->setText(str); -} - -// 打开串口端口 -bool SerialTool::openComPort() -{ - if (serialPort->open()) { - connect(serialPort, &SerialPort::readyRead, this, &SerialTool::readPortData); - return true; - } - return false; -} - -// 打开TCP/UDP端口 -bool SerialTool::openTcpUdpPort() -{ - if (tcpUdpPort->open()) { - connect(tcpUdpPort, &TcpUdpPort::readyRead, this, &SerialTool::readPortData); - return true; - } - return false; -} - -// 打开端口 -void SerialTool::openPort() -{ - bool status = false; - - if (portType == ComPort) { - status = openComPort(); - } else if (portType == NetworkPort) { - status = openTcpUdpPort(); - } - if (status) { - QIcon icon(":/SerialTool/images/close.png"); - ui.portSwitchAction->setIcon(icon); - ui.portSwitchAction->setText(tr("Close Port")); - ui.terminal->setEnabled(true); - ui.portRunAction->setEnabled(true); - if (runFlag && ui.tabWidget->widget(ui.tabWidget->currentIndex()) == ui.tabOsc) { - ui.oscPlot->start(); // 启动串口示波器 - } - dispPortStatus(); // 更新端口状态显示 - } -} - -void SerialTool::closePort() -{ - if (serialPort->isOpen()) { - serialPort->close(); // 关闭串口 - } - if (tcpUdpPort->isOpen()) { - tcpUdpPort->close(); - } - ui.oscPlot->stop(); // 串口示波器结束运行 - QIcon icon(":/SerialTool/images/connect.png"); - ui.portSwitchAction->setIcon(icon); - ui.portSwitchAction->setText(tr("Open Port")); - ui.terminal->setEnabled(false); - ui.portRunAction->setEnabled(false); - dispPortStatus(); // 更新端口状态显示 -} - -// 打开串口槽函数 -void SerialTool::onPortSwitchActionTriggered() -{ - if (ui.portRunAction->isEnabled() == true) { // 现在需要关闭端口 - closePort(); - } else { // 端口关闭时打开端口 - openPort(); - } -} - -// 打开串口设置对话框 -void SerialTool::openSetPortInfoBox() -{ - serialPort->portSetDialog(); -} - -//读取接收到的数据 -void SerialTool::readPortData() -{ - // 读取串口数据 - if (!runFlag) { - return; - } - QByteArray buf; - if (portType == ComPort) { - buf = serialPort->readAll(); // 读取串口数据 - } else if (portType == NetworkPort) { - buf = tcpUdpPort->readAll(); // 读取TCP/UDP数据 - } - rxCount += buf.length(); // 接收计数 - if (!buf.isEmpty()) { - if (ui.tabWidget->currentIndex() == 0) { // 串口调试助手 - ui.terminal->append(buf); - } - // 串口示波器接收数据 - if (ui.tabWidget->currentIndex() == 1 || ui.oscPlot->holdReceive()) { - for (int i = 0; i < buf.length(); ++i) { - WaveDataType data; - // 解析串口协议 - if (waveDecode->frameDecode(data, buf.data()[i]) == true) { - ui.oscPlot->addData(data); - } - } - } - // 串口文件传输 - if (ui.tabWidget->currentIndex() == 2) { - ui.fileTransfer->readData(buf); - } - if (m_vedioBox != NULL) { - m_vedioBox->addData(buf); - } - if (m_valueDisplay != NULL) { - m_valueDisplay->addData(buf); - } - } - buf.clear(); -} - -// 向端口发送数据,带参数 -void SerialTool::writePort(const QByteArray &array) -{ - txCount += array.length(); // 发送计数 - if (portType == ComPort) { - serialPort->write(array); - } else if (portType == NetworkPort) { - tcpUdpPort->write(array); - } -} - -void SerialTool::cleanData() -{ - switch (ui.tabWidget->currentIndex()) { - case 0: // 串口调试助手 - ui.terminal->clear(); - break; - case 1: - ui.oscPlot->clear(); - break; - } - // 计数清零 - rxCount = 0; - txCount = 0; -} - -void SerialTool::about() -{ - AboutBox aboutBox(this); - - aboutBox.exec(); -} - -void SerialTool::onValueDisplayTriggered() -{ - if (m_valueDisplay == NULL) { - m_valueDisplay = new ValueDisplay(this); - m_valueDisplay->setModal(false); - m_valueDisplay->setAttribute(Qt::WA_DeleteOnClose); - m_valueDisplay->setWindowOpacity(windowOpacity()); - connect(m_valueDisplay, SIGNAL(destroyed()), this, SLOT(onValueDisplayDelete())); - m_valueDisplay->show(); - } -} - -void SerialTool::onValueDisplayDelete() -{ - m_valueDisplay = NULL; -} - -void SerialTool::loadPortTool() -{ - if (portType == ComPort) { - serialPort->setVisibleWidget(true); - ui.portSetAction->setVisible(true); - tcpUdpPort->setVisibleWidget(false); - } else if (portType == NetworkPort) { - serialPort->setVisibleWidget(false); - ui.portSetAction->setVisible(false); - tcpUdpPort->setVisibleWidget(true); - } -} - -void SerialTool::onVedioBoxTriggered() -{ - if (m_vedioBox == NULL) { // 当对话框没有创建时创建 - m_vedioBox = new VedioBox(this); - connect(m_vedioBox, SIGNAL(destroyed()), this, SLOT(onVedioBoxDelete())); - m_vedioBox->setModal(false); // 非模态对话框 - m_vedioBox->setAttribute(Qt::WA_DeleteOnClose); - m_vedioBox->setWindowOpacity(windowOpacity()); - m_vedioBox->setFilePath(docPath); - m_vedioBox->show(); - } -} - -void SerialTool::onVedioBoxDelete() -{ - m_vedioBox = NULL; -} - -void SerialTool::setWindowStaysOnTop(bool enabled) -{ - Qt::WindowFlags flags = enabled ? - Qt::WindowStaysOnTopHint : Qt::Window; - QString str = enabled ? ":/SerialTool/images/pin_down.png" - : ":/SerialTool/images/pin_up.png"; - - hide(); - setWindowFlags(flags); - ui.actionStaysOnTop->setIcon(QIcon(str)); - show(); -} - -void SerialTool::onStaysOnTopTriggered() -{ - setWindowStaysOnTop(!(windowFlags() & Qt::WindowStaysOnTopHint)); -} - -void SerialTool::openWiki() -{ - QDesktopServices::openUrl(QUrl("https://github.com/Le-Seul/SerialTool/wiki")); -} - -void SerialTool::currentTabChanged(int index) -{ - if (runFlag && ui.tabWidget->widget(index) == ui.tabOsc) { // 只有在串口示波器选项卡下面才会启动示波器 - ui.oscPlot->start(); - } else { - ui.oscPlot->stop(); - } -} diff --git a/SerialTool/source/terminalview.cpp b/SerialTool/source/terminalview.cpp index 7d7ece0..4e785c9 100644 --- a/SerialTool/source/terminalview.cpp +++ b/SerialTool/source/terminalview.cpp @@ -1,9 +1,9 @@ #include "terminalview.h" +#include "ui_terminalview.h" #include #include #include #include -#include "ui_terminalview.h" TerminalView::TerminalView(QWidget *parent) : QWidget(parent), diff --git a/SerialTool/source/textedit.cpp b/SerialTool/source/textedit.cpp index c6fb651..e054223 100644 --- a/SerialTool/source/textedit.cpp +++ b/SerialTool/source/textedit.cpp @@ -14,12 +14,6 @@ TextEdit::TextEdit(QWidget *parent) : QsciScintilla(parent) connect(this, &QsciScintilla::linesChanged, this, &TextEdit::onLinesChanged); } -void TextEdit::setText(const QString &text) -{ - clear(); - append(text); -} - void TextEdit::append(const QString &text) { bool posEnd = SendScintilla(SCI_GETLENGTH) == SendScintilla(SCI_GETCURRENTPOS); diff --git a/SerialTool/source/valuedisplay.cpp b/SerialTool/source/valuedisplay.cpp index c762a6f..56e302a 100644 --- a/SerialTool/source/valuedisplay.cpp +++ b/SerialTool/source/valuedisplay.cpp @@ -25,7 +25,7 @@ ValueDisplay::~ValueDisplay() delete ui; } -void ValueDisplay::addData(const QByteArray &array) +void ValueDisplay::append(const QByteArray &array) { m_array.append(array); diff --git a/SerialTool/source/vediobox.cpp b/SerialTool/source/vediobox.cpp index 101148d..dc83ea1 100644 --- a/SerialTool/source/vediobox.cpp +++ b/SerialTool/source/vediobox.cpp @@ -1,25 +1,33 @@ #include "vediobox.h" +#include "ui_vediobox.h" #include #include #include -VedioBox::VedioBox(QWidget *parent) : QDialog(parent) +VedioBox::VedioBox(QWidget *parent) : + QDialog(parent), + ui(new Ui::VedioBox) { // 不显示问号 Qt::WindowFlags flags = Qt::Dialog; flags |= Qt::WindowCloseButtonHint; setWindowFlags(flags); - ui.setupUi(this); - ui.label->setFixedSize(325, 245); + ui->setupUi(this); + ui->label->setFixedSize(325, 245); setFixedSize(330, 279); // 不能伸缩的对话框 - connect(ui.saveButton, SIGNAL(clicked()), this, SLOT(saveImage())); - connect(ui.copyButton, SIGNAL(clicked()), this, SLOT(copyImage())); + connect(ui->saveButton, SIGNAL(clicked()), this, SLOT(saveImage())); + connect(ui->copyButton, SIGNAL(clicked()), this, SLOT(copyImage())); +} + +VedioBox::~VedioBox() +{ + delete ui; } // 添加一字节数据 -void VedioBox::addData(const QByteArray &arr) +void VedioBox::append(const QByteArray &arr) { array.append(arr); qint32 i, len = array.size() - 1; @@ -52,7 +60,7 @@ void VedioBox::addData(const QByteArray &arr) } } } - ui.label->setPixmap(pixmap.scaled(QSize(320, 240))); + ui->label->setPixmap(pixmap.scaled(QSize(320, 240))); image = pixmap; // 保存图像 memcpy(imageData, array.data() + 2, 600); // 复制到缓冲区 array = array.mid(602); // 保留余下内容 diff --git a/SerialTool/source/wavedecode.cpp b/SerialTool/source/wavedecode.cpp index 4ba6d84..b57f036 100644 --- a/SerialTool/source/wavedecode.cpp +++ b/SerialTool/source/wavedecode.cpp @@ -1,19 +1,19 @@ #include "wavedecode.h" enum { - Frame_Head = 0xA3, //֡ͷʶ - Frame_PointMode = 0xA8, // ģʽʶ - Frame_SyncMode = 0xA9, // ͬģʽʶ - Frame_InfoMode = 0xAA // Ϣ֡ʶ + Frame_Head = 0xA3, //帧头识别字 + Frame_PointMode = 0xA8, // 点模式识别字 + Frame_SyncMode = 0xA9, // 同步模式识别字 + Frame_InfoMode = 0xAA // 信息帧识别字 }; enum { - STA_None = 0, // ״̬ - STA_Head, // յ֡ͷ - STA_Point, // ģʽ - STA_Sync, // ͬģʽ - STA_Info, // Ϣģʽ - STA_SyncData // ͬģʽ + STA_None = 0, // 空闲状态 + STA_Head, // 接收到帧头 + STA_Point, // 点模式 + STA_Sync, // 同步模式 + STA_Info, // 信息模式 + STA_SyncData // 同步模式数据 }; enum Result { @@ -59,25 +59,25 @@ double WaveDecode::data2Double(uint32_t value, int type) return d; } -// һ, -int WaveDecode::pointData(WaveDataType &dst, uint8_t byte) +// 接收一个点数据, 仅仅是数据 +int WaveDecode::pointData(DataType &dst, uint8_t byte) { - static const int bytes[] = { 4, 1, 2, 4 }; // ͵ֽ + static const int bytes[] = { 4, 1, 2, 4 }; // 各种类型的字节数 - if (dataCount == 0) { // һֽͺͨϢ - channel = byte & 0x0F; // ֵͨ + if (dataCount == 0) { // 第一个字节是数据类型和通道信息 + channel = byte & 0x0F; // 通道值 // tpye: 0: float, 1: int8, 2: int16, 3: int32 type = byte >> 4; - if (type > 3) { // ʹ + if (type > 3) { // 数据类型错误 dataCount = 0; return Error; } dataLength = bytes[type]; - } else { // 漸ֽ + } else { // 后面几个字节是数据 data = (data << 8) | byte; - if (dataCount >= dataLength) { // + if (dataCount >= dataLength) { // 接收完毕 dst.channel = channel; - dst.mode = WaveValueMode; + dst.mode = ValueMode; dst.value = data2Double(data, type); dataCount = 0; data = 0; @@ -88,10 +88,10 @@ int WaveDecode::pointData(WaveDataType &dst, uint8_t byte) return Ok; } -// תʱ -void WaveDecode::timeStamp(WaveDataType &dst, uint8_t* buffer) +// 转换时间戳 +void WaveDecode::timeStamp(DataType &dst, uint8_t* buffer) { - dst.mode = WaveTimeStampMode; + dst.mode = TimeStampMode; dst.year = (buffer[0] >> 1) & 0x7F; dst.month = ((buffer[0] << 3) & 0x80) | ((buffer[1] >> 5) & 0x07); dst.day = buffer[1] & 0x1F; @@ -103,12 +103,12 @@ void WaveDecode::timeStamp(WaveDataType &dst, uint8_t* buffer) | (((uint32_t)buffer[6] << 8) & 0x00FF00) | (uint32_t)buffer[7]; } -// ֡, ʶ֡ͷ -bool WaveDecode::frameDecode(WaveDataType &data, uint8_t byte) +// 波形数据帧解码, 会识别帧头 +bool WaveDecode::frameDecode_p(DataType &data, uint8_t byte) { int res; - // ֡ͷ״̬ + // 捕获帧头状态机 switch (status) { case STA_None: status = byte == Frame_Head ? STA_Head : STA_None; @@ -139,12 +139,12 @@ bool WaveDecode::frameDecode(WaveDataType &data, uint8_t byte) case STA_Point: res = pointData(data, byte); switch (res) { - case Ok: // ڽ + case Ok: // 还在接收数据 break; - case Error: // ¿ʼ + case Error: // 错误则重新开始接收 status = STA_None; break; - case Done: // ʼ״̬true + case Done: // 结束初始化状态并返回true status = STA_None; return true; } @@ -152,21 +152,21 @@ bool WaveDecode::frameDecode(WaveDataType &data, uint8_t byte) case STA_Sync: frameCount = 0; frameLength = byte; - // len > 64֡ȴ, ƥ֡, תSTA_SyncData״̬ + // 如果len > 64则帧长度错误, 将重新匹配帧, 否则转到STA_SyncData状态 status = frameLength <= 64 ? STA_SyncData : STA_None; break; case STA_SyncData: - if (++frameCount >= frameLength) { // ﵽ֡˵֡, ״̬ + if (++frameCount >= frameLength) { // 计数达到帧长度说明帧结束, 重置状态 status = STA_None; } res = pointData(data, byte); switch (res) { - case Ok: // ڽ + case Ok: // 还在接收数据 break; - case Error: // ¿ʼ + case Error: // 错误则重新开始接收 status = STA_None; break; - case Done: // true + case Done: // 结束返回true return true; } break; @@ -179,8 +179,22 @@ bool WaveDecode::frameDecode(WaveDataType &data, uint8_t byte) return true; } break; - default: // 쳣λ״̬ + default: // 异常情况复位状态 status = STA_None; } return false; } + +QVector WaveDecode::frameDecode(const QByteArray &array) +{ + DataType data; + QVector vector; + + + for (char byte : array) { + if (frameDecode_p(data, byte) == true) { + vector.append(data); + } + } + return vector; +} diff --git a/SerialTool/source/xmodem.cpp b/SerialTool/source/xmodem.cpp index e86d36b..3c9eb80 100644 --- a/SerialTool/source/xmodem.cpp +++ b/SerialTool/source/xmodem.cpp @@ -1,14 +1,14 @@ #include "xmodem.h" -// ״̬ʹõַ -#define NONE 0x00 // ״̬ -#define TRAN 0x01 // ״̬ +// 状态机使用的字符 +#define NONE 0x00 // 空闲状态 +#define TRAN 0x01 // 传输状态 enum { - None, // ״̬ - Trans, // ״̬ - TransEnd, // ״̬ - TransEOT // EOTַӦ״̬ + None, // 空闲状态 + Trans, // 传输状态 + TransEnd, // 传输结束状态 + TransEOT // EOT字符的应答状态 }; #define SOH 0x01 @@ -27,26 +27,26 @@ void XModemClass::setThread(FileThread *thread) this->thread = thread; } -// Уֵ +// 计算校验值 char XModemClass::calcVerifi(const char *frame) { int value = 0; - // ֻʵУ㷨 + // 只实现了校验和算法 for (int i = 3; i < 128 + 3; ++i) { value += frame[i]; } return (char)(value & 0xFF); } -// ʼ +// 开始传输 void XModemClass::startTransmit() { status = None; transMode = true; } -// ʼ +// 开始接收 void XModemClass::startReceive() { QByteArray arr; @@ -58,73 +58,72 @@ void XModemClass::startReceive() thread->sendPortData(arr); } -// ȡ -bool XModemClass::cancelTrans() +// 取消传输 +void XModemClass::cancelTrans() { QByteArray arr; - if (transMode) { // ģʽȡ + if (transMode) { // 发送模式下取消传输 if (status == None) { arr.clear(); arr.append(EOT); thread->sendPortData(arr); - } else { // ģʽȡ + } else { // 接受模式下取消传输 arr.clear(); arr.append(CAN); thread->sendPortData(arr); } } - return true; } -// ģʽÿνһֽ +// 发送模式每次接收一个字节 int XModemClass::transmit(char ch, qint64 &bytes) { int rBytes; QByteArray arr; - if (ch == CAN) { // ȡ + if (ch == CAN) { // 取消传输 return 1; } switch (status) { case None: - if (ch == NAK) { // ʼ + if (ch == NAK) { // 开始传输 status = ACK; - memset(frame, 0, 132); // ʼ֡ - ch = ACK; // Ϊ洫һ֡ + memset(frame, 0, 132); // 初始化帧 + ch = ACK; // 为了下面传输第一帧 status = Trans; } - case TransEnd: // - // յACK˵һ֡ݴ, ʱEOT + case TransEnd: // 传输结束 + // 接收到ACK说明最后一帧数据传输完成, 此时传输EOT if (ch == ACK && status == TransEnd) { arr.clear(); arr.append(EOT); thread->sendPortData(arr); - status = TransEOT; // Ӧ״̬ + status = TransEOT; // 进入结束应答状态 break; } - case Trans: // - if (ch == ACK) { // һ + case Trans: // 传输数据 + if (ch == ACK) { // 传输下一块数据 frame[0] = SOH; ++frame[1]; frame[2] = ~frame[1]; rBytes = thread->readFile(frame + 3, 128); bytes += rBytes; - if (rBytes < 128) { // ˵һ֡ - // ֽ0x1A + if (rBytes < 128) { // 说明是最后一帧数据 + // 多余的字节填充0x1A for (int i = rBytes + 3; i < 131; ++i) { frame[i] = 0x1A; } status = TransEnd; } - frame[131] = calcVerifi(frame); // Уַ + frame[131] = calcVerifi(frame); // 计算校验字符 } arr.clear(); arr.append(frame, 132); - thread->sendPortData(arr); // + thread->sendPortData(arr); // 发送数据 break; case TransEOT: - if (ch == ACK) { // EOTԷӦ, + if (ch == ACK) { // EOT被对方应答, 传输结束 status = None; return 1; } @@ -133,7 +132,7 @@ int XModemClass::transmit(char ch, qint64 &bytes) return 0; } -// ģʽ +// 接收模式 int XModemClass::receive(const QByteArray &arr, qint64 &bytes) { int size, pos; @@ -143,30 +142,30 @@ int XModemClass::receive(const QByteArray &arr, qint64 &bytes) rxBuf.append(arr); size = rxBuf.size(); pdata = rxBuf.data(); - if (pdata[0] == EOT) { // + if (pdata[0] == EOT) { // 传输结束 tbuf.append(ACK); - thread->sendPortData(tbuf); // Ӧ־ + thread->sendPortData(tbuf); // 发送应答标志 return 1; } - // ѰSOHַ + // 寻找SOH字符 for (pos = 0; pos < size && pdata[pos] != SOH; ++pos); - if (size - pos < 131) { // 峤С132bytes˵֡ + if (size - pos < 131) { // 接收区缓冲长度小于132bytes说明不是完整的帧 return 0; } - pdata += pos; // ȡ֡ - // У - if (calcVerifi(pdata) == pdata[131] // Уֽ - && pdata[1] == ~pdata[2] // ֡У - && ((char)(lastCount + 1) == pdata[1] || lastCount == pdata[1])) { // ֡Ƿ + pdata += pos; // 获取帧数据 + // 校验 + if (calcVerifi(pdata) == pdata[131] // 检查校验字节 + && pdata[1] == ~pdata[2] // 帧计数校验 + && ((char)(lastCount + 1) == pdata[1] || lastCount == pdata[1])) { // 帧数是否正常 thread->writeFile(pdata + 3, 128); bytes += 128; lastCount = pdata[1]; tbuf.append(ACK); - thread->sendPortData(tbuf); // Ӧ־ + thread->sendPortData(tbuf); // 发送应答标志 } else { tbuf.append(NAK); - thread->sendPortData(tbuf); // Ӧ־ + thread->sendPortData(tbuf); // 发送应答标志 } - rxBuf = rxBuf.mid(pos + 132); // + rxBuf = rxBuf.mid(pos + 132); // 保留余下内容 return 0; } diff --git a/SerialTool/ui/serialtool.ui b/SerialTool/ui/mainwindow.ui similarity index 96% rename from SerialTool/ui/serialtool.ui rename to SerialTool/ui/mainwindow.ui index f83d823..7e936cb 100644 --- a/SerialTool/ui/serialtool.ui +++ b/SerialTool/ui/mainwindow.ui @@ -1,8 +1,8 @@ 官文亮 - SerialTool - + MainWindow + 0 @@ -241,7 +241,7 @@ - :/SerialTool/images/connect.png:/SerialTool/images/connect.png + :/SerialTool/images/connect.ico:/SerialTool/images/connect.ico Open Port @@ -269,7 +269,7 @@ - :/SerialTool/images/clear.png:/SerialTool/images/clear.png + :/SerialTool/images/clear.ico:/SerialTool/images/clear.ico Clear Buffer @@ -281,7 +281,7 @@ - :/SerialTool/images/port config.png:/SerialTool/images/port config.png + :/SerialTool/images/port config.ico:/SerialTool/images/port config.ico Port Settings @@ -388,7 +388,7 @@ - + :/SerialTool/images/pin_up.png:/SerialTool/images/pin_up.png diff --git a/SerialTool/ver_temp.h b/SerialTool/ver_temp.h index 6daf080..3dacdcc 100644 --- a/SerialTool/ver_temp.h +++ b/SerialTool/ver_temp.h @@ -1,7 +1,7 @@ #ifndef __VERSION_H #define __VERSION_H -#define MAIN_VERSION 1.2.1 +#define MAIN_VERSION 1.2.2 #define SOFTWARE_NAME "SerialTool" #define COPYRIGHT "Copyleft 2017 by Wenliang"