一、前言

录像机管理模块,在本系统中除了用来存储NVR信息以外,方便生成对应的摄像机树状列表,目前没有其他用处,一个考虑是为了方便后期拓展,比如改成SDK内核加载视频流和回放视频等,甚至还需要做一些人脸识别之类的处理,这个就需要提供原始的NVR信息了,录像机信息主要包括名称、类型(厂家,后期用来决定区分采用何种协议)、IP地址、用户姓名、用户密码、启用状态、安装位置,其中用户信息用来登录NVR验证,安装位置用来统计或者生成设备分布图,或者上传到第三方的大平台需要上报经纬度安装位置等信息。

一般这种小数据量的表格,比较固定,而且数据量也不多,通常直接加载数据库表来显示,使用的是QSqlTableModel类,该类继承QSqlQueryModel,只需要设置一个表名即可加载,使用还是非常方便的,这里需要提的就是自定义委托,当设置好表格可以直接修改数据提交以后写入到数据库,多多少少该表中就需要用到自定义委托,比如提供下拉框选择数据、密码文本框、提供日期框选择日期时间、提供微调框设置整数浮点数等,为此特意封装了一个超级自定义委托类,该类每次使用只需要new即可,无需给每个表格控件都继承或者设置不一样的委托,该组件完全开源。

分页组件开源地址:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo

文件名称:dbpage

体验地址:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe

文件名称:bin_video_system.zip

二、功能特点

  1. 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。
  2. 支持alt+enter全屏,esc退出全屏。
  3. 自定义信息框+错误框+询问框+右下角提示框。
  4. 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
  5. 云台仪表盘鼠标移上去高亮,八个方位精准识别。
  6. 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。
  7. 可在配置文件更改左上角logo+中文软件名称+英文软件名称。
  8. 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。
  9. 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。
  10. 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。
  11. 工具栏可以放置多个小图标和关闭图标。
  12. 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。
  13. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。
  14. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
  15. 视频画面窗体支持拖曳交换,瞬间响应。
  16. 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。
  17. 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。
  18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
  19. 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。
  20. 视频拖动到通道窗体外自动删除视频。
  21. 鼠标右键可删除当前+所有视频,截图当前+所有视频。
  22. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
  23. 在pro文件中可以自由开启是否加载地图。
  24. 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。
  25. 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。
  26. 默认超过10秒钟未操作自动隐藏鼠标指针。
  27. 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。
  28. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。

三、效果图

四、核心代码

