#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); returnToDeviceList(); ui->tableWidget->verticalHeader()->setVisible(false); ui->tableWidget->setColumnCount(2); QStringList headers = QString("ID, Название").split(','); ui->tableWidget->setHorizontalHeaderLabels(headers); QHeaderView *header = ui->tableWidget->horizontalHeader(); header->setSectionResizeMode(0, QHeaderView::Stretch); header->setSectionResizeMode(1, QHeaderView::Stretch); QFont headerFont = header->font(); headerFont.setBold(true); header->setFont(headerFont); ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->listWidgetDevices->setSpacing(10); ui->checkBoxIsWorking->setAttribute(Qt::WA_TransparentForMouseEvents); ui->checkBoxIsWorking->setFocusPolicy(Qt::NoFocus); QStringList filterItems = { "Все устройства", "Типы устройств", "Помещения", "Отделы", "Производители", "Модели устройств" }; ui->comboBoxFilters->addItems(filterItems); QStringList sortItems = { "Сначала новые", "Сначала старые", "Сначала дешевые", "Сначала дорогие", "Сначала с лайком" }; ui->comboBoxSort->addItems(sortItems); 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); 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->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())); QFile *styleFile = new QFile(":/styles.qss"); if (styleFile->open(QFile::ReadOnly)) { QTextStream ts(styleFile); QString style = ts.readAll(); qApp->setStyleSheet(style); } } MainWindow::~MainWindow() { delete ui; } void MainWindow::updateTableWidget(int index) { returnToDeviceList(); ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); switch (index) { case 0: // Все устройства clearDevicesOutputSettings(); updateListWidgetDevices(0); break; case 1: // Типы устройств fillTable(mapDeviceTypes); break; case 2: // Помещения fillTable(mapLocations); break; case 3: // Отделы fillTable(mapDepartments); break; case 4: // Производители fillTable(mapManufacturers); break; case 5: // Модели устройств fillTable(mapDeviceModels); break; default: break; } } void MainWindow::updateListWidget() { returnToDeviceList(); int selectedEntityId = getSelectedIndex(); if (selectedEntityId == -1) return; clearDevicesOutputSettings(); updateListWidgetDevices(selectedEntityId); } template void MainWindow::fillTable(const QMap &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::updateListWidgetDevices(int entityId) { client->getFilteredDevices( filterParams.isWorking(), filterParams.priceFrom(), filterParams.priceTo(), filterParams.getApllyFilters(), filterParams.getDisregardState(), entityId, ui->comboBoxFilters->currentIndex(), searchInfo, ui->comboBoxSort->currentText() ); } 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 = device.deviceModel().nameType(); typeName = typeName.left(typeName.length() - 1); if (typeName == "Персональные компьютер") typeName = "Персональный компьютер"; 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 updDevice = device; updDevice.setIsLiked(checked); client->updateDevice(updDevice.id(), updDevice); 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; } 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()); } void MainWindow::returnToDeviceList() { idCard = 0; ui->stackedWidget->setCurrentIndex(0); } void MainWindow::showItemInfo(QListWidgetItem *item) { if (!item) return; 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::showTableWithStructureElements(const QList &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::clearFilters() { ui->radioButtonWorking->setChecked(true); ui->doubleSpinBoxFrom->setValue(0.00); ui->doubleSpinBoxTo->setValue(0.00); filterParams.setIsWorking(true); filterParams.setPriceFrom(-1); filterParams.setPriceTo(-1); filterParams.setDisregardState(false); filterParams.setApllyFilters(false); } void MainWindow::clearDevicesOutputSettings() { ui->comboBoxSort->setCurrentIndex(0); ui->lineEditSearch->setText(""); searchInfo = ""; clearFilters(); } int MainWindow::getSelectedIndex() { QModelIndexList selectedIndexes = ui->tableWidget->selectionModel()->selectedRows(); if (selectedIndexes.isEmpty()) { return -1; } int rowIndex = selectedIndexes.first().row(); return ui->tableWidget->item(rowIndex, 0)->text().toInt(); } void MainWindow::pushButtonBackClicked() { returnToDeviceList(); } void MainWindow::pushButtonClearClicked() { ui->lineEditSearch->setText(""); } void MainWindow::changeSortOrder() { updateListWidgetDevices(getSelectedIndex()); } void MainWindow::pushButtonSearchClicked() { searchInfo = ui->lineEditSearch->text(); if (searchInfo.isEmpty()) { QMessageBox::warning(this, "Ошибка", "Пожалуйста, введите текст для поиска."); return; } ui->comboBoxSort->setCurrentIndex(0); clearFilters(); updateListWidgetDevices(getSelectedIndex()); } void MainWindow::pushButtonApplyFiltersClicked() { double priceFrom = ui->doubleSpinBoxFrom->value(); double priceTo = ui->doubleSpinBoxTo->value(); if (priceFrom > priceTo) { QMessageBox::warning(this, "Ошибка", "Начальное значение диапазона не может быть больше конечного значения."); ui->doubleSpinBoxFrom->setValue(filterParams.priceFrom()); ui->doubleSpinBoxTo->setValue(filterParams.priceTo()); 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::max()); } else { filterParams.setPriceFrom(priceFrom); filterParams.setPriceTo(priceTo); } updateListWidgetDevices(getSelectedIndex()); } void MainWindow::pushButtonCancelFiltersClicked() { clearFilters(); updateListWidgetDevices(getSelectedIndex()); } void MainWindow::pushButtonStructureClicked() { showTableWithStructureElements(mapDevices[idCard].deviceModel().structureElements()); } void MainWindow::pushButtonCharacteristicsClicked() { showTableWithDeviceModelCharacteristics(mapDevices[idCard].deviceModel()); } void MainWindow::pushButtonDefaultClicked() { clearDevicesOutputSettings(); updateListWidgetDevices(getSelectedIndex()); } QMap MainWindow::getMapDeviceModels() const { return mapDeviceModels; } void MainWindow::setMapDevices(const QMap &newMapDevices) { mapDevices = newMapDevices; updateTableWidget(0); connect(client, &ApiClient::devicesReceived, this, [this](const QList &filteredDevices) { ui->listWidgetDevices->clear(); if (filteredDevices.isEmpty()) { 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); } else { for (const auto &device : filteredDevices) { int deviceModelId = device.deviceModel().id(); if (mapDeviceModels.contains(deviceModelId)) { Device updatedDevice = device; updatedDevice.setDeviceModel(mapDeviceModels[deviceModelId]); addDeviceToList(updatedDevice); } else { addDeviceToList(device); } } } }); } void MainWindow::setMapDeviceModels(const QMap &newMapDeviceModels) { mapDeviceModels = newMapDeviceModels; } void MainWindow::setMapDeviceTypes(const QMap &newMapDeviceTypes) { mapDeviceTypes = newMapDeviceTypes; for (int i = 1; i <= mapDeviceTypes.size(); i++) { QString imagePath = QString(":/images/device-type-%1.png").arg(i); deviceTypeImages[i] = imagePath; } } void MainWindow::setMapManufacturers(const QMap &newMapManufacturers) { mapManufacturers = newMapManufacturers; } void MainWindow::setMapDepartments(const QMap &newMapDepartments) { mapDepartments = newMapDepartments; } void MainWindow::setMapLocations(const QMap &newMapLocations) { mapLocations = newMapLocations; } void MainWindow::setClient(ApiClient *newClient) { client = newClient; }