Add bank management functionality with UI and DAO improvements
Introduce `BankSettingsWindow` for managing bank data, added `EditBankDialog` for editing bank details, and created reusable `PaddedItemDelegate` for list padding. Refactor DAO to support fetching multiple applications by device ID for improved data handling. Adjust existing components to integrate new bank-related features.
This commit is contained in:
parent
ba0b6763a2
commit
dd66adf455
@ -260,7 +260,7 @@ void PayByPhoneScript::makePayment(
|
||||
|
||||
void PayByPhoneScript::doStart() {
|
||||
const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId);
|
||||
const ApplicationInfo app = ApplicationDAO::getApplicationsByDeviceId(m_account.deviceId, m_account.appName);
|
||||
const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appName);
|
||||
|
||||
if (device.id.isEmpty() || app.id.isEmpty()) {
|
||||
m_error = "Device or app not found....";
|
||||
|
||||
Binary file not shown.
@ -59,7 +59,20 @@ bool ApplicationDAO::updatePinCode(const QString &appId, const QString &pinCode)
|
||||
return true;
|
||||
}
|
||||
|
||||
ApplicationInfo ApplicationDAO::getApplicationsByDeviceId(const QString &deviceId, const QString &appName) {
|
||||
ApplicationInfo parseApplication(const QSqlQuery &query) {
|
||||
ApplicationInfo app;
|
||||
app.id = query.value("id").toString();
|
||||
app.deviceId = query.value("device_id").toString();
|
||||
app.pinCode = query.value("pin_code").toString();
|
||||
app.name = query.value("name").toString();
|
||||
app.package = query.value("package").toString();
|
||||
app.status = query.value("status").toString();
|
||||
app.comment = query.value("comment").toString();
|
||||
app.image = query.value("image").toByteArray();
|
||||
return app;
|
||||
}
|
||||
|
||||
ApplicationInfo ApplicationDAO::getApplication(const QString &deviceId, const QString &appName) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
|
||||
query.prepare(R"(
|
||||
@ -78,17 +91,30 @@ ApplicationInfo ApplicationDAO::getApplicationsByDeviceId(const QString &deviceI
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
ApplicationInfo app;
|
||||
app.id = query.value("id").toString();
|
||||
app.deviceId = query.value("device_id").toString();
|
||||
app.pinCode = query.value("pin_code").toString();
|
||||
app.name = query.value("name").toString();
|
||||
app.package = query.value("package").toString();
|
||||
app.status = query.value("status").toString();
|
||||
app.comment = query.value("comment").toString();
|
||||
app.image = query.value("image").toByteArray();
|
||||
return app;
|
||||
return parseApplication(query);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<ApplicationInfo> ApplicationDAO::getApplicationsByDeviceId(const QString &deviceId) {
|
||||
QSqlQuery query(DatabaseManager::instance().database());
|
||||
QList<ApplicationInfo> list;
|
||||
query.prepare(R"(
|
||||
SELECT id, device_id, pin_code, name, package, status, comment, image
|
||||
FROM applications
|
||||
WHERE device_id = :device_id
|
||||
)");
|
||||
|
||||
query.bindValue(":device_id", deviceId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Ошибка при получении приложений по deviceId:" << query.lastError().text();
|
||||
return {};
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
list.append(parseApplication(query));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -8,5 +8,7 @@ public:
|
||||
|
||||
[[nodiscard]] static bool updatePinCode(const QString &appId, const QString &pinCode);
|
||||
|
||||
[[nodiscard]] static ApplicationInfo getApplicationsByDeviceId(const QString &deviceId, const QString &appName);
|
||||
[[nodiscard]] static ApplicationInfo getApplication(const QString &deviceId, const QString &appName);
|
||||
|
||||
[[nodiscard]] static QList<ApplicationInfo> getApplicationsByDeviceId(const QString &deviceId);
|
||||
};
|
||||
|
||||
221
views/bank/BankSettingsWindow.cpp
Normal file
221
views/bank/BankSettingsWindow.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "BankSettingsWindow.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QHeaderView>
|
||||
#include <QScrollArea>
|
||||
#include <QCoreApplication>
|
||||
#include <QPushButton>
|
||||
#include <QTableWidget>
|
||||
#include <utility>
|
||||
#include <QMessageBox>
|
||||
#include <QLabel>
|
||||
#include <QDialog>
|
||||
|
||||
#include "dao/ApplicationDAO.h"
|
||||
#include "db/ApplicationInfo.h"
|
||||
#include "common/PaddedItemDelegate.h"
|
||||
#include "device/EditBankDialog.h"
|
||||
#include "widget/common/CollapsibleSection.h"
|
||||
|
||||
QTableWidgetItem *BankSettingsWindow::createTableWidget(const QString &text) {
|
||||
QTableWidgetItem *item = new QTableWidgetItem(text);
|
||||
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
return item;
|
||||
}
|
||||
|
||||
BankSettingsWindow::BankSettingsWindow(QWidget *parent, QString deviceId, QString deviceName)
|
||||
: QWidget(parent,
|
||||
Qt::Window
|
||||
| Qt::WindowTitleHint
|
||||
| Qt::WindowSystemMenuHint
|
||||
| Qt::WindowCloseButtonHint
|
||||
| Qt::WindowMinMaxButtonsHint),
|
||||
m_deviceId(std::move(deviceId)),
|
||||
m_deviceName(std::move(deviceName)
|
||||
) {
|
||||
setWindowTitle("Настройки банка [" + m_deviceName + "]");
|
||||
setMinimumSize(820, 400);
|
||||
setMaximumSize(820, 400);
|
||||
resize(820, 400);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout(this);
|
||||
|
||||
// Скролл-область
|
||||
auto *scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
|
||||
// Виджет-контейнер, в котором будет layout с таблицами и лейблами
|
||||
auto *contentWidget = new QWidget;
|
||||
auto *layout = new QVBoxLayout(contentWidget);
|
||||
|
||||
// Убираем отступы и рамку
|
||||
contentWidget->setContentsMargins(0, 0, 0, 0); // Убираем отступы
|
||||
layout->setContentsMargins(0, 0, 0, 0); // Убираем отступы у layout
|
||||
scrollArea->setStyleSheet("border: none;"); // Убираем рамку
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
|
||||
QList<ApplicationInfo> applications = ApplicationDAO::getApplicationsByDeviceId(m_deviceId);
|
||||
|
||||
QTableWidget *tableWidget = new QTableWidget(this);
|
||||
tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
tableWidget->setFocusPolicy(Qt::NoFocus);
|
||||
tableWidget->setStyleSheet(
|
||||
"QTableWidget {"
|
||||
" border: 1px solid grey;"
|
||||
// " gridline-color: lightgrey;"
|
||||
// " background-color: #f9f9f9;"
|
||||
" font-size: 14px;"
|
||||
"}"
|
||||
"QHeaderView::section {"
|
||||
// " background-color: #e0e0e0;"
|
||||
// " border: 1px solid grey;"
|
||||
" padding: 4px;"
|
||||
" font-weight: bold;"
|
||||
" text-align: left center;"
|
||||
"}"
|
||||
"QTableWidget::item {"
|
||||
" padding: 2px;"
|
||||
" border: none;"
|
||||
" text-align: left;"
|
||||
" vertical-align: middle; "
|
||||
"}"
|
||||
"QTableWidget::item:selected {"
|
||||
// " background-color: #cce5ff;"
|
||||
// " color: #003366;"
|
||||
"}"
|
||||
"QTableCornerButton::section {"
|
||||
// " background-color: #e0e0e0;"
|
||||
// " border: 1px solid grey;"
|
||||
"}"
|
||||
"QPushButton {"
|
||||
"border-radius: 4px;"
|
||||
"height: 26px;"
|
||||
"}"
|
||||
"QPushButton[btnClass='delete'] {"
|
||||
"background-color: red;"
|
||||
"}"
|
||||
"QPushButton[btnClass='edit'] {"
|
||||
"background-color: green;"
|
||||
"}"
|
||||
"QPushButton[btnClass='delete']:pressed {"
|
||||
"background-color: blue;"
|
||||
"}"
|
||||
"QPushButton[btnClass='edit']:pressed {"
|
||||
"background-color: blue;"
|
||||
"}"
|
||||
);
|
||||
tableWidget->setRowCount(applications.length());
|
||||
tableWidget->setColumnCount(7);
|
||||
tableWidget->setHorizontalHeaderLabels({
|
||||
"",
|
||||
"Имя",
|
||||
"Пин-код",
|
||||
"Статус",
|
||||
"Комментарий",
|
||||
"",
|
||||
""
|
||||
});
|
||||
|
||||
tableWidget->setWordWrap(true);
|
||||
tableWidget->setTextElideMode(Qt::ElideNone);
|
||||
|
||||
QMargins cellPadding{8, 4, 8, 4};
|
||||
auto *delegate = new PaddedItemDelegate(cellPadding, tableWidget);
|
||||
tableWidget->setItemDelegateForColumn(1, delegate);
|
||||
tableWidget->setItemDelegateForColumn(2, delegate);
|
||||
tableWidget->setItemDelegateForColumn(3, delegate);
|
||||
tableWidget->setItemDelegateForColumn(4, delegate);
|
||||
|
||||
tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);
|
||||
|
||||
|
||||
for (int k = 0; k < applications.size(); ++k) {
|
||||
const ApplicationInfo &app = applications[k];
|
||||
|
||||
|
||||
auto *icon = new QLabel(tableWidget);
|
||||
QPixmap pixmap(QCoreApplication::applicationDirPath() + "/images/alfa_icon.png");
|
||||
icon->setPixmap(pixmap);
|
||||
icon->setPixmap(pixmap.scaled(20, 20, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
icon->setStyleSheet(
|
||||
"background-color: transparent;"
|
||||
"padding:0 4px 0 0;"
|
||||
);
|
||||
icon->setMinimumSize(24, 20);
|
||||
tableWidget->setCellWidget(k, 0, icon);
|
||||
|
||||
tableWidget->setItem(k, 1, createTableWidget(app.name == "rshb" ? "Россельхозбанк" : app.name));
|
||||
tableWidget->setItem(k, 2, createTableWidget(app.pinCode));
|
||||
tableWidget->setItem(k, 3, createTableWidget(app.status));
|
||||
|
||||
QTableWidgetItem *item = new QTableWidgetItem(app.comment);
|
||||
item->setTextAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||
item->setSizeHint(QSize(100, app.comment.length() / 2)); // Минимальная высота ячейки для переноса
|
||||
tableWidget->setItem(k, 4, item);
|
||||
|
||||
// auto *deleteBtnItem = new QTableWidgetItem;
|
||||
// tableWidget->setItem(k, 4, deleteBtnItem);
|
||||
auto *deleteBtn = new QPushButton(" Удалить ", tableWidget);
|
||||
deleteBtn->setProperty("btnClass", "delete");
|
||||
// deleteBtn->setStyleSheet("padding: 4px 8px;");
|
||||
// deleteBtn->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
||||
tableWidget->setCellWidget(k, 5, deleteBtn);
|
||||
|
||||
connect(deleteBtn, &QPushButton::clicked, this, [this, app]() {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setWindowTitle(tr("Подтверждение"));
|
||||
msgBox.setText("Точно удалить все данные банка: " + app.name + "?");
|
||||
// добавляем свои кнопки с нужными надписями
|
||||
QPushButton *deleteBtn = msgBox.addButton(tr("Удалить"), QMessageBox::AcceptRole);
|
||||
QPushButton *closeBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole);
|
||||
// по умолчанию фокус на «Закрыть»
|
||||
msgBox.setDefaultButton(closeBtn);
|
||||
// делаем окно модальным и блокируем всё остальное
|
||||
msgBox.setModal(true);
|
||||
msgBox.exec(); // <-- блокирует до закрытия сообщения
|
||||
|
||||
if (msgBox.clickedButton() == deleteBtn) {
|
||||
// тут выполняем удаление
|
||||
} else {
|
||||
// просто закрыли — ничего не делаем
|
||||
}
|
||||
});
|
||||
|
||||
// auto *editBtn = new QTableWidgetItem;
|
||||
// tableWidget->setItem(k, 5, editBtn);
|
||||
auto *btn = new QPushButton(" Редактировать ", tableWidget);
|
||||
btn->setProperty("btnClass", "edit");
|
||||
// btn->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
||||
tableWidget->setCellWidget(k, 6, btn);
|
||||
connect(btn, &QPushButton::clicked, this, [this]() {
|
||||
BankEditDialog dlg(this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
// Пользователь нажал «OK»
|
||||
QString v1 = dlg.firstValue();
|
||||
QString v2 = dlg.secondValue();
|
||||
bool on = dlg.toggled();
|
||||
// … обработка значений …
|
||||
} else {
|
||||
// Пользователь нажал «Cancel» или закрыл окно
|
||||
}
|
||||
});
|
||||
}
|
||||
layout->addWidget(tableWidget);
|
||||
tableWidget->resizeRowsToContents();
|
||||
|
||||
// Добавим вертикальный Spacer в конец, чтобы прокручиваемая область не растягивала контент
|
||||
// QSpacerItem *spacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
// layout->addItem(spacer);
|
||||
|
||||
contentWidget->setLayout(layout);
|
||||
scrollArea->setWidget(contentWidget);
|
||||
mainLayout->addWidget(scrollArea);
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
16
views/bank/BankSettingsWindow.h
Normal file
16
views/bank/BankSettingsWindow.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <qtablewidget.h>
|
||||
#include <QWidget>
|
||||
|
||||
class BankSettingsWindow final : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BankSettingsWindow(QWidget *parent, QString deviceId, QString deviceName);
|
||||
|
||||
private:
|
||||
QString m_deviceId;
|
||||
QString m_deviceName;
|
||||
|
||||
QTableWidgetItem *createTableWidget(const QString &text);
|
||||
};
|
||||
35
views/common/PaddedItemDelegate.h
Normal file
35
views/common/PaddedItemDelegate.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QMargins>
|
||||
|
||||
class PaddedItemDelegate final : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PaddedItemDelegate(const QMargins &margins, QObject *parent = nullptr)
|
||||
: QStyledItemDelegate(parent), m_margins(margins) {
|
||||
}
|
||||
|
||||
void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override {
|
||||
QStyledItemDelegate::initStyleOption(option, index);
|
||||
// «вырезаем» рамки со всех сторон
|
||||
option->rect = option->rect.adjusted(
|
||||
m_margins.left(),
|
||||
m_margins.top(),
|
||||
-m_margins.right(),
|
||||
-m_margins.bottom()
|
||||
);
|
||||
}
|
||||
|
||||
// расширяем sizeHint — чтобы ResizeToContents «увидел» отступы
|
||||
[[nodiscard]] QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override {
|
||||
const QSize baseSize = QStyledItemDelegate::sizeHint(option, index);
|
||||
return QSize(
|
||||
baseSize.width() + m_margins.left() + m_margins.right(),
|
||||
baseSize.height() + m_margins.top() + m_margins.bottom()
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
QMargins m_margins;
|
||||
};
|
||||
@ -5,6 +5,9 @@
|
||||
#include <QImage>
|
||||
#include <QPushButton>
|
||||
#include <QCoreApplication>
|
||||
#include <QPointer>
|
||||
#include "bank/BankSettingsWindow.h"
|
||||
|
||||
|
||||
DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(parent) {
|
||||
auto *layout = new QGridLayout(this);
|
||||
@ -89,7 +92,6 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
|
||||
"border-radius: 6px;"
|
||||
);
|
||||
|
||||
// 3) две кнопки
|
||||
auto *btn1 = new QPushButton(overlay);
|
||||
QIcon btnIcon(QCoreApplication::applicationDirPath() + "/images/turn_on.png");
|
||||
btn1->setIcon(btnIcon);
|
||||
@ -112,7 +114,6 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
|
||||
"border: none;"
|
||||
);
|
||||
|
||||
|
||||
// собираем
|
||||
hbox->addWidget(icon);
|
||||
hbox->addWidget(label);
|
||||
@ -125,7 +126,37 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
|
||||
}
|
||||
vbox->addStretch();
|
||||
|
||||
|
||||
// кладём overlay в ту же ячейку, что и картинку,
|
||||
// но выравниваем его по левому-нижнему углу
|
||||
layout->addWidget(overlay, 0, 0, Qt::AlignLeft | Qt::AlignBottom);
|
||||
|
||||
auto *addBankBtn = new QPushButton(this);
|
||||
addBankBtn->setMaximumWidth(300);
|
||||
addBankBtn->setText("Добавить банк +");
|
||||
addBankBtn->setStyleSheet(
|
||||
"background-color: #fff;"
|
||||
"margin-top: 2px;"
|
||||
"padding: 4px;"
|
||||
"color: #000;"
|
||||
);
|
||||
|
||||
QString deviceId = device.id;
|
||||
QString deviceName = device.name;
|
||||
connect(addBankBtn, &QPushButton::clicked, this, [deviceId, deviceName]() {
|
||||
static QPointer<BankSettingsWindow> bankSettingsWindow;
|
||||
|
||||
// Если окна нет (либо ещё не было создано, либо уже удалилось) — создаём заново
|
||||
if (!bankSettingsWindow) {
|
||||
bankSettingsWindow = new BankSettingsWindow(nullptr, deviceId, deviceName);
|
||||
bankSettingsWindow->setWindowFlags(bankSettingsWindow->windowFlags() | Qt::Window);
|
||||
bankSettingsWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
// Показать/поднять/активировать
|
||||
bankSettingsWindow->show();
|
||||
bankSettingsWindow->raise();
|
||||
bankSettingsWindow->activateWindow();
|
||||
});
|
||||
layout->addWidget(addBankBtn, 1, 0);
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <qtablewidget.h>
|
||||
#include <QWidget>
|
||||
#include "db/DeviceInfo.h"
|
||||
|
||||
|
||||
48
views/device/EditBankDialog.h
Normal file
48
views/device/EditBankDialog.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include <QDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QCheckBox>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
// 1) Определяем диалог
|
||||
class BankEditDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BankEditDialog(QWidget *parent = nullptr) : QDialog(parent) {
|
||||
|
||||
setWindowTitle(tr("Введите данные"));
|
||||
setModal(true); // делаем его модальным
|
||||
|
||||
// 2) Форма с полями
|
||||
auto *form = new QFormLayout(this);
|
||||
firstEdit = new QLineEdit(this);
|
||||
secondEdit = new QLineEdit(this);
|
||||
toggle = new QCheckBox(tr("Включено"), this);
|
||||
|
||||
form->addRow(tr("Первое поле:"), firstEdit);
|
||||
form->addRow(tr("Второе поле:"), secondEdit);
|
||||
form->addRow(QString(), toggle);
|
||||
|
||||
// 3) Кнопки OK / Cancel
|
||||
auto *buttons = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||
Qt::Horizontal,
|
||||
this
|
||||
);
|
||||
form->addRow(buttons);
|
||||
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
QString firstValue() const { return firstEdit->text(); }
|
||||
QString secondValue() const { return secondEdit->text(); }
|
||||
bool toggled() const { return toggle->isChecked(); }
|
||||
|
||||
private:
|
||||
QLineEdit *firstEdit;
|
||||
QLineEdit *secondEdit;
|
||||
QCheckBox *toggle;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user