500 lines
16 KiB
C++
500 lines
16 KiB
C++
#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->listWidgetProjects->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);
|
||
|
||
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->listWidgetProjects, 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->pushButtonCanselFilters, SIGNAL(clicked()), this, SLOT(pushButtonCancelFiltersClicked()));
|
||
connect(ui->pushButtonDefault, SIGNAL(clicked()), this, SLOT(pushButtonDefaultClicked()));
|
||
|
||
QFile styleFile(":/styles.qss");
|
||
if (styleFile.open(QFile::ReadOnly)) {
|
||
QTextStream ts(&styleFile);
|
||
QString style = ts.readAll();
|
||
qApp->setStyleSheet(style);
|
||
}
|
||
}
|
||
|
||
MainWindow::~MainWindow()
|
||
{
|
||
delete ui;
|
||
}
|
||
|
||
void MainWindow::getStages(QMap<int, Stages> &map)
|
||
{
|
||
mapStages = map;
|
||
}
|
||
|
||
void MainWindow::getTeams(QMap<int, Team> &map)
|
||
{
|
||
mapTeams = map;
|
||
}
|
||
|
||
void MainWindow::getWorkers(QMap<int, Worker> &map)
|
||
{
|
||
mapWorkers = map;
|
||
}
|
||
|
||
void MainWindow::getDeviceTypes(QMap<int, DeviceType> &map)
|
||
{
|
||
mapDeviceTypes = map;
|
||
for (int i = 1; i <= mapDeviceTypes.size(); i++) {
|
||
QString imagePath = QString(":/images/device-type-%1.png").arg(i);
|
||
deviceTypeImages[i] = imagePath;
|
||
}
|
||
}
|
||
|
||
void MainWindow::getDeviceModels(QMap<int, DeviceModel> &map)
|
||
{
|
||
mapDeviceModels = map;
|
||
}
|
||
|
||
void MainWindow::getProjects(QMap<int, Project> &map)
|
||
{
|
||
mapDevices = map;
|
||
updateTableWidget(0);
|
||
}
|
||
|
||
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<Stages>(mapStages);
|
||
break;
|
||
case 3: // Команды
|
||
fillTable<Team>(mapTeams);
|
||
break;
|
||
case 4: // Работники
|
||
fillTable<Worker>(mapWorkers);
|
||
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)
|
||
{
|
||
ui->listWidgetProjects->clear();
|
||
|
||
auto filteredDevices = logic->findDevicesByAllParameters(
|
||
mapDevices,
|
||
entityId,
|
||
ui->comboBoxFilters->currentIndex(),
|
||
searchInfo,
|
||
filterParams,
|
||
ui->comboBoxSort->currentText()
|
||
);
|
||
|
||
if (filteredDevices.isEmpty()) {
|
||
QListWidgetItem *item = new QListWidgetItem(ui->listWidgetProjects);
|
||
ui->listWidgetProjects->addItem(item);
|
||
QWidget *cardWidget = createMessageEmptyCard();
|
||
item->setSizeHint(cardWidget->minimumSizeHint());
|
||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
||
ui->listWidgetProjects->setItemWidget(item, cardWidget);
|
||
} else {
|
||
for (auto &device : filteredDevices) {
|
||
addDeviceToList(device);
|
||
}
|
||
}
|
||
}
|
||
|
||
QWidget *MainWindow::createMessageEmptyCard()
|
||
{
|
||
QWidget *cardWidget = new QWidget(ui->listWidgetProjects);
|
||
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 Project &project)
|
||
{
|
||
QWidget *cardWidget = new QWidget(ui->listWidgetProjects);
|
||
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[project.deviceModel().idType()];
|
||
QPixmap pixmap(imagePath);
|
||
imageLabel->setPixmap(pixmap.scaled(100, 100, Qt::KeepAspectRatio));
|
||
|
||
iconTextlayout->addWidget(imageLabel);
|
||
|
||
QVBoxLayout *textLayout = new QVBoxLayout();
|
||
|
||
QLabel *serialNumberLabel = new QLabel(project.name(), cardWidget);
|
||
QFont serialNumberFont("Arial", 14, QFont::Bold);
|
||
serialNumberLabel->setFont(serialNumberFont);
|
||
textLayout->addWidget(serialNumberLabel);
|
||
|
||
QFont generalFont("Arial", 11);
|
||
|
||
QString typeName = project.deviceModel().nameType();
|
||
typeName = typeName.left(typeName.length());
|
||
if (typeName == "Персональные компьютер")
|
||
typeName = "Персональный компьютер";
|
||
QLabel *typeNameLabel = new QLabel(typeName + ": " + project.deviceModel().name(), cardWidget);
|
||
typeNameLabel->setFont(generalFont);
|
||
textLayout->addWidget(typeNameLabel);
|
||
|
||
QLabel *statusLabel = new QLabel(project.isReady() ? "Готов" : "Не готов", cardWidget);
|
||
statusLabel->setFont(generalFont);
|
||
textLayout->addWidget(statusLabel);
|
||
|
||
QHBoxLayout *priceLikeLayout = new QHBoxLayout();
|
||
priceLikeLayout->setSpacing(100);
|
||
|
||
QLabel *priceLabel = new QLabel(QString::number(project.budget()) + " ₽", 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(project.isLiked());
|
||
likeCheckBox->setFont(generalFont);
|
||
likeCheckBox->setStyleSheet(likeCheckBox->isChecked() ? "color: green;" : "color: black;");
|
||
|
||
connect(likeCheckBox, &QCheckBox::toggled, this, [this, project, likeCheckBox](bool checked) {
|
||
Project& deviceRef = mapDevices[project.id()];
|
||
deviceRef.setIsLiked(checked);
|
||
|
||
QString message = checked ? "Проект добавлен в избранное." : "Проект удален из избранного.";
|
||
QMessageBox::information(this, "Обновление", message);
|
||
|
||
likeCheckBox->setStyleSheet(checked ? "color: green;" : "color: black;");
|
||
});
|
||
|
||
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 Project &device)
|
||
{
|
||
QListWidgetItem *item = new QListWidgetItem(ui->listWidgetProjects);
|
||
ui->listWidgetProjects->addItem(item);
|
||
|
||
QWidget *cardWidget = createDeviceCard(device);
|
||
|
||
item->setSizeHint(cardWidget->minimumSizeHint());
|
||
ui->listWidgetProjects->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();
|
||
Project device = mapDevices[deviceId];
|
||
|
||
idCard = deviceId;
|
||
if (!device.StartProjectDate().isValid())
|
||
qDebug() << "StartProjectDate is invalid for device ID:" << device.id();
|
||
if (!device.FinishProjectDate().isValid())
|
||
qDebug() << "FinishProjectDate is invalid for device ID:" << device.id();
|
||
ui->lineEditId->setText(QString::number(device.id()));
|
||
ui->lineEditSerialNum->setText(device.name());
|
||
ui->lineEditPrice->setText(QString::number(device.budget(), 'f', 2));
|
||
ui->lineEditEmployee->setText(device.nameTeam());
|
||
ui->lineEditModel->setText(device.deviceModel().name());
|
||
ui->lineEditType->setText(device.deviceModel().nameType());
|
||
ui->textEditFurtherInformation->setPlainText(device.description());
|
||
ui->checkBoxIsWorking->setChecked(device.isReady());
|
||
|
||
ui->stackedWidget->setCurrentIndex(1);
|
||
}
|
||
|
||
void MainWindow::clearFilters()
|
||
{
|
||
ui->radioButtonWorking->setChecked(true);
|
||
ui->doubleSpinBoxFrom->setValue(0.00);
|
||
ui->doubleSpinBoxTo->setValue(0.00);
|
||
filterParams.setIsReady(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.setIsReady(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::pushButtonDefaultClicked()
|
||
{
|
||
clearDevicesOutputSettings();
|
||
updateListWidgetDevices(getSelectedIndex());
|
||
}
|
||
|
||
void MainWindow::closeEvent(QCloseEvent *event)
|
||
{
|
||
ServiceLoadDB serviceLoadDB;
|
||
serviceLoadDB.updateLikesState(mapDevices);
|
||
|
||
event->accept();
|
||
}
|
||
|