├── .gitignore ├── 3rdparty ├── 3rdparty.pri ├── BXC_MediaLibrary │ ├── bin │ │ ├── BXC_AudioRecorder.dll │ │ ├── BXC_AvEncoder.dll │ │ ├── BXC_VideoRecorder.dll │ │ ├── avcodec-60.dll │ │ ├── avdevice-60.dll │ │ ├── avfilter-9.dll │ │ ├── avformat-60.dll │ │ ├── avutil-58.dll │ │ ├── postproc-57.dll │ │ ├── swresample-4.dll │ │ └── swscale-7.dll │ ├── include │ │ ├── BXC_AudioRecorder.h │ │ ├── BXC_AvEncoder.h │ │ ├── BXC_AvFrame.h │ │ └── BXC_VideoRecorder.h │ └── lib │ │ ├── BXC_AudioRecorder.lib │ │ ├── BXC_AvEncoder.lib │ │ └── BXC_VideoRecorder.lib └── QsLog │ ├── .gitignore │ ├── LICENSE.txt │ ├── QsLog.cpp │ ├── QsLog.h │ ├── QsLog.pri │ ├── QsLogChanges.txt │ ├── QsLogDest.cpp │ ├── QsLogDest.h │ ├── QsLogDestConsole.cpp │ ├── QsLogDestConsole.h │ ├── QsLogDestFile.cpp │ ├── QsLogDestFile.h │ ├── QsLogDestFunctor.cpp │ ├── QsLogDestFunctor.h │ ├── QsLogDisableForThisFile.h │ ├── QsLogLevel.h │ ├── QsLogSharedLibrary.pro │ └── README.md ├── Index ├── About.cpp ├── About.h ├── Index.pri ├── IndexWidget.cpp ├── IndexWidget.h ├── Settings.cpp └── Settings.h ├── LICENSE ├── README.md ├── Record ├── CaptureAudioThread.cpp ├── CaptureAudioThread.h ├── CaptureVideoThread.cpp ├── CaptureVideoThread.h ├── Record.pri ├── RecordWidget.cpp ├── RecordWidget.h ├── Recorder.cpp └── Recorder.h ├── SRE.pro ├── Utils ├── ComLineWidget.cpp ├── ComLineWidget.h ├── ComLoadingLabel.cpp ├── ComLoadingLabel.h ├── ComLoadingWidget.cpp ├── ComLoadingWidget.h ├── ComMessageBox.cpp ├── ComMessageBox.h ├── ComOptionsBox.cpp ├── ComOptionsBox.h ├── ComSpinWidget.cpp ├── ComSpinWidget.h ├── ComSplitHWidget.cpp ├── ComSplitHWidget.h ├── ComSplitVWidget.cpp ├── ComSplitVWidget.h ├── FpsControl.cpp ├── FpsControl.h ├── SingletonUtils.cpp ├── SingletonUtils.h ├── Utils.h ├── Utils.pri └── constant.h ├── VNCClient ├── ClientDialog.cpp ├── ClientDialog.h ├── ClientTabWidget.cpp ├── ClientTabWidget.h ├── DesktopControlWidget.cpp ├── DesktopControlWidget.h ├── VNCClient.pri ├── VNCClientWidget.cpp └── VNCClientWidget.h ├── VNCServer ├── VNCServer.pri ├── VNCServerWidget.cpp └── VNCServerWidget.h ├── logo.ico ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── res.qrc └── res └── images ├── icon ├── error.png ├── logout.png ├── password.png ├── search.png ├── searchblack.png ├── settings.png ├── stop.png ├── success.png └── warning.png └── logo.png /.gitignore: -------------------------------------------------------------------------------- 1 | # clion 2 | .idea/ 3 | cmake-build-debug/* 4 | build/* 5 | 6 | # vs 7 | .vs 8 | 9 | # Qt Creator 10 | SRE.pro.user* 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /3rdparty/3rdparty.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += 3rdparty 2 | 3 | include($$PWD/QsLog/QsLog.pri) 4 | 5 | -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/BXC_AudioRecorder.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/BXC_AudioRecorder.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/BXC_AvEncoder.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/BXC_AvEncoder.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/BXC_VideoRecorder.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/BXC_VideoRecorder.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/avcodec-60.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/avcodec-60.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/avdevice-60.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/avdevice-60.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/avfilter-9.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/avfilter-9.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/avformat-60.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/avformat-60.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/avutil-58.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/avutil-58.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/postproc-57.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/postproc-57.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/swresample-4.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/swresample-4.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/bin/swscale-7.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/bin/swscale-7.dll -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/include/BXC_AudioRecorder.h: -------------------------------------------------------------------------------- 1 | #ifndef BXC_AUDIORECORDER_H 2 | #define BXC_AUDIORECORDER_H 3 | #include 4 | 5 | #ifdef BXC_MEDIALIBRARY_EXPORTS 6 | #define __DECLSPEC_INC __declspec(dllexport) 7 | #else 8 | #define __DECLSPEC_INC __declspec(dllimport) 9 | #endif //!BXC_MEDIALIBRARY_EXPORTS 10 | 11 | namespace BXC_MediaLibrary { 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | struct BXC_AudioRecorder { 17 | public: 18 | BXC_AudioRecorder() = delete; 19 | BXC_AudioRecorder(const char* capture) { 20 | this->capture = capture; 21 | } 22 | ~BXC_AudioRecorder() { 23 | } 24 | public: 25 | int id = -1; 26 | const char* capture;//音频采样设备,默认声卡:SOUNDCARD, 默认麦克风:MICROPHONE 27 | 28 | int nb_channels;//音频采样声道数(常见值:2,1) 29 | int nb_bits_sample;//一个音频采样点的比特数(常见值:16,8,24) 30 | int sample_rate;//音频采样率(常见值:44100,48000) 31 | int nb_samples;//一帧音频的采样点数量(常见值:1024,1056,1152) 32 | 33 | }; 34 | 35 | /** 36 | * 打开一个音频采样实例 37 | * 38 | * @param recorder 音频采样实例 39 | * @return >= 0 on success, a negative code on failure 40 | */ 41 | int __DECLSPEC_INC BXC_AudioRecorder_Open(BXC_AudioRecorder * recorder); 42 | 43 | /** 44 | * 关闭一个音频采样实例 45 | * 46 | * @param recorder 音频采样实例 47 | * @return >= 0 on success, a negative code on failure 48 | */ 49 | int __DECLSPEC_INC BXC_AudioRecorder_Close(BXC_AudioRecorder* recorder); 50 | 51 | /** 52 | * 获取音频采样数据 53 | * 54 | * @param recorder 音频采样实例 55 | * @param buffer 采样得到的音频字节流 56 | * @param size 采样得到的音频字节流长度 57 | * @param timestamp 采样时间戳 58 | * @return >= 0 on success, a negative code on failure 59 | */ 60 | int __DECLSPEC_INC BXC_get_sample(BXC_AudioRecorder* recorder,unsigned char*& buffer, int& size, int64_t& timestamp);//获取采样数据 61 | 62 | /** 63 | * 获取音频采样时使用的时间戳 64 | * 65 | * @return 时间戳(单位与BXC_get_sample获得的音频时间戳单位一致) 66 | */ 67 | int64_t __DECLSPEC_INC BXC_audio_timestamp(); 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | } 73 | #endif //BXC_AUDIORECORDER_H 74 | -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/include/BXC_AvEncoder.h: -------------------------------------------------------------------------------- 1 | #ifndef BXC_AVENCODER_H 2 | #define BXC_AVENCODER_H 3 | #ifdef BXC_MEDIALIBRARY_EXPORTS 4 | #define __DECLSPEC_INC __declspec(dllexport) 5 | #else 6 | #define __DECLSPEC_INC __declspec(dllimport) 7 | #endif //!BXC_MEDIALIBRARY_EXPORTS 8 | #include "BXC_AvFrame.h" 9 | 10 | namespace BXC_MediaLibrary { 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | * 打开一个音视频编码器实例 18 | * 19 | * @param encoder 音视频编码器实例 20 | * @param url 存储地址 21 | * @return >= 0 on success, a negative code on failure 22 | */ 23 | int __DECLSPEC_INC BXC_AvEncoder_Open(BXC_AvEncoder* encoder, const char* url); 24 | 25 | /** 26 | * 关闭一个音视频编码器实例 27 | * 28 | * @param encoder 音视频编码器实例 29 | * @return >= 0 on success, a negative code on failure 30 | */ 31 | int __DECLSPEC_INC BXC_AvEncoder_Close(BXC_AvEncoder* encoder); 32 | 33 | /** 34 | * 获取当前时间戳(microseconds.) 35 | * 36 | * @return 当前时间戳 37 | */ 38 | int64_t __DECLSPEC_INC BXC_gettime(); 39 | 40 | /** 41 | * 添加一帧待编码帧 42 | * 43 | * @param encoder 音视频编码器实例 44 | * @param frame 待编码帧 45 | * @return >= 0 on success, a negative code on failure 46 | */ 47 | int __DECLSPEC_INC BXC_send_frame(BXC_AvEncoder* encoder, BXC_AvFrame* frame); 48 | 49 | /** 50 | * 获取一帧编码帧 51 | * 52 | * @param encoder 音视频编码器实例 53 | * @param packet 获取的编码帧(获取的编码帧类型,取决于参数中的type) 54 | * @return >= 0 on success, a negative code on failure 55 | */ 56 | int __DECLSPEC_INC BXC_receive_packet(BXC_AvEncoder* encoder, BXC_AvPacket* packet); 57 | 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | } 63 | #endif //BXC_AVENCODER_H 64 | -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/include/BXC_AvFrame.h: -------------------------------------------------------------------------------- 1 | #ifndef BXC_AVFRAME_H 2 | #define BXC_AVFRAME_H 3 | #include 4 | namespace BXC_MediaLibrary { 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | enum BXC_AvType { 11 | AVNONE = 20, 12 | AVVIDEO, 13 | AVAUDIO, 14 | }; 15 | struct BXC_AvFrame 16 | { 17 | public: 18 | BXC_AvFrame() = delete; 19 | BXC_AvFrame(BXC_AvType type, int size) { 20 | this->type = type; 21 | this->size = size; 22 | this->data = (uint8_t*)malloc(this->size); 23 | } 24 | BXC_AvFrame(BXC_AvType type,int size, int64_t timestamp, int64_t count) { 25 | this->type = type; 26 | this->size = size; 27 | this->timestamp = timestamp; 28 | this->count = count; 29 | this->data = (uint8_t*)malloc(this->size); 30 | } 31 | ~BXC_AvFrame() { 32 | free(this->data); 33 | this->data = nullptr; 34 | } 35 | public: 36 | BXC_AvType type; 37 | int size; 38 | int64_t timestamp; 39 | int64_t count; 40 | uint8_t* data; 41 | }; 42 | struct BXC_AvPacket 43 | { 44 | public: 45 | BXC_AvPacket() = delete; 46 | BXC_AvPacket(BXC_AvType type, int size) { 47 | this->type = type; 48 | this->size = size; 49 | this->data = (uint8_t*)malloc(this->size); 50 | } 51 | BXC_AvPacket(BXC_AvType type, int size, int64_t stream_index , int64_t pts, int64_t dts, int64_t duration, int64_t pos, 52 | int64_t timestamp, int64_t count) { 53 | this->type = type; 54 | this->size = size; 55 | this->stream_index = stream_index; 56 | this->pts = pts; 57 | this->dts = dts; 58 | this->duration = duration; 59 | this->pos = pos; 60 | 61 | this->timestamp = timestamp; 62 | this->count = count; 63 | 64 | this->data = (uint8_t*)malloc(this->size); 65 | } 66 | ~BXC_AvPacket() { 67 | free(this->data); 68 | this->data = nullptr; 69 | } 70 | BXC_AvType type; 71 | int size; 72 | int64_t stream_index; 73 | int64_t pts; 74 | int64_t dts; 75 | int64_t duration; 76 | int64_t pos; 77 | 78 | int64_t timestamp; 79 | int64_t count; 80 | 81 | uint8_t* data; 82 | }; 83 | struct BXC_AvEncoder { 84 | public: 85 | BXC_AvEncoder() = delete; 86 | BXC_AvEncoder(bool hasVideo, const char* videoCodecName, int videoBitrate, int pixelFormat, int width, int height, int fps, 87 | bool hasAudio, const char* audioCodecName, int audioBitrate) { 88 | this->hasVideo = hasVideo; 89 | this->videoCodecName = videoCodecName; 90 | this->videoBitrate = videoBitrate; 91 | this->pixelFormat = pixelFormat; 92 | this->width = width; 93 | this->height = height; 94 | this->fps = fps; 95 | 96 | this->hasAudio = hasAudio; 97 | this->audioCodecName = audioCodecName; 98 | this->audioBitrate = audioBitrate; 99 | } 100 | ~BXC_AvEncoder() { 101 | 102 | } 103 | 104 | public: 105 | int id = -1; 106 | 107 | bool hasVideo = false;//是否编码视频流 108 | const char* videoCodecName = nullptr;//视频编码名称 109 | int width = 0;//视频宽 110 | int height = 0;//视频高 111 | int fps = 0;// 视频编码帧率 112 | int pixelFormat;//视频帧像素格式(BXC_PixelFormat) 113 | int videoBitrate = 0;//视频编码码率 114 | 115 | bool hasAudio = false;//是否编码音频流 116 | const char* audioCodecName = nullptr;//视频编码名称 117 | int audioBitrate = 0;//音频编码码率 118 | 119 | }; 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | }; 125 | #endif //BXC_AVFRAME_H -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/include/BXC_VideoRecorder.h: -------------------------------------------------------------------------------- 1 | #ifndef BXC_VIDEORECORDER_H 2 | #define BXC_VIDEORECORDER_H 3 | #include 4 | 5 | #ifdef BXC_MEDIALIBRARY_EXPORTS 6 | #define __DECLSPEC_INC __declspec(dllexport) 7 | #else 8 | #define __DECLSPEC_INC __declspec(dllimport) 9 | #endif //!BXC_MEDIALIBRARY_EXPORTS 10 | 11 | namespace BXC_MediaLibrary { 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | enum BXC_PixelFormat { 18 | PIXEL_UNKNOWN = 20,//未知 19 | PIXEL_BGRA, //BGRA 20 | PIXEL_RGB, //RGB 21 | }; 22 | 23 | 24 | struct BXC_VideoRecorder { 25 | public: 26 | BXC_VideoRecorder() = delete; 27 | BXC_VideoRecorder(const char* capture,int width,int height,int idx) { 28 | this->capture = capture; 29 | this->width = width; 30 | this->height = height; 31 | this->idx = idx; 32 | } 33 | ~BXC_VideoRecorder() { 34 | } 35 | public: 36 | int id = -1; 37 | const char* capture;//视频采样设备,WindowsDXGI: DXGI, WindowsGDI: GDI,或者其他摄像头的具体名称 38 | int width; //视频采样宽度 39 | int height; //视频采样高度 40 | int idx; //视频采样源为屏幕时,具体的屏幕序号 41 | 42 | BXC_PixelFormat pixelFormat;//视频帧像素格式(BXC_VideoRecorder_Open成功后自动赋值) 43 | int factWidth; //接口获取的视频采样设备宽度 44 | int factHeight;//接口获取的视频采样设备宽度 45 | }; 46 | 47 | /** 48 | * 打开一个视频采样实例 49 | * 50 | * @param recorder 视频采样实例 51 | * @return >= 0 on success, a negative code on failure 52 | */ 53 | int __DECLSPEC_INC BXC_VideoRecorder_Open(BXC_VideoRecorder* recorder); 54 | 55 | /** 56 | * 关闭一个视频采样实例 57 | * 58 | * @param recorder 视频采样实例 59 | * @return >= 0 on success, a negative code on failure 60 | */ 61 | int __DECLSPEC_INC BXC_VideoRecorder_Close(BXC_VideoRecorder* recorder); 62 | 63 | /** 64 | * 采样一帧视频帧数据 65 | * 66 | * @param recorder 视频采样实例 67 | * @param buffer 采样得到的一帧视频帧字节流 68 | * @param size 采样得到的一帧视频帧字节流长度 69 | * @param timestamp 采样时间戳 70 | * @return >= 0 on success, a negative code on failure 71 | */ 72 | int __DECLSPEC_INC BXC_get_frame(BXC_VideoRecorder* recorder,unsigned char*& buffer, int& size, int64_t& timestamp); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | } 78 | #endif //BXC_VIDEORECORDER_H 79 | -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/lib/BXC_AudioRecorder.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/lib/BXC_AudioRecorder.lib -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/lib/BXC_AvEncoder.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/lib/BXC_AvEncoder.lib -------------------------------------------------------------------------------- /3rdparty/BXC_MediaLibrary/lib/BXC_VideoRecorder.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/3rdparty/BXC_MediaLibrary/lib/BXC_VideoRecorder.lib -------------------------------------------------------------------------------- /3rdparty/QsLog/.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | build-* 3 | -------------------------------------------------------------------------------- /3rdparty/QsLog/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Razvan Petru 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or other 11 | materials provided with the distribution. 12 | * The name of the contributors may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLog.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #include "QsLog.h" 27 | #include "QsLogDest.h" 28 | #ifdef QS_LOG_SEPARATE_THREAD 29 | #include 30 | #include 31 | #endif 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | namespace QsLogging 40 | { 41 | typedef QVector DestinationList; 42 | 43 | static const char TraceString[] = "TRACE"; 44 | static const char DebugString[] = "DEBUG"; 45 | static const char InfoString[] = "INFO "; 46 | static const char WarnString[] = "WARN "; 47 | static const char ErrorString[] = "ERROR"; 48 | static const char FatalString[] = "FATAL"; 49 | 50 | // not using Qt::ISODate because we need the milliseconds too 51 | static const QString fmtDateTime("yyyy-MM-ddThh:mm:ss.zzz"); 52 | 53 | static Logger* sInstance = 0; 54 | 55 | static const char* LevelToText(Level theLevel) 56 | { 57 | switch (theLevel) { 58 | case TraceLevel: 59 | return TraceString; 60 | case DebugLevel: 61 | return DebugString; 62 | case InfoLevel: 63 | return InfoString; 64 | case WarnLevel: 65 | return WarnString; 66 | case ErrorLevel: 67 | return ErrorString; 68 | case FatalLevel: 69 | return FatalString; 70 | case OffLevel: 71 | return ""; 72 | default: { 73 | Q_ASSERT(!"bad log level"); 74 | return InfoString; 75 | } 76 | } 77 | } 78 | 79 | #ifdef QS_LOG_SEPARATE_THREAD 80 | class LogWriterRunnable : public QRunnable 81 | { 82 | public: 83 | LogWriterRunnable(QString message, Level level); 84 | virtual void run(); 85 | 86 | private: 87 | QString mMessage; 88 | Level mLevel; 89 | }; 90 | #endif 91 | 92 | class LoggerImpl 93 | { 94 | public: 95 | LoggerImpl(); 96 | 97 | #ifdef QS_LOG_SEPARATE_THREAD 98 | QThreadPool threadPool; 99 | #endif 100 | QMutex logMutex; 101 | Level level; 102 | DestinationList destList; 103 | bool includeTimeStamp; 104 | bool includeLogLevel; 105 | }; 106 | 107 | #ifdef QS_LOG_SEPARATE_THREAD 108 | LogWriterRunnable::LogWriterRunnable(QString message, Level level) 109 | : QRunnable() 110 | , mMessage(message) 111 | , mLevel(level) 112 | { 113 | } 114 | 115 | void LogWriterRunnable::run() 116 | { 117 | Logger::instance().write(mMessage, mLevel); 118 | } 119 | #endif 120 | 121 | 122 | LoggerImpl::LoggerImpl() 123 | : level(InfoLevel) 124 | , includeTimeStamp(true) 125 | , includeLogLevel(true) 126 | { 127 | // assume at least file + console 128 | destList.reserve(2); 129 | #ifdef QS_LOG_SEPARATE_THREAD 130 | threadPool.setMaxThreadCount(1); 131 | threadPool.setExpiryTimeout(-1); 132 | #endif 133 | } 134 | 135 | 136 | Logger::Logger() 137 | : d(new LoggerImpl) 138 | { 139 | } 140 | 141 | Logger& Logger::instance() 142 | { 143 | if (!sInstance) 144 | sInstance = new Logger; 145 | 146 | return *sInstance; 147 | } 148 | 149 | void Logger::destroyInstance() 150 | { 151 | delete sInstance; 152 | sInstance = 0; 153 | } 154 | 155 | // tries to extract the level from a string log message. If available, conversionSucceeded will 156 | // contain the conversion result. 157 | Level Logger::levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded) 158 | { 159 | if (conversionSucceeded) 160 | *conversionSucceeded = true; 161 | 162 | if (logMessage.startsWith(QLatin1String(TraceString))) 163 | return TraceLevel; 164 | if (logMessage.startsWith(QLatin1String(DebugString))) 165 | return DebugLevel; 166 | if (logMessage.startsWith(QLatin1String(InfoString))) 167 | return InfoLevel; 168 | if (logMessage.startsWith(QLatin1String(WarnString))) 169 | return WarnLevel; 170 | if (logMessage.startsWith(QLatin1String(ErrorString))) 171 | return ErrorLevel; 172 | if (logMessage.startsWith(QLatin1String(FatalString))) 173 | return FatalLevel; 174 | 175 | if (conversionSucceeded) 176 | *conversionSucceeded = false; 177 | return OffLevel; 178 | } 179 | 180 | Logger::~Logger() 181 | { 182 | #ifdef QS_LOG_SEPARATE_THREAD 183 | d->threadPool.waitForDone(); 184 | #endif 185 | delete d; 186 | d = 0; 187 | } 188 | 189 | void Logger::addDestination(DestinationPtr destination) 190 | { 191 | Q_ASSERT(destination.data()); 192 | d->destList.push_back(destination); 193 | } 194 | 195 | void Logger::setLoggingLevel(Level newLevel) 196 | { 197 | d->level = newLevel; 198 | } 199 | 200 | Level Logger::loggingLevel() const 201 | { 202 | return d->level; 203 | } 204 | 205 | void Logger::setIncludeTimestamp(bool e) 206 | { 207 | d->includeTimeStamp = e; 208 | } 209 | 210 | bool Logger::includeTimestamp() const 211 | { 212 | return d->includeTimeStamp; 213 | } 214 | 215 | void Logger::setIncludeLogLevel(bool l) 216 | { 217 | d->includeLogLevel = l; 218 | } 219 | 220 | bool Logger::includeLogLevel() const 221 | { 222 | return d->includeLogLevel; 223 | } 224 | 225 | //! creates the complete log message and passes it to the logger 226 | void Logger::Helper::writeToLog() 227 | { 228 | const char* const levelName = LevelToText(level); 229 | QString completeMessage; 230 | Logger &logger = Logger::instance(); 231 | if (logger.includeLogLevel()) { 232 | completeMessage. 233 | append(levelName). 234 | append(' '); 235 | } 236 | if (logger.includeTimestamp()) { 237 | completeMessage. 238 | append(QDateTime::currentDateTime().toString(fmtDateTime)). 239 | append(' '); 240 | } 241 | completeMessage.append(buffer); 242 | Logger::instance().enqueueWrite(completeMessage, level); 243 | } 244 | 245 | Logger::Helper::~Helper() 246 | { 247 | try { 248 | writeToLog(); 249 | } 250 | catch(std::exception&) { 251 | // you shouldn't throw exceptions from a sink 252 | Q_ASSERT(!"exception in logger helper destructor"); 253 | throw; 254 | } 255 | } 256 | 257 | //! directs the message to the task queue or writes it directly 258 | void Logger::enqueueWrite(const QString& message, Level level) 259 | { 260 | #ifdef QS_LOG_SEPARATE_THREAD 261 | LogWriterRunnable *r = new LogWriterRunnable(message, level); 262 | d->threadPool.start(r); 263 | #else 264 | write(message, level); 265 | #endif 266 | } 267 | 268 | //! Sends the message to all the destinations. The level for this message is passed in case 269 | //! it's useful for processing in the destination. 270 | void Logger::write(const QString& message, Level level) 271 | { 272 | QMutexLocker lock(&d->logMutex); 273 | for (DestinationList::iterator it = d->destList.begin(), 274 | endIt = d->destList.end();it != endIt;++it) { 275 | (*it)->write(message, level); 276 | } 277 | } 278 | 279 | } // end namespace 280 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLog.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #ifndef QSLOG_H 27 | #define QSLOG_H 28 | 29 | #include "QsLogLevel.h" 30 | #include "QsLogDest.h" 31 | #include 32 | #include 33 | 34 | #define QS_LOG_VERSION "2.0b3" 35 | 36 | namespace QsLogging 37 | { 38 | class Destination; 39 | class LoggerImpl; // d pointer 40 | 41 | class QSLOG_SHARED_OBJECT Logger 42 | { 43 | public: 44 | static Logger& instance(); 45 | static void destroyInstance(); 46 | static Level levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded = 0); 47 | 48 | ~Logger(); 49 | 50 | //! Adds a log message destination. Don't add null destinations. 51 | void addDestination(DestinationPtr destination); 52 | //! Logging at a level < 'newLevel' will be ignored 53 | void setLoggingLevel(Level newLevel); 54 | //! The default level is INFO 55 | Level loggingLevel() const; 56 | //! Set to false to disable timestamp inclusion in log messages 57 | void setIncludeTimestamp(bool e); 58 | //! Default value is true. 59 | bool includeTimestamp() const; 60 | //! Set to false to disable log level inclusion in log messages 61 | void setIncludeLogLevel(bool l); 62 | //! Default value is true. 63 | bool includeLogLevel() const; 64 | 65 | //! The helper forwards the streaming to QDebug and builds the final 66 | //! log message. 67 | class QSLOG_SHARED_OBJECT Helper 68 | { 69 | public: 70 | explicit Helper(Level logLevel) : 71 | level(logLevel), 72 | qtDebug(&buffer) 73 | {} 74 | ~Helper(); 75 | QDebug& stream(){ return qtDebug; } 76 | 77 | private: 78 | void writeToLog(); 79 | 80 | Level level; 81 | QString buffer; 82 | QDebug qtDebug; 83 | }; 84 | 85 | private: 86 | Logger(); 87 | Logger(const Logger&); // not available 88 | Logger& operator=(const Logger&); // not available 89 | 90 | void enqueueWrite(const QString& message, Level level); 91 | void write(const QString& message, Level level); 92 | 93 | LoggerImpl* d; 94 | 95 | friend class LogWriterRunnable; 96 | }; 97 | 98 | } // end namespace 99 | 100 | //! Logging macros: define QS_LOG_LINE_NUMBERS to get the file and line number 101 | //! in the log output. 102 | #ifndef QS_LOG_LINE_NUMBERS 103 | #define QLOG_TRACE() \ 104 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ 105 | else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() 106 | #define QLOG_DEBUG() \ 107 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ 108 | else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() 109 | #define QLOG_INFO() \ 110 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ 111 | else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() 112 | #define QLOG_WARN() \ 113 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ 114 | else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() 115 | #define QLOG_ERROR() \ 116 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ 117 | else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() 118 | #define QLOG_FATAL() \ 119 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ 120 | else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() 121 | #else 122 | #define QLOG_TRACE() \ 123 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \ 124 | else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__ 125 | #define QLOG_DEBUG() \ 126 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \ 127 | else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__ 128 | #define QLOG_INFO() \ 129 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \ 130 | else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__ 131 | #define QLOG_WARN() \ 132 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \ 133 | else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__ 134 | #define QLOG_ERROR() \ 135 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \ 136 | else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__ 137 | #define QLOG_FATAL() \ 138 | if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \ 139 | else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__ 140 | #endif 141 | 142 | #ifdef QS_LOG_DISABLE 143 | #include "QsLogDisableForThisFile.h" 144 | #endif 145 | 146 | #endif // QSLOG_H 147 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLog.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | #DEFINES += QS_LOG_LINE_NUMBERS # automatically writes the file and line for each log message 3 | #DEFINES += QS_LOG_DISABLE # logging code is replaced with a no-op 4 | #DEFINES += QS_LOG_SEPARATE_THREAD # messages are queued and written from a separate thread 5 | SOURCES += $$PWD/QsLogDest.cpp \ 6 | $$PWD/QsLog.cpp \ 7 | $$PWD/QsLogDestConsole.cpp \ 8 | $$PWD/QsLogDestFile.cpp \ 9 | $$PWD/QsLogDestFunctor.cpp 10 | 11 | HEADERS += $$PWD/QsLogDest.h \ 12 | $$PWD/QsLog.h \ 13 | $$PWD/QsLogDestConsole.h \ 14 | $$PWD/QsLogLevel.h \ 15 | $$PWD/QsLogDestFile.h \ 16 | $$PWD/QsLogDisableForThisFile.h \ 17 | $$PWD/QsLogDestFunctor.h 18 | 19 | OTHER_FILES += \ 20 | $$PWD/QsLogChanges.txt \ 21 | $$PWD/QsLogReadme.txt \ 22 | $$PWD/LICENSE.txt 23 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogChanges.txt: -------------------------------------------------------------------------------- 1 | ------------------- 2 | QsLog version 2.0b4 3 | Fixes: 4 | Fixed file name case error for Linux. 5 | 6 | Misc: 7 | * Moved to separate git repository. 8 | 9 | ------------------- 10 | QsLog version 2.0b3 11 | 12 | Changes: 13 | * added functor logging destination (thanks to Omar Carey for providing a patch) 14 | 15 | ------------------- 16 | QsLog version 2.0b2 17 | 18 | Changes: 19 | * function signature redefinition for file destination creation 20 | * added shared library build configuration. Credit goes to Xavier Lamien 21 | for the Linux-specific config. 22 | * removed Symbian support 23 | * this version does not guarantee support for Nokia N9 devices, although it should in theory still 24 | work with them 25 | * workaround for Issue 8 - when used from an executable and a plugin QsLog only logs from the 26 | executable. 27 | * utility function to parse the level from an existing log message 28 | 29 | Known issues: 30 | * The current version will crash at program exit when using QS_LOG_SEPARATE_THREAD and linking 31 | with QsLog dynamically. 32 | 33 | ------------------- 34 | QsLog version 2.0b1 35 | 36 | Changes: 37 | * destination pointers use shared pointer semantics 38 | * the file destination supports log rotation. As a consequence, log files are encoded as UTF-8 and 39 | the log appends rather than truncating on every startup when rotation is enabled. 40 | * added the posibility of disabling logging either at run time or compile time. 41 | * added the possibility of using a separate thread for writing to the log destinations. 42 | 43 | Fixes: 44 | * renamed the main.cpp example to avoid QtCreator confusion 45 | * offer a way to check if the destination creation has failed (for e.g files) 46 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #include "QsLogDest.h" 27 | #include "QsLogDestConsole.h" 28 | #include "QsLogDestFile.h" 29 | #include "QsLogDestFunctor.h" 30 | #include 31 | 32 | namespace QsLogging 33 | { 34 | 35 | Destination::~Destination() 36 | { 37 | } 38 | 39 | //! destination factory 40 | DestinationPtr DestinationFactory::MakeFileDestination(const QString& filePath, 41 | LogRotationOption rotation, const MaxSizeBytes &sizeInBytesToRotateAfter, 42 | const MaxOldLogCount &oldLogsToKeep) 43 | { 44 | if (EnableLogRotation == rotation) { 45 | QScopedPointer logRotation(new SizeRotationStrategy); 46 | logRotation->setMaximumSizeInBytes(sizeInBytesToRotateAfter.size); 47 | logRotation->setBackupCount(oldLogsToKeep.count); 48 | 49 | return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(logRotation.take()))); 50 | } 51 | 52 | return DestinationPtr(new FileDestination(filePath, RotationStrategyPtr(new NullRotationStrategy))); 53 | } 54 | 55 | DestinationPtr DestinationFactory::MakeDebugOutputDestination() 56 | { 57 | return DestinationPtr(new DebugOutputDestination); 58 | } 59 | 60 | DestinationPtr DestinationFactory::MakeFunctorDestination(QsLogging::Destination::LogFunction f) 61 | { 62 | return DestinationPtr(new FunctorDestination(f)); 63 | } 64 | 65 | DestinationPtr DestinationFactory::MakeFunctorDestination(QObject *receiver, const char *member) 66 | { 67 | return DestinationPtr(new FunctorDestination(receiver, member)); 68 | } 69 | 70 | } // end namespace 71 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDest.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #ifndef QSLOGDEST_H 27 | #define QSLOGDEST_H 28 | 29 | #include "QsLogLevel.h" 30 | #include 31 | #include 32 | class QString; 33 | class QObject; 34 | 35 | #ifdef QSLOG_IS_SHARED_LIBRARY 36 | #define QSLOG_SHARED_OBJECT Q_DECL_EXPORT 37 | #elif QSLOG_IS_SHARED_LIBRARY_IMPORT 38 | #define QSLOG_SHARED_OBJECT Q_DECL_IMPORT 39 | #else 40 | #define QSLOG_SHARED_OBJECT 41 | #endif 42 | 43 | namespace QsLogging 44 | { 45 | 46 | class QSLOG_SHARED_OBJECT Destination 47 | { 48 | public: 49 | typedef void (*LogFunction)(const QString &message, Level level); 50 | 51 | public: 52 | virtual ~Destination(); 53 | virtual void write(const QString& message, Level level) = 0; 54 | virtual bool isValid() = 0; // returns whether the destination was created correctly 55 | }; 56 | typedef QSharedPointer DestinationPtr; 57 | 58 | 59 | // a series of "named" paramaters, to make the file destination creation more readable 60 | enum LogRotationOption 61 | { 62 | DisableLogRotation = 0, 63 | EnableLogRotation = 1 64 | }; 65 | 66 | struct QSLOG_SHARED_OBJECT MaxSizeBytes 67 | { 68 | MaxSizeBytes() : size(0) {} 69 | explicit MaxSizeBytes(qint64 size_) : size(size_) {} 70 | qint64 size; 71 | }; 72 | 73 | struct QSLOG_SHARED_OBJECT MaxOldLogCount 74 | { 75 | MaxOldLogCount() : count(0) {} 76 | explicit MaxOldLogCount(int count_) : count(count_) {} 77 | int count; 78 | }; 79 | 80 | 81 | //! Creates logging destinations/sinks. The caller shares ownership of the destinations with the logger. 82 | //! After being added to a logger, the caller can discard the pointers. 83 | class QSLOG_SHARED_OBJECT DestinationFactory 84 | { 85 | public: 86 | static DestinationPtr MakeFileDestination(const QString& filePath, 87 | LogRotationOption rotation = DisableLogRotation, 88 | const MaxSizeBytes &sizeInBytesToRotateAfter = MaxSizeBytes(), 89 | const MaxOldLogCount &oldLogsToKeep = MaxOldLogCount()); 90 | static DestinationPtr MakeDebugOutputDestination(); 91 | // takes a pointer to a function 92 | static DestinationPtr MakeFunctorDestination(Destination::LogFunction f); 93 | // takes a QObject + signal/slot 94 | static DestinationPtr MakeFunctorDestination(QObject *receiver, const char *member); 95 | }; 96 | 97 | } // end namespace 98 | 99 | #endif // QSLOGDEST_H 100 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestConsole.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #include "QsLogDestConsole.h" 27 | #include 28 | #include 29 | 30 | #if defined(Q_OS_WIN) 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | void QsDebugOutput::output( const QString& message ) 34 | { 35 | OutputDebugStringW(reinterpret_cast(message.utf16())); 36 | OutputDebugStringW(L"\n"); 37 | } 38 | #elif defined(Q_OS_UNIX) 39 | #include 40 | void QsDebugOutput::output( const QString& message ) 41 | { 42 | fprintf(stderr, "%s\n", qPrintable(message)); 43 | fflush(stderr); 44 | } 45 | #endif 46 | 47 | void QsLogging::DebugOutputDestination::write(const QString& message, Level) 48 | { 49 | QsDebugOutput::output(message); 50 | } 51 | 52 | bool QsLogging::DebugOutputDestination::isValid() 53 | { 54 | return true; 55 | } 56 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestConsole.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #ifndef QSLOGDESTCONSOLE_H 27 | #define QSLOGDESTCONSOLE_H 28 | 29 | #include "QsLogDest.h" 30 | 31 | class QString; 32 | 33 | class QsDebugOutput 34 | { 35 | public: 36 | static void output(const QString& a_message); 37 | }; 38 | 39 | namespace QsLogging 40 | { 41 | 42 | // debugger sink 43 | class DebugOutputDestination : public Destination 44 | { 45 | public: 46 | virtual void write(const QString& message, Level level); 47 | virtual bool isValid(); 48 | }; 49 | 50 | } 51 | 52 | #endif // QSLOGDESTCONSOLE_H 53 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestFile.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #include "QsLogDestFile.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | const int QsLogging::SizeRotationStrategy::MaxBackupCount = 10; 33 | 34 | QsLogging::RotationStrategy::~RotationStrategy() 35 | { 36 | } 37 | 38 | QsLogging::SizeRotationStrategy::SizeRotationStrategy() 39 | : mCurrentSizeInBytes(0) 40 | , mMaxSizeInBytes(0) 41 | , mBackupsCount(0) 42 | { 43 | } 44 | 45 | void QsLogging::SizeRotationStrategy::setInitialInfo(const QFile &file) 46 | { 47 | mFileName = file.fileName(); 48 | mCurrentSizeInBytes = file.size(); 49 | } 50 | 51 | void QsLogging::SizeRotationStrategy::includeMessageInCalculation(const QString &message) 52 | { 53 | mCurrentSizeInBytes += message.toUtf8().size(); 54 | } 55 | 56 | bool QsLogging::SizeRotationStrategy::shouldRotate() 57 | { 58 | return mCurrentSizeInBytes > mMaxSizeInBytes; 59 | } 60 | 61 | // Algorithm assumes backups will be named filename.X, where 1 <= X <= mBackupsCount. 62 | // All X's will be shifted up. 63 | void QsLogging::SizeRotationStrategy::rotate() 64 | { 65 | if (!mBackupsCount) { 66 | if (!QFile::remove(mFileName)) 67 | std::cerr << "QsLog: backup delete failed " << qPrintable(mFileName); 68 | return; 69 | } 70 | 71 | // 1. find the last existing backup than can be shifted up 72 | const QString logNamePattern = mFileName + QString::fromUtf8(".%1"); 73 | int lastExistingBackupIndex = 0; 74 | for (int i = 1;i <= mBackupsCount;++i) { 75 | const QString backupFileName = logNamePattern.arg(i); 76 | if (QFile::exists(backupFileName)) 77 | lastExistingBackupIndex = qMin(i, mBackupsCount - 1); 78 | else 79 | break; 80 | } 81 | 82 | // 2. shift up 83 | for (int i = lastExistingBackupIndex;i >= 1;--i) { 84 | const QString oldName = logNamePattern.arg(i); 85 | const QString newName = logNamePattern.arg(i + 1); 86 | QFile::remove(newName); 87 | const bool renamed = QFile::rename(oldName, newName); 88 | if (!renamed) { 89 | std::cerr << "QsLog: could not rename backup " << qPrintable(oldName) 90 | << " to " << qPrintable(newName); 91 | } 92 | } 93 | 94 | // 3. rename current log file 95 | const QString newName = logNamePattern.arg(1); 96 | if (QFile::exists(newName)) 97 | QFile::remove(newName); 98 | if (!QFile::rename(mFileName, newName)) { 99 | std::cerr << "QsLog: could not rename log " << qPrintable(mFileName) 100 | << " to " << qPrintable(newName); 101 | } 102 | } 103 | 104 | QIODevice::OpenMode QsLogging::SizeRotationStrategy::recommendedOpenModeFlag() 105 | { 106 | return QIODevice::Append; 107 | } 108 | 109 | void QsLogging::SizeRotationStrategy::setMaximumSizeInBytes(qint64 size) 110 | { 111 | Q_ASSERT(size >= 0); 112 | mMaxSizeInBytes = size; 113 | } 114 | 115 | void QsLogging::SizeRotationStrategy::setBackupCount(int backups) 116 | { 117 | Q_ASSERT(backups >= 0); 118 | mBackupsCount = qMin(backups, SizeRotationStrategy::MaxBackupCount); 119 | } 120 | 121 | 122 | QsLogging::FileDestination::FileDestination(const QString& filePath, RotationStrategyPtr rotationStrategy) 123 | : mRotationStrategy(rotationStrategy) 124 | { 125 | mFile.setFileName(filePath); 126 | if (!mFile.open(QFile::WriteOnly | QFile::Text | mRotationStrategy->recommendedOpenModeFlag())) 127 | std::cerr << "QsLog: could not open log file " << qPrintable(filePath); 128 | mOutputStream.setDevice(&mFile); 129 | 130 | #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) 131 | //TODO sunqt6 132 | mOutputStream.setCodec(QTextCodec::codecForName("UTF-8")); 133 | #endif 134 | 135 | mRotationStrategy->setInitialInfo(mFile); 136 | } 137 | 138 | void QsLogging::FileDestination::write(const QString& message, Level) 139 | { 140 | mRotationStrategy->includeMessageInCalculation(message); 141 | if (mRotationStrategy->shouldRotate()) { 142 | mOutputStream.setDevice(NULL); 143 | mFile.close(); 144 | mRotationStrategy->rotate(); 145 | if (!mFile.open(QFile::WriteOnly | QFile::Text | mRotationStrategy->recommendedOpenModeFlag())) 146 | std::cerr << "QsLog: could not reopen log file " << qPrintable(mFile.fileName()); 147 | mRotationStrategy->setInitialInfo(mFile); 148 | mOutputStream.setDevice(&mFile); 149 | } 150 | #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) 151 | //TODO sunqt6 152 | mOutputStream << message << "\n"; 153 | #else 154 | mOutputStream << message << endl; 155 | #endif 156 | 157 | mOutputStream.flush(); 158 | } 159 | 160 | bool QsLogging::FileDestination::isValid() 161 | { 162 | return mFile.isOpen(); 163 | } 164 | 165 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestFile.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #ifndef QSLOGDESTFILE_H 27 | #define QSLOGDESTFILE_H 28 | 29 | #include "QsLogDest.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace QsLogging 36 | { 37 | class RotationStrategy 38 | { 39 | public: 40 | virtual ~RotationStrategy(); 41 | 42 | virtual void setInitialInfo(const QFile &file) = 0; 43 | virtual void includeMessageInCalculation(const QString &message) = 0; 44 | virtual bool shouldRotate() = 0; 45 | virtual void rotate() = 0; 46 | virtual QIODevice::OpenMode recommendedOpenModeFlag() = 0; 47 | }; 48 | 49 | // Never rotates file, overwrites existing file. 50 | class NullRotationStrategy : public RotationStrategy 51 | { 52 | public: 53 | virtual void setInitialInfo(const QFile &) {} 54 | virtual void includeMessageInCalculation(const QString &) {} 55 | virtual bool shouldRotate() { return false; } 56 | virtual void rotate() {} 57 | virtual QIODevice::OpenMode recommendedOpenModeFlag() { return QIODevice::Truncate; } 58 | }; 59 | 60 | // Rotates after a size is reached, keeps a number of <= 10 backups, appends to existing file. 61 | class SizeRotationStrategy : public RotationStrategy 62 | { 63 | public: 64 | SizeRotationStrategy(); 65 | static const int MaxBackupCount; 66 | 67 | virtual void setInitialInfo(const QFile &file); 68 | virtual void includeMessageInCalculation(const QString &message); 69 | virtual bool shouldRotate(); 70 | virtual void rotate(); 71 | virtual QIODevice::OpenMode recommendedOpenModeFlag(); 72 | 73 | void setMaximumSizeInBytes(qint64 size); 74 | void setBackupCount(int backups); 75 | 76 | private: 77 | QString mFileName; 78 | qint64 mCurrentSizeInBytes; 79 | qint64 mMaxSizeInBytes; 80 | int mBackupsCount; 81 | }; 82 | 83 | typedef QSharedPointer RotationStrategyPtr; 84 | 85 | // file message sink 86 | class FileDestination : public Destination 87 | { 88 | public: 89 | FileDestination(const QString& filePath, RotationStrategyPtr rotationStrategy); 90 | virtual void write(const QString& message, Level level); 91 | virtual bool isValid(); 92 | 93 | private: 94 | QFile mFile; 95 | QTextStream mOutputStream; 96 | QSharedPointer mRotationStrategy; 97 | }; 98 | 99 | } 100 | 101 | #endif // QSLOGDESTFILE_H 102 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestFunctor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Razvan Petru 2 | // Copyright (c) 2014, Omar Carey 3 | // All rights reserved. 4 | 5 | // Redistribution and use in source and binary forms, with or without modification, 6 | // are permitted provided that the following conditions are met: 7 | 8 | // * Redistributions of source code must retain the above copyright notice, this 9 | // list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright notice, this 11 | // list of conditions and the following disclaimer in the documentation and/or other 12 | // materials provided with the distribution. 13 | // * The name of the contributors may not be used to endorse or promote products 14 | // derived from this software without specific prior written permission. 15 | 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 24 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 25 | // OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | #include "QsLogDestFunctor.h" 28 | #include 29 | #include 30 | 31 | QsLogging::FunctorDestination::FunctorDestination(LogFunction f) 32 | : QObject(NULL) 33 | , mLogFunction(f) 34 | { 35 | } 36 | 37 | QsLogging::FunctorDestination::FunctorDestination(QObject *receiver, const char *member) 38 | : QObject(NULL) 39 | , mLogFunction(NULL) 40 | { 41 | connect(this, SIGNAL(logMessageReady(QString,int)), receiver, member, Qt::QueuedConnection); 42 | } 43 | 44 | 45 | void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level) 46 | { 47 | if (mLogFunction) 48 | mLogFunction(message, level); 49 | 50 | if (level > QsLogging::TraceLevel) 51 | emit logMessageReady(message, static_cast(level)); 52 | } 53 | 54 | bool QsLogging::FunctorDestination::isValid() 55 | { 56 | return true; 57 | } 58 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDestFunctor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Razvan Petru 2 | // Copyright (c) 2014, Omar Carey 3 | // All rights reserved. 4 | 5 | // Redistribution and use in source and binary forms, with or without modification, 6 | // are permitted provided that the following conditions are met: 7 | 8 | // * Redistributions of source code must retain the above copyright notice, this 9 | // list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright notice, this 11 | // list of conditions and the following disclaimer in the documentation and/or other 12 | // materials provided with the distribution. 13 | // * The name of the contributors may not be used to endorse or promote products 14 | // derived from this software without specific prior written permission. 15 | 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 24 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 25 | // OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | #ifndef QSLOGDESTFUNCTOR_H 28 | #define QSLOGDESTFUNCTOR_H 29 | 30 | #include "QsLogDest.h" 31 | #include 32 | 33 | namespace QsLogging 34 | { 35 | // Offers various types of function-like sinks. 36 | // This is an advanced destination type. Depending on your configuration, LogFunction might be 37 | // called from a different thread or even a different binary. You should not access QsLog from 38 | // inside LogFunction and should not perform any time-consuming operations. 39 | // logMessageReady is connected through a queued connection and trace messages are not included 40 | class FunctorDestination : public QObject, public Destination 41 | { 42 | Q_OBJECT 43 | public: 44 | explicit FunctorDestination(LogFunction f); 45 | FunctorDestination(QObject *receiver, const char *member); 46 | 47 | virtual void write(const QString &message, Level level); 48 | virtual bool isValid(); 49 | 50 | protected: 51 | // int used to avoid registering a new enum type 52 | Q_SIGNAL void logMessageReady(const QString &message, int level); 53 | 54 | private: 55 | LogFunction mLogFunction; 56 | }; 57 | } 58 | 59 | #endif // QSLOGDESTFUNCTOR_H 60 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogDisableForThisFile.h: -------------------------------------------------------------------------------- 1 | #ifndef QSLOGDISABLEFORTHISFILE_H 2 | #define QSLOGDISABLEFORTHISFILE_H 3 | 4 | #include 5 | // When included AFTER QsLog.h, this file will disable logging in that C++ file. When included 6 | // before, it will lead to compiler warnings or errors about macro redefinitions. 7 | 8 | #undef QLOG_TRACE 9 | #undef QLOG_DEBUG 10 | #undef QLOG_INFO 11 | #undef QLOG_WARN 12 | #undef QLOG_ERROR 13 | #undef QLOG_FATAL 14 | 15 | #define QLOG_TRACE() if (1) {} else qDebug() 16 | #define QLOG_DEBUG() if (1) {} else qDebug() 17 | #define QLOG_INFO() if (1) {} else qDebug() 18 | #define QLOG_WARN() if (1) {} else qDebug() 19 | #define QLOG_ERROR() if (1) {} else qDebug() 20 | #define QLOG_FATAL() if (1) {} else qDebug() 21 | 22 | #endif // QSLOGDISABLEFORTHISFILE_H 23 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogLevel.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Razvan Petru 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without modification, 5 | // are permitted provided that the following conditions are met: 6 | 7 | // * Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this 10 | // list of conditions and the following disclaimer in the documentation and/or other 11 | // materials provided with the distribution. 12 | // * The name of the contributors may not be used to endorse or promote products 13 | // derived from this software without specific prior written permission. 14 | 15 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 19 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | // OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | #ifndef QSLOGLEVEL_H 27 | #define QSLOGLEVEL_H 28 | 29 | namespace QsLogging 30 | { 31 | 32 | enum Level 33 | { 34 | TraceLevel = 0, 35 | DebugLevel, 36 | InfoLevel, 37 | WarnLevel, 38 | ErrorLevel, 39 | FatalLevel, 40 | OffLevel 41 | }; 42 | 43 | } 44 | 45 | #endif // QSLOGLEVEL_H 46 | -------------------------------------------------------------------------------- /3rdparty/QsLog/QsLogSharedLibrary.pro: -------------------------------------------------------------------------------- 1 | # This pro file will build QsLog as a shared library 2 | include(QsLog.pri) 3 | 4 | TARGET = QsLog 5 | VERSION = "2.0.0" 6 | QT -= gui 7 | CONFIG -= console 8 | CONFIG -= app_bundle 9 | CONFIG += shared 10 | TEMPLATE = lib 11 | 12 | DESTDIR = $$PWD/build-QsLogShared 13 | OBJECTS_DIR = $$DESTDIR/obj 14 | MOC_DIR = $$DESTDIR/moc 15 | 16 | win32 { 17 | DEFINES += QSLOG_IS_SHARED_LIBRARY 18 | } 19 | 20 | unix:!macx { 21 | # make install will install the shared object in the appropriate folders 22 | headers.files = QsLog.h QsLogDest.h QsLogLevel.h 23 | headers.path = /usr/include/$(QMAKE_TARGET) 24 | 25 | other_files.files = *.txt 26 | other_files.path = /usr/local/share/$(QMAKE_TARGET) 27 | 28 | contains(QT_ARCH, x86_64) { 29 | target.path = /usr/lib64 30 | } else { 31 | target.path = /usr/lib 32 | } 33 | 34 | INSTALLS += headers target other_files 35 | } 36 | -------------------------------------------------------------------------------- /3rdparty/QsLog/README.md: -------------------------------------------------------------------------------- 1 | ## QsLog - the simple Qt logger ## 2 | QsLog is an easy to use logger that is based on Qt's QDebug class. QsLog is released as open source, under the MIT license. 3 | 4 | ###Contribution policy### 5 | Bug fixes are welcome, larger changes however are not encouraged at this point due to the lack of time on my side for reviewing and integrating them. Your best bet in this case would be to open a ticket for your change or forking the project and implementing your change there, with the possibility of having it integrated in the future. 6 | All contributions will be credited, license of the contributions should be MIT. 7 | 8 | ### Features ### 9 | * Six logging levels (from trace to fatal) 10 | * Logging level threshold configurable at runtime. 11 | * Minimum overhead when logging is turned off. 12 | * Supports multiple destinations, comes with file and debug destinations. 13 | * Thread-safe 14 | * Supports logging of common Qt types out of the box. 15 | * Small dependency: just drop it in your project directly. 16 | 17 | ### Usage ### 18 | * Include QsLog.h. Include QsLogDest.h only where you create/add destinations. 19 | * Get the instance of the logger by calling QsLogging::Logger::instance(); 20 | * Optionally set the logging level. Info is default. 21 | * Create as many destinations as you want by using the QsLogging::DestinationFactory. 22 | * Add the destinations to the logger instance by calling addDestination. 23 | 24 | **Note**: The logger does not take ownership of the destinations. Make sure that the destinations still exist when you call one of the logging macros. A good place to create the destinations is the program's main function. 25 | 26 | ### Disabling logging ### 27 | Sometimes it's necessary to turn off logging. This can be done in several ways: 28 | 29 | * globally, at compile time, by enabling the QS_LOG_DISABLE macro in the supplied .pri file. 30 | * globally, at run time, by setting the log level to "OffLevel". 31 | * per file, at compile time, by including QsLogDisableForThisFile.h in the target file. 32 | 33 | ### Thread safety ### 34 | The Qt docs say: 35 | A **thread-safe** function can be called simultaneously from multiple threads, even when the invocations use shared data, because all references to the shared data are serialized. 36 | A **reentrant** function can also be called simultaneously from multiple threads, but only if each invocation uses its own data. 37 | 38 | Since sending the log message to the destinations is protected by a mutex, the logging macros are thread-safe provided that the log has been initialized - i.e: instance() has been called. 39 | The instance function and the setup functions (e.g: setLoggingLevel, addDestination) are NOT thread-safe and are NOT reentrant. -------------------------------------------------------------------------------- /Index/About.cpp: -------------------------------------------------------------------------------- 1 | #include "About.h" 2 | #include "constant.h" 3 | #include "ComLineWidget.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | About::About(QWidget *parent) : QDialog(parent) 14 | { 15 | 16 | setWindowFlags(Qt::Dialog| Qt::WindowCloseButtonHint); 17 | setAttribute(Qt::WA_StyledBackground,true); 18 | setWindowTitle("关于"); 19 | setFixedSize(660,340); 20 | 21 | mainVLayout = new QVBoxLayout(this); 22 | mainVLayout->setContentsMargins(0,0,0,0); 23 | mainVLayout->setSpacing(0); 24 | 25 | mainVLayout->addSpacing(10); 26 | initTopUi(); 27 | mainVLayout->addSpacing(10); 28 | initBottomUi(); 29 | mainVLayout->addStretch(10); 30 | } 31 | 32 | void About::initTopUi(){ 33 | 34 | QWidget *outWidget = new QWidget(this); 35 | outWidget->setFixedSize(600,140); 36 | outWidget->setStyleSheet(".QWidget{background-color:rgb(205,205,205);border-radius: 5px;}"); 37 | QVBoxLayout *outLayout = new QVBoxLayout(outWidget); 38 | outLayout->setContentsMargins(1,1,1,1); 39 | 40 | QWidget *topWidget = new QWidget(outWidget); 41 | topWidget->setStyleSheet(".QWidget{background-color:rgb(255,255,255);border-radius: 5px;}"); 42 | QVBoxLayout *topLayout = new QVBoxLayout(topWidget); 43 | topLayout->setContentsMargins(0,0,0,0); 44 | // about logo+名称 45 | QWidget *logoWidget = new QWidget(topWidget); 46 | logoWidget->setFixedHeight(60); 47 | QHBoxLayout *logoHLayout = new QHBoxLayout(logoWidget); 48 | logoHLayout->setContentsMargins(0,0,0,0); 49 | 50 | QLabel *logo = new QLabel(logoWidget); 51 | logo->setPixmap(QIcon(":/res/images/logo.png").pixmap(36,40)); 52 | 53 | QLabel *nameLabel = new QLabel(logoWidget); 54 | nameLabel->setStyleSheet(".QLabel{color:rgb(0,0,0);font-family:Microsoft YaHei;font-size:30px;}"); 55 | nameLabel->setText(QCoreApplication::applicationName()); 56 | 57 | logoHLayout->addSpacing(20); 58 | logoHLayout->addWidget(logo); 59 | logoHLayout->addSpacing(10); 60 | logoHLayout->addWidget(nameLabel); 61 | logoHLayout->addStretch(10); 62 | 63 | 64 | // about-声明 65 | QWidget *smWidget = new QWidget(topWidget); 66 | QHBoxLayout *smHLayout = new QHBoxLayout(smWidget); 67 | smHLayout->setContentsMargins(0,0,0,0); 68 | smWidget->setFixedHeight(60); 69 | 70 | QLabel *smContentLabel = new QLabel(smWidget); 71 | smContentLabel->setFixedWidth(500); 72 | // smContentLabel->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 73 | smContentLabel->setWordWrap(true); 74 | smContentLabel->setText(tr("