#include "frmconfignvr.h"
#include "ui_frmconfignvr.h"
#include "quiwidget.h"
#include "dbhelper.h"
#include "dbdelegate.h"
#include "excelapi.h"
#include "printapi.h"
#include "api.h" frmConfigNvr::frmConfigNvr(QWidget *parent) : QWidget(parent), ui(new Ui::frmConfigNvr)
{
ui->setupUi(this);
this->initForm();
this->initData();
} frmConfigNvr::~frmConfigNvr()
{
delete ui;
} void frmConfigNvr::initForm()
{
ui->widgetTop->setProperty("flag", "navbtn");
ui->labTip->setText("提示 → 必须和现场信息一致,改动后需重启应用");
API::initTableView(ui->tableView);
} void frmConfigNvr::initData()
{
model = new QSqlTableModel(this);
model->setTable("NvrInfo");
model->setSort(0, Qt::AscendingOrder);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select(); ui->tableView->setModel(model);
ui->tableView->setProperty("model", true); columnNames.clear();
columnNames << "编号" << "名称" << "类型" << "IP地址" << "用户姓名" << "用户密码" << "状态" << "安装位置"; columnWidths.clear();
columnWidths << 60 << 120 << 80 << 130 << 100 << 130 << 60 << 200; for (int i = 0; i < columnNames.count(); i++) {
model->setHeaderData(i, Qt::Horizontal, columnNames.at(i));
ui->tableView->setColumnWidth(i, columnWidths.at(i));
} //类型委托
DbDelegate *d_cbox_nvrType = new DbDelegate(this);
d_cbox_nvrType->setDelegateType("QComboBox");
d_cbox_nvrType->setDelegateValue(DBData::NvrTypes);
ui->tableView->setItemDelegateForColumn(2, d_cbox_nvrType); //用户密码委托
DbDelegate *d_txt_userPwd = new DbDelegate(this);
d_txt_userPwd->setDelegateType("QLineEdit");
d_txt_userPwd->setDelegatePwd(true);
d_txt_userPwd->setDelegateColumn(5);
ui->tableView->setItemDelegateForColumn(5, d_txt_userPwd); //状态委托
QStringList nvrEnable;
nvrEnable << "启用" << "禁用";
DbDelegate *d_cbox_nvrEnable = new DbDelegate(this);
d_cbox_nvrEnable->setDelegateType("QComboBox");
d_cbox_nvrEnable->setDelegateValue(nvrEnable);
ui->tableView->setItemDelegateForColumn(6, d_cbox_nvrEnable); //用来切换样式自动改变颜色
delegates << d_cbox_nvrType;
delegates << d_txt_userPwd;
delegates << d_cbox_nvrEnable;
} void frmConfigNvr::changeStyle()
{
foreach (DbDelegate *delegate, delegates) {
delegate->setTextColor(QUIConfig::TextColor);
delegate->setSelectBgColor(QUIConfig::NormalColorStart);
}
} void frmConfigNvr::on_btnAdd_clicked()
{
int count = model->rowCount();
model->insertRow(count); int nvrID = model->index(count - 1, 0).data().toInt() + 1;
QString nvrName = model->index(count - 1, 1).data().toString();
QString nvrType = model->index(count - 1, 2).data().toString();
QString nvrIP = model->index(count - 1, 3).data().toString();
QString userName = model->index(count - 1, 4).data().toString();
QString userPwd = model->index(count - 1, 5).data().toString();
QString nvrEnable = model->index(count - 1, 6).data().toString();
QString nvrAddr = model->index(count - 1, 7).data().toString(); if (nvrName.startsWith("录像机#")) {
nvrName = QString("录像机#%1").arg(nvrID);
} if (count == 0) {
nvrID = 1;
nvrName = "录像机#1";
nvrType = "海康";
nvrIP = "192.168.1.128";
userName = "admin";
userPwd = "admin";
nvrEnable = "启用";
nvrAddr = "录像机的安装位置";
} //设置新增加的行默认值
model->setData(model->index(count, 0), nvrID);
model->setData(model->index(count, 1), nvrName);
model->setData(model->index(count, 2), nvrType);
model->setData(model->index(count, 3), nvrIP);
model->setData(model->index(count, 4), userName);
model->setData(model->index(count, 5), userPwd);
model->setData(model->index(count, 6), nvrEnable);
model->setData(model->index(count, 7), nvrAddr);
ui->tableView->setCurrentIndex(model->index(count, 0));
} void frmConfigNvr::on_btnSave_clicked()
{
model->database().transaction();
if (model->submitAll()) {
model->database().commit();
DBHelper::loadNvrInfo();
emit nvrNameChanged();
} else {
model->database().rollback();
QUIHelper::showMessageBoxError("保存信息失败,信息不能为空,请重新填写!");
}
} void frmConfigNvr::on_btnDelete_clicked()
{
if (ui->tableView->currentIndex().row() < 0) {
QUIHelper::showMessageBoxError("请选择要删除的录像机!");
return;
} if (QUIHelper::showMessageBoxQuestion("确定要删除该录像机吗? 录像机对应的所有摄像机都会被删除!") == QMessageBox::Yes) {
int row = ui->tableView->currentIndex().row();
QString nvrName = model->index(row, 1).data().toString();
DBHelper::deleteIpcInfo(nvrName); model->removeRow(row);
model->submitAll();
ui->tableView->setCurrentIndex(model->index(model->rowCount() - 1, 0));
}
} void frmConfigNvr::on_btnReturn_clicked()
{
model->revertAll();
} void frmConfigNvr::on_btnClear_clicked()
{
if (model->rowCount() <= 0) {
return;
} if (QUIHelper::showMessageBoxQuestion("确定要清空所有录像机信息吗?") == QMessageBox::Yes) {
DBHelper::clearNvrInfo();
model->select();
}
} void frmConfigNvr::on_btnExcel_clicked()
{
QString name = "录像机信息";
QString fileName = QString("%1_%2").arg(name).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
QString file = API::getSaveFileNames(fileName, "Excel(*.xls)");
if (file.isEmpty()) {
return;
} QString columns = "*";
QString where = "order by NvrID asc";
QStringList content = DBHelper::getContent("NvrInfo", columns, where, "", ";"); int rowCount = content.count();
if (rowCount == 0) {
QUIHelper::showMessageBoxError("没有要处理的数据!");
return;
} QList<QString> columnNames = this->columnNames;
QList<int> columnWidths = this->columnWidths;
columnWidths[7] = 350; ExcelAPI::Instance()->saveExcel(file, name, name, "", columnNames, columnWidths, content);
QString msg = QString("导出%1到Excel").arg(name);
DBHelper::addUserLog("用户操作", msg); if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
QString url = QString("file:///%1").arg(file);
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
}
} void frmConfigNvr::on_btnPrint_clicked()
{
QString name = "录像机信息";
QString columns = "*";
QString where = "order by NvrID asc";
QStringList content = DBHelper::getContent("NvrInfo", columns, where, "", ";"); int rowCount = content.count();
if (rowCount == 0) {
QUIHelper::showMessageBoxError("没有要处理的数据!");
return;
} QList<QString> columnNames = this->columnNames;
QList<int> columnWidths = this->columnWidths;
columnWidths[7] = 350; PrintAPI::Instance()->print(name, "", columnNames, columnWidths, content, true);
QString msg = QString("打印%1").arg(name);
DBHelper::addUserLog("用户操作", msg);
}

