0 前言说明
0.1 系统说明
- 本视频监控系统做的是通用的系统,主要偏重整体框架和UI交互等。
- 主要功能包括摄像机管理,实时视频显示,视频轮询、视频存储、设备地图显示,各种画面切换,各种悬停子模块、onvif搜索设备和云台控制及预置位,通用的NVR视频流播放(比如海康的NVR支持直接取流回放)等功能。
- 如果是依赖SDK去实现的功能(雨刷、去雾等)都没有做,那个破坏了兼容性,无法通用其他摄像机设备以及其他操作系统。
- 每个厂家SDK和定制的功能都不一样,如果有这方面的需要都是买过去自己加上SDK的功能和自己定制需要的功能。
- 整个项目源代码行数大概30W行(项目代码本身约7W行),其中代码13.5W行(占比45%),注释12.7W行(占比42%),空行3.5W行。分层设计注释详细。
- 本程序会一直持续迭代更新,包括项目源码、整体框架、使用说明等,购买者可永久免费升级,一次购买终生售后。
0.2 特别说明
- 程序本身是个客户端(直接从摄像机取rtsp视频流)并不是服务器程序。
- 摄像机管理没有限制摄像机的数量,理论上10000路肯定没有问题,就是个数据库记录。
- 实时显示具体能支持多少路,和具体的电脑配置有关(亲测1.8G主频8G内存I5子码流64路,总之比海康大华客户端要更优秀)。
- 程序实时显示界面最大可以到64路,每个通道都是打开的时候才会去建立连接取视频流,而不是一开始就建立了连接。
- 系统采用onvif协议+rtsp视频流机制,并不限定支持哪家的摄像机,只要符合这两种协议的都支持,市面上99%的网络摄像机都支持这两种基础协议,包括但不限于海康、大华、宇视、天地伟业、华为等各种安防厂家的摄像机。
- 本系统没有内置人脸识别等任何相关算法,提供的是相关的接口,比如自己的算法识别到人脸区域后,将区域坐标传入视频控件自动绘制。
- 本系统适用于安防行业,所有录制视频也是针对摄像机的视频流,包括摄像机自身的rtsp格式视频流,摄像机重新推流的rtmp或者http的视频流,凡是源头不是摄像机的视频流一概不存储或者存储不成功,因为可能编码格式不一样。比如中央卫视、大雄兔等视频流是不存储的,因为源头不是摄像机。任何监控厂家的视频监控系统都是只存储监控摄像机的视频,其他一概不存储甚至添加都没法添加到系统中因为过滤掉了。
- 系统采用纯QtWidget(非qml)编写,解码采用ffmpeg,搜索采用onvif协议,视频播放采用rtsp协议,所有源码开放,并非有封装的库。
- 同时集成了数据库,多线程,串口通信,网络通信,音视频解码,网页地图、界面美化、UI布局等众多知识点。
- 未经本人许可不可将本项目源码扩散,如有发现本人将追究法律责任,谢谢配合。
0.3 相关站点
- 国内站点:https://gitee.com/feiyangqingyun
- 国际站点:https://github.com/feiyangqingyun
- 个人主页:https://blog.csdn.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun
- 产品主页:https://blog.csdn.net/feiyangqingyun/article/details/97565652
- 在线文档:https://feiyangqingyun.gitee.io/qwidgetdemo/video_system.html
- 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_system.zip。
0.4 功能特点
0.4.1 软件模块
- 视频监控模块,各种停靠小窗体子模块,包括设备列表、图文警情、窗口信息、云台控制、预置位、巡航设置、设备控制、悬浮地图、网页浏览等。
- 视频回放模块,包括本地回放、远程回放、设备播放、图片回放、视频上传等。
- 电子地图模块,包括图片地图、在线地图、离线地图、路径规划等。
- 日志查询模块,包括本地日志、设备日志等。
- 系统设置模块,包括系统设置(基本设置、视频参数、数据库设置、地图配置、串口配置等)、录像机管理、摄像机管理、轮询配置、用户管理等。
0.4.2 基础功能
- 支持各种视频流(rtsp、rtmp、http等)、视频文件(mp4、rmvb、avi等)、本地USB摄像机播放。
- 支持多画面切换,包括1、4、6、8、9、13、16、25、36、64画面切换。
- 支持全屏切换,多种切换方式包括鼠标右键菜单、工具栏按钮、快捷键(alt+enter全屏,esc退出全屏)。
- 支持视频轮询,包括1、4、9、16画面轮询,可设置轮询分组(轮询预案)、轮询间隔、码流类型等。
- 支持onvif协议,包括设备搜索、云台控制、预置位、设备控制(图片参数、校对时间、系统重启,抓拍图片等)。
- 支持权限管理,不同的用户可以对应不同的模块权限,比如删除日志、关闭系统等。
- 数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。
- 本地USB摄像机支持设置分辨率、帧率等参数。
- 所有停靠模块都自动生成对应的菜单用来控制显示和隐藏,在标题栏右键可以弹出。
- 支持显示所有模块、隐藏所有模块、复位普通布局、复位全屏布局。
- 双击设备弹出实时预览视频,支持图片地图、在线地图、离线地图等。
- 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
- 删除视频支持鼠标右键删除、悬浮条关闭删除、拖曳到视频监控面板外删除等多种方式。
- 图片地图上设备按钮可自由拖动,自动保存位置信息。百度地图上可以鼠标单击获取经纬度信息,用来更新设备位置。
- 视频监控面板窗体中任意通道支持拖曳交换,瞬间响应。
- 封装了百度地图,视图切换,运动轨迹,设备点位,鼠标按下获取经纬度等。
- 双击节点、拖曳节点、拖曳窗体交换位置等操作,均自动更新保存最后的播放地址,下次软件打开自动应用。
- 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
- 支持视频截图,可指定单个或者对所有通道截图,底部小工具栏也有截图按钮。
- 支持超时自动隐藏鼠标指针、自动全屏机制。
- 支持onvif云台控制,可上下左右移动云台摄像机,包括复位和焦距调整等。
- 支持任意onvif摄像机,包括但不限于海康、大华、宇视、天地伟业、华为等。
- 可保存视频,可选定时存储或者单文件存储,可选存储间隔时间。
- 可设置视频流通信方式tcp+udp,可设置视频解码是速度优先、质量优先、均衡等。
- 可设置软件中文名称、英文名称、LOGO图标等。
- 存储的视频文件支持导出到指定目录,支持批量上传到服务器。
0.4.3 特色功能
- 主界面采用停靠窗体模式,各种组件以小模块的形式加入,可自定义任意模块加入。
- 停靠模块可拖动任意位置嵌入和悬浮,支持最大化全屏,支持多屏幕。
- 双重布局文件存储机制,正常模式、全屏模式都对应不同的布局方案,自动切换和保存,比如全屏模式可以突出几个模块透明显示在指定位置,更具科幻感现代化。
- 原创onvif协议机制,采用底层协议解析(udp广播搜索+http请求执行命令)更轻量易懂易学习拓展,不依赖任何第三方组件比如gsoap。
- 原创数据导入导出机制,跨平台不依赖任何组件,瞬间导出数据。
- 内置多个原创组件,宇宙超值超级牛逼,包括数据导入导出组件(导出到xls、pdf、打印)、数据库组件(数据库管理线程、自动清理数据线程、万能分页、数据请求等)、地图组件、视频监控组件、文件多线程收发组件、onvif通信组件、通用浏览器内核组件等。
- 自定义信息框+错误框+询问框+右下角提示框(包含多种格式)等。
- 精美换肤,高达17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
- 视频控件悬浮条可以自行增加多个按钮,监控界面底部小工具栏也可自行增加按钮。
- 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。可选主码流、子码流。
- 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
- 可选多种内核自由切换,ffmpeg、vlc、mpv等,均可在pro中设置。推荐用ffmpeg,跨平台最多,默认提供好了linux和mac平台上编译好的库。
- 支持硬解码,可设置硬解码类型(qsv、dxva2、d3d11va等)。
- 默认采用opengl绘制视频,超低的CPU资源占用,支持yuyv和nv12两种格式绘制,很牛逼。
- 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,比如增加自定义模块,增加运行模式、机器人监控、无人机监控、挖掘机监控等。
- 支持xp、win7、win10、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。
- 注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。
0.5 目录说明
- 本源码项目文件中对编译生成的临时文件和可执行文件做了重定向,可执行文件并不在build开头的目录下,而是在源码同级目录的bin目录下。
- config目录放的是软件的配置文件、地图模块需要的图片资源等。
- db目录一般有三个文件,key.db是秘钥文件、video_system.db是对应sqlite的数据库文件、video_system.sql是对应数据库脚本(可以在系统设置中数据库管理部分执行脚本用来切换到mysql等其他数据库)。
- logo目录存放的各种左上角软件LOGO图片,可以在系统设置中下拉选择。
- map目录存放的图片地图模块所用的地图图片文件,可以手动拷贝到此。
- sound目录存放的本系统所用的声音文件。
- layout目录存放的不同工作模式不同界面对应的布局方案配置文件。
0.6 编译说明
0.6.1 特别提示
- 本系统没有说基于哪个Qt版本,由于系统中电子地图模块用到了浏览器模块,所以理论上要求你电脑的Qt版本也有浏览器模块才行
- windows上Qt5.6以上的版本需要msvc编译器的版本才有,其余系统都会有。
- 如果没有则电子地图模块不可用,但是其余功能全部可用没有任何影响。
- 本人亲测4.7、4.8、5.5、5.6、5.7、5.9、5.12、5.13、5.14、5.15、6.1等。
- 2021-1-6开始集成了miniblink浏览器内核,意味着mingw版本的qt5.6以上版本也全部支持,这样就所有系统都有浏览器模块不需要担心没有电子地图的问题。
- 部分构建套件可能不支持预编译头,预编译头仅仅是为了加快编译速度,和程序本身无关。比如在win+Qt5.5 5.6就发现不支持,也可能是支持的不够全面,如果编译发生错误可以试着打开pro文件注释掉PRECOMPILED_HEADER = head.h 这行。
- 源码如果在嵌入式linux arm上编译,默认取消了视频监控内核ffmpeg,如果已经交叉编译好了对应arm的ffmpeg库,可以在pro中注释掉这个限制。
contains(QT_ARCH, arm) {
DEFINES -= videoffmpeg
}
- Qt6.2的mingw版本的multimedia模块不可用,msvc版本的正常。
- 推荐用64位的Qt搭配64位的ffmpeg,目前绝大部分系统都是64位的,能获得最大性能提升,本人亲自对比测试32位和64位,64位无论资源占用和操作响应等体验都更优。
0.6.2 注意事项
- 可执行文件在源码同级目录的bin目录下。
- 编译完成后记得将源码下的file目录下(切记是file目录下而不是file目录)的所有文件复制到可执行文件同一目录。
- 如果开启了视频监控(默认开启),则记得将对应的动态库文件复制到可执行文件同一目录。比如采用ffmpeg内核(默认就是ffmpeg)的话,则将下载到的dll_ffmpeg4下的所有文件复制到可执行文件同一目录。
- 各个操作系统的ffmpeg和vlc编译好的动态库以及miniblink的动态库下载地址。
-https://pan.baidu.com/s/13LDRu6mXC6gaADtrGprNVA 提取码: ujm7。
- 如果是64位的qt则对应的dll时候拷贝dll_ffmpeg4_64目录下的。
- 如果使用的ffmpeg3则对应dll目录就是dll_ffmpeg,在ffmpeg.pri文件中可以看到具体启用的是ffmpeg3(支持XP)还是ffmpeg4(不支持XP),默认是ffmpeg4。
- 如果编译运行提示miniblink文件不存在请先拷贝,则说明你当前用的Qt版本没有浏览器模块,要么没安装,要么不支持,你也不用担心啥,此时自动切换用的miniblink浏览器内核,你还需要将ffmpeg库下载的网盘的地方找到dll_miniblink.zip下载解压到可执行文件同一目录即可。
- 图形字体对照表在doc目录下的IconFont.png、Font Awesome Cheatsheet.png,对应图形字体类IconHelper中加载的图形字体,后期如果还有增加的其他图形字体也是放在这里,一个类支持多种图形字体,通过不同的值范围自动设置。
- 如果发现地图打不开,请先确认file目录下的所有文件有没有拷贝过去。
- 如果是用vs+qt可能报错 error LNK2026,解决办法详细见文档中其他说明。
- 默认用户名admin 密码admin。
- 系统配置参数在加载的时候会对节点值进行过滤判断,如果为空会自动用初始值生成新的配置文件,如果不想要显示版权所有公司,可以填xxx而不是删掉整个值。
- 如果是用vlc推流的rtsp地址,比如 rtsp://:8554/aabb,由于vlc推流默认写死的采用的udp协议,所以监控系统也必须在系统设置中通信方式选择udp才行(默认tcp)。
0.6.3 离线地图
- 离线地图可以用网上的瓦片地图下载器下载百度的离线地图放到对应目录即可。
- 也可以直接下载网盘中已经下载好的上海市的离线地图。
- 下载地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取密码:01jf 文件名称:bin_map_tiles.zip
使用说明
- 将压缩包下的两个文件夹复制到对应可执行文件下的config文件夹下,和map.js文件同一级目录。
- tiles文件夹是街道图,tiles_hybrid文件夹是卫星图。
- 默认提供的是上海市徐汇区的瓦片地图,如果自己用万能地图下载器下载的百度地图的瓦片文件,也可以对应替换就行。
- 要注意的是格式,默认是jpg,如果下载的瓦片地图格式是png则需要打开config文件夹下的map_load.js文件,将.jpg改成.png保存即可。
0.7 视频格式
0.7.1 USB摄像头
- 内核ffmpeg写法:video=USB2.0 PC CAMERA(具体要看设备名)。
- 内核vlc写法:dshow://:dshow-vdev=Default (或者填USB2.0 PC CAMERA)
- 带参数写法:2020-12-12以后增加USB摄像头直接url带分辨率帧率写法,默认分辨率640x480。
写法举例
- video=USB2.0 PC CAMERA|1920x1080|30(表示1920*1080分辨率30帧)
- video=USB2.0 PC CAMERA|640x480(表示640*480分辨率)
- dshow://:dshow-vdev=USB2.0 PC CAMERA(表示打开视频设备USB2.0 PC CAMERA、其他参数全部默认)
- dshow://:dshow-vdev=USB2.0 PC CAMERA:dshow-adev=麦克风 (USB Audio Device):dshow-size=1920*1080:live-caching=300(表示打开视频设备USB2.0 PC CAMERA、打开音频设备麦克风 (USB Audio Device)、分辨率640x480、缓存时间300毫秒)
0.7.2 网络地址
- 下面的地址有时候会失效,可以自行网上找找其他的地址,网络视频地址建议在晚上测试会更流畅。
- 大雄兔:rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov
- 大雄兔:http://r.ossrs.net/live/bbb.flv
- 海康萤石:https://hls01open.ys7.com/openlive/6e0b2be040a943489ef0b9bb344b96b8.hd.m3u8
- 在线摄像机:http://vts.simba-cn.com:280/gb28181/21100000001320000002.m3u8
- 摄像机格式:https://blog.csdn.net/qq_38880380/article/details/80652697
0.7.3 中央卫视
- 中央卫视1:rtmp://58.200.131.2:1935/livetv/cctv1
- 中央卫视2:rtmp://58.200.131.2:1935/livetv/cctv2
- 中央卫视3:rtmp://58.200.131.2:1935/livetv/cctv3
- 中央卫视4:rtmp://58.200.131.2:1935/livetv/cctv4
- 中央卫视5:rtmp://58.200.131.2:1935/livetv/cctv5
- 中央卫视6:rtmp://58.200.131.2:1935/livetv/cctv6
- 中央卫视7:rtmp://58.200.131.2:1935/livetv/cctv7
- 中央卫视8:rtmp://58.200.131.2:1935/livetv/cctv8
- 中央卫视9:rtmp://58.200.131.2:1935/livetv/cctv9
- 中央卫视10:rtmp://58.200.131.2:1935/livetv/cctv10
0.7.4 视频文件
- http://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4
- http://vfx.mtime.cn/Video/2019/03/19/mp4/190319212559089721.mp4
- http://vfx.mtime.cn/Video/2019/03/17/mp4/190317150237409904.mp4
- http://vfx.mtime.cn/Video/2019/03/14/mp4/190314223540373995.mp4
0.7.5 网友提供
- rtmp://live.yihtc.com:10935/hls/stream_3
- rtmp://live.yihtc.com:10935/hls/stream_13
- rtmp://218.3.205.46/live/ggpd_sd
- rtmp://hls.hsrtv.cn/hls/hstv2
- rtmp://hls.hsrtv.cn/hls/hstv1
- rtmp://222.173.22.119:1935/live/jnyd_sd
- rtmp://222.173.22.119:1935/live/xwhd_hd
- rtmp://livetv.dhtv.cn:1935/live/peoples
- rtmp://livetv.dhtv.cn:1935/live/citylife
- rtmp://livetv.dhtv.cn:1935/live/financial
- rtmp://livetv.dhtv.cn:1935/live/news
0.8 版本说明
0.8.1 精益求精
0.8.2 破茧成蝶
V20211111
- ONVIF组件增加图片参数范围获取,之前默认0-255,有些设备是0-100 0-128之类的,获取后设置到滑动条范围。
- ONVIF组件增加网络参数设置,比如IP地址,子网掩码、网关地址、DNS设置等。
- ONVIF组件将结构体定义统一移到一个头文件onvifstruct.h,方便后期拓展管理。
- 预置位模块,调用、添加(调用)、删除三种功能,改成了以三个按钮的形式加到每个预置位信息的后面直接单击使用。之前是先选中预置位所在行,然后单击下面的按钮。
V20211101
- 修正开启轮询后关闭所有视频通道不弹出提示信息。
- 所有信息框增加阴影边框区分突出显示,并跟随系统换肤自动更新边框阴影。
- 修正视频轮询分隔符,将|改成;因为如果是竖杠遇到带有参数的url则会出错。
- 将设备图片统一存放到config/device目录,之前在config目录下,随着越来越多非常凌乱。
- 修复之前通过信号执行通道切换,对应文字显示反了的BUG(通道1交换到通道2,新的通道2应该显示之前通道1的文本)。
- 将鼠标按下两个通道交换的处理代码,复用信号槽切换通道的函数。
- 将视频监控布局切换部分单独提取类VideoBox,专门负责管理各种通道布局切换,复用代码并且方便后期拓展,这部分代码和具体的处理无关,一直以来就想要单独提取出来进行管理,后期可以方便的增加其他异形布局以及255通道布局等,很多项目都用到了这个切换逻辑。
- 同时增加了布局切换子菜单比如13画面子菜单切换到52_64通道。
- 修复Qt6中视频控件悬浮条无法显示的BUG,因为Qt6将void enterEvent(QEvent *);改成了void enterEvent(QEnterEvent *);也不打个招呼。这种改变编译也不会提示的。
- 数据库组件修正sqlserver数据库必须设置数据源的不足,改成了dsn字符串形式,不需要新建数据源也能直接通信。
- 数据库组件修正mysql数据库必须存在默认数据库mysql的不足,改成了不需要默认数据库也能正常通信。
- 数据库组件修正没有默认数据库也能在建立连接后新建数据库操作。
- 数据库脚本执行将DROP DATABASE IF EXIST改成了DROP DATABASE ,这样无论什么时候都能先删除原来的数据库然后再新建数据库CREATE DATABASE。有些数据库不支持IF EXIST。
V20211005
- 修正ffmpeg内核,在播放地址不存在的情况下,打开容易卡主引起崩溃的BUG,在打开回调函数中增加对线程停止标志位的判断,一旦在打开的回调中识别到需要停止线程则立即返回结束。
- 增加临时信息中间弹出框提示信息,比如一次性关闭所有通道的时候,界面会卡主的期间提示。
- 增加忙碌鼠标图标切换显示,忙完以后自动恢复鼠标样式。
- 修正ffmpeg内核,开始时间记录可能出现问题的BUG,会导致部分特殊MP4文件打不开。
- 应用程序关闭,增加全局退出信号关联到视频通道管理类,先关闭所有视频通道再彻底退出应用程序。不这样处理的话,发现vlc内核在开启了视频存储的时候,会关不掉程序。
- 修复在没有声音播放的情况下主动调用停止播放造成崩溃的BUG。
- 修复在linux系统上QUIWidget弹出的无边框窗体带系统标题栏的BUG。
- 修复ffmpeg内核关闭视频后opengl窗体来不及隐藏的BUG。
- 修复重复立即刷新打开所有通道,前一次还没执行后一次又来了的BUG,改成了定时器处理,在立即执行前将上一次还没来得及执行的先停止。
- 增加about关于对话框窗体,显示版本号、版权所有、网址、电话等信息。
- 所有弹出窗体都跟随软件主窗体默认居中,这个特性非常棒。
- 所有皮肤增加右键菜单选中图标样式、右键菜单二级子菜单右侧小三角箭头图标样式,单选框、复选框、禁用状态图标全部更新,从图形字体绘制,极其统一舒服。
- 着重对日志类savelog增加了最大行数、最大文件大小等参数设置,可以设置按照行数或者大小来自动分割日志文件。
- 日志类增加了可过滤不同的消息类型,不同消息类型增加消息头。
- 经过大量对比测试发现,使用miniblink浏览器内核,容易卡,说不定什么时候就失效了,问题集中在32位,64位的目前没有发现这个现象,webengine暂时没有这个现象,但是加载打开摄像机的网页配置,还是miniblink更优秀。
- 中文标题栏支持换行,既可以副标题写在英文标题上,也可以同等大小字体写在中文标题上。
V20210922
- 视频控件边框增加0像素选项,这样看起来没有边框,有些场景需要无缝拼接。
- 修复当采用NVR通道作为摄像机视频流显示的时候,ONVIF处理索引越界崩溃的情况,因为一台NVR同一个IP地址对应多个摄像机。
- 所有样式17套皮肤更新边框颜色。
- 系统信息增加对应的编译器名字、位数、版本等。
- 演示demo增加视频叠加演示功能,比如在主视频的左上角、右上角、左下角、右下角在增加一个视频缩略图显示。
- 新增天气预报模块,可设置城市、采集间隔、展示样式等。
- 增加了vlc内核下USB摄像头格式自动纠正,如果采用ffmpeg的格式video=USB2.0 PC CAMERA|1920x1080自动纠正。
- 纠正vlc内核下USB摄像头不自动拉伸的BUG。
- 修正vlc内核动态保存视频文件,文件命名不符合规范,重新按照设定的重命名。
- 修复vlc内核中USB摄像头会当做rtsp视频流的BUG。
- 天气预报模块新增城市显示,新增双击弹出天气预报设置,含打印信息。
- 系统信息,增加秘钥文件的内容,比如允许的设备数量、到期日期等。
- 修复配置文件一旦新增加节点,之前节点全部初始值运行的BUG,应该是存在的节点则读取节点值,不存在的节点以初始值运行。
V20210705
- 改进窗体居中显示算法,可设置参照窗体,默认基于当前屏幕中心,可设置参照主窗体则基于参照窗体,在大分辨率屏幕效果非常好,不然主窗体很小,弹个窗找不到还在很远的地方,还以为没有弹呢。
- 将登陆窗体、登出窗体、用户管理等公用界面,做成了通用库core_form。
- 修复MAC系统上无边框窗体无法最小化的BUG。
- 增加超级管理员密码A具有所有权限的机制,避免管理员误将系统设置权限取消后无法再次进去系统设置的问题。
- 图片参数增加锐度,图片参数设置滑块调节松开立即设置。
- 修复当没有启用图片地图的时候对应界面隐藏的时候保存设备坐标位置报错BUG,因为没有启用的情况下没有设置对应的对象指针。
V20210603
- 将onvif搜索的用户密码,设备播放界面的设备密码等配置参数全部改成了密文存储。
- 大量修改代码,全部支持Qt4-Qt6所有版本。
- 调整onvif代码执行机制,改成了异步执行。
- 云台协议增加了连续移动。
- 增加了预置位相关处理,包括获取预置位、调用预置位、添加预置位、删除预置位。
- 自动巡航按照预置位集合进行,采用定时器去调用预置位队列。
- 增加图文警情行数、窗口信息行数配置,0行表示自动处理。
- 做了大量的代码改进,比如onvif内核换成了QDom对象处理,之前是采用的QXmlQuery查询,由于XmlPatterns这个模块逐渐废弃了,而且在Qt6中不再有,所以彻底移除了XmlPatterns相关的代码,改用其他处理方式实现。
- 增加了预置位和自动巡航处理,其中包括获取预置位集合、调用预置位、添加预置位、删除预置位、设置起始位、调用起始位等。
- ONVIF内核几乎全部重写,将数据改成了结构体,比如设备信息、预置位信息、事件信息等,可以存储更多的数据,拓展也非常灵活。
- onvif处理部分增加了对非onvif设备的过滤,通过判断是否存在onvif地址。这样可以大大加快处理速度,打开视频的时候去实例化onvif通信,关闭视频的时候删除对应的onvif类,这样可以动态响应。
- 所有onvif指令改成了线程处理,处理完成一个立马处理下一个,排队处理。
V20210425
- 配置文件密码改成密文存储。
- 增加了无敌的牛逼的万能的完美入微级自动分页导航控件。
- 日志记录表增加索引,速度提升100倍以上。
- 新增多个设备轨迹 不同颜色+传入经纬度 单独示例。
- 对地图核心类所有覆盖物都增加颜色+粗细+透明度的参数,可动态传入对应值。
- 系统设置增加用户管理模块,可分别设置对应的权限。
- 万能权限管理算法,通过设置不同需要授权的模块名称,对应切换的按钮自动计算。
- 增加了appkey秘钥类,用于校验秘钥是否正确,运行时间等。
V20210403
- 增加全局变量AppData::LastLiveTime,记住程序最后的活动时间-包括键盘+鼠标活动,用于两个判断,一个是超过多久没有操作全屏下隐藏鼠标光标,一个是超过多久没有操作如果没有全屏则自动全屏。
- 增加App::TimeAutoFull配置参数用来判断比较超时自动全屏。
- 重命名为TimeHideCursor表示程序多久未操作自动隐藏光标,TimeAutoFull程序多久未操作自动全屏界面,下拉框选项值增加0,表示不启用此功能。
- 增加信息列表模块frmMsgList,用于图文列表显示信息,对应兄弟类frmMsgTable用于表格显示消息。
- 大改版,将中间部分全部改成了QMainWindow,子模块全部采用停靠窗体,可以悬浮半透明,自动记忆每个模块的最后的位置,启动后自动应用。
- 移除大改版后的所有不需要用的变量和配置参数,重新调整配置参数。
- 增加透明度参数用于停靠窗体独立出来后的透明度。
- 将摄像机控制部分比如云台+控制+预置位+巡航,单独分类到ipc模块,方便管理。
- 限定操作员不能移动停靠窗体等,需要管理员设计好。
- 修复系统设置中工作模式等切换造成的自动重启会弹出退出和登录两个窗体的BUG。
- 修复自动登录用户计算不正确的BUG,要以最后登录的用户为准。
V20210322
- USB摄像头增加参数帧率,第二个参数是分辨率,第三个参数为帧率,不设置则采用默认的帧率,video=USB2.0 PC CAMERA|1920x1080|25。
- 增加独立的demo模块,专门用于测试监控系统中用到的组件和控件,演示如何使用,比如视频图片界面演示从文件夹读取图片绘制到窗体,视频窗体演示系统的核心组件视频控件的设置参数如何使用等。
- 增加了对其他数据库的支持,比如posgres、oracle、odbc、kingbase等数据库,理论上只要支持odbc数据源方式的都支持。
- 增加IndexStart启动窗体索引配置参数,0-主程序 1-演示示例。
V20210305
- 修复数据库有时候没加载到的BUG。
- 新增配置参数控制画面切换的菜单和快捷图标是否显示。
- ffmpeg内核增加了可动态保存机制,点击开始保存按钮启动保存,单击结束则生成视频文件,如此往复。
- 海康内核判断主码流子码流改成了 /101? 和 /main/ 同时判断。
- 新增多屏幕的支持,自动在对应屏幕最大化全屏,对话框位置,右下角提示框等。
- 再次分类存放代码文件,分成core ui class三大类。
- 系统配置更改视频控件参数,统一一个函数设置,initCommonVideoWidget函数中做了过滤,必须关闭状态的视频控件设置才起作用。
- 设备播放模块增加大华NVR的远程回放地址,其他地址计算算法调整。
- 新增界面模块功能启用配置参数。
- 新增主界面顶部导航模块中间界面,用于不同的运行模式加载不同的模块。
0.8.3 快速迭代
V20201212
- 增加USB摄像机分辨率设置,直接url带掉。
- 所有地图内核公用一个,复用代码。
- 增加地图默认级别和中心点坐标设置参数。
- 主界面四个模块独立出来,做成了可配置,这样后期可以任意位置放置自定义模块。
- 四个模块标题栏自定义。
- vlc内核和mpv内核的离线判断,当句柄模式下,统一为getLastTime,当调用该函数的时候自动查询播放状态,如果正在播放则自动更新时间为当前时间。
- 将各种在代码中define定义不同内核的代码全部优化,统一为一个类,很大减少代码量,统一为CommonVideoWidget和CommonVideoManage类。
V20201108
- 轮询点模块增加批量生成功能。
- 录像机、摄像机、轮询点,增加导入导出功能。
- ffmpeg内核增加读取帧回调,超时识别,可以快速识别掉线。
20200828
- 增加了云台控制过滤,没有打开的视频禁用云台。
- linux上全屏BUG修复,采用showfullscreen。
- 增加轮询点管理模块。
- 修正轮询的可能崩溃的BUG。
V20200730
- 系统设置增加了视频上传模块,用来将本地的视频文件传输到服务器,多线程并发。
- 视频监控内核新增MPV内核,修正了其他内核的部分函数和处理。
- 海康内核进行大改动,同时支持视频流和本地MP4文件播放,自动分析切换。
- 海康内核增加回调处理,可以拿到每一张图片。
- 海康内核进行了linux上的实验,可以正常播放。
- ffmpeg内核增加保存到MP4。
- 本地文件回放vlc部分增加进度切换等。
- 悬浮条关闭按钮增加实际处理,之前只是打印消息。
- 改进了vlc和mpv的事件回调机制,使其同时支持qt4+qt5。
V20200620
- 增加了opengl显示实时视频,CPU占用极低。
- 增加了地图上设备点位置的调整。
- 设备点双击弹出实时视频预览。
- 增加GPS运动轨迹显示。
- ffmpeg解码类增加了音频播放,采用的QAudioOutput。
V20191105
- 增加云台控制功能,可以上下左右等八个方位控制云台,默认采用相对移动,云台中间按下表示复位。
- 系统设置增加码流类型选择,默认子码流,切换完自动应用。
- 云台控制增加速度功能,值越大,速度越快。
- 增加焦距控制,可放大缩小,速度也可控制。
1 用户登录退出
1.1 用户登录
+https://pan.baidu.com/s/13LDRu6mXC6gaADtrGprNVA 提取码: ujm7。
如果是64位的qt则对应的dll时候拷贝dll_ffmpeg4_64目录下的。如果使用的ffmpeg3则对应dll目录就是dll_ffmpeg,在ffmpeg.pri文件中可以看到具体启用的是ffmpeg3(支持XP)还是ffmpeg4(不支持XP),默认是ffmpeg4。如果编译运行提示miniblink文件不存在请先拷贝,则说明你当前用的Qt版本没有浏览器模块,要么没安装,要么不支持,你也不用担心啥,此时自动切换用的miniblink浏览器内核,你还需要将ffmpeg库下载的网盘的地方找到dll_miniblink.zip下载解压到可执行文件同一目录即可。系统中所有的图标,都采用的图形字体,对照表在doc目录下的FontAwesome.png、FontAliBaBa.png,对应图形字体类IconHelper中加载的图形字体,后期如果还有增加的其他图形字体也是放在这里,一个类支持多种图形字体,通过不同的值范围自动设置。如果发现地图打不开或者提示秘钥文件丢失,请先确认file目录下的所有文件有没有拷贝过去。如果是用vs+qt可能报错 error LNK2026,解决办法详细见文档中其他说明。默认用户名admin 密码admin。系统配置参数在加载的时候会对节点值进行过滤判断,如果为空会自动用初始值生成新的配置文件,如果不想要显示版权所有公司,可以填xxx而不是删掉整个值。如果是用vlc推流的rtsp地址,比如 rtsp://:8554/aabb,由于vlc推流默认写死的采用的udp协议,所以监控系统也必须在系统设置中通信方式选择udp才行(默认tcp)。0.6.3 离线地图
- 离线地图可以用网上的瓦片地图下载器下载百度的离线地图放到对应目录即可。
- 也可以直接下载网盘中已经下载好的上海市的离线地图。
- 下载地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取密码:01jf 文件名称:bin_map_tiles.zip
使用说明
- 将压缩包下的两个文件夹复制到对应可执行文件下的config文件夹下,和map.js文件同一级目录。
- tiles文件夹是街道图,tiles_hybrid文件夹是卫星图。
- 默认提供的是上海市徐汇区的瓦片地图,如果自己用万能地图下载器下载的百度地图的瓦片文件,也可以对应替换就行。
- 要注意的是格式,默认是jpg,如果下载的瓦片地图格式是png则需要打开config文件夹下的map_load.js文件,将.jpg改成.png保存即可。
0.7 视频格式
0.7.1 USB摄像头
- 内核ffmpeg写法:video=USB2.0 PC CAMERA(具体要看设备名)。
- 内核vlc写法:dshow://:dshow-vdev=Default (或者填USB2.0 PC CAMERA)
- 带参数写法:2020-12-12以后增加USB摄像头直接url带分辨率帧率写法,默认分辨率640x480。
写法举例
- video=USB2.0 PC CAMERA|1920x1080|30(表示1920*1080分辨率30帧)
- video=USB2.0 PC CAMERA|640x480(表示640*480分辨率)
- dshow://:dshow-vdev=USB2.0 PC CAMERA(表示打开视频设备USB2.0 PC CAMERA、其他参数全部默认)
- dshow://:dshow-vdev=USB2.0 PC CAMERA:dshow-adev=麦克风 (USB Audio Device):dshow-size=1920*1080:live-caching=300(表示打开视频设备USB2.0 PC CAMERA、打开音频设备麦克风 (USB Audio Device)、分辨率640x480、缓存时间300毫秒)
0.7.2 网络地址
- 下面的地址有时候会失效,可以自行网上找找其他的地址,网络视频地址建议在晚上测试会更流畅。
- 大雄兔:rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov
- 大雄兔:http://r.ossrs.net/live/bbb.flv
- 海康萤石:https://hls01open.ys7.com/openlive/6e0b2be040a943489ef0b9bb344b96b8.hd.m3u8
- 在线摄像机:http://vts.simba-cn.com:280/gb28181/21100000001320000002.m3u8
- 摄像机格式:https://blog.csdn.net/qq_38880380/article/details/80652697
0.7.3 中央卫视
- 中央卫视1:rtmp://58.200.131.2:1935/livetv/cctv1
- 中央卫视2:rtmp://58.200.131.2:1935/livetv/cctv2
- 中央卫视3:rtmp://58.200.131.2:1935/livetv/cctv3
- 中央卫视4:rtmp://58.200.131.2:1935/livetv/cctv4
- 中央卫视5:rtmp://58.200.131.2:1935/livetv/cctv5
- 中央卫视6:rtmp://58.200.131.2:1935/livetv/cctv6
- 中央卫视7:rtmp://58.200.131.2:1935/livetv/cctv7
- 中央卫视8:rtmp://58.200.131.2:1935/livetv/cctv8
- 中央卫视9:rtmp://58.200.131.2:1935/livetv/cctv9
- 中央卫视10:rtmp://58.200.131.2:1935/livetv/cctv10
0.7.4 视频文件
- http://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4
- http://vfx.mtime.cn/Video/2019/03/19/mp4/190319212559089721.mp4
- http://vfx.mtime.cn/Video/2019/03/17/mp4/190317150237409904.mp4
- http://vfx.mtime.cn/Video/2019/03/14/mp4/190314223540373995.mp4
0.7.5 网友提供
- rtmp://live.yihtc.com:10935/hls/stream_3
- rtmp://live.yihtc.com:10935/hls/stream_13
- rtmp://218.3.205.46/live/ggpd_sd
- rtmp://hls.hsrtv.cn/hls/hstv2
- rtmp://hls.hsrtv.cn/hls/hstv1
- rtmp://222.173.22.119:1935/live/jnyd_sd
- rtmp://222.173.22.119:1935/live/xwhd_hd
- rtmp://livetv.dhtv.cn:1935/live/peoples
- rtmp://livetv.dhtv.cn:1935/live/citylife
- rtmp://livetv.dhtv.cn:1935/live/financial
- rtmp://livetv.dhtv.cn:1935/live/news
0.8 版本说明
0.8.1 精益求精
0.8.2 破茧成蝶
V20220106
- 彻底修复全屏模式+webengine同时存在的情况下鼠标右键菜单无法弹出以及视频可能黑屏的BUG,这是Qt的BUG。
- 同时测试多屏幕下正常状态和全屏状态的情况,多屏幕不同分辨率。
- 增加其他设置界面,将串口设置、网络设置等移动到其他设置。随着功能越来越多,也很有必要单独拆分设置。
V20211220
- 重新梳理整个onvif模块,调整对应的结构,删除多余的变量和设置等,对应云台控制等操作需要指定profile,通过参数传入。
- 对应图片参数操作需要指定videosource,通过参数传入。
- 去除数据库字段mediaurl、ptzurl,因为这两个数据每次都是更新重新获取的,通过getServices获取,这两个字段改成了videosource、profiletoken,用来从数据库读取出来,每次使用的时候自动下发。
- 预置位表格中的按钮样式调整,去掉圆角,增加边距,效果更完美。
- 新增nvr多个通道onvif支持,改动onvif模块代码和数据库结构。
- 搜索设备后判断是否多个videosource,多个表示有多个视频源,一般是NVR,也有部分IPC自带多个视频源。
- 有多个则根据不同厂家不同规则,找出对应的每个通道的videosource、profiletoken、rtspmain、rtspsub用分隔符 | 插入到临时表格中。
- 摄像机管理界面接收到添加设备的时候,在addDevice槽函数中,判断发过来的数据,带了 | 要分别取出来作为通道添加到数据库中。
- 重新定义搜索的摄像机设备命名规则,按照摄像机#ip地址末尾数字的方式。
- 如果是NVR过来的摄像机,增加自动查找NVR的名称插入数据库。
- 获取预置位增加立即清空所有行,之前是先清空内容再根据读取到的预置位个数设置行数。
- 增加双击打开NVR(也叫分组)对应策略 0-最后空白通道 1-从头清空通道。
- 增加双击打开IPC(也叫设备)对应策略 0-最后空白通道 1-最后按下通道。
- 改进在分辨率不同缩放比例保持一致的UI体验,不受缩放比例的影响。
- 修正异或加密,增加对@String开头的密文进行过滤,防止高版本产生的配置文件到低版本的Qt程序不能正确解析的BUG。
- 如果打开视频流出错提示 Server returned 5XX Server Error reply 表示摄像机的码流满了,可能多个地方在拉取码流导致摄像机输出的视频流被占满,已经没有更多资源。
V20211205
- 地图内核增加了海量点接口。
- 路径规划模块彻底重写,支持重新绘制、沿线移动等模式,数据表格显示。
- 设备轨迹模块改成从gps点集合文本文件加载进行循环动态模拟移动,默认飞机图标,以便转动角度。
- 设备播放增加保存视频开关配置参数,可以直接在界面上开启,开启后,通过rtsp从nvr取流比如回放视频,可以将回放的视频保存MP4文件到本地。
- 修正Qt6通过属性设置标签labtip不能居中对齐的BUG。
- 封装通用的设置一堆按钮比如添加、删除、保存、导入、导出等按钮图形字体的函数,直接传入父面板即可,自动查找对应的objname设置图标,省去一堆重复代码。
- 新增飞行轨迹模块frmDeviceGps2,之前的frmDeviceGps作为通过外部函数调用移动。
- 样式统一整理规范,分类6大类:normal、black、light、dark、flat、other。
V20211111
- ONVIF组件增加图片参数范围获取,之前默认0-255,有些设备是0-100 0-128之类的,获取后设置到滑动条范围。
- ONVIF组件增加网络参数设置,比如IP地址,子网掩码、网关地址、DNS设置等。
- ONVIF组件将结构体定义统一移到一个头文件onvifstruct.h,方便后期拓展管理。
- 预置位模块,调用、添加(调用)、删除三种功能,改成了以三个按钮的形式加到每个预置位信息的后面直接单击使用。之前是先选中预置位所在行,然后单击下面的按钮。
- 通道轮询全部移动单独的悬停的模块。
- 视频面板窗体指针改成了全局变量,多处需要引用。
- 修复1通道轮询后,再次启动程序无法正确加载通道面板布局的BUG。
- 修复底部通道切换,部分样式效果悬停时候颜色不正确的BUG。改成了取报警图标颜色和已处理颜色。
- 路径规划模块增加模拟轨迹设备自动旋转角度移动。
- 路径规划模块模拟轨迹增加移动间隔下拉框选择。
- 修复Qt4对应webkit模块不支持返回数组的问题,改成字符串拼接用 ; 符隔开。
- 修复Qt4对应webkit模块不支持路径规划的BUG,因为开启了实时路况属性。
- 路径规划增加绘制实时轨迹线条,不同颜色显示。
V20211101
- 修正开启轮询后关闭所有视频通道不弹出提示信息。
- 所有信息框增加阴影边框区分突出显示,并跟随系统换肤自动更新边框阴影。
- 修正视频轮询分隔符,将|改成;因为如果是竖杠遇到带有参数的url则会出错。
- 将设备图片统一存放到config/device目录,之前在config目录下,随着越来越多非常凌乱。
- 修复之前通过信号执行通道切换,对应文字显示反了的BUG(通道1交换到通道2,新的通道2应该显示之前通道1的文本)。
- 将鼠标按下两个通道交换的处理代码,复用信号槽切换通道的函数。
- 将视频监控布局切换部分单独提取类VideoBox,专门负责管理各种通道布局切换,复用代码并且方便后期拓展,这部分代码和具体的处理无关,一直以来就想要单独提取出来进行管理,后期可以方便的增加其他异形布局以及255通道布局等,很多项目都用到了这个切换逻辑。
- 同时增加了布局切换子菜单比如13画面子菜单切换到52_64通道。
- 修复Qt6中视频控件悬浮条无法显示的BUG,因为Qt6将void enterEvent(QEvent *);改成了void enterEvent(QEnterEvent *);也不打个招呼。这种改变编译也不会提示的。
- 数据库组件修正sqlserver数据库必须设置数据源的不足,改成了dsn字符串形式,不需要新建数据源也能直接通信。
- 数据库组件修正mysql数据库必须存在默认数据库mysql的不足,改成了不需要默认数据库也能正常通信。
- 数据库组件修正没有默认数据库也能在建立连接后新建数据库操作。
- 数据库脚本执行将DROP DATABASE IF EXIST改成了DROP DATABASE ,这样无论什么时候都能先删除原来的数据库然后再新建数据库CREATE DATABASE。有些数据库不支持IF EXIST。
V20211005
- 修正ffmpeg内核,在播放地址不存在的情况下,打开容易卡主引起崩溃的BUG,在打开回调函数中增加对线程停止标志位的判断,一旦在打开的回调中识别到需要停止线程则立即返回结束。
- 增加临时信息中间弹出框提示信息,比如一次性关闭所有通道的时候,界面会卡主的期间提示。
- 增加忙碌鼠标图标切换显示,忙完以后自动恢复鼠标样式。
- 修正ffmpeg内核,开始时间记录可能出现问题的BUG,会导致部分特殊MP4文件打不开。
- 应用程序关闭,增加全局退出信号关联到视频通道管理类,先关闭所有视频通道再彻底退出应用程序。不这样处理的话,发现vlc内核在开启了视频存储的时候,会关不掉程序。
- 修复在没有声音播放的情况下主动调用停止播放造成崩溃的BUG。
- 修复在linux系统上QUIWidget弹出的无边框窗体带系统标题栏的BUG。
- 修复ffmpeg内核关闭视频后opengl窗体来不及隐藏的BUG。
- 修复重复立即刷新打开所有通道,前一次还没执行后一次又来了的BUG,改成了定时器处理,在立即执行前将上一次还没来得及执行的先停止。
- 增加about关于对话框窗体,显示版本号、版权所有、网址、电话等信息。
- 所有弹出窗体都跟随软件主窗体默认居中,这个特性非常棒。
- 所有皮肤增加右键菜单选中图标样式、右键菜单二级子菜单右侧小三角箭头图标样式,单选框、复选框、禁用状态图标全部更新,从图形字体绘制,极其统一舒服。
- 着重对日志类savelog增加了最大行数、最大文件大小等参数设置,可以设置按照行数或者大小来自动分割日志文件。
- 日志类增加了可过滤不同的消息类型,不同消息类型增加消息头。
- 经过大量对比测试发现,使用miniblink浏览器内核,容易卡,说不定什么时候就失效了,问题集中在32位,64位的目前没有发现这个现象,webengine暂时没有这个现象,但是加载打开摄像机的网页配置,还是miniblink更优秀。
- 中文标题栏支持换行,既可以副标题写在英文标题上,也可以同等大小字体写在中文标题上。
V20210922
- 视频控件边框增加0像素选项,这样看起来没有边框,有些场景需要无缝拼接。
- 修复当采用NVR通道作为摄像机视频流显示的时候,ONVIF处理索引越界崩溃的情况,因为一台NVR同一个IP地址对应多个摄像机。
- 所有样式17套皮肤更新边框颜色。
- 系统信息增加对应的编译器名字、位数、版本等。
- 演示demo增加视频叠加演示功能,比如在主视频的左上角、右上角、左下角、右下角在增加一个视频缩略图显示。
- 新增天气预报模块,可设置城市、采集间隔、展示样式等。
- 增加了vlc内核下USB摄像头格式自动纠正,如果采用ffmpeg的格式video=USB2.0 PC CAMERA|1920x1080自动纠正。
- 纠正vlc内核下USB摄像头不自动拉伸的BUG。
- 修正vlc内核动态保存视频文件,文件命名不符合规范,重新按照设定的重命名。
- 修复vlc内核中USB摄像头会当做rtsp视频流的BUG。
- 天气预报模块新增城市显示,新增双击弹出天气预报设置,含打印信息。
- 系统信息,增加秘钥文件的内容,比如允许的设备数量、到期日期等。
- 修复配置文件一旦新增加节点,之前节点全部初始值运行的BUG,应该是存在的节点则读取节点值,不存在的节点以初始值运行。
V20210705
- 改进窗体居中显示算法,可设置参照窗体,默认基于当前屏幕中心,可设置参照主窗体则基于参照窗体,在大分辨率屏幕效果非常好,不然主窗体很小,弹个窗找不到还在很远的地方,还以为没有弹呢。
- 将登陆窗体、登出窗体、用户管理等公用界面,做成了通用库core_form。
- 修复MAC系统上无边框窗体无法最小化的BUG。
- 增加超级管理员密码A具有所有权限的机制,避免管理员误将系统设置权限取消后无法再次进去系统设置的问题。
- 图片参数增加锐度,图片参数设置滑块调节松开立即设置。
- 修复当没有启用图片地图的时候对应界面隐藏的时候保存设备坐标位置报错BUG,因为没有启用的情况下没有设置对应的对象指针。
V20210603
- 将onvif搜索的用户密码,设备播放界面的设备密码等配置参数全部改成了密文存储。
- 大量修改代码,全部支持Qt4-Qt6所有版本。
- 调整onvif代码执行机制,改成了异步执行。
- 云台协议增加了连续移动。
- 增加了预置位相关处理,包括获取预置位、调用预置位、添加预置位、删除预置位。
- 自动巡航按照预置位集合进行,采用定时器去调用预置位队列。
- 增加图文警情行数、窗口信息行数配置,0行表示自动处理。
- 做了大量的代码改进,比如onvif内核换成了QDom对象处理,之前是采用的QXmlQuery查询,由于XmlPatterns这个模块逐渐废弃了,而且在Qt6中不再有,所以彻底移除了XmlPatterns相关的代码,改用其他处理方式实现。
- 增加了预置位和自动巡航处理,其中包括获取预置位集合、调用预置位、添加预置位、删除预置位、设置起始位、调用起始位等。
- ONVIF内核几乎全部重写,将数据改成了结构体,比如设备信息、预置位信息、事件信息等,可以存储更多的数据,拓展也非常灵活。
- onvif处理部分增加了对非onvif设备的过滤,通过判断是否存在onvif地址。这样可以大大加快处理速度,打开视频的时候去实例化onvif通信,关闭视频的时候删除对应的onvif类,这样可以动态响应。
- 所有onvif指令改成了线程处理,处理完成一个立马处理下一个,排队处理。
V20210425
- 配置文件密码改成密文存储。
- 增加了无敌的牛逼的万能的完美入微级自动分页导航控件。
- 日志记录表增加索引,速度提升100倍以上。
- 新增多个设备轨迹 不同颜色+传入经纬度 单独示例。
- 对地图核心类所有覆盖物都增加颜色+粗细+透明度的参数,可动态传入对应值。
- 系统设置增加用户管理模块,可分别设置对应的权限。
- 万能权限管理算法,通过设置不同需要授权的模块名称,对应切换的按钮自动计算。
- 增加了appkey秘钥类,用于校验秘钥是否正确,运行时间等。
V20210403
- 增加全局变量AppData::LastLiveTime,记住程序最后的活动时间-包括键盘+鼠标活动,用于两个判断,一个是超过多久没有操作全屏下隐藏鼠标光标,一个是超过多久没有操作如果没有全屏则自动全屏。
- 增加App::TimeAutoFull配置参数用来判断比较超时自动全屏。
- 重命名为TimeHideCursor表示程序多久未操作自动隐藏光标,TimeAutoFull程序多久未操作自动全屏界面,下拉框选项值增加0,表示不启用此功能。
- 增加信息列表模块frmMsgList,用于图文列表显示信息,对应兄弟类frmMsgTable用于表格显示消息。
- 大改版,将中间部分全部改成了QMainWindow,子模块全部采用停靠窗体,可以悬浮半透明,自动记忆每个模块的最后的位置,启动后自动应用。
- 移除大改版后的所有不需要用的变量和配置参数,重新调整配置参数。
- 增加透明度参数用于停靠窗体独立出来后的透明度。
- 将摄像机控制部分比如云台+控制+预置位+巡航,单独分类到ipc模块,方便管理。
- 限定操作员不能移动停靠窗体等,需要管理员设计好。
- 修复系统设置中工作模式等切换造成的自动重启会弹出退出和登录两个窗体的BUG。
- 修复自动登录用户计算不正确的BUG,要以最后登录的用户为准。
V20210322
- USB摄像头增加参数帧率,第二个参数是分辨率,第三个参数为帧率,不设置则采用默认的帧率,video=USB2.0 PC CAMERA|1920x1080|25。
- 增加独立的demo模块,专门用于测试监控系统中用到的组件和控件,演示如何使用,比如视频图片界面演示从文件夹读取图片绘制到窗体,视频窗体演示系统的核心组件视频控件的设置参数如何使用等。
- 增加了对其他数据库的支持,比如posgres、oracle、odbc、kingbase等数据库,理论上只要支持odbc数据源方式的都支持。
- 增加IndexStart启动窗体索引配置参数,0-主程序 1-演示示例。
V20210305
- 修复数据库有时候没加载到的BUG。
- 新增配置参数控制画面切换的菜单和快捷图标是否显示。
- ffmpeg内核增加了可动态保存机制,点击开始保存按钮启动保存,单击结束则生成视频文件,如此往复。
- 海康内核判断主码流子码流改成了 /101? 和 /main/ 同时判断。
- 新增多屏幕的支持,自动在对应屏幕最大化全屏,对话框位置,右下角提示框等。
- 再次分类存放代码文件,分成core ui class三大类。
- 系统配置更改视频控件参数,统一一个函数设置,initCommonVideoWidget函数中做了过滤,必须关闭状态的视频控件设置才起作用。
- 设备播放模块增加大华NVR的远程回放地址,其他地址计算算法调整。
- 新增界面模块功能启用配置参数。
- 新增主界面顶部导航模块中间界面,用于不同的运行模式加载不同的模块。
0.8.3 快速迭代
V20201212
- 增加USB摄像机分辨率设置,直接url带掉。
- 所有地图内核公用一个,复用代码。
- 增加地图默认级别和中心点坐标设置参数。
- 主界面四个模块独立出来,做成了可配置,这样后期可以任意位置放置自定义模块。
- 四个模块标题栏自定义。
- vlc内核和mpv内核的离线判断,当句柄模式下,统一为getLastTime,当调用该函数的时候自动查询播放状态,如果正在播放则自动更新时间为当前时间。
- 将各种在代码中define定义不同内核的代码全部优化,统一为一个类,很大减少代码量,统一为CommonVideoWidget和CommonVideoManage类。
V20201108
- 轮询点模块增加批量生成功能。
- 录像机、摄像机、轮询点,增加导入导出功能。
- ffmpeg内核增加读取帧回调,超时识别,可以快速识别掉线。
20200828
- 增加了云台控制过滤,没有打开的视频禁用云台。
- linux上全屏BUG修复,采用showfullscreen。
- 增加轮询点管理模块。
- 修正轮询的可能崩溃的BUG。
V20200730
- 系统设置增加了视频上传模块,用来将本地的视频文件传输到服务器,多线程并发。
- 视频监控内核新增MPV内核,修正了其他内核的部分函数和处理。
- 海康内核进行大改动,同时支持视频流和本地MP4文件播放,自动分析切换。
- 海康内核增加回调处理,可以拿到每一张图片。
- 海康内核进行了linux上的实验,可以正常播放。
- ffmpeg内核增加保存到MP4。
- 本地文件回放vlc部分增加进度切换等。
- 悬浮条关闭按钮增加实际处理,之前只是打印消息。
- 改进了vlc和mpv的事件回调机制,使其同时支持qt4+qt5。
V20200620
- 增加了opengl显示实时视频,CPU占用极低。
- 增加了地图上设备点位置的调整。
- 设备点双击弹出实时视频预览。
- 增加GPS运动轨迹显示。
- ffmpeg解码类增加了音频播放,采用的QAudioOutput。
V20191105
- 增加云台控制功能,可以上下左右等八个方位控制云台,默认采用相对移动,云台中间按下表示复位。
- 系统设置增加码流类型选择,默认子码流,切换完自动应用。
- 云台控制增加速度功能,值越大,速度越快。
- 增加焦距控制,可放大缩小,速度也可控制。
1 用户登录退出
1.1 用户登录
系统默认开启了自动登录,可以在系统设置中将自动登录按钮关闭即可,可以在用户登录界面勾选记住密码和自动登录复选框,如果勾选了记住密码,则下次弹出的登录窗体会自动把最后一次的密码填进去,如果勾选了自动登录,则直接以上一次的用户登录到系统。
1.2 用户退出
如果开启了自动登录机制,在单击右上角的关闭按钮,会弹出用户退出窗体,需要输入密码才能退出,也可以在代码中屏蔽掉自动登录的判断,这样任何时候关闭系统都会弹出窗体要求输入密码来退出。用户登录和退出内置了超级密码 a ,在记不住密码或者密码丢失的时候使用。
2 主界面操作
@@ -688,7 +609,7 @@ header, .context-menu, .megamenu-content, footer{
左侧和右侧的面板,可以通过单击面板右上角的关闭按钮来隐藏,当隐藏一个面板以后,剩余的面板会自动填充布局,如果需要重新显示面板,则在标题栏鼠标右键就可以对小面板进行显示和隐藏,右上角的时间和CPU显示面板可以在系统设置中控制显示隐藏。系统会自动记住最后的布局比如显示的面板和宽高占比,下次启动后自动应用。
特别说明
- 在停靠窗体的标题栏鼠标右键也会弹出子窗体的开启菜单,复选框勾选表示显示,悬浮的窗体没有这个特性,一定要是嵌入在主界面中的子窗体标题栏才有。
- 如果是全屏模式,由于没有了标题栏,想要关闭模块的话,需要将其拖动到边缘嵌入主窗体,然后在标题栏鼠标右键菜单中关闭即可。
2.2 面板拖动
面板和面板之间有个分隔条,鼠标移到对应分隔条的地方,会变成可拉动的鼠标指针,此时可以上下左右拉动调整宽高,调整好以后会自动保存宽高比例,下次启动后自动应用最后的配置来显示。
2.3 视频播放
-视频播放同时支持多种方式:
- 双击子节点播放单个摄像机,在当前选中通道处播放。
- 双击父节点播放整个录像机的摄像机,依次排列。
- 按住子节点拖曳到对应通道,播放摄像机。
- 本地文件直接拖曳到通道,自动播放本地文件。
- 启动后自动播放最后通道的视频信息。
2.4 视频截图
+视频播放同时支持多种方式:
- 双击子节点播放单个摄像机,在当前选中通道处播放。
- 双击父节点播放整个录像机的摄像机,依次排列。
- 按住子节点拖曳到对应通道,播放摄像机。
- 本地文件直接拖曳到通道,自动播放本地文件。
- 启动后自动播放最后通道的视频信息。
- 代码接口提供指定通道播放url。
- 代码接口提供指定两个通道交换,比如报警的时候将某个通道移到最前面显示。
2.4 视频截图
在视频监控主界面,通道鼠标右键,会弹出右键菜单,选择截图当前视频或者截图所有视频,截图默认保存在可执行文件所在目录下的snap目录。视频面板底部工具栏也有截图按钮触发这个动作。
文件名格式:Ch1_2020-07-30-13-41-24.png。
2.5 删除视频
有多种方法可以删除视频:
- 鼠标右键删除当前视频。
- 鼠标右键删除所有视频。
- 按住通道画面移出视频监控画面。
- 悬浮条关闭按钮。
2.6 画面切换
@@ -726,7 +647,7 @@ header, .context-menu, .megamenu-content, footer{
设备日志是指直接通过sdk协议,远程从NVR设备上拉取日志记录到本地显示,其余功能和本地日志一致,此功能未实现。
6 系统设置
6.1 系统设置
系统设置主界面如下图:
6.1.1 基本设置
基本设置中有部分参数的切换会自动重启应用。
-参数说明
- 开机运行:开启以后自动随着系统启动运行,默认开启。
- 自动登录:开启以后会自动以最后登录的用户信息登录到系统,默认关闭。
- 记住密码:开启以后会自动填入最后登录的用户信息到登录窗体,默认关闭。
- 中文标题:软件左上角标题栏的中文标题,改动立即应用。
- 英文标题:软件左上角标题栏的英文标题,改动立即应用。
- 版权所有:当前软件版权所有的公司,目前没有显示在哪里,备用。
- 全屏模式:开启以后,最大化显示自动全屏显示而不是最大化显示,默认关闭。
- 全屏适应:开启了以后会自动采用上移一个像素的办法解决opengl的BUG。
- 软件图标:自动从logo文件夹读取,可以自行选择对应的logo文件。
- 界面样式:系统自带17套皮肤,可以在这里自动换肤,默认视频黑。
- 工作模式:默认视频监控,可选机器人监控、无人机监控等。
- 导航样式:用于选择顶部导航栏和左侧导航栏的样式,上侧+左侧表示顶部导航栏上侧样式(图标在上面,文字在下面),左侧导航栏左侧样式(图标在左侧,文字在右侧)。
- 弹框时间:右下角弹出提示信息自动关闭时间,0秒表示常驻不关闭。
- 报警声音:0表示不启用,其余表示报警后播放的声音次数。
- 鼠标隐藏:主界面多久鼠标没有操作过会自动隐藏鼠标指针,一般在全屏轮询的时候需要设置,效果会更好。
- 自动全屏:经过多久以后鼠标没有操作过自动全屏,0表示不启用。
- 备用开关:后面做其他功能使用。
- 图文警情:图文警情模块消息行数,0表示自动计算填满,不产生滚动条。
- 窗口消息:窗口消息模块消息行数,0表示自动计算填满,不产生滚动条。
- 透明度值:停靠窗体的透明度值,可调节,动态应用。
6.1.2 视频参数
+参数说明
- 开机运行:开启以后自动随着系统启动运行,默认开启。
- 自动登录:开启以后会自动以最后登录的用户信息登录到系统,默认关闭。
- 记住密码:开启以后会自动填入最后登录的用户信息到登录窗体,默认关闭。
- 中文标题:软件左上角标题栏的中文标题,改动立即应用。
- 英文标题:软件左上角标题栏的英文标题,改动立即应用。
- 版权所有:当前软件版权所有的公司,目前没有显示在哪里,备用。
- 全屏模式:开启以后,最大化显示自动全屏显示而不是最大化显示,默认关闭。
- 全屏适应:开启了以后会自动采用上移一个像素的办法解决opengl的BUG。20220106已移除这个开关。
- 软件图标:自动从logo文件夹读取,可以自行选择对应的logo文件。
- 界面样式:系统自带17套皮肤,可以在这里自动换肤,默认视频黑。
- 工作模式:默认视频监控,可选机器人监控、无人机监控等。
- 导航样式:用于选择顶部导航栏和左侧导航栏的样式,上侧+左侧表示顶部导航栏上侧样式(图标在上面,文字在下面),左侧导航栏左侧样式(图标在左侧,文字在右侧)。
- 弹框时间:右下角弹出提示信息自动关闭时间,0秒表示常驻不关闭。
- 报警声音:0表示不启用,其余表示报警后播放的声音次数。
- 鼠标隐藏:主界面多久鼠标没有操作过会自动隐藏鼠标指针,一般在全屏轮询的时候需要设置,效果会更好。
- 自动全屏:经过多久以后鼠标没有操作过自动全屏,0表示不启用。
- 备用开关:后面做其他功能使用。
- 图文警情:图文警情模块消息行数,0表示自动计算填满,不产生滚动条。
- 窗口消息:窗口消息模块消息行数,0表示自动计算填满,不产生滚动条。
- 透明度值:停靠窗体的透明度值,可调节,动态应用。
6.1.2 视频参数
参数说明
- 保存视频:开启以后打开视频自动存储录像文件,目录在可执行文件video_normal。
- 存储间隔:录像文件按照什么规则存储视频,0分钟表示只存储到单个文件。
- 视频边框:视频控件的边框的宽度,值越大边框越粗。
- 报警视频:开启以后保存报警视频到可执行文件video_alarm,暂未启用。
- 硬件加速:当前视频内核采用何种硬件加速方式,默认none表示不启用硬件加速(常用的所有qsv、dxva2、d3d11va,建议用dxva2或者d3d11va,具体根据电脑是否支持定)。
- 通信方式:视频流采用何种通信方式,默认TCP(可靠连接,不会丢包,缺点就是慢),可选UDP(不可靠连接,容易丢包,但是速度快)。
- 视频回调:是否采用回调的形式来解码显示视频,比如vlc内核和海康内核都支持回调。
- 码流类型:双击摄像机以什么码流地址加载实时视频,默认子码流。
- 解码方式:ffmpeg内核有用,可选速度优先、质量优先、均衡处理。
- 播放音频:开启以后可以播放声音,有时候不需要声音的时候可以关闭,节省资源。
- 图片拉伸:默认开启,通道画面按照填充拉伸显示,不开启的话则按照等比例缩放。
- 打开间隔:软件启动后挨个加载打开视频的间隔,默认1秒钟。
- 重连间隔:软件多久检测一次摄像机是否掉线,默认10秒钟。
- 事件订阅:开启以后会用onvif的机制订阅报警事件。
- 自动校时:开启后摄像机上线立即同步本地时间到摄像机。
6.1.3 数据库设置
参数说明
- 默认提供了视频监控系统的数据库脚本文件(拓展名sql结尾的文件)。
- 单击初始化数据按钮可以对整个数据库进行新建和重置,相当于恢复出厂。
- 系统支持多种数据库,默认sqlite(Qt内置的数据库,无需安装),可选mysql、postgresql、oracle、人大金仓等。
- 具体还需要对应Qt版本有数据库插件支持,没有插件支持可以自行编译对应缺失的插件比如mysql,也可选直接通过万能的ODBC来连接。
- 除了sqlite数据库外,其余数据库都需要输入数据库名称、主机地址、通信端口、用户名称、用户密码信息,输入好以后可以单击连接测试按钮测试下是否正常。
- 默认提供的是mysql的动态库libmysql.dll,需要放到可执行文件同一目录,严格区分32位和64位的动态库。
6.1.4 地图配置
参数说明
- 地图秘钥:对应百度地图的秘钥,默认内置的作者的秘钥,很多软件系统都用的这个秘钥,用户数较多,可能有并发限制,为了不影响体验,强烈建议改成自己的,可以自行去官网申请,免费。
- 地图中心:默认地图的中心点坐标。
- 地图级别:默认地图打开以后的缩放级别。
6.1.5 功能激活
@@ -798,7 +719,7 @@ header, .context-menu, .megamenu-content, footer{
这里放的全部是个人一直持续更新完善的独创的轮子,所有的项目都公用这些轮子,用到哪个就包含哪个进来,更新只需要更新轮子代码就行。
视频监控系统包含的轮子超级丰富给力,物超所值,涵盖了数据导出模块、数据库应用、视频监控、ONVIF通信、TCP文件传输、地图应用、通用浏览器内核等。
名称 | 说明 |
---|
core_control | 通用自定义控件,很多系统经常用到的控件全部放在这里。 |
core_dataout | 数据导入导出到xls/pdf和打印类库,极速、跨平台、无依赖。 |
core_db | 数据库通用类库比如数据库线程管理、数据清理、数据采集等。 |
core_ffmpeg | 视频监控内核ffmpeg版本,本系统默认采用的内核。 |
core_vlc | 视频监控内核vlc版本,本系统自带该内核。 |
core_mpv | 视频监控内核mpv版本,需要额外购买,不在视频监控系统中。 |
core_haikang | 视频监控内核海康sdk版本,需要额外购买,不在视频监控系统中。 |
core_map | 地图综合应用类库,百度地图(支持在线离线)和echart封装类等。 |
core_onvif | onvif功能封装类,包括设备搜索、云台控制、设备参数设置等。 |
core_opengl | opengl封装类,支持打开yuv/nv12文件,绘制yuv/nv12帧数据,一般搭配ffmpeg视频内核视频,直接走GPU绘制。 |
core_qui | 通用的辅助类,包括自定义对话框,全局辅助函数,图形字体等。 |
core_tcpfile | 文件多线程收发类,支持多个并发。 |
core_video | 通用的视频监控管理类,封装了通用的视频控件和多通道统一管理。 |
core_webview | 通用浏览器控件类,同时支持webkit、wenengine、miniblink三种内核,打通了所有的Qt版本。 |
11.3.3.1 模块-core_control
名称 | 说明 |
---|
bottomwidget | 通用底部状态栏控件,可以设置软件名称、版本号、运行时间等。 |
colorcombobox | 颜色下拉框控件,在系统设置中有。 |
cpumemorylabel | CPU和内存使用情况标签控件,主界面右上角显示。 |
customtitlebar | 停靠窗体自定义标题栏控件。 |
devicebutton | 设备按钮控件,比如图片地图模块中用到,可设置不同的图标样式和状态等,双击发出信号进行相应处理比如弹出对应视频预览等。 |
framelesswidget | 无边框窗体管理类,无边框拖动+拉伸,主界面就用到了这个类。 |
lcddatetime | 软件右上角显示时间的控件。 |
panelwidget | 面板容器控件,主界面子模块表格消息,就用到此控件,用于将一堆widget放到此容器进行管理,自动形成滚动条等。 |
switchbutton | 开关按钮控件,在系统设置中存在大量该控件。 |
xslider | 滑动条控件,在原有滑动条基础上增加了鼠标按下立即定位等。 |
11.3.3.2 模块-core_dataout
名称 | 说明 |
---|
datacreat | 通用数据报表内容创建类,比如生成表格格式的html内容,然后赋值给dataprint直接打印,里面举例了图文混排的报告内容,后期会不断增加其他模板,也可以自行增加其他模板数据。 |
datacsv | 导入导出数据,csv格式,可设置分隔符。拓展名。过滤条件等。 |
datahead | 当前组件通用头文件。 |
datahelper | 辅助类,比如校验规则函数,通用数据导出+打印函数。 |
dataprint | 数据打印到pdf及纸张,支持多线程。 |
dataxls | 数据导出到xls类,支持多线程导出。 |
11.3.3.3 模块-core_db
名称 | 说明 |
---|
dbcleanthread | 自动清理数据线程类。 |
dbconnthread | 数据库通信管理线程类。 |
dbdelegate | 自定义委托全家桶,包括复选框、下拉框、密码框、按钮等。 |
dbhead | 当前组件通用头文件。 |
dbhelper | 各种数据库应用函数封装,比如初始化数据库、执行sql语句等。 |
dbhttpthread | 网络请求数据采集类。 |
dbpage | 数据库通用翻页类。 |
dbpagemodel | 数据库翻页类数据模型。 |
navpage | 分页导航控件。 |
11.3.3.4 模块-core_ffmpeg
名称 | 说明 |
---|
ffmpegconvert | 各种转换处理函数封装。 |
ffmpeghead | 当前组件通用头文件。 |
ffmpeghelper | 辅助类,包括版本号,校验url地址、获取流索引等。 |
ffmpegsync | 音视频同步类,包括了同步以及发出当前播放进度信号。 |
ffmpegthread | 核心解码类,主要代码都在这,包括音视频的解码。 |
ffmpegtool | 工具类,用于执行ffmpeg的命令获取结果。 |
ffmpegwidget | 视频显示窗体类,解码后到这里显示,依赖ffmpegthread。 |
videoffmpeg | 多通道管理类。 |
11.3.3.5 模块-core_map
名称 | 说明 |
---|
echartjs | echart模块中用到的json文件转js文件,获取js文件中的名字和经纬度等处理。 |
echarts | echart封装类,可加载仪表盘、闪烁点图、迁徙图、世界地图、区域地图等,每个点可自定义颜色和提示信息等。 |
mapbaidu | 百度地图封装类,支持在线和离线两种模式。 |
11.3.3.6 模块-core_onvif
名称 | 说明 |
---|
onvifbase | 基础类,用于获取设备信息、服务文件地址、能力文件地址、媒体文件地址、视频流地址等。 |
onvifdevice | 设备类,核心处理及管理,包括设置用户信息请求onvif地址、获取设备信息、云台控制、事件订阅、抓拍图片等。 |
onvifevent | 事件订阅具体实现类,可设置请求超时时间等。 |
onvifhead | 当前组件通用头文件。 |
onvifhelper | 辅助类,比如获取UUID用于请求、判断IP合法、获取本机IP地址集合、管理系统中所有onvif设备对象等。 |
onvifmedia | 获取媒体文件具体解析类。 |
onvifother | 其他处理类,比如系统重启、NTP校时、获取和设置网络信息、获取和设备时间、获取和设置图片参数等。 |
onvifptz | 云台控制实现类,包括绝对移动、相对移动等。 |
onvifquery | 数据查询类,用于将接收到的xml数据解析,并赋值字符串比如命名空间、设备地址、媒体地址、事件地址等。 |
onvifrequest | 网络请求类,包括设置用户信息、获取用户token数据、获取xml头部数据等,通用的请求数据返回结果函数。 |
onvifsearch | 设备搜索类,支持广播搜索、指定地址搜索,可获取设备信息集合、获取设备地址集合。 |
onvifservices | 服务类,用于获取媒体地址、云台地址等。 |
onvifsnap | 图片抓拍实现类,包括获取抓图地址、抓拍图片等。 |
11.3.3.7 模块-core_opengl
名称 | 说明 |
---|
openglhead | 当前组件通用头文件。 |
nv12glwidget | 继承自QGLWidget的NV12格式OPENGL绘制窗体。 |
nv12openglwidget | 继承自QOpenGLWidget的NV12格式OPENGL绘制窗体。 |
yuvglwidget | 继承自QGLWidget的YUV格式OPENGL绘制窗体。 |
yuvopenglwidget | 继承自QOpenGLWidget的YUV格式OPENGL绘制窗体。 |
11.3.3.8 模块-core_qui
名称 | 说明 |
---|
iconfont | 图形字体类,对应阿里巴巴的图形字体文件,系统中大量运用,将字体中的值转成图片显示。 |
iconhelper | 图形字体类,对应国际开源的fontawesome图形字体。 |
quiconfig | 存储当前组件的配置参数信息,比如全局的字体名称、字号、无边框窗体的最小化最大化关闭等图标、样式表的颜色值。 |
quidateselect | 自定义日期范围选择对话框。 |
quihead | 当前组件通用头文件。 |
quihelper | 项目通用辅助类,各种常用函数的封装,比如获取当前屏幕分辨率、设置字体、设置编码、加载翻译文件、各种进制数据转换、弹出各种对话框、设置延时时间等。 |
quiinputbox | 自定义输入框窗体,可指定不同的输入类型比如文本框、下拉框等。 |
quimessagebox | 自定义信息消息框窗体,可设置关闭倒计时,不同的类型比如信息框、询问框、错误框等。 |
quistyle | 当前组件通用样式设置管理类,可以指定枚举类型样式、传入样式内容设置、获取样式表文件对应的颜色值等。当前组件样式相关的处理函数都放在这里,统一管理。 |
quitipbox | 自定义右下角信息对话框,可设置对齐方式、关闭倒计时等。 |
quiwidget | 自定义无边框窗体,可设置标题,各种图标等。 |
11.3.3.9 模块-core_tcpfile
名称 | 说明 |
---|
tcpfilehead | 当前组件通用头文件。 |
tcpfilehelper | 辅助类,包括将字节转为MB单位、初始化表格控件、生成表格行、数据加密解密、解压文件、重启系统等。 |
tcpreceivefileserver | 接收文件服务类,管理多个接收文件线程,支持监听端口被动接收文件和主动连接服务器接收文件。 |
tcpreceivefilethread | 接收文件线程类,根据发送的文件名、包编号、块大小、挨个接收数据最终形成文件,可设置保存文件夹等。 |
tcpsearchfileserver | 搜索文件服务类,目前没用,用于接收请求搜索文件是否存在。 |
tcpsendfilethread | 发送文件线程类,按照 文件开始符+文件大小+文件内容+文件结束符 逐个分包发送,可对文件的每个包进行加密传输。 |
11.3.3.10 模块-core_video
名称 | 说明 |
---|
commonvideomanage | 通用视频管理类,比如定时器排队打开视频、排队重连视频,可设置超时时间、打开间隔、重连间隔等。 |
commonvideowidget | 通用视频控件类,视频监控系统支持多种内核,每种内核对应的视频控件接口一样,根据预定义关键字识别具体的视频控件类,搞个通用的视频控件类,就不用每个用到该控件的代码文件去挨个判断预定义变量生成对应的视频控件,很大减少重复冗余代码量。 |
11.3.3.11 模块-core_webview
名称 | 说明 |
---|
webcore.pri | 通用的根据不同的Qt版本、不同的编译器环境、不同的操作系统,加载对应的浏览器内核模块和定义不同的变量。 |
miniblink | miniblink封装处理类。 |
webhelper | 经纬度转换、获取小数点经纬度值等常用处理函数。 |
webjsdata | 通用的浏览器控件和Qt程序交互数据中转类。 |
webview | 通用浏览器控件,支持webkit、webengine、miniblink。 |
11.3.4 界面UI
这里分门别类存放的各种功能集合的界面类,每个类都一个ui文件、一个h头文件、一个cpp实现文件,方便快速查找对应功能的界面,也方便拓展增加界面。
- 不仅分文件夹存放的,而且命名也尽量按照对应功能打头,比如系统设置模块中的都用frmconfig打头,外层文件夹是整齐的,内部代码也是整齐的。
名称 | 说明 |
---|
frmconfig | 系统设置模块,包括基本设置、录像机管理、摄像机管理、轮询管理、用户管理、视频上传等。 |
frmdata | 日志查询模块,包括本地日志、设备日志等。 |
frmdemo | 演示demo示例,用于演示具体控件或者功能的使用,方便学习参考,比如视频图片、视频控件、视频存储都单独的使用demo。 |
frmipc | 存放摄像机处理相关的模块,比如设备控制,云台控制、预置位、巡航设置等。之前放在frmmodule模块中,后面独立出来管理更方便。 |
frmmain | 主界面模块,包括登录登出界面、主界面、右上角时间组件、欢迎组件等。 |
frmmap | 地图模块,包括通用地图内核界面、图片地图、在线地图、离线地图、路径规划等。 |
frmmodule | 停靠子窗体模块,包括停靠窗体管理核心类、设备列表、窗口信息、图文警情、设备轨迹、网页浏览等模块。将摄像机、机器人、无人机相关的模块放到了对应的模块文件夹,这里放的是系统通用的模块。 |
frmrobot | 无人机模块,包括图像增强、飞行监控等模块。 |
frmuavs | 无人机模块,包括图像增强、飞行监控等模块。 |
frmvideo | 视频监控模块,所有视频监控相关的都放在这里,包括主界面的视频监控布局窗体、视频回放、远程回放、图片回放等。 |
11.3.4.1 模块-frmconfig
名称 | 说明 |
---|
frmconfig | 系统设置模块主界面,采用堆栈窗体形式,加载多个子界面比如摄像机管理、轮询管理等。 |
frmconfigdb | 数据库设置,独立出来,很多系统通用。 |
frmconfigipc | 摄像机管理,可以增加、删除、修改、清空、导入、导出、打印摄像机信息。 |
frmconfigipcsearch | onvif设备搜索,独立出来的窗体,可以搜索局域网内的所有onvif摄像机信息,搜索完以后获取摄像机的视频流地址等,最后可以单个添加或者批量选中添加到摄像机信息表格中。 |
frmconfignvr | 录像机管理,可以增加、删除、修改、清空、导入、导出、打印录像机信息。 |
frmconfigpoll | 轮询管理,可以增加、删除、修改、清空、导入、导出、打印轮询点信息。可以按照设定规则批量生成轮询点信息。 |
frmconfigpollplus | 将轮询管理中的轮询参数配置、分组管理、批量添加等独立出来的界面,方便管理和拓展。 |
frmconfigsave | 录像计划,目前空的,等想好了怎么设计好在实现。 |
frmconfigsystem | 系统设置,包括基本设置、视频参数、数据库设置、地图配置、功能激活、颜色配置、串口配置、网络配置等。 |
frmconfiguser | 用户管理,可以增加、删除、修改、清空、导入、导出、打印用户信息。每个用户可以勾选不同的模块权限。 |
11.3.4.2 模块-frmdata
名称 | 说明 |
---|
frmdata | 日志查询模块主界面,采用堆栈窗体形式,加载多个子界面包括本地日志、设备日志等。 |
frmdatadevice | 设备日志,通过私有协议从NVR取对应设备日志信息。 |
frmdatauser | 本地地址,用户操作的日志信息,可查询和导出打印数据记录。 |
11.3.4.3 模块-frmdemo
名称 | 说明 |
---|
frmdemo | 单独的功能演示示例主窗体,加载多个子界面比如视频控件等。 |
frmdemovideoimage | 视频图片示例,从图片文件夹读取图片集合,定时器绘制取出图片发给视频控件绘制。 |
frmdemovideosave | 视频保存示例,演示如何对视频控件进行视频保存,可动态保存。 |
frmdemovideowidget | 视频控件示例,演示视频控件如何使用。 |
11.3.4.4 模块-frmipc
名称 | 说明 |
---|
frmipccontrol | 设备控制模块,可对选中设备进行图片参数调节、NTP校时、设备重启、抓拍图片(ONVIF抓图)等。 |
frmipcnavigate | 巡航管理模块,暂未实现,后期完善。 |
frmipcreset | 预置位管理模块,暂未实现,后期完善。 |
frmipcptz | 云台控制模块,可对选中的摄像机进行云台控制。 |
11.3.4.5 模块-frmmain
名称 | 说明 |
---|
frmlogin | 用户登录界面,三次错误关闭,下拉可选用户,内置超级密码。 |
frmlogout | 用户退出界面,三次错误关闭,下拉可选用户,内置超级密码。 |
frmmain | 系统主界面,采用堆栈窗体,加载各个子模块。 |
frmmain1 | 备用模块1界面,根据参数设置决定是否启用。 |
frmtimecpu | 右上角日期时间+CPU内存显示。 |
frmwelcome | 右上角欢迎信息界面。 |
11.3.4.6 模块-frmmap
名称 | 说明 |
---|
frmmap | 地图管理主界面,采用堆栈窗体形式,加载各个子界面比如图片地图、在线地图、离线地图、路径规划等。 |
frmmapcore | 通用百度地图内核界面,用来加载百度地图,可设置在线、离线模式,有很多个窗体用到类似功能特意封装到一个类,重复利用,比如悬浮地图、飞行轨迹、路径规划等模块都用到了此内核。 |
frmmapdevice | 通用的设备地图界面,在线地图和离线地图界面公用这个界面,唯一区别就是设置下地图的模式是在线还是离线。 |
frmmapimage | 图片地图界面,设备作为一个个按钮点显示在对应地图上,可以拖动,双击弹出预览实时视频。 |
frmmaplocal | 离线地图界面,可更新经纬度值、模拟运动轨迹等。 |
frmmapweb | 在线地图界面,可更新经纬度值、模拟运动轨迹等。 |
frmmaproute | 路径规划界面,可查询路线得到路线的经纬度坐标集合。 |
11.3.4.7 模块-frmmodule
名称 | 说明 |
---|
frmdevicegps | 设备轨迹模块,对设定的设备随机模拟轨迹,也可传入经纬度坐标值自动移动并绘制轨迹线条,不同设备可以不同颜色。 |
frmdevicetree | 设备列表模块,读取设备信息加载形成树状列表,双击或者拖动到视频监控窗体直接播放视频,提供右键菜单作为演示如何使用。 |
frmmodule | 主界面中心部分窗体,采用QMainWindow类,中间加载的视频监控面板,其余new出来每个子模块,子模块可停靠和悬浮拖动等。不同工作模式下的各种子模块都在此加载。同时负责管理模块的显示隐藏菜单。 |
frmmsglist | 图文警情模块,也叫消息列表模块,带有右键菜单添加、删除、清空列表中的消息,双击可以弹出大图预览。 |
frmmsglistitem | 图文警情模块子类,都是由一个个item组成放到panelwidget面板控件中,自动形成滚动条。 |
frmmsgtable | 窗口消息模块,也叫表格消息模块,表格形式显示打印信息,不同的内容可以不同颜色区分。 |
frmwebview | 网页浏览模块,传入一个url地址打开对应的网页,比如打开一个3D的网页。 |
11.3.4.8 模块-frmrobot
名称 | 说明 |
---|
frmrobotdata | 仿真数据模块,启动机器人通信服务,接收数据解析显示。 |
frmrobotdebug | 数据调试模块,可模拟发送轨迹数据测试解析类。 |
frmrobotdebug2 | 新数据调试模块,打印多个串口数据,不同颜色显示。 |
frmrobotemulate | 运动仿真模块,预留给用户实现,一般放个3D效果。 |
frmrobotlog | 机器人实时数据模块,预留给用户实现。 |
11.3.4.9 模块-frmuavs
名称 | 说明 |
---|
frmuavsflight | 飞行套件控件面板,放了多个飞行仪表,默认自动模拟数据,可以传入对应数据显示。 |
frmuavsimage | 图像增强模块,预留给用户实现。 |
frmuavspanel | 飞行监控面板。 |
11.3.4.10 模块-frmvideo
名称 | 说明 |
---|
frmvideo | 视频回放模块主界面,堆栈窗体形式,加载多个子界面比如本地回放、远程回放、设备播放等。 |
frmvideopanel | 视频监控面板,主界面中间部分,这是核心,管理多个通道,通道可移除删除,拖曳打开,拖曳交换等。 |
frmvideopaneltool | 视频监控底部工具栏,独立出来一个类专门管理。 |
frmvideoplayimage | 图片回放模块,按照规则查询图片目录,然后可设定播放速度进行图片序列播放。 |
frmvideoplaylocal | 本地回放模块,查询对应通道的本地存储的视频文件,双击播放,可暂停和拖动进度条位置。 |
frmvideoplaynvr | 远程回放模块,需要用厂家sdk去实现,从NVR回放录像。 |
frmvideoplayweb | 设备播放模块,通过RTSP视频流的形式从远程设备取视频进行播放,支持摄像机和录像机,手动填入地址也行。 |
frmvideopreview | 视频预览窗体,比如图片或者地图上双击设备弹出的视频预览,可以多个,关闭的时候自动释放资源。 |
frmvideoupload | 视频上传,将本地存储的视频文件上传到服务器。 |
12 二次开发说明
12.1 开发环境搭建
12.1.1 常规通用步骤
- 第一步:安装系统,推荐用vmware虚拟机。
- 第二步:安装qt环境,可以直接用官方下载的run安装包安装,有些要求用命令行安装。
- 第三步:写个空白窗体程序测试下是否环境正常。
- 第四步:编译ffmpeg,生成对应的动态库或者静态库。
- 第五步:打开video_system.pro项目进行编译。
- 第六步:打包发布,为了发布方便,推荐用静态编译的Qt+静态编译的ffmpeg,这样打包发布很清爽,就一个可执行文件。
12.1.2 windows+mingw
12.1.3 windows+msvc
12.1.4 linux+ubuntu
12.1.5 linux+deepin
12.1.6 linux+centeros
12.1.7 linux+uos
12.1.8 linux+银河麒麟
12.2 通用模块使用
12.3 人工智能集成
13 其他说明
13.1 海康onvif设置
+ 不仅分文件夹存放的,而且命名也尽量按照对应功能打头,比如系统设置模块中的都用frmconfig打头,外层文件夹是整齐的,内部代码也是整齐的。
名称 | 说明 |
---|
frmconfig | 系统设置模块,包括基本设置、录像机管理、摄像机管理、轮询管理、用户管理、视频上传等。 |
frmdata | 日志查询模块,包括本地日志、设备日志等。 |
frmdemo | 演示demo示例,用于演示具体控件或者功能的使用,方便学习参考,比如视频图片、视频控件、视频存储都单独的使用demo。 |
frmipc | 存放摄像机处理相关的模块,比如设备控制,云台控制、预置位、巡航设置等。之前放在frmmodule模块中,后面独立出来管理更方便。 |
frmmain | 主界面模块,包括登录登出界面、主界面、右上角时间组件、欢迎组件等。 |
frmmap | 地图模块,包括通用地图内核界面、图片地图、在线地图、离线地图、路径规划等。 |
frmmodule | 停靠子窗体模块,包括停靠窗体管理核心类、设备列表、窗口信息、图文警情、设备轨迹、网页浏览等模块。将摄像机、机器人、无人机相关的模块放到了对应的模块文件夹,这里放的是系统通用的模块。 |
frmrobot | 无人机模块,包括图像增强、飞行监控等模块。 |
frmuavs | 无人机模块,包括图像增强、飞行监控等模块。 |
frmvideo | 视频监控模块,所有视频监控相关的都放在这里,包括主界面的视频监控布局窗体、视频回放、远程回放、图片回放等。 |
11.3.4.1 模块-frmconfig
名称 | 说明 |
---|
frmconfig | 系统设置模块主界面,采用堆栈窗体形式,加载多个子界面比如摄像机管理、轮询管理等。 |
frmconfigdb | 数据库设置,独立出来,很多系统通用。 |
frmconfigipc | 摄像机管理,可以增加、删除、修改、清空、导入、导出、打印摄像机信息。 |
frmconfigipcsearch | onvif设备搜索,独立出来的窗体,可以搜索局域网内的所有onvif摄像机信息,搜索完以后获取摄像机的视频流地址等,最后可以单个添加或者批量选中添加到摄像机信息表格中。 |
frmconfignvr | 录像机管理,可以增加、删除、修改、清空、导入、导出、打印录像机信息。 |
frmconfigpoll | 轮询管理,可以增加、删除、修改、清空、导入、导出、打印轮询点信息。可以按照设定规则批量生成轮询点信息。 |
frmconfigpollplus | 将轮询管理中的轮询参数配置、分组管理、批量添加等独立出来的界面,方便管理和拓展。 |
frmconfigsave | 录像计划,目前空的,等想好了怎么设计好在实现。 |
frmconfigsystem | 系统设置,包括基本设置、视频参数、数据库设置、地图配置、功能激活、颜色配置、串口配置、网络配置等。 |
frmconfiguser | 用户管理,可以增加、删除、修改、清空、导入、导出、打印用户信息。每个用户可以勾选不同的模块权限。 |
11.3.4.2 模块-frmdata
名称 | 说明 |
---|
frmdata | 日志查询模块主界面,采用堆栈窗体形式,加载多个子界面包括本地日志、设备日志等。 |
frmdatadevice | 设备日志,通过私有协议从NVR取对应设备日志信息。 |
frmdatauser | 本地地址,用户操作的日志信息,可查询和导出打印数据记录。 |
11.3.4.3 模块-frmdemo
名称 | 说明 |
---|
frmdemo | 单独的功能演示示例主窗体,加载多个子界面比如视频控件等。 |
frmdemovideoimage | 视频图片示例,从图片文件夹读取图片集合,定时器绘制取出图片发给视频控件绘制。 |
frmdemovideosave | 视频保存示例,演示如何对视频控件进行视频保存,可动态保存。 |
frmdemovideowidget | 视频控件示例,演示视频控件如何使用。 |
11.3.4.4 模块-frmipc
名称 | 说明 |
---|
frmipccontrol | 设备控制模块,可对选中设备进行图片参数调节、NTP校时、设备重启、抓拍图片(ONVIF抓图)等。 |
frmipcnavigate | 巡航管理模块,暂未实现,后期完善。 |
frmipcreset | 预置位管理模块,暂未实现,后期完善。 |
frmipcptz | 云台控制模块,可对选中的摄像机进行云台控制。 |
11.3.4.5 模块-frmmain
名称 | 说明 |
---|
frmlogin | 用户登录界面,三次错误关闭,下拉可选用户,内置超级密码。 |
frmlogout | 用户退出界面,三次错误关闭,下拉可选用户,内置超级密码。 |
frmmain | 系统主界面,采用堆栈窗体,加载各个子模块。 |
frmmain1 | 备用模块1界面,根据参数设置决定是否启用。 |
frmtimecpu | 右上角日期时间+CPU内存显示。 |
frmwelcome | 右上角欢迎信息界面。 |
11.3.4.6 模块-frmmap
名称 | 说明 |
---|
frmmap | 地图管理主界面,采用堆栈窗体形式,加载各个子界面比如图片地图、在线地图、离线地图、路径规划等。 |
frmmapcore | 通用百度地图内核界面,用来加载百度地图,可设置在线、离线模式,有很多个窗体用到类似功能特意封装到一个类,重复利用,比如悬浮地图、飞行轨迹、路径规划等模块都用到了此内核。 |
frmmapdevice | 通用的设备地图界面,在线地图和离线地图界面公用这个界面,唯一区别就是设置下地图的模式是在线还是离线。 |
frmmapimage | 图片地图界面,设备作为一个个按钮点显示在对应地图上,可以拖动,双击弹出预览实时视频。 |
frmmaplocal | 离线地图界面,可更新经纬度值、模拟运动轨迹等。 |
frmmapweb | 在线地图界面,可更新经纬度值、模拟运动轨迹等。 |
frmmaproute | 路径规划界面,可查询路线得到路线的经纬度坐标集合。 |
11.3.4.7 模块-frmmodule
名称 | 说明 |
---|
frmdevicegps | 设备轨迹模块,对设定的设备随机模拟轨迹,也可传入经纬度坐标值自动移动并绘制轨迹线条,不同设备可以不同颜色。 |
frmdevicetree | 设备列表模块,读取设备信息加载形成树状列表,双击或者拖动到视频监控窗体直接播放视频,提供右键菜单作为演示如何使用。 |
frmmodule | 主界面中心部分窗体,采用QMainWindow类,中间加载的视频监控面板,其余new出来每个子模块,子模块可停靠和悬浮拖动等。不同工作模式下的各种子模块都在此加载。同时负责管理模块的显示隐藏菜单。 |
frmmsglist | 图文警情模块,也叫消息列表模块,带有右键菜单添加、删除、清空列表中的消息,双击可以弹出大图预览。 |
frmmsglistitem | 图文警情模块子类,都是由一个个item组成放到panelwidget面板控件中,自动形成滚动条。 |
frmmsgtable | 窗口消息模块,也叫表格消息模块,表格形式显示打印信息,不同的内容可以不同颜色区分。 |
frmwebview | 网页浏览模块,传入一个url地址打开对应的网页,比如打开一个3D的网页。 |
11.3.4.8 模块-frmrobot
名称 | 说明 |
---|
frmrobotdata | 仿真数据模块,启动机器人通信服务,接收数据解析显示。 |
frmrobotdebug | 数据调试模块,可模拟发送轨迹数据测试解析类。 |
frmrobotdebug2 | 新数据调试模块,打印多个串口数据,不同颜色显示。 |
frmrobotemulate | 运动仿真模块,预留给用户实现,一般放个3D效果。 |
frmrobotlog | 机器人实时数据模块,预留给用户实现。 |
11.3.4.9 模块-frmuavs
名称 | 说明 |
---|
frmuavsflight | 飞行套件控件面板,放了多个飞行仪表,默认自动模拟数据,可以传入对应数据显示。 |
frmuavsimage | 图像增强模块,预留给用户实现。 |
frmuavspanel | 飞行监控面板。 |
11.3.4.10 模块-frmvideo
名称 | 说明 |
---|
frmvideo | 视频回放模块主界面,堆栈窗体形式,加载多个子界面比如本地回放、远程回放、设备播放等。 |
frmvideopanel | 视频监控面板,主界面中间部分,这是核心,管理多个通道,通道可移除删除,拖曳打开,拖曳交换等。 |
frmvideopaneltool | 视频监控底部工具栏,独立出来一个类专门管理。 |
frmvideoplayimage | 图片回放模块,按照规则查询图片目录,然后可设定播放速度进行图片序列播放。 |
frmvideoplaylocal | 本地回放模块,查询对应通道的本地存储的视频文件,双击播放,可暂停和拖动进度条位置。 |
frmvideoplaynvr | 设备播放模块,通过RTSP视频流的形式从远程设备取视频进行播放,支持摄像机和录像机,手动填入地址也行。 |
frmvideoplayweb | 远程回放模块,需要用厂家sdk去实现,从NVR回放录像。 |
frmvideopreview | 视频预览窗体,比如图片或者地图上双击设备弹出的视频预览,可以多个,关闭的时候自动释放资源。 |
frmvideoupload | 视频上传,将本地存储的视频文件上传到服务器。 |
12 二次开发说明
12.1 开发环境搭建
12.1.1 常规通用步骤
- 第一步:安装系统,推荐用vmware虚拟机。
- 第二步:安装qt环境,可以直接用官方下载的run安装包安装,有些要求用命令行安装。
- 第三步:写个空白窗体程序测试下是否环境正常。
- 第四步:编译ffmpeg,生成对应的动态库或者静态库。
- 第五步:打开video_system.pro项目进行编译。
- 第六步:打包发布,为了发布方便,推荐用静态编译的Qt+静态编译的ffmpeg,这样打包发布很清爽,就一个可执行文件。
12.1.2 windows+mingw
12.1.3 windows+msvc
12.1.4 linux+ubuntu
12.1.5 linux+deepin
12.1.6 linux+centeros
12.1.7 linux+uos
12.1.8 linux+银河麒麟
12.2 通用模块使用
12.3 人工智能集成
13 其他说明
13.1 海康onvif设置
新版的海康的摄像机,默认onvif是关闭的,需要手动开启,开启以后记得添加onvif用户,并重启摄像机应用。提示:海康旗下的萤石目前暂时不支持onvif协议。
13.2 大华onvif设置
大华摄像机,需要在用户管理中添加onvif用户,添加好以后建议重启摄像机应用。
13.3 国际onvif工具
工具的名字叫ONVIF Device Manager,可以自行搜索下载,此工具位国际官方工具,如果此工具搜索不到摄像机,则说明该摄像机不是真正的onvif摄像机,不是标准的摄像机,目前市面上的绝大部分网络摄像机都支持onvif。
13.4 报警输入设置
- 默认摄像机IO输入或者开关量输入是关闭的,需要手动开启。
- 一般都是登录到摄像机的web页面找到开关量的地方,可能描述不一样但是大致的意思差不多。
- 一般摄像机会有两组开关量输入,而且开关量报警有常开常闭两种,都需要自己手动选择。
- 如果是常开的话意味着闭合是属于报警,反之亦然。
- 找两个导线接在对应口子(详见摄像机厂家的说明书,摄像机背面板也会有对应字样标识一般叫 in)。
- 短接或者扒开,都会有反应,onvif工具都能接收到信息(前提是单击过订阅事件按钮,而且顺利返回了订阅地址才行)。
- 会收到LogicalState关键字的信息,true或者1表示报警,false或者0表示正常。
- 可能每个厂家会有所区别,需要自己拿到数据后做特殊处理,但是大部分厂家都是相似的,实在不行无非搞个contains方法判断好了。
diff --git a/other/dbpage/main.cpp b/other/dbpage/main.cpp
index 3b0a430..54e7293 100644
--- a/other/dbpage/main.cpp
+++ b/other/dbpage/main.cpp
@@ -10,7 +10,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/echartgauge/main.cpp b/other/echartgauge/main.cpp
index cbb2ba0..b01c540 100644
--- a/other/echartgauge/main.cpp
+++ b/other/echartgauge/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/lineeditnext/main.cpp b/other/lineeditnext/main.cpp
index e35d4b0..ccd5674 100644
--- a/other/lineeditnext/main.cpp
+++ b/other/lineeditnext/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/mouseline/main.cpp b/other/mouseline/main.cpp
index 65db2c8..2bffb41 100644
--- a/other/mouseline/main.cpp
+++ b/other/mouseline/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/multobj2slot/main.cpp b/other/multobj2slot/main.cpp
index 077b3ec..8cd5f86 100644
--- a/other/multobj2slot/main.cpp
+++ b/other/multobj2slot/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/ntpclient/main.cpp b/other/ntpclient/main.cpp
index cb453c4..d871fb5 100644
--- a/other/ntpclient/main.cpp
+++ b/other/ntpclient/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/other/trayicon/main.cpp b/other/trayicon/main.cpp
index 3897cb0..79755cc 100644
--- a/other/trayicon/main.cpp
+++ b/other/trayicon/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/third/hotkey/main.cpp b/third/hotkey/main.cpp
index 7264077..de8f557 100644
--- a/third/hotkey/main.cpp
+++ b/third/hotkey/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/third/miniblink/main.cpp b/third/miniblink/main.cpp
index 352ad3e..c310d97 100644
--- a/third/miniblink/main.cpp
+++ b/third/miniblink/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/third/qcustomplotdemo/main.cpp b/third/qcustomplotdemo/main.cpp
index 9023a5b..5942c4f 100644
--- a/third/qcustomplotdemo/main.cpp
+++ b/third/qcustomplotdemo/main.cpp
@@ -13,7 +13,10 @@ int main(int argc, char *argv[])
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/third/qwtdemo/main.cpp b/third/qwtdemo/main.cpp
index 7cba000..cafdd21 100644
--- a/third/qwtdemo/main.cpp
+++ b/third/qwtdemo/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/third/shortcut/main.cpp b/third/shortcut/main.cpp
index 542bd47..5d87e35 100644
--- a/third/shortcut/main.cpp
+++ b/third/shortcut/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/base64helper/main.cpp b/tool/base64helper/main.cpp
index cc93730..fc0e953 100644
--- a/tool/base64helper/main.cpp
+++ b/tool/base64helper/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/comtool/api/quihelper.cpp b/tool/comtool/api/quihelper.cpp
index 2b3eabf..516cffb 100644
--- a/tool/comtool/api/quihelper.cpp
+++ b/tool/comtool/api/quihelper.cpp
@@ -1,5 +1,6 @@
#include "quihelper.h"
+#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
int QUIHelper::getScreenIndex()
{
//需要对多个屏幕进行处理
@@ -57,6 +58,11 @@ int QUIHelper::deskHeight()
return getScreenRect().height();
}
+QSize QUIHelper::deskSize()
+{
+ return getScreenRect().size();
+}
+
QWidget *QUIHelper::centerBaseForm = 0;
void QUIHelper::setFormInCenter(QWidget *form)
{
@@ -77,6 +83,19 @@ void QUIHelper::setFormInCenter(QWidget *form)
form->move(movePoint);
}
+void QUIHelper::showForm(QWidget *form)
+{
+ setFormInCenter(form);
+
+ //判断宽高是否超过了屏幕分辨率,超过了则最大化显示
+ //qDebug() << TIMEMS << form->size() << deskSize();
+ if (form->width() + 20 > deskWidth() || form->height() + 50 > deskHeight()) {
+ form->showMaximized();
+ } else {
+ form->show();
+ }
+}
+
QString QUIHelper::appName()
{
//没有必要每次都获取,只有当变量为空时才去获取一次
@@ -101,12 +120,36 @@ QString QUIHelper::appPath()
#endif
}
-QString QUIHelper::getUuid()
+QList QUIHelper::colors = QList();
+QList QUIHelper::getColorList()
{
- QString uuid = QUuid::createUuid().toString();
- uuid.replace("{", "");
- uuid.replace("}", "");
- return uuid;
+ //备用颜色集合 可以自行添加
+ if (colors.count() == 0) {
+ colors << QColor(0, 176, 180) << QColor(0, 113, 193) << QColor(255, 192, 0);
+ colors << QColor(72, 103, 149) << QColor(185, 87, 86) << QColor(0, 177, 125);
+ colors << QColor(214, 77, 84) << QColor(71, 164, 233) << QColor(34, 163, 169);
+ colors << QColor(59, 123, 156) << QColor(162, 121, 197) << QColor(72, 202, 245);
+ colors << QColor(0, 150, 121) << QColor(111, 9, 176) << QColor(250, 170, 20);
+ }
+
+ return colors;
+}
+
+QStringList QUIHelper::getColorNames()
+{
+ QList colors = getColorList();
+ QStringList colorNames;
+ foreach (QColor color, colors) {
+ colorNames << color.name();
+ }
+ return colorNames;
+}
+
+QColor QUIHelper::getRandColor()
+{
+ QList colors = getColorList();
+ int index = getRandValue(0, colors.count(), true);
+ return colors.at(index);
}
void QUIHelper::initRand()
@@ -116,6 +159,82 @@ void QUIHelper::initRand()
srand(t.msec() + t.second() * 1000);
}
+float QUIHelper::getRandFloat(float min, float max)
+{
+ double diff = fabs(max - min);
+ double value = (double)(rand() % 100) / 100;
+ value = min + value * diff;
+ return value;
+}
+
+double QUIHelper::getRandValue(int min, int max, bool contansMin, bool contansMax)
+{
+ int value;
+#if (QT_VERSION <= QT_VERSION_CHECK(5,10,0))
+ //通用公式 a是起始值,n是整数的范围
+ //int value = a + rand() % n;
+ if (contansMin) {
+ if (contansMax) {
+ value = min + 0 + (rand() % (max - min + 1));
+ } else {
+ value = min + 0 + (rand() % (max - min + 0));
+ }
+ } else {
+ if (contansMax) {
+ value = min + 1 + (rand() % (max - min + 0));
+ } else {
+ value = min + 1 + (rand() % (max - min - 1));
+ }
+ }
+#else
+ if (contansMin) {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 0);
+ }
+ } else {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 0);
+ }
+ }
+#endif
+ return value;
+}
+
+QStringList QUIHelper::getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat)
+{
+ //随机生成点坐标
+ QStringList points;
+ for (int i = 0; i < count; ++i) {
+ //0.00881415 0.000442928
+#if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
+ float lngx = QRandomGenerator::global()->bounded(dotLng);
+ float latx = QRandomGenerator::global()->bounded(dotLat);
+#else
+ float lngx = getRandFloat(dotLng / 10, dotLng);
+ float latx = getRandFloat(dotLat / 10, dotLat);
+#endif
+ //需要先用精度转换成字符串
+ QString lng2 = QString::number(mainLng + lngx, 'f', 8);
+ QString lat2 = QString::number(mainLat + latx, 'f', 8);
+ QString point = QString("%1,%2").arg(lng2).arg(lat2);
+ points << point;
+ }
+
+ return points;
+}
+
+QString QUIHelper::getUuid()
+{
+ QString uuid = QUuid::createUuid().toString();
+ uuid.replace("{", "");
+ uuid.replace("}", "");
+ return uuid;
+}
+
void QUIHelper::newDir(const QString &dirName)
{
QString strDir = dirName;
@@ -151,30 +270,68 @@ void QUIHelper::sleep(int msec)
void QUIHelper::setStyle()
{
//打印下所有内置风格的名字
- qDebug() << "Qt内置的样式" << QStyleFactory::keys();
+ qDebug() << TIMEMS << "QStyleFactory::keys" << QStyleFactory::keys();
+ //设置内置风格
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qApp->setStyle(QStyleFactory::create("Fusion"));
#else
qApp->setStyle(QStyleFactory::create("Cleanlooks"));
#endif
- //qApp->setPalette(QPalette("#FFFFFF"));
+
+ //设置指定颜色
+ QPalette palette;
+ palette.setBrush(QPalette::Window, QColor("#F0F0F0"));
+ qApp->setPalette(palette);
+}
+
+QFont QUIHelper::addFont(const QString &fontFile, const QString &fontName)
+{
+ //判断图形字体是否存在,不存在则加入
+ QFontDatabase fontDb;
+ if (!fontDb.families().contains(fontName)) {
+ int fontId = fontDb.addApplicationFont(fontFile);
+ QStringList listName = fontDb.applicationFontFamilies(fontId);
+ if (listName.count() == 0) {
+ qDebug() << QString("load %1 error").arg(fontName);
+ }
+ }
+
+ //再次判断是否包含字体名称防止加载失败
+ QFont font;
+ if (fontDb.families().contains(fontName)) {
+ font = QFont(fontName);
+#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
+ font.setHintingPreference(QFont::PreferNoHinting);
+#endif
+ }
+
+ return font;
}
void QUIHelper::setFont(int fontSize)
{
- QFont font;
- font.setFamily("MicroSoft Yahei");
-#ifdef Q_OS_ANDROID
- font.setPixelSize(15);
-#elif __arm__
- font.setPixelSize(25);
-#else
- font.setPixelSize(fontSize);
+#ifdef rk3399
+ return;
+#endif
+ //网页套件需要主动加载中文字体才能正常显示中文
+#ifdef Q_OS_WASM
+ QString fontFile = ":/font/DroidSansFallback.ttf";
+ QString fontName = "Droid Sans Fallback";
+ qApp->setFont(addFont(fontFile, fontName));
+ return;
#endif
-#ifndef rk3399
- qApp->setFont(font);
+#ifdef __arm__
+ fontSize = 25;
#endif
+#ifdef Q_OS_ANDROID
+ fontSize = 15;
+#endif
+
+ QFont font;
+ font.setFamily("MicroSoft Yahei");
+ font.setPixelSize(fontSize);
+ qApp->setFont(font);
}
void QUIHelper::setCode(bool utf8)
@@ -205,20 +362,23 @@ void QUIHelper::setTranslator(const QString &qmFile)
}
QTranslator *translator = new QTranslator(qApp);
- translator->load(qmFile);
- qApp->installTranslator(translator);
+ if (translator->load(qmFile)) {
+ qApp->installTranslator(translator);
+ }
}
-void QUIHelper::initAll()
+void QUIHelper::initAll(bool utf8, bool style, int fontSize)
{
//初始化随机数种子
QUIHelper::initRand();
- //设置样式风格
- QUIHelper::setStyle();
- //设置字体
- QUIHelper::setFont(13);
//设置编码
- QUIHelper::setCode();
+ QUIHelper::setCode(utf8);
+ //设置样式风格
+ if (style) {
+ QUIHelper::setStyle();
+ }
+ //设置字体
+ QUIHelper::setFont(fontSize);
//设置翻译文件支持多个
QUIHelper::setTranslator(":/qm/widgets.qm");
QUIHelper::setTranslator(":/qm/qt_zh_CN.qm");
@@ -299,7 +459,12 @@ QString QUIHelper::getXorEncryptDecrypt(const QString &value, char key)
key = 127;
}
+ //大概从5.9版本输出的加密密码字符串前面会加上 @String 字符
QString result = value;
+ if (result.startsWith("@String")) {
+ result = result.mid(8, result.length() - 9);
+ }
+
int count = result.count();
for (int i = 0; i < count; i++) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
@@ -331,6 +496,8 @@ uchar QUIHelper::getCheckCode(const QByteArray &data)
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit, bool stretchLast)
{
+ //设置弱属性用于应用qss特殊样式
+ tableView->setProperty("model", true);
//取消自动换行
tableView->setWordWrap(false);
//超出文本不显示省略号
@@ -374,7 +541,8 @@ void QUIHelper::openFile(const QString &fileName, const QString &msg)
#ifdef __arm__
return;
#endif
- if (fileName.isEmpty()) {
+ //文件不存在则不用处理
+ if (!QFile(fileName).exists()) {
return;
}
if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
@@ -401,8 +569,10 @@ bool QUIHelper::checkIniFile(const QString &iniFile)
QStringList list = line.split("=");
if (list.count() == 2) {
- if (list.at(1) == "") {
- qDebug() << "ini node no value" << list.at(0);
+ QString key = list.at(0);
+ QString value = list.at(1);
+ if (value.isEmpty()) {
+ qDebug() << TIMEMS << "ini node no value" << key;
ok = false;
break;
}
diff --git a/tool/comtool/api/quihelper.h b/tool/comtool/api/quihelper.h
index dc40547..96d037e 100644
--- a/tool/comtool/api/quihelper.h
+++ b/tool/comtool/api/quihelper.h
@@ -13,29 +13,52 @@ public:
//获取桌面宽度高度+居中显示
static int deskWidth();
static int deskHeight();
+ static QSize deskSize();
//居中显示窗体
//定义标志位指定是以桌面为参照还是主程序界面为参照
static QWidget *centerBaseForm;
static void setFormInCenter(QWidget *form);
+ static void showForm(QWidget *form);
//程序文件名称+当前所在路径
static QString appName();
static QString appPath();
- //获取uuid+初始化随机数种子+新建目录+延时
- static QString getUuid();
+ //获取内置颜色集合
+ static QList colors;
+ static QList getColorList();
+ static QStringList getColorNames();
+ //随机获取颜色集合中的颜色
+ static QColor getRandColor();
+
+ //初始化随机数种子
static void initRand();
+ //获取随机小数
+ static float getRandFloat(float min, float max);
+ //获取随机数,指定最小值和最大值
+ static double getRandValue(int min, int max, bool contansMin = false, bool contansMax = false);
+ //获取范围值随机经纬度集合
+ static QStringList getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat);
+
+ //获取uuid
+ static QString getUuid();
+ //可执行文件目录下新建目录
static void newDir(const QString &dirName);
+ //延时
static void sleep(int msec);
- //设置样式+字体+编码+居中+翻译
+ //设置Qt自带样式
static void setStyle();
- static void setFont(int fontSize = 12);
+ //设置字体
+ static QFont addFont(const QString &fontFile, const QString &fontName);
+ static void setFont(int fontSize = 12);
+ //设置编码
static void setCode(bool utf8 = true);
+ //设置翻译文件
static void setTranslator(const QString &qmFile);
//一次性设置所有
- static void initAll();
+ static void initAll(bool utf8 = true, bool style = true, int fontSize = 13);
//设置无边框
static void setFramelessForm(QWidget *widgetMain, bool tool = false, bool top = false, bool menu = true);
diff --git a/tool/comtool/main.cpp b/tool/comtool/main.cpp
index 3213034..c338af6 100644
--- a/tool/comtool/main.cpp
+++ b/tool/comtool/main.cpp
@@ -3,9 +3,13 @@
int main(int argc, char *argv[])
{
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
+
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/main.ico"));
diff --git a/tool/countcode/main.cpp b/tool/countcode/main.cpp
index 5767f4a..e98ee15 100644
--- a/tool/countcode/main.cpp
+++ b/tool/countcode/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/emailtool/main.cpp b/tool/emailtool/main.cpp
index 7d04704..0e6c45f 100644
--- a/tool/emailtool/main.cpp
+++ b/tool/emailtool/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/keydemo/main.cpp b/tool/keydemo/main.cpp
index 85d82da..4366476 100644
--- a/tool/keydemo/main.cpp
+++ b/tool/keydemo/main.cpp
@@ -8,7 +8,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/keytool/main.cpp b/tool/keytool/main.cpp
index f463491..2c34b25 100644
--- a/tool/keytool/main.cpp
+++ b/tool/keytool/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/livedemo/main.cpp b/tool/livedemo/main.cpp
index 5b0a0b4..8755b8d 100644
--- a/tool/livedemo/main.cpp
+++ b/tool/livedemo/main.cpp
@@ -8,7 +8,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/moneytool/main.cpp b/tool/moneytool/main.cpp
index 86f5ee4..4c784c8 100644
--- a/tool/moneytool/main.cpp
+++ b/tool/moneytool/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/tool/netserver/api/quihelper.cpp b/tool/netserver/api/quihelper.cpp
index 2b3eabf..516cffb 100644
--- a/tool/netserver/api/quihelper.cpp
+++ b/tool/netserver/api/quihelper.cpp
@@ -1,5 +1,6 @@
#include "quihelper.h"
+#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
int QUIHelper::getScreenIndex()
{
//需要对多个屏幕进行处理
@@ -57,6 +58,11 @@ int QUIHelper::deskHeight()
return getScreenRect().height();
}
+QSize QUIHelper::deskSize()
+{
+ return getScreenRect().size();
+}
+
QWidget *QUIHelper::centerBaseForm = 0;
void QUIHelper::setFormInCenter(QWidget *form)
{
@@ -77,6 +83,19 @@ void QUIHelper::setFormInCenter(QWidget *form)
form->move(movePoint);
}
+void QUIHelper::showForm(QWidget *form)
+{
+ setFormInCenter(form);
+
+ //判断宽高是否超过了屏幕分辨率,超过了则最大化显示
+ //qDebug() << TIMEMS << form->size() << deskSize();
+ if (form->width() + 20 > deskWidth() || form->height() + 50 > deskHeight()) {
+ form->showMaximized();
+ } else {
+ form->show();
+ }
+}
+
QString QUIHelper::appName()
{
//没有必要每次都获取,只有当变量为空时才去获取一次
@@ -101,12 +120,36 @@ QString QUIHelper::appPath()
#endif
}
-QString QUIHelper::getUuid()
+QList QUIHelper::colors = QList();
+QList QUIHelper::getColorList()
{
- QString uuid = QUuid::createUuid().toString();
- uuid.replace("{", "");
- uuid.replace("}", "");
- return uuid;
+ //备用颜色集合 可以自行添加
+ if (colors.count() == 0) {
+ colors << QColor(0, 176, 180) << QColor(0, 113, 193) << QColor(255, 192, 0);
+ colors << QColor(72, 103, 149) << QColor(185, 87, 86) << QColor(0, 177, 125);
+ colors << QColor(214, 77, 84) << QColor(71, 164, 233) << QColor(34, 163, 169);
+ colors << QColor(59, 123, 156) << QColor(162, 121, 197) << QColor(72, 202, 245);
+ colors << QColor(0, 150, 121) << QColor(111, 9, 176) << QColor(250, 170, 20);
+ }
+
+ return colors;
+}
+
+QStringList QUIHelper::getColorNames()
+{
+ QList colors = getColorList();
+ QStringList colorNames;
+ foreach (QColor color, colors) {
+ colorNames << color.name();
+ }
+ return colorNames;
+}
+
+QColor QUIHelper::getRandColor()
+{
+ QList colors = getColorList();
+ int index = getRandValue(0, colors.count(), true);
+ return colors.at(index);
}
void QUIHelper::initRand()
@@ -116,6 +159,82 @@ void QUIHelper::initRand()
srand(t.msec() + t.second() * 1000);
}
+float QUIHelper::getRandFloat(float min, float max)
+{
+ double diff = fabs(max - min);
+ double value = (double)(rand() % 100) / 100;
+ value = min + value * diff;
+ return value;
+}
+
+double QUIHelper::getRandValue(int min, int max, bool contansMin, bool contansMax)
+{
+ int value;
+#if (QT_VERSION <= QT_VERSION_CHECK(5,10,0))
+ //通用公式 a是起始值,n是整数的范围
+ //int value = a + rand() % n;
+ if (contansMin) {
+ if (contansMax) {
+ value = min + 0 + (rand() % (max - min + 1));
+ } else {
+ value = min + 0 + (rand() % (max - min + 0));
+ }
+ } else {
+ if (contansMax) {
+ value = min + 1 + (rand() % (max - min + 0));
+ } else {
+ value = min + 1 + (rand() % (max - min - 1));
+ }
+ }
+#else
+ if (contansMin) {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 0);
+ }
+ } else {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 0);
+ }
+ }
+#endif
+ return value;
+}
+
+QStringList QUIHelper::getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat)
+{
+ //随机生成点坐标
+ QStringList points;
+ for (int i = 0; i < count; ++i) {
+ //0.00881415 0.000442928
+#if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
+ float lngx = QRandomGenerator::global()->bounded(dotLng);
+ float latx = QRandomGenerator::global()->bounded(dotLat);
+#else
+ float lngx = getRandFloat(dotLng / 10, dotLng);
+ float latx = getRandFloat(dotLat / 10, dotLat);
+#endif
+ //需要先用精度转换成字符串
+ QString lng2 = QString::number(mainLng + lngx, 'f', 8);
+ QString lat2 = QString::number(mainLat + latx, 'f', 8);
+ QString point = QString("%1,%2").arg(lng2).arg(lat2);
+ points << point;
+ }
+
+ return points;
+}
+
+QString QUIHelper::getUuid()
+{
+ QString uuid = QUuid::createUuid().toString();
+ uuid.replace("{", "");
+ uuid.replace("}", "");
+ return uuid;
+}
+
void QUIHelper::newDir(const QString &dirName)
{
QString strDir = dirName;
@@ -151,30 +270,68 @@ void QUIHelper::sleep(int msec)
void QUIHelper::setStyle()
{
//打印下所有内置风格的名字
- qDebug() << "Qt内置的样式" << QStyleFactory::keys();
+ qDebug() << TIMEMS << "QStyleFactory::keys" << QStyleFactory::keys();
+ //设置内置风格
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qApp->setStyle(QStyleFactory::create("Fusion"));
#else
qApp->setStyle(QStyleFactory::create("Cleanlooks"));
#endif
- //qApp->setPalette(QPalette("#FFFFFF"));
+
+ //设置指定颜色
+ QPalette palette;
+ palette.setBrush(QPalette::Window, QColor("#F0F0F0"));
+ qApp->setPalette(palette);
+}
+
+QFont QUIHelper::addFont(const QString &fontFile, const QString &fontName)
+{
+ //判断图形字体是否存在,不存在则加入
+ QFontDatabase fontDb;
+ if (!fontDb.families().contains(fontName)) {
+ int fontId = fontDb.addApplicationFont(fontFile);
+ QStringList listName = fontDb.applicationFontFamilies(fontId);
+ if (listName.count() == 0) {
+ qDebug() << QString("load %1 error").arg(fontName);
+ }
+ }
+
+ //再次判断是否包含字体名称防止加载失败
+ QFont font;
+ if (fontDb.families().contains(fontName)) {
+ font = QFont(fontName);
+#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
+ font.setHintingPreference(QFont::PreferNoHinting);
+#endif
+ }
+
+ return font;
}
void QUIHelper::setFont(int fontSize)
{
- QFont font;
- font.setFamily("MicroSoft Yahei");
-#ifdef Q_OS_ANDROID
- font.setPixelSize(15);
-#elif __arm__
- font.setPixelSize(25);
-#else
- font.setPixelSize(fontSize);
+#ifdef rk3399
+ return;
+#endif
+ //网页套件需要主动加载中文字体才能正常显示中文
+#ifdef Q_OS_WASM
+ QString fontFile = ":/font/DroidSansFallback.ttf";
+ QString fontName = "Droid Sans Fallback";
+ qApp->setFont(addFont(fontFile, fontName));
+ return;
#endif
-#ifndef rk3399
- qApp->setFont(font);
+#ifdef __arm__
+ fontSize = 25;
#endif
+#ifdef Q_OS_ANDROID
+ fontSize = 15;
+#endif
+
+ QFont font;
+ font.setFamily("MicroSoft Yahei");
+ font.setPixelSize(fontSize);
+ qApp->setFont(font);
}
void QUIHelper::setCode(bool utf8)
@@ -205,20 +362,23 @@ void QUIHelper::setTranslator(const QString &qmFile)
}
QTranslator *translator = new QTranslator(qApp);
- translator->load(qmFile);
- qApp->installTranslator(translator);
+ if (translator->load(qmFile)) {
+ qApp->installTranslator(translator);
+ }
}
-void QUIHelper::initAll()
+void QUIHelper::initAll(bool utf8, bool style, int fontSize)
{
//初始化随机数种子
QUIHelper::initRand();
- //设置样式风格
- QUIHelper::setStyle();
- //设置字体
- QUIHelper::setFont(13);
//设置编码
- QUIHelper::setCode();
+ QUIHelper::setCode(utf8);
+ //设置样式风格
+ if (style) {
+ QUIHelper::setStyle();
+ }
+ //设置字体
+ QUIHelper::setFont(fontSize);
//设置翻译文件支持多个
QUIHelper::setTranslator(":/qm/widgets.qm");
QUIHelper::setTranslator(":/qm/qt_zh_CN.qm");
@@ -299,7 +459,12 @@ QString QUIHelper::getXorEncryptDecrypt(const QString &value, char key)
key = 127;
}
+ //大概从5.9版本输出的加密密码字符串前面会加上 @String 字符
QString result = value;
+ if (result.startsWith("@String")) {
+ result = result.mid(8, result.length() - 9);
+ }
+
int count = result.count();
for (int i = 0; i < count; i++) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
@@ -331,6 +496,8 @@ uchar QUIHelper::getCheckCode(const QByteArray &data)
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit, bool stretchLast)
{
+ //设置弱属性用于应用qss特殊样式
+ tableView->setProperty("model", true);
//取消自动换行
tableView->setWordWrap(false);
//超出文本不显示省略号
@@ -374,7 +541,8 @@ void QUIHelper::openFile(const QString &fileName, const QString &msg)
#ifdef __arm__
return;
#endif
- if (fileName.isEmpty()) {
+ //文件不存在则不用处理
+ if (!QFile(fileName).exists()) {
return;
}
if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
@@ -401,8 +569,10 @@ bool QUIHelper::checkIniFile(const QString &iniFile)
QStringList list = line.split("=");
if (list.count() == 2) {
- if (list.at(1) == "") {
- qDebug() << "ini node no value" << list.at(0);
+ QString key = list.at(0);
+ QString value = list.at(1);
+ if (value.isEmpty()) {
+ qDebug() << TIMEMS << "ini node no value" << key;
ok = false;
break;
}
diff --git a/tool/netserver/api/quihelper.h b/tool/netserver/api/quihelper.h
index dc40547..96d037e 100644
--- a/tool/netserver/api/quihelper.h
+++ b/tool/netserver/api/quihelper.h
@@ -13,29 +13,52 @@ public:
//获取桌面宽度高度+居中显示
static int deskWidth();
static int deskHeight();
+ static QSize deskSize();
//居中显示窗体
//定义标志位指定是以桌面为参照还是主程序界面为参照
static QWidget *centerBaseForm;
static void setFormInCenter(QWidget *form);
+ static void showForm(QWidget *form);
//程序文件名称+当前所在路径
static QString appName();
static QString appPath();
- //获取uuid+初始化随机数种子+新建目录+延时
- static QString getUuid();
+ //获取内置颜色集合
+ static QList colors;
+ static QList getColorList();
+ static QStringList getColorNames();
+ //随机获取颜色集合中的颜色
+ static QColor getRandColor();
+
+ //初始化随机数种子
static void initRand();
+ //获取随机小数
+ static float getRandFloat(float min, float max);
+ //获取随机数,指定最小值和最大值
+ static double getRandValue(int min, int max, bool contansMin = false, bool contansMax = false);
+ //获取范围值随机经纬度集合
+ static QStringList getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat);
+
+ //获取uuid
+ static QString getUuid();
+ //可执行文件目录下新建目录
static void newDir(const QString &dirName);
+ //延时
static void sleep(int msec);
- //设置样式+字体+编码+居中+翻译
+ //设置Qt自带样式
static void setStyle();
- static void setFont(int fontSize = 12);
+ //设置字体
+ static QFont addFont(const QString &fontFile, const QString &fontName);
+ static void setFont(int fontSize = 12);
+ //设置编码
static void setCode(bool utf8 = true);
+ //设置翻译文件
static void setTranslator(const QString &qmFile);
//一次性设置所有
- static void initAll();
+ static void initAll(bool utf8 = true, bool style = true, int fontSize = 13);
//设置无边框
static void setFramelessForm(QWidget *widgetMain, bool tool = false, bool top = false, bool menu = true);
diff --git a/tool/netserver/main.cpp b/tool/netserver/main.cpp
index 9146383..18b2ebb 100644
--- a/tool/netserver/main.cpp
+++ b/tool/netserver/main.cpp
@@ -3,9 +3,13 @@
int main(int argc, char *argv[])
{
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
+
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/main.ico"));
diff --git a/tool/nettool/api/appdata.cpp b/tool/nettool/api/appdata.cpp
index a0c1789..7ad8454 100644
--- a/tool/nettool/api/appdata.cpp
+++ b/tool/nettool/api/appdata.cpp
@@ -85,7 +85,7 @@ void AppData::loadIP(QComboBox *cbox)
//获取本机所有IP
static QStringList ips;
if (ips.count() == 0) {
-#ifdef emsdk
+#ifdef Q_OS_WASM
ips << "127.0.0.1";
#else
QList netInterfaces = QNetworkInterface::allInterfaces();
diff --git a/tool/nettool/api/quihelper.cpp b/tool/nettool/api/quihelper.cpp
index 2b3eabf..516cffb 100644
--- a/tool/nettool/api/quihelper.cpp
+++ b/tool/nettool/api/quihelper.cpp
@@ -1,5 +1,6 @@
#include "quihelper.h"
+#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
int QUIHelper::getScreenIndex()
{
//需要对多个屏幕进行处理
@@ -57,6 +58,11 @@ int QUIHelper::deskHeight()
return getScreenRect().height();
}
+QSize QUIHelper::deskSize()
+{
+ return getScreenRect().size();
+}
+
QWidget *QUIHelper::centerBaseForm = 0;
void QUIHelper::setFormInCenter(QWidget *form)
{
@@ -77,6 +83,19 @@ void QUIHelper::setFormInCenter(QWidget *form)
form->move(movePoint);
}
+void QUIHelper::showForm(QWidget *form)
+{
+ setFormInCenter(form);
+
+ //判断宽高是否超过了屏幕分辨率,超过了则最大化显示
+ //qDebug() << TIMEMS << form->size() << deskSize();
+ if (form->width() + 20 > deskWidth() || form->height() + 50 > deskHeight()) {
+ form->showMaximized();
+ } else {
+ form->show();
+ }
+}
+
QString QUIHelper::appName()
{
//没有必要每次都获取,只有当变量为空时才去获取一次
@@ -101,12 +120,36 @@ QString QUIHelper::appPath()
#endif
}
-QString QUIHelper::getUuid()
+QList QUIHelper::colors = QList();
+QList QUIHelper::getColorList()
{
- QString uuid = QUuid::createUuid().toString();
- uuid.replace("{", "");
- uuid.replace("}", "");
- return uuid;
+ //备用颜色集合 可以自行添加
+ if (colors.count() == 0) {
+ colors << QColor(0, 176, 180) << QColor(0, 113, 193) << QColor(255, 192, 0);
+ colors << QColor(72, 103, 149) << QColor(185, 87, 86) << QColor(0, 177, 125);
+ colors << QColor(214, 77, 84) << QColor(71, 164, 233) << QColor(34, 163, 169);
+ colors << QColor(59, 123, 156) << QColor(162, 121, 197) << QColor(72, 202, 245);
+ colors << QColor(0, 150, 121) << QColor(111, 9, 176) << QColor(250, 170, 20);
+ }
+
+ return colors;
+}
+
+QStringList QUIHelper::getColorNames()
+{
+ QList colors = getColorList();
+ QStringList colorNames;
+ foreach (QColor color, colors) {
+ colorNames << color.name();
+ }
+ return colorNames;
+}
+
+QColor QUIHelper::getRandColor()
+{
+ QList colors = getColorList();
+ int index = getRandValue(0, colors.count(), true);
+ return colors.at(index);
}
void QUIHelper::initRand()
@@ -116,6 +159,82 @@ void QUIHelper::initRand()
srand(t.msec() + t.second() * 1000);
}
+float QUIHelper::getRandFloat(float min, float max)
+{
+ double diff = fabs(max - min);
+ double value = (double)(rand() % 100) / 100;
+ value = min + value * diff;
+ return value;
+}
+
+double QUIHelper::getRandValue(int min, int max, bool contansMin, bool contansMax)
+{
+ int value;
+#if (QT_VERSION <= QT_VERSION_CHECK(5,10,0))
+ //通用公式 a是起始值,n是整数的范围
+ //int value = a + rand() % n;
+ if (contansMin) {
+ if (contansMax) {
+ value = min + 0 + (rand() % (max - min + 1));
+ } else {
+ value = min + 0 + (rand() % (max - min + 0));
+ }
+ } else {
+ if (contansMax) {
+ value = min + 1 + (rand() % (max - min + 0));
+ } else {
+ value = min + 1 + (rand() % (max - min - 1));
+ }
+ }
+#else
+ if (contansMin) {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 0, max + 0);
+ }
+ } else {
+ if (contansMax) {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 1);
+ } else {
+ value = QRandomGenerator::global()->bounded(min + 1, max + 0);
+ }
+ }
+#endif
+ return value;
+}
+
+QStringList QUIHelper::getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat)
+{
+ //随机生成点坐标
+ QStringList points;
+ for (int i = 0; i < count; ++i) {
+ //0.00881415 0.000442928
+#if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
+ float lngx = QRandomGenerator::global()->bounded(dotLng);
+ float latx = QRandomGenerator::global()->bounded(dotLat);
+#else
+ float lngx = getRandFloat(dotLng / 10, dotLng);
+ float latx = getRandFloat(dotLat / 10, dotLat);
+#endif
+ //需要先用精度转换成字符串
+ QString lng2 = QString::number(mainLng + lngx, 'f', 8);
+ QString lat2 = QString::number(mainLat + latx, 'f', 8);
+ QString point = QString("%1,%2").arg(lng2).arg(lat2);
+ points << point;
+ }
+
+ return points;
+}
+
+QString QUIHelper::getUuid()
+{
+ QString uuid = QUuid::createUuid().toString();
+ uuid.replace("{", "");
+ uuid.replace("}", "");
+ return uuid;
+}
+
void QUIHelper::newDir(const QString &dirName)
{
QString strDir = dirName;
@@ -151,30 +270,68 @@ void QUIHelper::sleep(int msec)
void QUIHelper::setStyle()
{
//打印下所有内置风格的名字
- qDebug() << "Qt内置的样式" << QStyleFactory::keys();
+ qDebug() << TIMEMS << "QStyleFactory::keys" << QStyleFactory::keys();
+ //设置内置风格
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qApp->setStyle(QStyleFactory::create("Fusion"));
#else
qApp->setStyle(QStyleFactory::create("Cleanlooks"));
#endif
- //qApp->setPalette(QPalette("#FFFFFF"));
+
+ //设置指定颜色
+ QPalette palette;
+ palette.setBrush(QPalette::Window, QColor("#F0F0F0"));
+ qApp->setPalette(palette);
+}
+
+QFont QUIHelper::addFont(const QString &fontFile, const QString &fontName)
+{
+ //判断图形字体是否存在,不存在则加入
+ QFontDatabase fontDb;
+ if (!fontDb.families().contains(fontName)) {
+ int fontId = fontDb.addApplicationFont(fontFile);
+ QStringList listName = fontDb.applicationFontFamilies(fontId);
+ if (listName.count() == 0) {
+ qDebug() << QString("load %1 error").arg(fontName);
+ }
+ }
+
+ //再次判断是否包含字体名称防止加载失败
+ QFont font;
+ if (fontDb.families().contains(fontName)) {
+ font = QFont(fontName);
+#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
+ font.setHintingPreference(QFont::PreferNoHinting);
+#endif
+ }
+
+ return font;
}
void QUIHelper::setFont(int fontSize)
{
- QFont font;
- font.setFamily("MicroSoft Yahei");
-#ifdef Q_OS_ANDROID
- font.setPixelSize(15);
-#elif __arm__
- font.setPixelSize(25);
-#else
- font.setPixelSize(fontSize);
+#ifdef rk3399
+ return;
+#endif
+ //网页套件需要主动加载中文字体才能正常显示中文
+#ifdef Q_OS_WASM
+ QString fontFile = ":/font/DroidSansFallback.ttf";
+ QString fontName = "Droid Sans Fallback";
+ qApp->setFont(addFont(fontFile, fontName));
+ return;
#endif
-#ifndef rk3399
- qApp->setFont(font);
+#ifdef __arm__
+ fontSize = 25;
#endif
+#ifdef Q_OS_ANDROID
+ fontSize = 15;
+#endif
+
+ QFont font;
+ font.setFamily("MicroSoft Yahei");
+ font.setPixelSize(fontSize);
+ qApp->setFont(font);
}
void QUIHelper::setCode(bool utf8)
@@ -205,20 +362,23 @@ void QUIHelper::setTranslator(const QString &qmFile)
}
QTranslator *translator = new QTranslator(qApp);
- translator->load(qmFile);
- qApp->installTranslator(translator);
+ if (translator->load(qmFile)) {
+ qApp->installTranslator(translator);
+ }
}
-void QUIHelper::initAll()
+void QUIHelper::initAll(bool utf8, bool style, int fontSize)
{
//初始化随机数种子
QUIHelper::initRand();
- //设置样式风格
- QUIHelper::setStyle();
- //设置字体
- QUIHelper::setFont(13);
//设置编码
- QUIHelper::setCode();
+ QUIHelper::setCode(utf8);
+ //设置样式风格
+ if (style) {
+ QUIHelper::setStyle();
+ }
+ //设置字体
+ QUIHelper::setFont(fontSize);
//设置翻译文件支持多个
QUIHelper::setTranslator(":/qm/widgets.qm");
QUIHelper::setTranslator(":/qm/qt_zh_CN.qm");
@@ -299,7 +459,12 @@ QString QUIHelper::getXorEncryptDecrypt(const QString &value, char key)
key = 127;
}
+ //大概从5.9版本输出的加密密码字符串前面会加上 @String 字符
QString result = value;
+ if (result.startsWith("@String")) {
+ result = result.mid(8, result.length() - 9);
+ }
+
int count = result.count();
for (int i = 0; i < count; i++) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
@@ -331,6 +496,8 @@ uchar QUIHelper::getCheckCode(const QByteArray &data)
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit, bool stretchLast)
{
+ //设置弱属性用于应用qss特殊样式
+ tableView->setProperty("model", true);
//取消自动换行
tableView->setWordWrap(false);
//超出文本不显示省略号
@@ -374,7 +541,8 @@ void QUIHelper::openFile(const QString &fileName, const QString &msg)
#ifdef __arm__
return;
#endif
- if (fileName.isEmpty()) {
+ //文件不存在则不用处理
+ if (!QFile(fileName).exists()) {
return;
}
if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
@@ -401,8 +569,10 @@ bool QUIHelper::checkIniFile(const QString &iniFile)
QStringList list = line.split("=");
if (list.count() == 2) {
- if (list.at(1) == "") {
- qDebug() << "ini node no value" << list.at(0);
+ QString key = list.at(0);
+ QString value = list.at(1);
+ if (value.isEmpty()) {
+ qDebug() << TIMEMS << "ini node no value" << key;
ok = false;
break;
}
diff --git a/tool/nettool/api/quihelper.h b/tool/nettool/api/quihelper.h
index dc40547..96d037e 100644
--- a/tool/nettool/api/quihelper.h
+++ b/tool/nettool/api/quihelper.h
@@ -13,29 +13,52 @@ public:
//获取桌面宽度高度+居中显示
static int deskWidth();
static int deskHeight();
+ static QSize deskSize();
//居中显示窗体
//定义标志位指定是以桌面为参照还是主程序界面为参照
static QWidget *centerBaseForm;
static void setFormInCenter(QWidget *form);
+ static void showForm(QWidget *form);
//程序文件名称+当前所在路径
static QString appName();
static QString appPath();
- //获取uuid+初始化随机数种子+新建目录+延时
- static QString getUuid();
+ //获取内置颜色集合
+ static QList colors;
+ static QList getColorList();
+ static QStringList getColorNames();
+ //随机获取颜色集合中的颜色
+ static QColor getRandColor();
+
+ //初始化随机数种子
static void initRand();
+ //获取随机小数
+ static float getRandFloat(float min, float max);
+ //获取随机数,指定最小值和最大值
+ static double getRandValue(int min, int max, bool contansMin = false, bool contansMax = false);
+ //获取范围值随机经纬度集合
+ static QStringList getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat);
+
+ //获取uuid
+ static QString getUuid();
+ //可执行文件目录下新建目录
static void newDir(const QString &dirName);
+ //延时
static void sleep(int msec);
- //设置样式+字体+编码+居中+翻译
+ //设置Qt自带样式
static void setStyle();
- static void setFont(int fontSize = 12);
+ //设置字体
+ static QFont addFont(const QString &fontFile, const QString &fontName);
+ static void setFont(int fontSize = 12);
+ //设置编码
static void setCode(bool utf8 = true);
+ //设置翻译文件
static void setTranslator(const QString &qmFile);
//一次性设置所有
- static void initAll();
+ static void initAll(bool utf8 = true, bool style = true, int fontSize = 13);
//设置无边框
static void setFramelessForm(QWidget *widgetMain, bool tool = false, bool top = false, bool menu = true);
diff --git a/tool/nettool/form/frmmain.cpp b/tool/nettool/form/frmmain.cpp
index 94a5c94..39d771a 100644
--- a/tool/nettool/form/frmmain.cpp
+++ b/tool/nettool/form/frmmain.cpp
@@ -33,7 +33,7 @@ void frmMain::initForm()
ui->tabWidget->addTab(new frmWebClient, "WEB客户端");
ui->tabWidget->addTab(new frmWebServer, "WEB服务端");
#endif
-#ifdef emsdk
+#ifdef Q_OS_WASM
AppConfig::CurrentIndex = 4;
#endif
}
diff --git a/tool/nettool/form/frmtcpserver.cpp b/tool/nettool/form/frmtcpserver.cpp
index 421ad99..0cfa9f8 100644
--- a/tool/nettool/form/frmtcpserver.cpp
+++ b/tool/nettool/form/frmtcpserver.cpp
@@ -212,6 +212,8 @@ void frmTcpServer::on_btnListen_clicked()
if (isOk) {
append(0, "监听成功");
ui->btnListen->setText("关闭");
+ } else {
+ append(2, QString("监听失败: %1").arg(server->errorString()));
}
} else {
isOk = false;
diff --git a/tool/nettool/form/frmudpserver.cpp b/tool/nettool/form/frmudpserver.cpp
index b74a03d..78b4f8c 100644
--- a/tool/nettool/form/frmudpserver.cpp
+++ b/tool/nettool/form/frmudpserver.cpp
@@ -242,8 +242,10 @@ void frmUdpServer::on_btnListen_clicked()
if (ui->btnListen->text() == "监听") {
bool ok = socket->bind(QHostAddress(AppConfig::UdpListenIP), AppConfig::UdpListenPort);
if (ok) {
- ui->btnListen->setText("关闭");
append(0, "监听成功");
+ ui->btnListen->setText("关闭");
+ } else {
+ append(2, QString("监听失败: %1").arg(socket->errorString()));
}
} else {
socket->abort();
diff --git a/tool/nettool/form/frmwebserver.cpp b/tool/nettool/form/frmwebserver.cpp
index 0ade9df..05d856b 100644
--- a/tool/nettool/form/frmwebserver.cpp
+++ b/tool/nettool/form/frmwebserver.cpp
@@ -210,6 +210,8 @@ void frmWebServer::on_btnListen_clicked()
if (isOk) {
append(0, "监听成功");
ui->btnListen->setText("关闭");
+ } else {
+ append(2, QString("监听失败: %1").arg(server->errorString()));
}
} else {
isOk = false;
diff --git a/tool/nettool/main.cpp b/tool/nettool/main.cpp
index 88e8645..96951d8 100644
--- a/tool/nettool/main.cpp
+++ b/tool/nettool/main.cpp
@@ -3,9 +3,13 @@
int main(int argc, char *argv[])
{
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
+
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/main.ico"));
diff --git a/tool/nettool/nettool.pro b/tool/nettool/nettool.pro
index 40a4616..1f9e7c4 100644
--- a/tool/nettool/nettool.pro
+++ b/tool/nettool/nettool.pro
@@ -13,7 +13,6 @@ TARGET = nettool
TEMPLATE = app
RC_FILE = qrc/main.rc
wasm {
-DEFINES += emsdk
RESOURCES += qrc/font.qrc
} else {
DESTDIR = $$PWD/../bin
diff --git a/tool/nettool/qrc/font.qrc b/tool/nettool/qrc/font.qrc
index d28c6d2..1d77f67 100644
--- a/tool/nettool/qrc/font.qrc
+++ b/tool/nettool/qrc/font.qrc
@@ -1,5 +1,5 @@
- DroidSansFallback.ttf
+ font/DroidSansFallback.ttf
diff --git a/tool/nettool/qrc/DroidSansFallback.ttf b/tool/nettool/qrc/font/DroidSansFallback.ttf
similarity index 100%
rename from tool/nettool/qrc/DroidSansFallback.ttf
rename to tool/nettool/qrc/font/DroidSansFallback.ttf
diff --git a/tool/pngtool/main.cpp b/tool/pngtool/main.cpp
index e3cd0c4..52f8d8d 100644
--- a/tool/pngtool/main.cpp
+++ b/tool/pngtool/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/ui/flatui/main.cpp b/ui/flatui/main.cpp
index 3a02087..e44e938 100644
--- a/ui/flatui/main.cpp
+++ b/ui/flatui/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/ui/iconhelper/main.cpp b/ui/iconhelper/main.cpp
index 9bfc960..780e53f 100644
--- a/ui/iconhelper/main.cpp
+++ b/ui/iconhelper/main.cpp
@@ -11,7 +11,10 @@ int main(int argc, char *argv[])
//设置高分屏缩放舍入策略
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/ui/styledemo/main.cpp b/ui/styledemo/main.cpp
index 390c61b..5638191 100644
--- a/ui/styledemo/main.cpp
+++ b/ui/styledemo/main.cpp
@@ -13,10 +13,9 @@ int main(int argc, char *argv[])
#endif
QApplication a(argc, argv);
- //a.setFont(QFont("Microsoft Yahei", 9));
QFont font;
font.setFamily("Microsoft Yahei");
- font.setPixelSize(12);
+ font.setPixelSize(13);
a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
diff --git a/ui/uidemo01/form/frmmain.cpp b/ui/uidemo01/form/frmmain.cpp
index d36ab06..af2a4f4 100644
--- a/ui/uidemo01/form/frmmain.cpp
+++ b/ui/uidemo01/form/frmmain.cpp
@@ -40,11 +40,14 @@ void frmMain::initForm()
ui->widgetTitle->installEventFilter(this);
ui->widgetTitle->setProperty("form", "title");
ui->widgetTop->setProperty("nav", "top");
+
+ QFont font;
+ font.setPixelSize(25);
+ ui->labTitle->setFont(font);
ui->labTitle->setText("智能访客管理平台");
- ui->labTitle->setFont(QFont("Microsoft Yahei", 20));
this->setWindowTitle(ui->labTitle->text());
- ui->stackedWidget->setStyleSheet("QLabel{font:60pt;}");
+ ui->stackedWidget->setStyleSheet("QLabel{font:60px;}");
//单独设置指示器大小
int addWidth = 20;
@@ -55,22 +58,21 @@ void frmMain::initForm()
int borderWidth = 3;
QStringList qss;
- qss.append(QString("QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{width:%1px;}").arg(addWidth));
- qss.append(QString("QComboBox::down-arrow,QDateEdit[calendarPopup=\"true\"]::down-arrow,QTimeEdit[calendarPopup=\"true\"]::down-arrow,"
- "QDateTimeEdit[calendarPopup=\"true\"]::down-arrow{width:%1px;height:%1px;right:2px;}").arg(addHeight));
- qss.append(QString("QRadioButton::indicator{width:%1px;height:%1px;}").arg(rbtnWidth));
- qss.append(QString("QCheckBox::indicator,QGroupBox::indicator,QTreeWidget::indicator,QListWidget::indicator{width:%1px;height:%1px;}").arg(ckWidth));
- qss.append(QString("QScrollBar:horizontal{min-height:%1px;border-radius:%2px;}QScrollBar::handle:horizontal{border-radius:%2px;}"
- "QScrollBar:vertical{min-width:%1px;border-radius:%2px;}QScrollBar::handle:vertical{border-radius:%2px;}").arg(scrWidth).arg(scrWidth / 2));
- qss.append(QString("QWidget#widget_top>QToolButton:pressed,QWidget#widget_top>QToolButton:hover,"
- "QWidget#widget_top>QToolButton:checked,QWidget#widget_top>QLabel:hover{"
- "border-width:0px 0px %1px 0px;}").arg(borderWidth));
- qss.append(QString("QWidget#widgetleft>QPushButton:checked,QWidget#widgetleft>QToolButton:checked,"
- "QWidget#widgetleft>QPushButton:pressed,QWidget#widgetleft>QToolButton:pressed{"
- "border-width:0px 0px 0px %1px;}").arg(borderWidth));
+ qss << QString("QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{width:%1px;}").arg(addWidth);
+ qss << QString("QComboBox::down-arrow,QDateEdit[calendarPopup=\"true\"]::down-arrow,QTimeEdit[calendarPopup=\"true\"]::down-arrow,"
+ "QDateTimeEdit[calendarPopup=\"true\"]::down-arrow{width:%1px;height:%1px;right:2px;}").arg(addHeight);
+ qss << QString("QRadioButton::indicator{width:%1px;height:%1px;}").arg(rbtnWidth);
+ qss << QString("QCheckBox::indicator,QGroupBox::indicator,QTreeWidget::indicator,QListWidget::indicator{width:%1px;height:%1px;}").arg(ckWidth);
+ qss << QString("QScrollBar:horizontal{min-height:%1px;border-radius:%2px;}QScrollBar::handle:horizontal{border-radius:%2px;}"
+ "QScrollBar:vertical{min-width:%1px;border-radius:%2px;}QScrollBar::handle:vertical{border-radius:%2px;}").arg(scrWidth).arg(scrWidth / 2);
+ qss << QString("QWidget#widget_top>QToolButton:pressed,QWidget#widget_top>QToolButton:hover,"
+ "QWidget#widget_top>QToolButton:checked,QWidget#widget_top>QLabel:hover{"
+ "border-width:0px 0px %1px 0px;}").arg(borderWidth);
+ qss << QString("QWidget#widgetleft>QPushButton:checked,QWidget#widgetleft>QToolButton:checked,"
+ "QWidget#widgetleft>QPushButton:pressed,QWidget#widgetleft>QToolButton:pressed{"
+ "border-width:0px 0px 0px %1px;}").arg(borderWidth);
this->setStyleSheet(qss.join(""));
-
QSize icoSize(32, 32);
int icoWidth = 85;
diff --git a/ui/uidemo01/main.cpp b/ui/uidemo01/main.cpp
index 7da7e26..2609fa5 100644
--- a/ui/uidemo01/main.cpp
+++ b/ui/uidemo01/main.cpp
@@ -6,9 +6,13 @@ int main(int argc, char *argv[])
{
//设置不应用操作系统设置比如字体
QApplication::setDesktopSettingsAware(false);
-#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
- QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
#endif
+#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
+ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
+#endif
+
QApplication a(argc, argv);
AppInit::Instance()->start();
@@ -26,6 +30,7 @@ int main(int argc, char *argv[])
}
frmMain w;
+ w.resize(800, 600);
QUIHelper::setFormInCenter(&w);
w.show();
diff --git a/ui/uidemo08/form/frmmain.cpp b/ui/uidemo08/form/frmmain.cpp
index 0d84e2a..1d47c95 100644
--- a/ui/uidemo08/form/frmmain.cpp
+++ b/ui/uidemo08/form/frmmain.cpp
@@ -66,13 +66,15 @@ void frmMain::initForm()
ui->widgetTitle->setProperty("form", "title");
//关联事件过滤器用于双击放大
ui->widgetTitle->installEventFilter(this);
-
ui->widgetTop->setProperty("nav", "top");
+
+ QFont font;
+ font.setPixelSize(25);
+ ui->labTitle->setFont(font);
ui->labTitle->setText("智能访客管理平台");
- ui->labTitle->setFont(QFont("Microsoft Yahei", 20));
this->setWindowTitle(ui->labTitle->text());
- ui->stackedWidget->setStyleSheet("QLabel{font:60pt;}");
+ ui->stackedWidget->setStyleSheet("QLabel{font:60px;}");
QSize icoSize(32, 32);
int icoWidth = 85;
diff --git a/ui/uidemo08/main.cpp b/ui/uidemo08/main.cpp
index 6f2c79d..c484fa2 100644
--- a/ui/uidemo08/main.cpp
+++ b/ui/uidemo08/main.cpp
@@ -6,8 +6,11 @@ int main(int argc, char *argv[])
{
//设置不应用操作系统设置比如字体
QApplication::setDesktopSettingsAware(false);
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
- QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
+ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
AppInit::Instance()->start();
diff --git a/ui/uidemo09/main.cpp b/ui/uidemo09/main.cpp
index 83e86df..281e3fc 100644
--- a/ui/uidemo09/main.cpp
+++ b/ui/uidemo09/main.cpp
@@ -6,8 +6,11 @@ int main(int argc, char *argv[])
{
//设置不应用操作系统设置比如字体
QApplication::setDesktopSettingsAware(false);
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
- QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
+ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
AppInit::Instance()->start();
diff --git a/ui/uidemo10/main.cpp b/ui/uidemo10/main.cpp
index 56badb9..9507673 100644
--- a/ui/uidemo10/main.cpp
+++ b/ui/uidemo10/main.cpp
@@ -6,8 +6,11 @@ int main(int argc, char *argv[])
{
//设置不应用操作系统设置比如字体
QApplication::setDesktopSettingsAware(false);
+#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
+ QApplication::setAttribute(Qt::AA_Use96Dpi);
+#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
- QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
+ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
AppInit::Instance()->start();
diff --git a/video/playffmpeg/main.cpp b/video/playffmpeg/main.cpp
index d22ee79..8342eb6 100644
--- a/video/playffmpeg/main.cpp
+++ b/video/playffmpeg/main.cpp
@@ -9,7 +9,10 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/video/plaympv/main.cpp b/video/plaympv/main.cpp
index c29e982..90c31d0 100644
--- a/video/plaympv/main.cpp
+++ b/video/plaympv/main.cpp
@@ -6,7 +6,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/video/playvlc/main.cpp b/video/playvlc/main.cpp
index 840229a..e6f1306 100644
--- a/video/playvlc/main.cpp
+++ b/video/playvlc/main.cpp
@@ -6,7 +6,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/video/videobox/main.cpp b/video/videobox/main.cpp
index 0c3c1e4..86d9e93 100644
--- a/video/videobox/main.cpp
+++ b/video/videobox/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/video/videopanel/main.cpp b/video/videopanel/main.cpp
index eb8b611..c51a24c 100644
--- a/video/videopanel/main.cpp
+++ b/video/videopanel/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/video/videopanel/videopanel.cpp b/video/videopanel/videopanel.cpp
index 1c16e7e..8a089fb 100644
--- a/video/videopanel/videopanel.cpp
+++ b/video/videopanel/videopanel.cpp
@@ -81,6 +81,7 @@ void VideoPanel::initForm()
widget->installEventFilter(this);
widget->setFocusPolicy(Qt::StrongFocus);
widget->setAlignment(Qt::AlignCenter);
+ widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//二选一可以选择显示文字,也可以选择显示背景图片
widget->setText(QString("通道 %1").arg(i + 1));
diff --git a/video/videowidget/main.cpp b/video/videowidget/main.cpp
index 243dd30..61d0dbe 100644
--- a/video/videowidget/main.cpp
+++ b/video/videowidget/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/colorwidget/main.cpp b/widget/colorwidget/main.cpp
index 22a3116..da06ead 100644
--- a/widget/colorwidget/main.cpp
+++ b/widget/colorwidget/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/framelesswidget/main.cpp b/widget/framelesswidget/main.cpp
index a81f617..3d7f473 100644
--- a/widget/framelesswidget/main.cpp
+++ b/widget/framelesswidget/main.cpp
@@ -10,7 +10,10 @@ int main(int argc, char *argv[])
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/gifwidget/main.cpp b/widget/gifwidget/main.cpp
index a211f3c..6ff387c 100644
--- a/widget/gifwidget/main.cpp
+++ b/widget/gifwidget/main.cpp
@@ -12,7 +12,10 @@ int main(int argc, char *argv[])
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
a.setWindowIcon(QIcon(":/image/gifwidget.ico"));
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
diff --git a/widget/lunarcalendarwidget/main.cpp b/widget/lunarcalendarwidget/main.cpp
index e2b8f22..c96797c 100644
--- a/widget/lunarcalendarwidget/main.cpp
+++ b/widget/lunarcalendarwidget/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/maskwidget/main.cpp b/widget/maskwidget/main.cpp
index db5a396..a52e489 100644
--- a/widget/maskwidget/main.cpp
+++ b/widget/maskwidget/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/movewidget/main.cpp b/widget/movewidget/main.cpp
index f8e0d7f..2ae74aa 100644
--- a/widget/movewidget/main.cpp
+++ b/widget/movewidget/main.cpp
@@ -7,7 +7,10 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/screenwidget/main.cpp b/widget/screenwidget/main.cpp
index 32be8b1..d461f3a 100644
--- a/widget/screenwidget/main.cpp
+++ b/widget/screenwidget/main.cpp
@@ -11,7 +11,10 @@ int main(int argc, char *argv[])
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
#endif
QApplication a(argc, argv);
- a.setFont(QFont("Microsoft Yahei", 9));
+ QFont font;
+ font.setFamily("Microsoft Yahei");
+ font.setPixelSize(13);
+ a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
diff --git a/widget/widget.pro b/widget/widget.pro
index 8920bc2..80eff01 100644
--- a/widget/widget.pro
+++ b/widget/widget.pro
@@ -6,3 +6,10 @@ SUBDIRS += lunarcalendarwidget
SUBDIRS += maskwidget
SUBDIRS += movewidget
SUBDIRS += screenwidget
+
+#Qt6有些项目还不支持
+greaterThan(QT_MAJOR_VERSION, 5) {
+msvc {
+SUBDIRS -= lunarcalendarwidget
+}
+}