PNP_PIbd-31_Rodionov_I_A_Co.../mainwindow.cpp
2024-12-24 18:13:22 +04:00

641 lines
23 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);
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<DeviceType>(mapDeviceTypes);
break;
case 2: // Помещения
fillTable<Location>(mapLocations);
break;
case 3: // Отделы
fillTable<Department>(mapDepartments);
break;
case 4: // Производители
fillTable<Manufacturer>(mapManufacturers);
break;
case 5: // Модели устройств
fillTable<DeviceModel>(mapDeviceModels);
break;
default:
break;
}
}
void MainWindow::updateListWidget()
{
returnToDeviceList();
int selectedEntityId = getSelectedIndex();
if (selectedEntityId == -1)
return;
clearDevicesOutputSettings();
updateListWidgetDevices(selectedEntityId);
}
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::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<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::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<double>::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<int, DeviceModel> MainWindow::getMapDeviceModels() const
{
return mapDeviceModels;
}
void MainWindow::setMapDevices(const QMap<int, Device> &newMapDevices)
{
mapDevices = newMapDevices;
updateTableWidget(0);
connect(client, &ApiClient::devicesReceived, this, [this](const QList<Device> &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<int, DeviceModel> &newMapDeviceModels)
{
mapDeviceModels = newMapDeviceModels;
}
void MainWindow::setMapDeviceTypes(const QMap<int, DeviceType> &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<int, Manufacturer> &newMapManufacturers)
{
mapManufacturers = newMapManufacturers;
}
void MainWindow::setMapDepartments(const QMap<int, Department> &newMapDepartments)
{
mapDepartments = newMapDepartments;
}
void MainWindow::setMapLocations(const QMap<int, Location> &newMapLocations)
{
mapLocations = newMapLocations;
}
void MainWindow::setClient(ApiClient *newClient)
{
client = newClient;
}