Qt编写安防视频监控系统20-录像机管理的更多相关文章

  1. Qt编写安防视频监控系统(界面很漂亮)

    一.前言 视频监控系统在整个安防领域,已经做到了烂大街的程序,全国起码几百家公司做过类似的系统,当然这一方面的需求量也是非常旺盛的,各种定制化的需求越来越多,尤其是这几年借着人脸识别的东风,发展更加迅 ...

  2. Qt编写安防视频监控系统11-动态换肤

    一.前言 Qt中的动态换肤技术是非常一流的,直接调用qApp->setStyleSheet(qss);就可以对整个应用程序进行换肤,如果样式表内容不多,或者对应的贴图不对,效率还是蛮好的,不过据 ...

  3. Qt编写安防视频监控系统7-全屏切换

    一.前言 全屏切换这个功能点属于简单的,一般会做到右键菜单中,也提供了快捷键比如alt+enter来触发,恢复全屏则按esc即可,全屏处理基本上都是隐藏通道面板以外的窗体,保持最大化展示,由于采用了模 ...

  4. Qt编写安防视频监控系统5-视频回放

    一.前言 一般视频回放都会采用GB28181国标来处理,这样可以保证兼容国内各大厂家的NVR,毕竟在同一的国家标准下,大家都会统一支持国标的,就不需要根据各个厂家的SDK来做兼容处理,烦得很,厂家越来 ...

  5. Qt编写安防视频监控系统18-云台控制

    一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂 ...

  6. Qt编写安防视频监控系统12-异形布局

    一.前言 视频监控系统中,除了常规的1画面.4画面.9画面.16画面以外,还有几个布局比较另类,比如6画面.8画面.13画面,有些通道需要占据不同的行列,4画面.9画面.16画面都是非常对称的布局,行 ...

  7. Qt编写安防视频监控系统9-自动隐藏光标

    一.前言 这个效果的灵感来自于大屏电子看板系统,在很多系统中尤其是上了大屏的时候,其实在用户不在操作的时候,是很不希望看到那个鼠标箭头指针的,只有当用户操作的时候才显示出来,这个就需要开个定时器定时计 ...

  8. Qt编写安防视频监控系统8-双击节点

    一.前言 在所有的视频监控系统中,双击摄像机的节点,对应摄像机加载到当前焦点通道显示,这个都是必须具备的功能,还有一些厂家会做双击NVR节点,自动加载该NVR下的所有摄像机全部显示,从通道1开始到通道 ...

  9. Qt编写安防视频监控系统3-通道交换

    一.前言 最开始写通道交换的功能的时候,走了很多弯路,比如最开始用最初级的办法,触发交换的时候,先关闭视频,然后设置新的url重新打开视频,这样处理非常低级而且耗内存还卡还很慢,毕竟重新打开视频都需要 ...

  10. Qt编写安防视频监控系统1-通道切换

    一.前言 通道切换在视频监控系统中是最基础的必备功能,一般都会提供1通道+4通道+6通道+8通道+9通道+16通道这几个通道切换,可能做得比较好的还会提供24通道+32通道的,这个可能对电脑的配置就有 ...

