PNP_PIbd-31_Rodionov_I_A_Co.../mainwindow.cpp
2025-01-14 21:33:47 +04:00

681 lines
24 KiB
C++
Raw 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"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowIcon(QIcon(":/images/mw-icon.png"));
int width = frameGeometry().width();
int height = frameGeometry().height();
QScreen *screen = qApp->primaryScreen();
int screenWidth = screen->geometry().width();
int screenHeight = screen->geometry().height();
setGeometry((screenWidth/2)-(width/2), (screenHeight/2)-(height/2), width, height);
QStringList filterItems = {
"Все устройства",
"Типы устройств",
"Помещения",
"Отделы",
"Производители",
"Модели устройств"
};
ui->comboBoxFilters->addItems(filterItems);
QStringList sortItems = {
"Сначала новые",
"Сначала старые",
"Сначала дешевые",
"Сначала дорогие",
"Сначала с лайком"
};
ui->comboBoxSort->addItems(sortItems);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->setColumnCount(2);
QStringList headers = {"ID", "Название"};
ui->tableWidget->setHorizontalHeaderLabels(headers);
QHeaderView *header = ui->tableWidget->horizontalHeader();
QFont headerFont = header->font();
headerFont.setBold(true);
header->setFont(headerFont);
header->setSectionResizeMode(QHeaderView::Stretch);
ui->listWidgetDevices->setSpacing(10);
QLineEdit *searchEdit = ui->lineEditSearch;
QPushButton *searchButton = new QPushButton(this);
ButtonHoverWatcher *watcher = new ButtonHoverWatcher(this);
searchButton->installEventFilter(watcher);
searchButton->setCursor(Qt::PointingHandCursor);
searchButton->setStyleSheet("background: transparent; border: none;");
searchButton->setIcon(QIcon(":/images/search.png"));
searchButton->setFixedSize(22, 22);
QMargins margins = searchEdit->textMargins();
searchEdit->setTextMargins(margins.left(), margins.top(), searchButton->width(), margins.bottom());
searchEdit->setPlaceholderText(QStringLiteral("Поиск устройств по модели, типу или серийному номеру..."));
searchEdit->setMaxLength(200);
QHBoxLayout *searchLayout = new QHBoxLayout();
searchLayout->addStretch();
searchLayout->addWidget(searchButton);
searchLayout->setSpacing(0);
searchLayout->setContentsMargins(3, 2, 3, 2);
searchEdit->setLayout(searchLayout);
QButtonGroup *buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(ui->radioButtonWorking);
buttonGroup->addButton(ui->radioButtonNotWorking);
buttonGroup->addButton(ui->radioButtonDisregard);
ui->radioButtonWorking->setChecked(true);
ui->checkBoxIsWorking->setAttribute(Qt::WA_TransparentForMouseEvents);
ui->checkBoxIsWorking->setFocusPolicy(Qt::NoFocus);
ui->pushButtonDisregardPrice->setToolTip("Цена не учитывается при том условии, если оба значения из диапазона равны нулю");
QFile *styleFile = new QFile(":/styles.qss");
if (styleFile->open(QFile::ReadOnly)) {
QTextStream ts(styleFile);
QString style = ts.readAll();
qApp->setStyleSheet(style);
}
connect(ui->comboBoxFilters, SIGNAL(activated(int)), this, SLOT(updateTableWidget(int)));
connect(ui->comboBoxSort, SIGNAL(activated(int)), this, SLOT(changeSortOrder()));
connect(ui->tableWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateListWidget()));
connect(ui->listWidgetDevices, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(showItemInfo(QListWidgetItem*)));
connect(ui->pushButtonBack, SIGNAL(clicked()), this, SLOT(pushButtonBackClicked()));
connect(ui->pushButtonClear, SIGNAL(clicked()), this, SLOT(pushButtonClearClicked()));
connect(searchEdit, SIGNAL(returnPressed()), this, SLOT(pushButtonSearchClicked()));
connect(searchButton, SIGNAL(clicked()), this, SLOT(pushButtonSearchClicked()));
connect(ui->pushButtonDisregardPrice, SIGNAL(clicked()), this, SLOT(pushButtonDisregardPriceClicked()));
connect(ui->pushButtonApplyFilters, SIGNAL(clicked()), this, SLOT(pushButtonApplyFiltersClicked()));
connect(ui->pushButtonCancelFilters, SIGNAL(clicked()), this, SLOT(pushButtonCancelFiltersClicked()));
connect(ui->pushButtonDefault, SIGNAL(clicked()), this, SLOT(pushButtonDefaultClicked()));
connect(ui->pushButtonStructure, SIGNAL(clicked()), this, SLOT(pushButtonStructureClicked()));
connect(ui->pushButtonCharacteristics, SIGNAL(clicked()), this, SLOT(pushButtonCharacteristicsClicked()));
returnToDeviceList();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateTableWidget(int index)
{
returnToDeviceList();
ui->tableWidget->clearContents();
ui->tableWidget->setRowCount(0);
switch (index) {
case 0: // Все устройства
clearDevicesOutputSettings();
updateDevices(-1);
break;
case 1: // Типы устройств
_client->getEntities("/api/devicetypes");
break;
case 2: // Помещения
_client->getEntities("/api/locations");
break;
case 3: // Отделы
_client->getEntities("/api/departments");
break;
case 4: // Производители
_client->getEntities("/api/manufacturers");
break;
case 5: // Модели устройств
_client->getEntities("/api/devicemodels");
break;
default:
break;
}
}
void MainWindow::updateListWidget()
{
returnToDeviceList();
int selectedElementId = getSelectedElementId();
if (selectedElementId == -1)
return;
clearDevicesOutputSettings();
updateDevices(selectedElementId);
}
void MainWindow::changeSortOrder()
{
updateDevices(getSelectedElementId());
}
void MainWindow::updateDevices(int entityId)
{
_client->getFilteredDevices(
_filterParams.isWorking(),
_filterParams.priceFrom(),
_filterParams.priceTo(),
_filterParams.apllyFilters(),
_filterParams.disregardState(),
entityId,
ui->comboBoxFilters->currentIndex(),
_searchInfo,
ui->comboBoxSort->currentText()
);
}
int MainWindow::getSelectedElementId()
{
QModelIndexList selectedIndexes = ui->tableWidget->selectionModel()->selectedRows();
if (selectedIndexes.isEmpty()) {
return -1;
}
int rowIndex = selectedIndexes.first().row();
return ui->tableWidget->item(rowIndex, 0)->text().toInt();
}
template <typename T>
void MainWindow::fillTable(const QMap<int, T> &map)
{
int row = 0;
for (auto &item : map) {
ui->tableWidget->insertRow(row);
QTableWidgetItem *idItem = new QTableWidgetItem(QString::number(item.id()));
QTableWidgetItem *nameItem = new QTableWidgetItem(item.name());
idItem->setFlags(idItem->flags() & ~Qt::ItemIsEditable);
nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(row, 0, idItem);
ui->tableWidget->setItem(row, 1, nameItem);
idItem->setTextAlignment(Qt::AlignCenter);
nameItem->setTextAlignment(Qt::AlignCenter);
row++;
}
}
void MainWindow::fillListWidget(const QList<Device> &devices)
{
ui->listWidgetDevices->clear();
if (devices.isEmpty()) {
addMessageEmptyToList();
} else {
for (const auto &device : devices) {
addDeviceToList(device);
}
}
}
void MainWindow::addMessageEmptyToList()
{
QListWidgetItem *item = new QListWidgetItem(ui->listWidgetDevices);
ui->listWidgetDevices->addItem(item);
QWidget *cardWidget = createMessageEmptyCard();
item->setSizeHint(cardWidget->minimumSizeHint());
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
ui->listWidgetDevices->setItemWidget(item, cardWidget);
}
void MainWindow::addDeviceToList(const Device &device)
{
QListWidgetItem *item = new QListWidgetItem(ui->listWidgetDevices);
ui->listWidgetDevices->addItem(item);
QWidget *cardWidget = createDeviceCard(device);
item->setSizeHint(cardWidget->minimumSizeHint());
ui->listWidgetDevices->setItemWidget(item, cardWidget);
item->setData(Qt::UserRole, device.id());
}
QWidget *MainWindow::createMessageEmptyCard()
{
QWidget *cardWidget = new QWidget(ui->listWidgetDevices);
QVBoxLayout *cardLayout = new QVBoxLayout(cardWidget);
QLabel *titleLabel = new QLabel("По заданным параметрам ничего не найдено", cardWidget);
QFont titleFont("Arial", 17, QFont::Bold);
titleLabel->setFont(titleFont);
cardLayout->addWidget(titleLabel, 0, Qt::AlignCenter);
cardLayout->setSpacing(12);
QLabel *imageLabel = new QLabel(cardWidget);
QPixmap pixmap(":/images/question.png");
imageLabel->setPixmap(pixmap.scaled(256, 256, Qt::KeepAspectRatio));
cardLayout->addWidget(imageLabel, 0, Qt::AlignCenter);
return cardWidget;
}
QWidget *MainWindow::createDeviceCard(const Device &device)
{
QWidget *cardWidget = new QWidget(ui->listWidgetDevices);
QVBoxLayout *cardLayout = new QVBoxLayout(cardWidget);
QFrame *topBorder = new QFrame(cardWidget);
topBorder->setFrameShape(QFrame::HLine);
topBorder->setFrameShadow(QFrame::Sunken);
cardLayout->addWidget(topBorder);
QHBoxLayout *iconTextlayout = new QHBoxLayout();
QLabel *imageLabel = new QLabel(cardWidget);
QString imagePath = _deviceTypeImages[device.deviceModel().idType()];
QPixmap pixmap(imagePath);
imageLabel->setPixmap(pixmap.scaled(100, 100, Qt::KeepAspectRatio));
iconTextlayout->addWidget(imageLabel);
QVBoxLayout *textLayout = new QVBoxLayout();
QLabel *serialNumberLabel = new QLabel(device.serialNumber(), cardWidget);
QFont serialNumberFont("Arial", 14, QFont::Bold);
serialNumberLabel->setFont(serialNumberFont);
textLayout->addWidget(serialNumberLabel);
QFont generalFont("Arial", 11);
QString typeName = normalizeTypeName(device.deviceModel().nameType());
QLabel *typeNameLabel = new QLabel(typeName + ": " + device.deviceModel().name(), cardWidget);
typeNameLabel->setFont(generalFont);
textLayout->addWidget(typeNameLabel);
QLabel *statusLabel = new QLabel(device.isWorking() ? "Работает" : "Сломано", cardWidget);
statusLabel->setFont(generalFont);
textLayout->addWidget(statusLabel);
QHBoxLayout *priceLikeLayout = new QHBoxLayout();
priceLikeLayout->setSpacing(100);
QLabel *priceLabel = new QLabel(QString::number(device.price()) + "", cardWidget);
priceLabel->setFont(generalFont);
priceLabel->setFixedWidth(100);
priceLikeLayout->addWidget(priceLabel);
priceLikeLayout->addSpacerItem(new QSpacerItem(40, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
QCheckBox *likeCheckBox = new QCheckBox("Нравится", cardWidget);
likeCheckBox->setChecked(device.isLiked());
likeCheckBox->setFont(generalFont);
likeCheckBox->setStyleSheet(likeCheckBox->isChecked() ? "color: green;" : "color: black;");
connect(likeCheckBox, &QCheckBox::toggled, this, [this, device, likeCheckBox](bool checked) {
Device updatedDevice = device;
updatedDevice.setIsLiked(checked);
_client->updateDevice(updatedDevice.id(), updatedDevice);
connect(_client, &ApiClient::deviceUpdated, this, [this, checked, device, likeCheckBox](bool success) {
disconnect(_client, &ApiClient::deviceUpdated, this, nullptr);
if (success) {
QString message = checked ? "Устройство добавлено в избранное." : "Устройство удалено из избранного.";
QMessageBox::information(this, "Обновление", message);
Device& deviceRef = _mapDevices[device.id()];
deviceRef.setIsLiked(checked);
likeCheckBox->setStyleSheet(checked ? "color: green;" : "color: black;");
} else {
QMessageBox::critical(this, "Ошибка", "Не удалось изменить состояние устройства.");
}
});
});
priceLikeLayout->addWidget(likeCheckBox);
textLayout->addLayout(priceLikeLayout);
iconTextlayout->addSpacerItem(new QSpacerItem(40, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
iconTextlayout->addLayout(textLayout);
cardLayout->addLayout(iconTextlayout);
QFrame *bottomBorder = new QFrame(cardWidget);
bottomBorder->setFrameShape(QFrame::HLine);
bottomBorder->setFrameShadow(QFrame::Sunken);
cardLayout->addWidget(bottomBorder);
cardLayout->setContentsMargins(2, 0, 2, 0);
return cardWidget;
}
QString MainWindow::normalizeTypeName(const QString &name)
{
QString typeName = name.left(name.length() - 1);
if (typeName == "Персональные компьютер")
typeName = "Персональный компьютер";
return typeName;
}
void MainWindow::showItemInfo(QListWidgetItem *item)
{
if (!item)
return;
ui->listWidgetDevices->scrollToItem(item, QAbstractItemView::PositionAtCenter);
int deviceId = item->data(Qt::UserRole).toInt();
Device device = _mapDevices[deviceId];
_idCard = deviceId;
ui->lineEditId->setText(QString::number(device.id()));
ui->lineEditSerialNum->setText(device.serialNumber());
ui->lineEditPurchaseDate->setText(device.purchaseDate().toString("dd.MM.yyyy HH:mm:ss"));
ui->lineEditPrice->setText(QString::number(device.price(), 'f', 2));
ui->lineEditWarranty->setText(device.warrantyExpireDate().toString("dd.MM.yyyy HH:mm:ss"));
ui->lineEditLocation->setText(device.nameLocation());
ui->lineEditEmployee->setText(device.nameEmployee());
ui->lineEditDepartment->setText(device.nameDepartment());
ui->lineEditModel->setText(device.deviceModel().name());
ui->lineEditType->setText(device.deviceModel().nameType());
ui->lineEditManuf->setText(device.deviceModel().nameManuf());
ui->textEditFurtherInformation->setPlainText(device.furtherInformation());
ui->checkBoxIsWorking->setChecked(device.isWorking());
ui->stackedWidget->setCurrentIndex(1);
}
void MainWindow::returnToDeviceList()
{
_idCard = 0;
ui->stackedWidget->setCurrentIndex(0);
}
void MainWindow::showTableWithStructureElements(const QList<DeviceStructureElement> &elements)
{
QDialog* dialog = new QDialog(this);
dialog->setWindowTitle("Элементы структуры устройства");
dialog->resize(1100, 600);
QTableWidget* tableWidget = new QTableWidget(dialog);
tableWidget->setColumnCount(5);
QFont font("Arial", 12);
tableWidget->setFont(font);
QStringList headers = {"Название модели", "Производитель", "Описание элемента", "Тип элемента", "Количество"};
tableWidget->setHorizontalHeaderLabels(headers);
QFont headerFont("Arial", 12, QFont::Bold);
for (int i = 0; i < tableWidget->columnCount(); i++) {
tableWidget->horizontalHeaderItem(i)->setFont(headerFont);
}
tableWidget->setRowCount(elements.size());
for (int row = 0; row < elements.size(); row++) {
const DeviceStructureElement& element = elements[row];
tableWidget->setItem(row, 0, new QTableWidgetItem(element.nameModel()));
tableWidget->setItem(row, 1, new QTableWidgetItem(element.nameManuf()));
tableWidget->setItem(row, 2, new QTableWidgetItem(element.description()));
tableWidget->setItem(row, 3, new QTableWidgetItem(element.nameType()));
tableWidget->setItem(row, 4, new QTableWidgetItem(QString::number(element.count())));
for (int col = 0; col < tableWidget->columnCount(); col++) {
tableWidget->item(row, col)->setFlags(tableWidget->item(row, col)->flags() & ~Qt::ItemIsEditable);
}
}
connect(tableWidget, &QTableWidget::cellClicked, [tableWidget](int row, int col) {
QString text = tableWidget->item(row, col)->text();
QToolTip::showText(QCursor::pos(), text);
});
tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
tableWidget->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Interactive);
tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
tableWidget->horizontalHeader()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
tableWidget->setColumnWidth(2, tableWidget->columnWidth(0) * 2);
tableWidget->setFocusPolicy(Qt::NoFocus);
QVBoxLayout* layout = new QVBoxLayout(dialog);
layout->addWidget(tableWidget);
dialog->setLayout(layout);
dialog->exec();
}
void MainWindow::showTableWithDeviceModelCharacteristics(const DeviceModel &model)
{
QDialog* dialog = new QDialog(this);
dialog->setWindowTitle("Характеристики устройства");
dialog->setFixedSize(1200, 75);
QTableWidget* tableWidget = new QTableWidget(dialog);
tableWidget->setColumnCount(6);
QFont font("Arial", 11);
tableWidget->setFont(font);
QStringList headers = {"Эффективность работы", "Надежность", "Энергоэффективность", "Удобство использования", "Долговечность", "Эстетические качества"};
tableWidget->setHorizontalHeaderLabels(headers);
QFont headerFont("Arial", 11, QFont::Bold);
for (int i = 0; i < tableWidget->columnCount(); i++) {
tableWidget->horizontalHeaderItem(i)->setFont(headerFont);
}
tableWidget->setRowCount(1);
tableWidget->setItem(0, 0, new QTableWidgetItem(QString::number(model.workEfficiency())));
tableWidget->setItem(0, 1, new QTableWidgetItem(QString::number(model.reliability())));
tableWidget->setItem(0, 2, new QTableWidgetItem(QString::number(model.energyEfficiency())));
tableWidget->setItem(0, 3, new QTableWidgetItem(QString::number(model.userFriendliness())));
tableWidget->setItem(0, 4, new QTableWidgetItem(QString::number(model.durability())));
tableWidget->setItem(0, 5, new QTableWidgetItem(QString::number(model.aestheticQualities())));
for (int col = 0; col < tableWidget->columnCount(); col++) {
tableWidget->item(0, col)->setFlags(tableWidget->item(0, col)->flags() & ~Qt::ItemIsEditable);
tableWidget->item(0, col)->setTextAlignment(Qt::AlignCenter);
tableWidget->horizontalHeader()->setSectionResizeMode(col, QHeaderView::Stretch);
}
tableWidget->verticalHeader()->setVisible(false);
tableWidget->setFocusPolicy(Qt::NoFocus);
QVBoxLayout* layout = new QVBoxLayout(dialog);
layout->addWidget(tableWidget);
dialog->setLayout(layout);
dialog->exec();
}
void MainWindow::pushButtonBackClicked()
{
returnToDeviceList();
}
void MainWindow::pushButtonClearClicked()
{
ui->lineEditSearch->setText("");
}
void MainWindow::pushButtonSearchClicked()
{
_searchInfo = ui->lineEditSearch->text();
if (_searchInfo.isEmpty()) {
QMessageBox::warning(this, "Ошибка", "Пожалуйста, введите текст для поиска.");
return;
}
ui->comboBoxSort->setCurrentIndex(0);
clearFilters();
updateDevices(getSelectedElementId());
}
void MainWindow::pushButtonDisregardPriceClicked()
{
clearSpinBoxes();
}
void MainWindow::pushButtonApplyFiltersClicked()
{
double priceFrom = ui->doubleSpinBoxFrom->value();
double priceTo = ui->doubleSpinBoxTo->value();
if (priceFrom > priceTo) {
QMessageBox::warning(this, "Ошибка", "Начальное значение диапазона не может быть больше конечного значения.");
clearSpinBoxes();
return;
}
_filterParams.setApllyFilters(true);
_filterParams.setDisregardState(ui->radioButtonDisregard->isChecked());
_filterParams.setIsWorking(ui->radioButtonWorking->isChecked());
if (priceFrom == 0.00 && priceTo == 0.00) {
_filterParams.setPriceFrom(0.00);
_filterParams.setPriceTo(std::numeric_limits<double>::max());
} else {
_filterParams.setPriceFrom(priceFrom);
_filterParams.setPriceTo(priceTo);
}
updateDevices(getSelectedElementId());
}
void MainWindow::pushButtonCancelFiltersClicked()
{
clearFilters();
updateDevices(getSelectedElementId());
}
void MainWindow::pushButtonStructureClicked()
{
showTableWithStructureElements(_mapDevices[_idCard].deviceModel().structureElements());
}
void MainWindow::pushButtonCharacteristicsClicked()
{
showTableWithDeviceModelCharacteristics(_mapDevices[_idCard].deviceModel());
}
void MainWindow::pushButtonDefaultClicked()
{
clearDevicesOutputSettings();
updateDevices(getSelectedElementId());
}
void MainWindow::clearDevicesOutputSettings()
{
ui->comboBoxSort->setCurrentIndex(0);
ui->lineEditSearch->setText("");
_searchInfo = "";
clearFilters();
}
void MainWindow::clearFilters()
{
ui->radioButtonWorking->setChecked(true);
clearSpinBoxes();
_filterParams.setIsWorking(true);
_filterParams.setPriceFrom(-1);
_filterParams.setPriceTo(-1);
_filterParams.setDisregardState(false);
_filterParams.setApllyFilters(false);
}
void MainWindow::clearSpinBoxes()
{
ui->doubleSpinBoxFrom->setValue(0.00);
ui->doubleSpinBoxTo->setValue(0.00);
}
void MainWindow::setClient(ApiClient *newClient)
{
_client = newClient;
connect(_client, &ApiClient::devicesReceived, this, &MainWindow::onDevicesReceived);
connect(_client, &ApiClient::departmentsReceived, this, &MainWindow::onDepartmentsReceived);
connect(_client, &ApiClient::deviceModelsReceived, this, &MainWindow::onDeviceModelsReceived);
connect(_client, &ApiClient::deviceTypesReceived, this, &MainWindow::onDeviceTypesReceived);
connect(_client, &ApiClient::locationsReceived, this, &MainWindow::onLocationsReceived);
connect(_client, &ApiClient::manufacturersReceived, this, &MainWindow::onManufacturersReceived);
_client->getEntities("/api/devicetypes");
updateTableWidget(0);
}
void MainWindow::onDevicesReceived(const QList<Device> &devices)
{
_mapDevices = getDevicesMap(devices);
fillListWidget(devices);
}
void MainWindow::onDepartmentsReceived(const QMap<int, Department> &departments)
{
fillTable<Department>(departments);
}
void MainWindow::onDeviceModelsReceived(const QMap<int, DeviceModel> &deviceModels)
{
fillTable<DeviceModel>(deviceModels);
}
void MainWindow::onDeviceTypesReceived(const QMap<int, DeviceType> &deviceTypes)
{
if (_initialTypesLoad) {
_initialTypesLoad = false;
} else {
fillTable<DeviceType>(deviceTypes);
}
for (const DeviceType &type : deviceTypes) {
QString imagePath = QString(":/images/device-type-%1.png").arg(type.name());
if (QFile::exists(imagePath)) {
_deviceTypeImages[type.id()] = imagePath;
} else {
_deviceTypeImages[type.id()] = ":/images/placeholder.png";
}
}
}
void MainWindow::onManufacturersReceived(const QMap<int, Manufacturer> &manufacturers)
{
fillTable<Manufacturer>(manufacturers);
}
void MainWindow::onLocationsReceived(const QMap<int, Location> &locations)
{
fillTable<Location>(locations);
}
QMap<int, Device> MainWindow::getDevicesMap(const QList<Device> &devices)
{
QMap<int, Device> devicesMap;
for (const Device &device : devices) {
devicesMap.insert(device.id(), device);
}
return devicesMap;
}