一个Qt开发的免费开源的国产录屏软件,将来还会扩展类似于VNC一样的远程控制的功能。

")); 75 | smHLayout->addSpacing(10); 76 | smHLayout->addWidget(smContentLabel); 77 | smHLayout->addStretch(10); 78 | 79 | 80 | topLayout->addWidget(logoWidget); 81 | topLayout->addWidget(new ComLineWidget(this)); 82 | topLayout->addWidget(smWidget); 83 | topLayout->addStretch(10); 84 | outLayout->addWidget(topWidget); 85 | mainVLayout->addWidget(outWidget,0,Qt::AlignHCenter); 86 | 87 | } 88 | 89 | void About::initBottomUi(){ 90 | QWidget *outWidget = new QWidget(this); 91 | outWidget->setFixedSize(600,130); 92 | outWidget->setStyleSheet(".QWidget{background-color:rgb(205,205,205);border-radius: 5px;}"); 93 | QVBoxLayout *outLayout = new QVBoxLayout(outWidget); 94 | outLayout->setContentsMargins(1,1,1,1); 95 | 96 | QWidget * bottomWidget = new QWidget(outWidget); 97 | bottomWidget->setStyleSheet(".QWidget{background-color:rgb(255,255,255);border-radius: 5px;}"); 98 | QVBoxLayout *bottomVLayout = new QVBoxLayout(bottomWidget); 99 | bottomVLayout->setContentsMargins(20,10,20,10); 100 | 101 | QLabel *copyrightLabel = new QLabel(bottomWidget); 102 | copyrightLabel->setStyleSheet(".QLabel{color:rgb(0,0,0);font-family:Microsoft YaHei;font-size:14px;}"); 103 | copyrightLabel->setText(QString("当前版本 V%1").arg(QCoreApplication::applicationVersion())); 104 | 105 | QLabel *authorLabel = new QLabel(bottomWidget); 106 | authorLabel->setStyleSheet(".QLabel{color:rgb(0,0,0);font-family:Microsoft YaHei;font-size:14px;}"); 107 | authorLabel->setText(tr("作者 北小菜")); 108 | authorLabel->setOpenExternalLinks(true); 109 | connect(authorLabel,&QLabel::linkActivated,this,[](const QString &link){ 110 | QDesktopServices::openUrl(QUrl(link)); 111 | }); 112 | 113 | 114 | 115 | // 开源地址 start 116 | QWidget *osWidget = new QWidget(bottomWidget);// 开源地址 117 | osWidget->setFixedHeight(20); 118 | QHBoxLayout *osHLayout = new QHBoxLayout(osWidget); 119 | osHLayout->setContentsMargins(0,0,0,0); 120 | 121 | QLabel *osLabel = new QLabel(osWidget); 122 | osLabel->setStyleSheet(".QLabel{color:rgb(0,0,0);font-family:Microsoft YaHei;font-size:14px;}"); 123 | osLabel->setText("开源地址"); 124 | QToolButton *osAddressBtn = new QToolButton(osWidget); 125 | osAddressBtn->setCursor(Qt::PointingHandCursor); 126 | osAddressBtn->setStyleSheet("QToolButton{border:0px;font-family:Microsoft YaHei;font-size:13px;color:rgb(43,113,237)}"); 127 | osAddressBtn->setText(URL_OPENSOURCE); 128 | connect(osAddressBtn,&QToolButton::clicked,this,[](){ 129 | QDesktopServices::openUrl(QUrl(URL_OPENSOURCE)); 130 | }); 131 | 132 | osHLayout->addWidget(osLabel); 133 | osHLayout->addSpacing(6); 134 | osHLayout->addWidget(osAddressBtn); 135 | osHLayout->addStretch(10); 136 | // 开源地址 end 137 | 138 | bottomVLayout->addSpacing(10); 139 | bottomVLayout->addWidget(copyrightLabel); 140 | bottomVLayout->addWidget(authorLabel); 141 | bottomVLayout->addSpacing(10); 142 | bottomVLayout->addWidget(new ComLineWidget(this)); 143 | bottomVLayout->addWidget(osWidget); 144 | bottomVLayout->addStretch(10); 145 | 146 | outLayout->addWidget(bottomWidget); 147 | mainVLayout->addWidget(outWidget,0,Qt::AlignHCenter); 148 | 149 | } 150 | -------------------------------------------------------------------------------- /Index/About.h: -------------------------------------------------------------------------------- 1 | #ifndef ABOUT_H 2 | #define ABOUT_H 3 | 4 | #include 5 | QT_BEGIN_NAMESPACE; 6 | class QVBoxLayout; 7 | QT_END_NAMESPACE; 8 | 9 | class About : public QDialog 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit About(QWidget *parent); 14 | private: 15 | QVBoxLayout *mainVLayout; 16 | 17 | void initTopUi(); 18 | void initBottomUi(); 19 | 20 | signals: 21 | 22 | }; 23 | 24 | #endif // ABOUT_H 25 | -------------------------------------------------------------------------------- /Index/Index.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/IndexWidget.h \ 3 | $$PWD/Settings.h \ 4 | $$PWD/About.h 5 | 6 | SOURCES += \ 7 | $$PWD/IndexWidget.cpp \ 8 | $$PWD/Settings.cpp \ 9 | $$PWD/About.cpp 10 | 11 | INCLUDEPATH += Index 12 | -------------------------------------------------------------------------------- /Index/IndexWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "IndexWidget.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "ComLineWidget.h" 18 | #include "ComMessageBox.h" 19 | #include "constant.h" 20 | #include "RecordWidget.h" 21 | #include "About.h" 22 | #include "Settings.h" 23 | #include "VNCClientWidget.h" 24 | #include "VNCServerWidget.h" 25 | #include "Utils.h" 26 | #include "SingletonUtils.h" 27 | 28 | IndexWidget::IndexWidget(QWidget *parent) : QWidget(parent) 29 | { 30 | setAttribute(Qt::WA_StyledBackground,true); 31 | setStyleSheet(".IndexWidget{background-color:rgb(76,76,76);}");//31,33,42->76,76,76 32 | initUi(); 33 | initSettings(); 34 | 35 | } 36 | void IndexWidget::initUi(){ 37 | QHBoxLayout *mainHLayout = new QHBoxLayout(this); 38 | mainHLayout->setContentsMargins(0,0,0,0); 39 | mainHLayout->setSpacing(0); 40 | 41 | QWidget *leftWidget = initLeftWidget(); 42 | leftWidget->setFixedWidth(200); 43 | 44 | QWidget *rightWidget = initRightWidget(); 45 | mainHLayout->addWidget(leftWidget); 46 | mainHLayout->addSpacing(1); 47 | mainHLayout->addWidget(rightWidget); 48 | } 49 | QWidget* IndexWidget::initLeftWidget(){ 50 | QWidget * widget = new QWidget(this); 51 | widget->setStyleSheet(QString(".QWidget{background-color:%1;}").arg("rgb(43,46,56)")); 52 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 53 | widgetVLayout->setContentsMargins(0,0,0,0); 54 | widgetVLayout->setSpacing(0); 55 | 56 | QSize size(140,40); 57 | 58 | vncServerBtn = new QPushButton(widget); 59 | vncServerBtn->setCursor(Qt::PointingHandCursor); 60 | vncServerBtn->setStyleSheet(left_btn_no_background); 61 | vncServerBtn->setFixedSize(size); 62 | vncServerBtn->setText("远程协助"); 63 | 64 | vncClientBtn = new QPushButton(widget); 65 | vncClientBtn->setCursor(Qt::PointingHandCursor); 66 | vncClientBtn->setStyleSheet(left_btn_no_background); 67 | vncClientBtn->setFixedSize(size); 68 | vncClientBtn->setText("远程控制"); 69 | 70 | recordBtn = new QPushButton(widget); 71 | recordBtn->setCursor(Qt::PointingHandCursor); 72 | recordBtn->setStyleSheet(left_btn_no_background_selected); 73 | recordBtn->setFixedSize(size); 74 | recordBtn->setText("录制屏幕"); 75 | 76 | connect(vncServerBtn,&QPushButton::clicked,this,[this](){ 77 | vncServerBtn->setStyleSheet(left_btn_no_background_selected); 78 | vncClientBtn->setStyleSheet(left_btn_no_background); 79 | recordBtn->setStyleSheet(left_btn_no_background); 80 | 81 | this->rightStackedWidget->setCurrentWidget(vncServerWidget); 82 | 83 | }); 84 | connect(vncClientBtn,&QPushButton::clicked,this,[this](){ 85 | vncServerBtn->setStyleSheet(left_btn_no_background); 86 | vncClientBtn->setStyleSheet(left_btn_no_background_selected); 87 | recordBtn->setStyleSheet(left_btn_no_background); 88 | this->rightStackedWidget->setCurrentWidget(vncClientWidget); 89 | }); 90 | connect(recordBtn,&QPushButton::clicked,this,[this](){ 91 | vncServerBtn->setStyleSheet(left_btn_no_background); 92 | vncClientBtn->setStyleSheet(left_btn_no_background); 93 | recordBtn->setStyleSheet(left_btn_no_background_selected); 94 | this->rightStackedWidget->setCurrentWidget(recordWidget); 95 | }); 96 | 97 | 98 | // 菜单start 99 | QMenu *settingsMenu = new QMenu(this); 100 | 101 | QAction *settingsAct = settingsMenu->addAction("设置"); 102 | settingsAct->setShortcuts(QKeySequence::WhatsThis); 103 | connect(settingsAct, &QAction::triggered, this, [this]() { 104 | Settings dlg(this); 105 | dlg.exec(); 106 | }); 107 | 108 | QAction *aboutAct = settingsMenu->addAction("关于"); 109 | aboutAct->setShortcuts(QKeySequence::Preferences); 110 | connect(aboutAct, &QAction::triggered, this, [this]() { 111 | About dlg(this); 112 | dlg.exec(); 113 | }); 114 | QAction *feedbackAct = settingsMenu->addAction("反馈"); 115 | connect(feedbackAct, &QAction::triggered, this, []() { 116 | QDesktopServices::openUrl(QUrl(SRE_URL_FEEDBACK)); 117 | }); 118 | 119 | QAction *logoutAct = settingsMenu->addAction("退出"); 120 | logoutAct->setShortcuts(QKeySequence::Quit); 121 | connect(logoutAct, &QAction::triggered, this, [this]() { 122 | switch (QMessageBox::information(this,"提示","确认要退出吗?","确定","取消",0)){ 123 | case 0:{ 124 | 125 | QApplication* app; 126 | app->quit(); 127 | break; 128 | } 129 | } 130 | }); 131 | 132 | 133 | 134 | settingsMenu->addAction(settingsAct); 135 | settingsMenu->addSeparator(); 136 | settingsMenu->addAction(aboutAct); 137 | settingsMenu->addSeparator(); 138 | settingsMenu->addAction(feedbackAct); 139 | settingsMenu->addSeparator(); 140 | settingsMenu->addAction(logoutAct); 141 | // 菜单end 142 | 143 | QPushButton *settingsBtn = new QPushButton(widget); 144 | settingsBtn->setIcon(QIcon(":/res/images/icon/settings.png")); 145 | settingsBtn->setText("菜单"); 146 | settingsBtn->setStyleSheet(".QPushButton {color:rgb(255,255,255);font-size:16px;border:1px solid rgb(76,76,76); border-radius: 3px;padding: 2px;}\ 147 | .QPushButton:hover {background-color: rgb(53,53,53);}\ 148 | .QPushButton:focus{outline: none;}"); 149 | settingsBtn->setCursor(Qt::PointingHandCursor); 150 | settingsBtn->setFixedSize(100,40); 151 | connect(settingsBtn,&QPushButton::clicked,this,[this,settingsMenu](){ 152 | settingsMenu->exec(QCursor::pos()); 153 | }); 154 | 155 | widgetVLayout->addSpacing(60); 156 | widgetVLayout->addWidget(vncServerBtn,0,Qt::AlignHCenter); 157 | widgetVLayout->addSpacing(20); 158 | widgetVLayout->addWidget(vncClientBtn,0,Qt::AlignHCenter); 159 | widgetVLayout->addSpacing(20); 160 | widgetVLayout->addWidget(recordBtn,0,Qt::AlignHCenter); 161 | widgetVLayout->addStretch(10); 162 | widgetVLayout->addWidget(settingsBtn,0,Qt::AlignHCenter); 163 | widgetVLayout->addSpacing(20); 164 | return widget; 165 | } 166 | QWidget* IndexWidget::initRightWidget(){ 167 | QWidget * widget = new QWidget(this); 168 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 169 | widgetVLayout->setContentsMargins(0,0,0,0); 170 | widgetVLayout->setSpacing(0); 171 | 172 | // StackedWidget start 173 | rightStackedWidget = new QStackedWidget(widget); 174 | rightStackedWidget->setStyleSheet(QString(".QStackedWidget{background-color:%1;}").arg("rgb(43,46,56)")); 175 | 176 | recordWidget = new RecordWidget(this); 177 | vncServerWidget = new VNCServerWidget(this); 178 | vncClientWidget = new VNCClientWidget(this); 179 | 180 | rightStackedWidget->addWidget(recordWidget); 181 | rightStackedWidget->addWidget(vncServerWidget); 182 | rightStackedWidget->addWidget(vncClientWidget); 183 | 184 | rightStackedWidget->setCurrentWidget(recordWidget); 185 | // StackedWidget end 186 | 187 | widgetVLayout->addWidget(rightStackedWidget); 188 | 189 | return widget; 190 | } 191 | void IndexWidget::initSettings(){ 192 | QSettings settings; 193 | 194 | QString dirVal = settings.value(SRE_SETTINGS_DIR).toString(); 195 | if(dirVal.isEmpty()){ 196 | dirVal = QApplication::applicationDirPath() + "/Record"; 197 | Utils::mkDirs(dirVal); 198 | settings.setValue(SRE_SETTINGS_DIR,dirVal); 199 | } 200 | SingletonUtils::getInstance()->setRecordDir(dirVal); 201 | } 202 | -------------------------------------------------------------------------------- /Index/IndexWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef INDEXWIDGET_H 2 | #define INDEXWIDGET_H 3 | 4 | #include 5 | QT_BEGIN_NAMESPACE; 6 | class QCheckBox; 7 | class QLineEdit; 8 | class QPushButton; 9 | class QStackedWidget; 10 | QT_END_NAMESPACE; 11 | class RecordWidget; 12 | class VNCClientWidget; 13 | class VNCServerWidget; 14 | 15 | class IndexWidget : public QWidget 16 | { 17 | Q_OBJECT 18 | public: 19 | explicit IndexWidget(QWidget *parent); 20 | 21 | private: 22 | void initUi(); 23 | void initSettings(); 24 | QWidget* initLeftWidget(); 25 | //按钮无背景 26 | const QString left_btn_no_background = ".QPushButton {color:rgb(255,255,255);font-size:15px;border:1px solid rgb(76,76,76); border-radius: 3px;padding: 2px;}\ 27 | .QPushButton:hover {background-color: rgb(53,53,53);}\ 28 | .QPushButton:focus{outline: none;}"; 29 | //按钮无背景-选中 30 | const QString left_btn_no_background_selected = ".QPushButton {color:rgb(221,58,95);background-color: rgb(53,53,53);font-size:15px;border:1px solid rgb(76,76,76); border-radius: 3px;padding: 2px;}\ 31 | .QPushButton:focus{outline: none;}"; 32 | QPushButton *vncServerBtn; 33 | QPushButton *vncClientBtn; 34 | QPushButton *recordBtn; 35 | 36 | QWidget* initRightWidget(); 37 | QStackedWidget *rightStackedWidget; 38 | RecordWidget *recordWidget; 39 | VNCClientWidget *vncClientWidget; 40 | VNCServerWidget *vncServerWidget; 41 | 42 | signals: 43 | 44 | }; 45 | 46 | #endif // INDEXWIDGET_H 47 | -------------------------------------------------------------------------------- /Index/Settings.cpp: -------------------------------------------------------------------------------- 1 | #include "Settings.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) 13 | #include 14 | #endif 15 | #include "ComLineWidget.h" 16 | #include "ComMessageBox.h" 17 | #include "constant.h" 18 | #include "SingletonUtils.h" 19 | 20 | Settings::Settings(QWidget *parent) : QDialog(parent) 21 | { 22 | setWindowFlags(Qt::Dialog| Qt::WindowCloseButtonHint); 23 | setFixedSize(1000,600); 24 | setAttribute(Qt::WA_StyledBackground,true); 25 | setStyleSheet(QString(".Settings{background-color:%1;}").arg("rgb(31,33,42)")); 26 | setWindowTitle("设置"); 27 | initUi(); 28 | 29 | } 30 | void Settings::initUi(){ 31 | QHBoxLayout *mainHLayout = new QHBoxLayout(this); 32 | mainHLayout->setContentsMargins(0,0,0,0); 33 | mainHLayout->setSpacing(0); 34 | 35 | 36 | QWidget *leftWidget = initLeftWidget(); 37 | leftWidget->setFixedWidth(200); 38 | QWidget *rightWidget = initRightWidget(); 39 | 40 | mainHLayout->addWidget(leftWidget); 41 | mainHLayout->addSpacing(2); 42 | mainHLayout->addWidget(rightWidget); 43 | } 44 | QWidget* Settings::initLeftWidget(){ 45 | QWidget * widget = new QWidget(this); 46 | widget->setStyleSheet(QString(".QWidget{background-color:%1;}").arg("rgb(43,46,56)")); 47 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 48 | widgetVLayout->setContentsMargins(0,0,0,0); 49 | widgetVLayout->setSpacing(0); 50 | 51 | 52 | QPushButton *commonBtn = new QPushButton(widget);//通用 53 | commonBtn->setStyleSheet(".QPushButton {color:white;font-size:16px;background-color:rgb(43,113,237);border:none; border-radius: 2px;padding: 2px;}\ 54 | .QPushButton:pressed {background-color: rgba(43,113,237,0.5);}\ 55 | .QPushButton:hover {background-color: rgba(43,113,237,0.5);}\ 56 | .QPushButton:focus{outline: none;}"); 57 | commonBtn->setFixedSize(120,40); 58 | commonBtn->setText("通用"); 59 | 60 | widgetVLayout->addSpacing(10); 61 | widgetVLayout->addWidget(commonBtn,0,Qt::AlignHCenter); 62 | widgetVLayout->addStretch(10); 63 | 64 | 65 | return widget; 66 | } 67 | QWidget* Settings::initRightWidget(){ 68 | QWidget * widget = new QWidget(this); 69 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 70 | widgetVLayout->setContentsMargins(0,0,0,0); 71 | widgetVLayout->setSpacing(0); 72 | 73 | rightStackedWidget = new QStackedWidget(widget); 74 | rightStackedWidget->setContentsMargins(10,0,10,0); 75 | initCommonWidget(); 76 | 77 | //bottom start 78 | QWidget *bottomWidget = new QWidget(this); 79 | bottomWidget->setFixedHeight(50); 80 | QHBoxLayout *bottomHLayout = new QHBoxLayout(bottomWidget); 81 | bottomHLayout->setContentsMargins(0,0,0,0); 82 | bottomHLayout->setSpacing(0); 83 | 84 | // 背景为浅灰色,无边框,白色字 85 | const QString right_bottom_btn = ".QPushButton {color:white;font-size:16px;background-color:rgb(60,64,75);border:none; border-radius: 3px;padding: 2px;}\ 86 | .QPushButton:hover {background-color: rgb(70,74,85);}\ 87 | .QPushButton:focus{outline: none;}"; 88 | 89 | QPushButton *okBtn = new QPushButton(bottomWidget); 90 | okBtn->setText("保存"); 91 | okBtn->setStyleSheet(right_bottom_btn); 92 | okBtn->setCursor(Qt::PointingHandCursor); 93 | okBtn->setFixedSize(100,40); 94 | connect(okBtn,&QPushButton::clicked,this,[this](){ 95 | 96 | }); 97 | 98 | QPushButton *cancelBtn = new QPushButton(bottomWidget); 99 | cancelBtn->setText("取消"); 100 | cancelBtn->setStyleSheet(right_bottom_btn); 101 | cancelBtn->setCursor(Qt::PointingHandCursor); 102 | cancelBtn->setFixedSize(100,40); 103 | connect(cancelBtn,&QPushButton::clicked,this,[this](){ 104 | this->close(); 105 | }); 106 | 107 | 108 | 109 | bottomHLayout->addStretch(10); 110 | bottomHLayout->addWidget(okBtn); 111 | bottomHLayout->addSpacing(20); 112 | bottomHLayout->addWidget(cancelBtn); 113 | bottomHLayout->addSpacing(20); 114 | //bottom end 115 | 116 | 117 | widgetVLayout->addWidget(rightStackedWidget); 118 | widgetVLayout->addSpacing(2); 119 | widgetVLayout->addWidget(bottomWidget); 120 | return widget; 121 | } 122 | 123 | void Settings::initCommonWidget(){ 124 | 125 | QSettings settings; 126 | QWidget * widget = new QWidget(rightStackedWidget); 127 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 128 | widgetVLayout->setContentsMargins(0,0,0,0); 129 | widgetVLayout->setSpacing(0); 130 | 131 | //dir start 132 | QWidget *dirWidget = new QWidget(widget); 133 | dirWidget->setStyleSheet(QString(".QWidget{background-color:%1;}").arg("rgb(43,46,56)")); 134 | dirWidget->setFixedHeight(50); 135 | QHBoxLayout *dirHLayout = new QHBoxLayout(dirWidget); 136 | dirHLayout->setContentsMargins(0,0,0,0); 137 | dirHLayout->setSpacing(0); 138 | 139 | QLabel *dirNameLabel = new QLabel(dirWidget); 140 | dirNameLabel->setFixedWidth(60); 141 | dirNameLabel->setStyleSheet(".QLabel{color:rgb(255,255,255);font-size:15px;}"); 142 | dirNameLabel->setText("录像路径"); 143 | 144 | QLineEdit *dirLineEdit = new QLineEdit(dirWidget); 145 | dirLineEdit->setFixedHeight(32); 146 | dirLineEdit->setPlaceholderText("请输入录像路径"); 147 | dirLineEdit->setStyleSheet(".QLineEdit{color:rgb(0,0,0);font-size:15px;border:1px solid rgb(217,217,217);border-radius: 3px; padding: 1px;}\ 148 | .QLineEdit:hover {border:1px solid rgb(64,65,66);}"); 149 | dirLineEdit->setClearButtonEnabled(true); 150 | dirLineEdit->setFocusPolicy(Qt::FocusPolicy::ClickFocus); 151 | 152 | dirLineEdit->setText(SingletonUtils::getInstance()->getRecordDir()); 153 | dirLineEdit->setCursorPosition(0); 154 | 155 | QPushButton *dirBtn= new QPushButton(dirWidget); 156 | dirBtn->setStyleSheet( ".QPushButton {color:rgb(64,65,66);font-family:Microsoft YaHei;font-size:14px;background-color:white; border:1px solid rgb(64,65,66); padding: 0px;}\ 157 | .QPushButton:pressed {background-color: rgba(240,240,240,0.8);}\ 158 | .QPushButton:hover {background-color: rgba(240,240,240,0.4); border-color:rgba(64,65,66,0.5);}\ 159 | .QPushButton:focus{outline: none;}"); 160 | dirBtn->setFixedSize(100,40); 161 | dirBtn->setText("选择"); 162 | connect(dirBtn,&QPushButton::clicked,this,[this,dirLineEdit](){ 163 | QString dirVal = QFileDialog::getExistingDirectory(this,"浏览","").trimmed(); 164 | if(dirVal.length()>0){ 165 | dirLineEdit->setText(dirVal); 166 | dirLineEdit->setCursorPosition(0); 167 | QSettings settings; 168 | settings.setValue(SRE_SETTINGS_DIR,dirVal); 169 | } 170 | 171 | }); 172 | dirHLayout->addSpacing(10); 173 | dirHLayout->addWidget(dirNameLabel); 174 | dirHLayout->addSpacing(10); 175 | dirHLayout->addWidget(dirLineEdit); 176 | dirHLayout->addSpacing(10); 177 | dirHLayout->addWidget(dirBtn); 178 | dirHLayout->addSpacing(10); 179 | //dir end 180 | 181 | widgetVLayout->addSpacing(10); 182 | widgetVLayout->addWidget(dirWidget); 183 | widgetVLayout->addStretch(10); 184 | 185 | 186 | rightStackedWidget->addWidget(widget); 187 | rightStackedWidget->setCurrentWidget(widget); 188 | } 189 | -------------------------------------------------------------------------------- /Index/Settings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | 4 | #include 5 | QT_BEGIN_NAMESPACE; 6 | class QCheckBox; 7 | class QLineEdit; 8 | class QStackedWidget; 9 | QT_END_NAMESPACE; 10 | 11 | class Settings : public QDialog 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit Settings(QWidget *parent); 16 | 17 | private: 18 | void initUi(); 19 | QWidget* initLeftWidget(); 20 | QWidget* initRightWidget(); 21 | QStackedWidget *rightStackedWidget; 22 | 23 | void initCommonWidget(); 24 | 25 | 26 | signals: 27 | 28 | }; 29 | 30 | #endif // SETTINGS_H 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Vanishi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SRE 2 | 3 | * 作者:北小菜 4 | * 邮箱:bilibili_bxc@126.com 5 | * QQ:1402990689 6 | * 作者主页:http://www.any12345.com/user/4 7 | * 作者-哔哩哔哩主页:https://space.bilibili.com/487906612 8 | * 作者-头条西瓜主页:https://www.ixigua.com/home/4171970536803763 9 | * 软件github开源地址:https://github.com/any12345com/SRE 10 | * 软件gitee开源地址:https://gitee.com/Vanishi/SRE 11 | 12 | ### 视频教程 13 | 14 | * [西瓜头条 SRE讲解 合集视频地址](https://www.ixigua.com/7250311251979731459) 15 | * [哔哩哔哩 SRE讲解 合集视频地址](https://space.bilibili.com/487906612/channel/collectiondetail?sid=1426811) 16 | 17 | ### 分支介绍 18 | * day1 分支:仅仅实现了录屏功能,且功能不完善,Qt初学者可以参考学习 19 | * day2 分支:比较完善的实现了录音录屏功能,软件UI也做了较大调整,录音录屏所使用动态库非常适合学习 20 | 21 | 22 | ### 软件介绍 23 | 24 | - 一个Qt开发的开源远程控制软件(SRE),还在开发中,当前实现了录屏录音功能 25 | 26 | - 关于录音录屏的功能我是基于动态库实现的, 27 | - 动态库github开源地址:https://github.com/any12345com/BXC_MediaLibrary, 28 | - 动态库gitee开源地址:https://gitee.com/Vanishi/BXC_MediaLibrary 29 | 30 | 31 | ### 软件开发环境(兼容Qt6) 32 | * 以下是作者经常编译的版本 33 | * C++11 34 | * QtCreator9.0.2 + Qt6.5.1 + MinGW 64-bit 35 | * 推荐使用Qt6.x进行开发 36 | 37 | 38 | ### 授权协议 39 | 40 | - 本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 41 | 但是本项目也零碎的使用了一些其他的第三方库,包括使用了Qt, 42 | 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 43 | 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议,以及遵循相应的规定。 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Record/CaptureAudioThread.cpp: -------------------------------------------------------------------------------- 1 | #include "CaptureAudioThread.h" 2 | #include "BXC_AudioRecorder.h" 3 | #include "BXC_AvEncoder.h" 4 | #include "FpsControl.h" 5 | #include "Recorder.h" 6 | #include 7 | #include 8 | 9 | using namespace BXC_MediaLibrary; 10 | CaptureAudioThread::CaptureAudioThread(QObject *parent,CaptureAudioDevice *audioDevice): QThread(parent),mAudioDevice(audioDevice){ 11 | mRecorder = (Recorder *)parent; 12 | 13 | } 14 | CaptureAudioThread::~CaptureAudioThread(){ 15 | mIsStop = true; 16 | while (true) { 17 | if(isFinished()){ 18 | break; 19 | }else{ 20 | msleep(1); 21 | } 22 | } 23 | 24 | } 25 | void CaptureAudioThread::run(){ 26 | 27 | mIsStop = false; 28 | int ret; 29 | BXC_AudioRecorder * audioRecorder = mRecorder->getAudioRecorder(); 30 | BXC_AvEncoder * avEncoder = mRecorder->getAvEncoder(); 31 | 32 | BXC_AvFrame* audioFrame = new BXC_AvFrame(AVAUDIO, 10000); 33 | 34 | uint8_t* audioBuff = new uint8_t[10000]; 35 | int audioBuffSize = 0; 36 | 37 | int recvBuffSize = 0; 38 | uint8_t* recvBuff = new uint8_t[10000]; 39 | 40 | 41 | const int frameSize = 4608; // 4224=1056 * 4; 4608=1152 * 4; 42 | int64_t timestamp = 0; 43 | int64_t frameTimestamp = 0; 44 | int64_t frameCount = 0; 45 | 46 | while (true) 47 | { 48 | if(mIsStop){ 49 | break; 50 | } 51 | 52 | ret = BXC_get_sample(audioRecorder, recvBuff, recvBuffSize, timestamp); 53 | if (ret >= 0) { 54 | if (recvBuffSize > 0) { 55 | if (0 == audioBuffSize) { 56 | frameTimestamp = timestamp; 57 | } 58 | memcpy(audioBuff + audioBuffSize, recvBuff, recvBuffSize); 59 | audioBuffSize += recvBuffSize; 60 | 61 | if (audioBuffSize >= frameSize) { 62 | memcpy(audioFrame->data, audioBuff, frameSize); 63 | audioFrame->size = frameSize; 64 | audioFrame->timestamp = frameTimestamp; 65 | audioFrame->count = frameCount; 66 | 67 | BXC_send_frame(avEncoder, audioFrame); 68 | 69 | audioBuffSize -= frameSize; 70 | memmove(audioBuff, audioBuff + frameSize, audioBuffSize); 71 | frameTimestamp = timestamp; 72 | ++frameCount; 73 | } 74 | } 75 | }else { 76 | 77 | } 78 | } 79 | 80 | if (recvBuff) { 81 | delete[]recvBuff; 82 | recvBuff = nullptr; 83 | } 84 | if (audioBuff) { 85 | delete[]audioBuff; 86 | audioBuff = nullptr; 87 | } 88 | this->exit(); 89 | } 90 | -------------------------------------------------------------------------------- /Record/CaptureAudioThread.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPTUREAUDIOTHREAD_H 2 | #define CAPTUREAUDIOTHREAD_H 3 | #include 4 | 5 | class Recorder; 6 | struct CaptureAudioDevice; 7 | class CaptureAudioThread : public QThread 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit CaptureAudioThread(QObject *parent,CaptureAudioDevice *audioDevice); 12 | ~CaptureAudioThread(); 13 | protected: 14 | void run() override; 15 | private: 16 | Recorder *mRecorder; 17 | CaptureAudioDevice *mAudioDevice; 18 | bool mIsStop = true; 19 | signals: 20 | 21 | private slots: 22 | 23 | }; 24 | 25 | #endif // CAPTUREAUDIOTHREAD_H 26 | -------------------------------------------------------------------------------- /Record/CaptureVideoThread.cpp: -------------------------------------------------------------------------------- 1 | #include "CaptureVideoThread.h" 2 | #include "BXC_VideoRecorder.h" 3 | #include "BXC_AvEncoder.h" 4 | #include "FpsControl.h" 5 | #include "Recorder.h" 6 | #include 7 | #include 8 | 9 | using namespace BXC_MediaLibrary; 10 | CaptureVideoThread::CaptureVideoThread(QObject *parent,CaptureVideoDevice *videoDevice): QThread(parent),mVideoDevice(videoDevice){ 11 | mRecorder = (Recorder *)parent; 12 | 13 | } 14 | CaptureVideoThread::~CaptureVideoThread(){ 15 | mIsStop = true; 16 | while (true) { 17 | if(isFinished()){ 18 | break; 19 | }else{ 20 | msleep(1); 21 | } 22 | } 23 | // terminate();//强制结束 24 | // wait();//配合terminate()强制结束后,等待回收资源 25 | } 26 | void CaptureVideoThread::run(){ 27 | mIsStop = false; 28 | 29 | int fps = mVideoDevice->getFps(); 30 | int width = mVideoDevice->width; 31 | int height = mVideoDevice->height; 32 | 33 | 34 | int frameBuffSize = height * width * 4; 35 | uint8_t* frameBuff = new uint8_t[frameBuffSize]; 36 | uint8_t* frameBuff_rgba = new uint8_t[frameBuffSize]; 37 | 38 | BXC_AvFrame* videoFrame = new BXC_AvFrame(AVVIDEO, frameBuffSize); 39 | 40 | 41 | int64_t frameTimestamp = 0; 42 | int64_t frameCount = 0; 43 | 44 | int show_interval = 5;//屏幕显示时间隔数量 45 | if(mVideoDevice->isCamera()){ 46 | show_interval = 2; 47 | } 48 | 49 | int ret; 50 | FpsControl fpsControl(fps); 51 | fpsControl.realTimeStart(); 52 | 53 | while (true) 54 | { 55 | fpsControl.intervalStart(); 56 | if(mIsStop){ 57 | break; 58 | } 59 | ret = BXC_get_frame(mRecorder->getVideoRecorder(), frameBuff, frameBuffSize,frameTimestamp); 60 | 61 | if (ret >= 0) { 62 | 63 | memcpy(videoFrame->data, frameBuff, frameBuffSize); 64 | videoFrame->size = frameBuffSize; 65 | videoFrame->timestamp = frameTimestamp; 66 | videoFrame->count = frameCount; 67 | 68 | BXC_send_frame(mRecorder->getAvEncoder(), videoFrame); 69 | 70 | if(0 == frameCount % show_interval){ 71 | if(PIXEL_BGRA == mRecorder->getPixelFormat()){ 72 | // (bgra->rgba)大端模式,RGBA中R存储在高位,A存储在低位 73 | memcpy_s(frameBuff_rgba,frameBuffSize,frameBuff,frameBuffSize); 74 | for (int i = 0; i < width*height; i++) { 75 | frameBuff_rgba[i] = (frameBuff_rgba[i] & 0x000000FF) | // ______AA 76 | ((frameBuff_rgba[i] & 0x0000FF00) << 16) | // RR______ 77 | (frameBuff_rgba[i] & 0x00FF0000) | // __GG____ 78 | ((frameBuff_rgba[i] & 0xFF000000) >> 16); // ____BB__ 79 | } 80 | QImage image(frameBuff_rgba, width,height,QImage::Format_RGB32); 81 | emit mRecorder->setImage(image.copy()); 82 | 83 | }else if(PIXEL_RGB == mRecorder->getPixelFormat()){ 84 | QImage image(frameBuff, width,height,QImage::Format_RGB888); 85 | emit mRecorder->setImage(image.copy()); 86 | } 87 | } 88 | ++frameCount; 89 | fpsControl.realTimeIncrease(); 90 | }else{ 91 | continue; 92 | //break; 93 | } 94 | 95 | fpsControl.adjust(); 96 | // qDebug() <<"realTimeFps=" << fpsControl.getRealTimeFps(); 97 | } 98 | 99 | if(frameBuff){ 100 | delete[] frameBuff; 101 | frameBuff = nullptr; 102 | } 103 | if(frameBuff_rgba){ 104 | delete[] frameBuff_rgba; 105 | frameBuff_rgba = nullptr; 106 | } 107 | this->exit(); 108 | } 109 | -------------------------------------------------------------------------------- /Record/CaptureVideoThread.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPTUREVIDEOTHREAD_H 2 | #define CAPTUREVIDEOTHREAD_H 3 | #include 4 | 5 | class Recorder; 6 | struct CaptureVideoDevice; 7 | class CaptureVideoThread : public QThread 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit CaptureVideoThread(QObject *parent,CaptureVideoDevice *videoDevice); 12 | ~CaptureVideoThread(); 13 | protected: 14 | void run() override; 15 | private: 16 | Recorder *mRecorder; 17 | CaptureVideoDevice *mVideoDevice; 18 | bool mIsStop = true; 19 | signals: 20 | 21 | private slots: 22 | 23 | }; 24 | 25 | #endif // CAPTUREVIDEOTHREAD_H 26 | -------------------------------------------------------------------------------- /Record/Record.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/CaptureVideoThread.h\ 3 | $$PWD/CaptureAudioThread.h\ 4 | $$PWD/RecordWidget.h \ 5 | $$PWD/Recorder.h 6 | 7 | 8 | SOURCES += \ 9 | $$PWD/CaptureVideoThread.cpp\ 10 | $$PWD/CaptureAudioThread.cpp\ 11 | $$PWD/RecordWidget.cpp \ 12 | $$PWD/Recorder.cpp 13 | 14 | 15 | INCLUDEPATH += Record 16 | -------------------------------------------------------------------------------- /Record/RecordWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "RecordWidget.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "ComMessageBox.h" 13 | #include "ComLineWidget.h" 14 | #include "Utils.h" 15 | #include "SingletonUtils.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | RecordWidget::RecordWidget(QWidget *parent) : QWidget(parent) 25 | { 26 | initUi(); 27 | 28 | mRecorder = new Recorder(this); 29 | connect(mRecorder, &Recorder::setImage, this, &RecordWidget::onSetImage); 30 | 31 | mIsRecord = false; 32 | durationTimer = new QTimer(this); 33 | connect(durationTimer,&QTimer::timeout,this,[this](){ 34 | 35 | int seconds = QDateTime::currentDateTime().toSecsSinceEpoch() - mRecordStartDate.toSecsSinceEpoch(); 36 | durationLabel->setText(Utils::secondsToDurationStr(seconds)); 37 | // durationLabel->setText(QTime::currentTime().toString()); 38 | }); 39 | 40 | 41 | } 42 | RecordWidget::~RecordWidget(){ 43 | disconnect(mRecorder, &Recorder::setImage, this, &RecordWidget::onSetImage); 44 | if(mRecorder){ 45 | delete mRecorder; 46 | mRecorder = nullptr; 47 | } 48 | if(mMediaDevices){ 49 | delete mMediaDevices; 50 | mMediaDevices = nullptr; 51 | } 52 | 53 | for (int i = 0; i < mVideoDevices.size(); ++i) { 54 | CaptureVideoDevice *device = mVideoDevices[i]; 55 | delete device; 56 | device = nullptr; 57 | } 58 | for (int i = 0; i < mAudioDevices.size(); ++i) { 59 | CaptureAudioDevice *device = mAudioDevices[i]; 60 | delete device; 61 | device = nullptr; 62 | } 63 | mVideoDevices.clear(); 64 | mAudioDevices.clear(); 65 | 66 | } 67 | void RecordWidget::initUi(){ 68 | QVBoxLayout *mainVLayout = new QVBoxLayout(this); 69 | mainVLayout->setContentsMargins(0,0,0,0); 70 | mainVLayout->setSpacing(0); 71 | 72 | //name strt 73 | QWidget * nameWidget = new QWidget(this); 74 | nameWidget->setFixedHeight(50); 75 | QHBoxLayout *nameHLayout = new QHBoxLayout(nameWidget); 76 | nameHLayout->setContentsMargins(0,0,0,0); 77 | nameHLayout->setSpacing(0); 78 | QLabel *nameLabel = new QLabel(nameWidget); 79 | nameLabel->setFixedHeight(30); 80 | nameLabel->setStyleSheet(".QLabel{color:rgb(255,255,255);font-size:15px;border:1px solid rgb(76,76,76); border-radius: 2px;padding: 4px 8px;}"); 81 | nameLabel->setText(tr("录制屏幕")); 82 | nameHLayout->addStretch(10); 83 | nameHLayout->addWidget(nameLabel); 84 | nameHLayout->addStretch(10); 85 | //name end 86 | 87 | //image start 88 | QWidget *imageWidget = new QWidget(this); 89 | imageWidget->setStyleSheet(QString(".QWidget{background-color:%1;}").arg("rgb(25,27,38)")); 90 | QHBoxLayout *imageHLayout = new QHBoxLayout(imageWidget); 91 | imageHLayout->setContentsMargins(0,1,0,1); 92 | imageHLayout->setSpacing(0); 93 | 94 | imageLabel = new QLabel(imageWidget); 95 | imageLabel->setFixedSize(880,500); 96 | imageHLayout->addStretch(10); 97 | imageHLayout->addWidget(imageLabel); 98 | imageHLayout->addStretch(10); 99 | //image end 100 | 101 | // record start 102 | QWidget * recordWidget = initRecordWidget(); 103 | // record end 104 | 105 | 106 | // bottom start 107 | QWidget * bottomWidget = new QWidget(this); 108 | bottomWidget->setFixedHeight(40); 109 | QHBoxLayout *bottomHLayout = new QHBoxLayout(bottomWidget); 110 | bottomHLayout->setContentsMargins(0,0,0,0); 111 | bottomHLayout->setSpacing(0); 112 | 113 | QLabel *durationNameLabel = new QLabel(bottomWidget); 114 | durationNameLabel->setStyleSheet(".QLabel{color:rgb(255,242,252);font-size:16px;}"); 115 | durationNameLabel->setText("REC:"); 116 | 117 | durationLabel = new QLabel(bottomWidget); 118 | durationLabel->setStyleSheet(".QLabel{color:rgb(255,242,252);font-size:18px;}"); 119 | durationLabel->setText(Utils::secondsToDurationStr(0)); 120 | 121 | QPushButton *videoBtn = new QPushButton(bottomWidget); 122 | videoBtn->setStyleSheet(".QPushButton {color:rgb(255,255,255);font-size:15px;border:1px solid rgb(76,76,76); border-radius: 3px;padding: 2px;}\ 123 | .QPushButton:pressed {background-color: rgba(64,65,66,0.5);}\ 124 | .QPushButton:hover {background-color: rgba(64,65,66,0.5);}\ 125 | .QPushButton:focus{outline: none;}"); 126 | videoBtn->setFixedSize(100,30); 127 | videoBtn->setCursor(Qt::PointingHandCursor); 128 | videoBtn->setText(tr("录制列表")); 129 | connect(videoBtn,&QPushButton::clicked,this,[this](){ 130 | QDesktopServices::openUrl(QUrl::fromLocalFile(SingletonUtils::getInstance()->getRecordDir())); 131 | 132 | }); 133 | 134 | bottomHLayout->addSpacing(20); 135 | bottomHLayout->addWidget(durationNameLabel); 136 | bottomHLayout->addSpacing(10); 137 | bottomHLayout->addWidget(durationLabel); 138 | bottomHLayout->addStretch(10); 139 | bottomHLayout->addWidget(videoBtn); 140 | bottomHLayout->addSpacing(60); 141 | // bottom end 142 | 143 | 144 | mainVLayout->addWidget(nameWidget); 145 | mainVLayout->addWidget(imageWidget); 146 | mainVLayout->addWidget(recordWidget); 147 | ComLineWidget*line = new ComLineWidget(this); 148 | line->setStyleSheet(QString(".ComLineWidget{background-color:%1;}").arg("rgb(25,27,38)")); 149 | mainVLayout->addWidget(line); 150 | 151 | mainVLayout->addWidget(bottomWidget); 152 | ComLineWidget*line2 = new ComLineWidget(this); 153 | line2->setStyleSheet(QString(".ComLineWidget{background-color:%1;}").arg("rgb(25,27,38)")); 154 | mainVLayout->addWidget(line2); 155 | 156 | mainVLayout->addStretch(10); 157 | } 158 | QWidget* RecordWidget::initRecordWidget(){ 159 | QWidget * widget = new QWidget(this); 160 | widget->setFixedHeight(80); 161 | QHBoxLayout *widgetHLayout = new QHBoxLayout(widget); 162 | widgetHLayout->setContentsMargins(0,0,0,0); 163 | widgetHLayout->setSpacing(0); 164 | 165 | QWidget *recordSourceWidget = initRecordSourceWidget(); 166 | 167 | startBtn = new QPushButton(widget); 168 | startBtn->setFixedSize(120,40); 169 | startBtn->setCursor(Qt::PointingHandCursor); 170 | startBtn->setText(tr("开始")); 171 | pauseBtn = new QPushButton(widget); 172 | pauseBtn->setFixedSize(120,40); 173 | pauseBtn->setCursor(Qt::PointingHandCursor); 174 | pauseBtn->setText(tr("暂停")); 175 | stopBtn = new QPushButton(widget); 176 | stopBtn->setFixedSize(120,40); 177 | stopBtn->setCursor(Qt::PointingHandCursor); 178 | stopBtn->setText(tr("停止")); 179 | connect(startBtn,&QPushButton::clicked,this,&RecordWidget::onStartBtn); 180 | connect(stopBtn,&QPushButton::clicked,this,&RecordWidget::onStopBtn); 181 | pauseBtn->hide(); 182 | stopBtn->hide(); 183 | 184 | widgetHLayout->addWidget(recordSourceWidget); 185 | widgetHLayout->addWidget(pauseBtn); 186 | widgetHLayout->addSpacing(10); 187 | widgetHLayout->addWidget(startBtn); 188 | widgetHLayout->addSpacing(10); 189 | widgetHLayout->addWidget(stopBtn); 190 | widgetHLayout->addSpacing(40); 191 | 192 | return widget; 193 | } 194 | QWidget* RecordWidget::initRecordSourceWidget(){ 195 | mMediaDevices = new QMediaDevices(this); 196 | 197 | mVideoDevices.append(new CaptureVideoDevice("请选择视频源")); 198 | mVideoDevices.append(new CaptureVideoDevice(true,false,"系统屏幕(DXGI)","DXGI",25)); 199 | mVideoDevices.append(new CaptureVideoDevice(true,false,"系统屏幕(GDI)","GDI",20)); 200 | mAudioDevices.append(new CaptureAudioDevice("请选择音频源")); 201 | mAudioDevices.append(new CaptureAudioDevice(true,"系统声音","SOUNDCARD")); 202 | mAudioDevices.append(new CaptureAudioDevice(true,"麦克风","MICROPHONE")); 203 | for (auto &device : mMediaDevices->videoInputs()) { 204 | 205 | QString name = device.description(); 206 | QString nickname = device.description(); 207 | if(nickname.length()> 25){ 208 | nickname = nickname.mid(0,25); 209 | } 210 | mVideoDevices.append(new CaptureVideoDevice(true,true,nickname,name,25)); 211 | } 212 | for (auto &device : mMediaDevices->audioInputs()) { 213 | QString name = device.description(); 214 | QString nickname = device.description(); 215 | if(nickname.length()> 25){ 216 | nickname = nickname.mid(0,25); 217 | } 218 | mAudioDevices.append(new CaptureAudioDevice(true,nickname,name)); 219 | } 220 | 221 | QWidget * widget = new QWidget(this); 222 | QHBoxLayout *widgetHLayout = new QHBoxLayout(widget); 223 | widgetHLayout->setContentsMargins(0,0,0,0); 224 | widgetHLayout->setSpacing(0); 225 | 226 | QString record_source_QComboBox = ".QComboBox {color:rgb(0,0,0);background-color:rgb(240,240,240);font-size:15px;border:1px solid rgb(217,217,217);}\ 227 | .QComboBox:hover {border:1px solid rgb(54,98,180);}\ 228 | .QComboBox::drop-down{width:0px;} \ 229 | .QComboBox QAbstractItemView{outline:0px;} \ 230 | .QComboBox QAbstractItemView::item {font-size:13px;background-color:rgb(255,255,255);height: 28px;border-bottom:1px solid rgb(217,217,217);}\ 231 | .QComboBox QAbstractItemView::item:selected {color:rgb(255,255,255);background-color:rgb(54,98,180);}"; 232 | 233 | 234 | //视频源选择框 235 | QComboBox * videoSourceBox = new QComboBox(widget); 236 | videoSourceBox->setStyleSheet(record_source_QComboBox); 237 | videoSourceBox->setFixedSize(220,36); 238 | QStyledItemDelegate *videoSourceDelegate = new QStyledItemDelegate(videoSourceBox); 239 | videoSourceBox->setItemDelegate(videoSourceDelegate); 240 | videoSourceBox->clear(); 241 | 242 | //音频源选择框 243 | QComboBox * audioSourceBox = new QComboBox(widget); 244 | audioSourceBox->setStyleSheet(record_source_QComboBox); 245 | audioSourceBox->setFixedSize(220,36); 246 | QStyledItemDelegate *audioSourceDelegate = new QStyledItemDelegate(audioSourceBox); 247 | audioSourceBox->setItemDelegate(audioSourceDelegate); 248 | audioSourceBox->clear(); 249 | 250 | for (int i = 0; i < mVideoDevices.size(); ++i) { 251 | CaptureVideoDevice* device = mVideoDevices[i]; 252 | videoSourceBox->addItem(device->getNickname()); 253 | } 254 | connect(videoSourceBox, QOverload::of(&QComboBox::currentIndexChanged), 255 | [this](int index){ 256 | mSelectedVideoIndex = index; 257 | 258 | }); 259 | for (int i = 0; i < mAudioDevices.size(); ++i) { 260 | CaptureAudioDevice *device = mAudioDevices[i]; 261 | audioSourceBox->addItem(device->getNickname()); 262 | } 263 | connect(audioSourceBox, QOverload::of(&QComboBox::currentIndexChanged), 264 | [this](int index){ 265 | mSelectedAudioIndex = index; 266 | }); 267 | //添加控件 268 | widgetHLayout->addSpacing(20); 269 | widgetHLayout->addWidget(videoSourceBox); 270 | widgetHLayout->addSpacing(20); 271 | widgetHLayout->addWidget(audioSourceBox); 272 | 273 | widgetHLayout->addStretch(10); 274 | 275 | 276 | return widget; 277 | } 278 | void RecordWidget::onStartBtn(bool checked){ 279 | 280 | if(mIsRecord){ 281 | 282 | }else{ 283 | CaptureVideoDevice *videoDevice = mVideoDevices[mSelectedVideoIndex]; 284 | CaptureAudioDevice *audioDevice = mAudioDevices[mSelectedAudioIndex]; 285 | 286 | if(!videoDevice->isUse() && !audioDevice->isUse()){ 287 | ComMessageBox::error(this,"请至少选择一种输入源!"); 288 | return; 289 | } 290 | QString url = QString("%1/%2.mp4").arg(SingletonUtils::getInstance()->getRecordDir()). 291 | arg(QDateTime::currentDateTime().toLocalTime().toString("yyyy-MM-dd-hh-mm-ss")); 292 | 293 | if(mRecorder->start(videoDevice,audioDevice,url)){ 294 | startBtn->hide(); 295 | pauseBtn->show(); 296 | stopBtn->show(); 297 | 298 | mIsRecord = true; 299 | mRecordStartDate = QDateTime::currentDateTime(); 300 | durationTimer->start(1000); 301 | }else{ 302 | ComMessageBox::error(this,"输入源存在错误!"); 303 | } 304 | } 305 | 306 | } 307 | void RecordWidget::onStopBtn(bool checked){ 308 | if(mIsRecord){ 309 | startBtn->show(); 310 | pauseBtn->hide(); 311 | stopBtn->hide(); 312 | mIsRecord = false; 313 | durationTimer->stop(); 314 | mRecorder->stop(); 315 | durationLabel->setText(Utils::secondsToDurationStr(0)); 316 | }else{ 317 | 318 | 319 | } 320 | } 321 | void RecordWidget::onSetImage(QImage image) 322 | { 323 | 324 | // update(); //调用update将执行 paintEvent函数 325 | int scaled_h = imageLabel->height(); 326 | int scaled_w = int(float(scaled_h) * float(image.width())/float(image.height())); 327 | 328 | QImage scaled_image = image.scaled(scaled_w, scaled_h, Qt::IgnoreAspectRatio); 329 | 330 | // qDebug()<<"RecordWidget::onSetImage width="<width()<<",height="<height()<< 331 | // ",image.width="< mVideoDevices; 39 | int mSelectedVideoIndex = 0; 40 | QVector mAudioDevices; 41 | int mSelectedAudioIndex = 0; 42 | 43 | private: 44 | Recorder *mRecorder; 45 | bool mIsRecord;//是否在录制中 46 | QDateTime mRecordStartDate;//开始录制的时间 47 | 48 | signals: 49 | 50 | public slots: 51 | void onSetImage(QImage image); 52 | void onStartBtn(bool checked); 53 | void onStopBtn(bool checked); 54 | }; 55 | 56 | #endif // RECORDWIDGET_H 57 | -------------------------------------------------------------------------------- /Record/Recorder.cpp: -------------------------------------------------------------------------------- 1 | #include "Recorder.h" 2 | #include "CaptureVideoThread.h" 3 | #include "CaptureAudioThread.h" 4 | #include "SingletonUtils.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | /* 10 | * Qt跨平台宏 https://zhuanlan.zhihu.com/p/619580373 11 | */ 12 | 13 | Recorder::Recorder(QObject *parent): QObject(parent) 14 | { 15 | } 16 | Recorder::~Recorder(){ 17 | this->stop(); 18 | } 19 | 20 | bool Recorder::start(CaptureVideoDevice* videoDevice,CaptureAudioDevice* audioDevice,const QString &url){ 21 | mVideoDevice = videoDevice; 22 | mAudioDevice = audioDevice; 23 | 24 | //采集视频相关参数 25 | int videoBitrate = 2000000; 26 | mVideoDevice->width = SingletonUtils::getInstance()->getScreenWidth(); 27 | mVideoDevice->height = SingletonUtils::getInstance()->getScreenHeight(); 28 | 29 | int fps = mVideoDevice->getFps(); 30 | bool hasVideo = mVideoDevice->isUse(); 31 | const char* videoCodecName = "libx264";//h264_qsv,libx264,h264_nvenc,h264_amf 32 | 33 | //采集音频相关参数 34 | bool hasAudio = mAudioDevice->isUse(); 35 | const char* audioCodecName = "aac";//aac,libmp3lame 36 | int audioBitrate = 128000; 37 | 38 | int ret; 39 | 40 | if(hasVideo){ 41 | const char * videoCapture = mVideoDevice->getName().toStdString().data(); 42 | mVideoRecorder = new BXC_VideoRecorder(videoCapture,mVideoDevice->width,mVideoDevice->height,0); 43 | 44 | ret = BXC_VideoRecorder_Open(mVideoRecorder); 45 | if (ret < 0) { 46 | return -1; 47 | } 48 | 49 | mVideoDevice->width = mVideoRecorder->factWidth; 50 | mVideoDevice->height = mVideoRecorder->factHeight; 51 | mPixelFormat = mVideoRecorder->pixelFormat; 52 | 53 | } 54 | if(hasAudio){ 55 | const char * audioCapture = mAudioDevice->getName().toStdString().data(); 56 | mAudioRecorder = new BXC_AudioRecorder(audioCapture); 57 | 58 | ret = BXC_AudioRecorder_Open(mAudioRecorder); 59 | if (ret < 0) { 60 | return -1; 61 | } 62 | } 63 | 64 | mAvEncoder = new BXC_AvEncoder(hasVideo, videoCodecName, videoBitrate, mPixelFormat, 65 | mVideoDevice->width, mVideoDevice->height, fps, 66 | hasAudio, audioCodecName, audioBitrate); 67 | 68 | ret = BXC_AvEncoder_Open(mAvEncoder,url.toLatin1().constData()); 69 | if (ret < 0) { 70 | return -1; 71 | } 72 | 73 | mIsStop = false; 74 | //开启采集视频帧线程 75 | if(hasVideo){ 76 | mCaptureVideoThread = new CaptureVideoThread(this,mVideoDevice); 77 | mCaptureVideoThread->start(QThread::NormalPriority); 78 | } 79 | 80 | //开启采集音频帧线程 81 | if(hasAudio){ 82 | mCaptureAudioThread = new CaptureAudioThread(this,mAudioDevice); 83 | mCaptureAudioThread->start(QThread::NormalPriority); 84 | } 85 | 86 | return true; 87 | 88 | } 89 | bool Recorder::pause(){ 90 | return false; 91 | } 92 | bool Recorder::stop(){ 93 | mIsStop = true; 94 | 95 | if(mCaptureVideoThread){ 96 | delete mCaptureVideoThread; 97 | mCaptureVideoThread = nullptr; 98 | } 99 | if(mCaptureAudioThread){ 100 | delete mCaptureAudioThread; 101 | mCaptureAudioThread = nullptr; 102 | } 103 | 104 | if(mVideoRecorder){ 105 | BXC_VideoRecorder_Close(mVideoRecorder); 106 | delete mVideoRecorder; 107 | mVideoRecorder = nullptr; 108 | } 109 | 110 | if(mAudioRecorder){ 111 | BXC_AudioRecorder_Close(mAudioRecorder); 112 | delete mAudioRecorder; 113 | mAudioRecorder = nullptr; 114 | } 115 | 116 | if(mAvEncoder){ 117 | BXC_AvEncoder_Close(mAvEncoder); 118 | delete mAvEncoder; 119 | mAvEncoder = nullptr; 120 | } 121 | 122 | if(mVideoDevice && mVideoDevice->isUse()){ 123 | 124 | QTimer::singleShot(100,this,[this](){ 125 | QImage image(mVideoDevice->width,mVideoDevice->height,QImage::Format_RGB32); 126 | image.fill(QColor(25,27,38)); 127 | emit this->setImage(image.copy()); 128 | }); 129 | } 130 | // std::thread([](Recorder *recorder){}, this).detach(); 131 | return true; 132 | } 133 | BXC_VideoRecorder* Recorder::getVideoRecorder(){ 134 | return mVideoRecorder; 135 | } 136 | BXC_PixelFormat Recorder::getPixelFormat(){ 137 | return mPixelFormat; 138 | } 139 | BXC_AudioRecorder* Recorder::getAudioRecorder(){ 140 | return mAudioRecorder; 141 | } 142 | BXC_AvEncoder* Recorder::getAvEncoder(){ 143 | return mAvEncoder; 144 | } 145 | -------------------------------------------------------------------------------- /Record/Recorder.h: -------------------------------------------------------------------------------- 1 | #ifndef RECORDER_H 2 | #define RECORDER_H 3 | 4 | #include 5 | #include 6 | #include "BXC_VideoRecorder.h" 7 | #include "BXC_AudioRecorder.h" 8 | #include "BXC_AvEncoder.h" 9 | using namespace BXC_MediaLibrary; 10 | class CaptureVideoThread; 11 | class CaptureAudioThread; 12 | struct CaptureVideoDevice{ 13 | CaptureVideoDevice() = delete; 14 | CaptureVideoDevice(QString nickname):mNickname(nickname){ 15 | 16 | } 17 | CaptureVideoDevice(bool use,bool isCamera,QString nickname,QString name,int fps): 18 | mUse(use),mIsCamera(isCamera),mNickname(nickname),mName(name),mFps(fps){ 19 | 20 | } 21 | public: 22 | bool isUse(){ 23 | return mUse; 24 | } 25 | bool isCamera(){ 26 | return mIsCamera; 27 | } 28 | QString getNickname(){ 29 | return mNickname; 30 | } 31 | QString getName(){ 32 | return mName; 33 | } 34 | 35 | int getFps(){ 36 | return mFps; 37 | } 38 | 39 | int width; 40 | int height; 41 | private: 42 | bool mUse = false; 43 | bool mIsCamera = false; 44 | QString mNickname; 45 | QString mName; 46 | int mFps; 47 | }; 48 | struct CaptureAudioDevice{ 49 | CaptureAudioDevice() = delete; 50 | CaptureAudioDevice(QString nickname): 51 | mUse(false),mNickname(nickname){ 52 | 53 | } 54 | CaptureAudioDevice(bool use,QString nickname,QString name): 55 | mUse(use),mNickname(nickname),mName(name){ 56 | 57 | } 58 | public: 59 | bool isUse(){ 60 | return mUse; 61 | } 62 | QString getNickname(){ 63 | return mNickname; 64 | } 65 | QString getName(){ 66 | return mName; 67 | } 68 | private: 69 | bool mUse; 70 | QString mNickname; 71 | QString mName; 72 | }; 73 | class Recorder : public QObject 74 | { 75 | Q_OBJECT 76 | public: 77 | explicit Recorder(QObject *parent); 78 | ~Recorder(); 79 | 80 | public: 81 | bool start(CaptureVideoDevice* videoDevice,CaptureAudioDevice* audioDevice,const QString &url); 82 | bool pause(); 83 | bool stop(); 84 | 85 | BXC_VideoRecorder* getVideoRecorder(); 86 | BXC_AudioRecorder* getAudioRecorder(); 87 | BXC_AvEncoder* getAvEncoder(); 88 | BXC_PixelFormat getPixelFormat(); 89 | private: 90 | CaptureVideoDevice *mVideoDevice = nullptr; 91 | CaptureAudioDevice *mAudioDevice = nullptr; 92 | CaptureVideoThread *mCaptureVideoThread = nullptr; 93 | CaptureAudioThread *mCaptureAudioThread = nullptr; 94 | BXC_VideoRecorder *mVideoRecorder = nullptr; 95 | BXC_AudioRecorder *mAudioRecorder = nullptr; 96 | BXC_AvEncoder *mAvEncoder = nullptr; 97 | bool mIsStop = true; 98 | BXC_PixelFormat mPixelFormat = PIXEL_UNKNOWN; 99 | 100 | signals: 101 | void setImage(QImage image); 102 | private slots: 103 | 104 | }; 105 | 106 | #endif // RECORDER_H 107 | -------------------------------------------------------------------------------- /SRE.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets multimedia 3 | greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat 4 | 5 | CONFIG += c++11 6 | 7 | # You can make your code fail to compile if it uses deprecated APIs. 8 | # In order to do so, uncomment the following line. 9 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 10 | 11 | SOURCES += \ 12 | main.cpp \ 13 | mainwindow.cpp 14 | 15 | HEADERS += \ 16 | mainwindow.h 17 | 18 | RESOURCES += \ 19 | res.qrc 20 | 21 | RC_ICONS = logo.ico # 配置桌面软件和的图标 22 | 23 | # Default rules for deployment. 24 | qnx: target.path = /tmp/$${TARGET}/bin 25 | else: unix:!android: target.path = /opt/$${TARGET}/bin 26 | !isEmpty(target.path): INSTALLS += target 27 | 28 | include(3rdparty/3rdparty.pri) 29 | include(Index/Index.pri) 30 | include(Record/Record.pri) 31 | include(VNCServer/VNCServer.pri) 32 | include(VNCClient/VNCClient.pri) 33 | include(Utils/Utils.pri) 34 | 35 | # windows 36 | win32: LIBS += -lws2_32 37 | 38 | # BXC_MediaLibrary 39 | win32: LIBS += -L$$PWD/3rdparty/BXC_MediaLibrary/lib/ -lBXC_AudioRecorder -lBXC_VideoRecorder -lBXC_AvEncoder 40 | INCLUDEPATH += $$PWD/3rdparty/BXC_MediaLibrary/include 41 | DEPENDPATH += $$PWD/3rdparty/BXC_MediaLibrary/include 42 | 43 | 44 | -------------------------------------------------------------------------------- /Utils/ComLineWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ComLineWidget.h" 2 | 3 | ComLineWidget::ComLineWidget(QWidget *parent,int type) : QWidget(parent) 4 | { 5 | setAttribute(Qt::WA_StyledBackground,true); 6 | setStyleSheet(".ComLineWidget{background-color:rgb(233,233,233);}"); 7 | if(1==type){ 8 | setFixedWidth(1); 9 | }else{ 10 | setFixedHeight(1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Utils/ComLineWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef COMLINEWIDGET_H 2 | #define COMLINEWIDGET_H 3 | 4 | #include 5 | 6 | class ComLineWidget : public QWidget 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ComLineWidget(QWidget *parent,int type=0); 11 | 12 | signals: 13 | 14 | }; 15 | 16 | #endif // COMLINEWIDGET_H 17 | -------------------------------------------------------------------------------- /Utils/ComLoadingLabel.cpp: -------------------------------------------------------------------------------- 1 | #include "ComLoadingLabel.h" 2 | #include 3 | 4 | ComLoadingLabel::ComLoadingLabel(QWidget *parent) : QLabel(parent) 5 | { 6 | QMovie *movie = new QMovie(this); 7 | movie->setFileName(":/res/images/loading.gif"); 8 | setFixedSize(20,20); 9 | setScaledContents(true); 10 | setMovie(movie); 11 | movie->start(); 12 | hide(); 13 | } 14 | -------------------------------------------------------------------------------- /Utils/ComLoadingLabel.h: -------------------------------------------------------------------------------- 1 | #ifndef COMLOADINGLABEL_H 2 | #define COMLOADINGLABEL_H 3 | 4 | #include 5 | 6 | class ComLoadingLabel : public QLabel 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ComLoadingLabel(QWidget *parent); 11 | 12 | signals: 13 | 14 | }; 15 | 16 | #endif // COMLOADINGLABEL_H 17 | -------------------------------------------------------------------------------- /Utils/ComLoadingWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ComLoadingWidget.h" 2 | #include 3 | #include 4 | #include 5 | 6 | ComLoadingWidget::ComLoadingWidget(QWidget *parent) :QWidget(parent) 7 | { 8 | 9 | // setAttribute(Qt::WA_StyledBackground,true); 10 | // setStyleSheet("background-color: rgba(0,0,0,0.2)"); 11 | 12 | QVBoxLayout *boxLayout = new QVBoxLayout(this); 13 | boxLayout->setContentsMargins(0,100,0,0); 14 | 15 | QLabel *loadingLabel = new QLabel(this); 16 | 17 | 18 | boxLayout->addWidget(loadingLabel,0,Qt::AlignCenter); 19 | 20 | QMovie *movie = new QMovie(this); 21 | movie->setFileName(":/res/images/loading.gif"); 22 | loadingLabel->setFixedSize(30,30); 23 | loadingLabel->setScaledContents(true); 24 | loadingLabel->setMovie(movie); 25 | movie->start(); 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /Utils/ComLoadingWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef COMLOADINGWIDGET_H 2 | #define COMLOADINGWIDGET_H 3 | 4 | #include 5 | 6 | class ComLoadingWidget : public QWidget 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ComLoadingWidget(QWidget *parent); 11 | 12 | signals: 13 | 14 | }; 15 | 16 | #endif // COMLOADINGWIDGET_H 17 | -------------------------------------------------------------------------------- /Utils/ComMessageBox.cpp: -------------------------------------------------------------------------------- 1 | #include "ComMessageBox.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | ComMessageBox::ComMessageBox(bool success,const QString &text,QWidget *parent) : QDialog(parent) 8 | { 9 | 10 | //设置模态 11 | setWindowModality(Qt::ApplicationModal); 12 | // 隐藏?号 13 | setWindowFlags(Qt::Dialog| Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint); 14 | setWindowTitle("提示"); 15 | 16 | setFixedSize(320,120); 17 | setStyleSheet(".ComMessageBox{background-color:rgb(255,255,255);}"); 18 | 19 | QVBoxLayout *boxLayout = new QVBoxLayout(this); 20 | boxLayout->setContentsMargins(0,0,0,0); 21 | boxLayout->setSpacing(0); 22 | 23 | QWidget *line = new QWidget(this); 24 | line->setStyleSheet(".QWidget{background-color:rgb(233,233,233);}"); 25 | line->setFixedHeight(1); 26 | 27 | 28 | QWidget *boxHWidget = new QWidget(this); 29 | QHBoxLayout *boxHLayout = new QHBoxLayout(boxHWidget); 30 | boxHLayout->setContentsMargins(20,0,20,0); 31 | 32 | QString filename; 33 | if(success){ 34 | filename = ":/res/images/icon/success.png"; 35 | }else { 36 | filename = ":/res/images/icon/error.png"; 37 | } 38 | 39 | QLabel *iconLabel = new QLabel(this); 40 | iconLabel->setPixmap(QIcon(filename).pixmap(50,50)); 41 | 42 | QLabel *textLabel = new QLabel(this); 43 | textLabel->setWordWrap(true); 44 | QString tt = QString("