随机推荐

  1. KubeSphere 部署 Kafka 集群实战指南

    本文档将详细阐述如何利用 Helm 这一强大的工具,快速而高效地在 K8s 集群上安装并配置一个 Kafka 集群. 实战服务器配置(架构 1:1 复刻小规模生产环境,配置略有不同) 主机名 IP C ...

  2. 云原生周刊:2024 年 K8s 基准报告 | 2024.4.8

    开源项目推荐 Argo CD Image Updater Argo CD Image Updater 是一个自动更新 Argo CD 管理的 Kubernetes 工作负载容器镜像的工具.简而言之,它 ...

  3. 有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?

    本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式.既然,已经有了 Redis 可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看. 为什么需要本地缓存? 尽管已经有 Redis ...

  4. Webstorm 2024 安装使用 (附加永久激活码、补丁)

    下载安装 第二步,安装完成之后,下载补丁 下载地址(里面包含激活码) 完成,之后输入激活码 免责声明:本文中的资源均来自互联网,仅供个人学习和交流使用,严禁用于商业行为,下载后请在24小时内从电脑中彻 ...

  5. CSPS2024题目总结

    T1 决斗 签到题,考场上10min就做出来了. 我的方法是排序之后贪心打怪,就是用尽量小的怪去打现在场上最小的怪.用一个同侧双指针实现. \(O(nlogn)\). 另一种方法注意到了值域很小,可以 ...

  6. 部署个SSH蜜罐玩玩,又能增强安全性,又能当电子蛐蛐

    前言 最近有个旧服务器的 SSL 证书过期了,每次都申请 SSL 证书太麻烦了,我直接把 swag 方案部署上去. 然后发现这个服务器在安全方面有所疏忽,所以又加固了一下,SSH 部分我想起来之前用过 ...

  7. 本文是第一篇在GitHub仓库中撰写的.md格式的blog文件

    正文内容: 具体内容,只是未来测试,给出福利: 模板格式: title: 博文标题 description: 博文摘要 #多个标签请使用英文逗号分隔或使用数组语法 tags: 标签1, 标签2 #多个 ...

  8. 根据docker镜像反推dockerfile

    Dockerfile 是一个文本文件,其中包含我们为了构建 Docker 镜像而手动执行的所有命令. Docker 可以从 Dockerfile 中读取指令来自动构建镜像.我们可以使用 docker ...

  9. C++之OpenCV入门到提高005:005 图像操作

    一.介绍 今天是这个系列<C++之 Opencv 入门到提高>得第五篇文章.这篇文章也不难,介绍如何图像的基本操作,比如:读取一张图片的像素值,如何修改一张图片中的像素值,如何读取一张图片 ...

  10. 一条语句查看web日志排名前十的IP/URL页面及总数

    查看 Nginx web 访问日志访问量前十的ip 以及访问的网站页面地址 ,可以分析网站哪些页面受欢迎,以及访问量大的ip在干什么! 标签: <无> 代码片段(3)[全屏查看所有代码] ...