FemaLocalSoftware/mainwindow.cpp
2025-01-13 11:30:39 +03:00

1228 lines
45 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "alarmsservice.h"
#include "flowlayout.h"
#include "paginationbar.h"
#include "sensordialog.h"
#include "alarmwidget.h"
#include "journalservice.h"
#include "logwidget.h"
#include "qcustomplot.h"
#include "serverwidget.h"
#include <QComboBox>
#include <QDateTime>
#include <QGridLayout>
#include <QMessageBox>
#include <QResizeEvent>
#include <QScrollArea>
#include <QTimer>
#include <QDateTime>
#include <QTimeZone>
#include <QPalette>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
httpClient = new HttpClient(this);
sensorService = new SensorService(httpClient, this);
alarmsService = new AlarmsService(httpClient, this);
journalService = new JournalService(httpClient, this);
TranslateUpdate();
SetupSensorTab();
startRefreshTimer();
SetupIncidentTab();
SetupStatisticTab();
SetupJournalTab();
//------------------------------------------------------------------------------
ui->startSelectStatistic->setAttribute(Qt::WA_TranslucentBackground, true);
settings = sensorService->getSettings();
ui->serialLineEdit->setText(settings.serial);
ui->factoryLineEdit->setText(settings.factory);
ui->exhuyantLineEdit->setText(settings.exhuyant);
ui->fleetLineEdit->setText(settings.fleet);
ui->sideLineEdit->setText(settings.side);
ui->gosNumberLineEdit->setText(settings.gosNumber);
ui->factoryNumberLineEdit->setText(settings.factoryNumber);
ui->groupLineEdit->setText(settings.group);
ui->adresLineEdit->setText(settings.adres);
ui->userNameLineEdit->setText(settings.userName);
ui->userPasswordLineEdit->setText(settings.userPassword);
ui->argusSerialLineEdit->setText(settings.argusSerial);
QLayoutItem *child;
while ((child = ui->scrollAreaServersLayout->takeAt(0)) != nullptr) {
if (child->widget()) {
child->widget()->deleteLater();
}
}
for (const auto &server : settings.servers) {
QString domain = server.first;
int port = server.second.toInt();
ServerWidget *serverWidget = new ServerWidget(domain, port, this);
connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
serverWidget->deleteLater();
});
ui->scrollAreaServersLayout->addWidget(serverWidget);
}
connect(ui->tabWidget, &QTabWidget::currentChanged, this, [this](int index) {
if (index == 4) {
settings = sensorService->getSettings();
}
});
connect(ui->serverButtonSettings, &QPushButton::clicked, this, &MainWindow::onServerButtonSettings);
connect(ui->saveButtonSettings, &QPushButton::clicked, this, &MainWindow::onSaveButtonSettings);
connect(ui->cancelButtonSettings, &QPushButton::clicked, this, &MainWindow::onCancelButtonSettings);
connect(ui->importButtonSettings, &QPushButton::clicked, this, &MainWindow::onImportButtonSettings);
connect(ui->exportButtonSettings, &QPushButton::clicked, this, &MainWindow::onExportButtonSettings);
}
void MainWindow::onServerButtonSettings() {
ServerWidget *serverWidget = new ServerWidget("", 0000, this);
connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
serverWidget->deleteLater();
});
ui->scrollAreaServersLayout->addWidget(serverWidget);
}
void MainWindow::onSaveButtonSettings(){
settings.serial = ui->serialLineEdit->text();
settings.factory = ui->factoryLineEdit->text();
settings.exhuyant = ui->exhuyantLineEdit->text();
settings.fleet = ui->fleetLineEdit->text();
settings.side = ui->sideLineEdit->text();
settings.gosNumber = ui->gosNumberLineEdit->text();
settings.factoryNumber = ui->factoryNumberLineEdit->text();
settings.group = ui->groupLineEdit->text();
settings.adres = ui->adresLineEdit->text();
settings.userName = ui->userNameLineEdit->text();
settings.userPassword = ui->userPasswordLineEdit->text();
settings.argusSerial = ui->argusSerialLineEdit->text();
settings.servers.clear();
QList<QPair<QString, QString>> updatedServers;
for (int i = 0; i < ui->scrollAreaServersLayout->count(); ++i) {
if (auto *serverWidget = qobject_cast<ServerWidget*>(ui->scrollAreaServersLayout->itemAt(i)->widget())) {
if (!serverWidget->deleted) {
updatedServers.append(qMakePair(serverWidget->getDomain(), serverWidget->getPort()));
}
}
}
settings.servers = updatedServers;
sensorService->updateSettings(settings);
onCancelButtonSettings();
}
void MainWindow::onCancelButtonSettings(){
settings = sensorService->getSettings();
ui->serialLineEdit->setText(settings.serial);
ui->factoryLineEdit->setText(settings.factory);
ui->exhuyantLineEdit->setText(settings.exhuyant);
ui->fleetLineEdit->setText(settings.fleet);
ui->sideLineEdit->setText(settings.side);
ui->gosNumberLineEdit->setText(settings.gosNumber);
ui->factoryNumberLineEdit->setText(settings.factoryNumber);
ui->groupLineEdit->setText(settings.group);
ui->adresLineEdit->setText(settings.adres);
ui->userNameLineEdit->setText(settings.userName);
ui->userPasswordLineEdit->setText(settings.userPassword);
ui->argusSerialLineEdit->setText(settings.argusSerial);
QLayoutItem *child;
while ((child = ui->scrollAreaServersLayout->takeAt(0)) != nullptr) {
if (child->widget()) {
child->widget()->deleteLater();
}
}
for (const auto &server : settings.servers) {
QString domain = server.first;
int port = server.second.toInt();
ServerWidget *serverWidget = new ServerWidget(domain, port, this);
connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
serverWidget->deleteLater();
});
ui->scrollAreaServersLayout->addWidget(serverWidget);
}
}
void MainWindow::onImportButtonSettings() {
QString filePath = QFileDialog::getOpenFileName(
this,
"Открыть файл настроек",
QDir::homePath(),
"JSON файлы (*.json);;Все файлы (*)"
);
if (filePath.isEmpty()) {
return;
}
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::critical(this, "Ошибка", "Не удалось открыть файл настроек.");
return;
}
QByteArray fileData = file.readAll();
file.close();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(fileData, &parseError);
if (parseError.error != QJsonParseError::NoError) {
QMessageBox::critical(this, "Ошибка", "Файл содержит некорректный JSON: " + parseError.errorString());
return;
}
if (!jsonDoc.isObject()) {
QMessageBox::critical(this, "Ошибка", "Файл настроек должен содержать JSON-объект.");
return;
}
QJsonObject settingsJson = jsonDoc.object();
QJsonObject response = httpClient->post(utils::API_URL + "/settings/deviceSettings", settingsJson);
if (response.isEmpty()) {
QMessageBox::critical(this, "Ошибка", "Не удалось отправить настройки на сервер.");
} else {
QMessageBox::information(this, "Успех", "Настройки успешно импортированы.");
}
onCancelButtonSettings();
}
void MainWindow::onExportButtonSettings(){
QJsonObject responseJson = httpClient->get(utils::API_URL + "/settings/deviceSettings");
if (responseJson.isEmpty()) {
QMessageBox::warning(this, "Ошибка", "Не удалось получить настройки с сервера.");
return;
}
QString filePath = QFileDialog::getSaveFileName(
this,
"Сохранить файл настроек",
QDir::homePath() + "/settings.json",
"JSON файлы (*.json);;Все файлы (*)"
);
// Если путь не выбран, выходим
if (filePath.isEmpty()) {
return;
}
// Конвертируем JSON в строку
QJsonDocument jsonDoc(responseJson);
QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);
// Сохраняем JSON в файл
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write(jsonData);
file.close();
QMessageBox::information(this, "Успех", "Настройки успешно сохранены в файл.");
} else {
QMessageBox::critical(this, "Ошибка", "Не удалось сохранить настройки в файл.");
}
}
void MainWindow::SetupStatisticTab() {
statisticType = 0;
ui->startSelectStatistic->setDisplayFormat("dd/MM/yyyy HH:mm");
ui->endSelectStatistic->setDisplayFormat("dd/MM/yyyy HH:mm");
updateComboboxStatistic();
realTimeChartTimer = new QTimer(this);
statisticChart = new QCustomPlot(this);
statisticChart->setFixedSize(1210, 650);
statisticChart->addGraph();
QPen pen;
pen.setColor(QColor(19, 58, 97));
pen.setWidth(2);
statisticChart->graph(0)->setPen(pen);
QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);
dateTimeTicker->setDateTimeFormat("HH:mm:ss dd.MM.yyyy");
statisticChart->xAxis->setTicker(dateTimeTicker);
statisticChart->axisRect()->setupFullAxesBox();
statisticChart->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
ui->chartNButtonsLayout->addWidget(statisticChart);
statisticChart->hide();
connect(realTimeChartTimer, &QTimer::timeout, this, &MainWindow::updateRealTimeChart);
connect(ui->sensorSelectStatistic, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::onSensorSelectStatisticChanged);
connect(ui->realTimeButtonStatistic, &QPushButton::clicked, this, &MainWindow::onRealTimeStatisticClicked);
connect(ui->archiveButtonStatistic, &QPushButton::clicked, this, &MainWindow::onArchiveStatisticClicked);
connect(ui->showStatisticButton, &QPushButton::clicked, this, &MainWindow::onShowStatisticClicked);
}
void MainWindow::ondialogClosedFromWidget(QString groupWithSensor, QDateTime start, QDateTime end) {
ui->tabWidget->setCurrentIndex(2);
ui->sensorSelectStatistic->setCurrentIndex(groupWithSensorToIndex[groupWithSensor]);
ui->startSelectStatistic->setDateTime(start);
ui->endSelectStatistic->setDateTime(end);
onArchiveStatisticClicked();
onShowStatisticClicked();
}
void MainWindow::onSensorSelectStatisticChanged(int index) {
if(statisticType) {
onRealTimeStatisticClicked();
}
}
void MainWindow::updateRealTimeChart() {
if (!statisticChart) return;
qint64 endTime = QDateTime::currentSecsSinceEpoch();
qint64 startTime = endTime - 5;
PlotData newData = sensorService->getDeviceSensorData(
groupWithSensor[ui->sensorSelectStatistic->currentIndex()], startTime, endTime);
if (!newData.X.isEmpty() && !newData.Y.isEmpty()) {
for(size_t i = 0; i < newData.X.size(); ++i) {
statisticChart->graph(0)->addData(newData.X[i], newData.Y[i]);
}
statisticChart->replot();
}
}
void MainWindow::onRealTimeStatisticClicked() {
statisticType = 1;
ui->startSelectStatistic->hide();
ui->endSelectStatistic->hide();
ui->showStatisticButton->hide();
ui->label_16->hide();
ui->label_14->hide();
if (statisticType) {
ui->realTimeButtonStatistic->setStyleSheet(R"(
QPushButton {
border-style: solid;
border-color: #d5cb7a;
border-width: 2px;
background-color: #d5cb7a;
color: #13385F;
font-family: Inter;
font-size: 22px;
font-weight: 500;
line-height: 26.63px;
text-align: center;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
)");
ui->archiveButtonStatistic->setStyleSheet(R"(
QPushButton {
border-style: solid;
border-color: #d5cb7a;
border-width: 2px;
color: #13385F;
font-family: Inter;
font-size: 22px;
font-weight: 500;
line-height: 26.63px;
text-align: center;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
)");
}
ui->pseudoChart->hide();
statisticChart->show();
qint64 currentTime = QDateTime::currentSecsSinceEpoch();
qint64 initialStartTime = 1;
PlotData initialData = sensorService->getDeviceSensorData(
groupWithSensor[ui->sensorSelectStatistic->currentIndex()], initialStartTime, currentTime);
if (!initialData.X.isEmpty() && !initialData.Y.isEmpty()) {
statisticChart->graph(0)->setData(initialData.X, initialData.Y);
statisticChart->xAxis->setRange(initialData.X.last() - 600, initialData.X.last());
statisticChart->yAxis->setRange(*std::min_element(initialData.Y.begin(), initialData.Y.end()) - 10,
*std::max_element(initialData.Y.begin(), initialData.Y.end()) + 10);
statisticChart->replot();
}
realTimeChartTimer->start(5000);
}
void MainWindow::onArchiveStatisticClicked() {
if (realTimeChartTimer && realTimeChartTimer->isActive()) {
realTimeChartTimer->stop();
}
statisticType = 0;
statisticChart->hide();
ui->pseudoChart->show();
ui->startSelectStatistic->show();
ui->endSelectStatistic->show();
ui->showStatisticButton->show();
ui->label_16->show();
ui->label_14->show();
if(!statisticType) {
ui->realTimeButtonStatistic->setStyleSheet(R"(
QPushButton {
border-style: solid;
border-color: #d5cb7a;
border-width: 2px;
color: #13385F;
font-family: Inter;
font-size: 22px;
font-weight: 500;
line-height: 26.63px;
text-align: center;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
)");
ui->archiveButtonStatistic->setStyleSheet(R"(
QPushButton {
border-style: solid;
border-color: #d5cb7a;
border-width: 2px;
background-color: #d5cb7a;
color: #13385F;
font-family: Inter;
font-size: 22px;
font-weight: 500;
line-height: 26.63px;
text-align: center;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
)");
}
}
void MainWindow::onShowStatisticClicked() {
ui->pseudoChart->hide();
if (!statisticChart) {
return;
}
statisticChart->show();
qint64 start = ui->startSelectStatistic->dateTime().toSecsSinceEpoch();
if(!start) {
start = 1;
}
qint64 end = ui->endSelectStatistic->dateTime().toSecsSinceEpoch();
if(!end) {
end = QDateTime::currentMSecsSinceEpoch();
}
PlotData data = sensorService->getDeviceSensorData(groupWithSensor[ui->sensorSelectStatistic->currentIndex()], start, end);
statisticChart->graph(0)->setData(data.X, data.Y);
statisticChart->yAxis->setRange(*std::min_element(data.Y.begin(), data.Y.end()) - 10,
*std::max_element(data.Y.begin(), data.Y.end()) + 10);
statisticChart->graph(0)->rescaleAxes();
statisticChart->replot();
}
void MainWindow::updateComboboxStatistic() {
ui->sensorSelectStatistic->clear();
groupWithSensor.clear();
sensorGroupTree tree = sensorService->getSensorGroupsTree();
QStringList groups = tree.groupToLocalGroup.keys();
std::sort(groups.begin(), groups.end(), [&tree](const QString &a, const QString &b) {
return tree.groupToLocalGroup[a] < tree.groupToLocalGroup[b];
});
int index = 0;
for (const QString &group : groups) {
const QString &localizedGroupName = tree.groupToLocalGroup[group];
if (tree.groupToSensorWithLocal.contains(group)) {
const QMap<QString, QString> &sensors = tree.groupToSensorWithLocal[group];
for (auto it = sensors.begin(); it != sensors.end(); ++it) {
const QString &sensorId = it.key();
const QString &sensorName = it.value();
QString itemData = group + '/' + sensorId;
groupWithSensorToIndex[itemData] = index;
groupWithSensor.append(itemData);
ui->sensorSelectStatistic->addItem(localizedGroupName + '/' + sensorName, QVariant::fromValue(itemData));
index++;
}
}
}
}
void MainWindow::SetupJournalTab() {
loadSensorsTree(ui->treeJournal);
connect(ui->searchJournal,
&QLineEdit::textChanged,
this,
&MainWindow::onSearchJournalTextChanged);
ui->timeIntervalJournal->addItems(
{"За всё время", "За сегодня", "За вчера", "За последние 7 дней"});
ui->statusJournal->addItems(
{"Все статусы", "Отладка", "Информация", "Предупреждение", "Ошибка", "Экстренно"});
ui->sortJournal->addItems({"По времени", "По критичности"});
journalSettings = getJournalDataSettings();
int amount = journalService->getLogsAmount(journalSettings->groupsWithSensors, journalSettings->status,
journalSettings->start_time, journalSettings->end_time);
paginationBarJournal = new PaginationBar((amount + 24 - 1)/ 24);
ui->paginationBarJournalLayout->addStretch();
ui->paginationBarJournalLayout->addWidget(paginationBarJournal);
ui->paginationBarJournalLayout->addStretch();
QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
journalSettings->cmp, journalSettings->start_time,
journalSettings->end_time, 1, 24);
for(int i = 0; i < arr.size(); ++i) {
LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getThreatLevel(), ui->scrollWidgetJournal);
logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutJournal->addWidget(logWidget);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutJournal->addSpacerItem(spacer);
}
connect(ui->searchLogs, &QPushButton::clicked, this, &MainWindow::onSearchJournalClicked);
connect(ui->updateTreeButtonJournal, &QPushButton::clicked, this, &MainWindow::updateTreeClicked);
connect(paginationBarJournal,
&PaginationBar::pageChanged,
this,
&MainWindow::onJournalPageChanged);
}
void MainWindow::onJournalPageChanged(int page)
{
while (QLayoutItem *item = ui->scrollLayoutJournal->takeAt(0)) {
if (QWidget *widget = item->widget()) {
widget->deleteLater();
}
delete item;
}
QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
journalSettings->cmp, journalSettings->start_time,
journalSettings->end_time, page, 24);
for(int i = 0; i < arr.size(); ++i) {
LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getThreatLevel(), ui->scrollWidgetJournal);
logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutJournal->addWidget(logWidget);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutJournal->addSpacerItem(spacer);
}
}
void MainWindow::onSearchJournalClicked() {
while (QLayoutItem *item = ui->scrollLayoutJournal->takeAt(0)) {
if (QWidget *widget = item->widget()) {
widget->deleteLater();
}
delete item;
}
journalSettings = getJournalDataSettings();
int amount = journalService->getLogsAmount(journalSettings->groupsWithSensors, journalSettings->status,
journalSettings->start_time, journalSettings->end_time);
paginationBarJournal->setTotalPages((amount + 24 - 1)/ 24);
QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
journalSettings->cmp, journalSettings->start_time,
journalSettings->end_time, 1, 24);
for(int i = 0; i < arr.size(); ++i) {
LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getThreatLevel(), ui->scrollWidgetJournal);
logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutJournal->addWidget(logWidget);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutJournal->addSpacerItem(spacer);
}
}
JournalSettings* MainWindow::getJournalDataSettings() {
QString time = ui->timeIntervalJournal->currentText();
qint64 start_time, end_time;
QTimeZone systemTimeZone = QTimeZone::systemTimeZone();
QTimeZone spbTimeZone("Europe/Moscow");
QDateTime now = QDateTime::currentDateTime();
now.setTimeZone(systemTimeZone);
now = now.toTimeZone(spbTimeZone);
if (time == "За всё время") {
start_time = 1;
end_time = now.toSecsSinceEpoch();
} else if (time == "За сегодня") {
QDateTime startOfDay = now.date().startOfDay();
start_time = startOfDay.toSecsSinceEpoch();
end_time = now.toSecsSinceEpoch();
} else if (time == "За вчера") {
QDateTime startOfYesterday = now.addDays(-1).date().startOfDay();
QDateTime endOfYesterday = startOfYesterday.addDays(1).addSecs(-1);
start_time = startOfYesterday.toSecsSinceEpoch();
end_time = endOfYesterday.toSecsSinceEpoch();
} else if (time == "За последние 7 дней") {
QDateTime startOf7DaysAgo = now.addDays(-6).date().startOfDay();
start_time = startOf7DaysAgo.toSecsSinceEpoch();
end_time = now.toSecsSinceEpoch();
} else {
start_time = 1;
end_time = now.toSecsSinceEpoch();
}
QString searchQuery = ui->searchJournal->text().trimmed();
searchQuery = searchQuery.toLower();
QMap<QString, QList<QString>> sensorsMap;
for (int i = 0; i < ui->treeJournal->topLevelItemCount(); ++i) {
QTreeWidgetItem *groupItem = ui->treeJournal->topLevelItem(i);
QString groupName = groupItem->data(0, Qt::UserRole).toString();
QList<QString> sensorIds;
for (int j = 0; j < groupItem->childCount(); ++j) {
QTreeWidgetItem *sensorItem = groupItem->child(j);
if (sensorItem->checkState(0) == Qt::Checked) {
QString sensorText = sensorItem->text(0);
if (searchQuery.isEmpty() || sensorText.toLower().contains(searchQuery)) {
sensorIds.append(sensorItem->data(0, Qt::UserRole).toString());
}
}
}
if (!sensorIds.isEmpty()) {
sensorsMap[groupName] = sensorIds;
}
}
bool cmp = ui->sortJournal->currentText() == "По времени" ? 0 : 1;
QList<int> status;
QString statusText = ui->statusJournal->currentText();
if (statusText == "Отладка"){
status = {0};
} else if (statusText == "Информация"){
status = {1};
} else if (statusText == "Предупреждение"){
status = {2};
} else if (statusText == "Ошибка"){
status = {3};
} else if (statusText == "Экстренно"){
status = {4};
}
return new JournalSettings(sensorsMap, start_time, end_time, cmp, status);
}
void MainWindow::onTreeJournalChanged(QTreeWidgetItem *item, int column)
{
Q_UNUSED(column);
}
void MainWindow::onSearchJournalTextChanged(const QString &text)
{
Q_UNUSED(text);
if (text.isEmpty()) {
ui->searchJournal->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #a6a6a6;
}
)");
} else {
ui->searchJournal->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #13385F;
}
)");
}
}
void MainWindow::SetupIncidentTab() {
loadSensorsTree(ui->treeIncidents);
connect(ui->treeIncidents, &QTreeWidget::itemChanged, this, &MainWindow::onTreeIncidentsChanged);
connect(ui->searchIncedents,
&QLineEdit::textChanged,
this,
&MainWindow::onSearchIncedentsTextChanged);
ui->timeIntervalIncedents->addItems(
{"За всё время", "За сегодня", "За вчера", "За последние 7 дней"});
settingsIncident = getIncidentDataSettings();
int amount = alarmsService->getAlarmsAmount(settingsIncident->groupsWithSensors, settingsIncident->start_time, settingsIncident->end_time);
paginationBarIncident = new PaginationBar((amount + 24 - 1)/ 24, this);
QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
settingsIncident->end_time, 1, 24);
for(int i = 0; i < arr.size(); ++i) {
AlarmWidget *a = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
connect(a, &AlarmWidget::dialogClosedFromWidget, this, &MainWindow::ondialogClosedFromWidget);
a->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutIncidents->addWidget(a);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutIncidents->addSpacerItem(spacer);
}
ui->paginationBarIncedentsLayout->addStretch();
ui->paginationBarIncedentsLayout->addWidget(paginationBarIncident);
ui->paginationBarIncedentsLayout->addStretch();
connect(ui->searchIncidents, &QPushButton::clicked, this, &MainWindow::onSearchIncidentsClicked);
connect(ui->updateTreeButtonIncident, &QPushButton::clicked, this, &MainWindow::updateTreeClicked);
connect(paginationBarIncident,
&PaginationBar::pageChanged,
this,
&MainWindow::onIncidentsPageChanged);
}
void MainWindow::onIncidentsPageChanged(int page)
{
while (QLayoutItem *item = ui->scrollLayoutIncidents->takeAt(0)) {
if (QWidget *widget = item->widget()) {
widget->deleteLater();
}
delete item;
}
QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
settingsIncident->end_time, page, 24);
for(int i = 0; i < arr.size(); ++i) {
AlarmWidget *alarmWidget = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
alarmWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutIncidents->addWidget(alarmWidget);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutIncidents->addSpacerItem(spacer);
}
}
void MainWindow::onSearchIncidentsClicked() {
while (QLayoutItem *item = ui->scrollLayoutIncidents->takeAt(0)) {
if (QWidget *widget = item->widget()) {
widget->deleteLater();
}
delete item;
}
settingsIncident = getIncidentDataSettings();
int amount = alarmsService->getAlarmsAmount(settingsIncident->groupsWithSensors, settingsIncident->start_time, settingsIncident->end_time);
paginationBarIncident->setTotalPages((amount + 24 - 1)/ 24);
QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
settingsIncident->end_time, 1, 24);
for(int i = 0; i < arr.size(); ++i) {
AlarmWidget *a = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
a->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ui->scrollLayoutIncidents->addWidget(a);
}
if (arr.size() < 24) {
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
ui->scrollLayoutIncidents->addSpacerItem(spacer);
}
}
AlarmSettings* MainWindow::getIncidentDataSettings() {
QString time = ui->timeIntervalIncedents->currentText();
qint64 start_time, end_time;
QTimeZone systemTimeZone = QTimeZone::systemTimeZone();
QTimeZone spbTimeZone("Europe/Moscow");
QDateTime now = QDateTime::currentDateTime();
now.setTimeZone(systemTimeZone);
now = now.toTimeZone(spbTimeZone);
if (time == "За всё время") {
start_time = 1;
end_time = now.toSecsSinceEpoch();
} else if (time == "За сегодня") {
QDateTime startOfDay = now.date().startOfDay();
start_time = startOfDay.toSecsSinceEpoch();
end_time = now.toSecsSinceEpoch();
} else if (time == "За вчера") {
QDateTime startOfYesterday = now.addDays(-1).date().startOfDay();
QDateTime endOfYesterday = startOfYesterday.addDays(1).addSecs(-1);
start_time = startOfYesterday.toSecsSinceEpoch();
end_time = endOfYesterday.toSecsSinceEpoch();
} else if (time == "За последние 7 дней") {
QDateTime startOf7DaysAgo = now.addDays(-6).date().startOfDay();
start_time = startOf7DaysAgo.toSecsSinceEpoch();
end_time = now.toSecsSinceEpoch();
} else {
start_time = 1;
end_time = now.toSecsSinceEpoch();
}
QString searchQuery = ui->searchIncedents->text().trimmed();
searchQuery = searchQuery.toLower();
QMap<QString, QList<QString>> sensorsMap;
for (int i = 0; i < ui->treeIncidents->topLevelItemCount(); ++i) {
QTreeWidgetItem *groupItem = ui->treeIncidents->topLevelItem(i);
QString groupName = groupItem->data(0, Qt::UserRole).toString();
QList<QString> sensorIds;
for (int j = 0; j < groupItem->childCount(); ++j) {
QTreeWidgetItem *sensorItem = groupItem->child(j);
if (sensorItem->checkState(0) == Qt::Checked) {
QString sensorText = sensorItem->text(0);
if (searchQuery.isEmpty() || sensorText.toLower().contains(searchQuery)) {
sensorIds.append(sensorItem->data(0, Qt::UserRole).toString());
}
}
}
if (!sensorIds.isEmpty()) {
sensorsMap[groupName] = sensorIds;
}
}
return new AlarmSettings(sensorsMap, start_time, end_time);
}
void MainWindow::onTreeIncidentsChanged(QTreeWidgetItem *item, int column)
{
Q_UNUSED(column);
}
void MainWindow::onSearchIncedentsTextChanged(const QString &text)
{
Q_UNUSED(text);
if (text.isEmpty()) {
ui->searchIncedents->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #a6a6a6;
}
)");
} else {
ui->searchIncedents->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #13385F;
}
)");
}
}
void MainWindow::loadSensorsTree(QTreeWidget *treeWidget)
{
if (!treeWidget) return;
QTreeWidget *bufferTree = new QTreeWidget();
sensorGroupTree tree = sensorService->getSensorGroupsTree();
QStringList groups = tree.groupToLocalGroup.keys();
std::sort(groups.begin(), groups.end());
for (const QString &group : groups) {
QTreeWidgetItem *groupItem = new QTreeWidgetItem(bufferTree);
const QString &localizedGroupName = tree.groupToLocalGroup[group];
groupItem->setText(0, localizedGroupName);
groupItem->setData(0, Qt::UserRole, group);
if (tree.groupToSensorWithLocal.contains(group)) {
const QMap<QString, QString> &sensors = tree.groupToSensorWithLocal[group];
for (auto it = sensors.begin(); it != sensors.end(); ++it) {
const QString &sensorId = it.key();
const QString &sensorName = it.value();
nameToId[sensorName] = sensorId;
QTreeWidgetItem *sensorItem = new QTreeWidgetItem(groupItem);
sensorItem->setText(0, sensorName);
sensorItem->setCheckState(0, Qt::Checked);
sensorItem->setData(0, Qt::UserRole, sensorId);
}
}
}
treeWidget->clear();
moveTopLevelItems(bufferTree, treeWidget);
delete bufferTree;
}
void MainWindow::moveTopLevelItems(QTreeWidget *source, QTreeWidget *destination)
{
while (source->topLevelItemCount() > 0) {
QTreeWidgetItem *item = source->takeTopLevelItem(0);
destination->addTopLevelItem(item);
}
}
void MainWindow::SetupSensorTab()
{
QScrollArea *scrollArea = new QScrollArea(this);
scrollArea->setStyleSheet("QScrollArea {"
" background: transparent;"
" border: none;"
"}"
"QScrollBar:vertical {"
" background: #ebebeb;"
" width: 10px;"
" border-radius: 5px;"
"}"
"QScrollBar::handle:vertical {"
" background: #6d6d6d;"
" border-radius: 5px;"
" min-height: 20px;"
"}"
"QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {"
" border: none;"
" background: none;"
" color: none;"
"}"
"QScrollBar::sub-line:vertical, QScrollBar::add-line:vertical {"
" background: transparent;"
" border: none;"
"}"
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {"
" background: transparent;"
"}");
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
widgetContainer = new QWidget(scrollArea);
widgetContainer->setStyleSheet("background: transparent;");
layout = new FlowLayout(widgetContainer, 10, 10, 10);
widgetContainer->setLayout(layout);
scrollArea->setWidget(widgetContainer);
ui->sensorsLayout->addWidget(scrollArea);
connect(ui->search, &QLineEdit::textChanged, this, &MainWindow::onSearchTextChanged);
ui->showHiddenSelect->addItems({"Да", "Нет"});
connect(ui->groupSelect,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&MainWindow::onGroupSelected);
connect(ui->showHiddenSelect,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&MainWindow::onShowHiddenSelected);
loadSensorGroups();
}
void MainWindow::updateTreeClicked()
{
QObject *senderObj = sender();
if (!senderObj) return;
if (senderObj == ui->updateTreeButtonJournal) {
ui->treeJournal->hide();
loadSensorsTree(ui->treeJournal);
ui->treeJournal->show();
} else if (senderObj == ui->updateTreeButtonIncident) {
ui->treeIncidents->hide();
loadSensorsTree(ui->treeIncidents);
ui->treeIncidents->show();
}
}
//TODO: посмотреть что с таймером
void MainWindow::startRefreshTimer()
{
QTimer *refreshTimer = new QTimer(this);
connect(refreshTimer, &QTimer::timeout, this, [this]() {
if (ui->tabWidget->currentWidget() == ui->sensorsTab) {
updateDisplayedWidgets();
}
TranslateUpdate();
});
refreshTimer->start(5000); //5 sec
}
void MainWindow::TranslateUpdate() {
translate = sensorService->getTranslate();
}
void MainWindow::showSensorDialog(SensorWidget *sensor)
{
SensorDialog *dialog = new SensorDialog(this, sensor, httpClient);
dialog->setWindowModality(Qt::ApplicationModal);
connect(dialog, &SensorDialog::resultReady, this, &MainWindow::onSensorDialogFinished);
dialog->exec();
}
void MainWindow::onSensorDialogFinished(int result)
{
switch (result) {
case SensorDialog::SaveSuccess:
updateDisplayedWidgets();
break;
case SensorDialog::SaveError:
QMessageBox::critical(nullptr, "Ошибка", "Данные не сохранены, попробуйте еще раз");
break;
case SensorDialog::NoSave:
updateDisplayedWidgets();
break;
default:
break;
}
}
void MainWindow::loadSensorGroups()
{
QMap<QString, QString> groupsMap = sensorService->getLocalizedSensorGroups();
if (groupsMap.isEmpty()) {
QTimer::singleShot(5000, this, &MainWindow::loadSensorGroups);
return;
}
ui->groupSelect->clear();
for (auto it = groupsMap.begin(); it != groupsMap.end(); ++it) {
if(it.key() == "*SYSTEM") {
continue;
}
ui->groupSelect->addItem(it.key(), it.value());
}
if (!groupsMap.isEmpty()) {
loadSensors(groupsMap[groupsMap.firstKey()]);
}
}
void MainWindow::loadSensors(const QString &group)
{
QList<Sensor> sensors = sensorService->getSensors(group);
const auto &existingWidgets = widgetContainer->findChildren<SensorWidget *>();
for (SensorWidget *widget : existingWidgets) {
delete widget;
}
layout->clear();
for (const Sensor &sensor : sensors) {
if(sensor.id == "*NAME") {
continue;
}
SensorWidget *s = new SensorWidget(nullptr, sensor);
layout->addWidget(s);
connect(s, &SensorWidget::clicked, this, &MainWindow::showSensorDialog);
}
widgetContainer->update();
}
void MainWindow::updateDisplayedWidgets()
{
QString selectedGroup = ui->groupSelect->currentData().toString();
QString showHidden = ui->showHiddenSelect->currentText();
QString searchText = ui->search->text();
// Загружаем датчики только для выбранной группы
QList<Sensor> sensors = sensorService->getSensors(selectedGroup);
// Храним уже добавленные виджеты
QMap<QString, SensorWidget *> existingWidgets;
// Сохраняем существующие виджеты и их сенсоры для последующего обновления
const auto &widgets = widgetContainer->findChildren<SensorWidget *>();
for (SensorWidget *widget : widgets) {
existingWidgets[widget->getSensor().id] = widget;
}
layout->clear(); // Очищаем layout, но не удаляем сами виджеты
// Проходим по новым датчикам и добавляем их в layout, если они ещё не добавлены
for (const Sensor &sensor : sensors) {
SensorWidget *widget = nullptr;
if(sensor.id == "*NAME") {
continue;
}
// Проверяем, существует ли виджет для данного сенсора
if (existingWidgets.contains(sensor.id)) {
widget = existingWidgets[sensor.id];
widget->setSensor(sensor); // Обновляем данные существующего виджета
} else {
widget = new SensorWidget(nullptr, sensor);
connect(widget, &SensorWidget::clicked, this, &MainWindow::showSensorDialog);
}
// Применяем фильтрацию по условиям
bool matchesHidden = (showHidden == "Да") || !sensor.isHide;
bool matchesSearch = sensor.name.contains(searchText, Qt::CaseInsensitive);
if (matchesHidden && matchesSearch) {
layout->addWidget(widget);
widget->show();
} else {
widget->hide();
}
}
widgetContainer->update(); // Обновляем виджеты в контейнере
}
void MainWindow::onGroupSelected(int index)
{
Q_UNUSED(index);
loadSensors(ui->groupSelect->currentText());
updateDisplayedWidgets();
}
void MainWindow::onShowHiddenSelected(int index)
{
Q_UNUSED(index);
updateDisplayedWidgets();
}
void MainWindow::onSearchTextChanged(const QString &text)
{
Q_UNUSED(text);
if (text.isEmpty()) {
ui->search->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #a6a6a6;
}
)");
} else {
ui->search->setStyleSheet(R"(
QLineEdit {
width: 778px;
height: 60px;
border: 2px solid #DCD174;
font-family: Inter;
font-size: 26px;
font-weight: 400;
line-height: 31.47px;
text-align: left;
background: #00000000;
color: #13385F;
}
)");
}
updateDisplayedWidgets();
}
MainWindow::~MainWindow()
{
delete ui;
}