一、前言
日志查詢功能是基礎功能,主要分兩塊,一個是本地日志查詢,包括運行日志、報警日志、操作日志;一個是設備日志查詢,就是通過SDK去拉去NVR設備的日志信息,包括系統操作、配置操作、報警操作、錄像操作、文件操作、遠程操作、其他操作等,這些日志信息都是存儲在NVR設備上的,根據查詢的請求逐一返回日志信息到客戶端顯示。本地日志查詢一般是綁定數據庫表,然后設定查詢的條件,然后select結果即可,采用的是QTableView控件來顯示數據,而遠程設備的日志,根據查詢的結果自己處理分頁,用鏈表存儲起來,采用的是QTableWidget控件,兩個控件使用起來都很方便。
關於日志查詢、數據查詢之類的功能模塊,其實大部分系統都會用到,還有分頁功能,所以在這些年寫了這么多系統的過程中,早就封裝好了一套自定義的分頁組件,傳入表名、查詢條件、排序字段、排序規則,select以后就會自動分頁顯示,單擊上一頁、下一頁、第一頁、末一頁按鈕進行翻頁切換,同時還提供label來顯示當前第幾頁、共幾頁、每頁多少行、執行查詢耗時等,該組件完全開源。
分頁組件開源地址: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
二、功能特點
- 支持16畫面切換,全屏切換等,包括1+4+6+8+9+13+16畫面切換。
- 支持alt+enter全屏,esc退出全屏。
- 自定義信息框+錯誤框+詢問框+右下角提示框。
- 17套皮膚樣式隨意更換,所有樣式全部統一,包括菜單等。
- 雲台儀表盤鼠標移上去高亮,八個方位精准識別。
- 底部畫面工具欄(畫面分割切換+截圖聲音等設置)移上去高亮。
- 可在配置文件更改左上角logo+中文軟件名稱+英文軟件名稱。
- 封裝了百度地圖,三維切換,設備點位,鼠標按下獲取經緯度等。
- 堆棧窗體,每個窗體都是個單獨的qwidget,方便編寫自己的代碼。
- 頂部鼠標右鍵菜單,可動態控制時間CPU+左上角面板+左下角面板+右上角面板+右下角面板的顯示和隱藏,支持恢復默認布局。
- 工具欄可以放置多個小圖標和關閉圖標。
- 左側右側可拖動拉伸,並自動記憶寬高位置,重啟后恢復。
- 雙擊攝像機節點自動播放視頻,雙擊節點自動依次添加視頻,會自動跳到下一個,雙擊父節點自動添加該節點下的所有視頻。
- 攝像機節點拖曳到對應窗體播放視頻,同時支持拖曳本地文件直接播放。
- 視頻畫面窗體支持拖曳交換,瞬間響應。
- 雙擊節點+拖曳節點+拖曳窗體交換位置,均自動更新url.txt。
- 支持從url.txt中加載16通道視頻播放,自動記憶最后通道對應的視頻,軟件啟動后自動打開播放。
- 右下角音量條控件,失去焦點自動隱藏,音量條帶靜音圖標。
- 集成百度地圖,可以添加設備對應位置,自動生成地圖,支持縮放和三維地圖,提供地圖風格選擇,共12種風格。
- 視頻拖動到通道窗體外自動刪除視頻。
- 鼠標右鍵可刪除當前+所有視頻,截圖當前+所有視頻。
- 錄像機管理、攝像機管理,可添加刪除修改導入導出打印信息,立即應用新的設備信息生成樹狀列表,不需重啟。
- 在pro文件中可以自由開啟是否加載地圖。
- 視頻播放可選四種內核自由切換,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中設置。
- 可設置1+4+9+16畫面輪詢,可設置輪詢間隔以及輪詢碼流類型等,直接在主界面底部工具欄右側單擊啟動輪詢按鈕即可,再次單擊停止輪詢。
- 默認超過10秒鍾未操作自動隱藏鼠標指針。
- 支持onvif搜素設備,支持任意onvif攝像機,包括但不限於海康大華宇視天地偉業華為等,支持onvif雲台控制。
- 高度可定制化,用戶可以很方便的在此基礎上衍生自己的功能,支持linux系統。
三、效果圖
四、核心代碼
#include "frmloglocal.h"
#include "ui_frmloglocal.h"
#include "quiwidget.h"
#include "dbdelegate.h"
frmLogLocal::frmLogLocal(QWidget *parent) : QWidget(parent), ui(new Ui::frmLogLocal)
{
ui->setupUi(this);
this->initForm();
this->initData();
this->initIcon();
this->loadData();
}
frmLogLocal::~frmLogLocal()
{
delete ui;
}
void frmLogLocal::initForm()
{
for (int i = 1; i <= 16; i++) {
ui->cboxCh->addItem(QString("通道%1").arg(i));
}
QStringList type;
type << "運行日志" << "報警日志" << "操作日志";
ui->cboxType->addItems(type);
ui->dateTimeStart->setDate(QDate::currentDate());
ui->dateTimeEnd->setDate(QDate::currentDate().addDays(1));
ui->dateTimeStart->calendarWidget()->setLocale(QLocale::Chinese);
ui->dateTimeEnd->calendarWidget()->setLocale(QLocale::Chinese);
}
void frmLogLocal::initIcon()
{
quint32 size = 15;
quint32 pixWidth = 20;
quint32 pixHeight = 15;
QSize iconSize = QSize(pixWidth, pixHeight);
QPixmap pix1 = IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf002, size, pixWidth, pixHeight);
QPixmap pix2 = IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf1c3, size, pixWidth, pixHeight);
QPixmap pix3 = IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf00d, size, pixWidth, pixHeight);
QPixmap pix4 = IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf1f8, size, pixWidth, pixHeight);
ui->btnSelect->setIconSize(iconSize);
ui->btnExcel->setIconSize(iconSize);
ui->btnDelete->setIconSize(iconSize);
ui->btnClear->setIconSize(iconSize);
ui->btnSelect->setIcon(QIcon(pix1));
ui->btnExcel->setIcon(QIcon(pix2));
ui->btnDelete->setIcon(QIcon(pix3));
ui->btnClear->setIcon(QIcon(pix4));
foreach (DbDelegate *delegate, delegates) {
delegate->setTextColor(QUIConfig::TextColor);
delegate->setSelectBgColor(QUIConfig::NormalColorStart);
}
}
void frmLogLocal::initData()
{
QStringList headText;
headText << "標識" << "序號" << "時間" << "用戶" << "通道" << "類型" << "內容" << "備注";
ui->tableWidget->setColumnCount(headText.count());
ui->tableWidget->setHorizontalHeaderLabels(headText);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
//ui->tableWidget->setAlternatingRowColors(true);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget->horizontalHeader()->setFixedHeight(25);
ui->tableWidget->verticalHeader()->setDefaultSectionSize(25);
#if 1
//設置列寬
ui->tableWidget->setColumnWidth(0, 50);
ui->tableWidget->setColumnWidth(1, 60);
ui->tableWidget->setColumnWidth(2, 160);
ui->tableWidget->setColumnWidth(3, 120);
ui->tableWidget->setColumnWidth(4, 100);
ui->tableWidget->setColumnWidth(5, 100);
ui->tableWidget->setColumnWidth(6, 160);
ui->tableWidget->setColumnWidth(7, 50);
#else
//自適應列寬
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
ui->tableWidget->verticalHeader()->setResizeMode(QHeaderView::Stretch);
ui->tableWidget->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
#else
ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
#endif
//設置第一列委托,自動根據內容顯示不同圖標
DbDelegate *d_pixmap = new DbDelegate(this);
d_pixmap->setDelegateColumn(0);
d_pixmap->setDelegateType("QPixmap");
d_pixmap->setCheckColumn(6);
d_pixmap->setCheckType("contains");
d_pixmap->setCheckValue("離線|故障|報警");
d_pixmap->setCheckOkImage(IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf071, 15, 15, 15));
d_pixmap->setCheckNoImage(IconHelper::Instance()->getPixmap(QUIConfig::TextColor, 0xf06a, 15, 15, 15));
ui->tableWidget->setItemDelegateForColumn(0, d_pixmap);
delegates << d_pixmap;
}
void frmLogLocal::loadData()
{
QStringList content;
content << "設備上線" << "設備離線" << "設備正常" << "設備故障" << "設備報警";
QStringList type;
type << "運行日志" << "報警日志" << "操作日志";
QDateTime now = QDateTime::currentDateTime();
//設置行數+行高
int count = 30;
ui->tableWidget->setRowCount(count);
for (int i = 0; i < count; i++) {
now = now.addSecs(60 * 30 * i);
QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(i + 1));
QTableWidgetItem *item2 = new QTableWidgetItem(now.toString("yyyy-MM-dd HH:mm:ss"));
QTableWidgetItem *item3 = new QTableWidgetItem("admin");
QTableWidgetItem *item4 = new QTableWidgetItem(QString("通道%1").arg((qrand() % 16) + 1));
QTableWidgetItem *item5 = new QTableWidgetItem(type.at(qrand() % 3));
QTableWidgetItem *item6 = new QTableWidgetItem(content.at(qrand() % 5));
item1->setTextAlignment(Qt::AlignCenter);
item2->setTextAlignment(Qt::AlignCenter);
item3->setTextAlignment(Qt::AlignCenter);
//item4->setTextAlignment(Qt::AlignCenter);
item5->setTextAlignment(Qt::AlignCenter);
item6->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 1, item1);
ui->tableWidget->setItem(i, 2, item2);
ui->tableWidget->setItem(i, 3, item3);
ui->tableWidget->setItem(i, 4, item4);
ui->tableWidget->setItem(i, 5, item5);
ui->tableWidget->setItem(i, 6, item6);
}
}