%1

").arg(text); 45 | textLabel->setText(tr(tt.toUtf8())); 46 | 47 | boxHLayout->addWidget(iconLabel); 48 | boxHLayout->addSpacing(10); 49 | boxHLayout->addWidget(textLabel); 50 | boxHLayout->addStretch(5); 51 | 52 | 53 | boxLayout->addWidget(line); 54 | boxLayout->addWidget(boxHWidget); 55 | 56 | } 57 | void ComMessageBox::success(QWidget *parent,const QString &text){ 58 | ComMessageBox mb(true,text,parent); 59 | mb.exec(); 60 | } 61 | 62 | void ComMessageBox::error(QWidget *parent,const QString &text){ 63 | ComMessageBox mb(false,text,parent); 64 | mb.exec(); 65 | } 66 | -------------------------------------------------------------------------------- /Utils/ComMessageBox.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMESSAGEBOX_H 2 | #define COMMESSAGEBOX_H 3 | 4 | #include 5 | 6 | class ComMessageBox : public QDialog 7 | { 8 | Q_OBJECT 9 | private: 10 | explicit ComMessageBox(bool success,const QString &text,QWidget *parent); 11 | 12 | public: 13 | static void success(QWidget *parent,const QString &text); 14 | static void error(QWidget *parent,const QString &text); 15 | 16 | 17 | signals: 18 | 19 | }; 20 | 21 | #endif // COMMESSAGEBOX_H 22 | -------------------------------------------------------------------------------- /Utils/ComOptionsBox.cpp: -------------------------------------------------------------------------------- 1 | #include "ComOptionsBox.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ComOptionsBox::ComOptionsBox(QWidget *parent,const QString &name) : QWidget(parent) 9 | { 10 | setAttribute(Qt::WA_StyledBackground,true); 11 | setStyleSheet(".ComOptionsBox{ background-color:rgb(241,244,251);}"); 12 | 13 | QVBoxLayout *boxLayout = new QVBoxLayout(this); 14 | boxLayout->setContentsMargins(3,0,3,2); 15 | 16 | // 菜单 17 | QWidget *menuWidget = new QWidget(this); 18 | QHBoxLayout *menuLayout = new QHBoxLayout(menuWidget); 19 | menuLayout->setContentsMargins(5,0,5,0); 20 | menuWidget->setFixedHeight(30); 21 | menuWidget->setStyleSheet(".QWidget{background-color: rgba(0,0,0,0);}"); 22 | 23 | QToolButton *icon = new QToolButton(menuWidget); 24 | icon->setAutoRaise(true); 25 | icon->setArrowType(Qt::ArrowType::DownArrow); 26 | QLabel *titleLabel = new QLabel(menuWidget); 27 | titleLabel->setStyleSheet(".QLabel{background-color: rgba(0,0,0,0);color:rgb(0,0,0);}"); 28 | titleLabel->setText(tr(name.toStdString().data())); 29 | menuLayout->addWidget(icon); 30 | menuLayout->addWidget(titleLabel); 31 | 32 | 33 | 34 | //内容 35 | QWidget *contentWidget = new QWidget(this); 36 | contentWidget->setStyleSheet(".QWidget{background-color: rgb(255,255,255);}"); 37 | QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget); 38 | contentLayout->setContentsMargins(0,0,0,0); 39 | 40 | boxLayout->addWidget(menuWidget); 41 | boxLayout->addWidget(contentWidget); 42 | 43 | connect(icon,&QToolButton::clicked,this,[icon,contentWidget](){ 44 | if(icon->arrowType()==Qt::ArrowType::DownArrow){ 45 | contentWidget->hide(); 46 | icon->setArrowType(Qt::ArrowType::RightArrow); 47 | }else if (icon->arrowType()==Qt::ArrowType::RightArrow) { 48 | contentWidget->show(); 49 | icon->setArrowType(Qt::ArrowType::DownArrow); 50 | } 51 | }); 52 | 53 | gWidget = new QWidget(contentWidget); 54 | gLayout = new QGridLayout(gWidget); 55 | gLayout->setSpacing(18); 56 | gLayout->setColumnMinimumWidth(0,60); 57 | gLayout->setColumnStretch(2,10); 58 | 59 | 60 | contentLayout->addWidget(gWidget); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Utils/ComOptionsBox.h: -------------------------------------------------------------------------------- 1 | #ifndef COMOPTIONSBOX_H 2 | #define COMOPTIONSBOX_H 3 | 4 | #include 5 | QT_BEGIN_NAMESPACE; 6 | class QVBoxLayout; 7 | class QGridLayout; 8 | QT_END_NAMESPACE; 9 | 10 | class ComOptionsBox : public QWidget 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ComOptionsBox(QWidget *parent,const QString &name); 15 | 16 | QWidget *gWidget; 17 | QGridLayout *gLayout; 18 | int rowStart = 0; 19 | 20 | private: 21 | 22 | 23 | signals: 24 | 25 | public slots: 26 | }; 27 | 28 | #endif // COMOPTIONSBOX_H 29 | -------------------------------------------------------------------------------- /Utils/ComSpinWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ComSpinWidget.h" 2 | #include 3 | #include 4 | #include 5 | 6 | ComSpinWidget::ComSpinWidget(const QString &name,int min,int max,int value,int left,int right,QWidget *parent) : QWidget(parent) 7 | { 8 | this->value = value; 9 | 10 | QHBoxLayout *boxHLayout = new QHBoxLayout(this); 11 | boxHLayout->setContentsMargins(left,0,right,0); 12 | 13 | QLabel *nameLabel = new QLabel(this); 14 | nameLabel->setStyleSheet(".QLabel{color:rgb(64,65,66);font-family:Microsoft YaHei;font-size:12px;}"); 15 | nameLabel->setText(name); 16 | 17 | 18 | QSpinBox *countSpin = new QSpinBox(this); 19 | countSpin->setMinimum(min); 20 | countSpin->setMaximum(max); 21 | // countSpin->setSuffix("秒"); 22 | countSpin->setFixedWidth(100); 23 | countSpin->setStyleSheet(".QSpinBox{color:rgb(64,65,66);font-family:Microsoft YaHei;font-size:13px;border:1px solid rgb(217,217,217);border-radius: 3px; padding: 1px;}\ 24 | .QSpinBox:hover {border:1px solid rgb(64,65,66);}"); 25 | countSpin->setValue(value); 26 | 27 | boxHLayout->addWidget(nameLabel); 28 | boxHLayout->addWidget(countSpin); 29 | boxHLayout->addStretch(10); 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Utils/ComSpinWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef COMSPINWIDGET_H 2 | #define COMSPINWIDGET_H 3 | 4 | #include 5 | 6 | class ComSpinWidget : public QWidget 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ComSpinWidget(const QString &name,int min,int max,int value,int left,int right,QWidget *parent); 11 | 12 | int value = 0; 13 | 14 | signals: 15 | 16 | }; 17 | 18 | #endif // COMSPINWIDGET_H 19 | -------------------------------------------------------------------------------- /Utils/ComSplitHWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ComSplitHWidget.h" 2 | 3 | ComSplitHWidget::ComSplitHWidget(QWidget *parent) : QWidget(parent) 4 | { 5 | setAttribute(Qt::WA_StyledBackground,true); 6 | setStyleSheet(".ComSplitHWidget{background-color:rgb(221,222,225);}"); 7 | 8 | setCursor(Qt::SplitHCursor); 9 | } 10 | void ComSplitHWidget::mousePressEvent(QMouseEvent *event){ 11 | 12 | if (event->button() == Qt::LeftButton){ 13 | this->raise();//将此按钮移动到顶层显示 14 | this->pressPoint =event->pos(); 15 | } 16 | 17 | } 18 | 19 | void ComSplitHWidget::mouseMoveEvent(QMouseEvent *event){ 20 | 21 | if(event->buttons() == Qt::LeftButton){ 22 | QPoint change= event->pos() - this->pressPoint; 23 | int distance = change.x(); 24 | emit moveDistance(distance); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Utils/ComSplitHWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef COMSPLITHWIDGET_H 2 | #define COMSPLITHWIDGET_H 3 | 4 | #include 5 | #include 6 | class ComSplitHWidget : public QWidget 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ComSplitHWidget(QWidget *parent); 11 | protected: 12 | void mousePressEvent(QMouseEvent *event) override; 13 | void mouseMoveEvent(QMouseEvent *event) override; 14 | private: 15 | QPoint pressPoint; 16 | signals: 17 | void moveDistance(int distance); 18 | public slots: 19 | }; 20 | 21 | #endif // COMSPLITHWIDGET_H 22 | -------------------------------------------------------------------------------- /Utils/ComSplitVWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ComSplitVWidget.h" 2 | ComSplitVWidget::ComSplitVWidget(QWidget *parent) : QWidget(parent) 3 | { 4 | setAttribute(Qt::WA_StyledBackground,true); 5 | setStyleSheet(".ComSplitVWidget{background-color:rgb(221,222,225);}"); 6 | 7 | setCursor(Qt::SplitVCursor); 8 | } 9 | void ComSplitVWidget::mousePressEvent(QMouseEvent *event){ 10 | 11 | if (event->button() == Qt::LeftButton){ 12 | this->raise();//将此按钮移动到顶层显示 13 | this->pressPoint =event->pos(); 14 | } 15 | 16 | } 17 | 18 | void ComSplitVWidget::mouseMoveEvent(QMouseEvent *event){ 19 | 20 | if(event->buttons() == Qt::LeftButton){ 21 | QPoint change= event->pos() - this->pressPoint; 22 | int distance = change.y(); 23 | emit moveDistance(distance); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Utils/ComSplitVWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef COMSPLITVWIDGET_H 2 | #define COMSPLITVWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | class ComSplitVWidget : public QWidget 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit ComSplitVWidget(QWidget *parent); 12 | protected: 13 | void mousePressEvent(QMouseEvent *event) override; 14 | void mouseMoveEvent(QMouseEvent *event) override; 15 | private: 16 | QPoint pressPoint; 17 | signals: 18 | void moveDistance(int distance); 19 | 20 | public slots: 21 | }; 22 | 23 | #endif // COMSPLITVWIDGET_H 24 | -------------------------------------------------------------------------------- /Utils/FpsControl.cpp: -------------------------------------------------------------------------------- 1 | #include "FpsControl.h" 2 | #include 3 | #include 4 | #include 5 | 6 | FpsControl::FpsControl(int fps):target_fps(fps){ 7 | interval_duration = float(float(1000) / float(fps)); 8 | } 9 | FpsControl::~FpsControl() { 10 | 11 | } 12 | 13 | void FpsControl::realTimeStart() { 14 | realtime_start = gettime(); 15 | } 16 | void FpsControl::realTimeIncrease() { 17 | ++realtime_totalCount; 18 | } 19 | 20 | void FpsControl::intervalStart() { 21 | interval_start = gettime(); 22 | } 23 | 24 | void FpsControl::adjust() { 25 | 26 | //单帧间隔计算及其休眠计算 27 | interval_end = gettime(); 28 | interval_extra = interval_duration - (interval_end - interval_start); 29 | 30 | if (interval_extra > 0) { 31 | if (total_interval_extra > 0) { 32 | if (total_interval_extra >= interval_extra) { 33 | total_interval_extra -= interval_extra; 34 | } 35 | else { 36 | interval_extra -= total_interval_extra; 37 | total_interval_extra = 0; 38 | std::this_thread::sleep_for(std::chrono::milliseconds(interval_extra / 2)); 39 | } 40 | } 41 | else { 42 | std::this_thread::sleep_for(std::chrono::milliseconds(interval_extra / 2)); 43 | } 44 | } 45 | else if (interval_extra < 0) { 46 | total_interval_extra += (-interval_extra); 47 | } 48 | 49 | //实时计算帧率 50 | realtime_duration = gettime() - realtime_start; 51 | 52 | if (realtime_duration > 0) { 53 | realtime_fps = float(realtime_totalCount * 1000) / realtime_duration; 54 | if (realtime_fps > target_fps) { 55 | std::this_thread::sleep_for(std::chrono::milliseconds(interval_extra / 2)); 56 | } 57 | } 58 | 59 | } 60 | float FpsControl::getRealTimeFps(){ 61 | return realtime_fps; 62 | } 63 | int64_t FpsControl::gettime()// 获取毫秒级时间戳(13位) 64 | { 65 | return std::chrono::duration_cast( 66 | std::chrono::system_clock::now().time_since_epoch()). 67 | count(); 68 | 69 | } 70 | 71 | -------------------------------------------------------------------------------- /Utils/FpsControl.h: -------------------------------------------------------------------------------- 1 | #ifndef FPSCONTROL_H 2 | #define FPSCONTROL_H 3 | #include 4 | 5 | class FpsControl 6 | { 7 | public: 8 | FpsControl() = delete; 9 | FpsControl(int fps); 10 | ~FpsControl(); 11 | public: 12 | void realTimeStart(); 13 | void realTimeIncrease(); 14 | void intervalStart(); 15 | void adjust(); 16 | float getRealTimeFps(); 17 | 18 | private: 19 | int64_t gettime(); 20 | private: 21 | int target_fps;//目标 fps 22 | 23 | int64_t interval_start = 0; 24 | int64_t interval_end = 0; 25 | float interval_duration = 0;//单帧间隔时长(单位毫秒) 26 | int interval_extra = 0;//单帧额外需要休眠的时间(单位毫秒) 27 | int total_interval_extra = 0;//积累滞后的补偿休眠时长(单位毫秒) 28 | 29 | int64_t realtime_start = 0;//计算实时帧率的开始时间戳 30 | int64_t realtime_totalCount = 0;//开始计算实时帧率的总数量 31 | int64_t realtime_duration = 0;//开始计算实时帧率至今总耗时 32 | float realtime_fps = 0.0;//实时帧率 33 | 34 | 35 | }; 36 | 37 | #endif //FPSCONTROL_H 38 | -------------------------------------------------------------------------------- /Utils/SingletonUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "SingletonUtils.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | QAtomicPointer SingletonUtils::m_instance = 0; 8 | QMutex SingletonUtils::m_instanceMtx; 9 | 10 | 11 | SingletonUtils::SingletonUtils(QObject *parent): QObject(parent){ 12 | } 13 | SingletonUtils::~SingletonUtils(){ 14 | } 15 | 16 | 17 | SingletonUtils * SingletonUtils::getInstance(){ 18 | //! testAndSetOrders操作保证在原子操作前和后的的内存访问 不会被重新排序。 19 | if(m_instance.testAndSetOrdered(0,0)){ 20 | QMutexLocker locker(&m_instanceMtx); 21 | m_instance.testAndSetOrdered(0,new SingletonUtils(nullptr)); 22 | } 23 | return m_instance; 24 | 25 | } 26 | 27 | void SingletonUtils::setScreenSize(int width,int height){ 28 | mScreenWidth = width; 29 | mScreenHeight = height; 30 | } 31 | int SingletonUtils::getScreenWidth(){ 32 | return mScreenWidth; 33 | } 34 | int SingletonUtils::getScreenHeight(){ 35 | return mScreenHeight; 36 | } 37 | void SingletonUtils::setFinger(const QString &finger){ 38 | m_finger = finger; 39 | } 40 | QString SingletonUtils::getFinger() const{ 41 | return m_finger; 42 | } 43 | 44 | void SingletonUtils::setRecordDir(const QString &recordDir){ 45 | m_recordDir = recordDir; 46 | } 47 | QString SingletonUtils::getRecordDir() const{ 48 | return m_recordDir; 49 | } 50 | -------------------------------------------------------------------------------- /Utils/SingletonUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETONUTILS_H 2 | #define SINGLETONUTILS_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE; 7 | class QMutex; 8 | QT_END_NAMESPACE; 9 | 10 | class SingletonUtils : public QObject 11 | { 12 | Q_OBJECT 13 | private: 14 | explicit SingletonUtils(QObject *parent); 15 | ~SingletonUtils(); 16 | 17 | public: 18 | static SingletonUtils *getInstance(); 19 | void setScreenSize(int width,int height); 20 | int getScreenWidth();//主屏幕分辨率宽 21 | int getScreenHeight();//主屏幕分辨率高 22 | 23 | void setFinger(const QString &finger); 24 | QString getFinger() const; 25 | 26 | void setRecordDir(const QString &recordDir); 27 | QString getRecordDir() const; 28 | 29 | private: 30 | static QAtomicPointer m_instance; 31 | static QMutex m_instanceMtx; 32 | 33 | int mScreenWidth; 34 | int mScreenHeight; 35 | QString m_finger;//机器指纹 36 | QString m_recordDir;//录制视频的输出文件夹路径 37 | signals: 38 | 39 | }; 40 | 41 | #endif // SINGLETONUTILS_H 42 | -------------------------------------------------------------------------------- /Utils/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class Utils 9 | { 10 | public: 11 | static int64_t getCurTimestamp()// 获取毫秒级时间戳(13位) 12 | { 13 | return std::chrono::duration_cast( 14 | std::chrono::system_clock::now().time_since_epoch()). 15 | count(); 16 | 17 | } 18 | static int getCurTimestamp_second()// 获取秒级时间戳(10位) 19 | { 20 | int64_t curTimestamp = getCurTimestamp(); 21 | 22 | return int(curTimestamp/1000); 23 | } 24 | 25 | static bool mkDirs(QString dirPath){ 26 | QDir dir(dirPath); 27 | if(dir.exists()){ 28 | return true; 29 | }else{ 30 | bool result = dir.mkpath(dirPath);//创建多级目录 31 | return result; 32 | } 33 | } 34 | static QString secondsToDurationStr(int seconds){ 35 | int h = seconds/3600; 36 | int m = (seconds%3600)/60; 37 | int s = seconds%60; 38 | 39 | QString h_s; 40 | if(h<10){ 41 | h_s = QString("0%1").arg(h); 42 | }else{ 43 | h_s = QString::number(h); 44 | } 45 | QString m_s; 46 | if(m<10){ 47 | m_s = QString("0%1").arg(m); 48 | }else{ 49 | m_s = QString::number(m); 50 | } 51 | QString s_s; 52 | if(s<10){ 53 | s_s = QString("0%1").arg(s); 54 | }else{ 55 | s_s = QString::number(s); 56 | } 57 | QString durationStr = QString("%1:%2:%3").arg(h_s).arg(m_s).arg(s_s); 58 | return durationStr; 59 | } 60 | static void clearLogDir(const QString &logDir){ 61 | 62 | QDir dir(logDir); 63 | if(!dir.exists()){ 64 | return ; 65 | } 66 | dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); 67 | dir.setSorting(QDir::Size | QDir::Reversed); 68 | QFileInfoList list = dir.entryInfoList(); 69 | for (int i = 0; i < list.size(); ++i){ 70 | QFileInfo fileInfo = list.at(i); 71 | QString filename =fileInfo.fileName(); 72 | if(filename.size() > 10){ 73 | QDateTime time = QDateTime::fromString(filename.mid(0,10),"yyyy-MM-dd"); 74 | if(time.toSecsSinceEpoch() > 0){ 75 | //此前遗留的日志文件,删除 76 | fileInfo.dir().remove(fileInfo.absoluteFilePath()); 77 | } 78 | } 79 | 80 | } 81 | } 82 | 83 | static bool clearDir(const QString& path) 84 | { 85 | if (path.isEmpty()){ 86 | return false; 87 | } 88 | QDir dir(path); 89 | if(!dir.exists()){ 90 | return true; 91 | } 92 | dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); //设置过滤 93 | QFileInfoList fileList = dir.entryInfoList(); // 获取所有的文件信息 94 | foreach (QFileInfo file, fileList){ //遍历文件信息 95 | if (file.isFile()){ 96 | // file.dir().remove(file.fileName()); 97 | file.dir().removeRecursively(); 98 | }else{ // 递归删除 99 | clearDir(file.absoluteFilePath()); 100 | } 101 | } 102 | return dir.rmdir(dir.absolutePath()); 103 | } 104 | 105 | }; 106 | 107 | #endif // UTILS_H 108 | -------------------------------------------------------------------------------- /Utils/Utils.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/Utils.h \ 3 | $$PWD/SingletonUtils.h \ 4 | $$PWD/ComLineWidget.h \ 5 | $$PWD/ComLoadingLabel.h \ 6 | $$PWD/ComLoadingWidget.h \ 7 | $$PWD/ComMessageBox.h \ 8 | $$PWD/ComOptionsBox.h \ 9 | $$PWD/ComSpinWidget.h \ 10 | $$PWD/ComSplitHWidget.h \ 11 | $$PWD/ComSplitVWidget.h \ 12 | $$PWD/FpsControl.h \ 13 | $$PWD/constant.h 14 | 15 | SOURCES += \ 16 | $$PWD/SingletonUtils.cpp \ 17 | $$PWD/ComLineWidget.cpp \ 18 | $$PWD/ComLoadingLabel.cpp \ 19 | $$PWD/ComLoadingWidget.cpp \ 20 | $$PWD/ComMessageBox.cpp \ 21 | $$PWD/ComOptionsBox.cpp \ 22 | $$PWD/ComSpinWidget.cpp \ 23 | $$PWD/ComSplitHWidget.cpp \ 24 | $$PWD/ComSplitVWidget.cpp \ 25 | $$PWD/FpsControl.cpp \ 26 | 27 | INCLUDEPATH += Utils 28 | -------------------------------------------------------------------------------- /Utils/constant.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSTANT_H 2 | #define CONSTANT_H 3 | 4 | #include 5 | 6 | const QString URL_DOCUMENT = "https://github.com/any12345com/SRE/blob/master/README.md";// 文档 7 | const QString URL_OPENSOURCE = "https://github.com/any12345com/SRE"; // 开源地址 8 | const QString SRE_URL_FEEDBACK = "https://github.com/any12345com/SRE/issues"; // 反馈 9 | const QString SRE_SETTINGS_DIR = "SRE_SETTINGS_DIR"; 10 | 11 | #endif // CONSTANT_H 12 | -------------------------------------------------------------------------------- /VNCClient/ClientDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "ClientDialog.h" 2 | #include "ClientTabWidget.h" 3 | #include 4 | #include 5 | #include 6 | ClientDialog::ClientDialog(QWidget *parent) :QDialog(parent) 7 | { 8 | qDebug()<<"ClientDialog::ClientDialog()"; 9 | Qt::WindowFlags flags=Qt::Dialog; 10 | flags |= Qt::WindowMinMaxButtonsHint; 11 | flags |= Qt::WindowCloseButtonHint; 12 | setWindowFlags(flags); 13 | resize(1000,600); 14 | setAttribute(Qt::WA_StyledBackground,true); 15 | setStyleSheet(QString(".ClientDialog{background-color:%1;}").arg("rgb(43,46,56)")); 16 | setWindowTitle(tr("远程控制")); 17 | 18 | initUi(); 19 | 20 | } 21 | 22 | ClientDialog::~ClientDialog(){ 23 | qDebug()<<"ClientDialog::~ClientDialog()"; 24 | 25 | } 26 | void ClientDialog::initUi(){ 27 | QVBoxLayout *mainVLayout = new QVBoxLayout(this); 28 | mainVLayout->setContentsMargins(0,0,0,0); 29 | mainVLayout->setSpacing(0); 30 | 31 | CilentTabWidget *tabWidget = new CilentTabWidget(this); 32 | mainVLayout->addWidget(tabWidget); 33 | 34 | tabWidget->addDesktopTab(); 35 | 36 | } 37 | 38 | void ClientDialog::closeEvent(QCloseEvent *event){ 39 | Q_UNUSED(event); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /VNCClient/ClientDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENTDIALOG_H 2 | #define CLIENTDIALOG_H 3 | 4 | #include 5 | 6 | class ClientDialog : public QDialog 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | explicit ClientDialog(QWidget *parent); 12 | ~ClientDialog(); 13 | private: 14 | void initUi(); 15 | 16 | protected: 17 | void closeEvent(QCloseEvent *) override; 18 | 19 | signals: 20 | 21 | public slots: 22 | 23 | }; 24 | 25 | #endif // CLIENTDIALOG_H 26 | -------------------------------------------------------------------------------- /VNCClient/ClientTabWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ClientTabWidget.h" 2 | #include 3 | #include 4 | #include 5 | #include "DesktopControlWidget.h" 6 | #include 7 | 8 | CilentTabWidget::CilentTabWidget(QWidget *parent) : QTabWidget(parent) 9 | { 10 | QString tab_qss = "QTabWidget::pane{} \ 11 | QTabBar::tab {color:rgb(0,0,0);font-size:14px;min-width:110px;height:30px;margin:2px;} \ 12 | QTabBar::tab:!selected {background:rgb(255,255,255);border:1px solid rgb(233,233,233);} \ 13 | QTabBar::tab:hover{background:rgba(255,255,255,0.8);} \ 14 | QTabBar::tab:selected {background:rgb(219,228,241);}"; 15 | 16 | setStyleSheet(tab_qss); 17 | QTabBar *tabBar = this->tabBar(); 18 | tabBar->setTabsClosable(true); 19 | tabBar->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); 20 | tabBar->setMovable(true); 21 | tabBar->setContextMenuPolicy(Qt::CustomContextMenu); 22 | 23 | // connect(tabBar, &QTabBar::customContextMenuRequested, this, &CilentTabWidget::onHandleContextMenuRequested); 24 | connect(tabBar, &QTabBar::tabCloseRequested, this, &CilentTabWidget::onCloseTab); 25 | setDocumentMode(true); 26 | // setElideMode(Qt::ElideRight); 27 | 28 | } 29 | 30 | 31 | void CilentTabWidget::addDesktopTab(){ 32 | 33 | DesktopControlWidget *desktop = new DesktopControlWidget(this); 34 | addTab(desktop,tr("首页")); 35 | setCurrentWidget(desktop); 36 | 37 | // connect(desktop,&PageIndex::notifyCreateCustomTask,this,[this](const QString &address){ 38 | // createPageCustomTask(address); 39 | // }); 40 | } 41 | 42 | void CilentTabWidget::onCloseTab(int index){ 43 | QWidget *cw = widget(index); 44 | if("PageIndex"==QString(cw->metaObject()->className())){ 45 | 46 | }else{ 47 | removeTab(index); 48 | 49 | cw->deleteLater(); 50 | // delete currentWidget; 51 | 52 | // if (WebView *view = webView(index)) { 53 | // bool hasFocus = view->hasFocus(); 54 | // removeTab(index); 55 | // if (hasFocus && count() > 0) 56 | // currentWebView()->setFocus(); 57 | // if (count() == 0) 58 | // createTab(); 59 | // view->deleteLater(); 60 | // } 61 | 62 | 63 | } 64 | 65 | 66 | } 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /VNCClient/ClientTabWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENTTABWIDGET_H 2 | #define CLIENTTABWIDGET_H 3 | #include 4 | 5 | class CilentTabWidget : public QTabWidget 6 | { 7 | Q_OBJECT 8 | public: 9 | explicit CilentTabWidget(QWidget *parent); 10 | 11 | public: 12 | void addDesktopTab(); 13 | 14 | signals: 15 | public slots: 16 | void onCloseTab(int index); 17 | 18 | }; 19 | 20 | #endif // CLIENTTABWIDGET_H 21 | -------------------------------------------------------------------------------- /VNCClient/DesktopControlWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "DesktopControlWidget.h" 2 | #include 3 | 4 | DesktopControlWidget::DesktopControlWidget(QWidget *parent) 5 | : QWidget{parent} 6 | { 7 | setAttribute(Qt::WA_StyledBackground,true); 8 | setStyleSheet(QString(".DesktopControlWidget{background-color:%1;}").arg("rgb(255,0,0)")); 9 | 10 | initUi(); 11 | } 12 | void DesktopControlWidget::initUi(){ 13 | QVBoxLayout *mainVLayout = new QVBoxLayout(this); 14 | mainVLayout->setContentsMargins(0,0,0,0); 15 | mainVLayout->setSpacing(0); 16 | 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /VNCClient/DesktopControlWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef DESKTOPCONTROLWIDGET_H 2 | #define DESKTOPCONTROLWIDGET_H 3 | 4 | #include 5 | 6 | class DesktopControlWidget : public QWidget 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit DesktopControlWidget(QWidget *parent = nullptr); 11 | private: 12 | void initUi(); 13 | signals: 14 | 15 | }; 16 | 17 | #endif // DESKTOPCONTROLWIDGET_H 18 | -------------------------------------------------------------------------------- /VNCClient/VNCClient.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/ClientDialog.h \ 3 | $$PWD/ClientTabWidget.h \ 4 | $$PWD/DesktopControlWidget.h \ 5 | $$PWD/VNCClientWidget.h \ 6 | 7 | 8 | SOURCES += \ 9 | $$PWD/ClientDialog.cpp \ 10 | $$PWD/ClientTabWidget.cpp \ 11 | $$PWD/DesktopControlWidget.cpp \ 12 | $$PWD/VNCClientWidget.cpp \ 13 | 14 | 15 | INCLUDEPATH += VNCClient 16 | -------------------------------------------------------------------------------- /VNCClient/VNCClientWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "VNCClientWidget.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ComLineWidget.h" 8 | #include "ClientDialog.h" 9 | 10 | VNCClientWidget::VNCClientWidget(QWidget *parent) : QWidget(parent) 11 | { 12 | setAttribute(Qt::WA_StyledBackground,true); 13 | setStyleSheet(QString(".VNCClientWidget{background-color:%1;}").arg("rgb(25,27,38)")); 14 | 15 | clientDialog = new ClientDialog(this); 16 | 17 | initUi(); 18 | 19 | } 20 | void VNCClientWidget::initUi(){ 21 | QHBoxLayout *mainHLayout = new QHBoxLayout(this); 22 | mainHLayout->setContentsMargins(0,0,0,0); 23 | mainHLayout->setSpacing(0); 24 | 25 | QWidget *leftWidget = initLeftWidget(); 26 | leftWidget->setFixedWidth(300); 27 | 28 | QWidget *rightWidget = initRightWidget(); 29 | mainHLayout->addWidget(leftWidget); 30 | // ComLineWidget *line = new ComLineWidget(this,1); 31 | // line->setStyleSheet(".ComLineWidget{background-color:rgb(76,76,76);}"); 32 | // mainHLayout->addWidget(line); 33 | mainHLayout->addWidget(rightWidget); 34 | } 35 | QWidget* VNCClientWidget::initLeftWidget(){ 36 | QWidget * widget = new QWidget(this); 37 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 38 | widgetVLayout->setContentsMargins(0,0,0,0); 39 | widgetVLayout->setSpacing(0); 40 | 41 | //name strt 42 | QWidget * nameWidget = new QWidget(widget); 43 | nameWidget->setFixedHeight(80); 44 | QHBoxLayout *nameHLayout = new QHBoxLayout(nameWidget); 45 | nameHLayout->setContentsMargins(0,0,0,0); 46 | nameHLayout->setSpacing(0); 47 | QLabel *nameLabel = new QLabel(nameWidget); 48 | nameLabel->setFixedHeight(40); 49 | nameLabel->setCursor(Qt::PointingHandCursor); 50 | nameLabel->setStyleSheet(".QLabel{color:rgb(255,255,255);font-size:18px;border:1px solid rgb(76,76,76); border-radius: 2px;padding: 4px 8px;}"); 51 | nameLabel->setText(tr("我的设备列表")); 52 | nameHLayout->addSpacing(40); 53 | nameHLayout->addWidget(nameLabel); 54 | nameHLayout->addStretch(10); 55 | //name end 56 | 57 | //list start 58 | QWidget * deviceWidget = new QWidget(widget); 59 | QHBoxLayout *deviceHLayout = new QHBoxLayout(deviceWidget); 60 | deviceHLayout->setContentsMargins(20,0,20,0); 61 | deviceHLayout->setSpacing(0); 62 | deviceListWidget = new QListWidget(deviceWidget); 63 | deviceListWidget->setStyleSheet("QListWidget{background-color:rgba(0,0,0,0);border:1px solid gray;padding:10px; font-size:18px;color:rgb(255,255,255); }" 64 | "QListWidget::Item{padding:10px; }" 65 | "QListWidget::Item:hover{background:rgb(54,98,180); }" 66 | "QListWidget::item:selected{background:rgb(54,98,180); }" 67 | "QListWidget::item:selected:!active{background:rgb(54,98,180); }" 68 | ); 69 | deviceListWidget->setFocusPolicy(Qt::NoFocus);//去除虚线框 70 | 71 | // deviceListWidget->setStyleSheet(".QListWidget{border:1px solid rgb(217,217,217); border-radius: 0px;padding: 2px;}"); 72 | // deviceListWidget->setFixedHeight(200); 73 | 74 | deviceHLayout->addSpacing(10); 75 | deviceHLayout->addWidget(deviceListWidget); 76 | deviceHLayout->addSpacing(10); 77 | 78 | 79 | QListWidgetItem * item = new QListWidgetItem("test1",deviceListWidget); 80 | deviceListWidget->addItem(item); 81 | item = new QListWidgetItem("test2",deviceListWidget); 82 | deviceListWidget->addItem(item); 83 | //list end 84 | 85 | 86 | widgetVLayout->addSpacing(80); 87 | widgetVLayout->addWidget(nameWidget); 88 | widgetVLayout->addSpacing(10); 89 | widgetVLayout->addWidget(deviceWidget); 90 | widgetVLayout->addStretch(10); 91 | 92 | return widget; 93 | 94 | } 95 | QWidget* VNCClientWidget::initRightWidget(){ 96 | QWidget * widget = new QWidget(this); 97 | QVBoxLayout *widgetVLayout = new QVBoxLayout(widget); 98 | widgetVLayout->setContentsMargins(0,0,0,0); 99 | widgetVLayout->setSpacing(0); 100 | 101 | 102 | QWidget * menuWidget = new QWidget(widget); 103 | menuWidget->setFixedHeight(80); 104 | QHBoxLayout *menuHLayout = new QHBoxLayout(menuWidget); 105 | menuHLayout->setContentsMargins(0,0,0,0); 106 | menuHLayout->setSpacing(0); 107 | 108 | QPushButton *deskControlBtn = new QPushButton(widget); 109 | deskControlBtn->setFixedSize(120,40); 110 | deskControlBtn->setCursor(Qt::PointingHandCursor); 111 | deskControlBtn->setText(tr("桌面控制")); 112 | 113 | QPushButton *deskViewBtn = new QPushButton(widget); 114 | deskViewBtn->setFixedSize(120,40); 115 | deskViewBtn->setCursor(Qt::PointingHandCursor); 116 | deskViewBtn->setText(tr("桌面观看")); 117 | 118 | connect(deskControlBtn,&QPushButton::clicked,this,[this](){ 119 | clientDialog->show(); 120 | }); 121 | 122 | connect(deskViewBtn,&QPushButton::clicked,this,[this](){ 123 | clientDialog->show(); 124 | }); 125 | 126 | menuHLayout->addStretch(10); 127 | menuHLayout->addWidget(deskControlBtn); 128 | menuHLayout->addSpacing(20); 129 | menuHLayout->addWidget(deskViewBtn); 130 | menuHLayout->addStretch(10); 131 | 132 | 133 | widgetVLayout->addSpacing(100); 134 | widgetVLayout->addWidget(menuWidget); 135 | widgetVLayout->addStretch(10); 136 | 137 | 138 | 139 | return widget; 140 | 141 | 142 | } 143 | -------------------------------------------------------------------------------- /VNCClient/VNCClientWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef VNCCLIENTWIDGET_H 2 | #define VNCCLIENTWIDGET_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE; 7 | class QListWidget; 8 | QT_END_NAMESPACE; 9 | class ClientDialog; 10 | 11 | class VNCClientWidget : public QWidget 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit VNCClientWidget(QWidget *parent); 16 | private: 17 | void initUi(); 18 | QWidget* initLeftWidget(); 19 | QListWidget *deviceListWidget; 20 | 21 | QWidget* initRightWidget(); 22 | 23 | ClientDialog *clientDialog; 24 | 25 | signals: 26 | 27 | }; 28 | 29 | #endif // VNCCLIENTWIDGET_H 30 | -------------------------------------------------------------------------------- /VNCServer/VNCServer.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/VNCServerWidget.h 3 | 4 | SOURCES += \ 5 | $$PWD/VNCServerWidget.cpp 6 | 7 | 8 | INCLUDEPATH += VNCServer 9 | -------------------------------------------------------------------------------- /VNCServer/VNCServerWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "VNCServerWidget.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | VNCServerWidget::VNCServerWidget(QWidget *parent) : QWidget(parent) 8 | { 9 | setAttribute(Qt::WA_StyledBackground,true); 10 | setStyleSheet(QString(".VNCServerWidget{background-color:%1;}").arg("rgb(25,27,38)")); 11 | initUi(); 12 | } 13 | 14 | void VNCServerWidget::initUi(){ 15 | 16 | QVBoxLayout *mainVLayout = new QVBoxLayout(this); 17 | mainVLayout->setContentsMargins(0,0,0,0); 18 | mainVLayout->setSpacing(0); 19 | 20 | //name start 21 | QWidget * nameWidget = new QWidget(this); 22 | nameWidget->setFixedHeight(80); 23 | QHBoxLayout *nameHLayout = new QHBoxLayout(nameWidget); 24 | nameHLayout->setContentsMargins(0,0,0,0); 25 | nameHLayout->setSpacing(0); 26 | QLabel *nameLabel = new QLabel(nameWidget); 27 | nameLabel->setFixedHeight(40); 28 | nameLabel->setCursor(Qt::PointingHandCursor); 29 | nameLabel->setStyleSheet(".QLabel{color:rgb(255,255,255);font-size:18px;border:1px solid rgb(76,76,76); border-radius: 2px;padding: 4px 8px;}"); 30 | nameLabel->setText(tr("允许控制本设备")); 31 | nameHLayout->addSpacing(40); 32 | nameHLayout->addWidget(nameLabel); 33 | nameHLayout->addStretch(10); 34 | //name end 35 | 36 | //info start 37 | QWidget * infoWidget = new QWidget(this); 38 | infoWidget->setFixedHeight(100); 39 | QHBoxLayout *infoHLayout = new QHBoxLayout(infoWidget); 40 | infoHLayout->setContentsMargins(0,0,0,0); 41 | infoHLayout->setSpacing(0); 42 | 43 | //info-left 44 | QString qss_name = ".QLabel{color:rgb(200,200,200);font-size:18px;}"; 45 | QString qss_value = ".QLabel{color:rgb(255,255,255);font-size:22px;}"; 46 | QWidget * infoLeftWidget = new QWidget(infoWidget); 47 | infoLeftWidget->setFixedWidth(200); 48 | QVBoxLayout *infoLeftVLayout = new QVBoxLayout(infoLeftWidget); 49 | infoLeftVLayout->setContentsMargins(0,0,0,0); 50 | infoLeftVLayout->setSpacing(0); 51 | 52 | QLabel *infoLeft_name = new QLabel(infoLeftWidget); 53 | infoLeft_name->setStyleSheet(qss_name); 54 | infoLeft_name->setText("本设备IP地址"); 55 | 56 | QLabel *infoLeft_ip = new QLabel(infoLeftWidget); 57 | infoLeft_ip->setStyleSheet(qss_value); 58 | infoLeft_ip->setText("127.0.0.1"); 59 | 60 | 61 | infoLeftVLayout->addSpacing(20); 62 | infoLeftVLayout->addWidget(infoLeft_name); 63 | infoLeftVLayout->addSpacing(10); 64 | infoLeftVLayout->addWidget(infoLeft_ip); 65 | infoLeftVLayout->addStretch(10); 66 | 67 | //info-right 68 | QWidget * infoRightWidget = new QWidget(infoWidget); 69 | infoRightWidget->setFixedWidth(200); 70 | QVBoxLayout *infoRightVLayout = new QVBoxLayout(infoRightWidget); 71 | infoRightVLayout->setContentsMargins(0,0,0,0); 72 | infoRightVLayout->setSpacing(0); 73 | 74 | QLabel *infoRight_name = new QLabel(infoRightWidget); 75 | infoRight_name->setStyleSheet(qss_name); 76 | infoRight_name->setText("连接验证码"); 77 | 78 | QLabel *infoRight_code = new QLabel(infoRightWidget); 79 | infoRight_code->setStyleSheet(qss_value); 80 | infoRight_code->setText("112400"); 81 | 82 | 83 | infoRightVLayout->addSpacing(20); 84 | infoRightVLayout->addWidget(infoRight_name); 85 | infoRightVLayout->addSpacing(10); 86 | infoRightVLayout->addWidget(infoRight_code); 87 | infoRightVLayout->addStretch(10); 88 | 89 | infoHLayout->addStretch(10); 90 | infoHLayout->addWidget(infoLeftWidget); 91 | infoHLayout->addSpacing(60); 92 | infoHLayout->addWidget(infoRightWidget); 93 | infoHLayout->addStretch(10); 94 | //info end 95 | 96 | 97 | 98 | 99 | // mainVLayout->addWidget(label,0,Qt::AlignHCenter); 100 | // mainVLayout->addStretch(50); 101 | 102 | mainVLayout->addSpacing(80); 103 | mainVLayout->addWidget(nameWidget); 104 | mainVLayout->addSpacing(10); 105 | mainVLayout->addWidget(infoWidget); 106 | mainVLayout->addStretch(10); 107 | } 108 | -------------------------------------------------------------------------------- /VNCServer/VNCServerWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef VNCSERVERWIDGET_H 2 | #define VNCSERVERWIDGET_H 3 | 4 | #include 5 | 6 | 7 | class VNCServerWidget : public QWidget 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit VNCServerWidget(QWidget *parent); 12 | private: 13 | void initUi(); 14 | signals: 15 | 16 | }; 17 | 18 | #endif // VNCSERVERWIDGET_H 19 | -------------------------------------------------------------------------------- /logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/logo.ico -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Utils/Utils.h" 9 | #include "Utils/ComMessageBox.h" 10 | using namespace QsLogging; 11 | 12 | void initLogger(const QString &logDir){ 13 | 14 | if(Utils::mkDirs(logDir)){ 15 | Logger& logger = Logger::instance(); 16 | logger.setLoggingLevel(QsLogging::TraceLevel); 17 | // QString timeStr = QDate::currentDate().toString("yyyy-MM-dd"); 18 | // QDateTime time = QDateTime::fromString(timeStr,"yyyy-MM-dd"); 19 | 20 | QString logFile = QString("%1/run.log").arg(logDir); 21 | DestinationPtr des( 22 | DestinationFactory::MakeFileDestination(logFile, 23 | EnableLogRotation, 24 | MaxSizeBytes(1*1024*1024), 25 | MaxOldLogCount(1))); 26 | logger.addDestination(des); 27 | QLOG_INFO()<<"initLogger() success logDir="<= QT_VERSION_CHECK(6,0,0)) 57 | QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor); 58 | #elif (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) 59 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 60 | QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 61 | #endif 62 | 63 | 64 | QApplication a(argc, argv); 65 | a.setWindowIcon(QIcon(QStringLiteral(":/res/images/logo.png"))); 66 | 67 | QSharedMemory shared("SRE"); 68 | if(shared.attach()){ 69 | ComMessageBox::error(NULL,"软件已经在运行中"); 70 | return 0; 71 | } 72 | shared.create(1); 73 | 74 | // 获取程序当前地址,需要在QApplication初始化之后获取,否则获取的地址错误 75 | // QString logDir = QDir::homePath()+"/AppData/Local/SRE/logs"; 76 | QString logDir = QApplication::applicationDirPath() + "/logs"; 77 | // Utils::clearLogDir(logDir); 78 | initLogger(logDir); 79 | 80 | QString vInfo = QString("SRE V%1").arg(QCoreApplication::applicationVersion()); 81 | 82 | qDebug()<< vInfo; 83 | QLOG_INFO()<< vInfo; 84 | 85 | MainWindow mainWindow; 86 | mainWindow.show(); 87 | 88 | return a.exec(); 89 | } 90 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "SingletonUtils.h" 7 | #include "IndexWidget.h" 8 | #include 9 | #include 10 | 11 | MainWindow::MainWindow(QWidget *parent) 12 | : QMainWindow(parent) 13 | { 14 | setAttribute(Qt::WA_StyledBackground,true); 15 | setStyleSheet(QString(".MainWindow{background-color:%1;}").arg("rgb(31,33,42)")); 16 | QString title = QString("SRE V%1 (64-bit,windows)").arg(QCoreApplication::applicationVersion()); 17 | setWindowTitle(title); 18 | 19 | QList screens = QGuiApplication::screens();//获取多屏幕 20 | // QScreen * screen = QGuiApplication::primaryScreen();//获取主屏幕 21 | QScreen * screen = screens.at(0);//获取多屏幕第一块屏幕(暂未做多屏幕的兼容) 22 | QRect screenRect = screen->geometry(); 23 | int screenWidth = screenRect.width(); 24 | int screenHeight = screenRect.height(); 25 | SingletonUtils::getInstance()->setScreenSize(screenWidth,screenHeight); 26 | 27 | int w = int(float(screenWidth) * 0.5); 28 | int h = int(float(screenHeight) * 0.5); 29 | 30 | QLOG_INFO() << "screens="<size(); 42 | } 43 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | class MainWindow : public QMainWindow 6 | { 7 | Q_OBJECT 8 | public: 9 | MainWindow(QWidget *parent = nullptr); 10 | private: 11 | virtual void resizeEvent(QResizeEvent* event) override; 12 | }; 13 | #endif // MAINWINDOW_H 14 | -------------------------------------------------------------------------------- /res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | res/images/logo.png 4 | res/images/icon/error.png 5 | res/images/icon/logout.png 6 | res/images/icon/password.png 7 | res/images/icon/search.png 8 | res/images/icon/searchblack.png 9 | res/images/icon/settings.png 10 | res/images/icon/stop.png 11 | res/images/icon/success.png 12 | res/images/icon/warning.png 13 | 14 | 15 | -------------------------------------------------------------------------------- /res/images/icon/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/error.png -------------------------------------------------------------------------------- /res/images/icon/logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/logout.png -------------------------------------------------------------------------------- /res/images/icon/password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/password.png -------------------------------------------------------------------------------- /res/images/icon/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/search.png -------------------------------------------------------------------------------- /res/images/icon/searchblack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/searchblack.png -------------------------------------------------------------------------------- /res/images/icon/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/settings.png -------------------------------------------------------------------------------- /res/images/icon/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/stop.png -------------------------------------------------------------------------------- /res/images/icon/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/success.png -------------------------------------------------------------------------------- /res/images/icon/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/icon/warning.png -------------------------------------------------------------------------------- /res/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beixiaocai/SRE/5562736ef69cf0447e1777313bbe6564214d2448/res/images/logo.png --------------------------------------------------------------------------------