#include "BankSettingsWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dao/ApplicationDAO.h" #include "db/ApplicationInfo.h" #include "net/NetworkService.h" #include "common/PaddedItemDelegate.h" #include "device/EditBankDialog.h" #include "birbank/LoginAndCheckAccountsBirbankScript.h" #include "ozon/LoginAndCheckAccountsScript.h" #include "rshb/LoginAndCheckAccountsScript.h" #include "toss/LoginAndCheckAccountsTossScript.h" #include "widget/common/CollapsibleSection.h" #include "ziraat/LoginAndCheckAccountsZiraatScript.h" QTableWidgetItem *BankSettingsWindow::createTableWidget(const QString &text) { QTableWidgetItem *item = new QTableWidgetItem(text); item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); return item; } QString parseStatus(const ApplicationInfo &app) { if (!app.install) { return "не установлен"; } if (app.status == "active") { if (!app.pinCodeChecked) { return app.pinCode.isEmpty() ? "нет пин-код" : "пин-код не проверен"; } return "работает"; } else if (app.status == "off") { return "выключено"; } else { return app.status; } } void BankSettingsWindow::startCheckPinCode(const QString &appCode) { QThread *thread = new QThread(nullptr); if (appCode == "rshb") { auto *worker = new Rshb::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &Rshb::LoginAndCheckAccountsScript::start); connect(worker, &Rshb::LoginAndCheckAccountsScript::finished, thread, &QThread::quit); connect(worker, &Rshb::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else if (appCode == "ziraat") { auto *worker = new LoginAndCheckAccountsZiraatScript(m_deviceId, appCode, nullptr); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &LoginAndCheckAccountsZiraatScript::start); connect(worker, &LoginAndCheckAccountsZiraatScript::finished, thread, &QThread::quit); connect(worker, &LoginAndCheckAccountsZiraatScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else if (appCode == "ozon") { auto *worker = new Ozon::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &Ozon::LoginAndCheckAccountsScript::start); connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, thread, &QThread::quit); connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else if (appCode == "birbank") { auto *worker = new LoginAndCheckAccountsBirbankScript(m_deviceId, appCode, nullptr); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &LoginAndCheckAccountsBirbankScript::start); connect(worker, &LoginAndCheckAccountsBirbankScript::finished, thread, &QThread::quit); connect(worker, &LoginAndCheckAccountsBirbankScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else if (appCode == "toss") { auto *worker = new LoginAndCheckAccountsTossScript(m_deviceId, appCode, nullptr); worker->moveToThread(thread); connect(thread, &QThread::started, worker, &LoginAndCheckAccountsTossScript::start); connect(worker, &LoginAndCheckAccountsTossScript::finished, thread, &QThread::quit); connect(worker, &LoginAndCheckAccountsTossScript::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); } else { thread->deleteLater(); return; } thread->start(); } void sendAppStatus(const QString &deviceId, const QString &code, const QString &status) { const ApplicationInfo app = ApplicationDAO::getApplication(deviceId, code); if (app.bankProfileId.isEmpty()) { qWarning() << "[BankSettings] sendAppStatus: no bankProfileId for" << code; return; } const bool enable = (status == "active"); auto *thread = new QThread; auto *net = new NetworkService; net->moveToThread(thread); net->addExtra("bank_profile_id", app.bankProfileId); net->addExtra("enable", enable); QObject::connect(thread, &QThread::started, net, &NetworkService::toggleBankProfile); QObject::connect(net, &NetworkService::finished, thread, &QThread::quit); QObject::connect(net, &NetworkService::finished, net, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); thread->start(); } void BankSettingsWindow::reloadContent(QTableWidget *tableWidget) { QList applications = ApplicationDAO::getApplicationsByDeviceId(m_deviceId); tableWidget->setRowCount(applications.length()); tableWidget->setColumnCount(7); tableWidget->setHorizontalHeaderLabels({ "", "Имя", "Пин-код", "Статус", "Комментарий", "", "" }); tableWidget->setWordWrap(true); tableWidget->setTextElideMode(Qt::ElideNone); tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter); for (int i = 0; i < 7; ++i) { tableWidget->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); } for (int i = 0; i < applications.length(); ++i) { tableWidget->verticalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); } 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/" + app.code + "_icon.png"); icon->setPixmap(pixmap); icon->setPixmap(pixmap.scaled(20, 20, Qt::KeepAspectRatio, Qt::SmoothTransformation)); icon->setStyleSheet( "background-color: transparent;" "text-align: center;" "padding:0 4px 0 0;" ); icon->setMinimumSize(24, 20); tableWidget->setCellWidget(k, 0, icon); tableWidget->setItem(k, 1, createTableWidget(app.name)); // QTableWidgetItem *picCodeItem = new QTableWidgetItem(app.pinCode); // picCodeItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); auto *picCode = new QLabel(app.pinCode); if (!app.pinCode.isEmpty() && !app.pinCodeChecked) { picCode->setStyleSheet( "background-color: orange;" "color: white;" ); } picCode->setAlignment(Qt::AlignCenter); tableWidget->setCellWidget(k, 2, picCode); tableWidget->setItem(k, 3, createTableWidget(parseStatus(app))); // tableWidget->setItem(k, 4, createTableWidget(app.comment)); 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); if (app.install) { if (!app.pinCode.isEmpty() && !app.pinCodeChecked) { auto *pinCodeBtn = new QPushButton(" Проверить пин-код ", tableWidget); pinCodeBtn->setProperty("btnClass", "pincode"); tableWidget->setCellWidget(k, 5, pinCodeBtn); connect(pinCodeBtn, &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) { startCheckPinCode(app.code); } }); } else { if (app.status == "active" && !app.pinCode.isEmpty()) { 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,tableWidget, 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) { if (!ApplicationDAO::update(app.id, app.pinCode, app.comment, "off")) { qDebug() << "Cant update bank data"; } else { sendAppStatus(app.deviceId, app.code, "off"); tableWidget->clearContents(); reloadContent(tableWidget); tableWidget->resizeRowsToContents(); } } 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, tableWidget, k,app]() { BankEditDialog dlg(app, this); if (dlg.exec() == QDialog::Accepted) { const QString pinCode = dlg.firstValue(); const QString comment = dlg.secondValue(); bool on = dlg.toggled(); if (!ApplicationDAO::update(app.id, pinCode, comment, on ? "active" : "off")) { qDebug() << "Cant update bank data"; } else { sendAppStatus(app.deviceId, app.code, on ? "active" : "off"); tableWidget->clearContents(); reloadContent(tableWidget); tableWidget->resizeRowsToContents(); } } else { // Пользователь нажал «Cancel» или закрыл окно } }); } } } BankSettingsWindow::BankSettingsWindow(QWidget *parent, QString deviceId, QString deviceName, const ApplicationInfo &app) : 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(800, 400); setMaximumSize(1000, 800); resize(800, 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); 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='pincode'] {" "background-color: orange;" "}" "QPushButton[btnClass='edit'] {" "background-color: green;" "}" "QPushButton[btnClass='delete']:pressed {" "background-color: blue;" "}" "QPushButton[btnClass='edit']:pressed {" "background-color: blue;" "}" ); tableWidget->clearContents(); reloadContent(tableWidget); tableWidget->resizeColumnsToContents(); 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); }