Введение
В системе должно быть много параметров конфигурации, хранящихся в файле конфигурации.Файл конфигурации может быть ini-файлом, json-файлом или текстовым файлом в произвольном формате.Я рекомендую ini-файл, потому что это очень удобно для чтения и записи узлов., поддерживает китайский контент, могут храниться различные встроенные в Qt типы данных, даже включая QByteArray, например, файл макета может храниться непосредственно в конфигурационном файле, представляющем собой набор непонятных символов. вы решили сохранить его в файле json, который люди не могут прочитать напрямую.
С увеличением функций, параметров узла, соответствующих конфигурационным файлам, становится все больше, и то же самое верно и для системы мониторинга.Помню, что в первой версии было всего около десяти параметров (название, операция запуска, интерфейс стиль и т.д.) В этой части основных настроек имеется десять переключателей, поэтому в процессе непрерывной итерации параметры конфигурации непрерывно делятся на категории и группы для хранения параметров конфигурации, что удобно для управления и легко читается и понять код.В основном интерфейсе разные группы соответствуют разным QGroupBox, поле группы соответствует настройке каждого параметра, переключатель может быть обозначен кнопкой переключения, а другие могут быть текстовыми полями и выпадающими окнами .
Мне нравится читать и записывать параметры конфигурации в отдельный класс, и при этом преобразовывать значения параметров конфигурации в соответствующие глобальные переменные.Это очень круто использовать.Большую часть параметров нужно использовать в более чем в одном месте.Очень эффективно делать маппинг с глобальными переменными.Высокий,класс параметров конфигурации,параметры конфигурации всей системы хранятся в ini файле,кроссплатформенность,все параметры соответствуют переменной,при чтении параметры конфигурации, присвойте значение переменной, при записи запишите значение переменной в документ конфигурации. Для того, чтобы изменение параметров можно было применить сразу (очень немногие нуждаются в автоматическом перезапуске приложения, например смена режима работы), при изменении параметра специально отправляется соответствующий сигнал, а место получения сигнала можно изменяться автоматически.
Описание основных параметров
- Операция запуска: после включения она автоматически запускается при запуске системы и включена по умолчанию.
- Автоматический вход: после включения он будет автоматически входить в систему с информацией о последнем вошедшем в систему пользователе, и по умолчанию он отключен.
- Запомнить пароль: если этот параметр включен, информация о последнем вошедшем в систему пользователе будет автоматически заполняться в форме входа, и по умолчанию эта функция отключена.
- Китайское название: китайское название строки заголовка в верхнем левом углу программного обеспечения, изменения будут применены немедленно.
- Английское название: английское название строки заголовка в верхнем левом углу программного обеспечения, изменения будут применены немедленно.
- Авторское право: Компания, которая владеет текущим авторским правом на программное обеспечение, где оно в настоящее время не отображается, запасное.
- Полноэкранный режим: если этот параметр включен, развернутый дисплей автоматически отображается в полноэкранном режиме вместо развернутого. По умолчанию он отключен.
- Полноэкранная адаптация: после включения автоматически использует метод перемещения на один пиксель вверх для устранения ошибки opengl.
- Значок программного обеспечения: автоматически считывается из папки с логотипом, вы можете выбрать соответствующий файл логотипа самостоятельно.
- Стиль интерфейса: Система поставляется с 17 наборами скинов, которые можно автоматически менять здесь, а видео по умолчанию черное.
- Режим работы: видеонаблюдение по умолчанию, дополнительное наблюдение за роботом, наблюдение с помощью дрона и т. д.
- Стиль навигации: используется для выбора стиля верхней панели навигации и левой панели навигации, верхняя сторона + левая сторона означает стиль верхней стороны верхней панели навигации (значок вверху, текст внизу), стиль слева левой панели навигации (иконка слева, текст справа).
- Время всплывающего окна: всплывающее сообщение в правом нижнем углу автоматически закрывает время. 0 секунд означает, что оно не будет закрыто навсегда.
- Звук будильника: 0 означает, что не включено, остальные означают количество звуков, воспроизводимых после будильника.
- Скрытие мыши: основной интерфейс автоматически скроет указатель мыши, если мышь не использовалась в течение длительного времени.Как правило, это необходимо установить во время полноэкранного опроса, и эффект будет лучше.
- Автоматический полноэкранный режим: мышь долгое время не работала в автоматическом полноэкранном режиме, 0 означает, что режим не включен.
- Запасной переключатель: зарезервирован для последующего использования.
- Picture alarm: номер сообщения графического полицейского модуля, 0 означает, что автоматический расчет выполнен, и полоса прокрутки не создается.
- Сообщение окна: номер строки сообщения модуля сообщений окна, 0 указывает, что автоматический расчет заполнен, и полоса прокрутки не создается.
- Значение прозрачности: значение прозрачности закрепленной формы, которое можно регулировать и применять динамически.
2. Особенности
(1) Программный модуль
- Модуль видеомониторинга, различные подмодули стыковки небольших окон, включая список устройств, графическую сигнализацию, информацию об окне, управление PTZ, предустановленное положение, настройку круиза, управление устройством, плавающую карту, просмотр веб-страниц и т. д.
- Модуль воспроизведения видео, включая локальное воспроизведение, удаленное воспроизведение, воспроизведение на устройстве, воспроизведение изображений, загрузку видео и т. д.
- Модуль электронной карты, включая карту изображений, онлайн-карту, автономную карту, планирование маршрута и т. д.
- Модуль запроса журнала, включая локальные журналы, журналы устройств и т. д.
- Модуль системных настроек, включая системные настройки (основные настройки, параметры видео, настройки базы данных, конфигурация карты, конфигурация последовательного порта и т. д.), управление регистратором, управление камерой, конфигурация опроса, управление пользователями и т. д.
(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, включая поиск устройств, управление PTZ, управление устройствами (параметры изображения, время проверки, перезагрузка системы, моментальные снимки и т. д.).
- Поддержка управления разрешениями, разные пользователи могут соответствовать разным разрешениям модуля, таким как удаление журналов, завершение работы системы и т. д.
- База данных поддерживает различные базы данных, включая sqlite, mysql, sqlserver, postgresql, oracle, NPC Jincang и т. д.
- Локальная USB-камера поддерживает установку таких параметров, как разрешение и частота кадров.
- Все модули стыковки автоматически генерируют соответствующие меню для управления отображением и скрытием, которые можно открыть, щелкнув правой кнопкой мыши строку заголовка.
- Поддержка отображения всех модулей, скрытия всех модулей, сброса обычного макета, сброса полноэкранного макета.
- Дважды щелкните устройство, чтобы отобразить видео для предварительного просмотра в реальном времени, поддержку графических карт, онлайн-карт, автономных карт и т. д.
- Перетащите узел камеры в соответствующее окно, чтобы воспроизвести видео, и поддержите перетаскивание локальных файлов для прямого воспроизведения.
- Удаление видео поддерживается несколькими способами, такими как щелчок правой кнопкой мыши, закрытие полосы приостановки для удаления и перетаскивание видео за пределы панели видеонаблюдения для удаления.
- Кнопку устройства на карте изображения можно свободно перетаскивать, и информация о местоположении автоматически сохраняется. На карте Baidu вы можете щелкнуть мышью, чтобы получить информацию о широте и долготе, которая используется для обновления местоположения устройства.
- Любой канал в окне панели видеонаблюдения поддерживает перетаскивание и мгновенный отклик.
- Он включает в себя карту Baidu, переключение видов, отслеживание движения, точку устройства, нажатие мыши для получения широты и долготы и т. д.
- Двойной щелчок по узлу, перетаскивание узла, перетаскивание окна для обмена позициями и т. д. автоматически обновит и сохранит последний адрес воспроизведения, и программа автоматически применит его в следующий раз.
- Полоса громкости в правом нижнем углу автоматически скрывается, когда фокус теряется, а на полосе громкости есть значок отключения звука.
- Поддерживает скриншоты видео, вы можете указать один или все каналы для создания скриншотов, а также есть кнопка скриншота на небольшой панели инструментов внизу.
- Поддерживает автоматическое скрытие указателя мыши с течением времени, автоматический полноэкранный механизм.
- Поддержка onvif управления PTZ, может перемещать PTZ-камеру вверх, вниз, влево и вправо, включая сброс и регулировку фокуса.
- Поддержка любой камеры onvif, включая, помимо прочего, Hikvision, Dahua, Uniview, Tiandiweiye, Huawei и т. д.
- Видео может быть сохранено, дополнительное хранение времени или хранение одного файла, дополнительный интервал хранения.
- Вы можете установить режим передачи видеопотока tcp+udp, и вы можете установить декодирование видео на приоритет скорости, приоритет качества, выравнивание и т. д.
- Можно установить китайское название, английское название, значок LOGO и т. д. программного обеспечения.
- Сохраненные видеофайлы можно экспортировать в указанный каталог и загружать на сервер партиями.
(3) Особенности
- Основной интерфейс принимает режим формы стыковки, различные компоненты добавляются в виде небольших модулей, и любой модуль можно добавить, настроив его.
- Стыковочный модуль можно встроить и подвесить в любом месте путем перетаскивания, он поддерживает развертывание на весь экран и поддержку нескольких экранов.
- Механизм хранения файлов с двойной компоновкой, нормальный режим и полноэкранный режим соответствуют разным схемам компоновки, автоматически переключаются и сохраняются.Например, полноэкранный режим может выделять несколько модулей и отображать их прозрачно в назначенных позициях, что является более современным и научная фантастика.
- Оригинальный механизм протокола onvif, использующий базовый анализ протокола (поиск широковещательной рассылки udp + команда выполнения http-запроса), легче, проще для понимания, прост в освоении и расширении и не зависит от каких-либо сторонних компонентов, таких как gsoap.
- Исходный механизм импорта и экспорта данных, который не зависит от каких-либо компонентов на разных платформах, может экспортировать данные мгновенно.
- Благодаря встроенному множеству оригинальных компонентов вселенная очень ценна, включая компоненты импорта и экспорта данных (экспорт в xls, pdf, печать), компоненты базы данных (поток управления базой данных, поток автоматической очистки данных, универсальный пейджинг, запрос данных и т. д.) , компонент карты , компоненты видеонаблюдения, компоненты файлового многопоточного трансивера, компоненты связи onvif, общие компоненты ядра браузера и т. д.
- Пользовательское информационное окно + окно ошибки + окно запроса + окно подсказки в правом нижнем углу (включая несколько форматов) и т. д.
- Изысканная замена скинов, до 17 наборов стилей скинов можно заменить по желанию, все стили унифицированы, включая меню и т.д.
- Панель приостановки управления видео может добавлять несколько кнопок сама по себе, а небольшая панель инструментов в нижней части интерфейса мониторинга также может добавлять кнопки сама по себе.
- Дважды щелкните узел камеры, чтобы автоматически воспроизвести видео, дважды щелкните узел, чтобы автоматически добавить видео по порядку и автоматически перейти к следующему, и дважды щелкните родительский узел, чтобы автоматически добавить все видео под узлом. Основной поток и дополнительный поток являются необязательными.
- Управление рекордером, управление камерой, можно добавлять, удалять, изменять, импортировать и экспортировать информацию о печати, а также немедленно применять новую информацию об устройстве для создания древовидного списка без перезапуска.
- Различные ядра можно свободно переключать, ffmpeg, vlc, mpv и т. д. можно установить в pro. Рекомендуется использовать ffmpeg, который является наиболее кроссплатформенным, по умолчанию предоставляются скомпилированные библиотеки для linux и mac платформ.
- Поддержка жесткого декодирования, вы можете установить тип жесткого декодирования (qsv, dxva2, d3d11va и т. д.).
- По умолчанию для отрисовки видео используется opengl, который имеет сверхнизкое потребление ресурсов ЦП и поддерживает для отрисовки форматы yuyv и nv12, что очень мощно.
- Обладая широкими возможностями настройки, пользователи могут легко создавать на этой основе свои собственные функции, такие как добавление пользовательских модулей, добавление режимов работы, мониторинг роботов, мониторинг дронов, мониторинг экскаваторов и т. д.
- Поддержка xp, win7, win10, linux, mac, различных отечественных систем (UOS, win kylin, galaxy kylin и т. д.), встроенных linux и других систем.
- Полные комментарии, четкая структура проекта, очень подробное и полное руководство по использованию и разработке, точное функциональное описание каждого файла кода и непрерывные итерационные версии.
3. Адрес опыта
- Адрес опыта:disk.baidu.com/is/1's 7TH_GE Y…Код извлечения: 01jf Имя файла: bin_video_system.zip.
- Внутренний сайт:git ee.com/летающий свет…
- Международный сайт:GitHub.com/Летающий свет…
- Домашняя страница:blog.CSDN.net/Летающий свет…
- Знать домашнюю страницу:уууууу. call.com/people/fee…
- Онлайн-документация:Демонстрация виджета Feiyangqingyun.git ee.IO/Q…
В-четвертых, карта эффектов
Пять, основной код
void frmConfigSystem::initAppConfig1()
{
QStringList styleNames, styleFiles;
QUIStyle::getStyle(styleNames, styleFiles);
for (int i = 0; i < styleNames.count(); i++) {
ui->cboxStyleName->addItem(styleNames.at(i), styleFiles.at(i));
}
ui->cboxStyleName->setCurrentIndex(ui->cboxStyleName->findData(AppConfig::StyleName));
connect(ui->cboxStyleName, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig1()));
ui->txtCopyright->setText(AppConfig::Copyright);
connect(ui->txtCopyright, SIGNAL(textChanged(QString)), this, SLOT(saveAppConfig1()));
ui->txtTitleCn->setText(AppConfig::TitleCn);
connect(ui->txtTitleCn, SIGNAL(textChanged(QString)), this, SLOT(saveAppConfig1()));
ui->txtTitleEn->setText(AppConfig::TitleEn);
connect(ui->txtTitleEn, SIGNAL(textChanged(QString)), this, SLOT(saveAppConfig1()));
//设置移到 最左侧不然文字长了默认会在右边
ui->txtCopyright->setCursorPosition(0);
ui->txtTitleCn->setCursorPosition(0);
ui->txtTitleEn->setCursorPosition(0);
//从logo目录下加载所有图片
QDir dir(QUIHelper::appPath() + "/logo");
QStringList fileNames = dir.entryList(QStringList() << "*.png");
foreach (QString fileName, fileNames) {
ui->cboxLogoImage->addItem(fileName.split(".").first());
}
//如果一个都没有则添加一个空的防止配置文件被重置
if (fileNames.count() == 0) {
ui->cboxLogoImage->addItem(AppConfig::LogoImage);
}
ui->cboxLogoImage->setCurrentIndex(ui->cboxLogoImage->findText(AppConfig::LogoImage));
connect(ui->cboxLogoImage, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig1()));
}
void frmConfigSystem::saveAppConfig1()
{
int styleIndex = ui->cboxStyleName->currentIndex();
QString styleName = ui->cboxStyleName->itemData(styleIndex).toString();
if (AppConfig::StyleName != styleName) {
AppConfig::StyleName = styleName;
AppStyle::initStyle();
AppEvent::Instance()->slot_changeStyle();
}
QString company = ui->txtCopyright->text().trimmed();
if (AppConfig::Copyright != company) {
AppConfig::Copyright = company;
AppEvent::Instance()->slot_changeTitleInfo();
}
QString titleCn = ui->txtTitleCn->text().trimmed();
if (AppConfig::TitleCn != titleCn) {
AppConfig::TitleCn = titleCn;
AppEvent::Instance()->slot_changeTitleInfo();
}
QString titleEn = ui->txtTitleEn->text().trimmed();
if (AppConfig::TitleEn != titleEn) {
AppConfig::TitleEn = titleEn;
AppEvent::Instance()->slot_changeTitleInfo();
}
QString logoImage = ui->cboxLogoImage->currentText().trimmed();
if (AppConfig::LogoImage != logoImage) {
AppConfig::LogoImage = logoImage;
AppEvent::Instance()->slot_changeLogo();
}
AppConfig::writeConfig();
}
void frmConfigSystem::initAppConfig2()
{
QStringList listWorkMode;
listWorkMode << "视频监控" << "机器人监控" << "无人机监控";
ui->cboxWorkMode->addItems(listWorkMode);
ui->cboxWorkMode->setCurrentIndex(AppConfig::WorkMode);
connect(ui->cboxWorkMode, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
//ui->cboxWorkMode->setEnabled(AppConfig::WorkMode != 1);
QStringList listNavStyle;
listNavStyle << "左侧+左侧" << "左侧+上侧" << "上侧+左侧" << "上侧+上侧";
ui->cboxNavStyle->addItems(listNavStyle);
ui->cboxNavStyle->setCurrentIndex(AppConfig::NavStyle);
connect(ui->cboxNavStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
QStringList listTime;
listTime << "0秒钟" << "10秒钟" << "20秒钟" << "30秒钟" << "60秒钟" << "120秒钟";
ui->cboxTimeHideCursor->addItems(listTime);
QString timeHideCursor = QString("%1秒钟").arg(AppConfig::TimeHideCursor);
ui->cboxTimeHideCursor->setCurrentIndex(ui->cboxTimeHideCursor->findText(timeHideCursor));
connect(ui->cboxTimeHideCursor, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
ui->cboxTimeAutoFull->addItems(listTime);
QString timeAutoFull = QString("%1秒钟").arg(AppConfig::TimeAutoFull);
ui->cboxTimeAutoFull->setCurrentIndex(ui->cboxTimeAutoFull->findText(timeAutoFull));
connect(ui->cboxTimeAutoFull, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
QStringList listCount;
listCount << "0次" << "1次" << "3次" << "5次" << "10次" << "20次" << "50次" << "100次";
ui->cboxAlarmSoundCount->addItems(listCount);
QString alarmSoundCount = QString("%1次").arg(AppConfig::AlarmSoundCount);
ui->cboxAlarmSoundCount->setCurrentIndex(ui->cboxAlarmSoundCount->findText(alarmSoundCount));
connect(ui->cboxAlarmSoundCount, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
QStringList msgCount;
msgCount << "0行" << "1行" << "3行" << "5行" << "10行" << "15行" << "20行" << "25行" << "30行" << "50行";
ui->cboxMsgListCount->addItems(msgCount);
QString msgListCount = QString("%1行").arg(AppConfig::MsgListCount);
ui->cboxMsgListCount->setCurrentIndex(ui->cboxMsgListCount->findText(msgListCount));
connect(ui->cboxMsgListCount, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
ui->cboxMsgTableCount->addItems(msgCount);
QString msgTableCount = QString("%1行").arg(AppConfig::MsgTableCount);
ui->cboxMsgTableCount->setCurrentIndex(ui->cboxMsgTableCount->findText(msgTableCount));
connect(ui->cboxMsgTableCount, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
ui->labWindowOpacityValue->setText(QString::number(AppConfig::WindowOpacity));
ui->sliderWindowOpacity->setValue(AppConfig::WindowOpacity);
ui->sliderWindowOpacity->setRange(10, 100);
connect(ui->sliderWindowOpacity, SIGNAL(valueChanged(int)), this, SLOT(saveAppConfig2()));
QStringList listTipInterval;
listTipInterval << "0秒钟" << "3秒钟" << "5秒钟" << "10秒钟" << "20秒钟" << "30秒钟" << "60秒钟" << "120秒" << "10000秒钟";
ui->cboxTipInterval->addItems(listTipInterval);
QString tipInterval = QString("%1秒钟").arg(AppConfig::TipInterval);
ui->cboxTipInterval->setCurrentIndex(ui->cboxTipInterval->findText(tipInterval));
connect(ui->cboxTipInterval, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAppConfig2()));
}
void frmConfigSystem::saveAppConfig2()
{
int workMode = ui->cboxWorkMode->currentIndex();
if (AppConfig::WorkMode != workMode) {
//先要发个退出信号出去通知我要准备退出啦
AppEvent::Instance()->slot_exitAll();
AppConfig::WorkMode = workMode;
AppConfig::writeConfig();
AppFun::reboot();
}
int navStyle = ui->cboxNavStyle->currentIndex();
if (AppConfig::NavStyle != navStyle) {
//先要发个退出信号出去通知我要准备退出啦
AppEvent::Instance()->slot_exitAll();
AppConfig::NavStyle = navStyle;
AppConfig::writeConfig();
AppFun::reboot();
}
QString timeHideCursor = ui->cboxTimeHideCursor->currentText();
AppConfig::TimeHideCursor = timeHideCursor.mid(0, timeHideCursor.length() - 2).toInt();
QString timeAutoFull = ui->cboxTimeAutoFull->currentText();
AppConfig::TimeAutoFull = timeAutoFull.mid(0, timeAutoFull.length() - 2).toInt();
QString alarmSoundCount = ui->cboxAlarmSoundCount->currentText();
AppConfig::AlarmSoundCount = alarmSoundCount.mid(0, alarmSoundCount.length() - 1).toInt();
QString msgListCount = ui->cboxMsgListCount->currentText();
AppConfig::MsgListCount = msgListCount.mid(0, msgListCount.length() - 1).toInt();
QString msgTableCount = ui->cboxMsgTableCount->currentText();
AppConfig::MsgTableCount = msgTableCount.mid(0, msgTableCount.length() - 1).toInt();
int windowOpacity = ui->sliderWindowOpacity->value();
if (AppConfig::WindowOpacity != windowOpacity) {
AppConfig::WindowOpacity = windowOpacity;
ui->labWindowOpacityValue->setText(QString::number(AppConfig::WindowOpacity));
AppEvent::Instance()->slot_changeWindowOpacity();
}
QString tipInterval = ui->cboxTipInterval->currentText();
AppConfig::TipInterval = tipInterval.mid(0, tipInterval.length() - 2).toInt();
AppConfig::writeConfig();
}