#include "AccountSettingsWindow.h" #include #include #include #include #include #include #include #include #include #include #include "birbank/LoginAndCheckAccountsBirbankScript.h" #include "toss/LoginAndCheckAccountsTossScript.h" #include "dao/AccountDAO.h" #include "dao/ApplicationDAO.h" #include "device/EditBankAccountDialog.h" #include "device/EditBankDialog.h" #include "net/NetworkService.h" AccountSettingsWindow::AccountSettingsWindow( 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)), m_applicationInfo(app) { setWindowTitle("Настройки банка [" + app.name + "]"); setMinimumSize(800, 400); setMaximumSize(1000, 800); resize(800, 400); // 1. Редактирование пин-кода // 2. Включение/отключения банка // 3. Работа с картами (вкл/выкл) и редактирование цифр // 4. Запуск проверки пин-код и парсинга аккаунтов 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(4, 4, 4, 4); // Убираем отступы у layout // scrollArea->setStyleSheet("border: none;"); // Убираем рамку layout->setAlignment(Qt::AlignTop); QHBoxLayout *row1 = new QHBoxLayout(); QString status = QString("Статус: ") + (m_applicationInfo.status == "active" ? "Активен" : "Неактивен") + QString(", пин-код: ") + (m_applicationInfo.pinCodeChecked ? "Проверен" : "Не проверен"); m_statusLabel = new QLabel(status); m_statusLabel->setTextFormat(Qt::RichText); row1->addWidget(m_statusLabel); QPushButton *editBankBtn = new QPushButton("Редактировать"); editBankBtn->setStyleSheet( "background-color: green;" "color: white;" ); editBankBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); row1->addWidget(editBankBtn); connect(editBankBtn, &QPushButton::clicked, this, [this]() { BankEditDialog dlg(m_applicationInfo, this); if (dlg.exec() == QDialog::Accepted) { const QString pinCode = dlg.firstValue(); const QString comment = dlg.secondValue(); bool on = dlg.toggled(); if (!ApplicationDAO::update(m_applicationInfo.id, pinCode, comment, on ? "active" : "off")) { qDebug() << "Cant update bank data"; } else { m_applicationInfo.pinCode = pinCode; m_applicationInfo.comment = comment; m_applicationInfo.status = on ? "active" : "off"; QString status = QString("Статус: ") + (on ? "Активен" : "Неактивен") + QString(", пин-код: ") + (m_applicationInfo.pinCodeChecked ? "Проверен" : "Не проверен"); m_statusLabel->setText(status); m_commentLabel->setText(comment); sendAppStatus(m_applicationInfo.deviceId, m_applicationInfo.code, on ? "active" : "off"); } } }); layout->addLayout(row1); QHBoxLayout *commentRow = new QHBoxLayout(); m_commentLabel = new QLabel(m_applicationInfo.comment); m_commentLabel->setStyleSheet( "color: gray;" "margin-bottom: 8px;" ); commentRow->addWidget(m_commentLabel); layout->addLayout(commentRow); QPushButton *soloButton = new QPushButton("Запустить проверку пин-кода"); soloButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); // soloButton->setStyleSheet(""); soloButton->setStyleSheet( "background-color: orange;" "color: white;" ); QObject::connect(soloButton, &QPushButton::clicked, [&, this]() { if (!m_applicationInfo.pinCode.isEmpty()) { QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Запустить проверку пин-кода?")); msgBox.setText( "Запуститься скрипт проверки входа в банк " + m_applicationInfo.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(m_applicationInfo.code); close(); } } }); layout->addWidget(soloButton); layout->addWidget(new QLabel("Счета")); QTableWidget *tableWidget = new QTableWidget(this); tableWidget->setSelectionMode(QAbstractItemView::NoSelection); tableWidget->setFocusPolicy(Qt::NoFocus); reloadContent(tableWidget); tableWidget->resizeColumnsToContents(); layout->addWidget(tableWidget); QPushButton *addAccountButton = new QPushButton("Добавить аккаунт"); addAccountButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); AccountInfo account; connect(addAccountButton, &QPushButton::clicked, this, [this, tableWidget, account]() { EditBankAccountDialog dlg(account, this); if (dlg.exec() == QDialog::Accepted) { const QString cardNumber = dlg.cardNumberValue(); const QString currency = dlg.currencyValue(); bool on = dlg.toggled(); AccountInfo accountInfo; accountInfo.currency = currency; accountInfo.description = cardNumber; accountInfo.amount = 0; accountInfo.appCode = m_applicationInfo.code; accountInfo.deviceId = m_deviceId; accountInfo.status = on ? AccountStatus::Active : AccountStatus::Off; accountInfo.lastNumbers = cardNumber.right(4); if (!AccountDAO::upsertAccount(accountInfo)) { qDebug() << "Cant insert bank account data"; } else { reloadContent(tableWidget); tableWidget->resizeColumnsToContents(); updateAccountData(accountInfo); } } }); layout->addWidget(addAccountButton); 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); } void AccountSettingsWindow::startCheckPinCode(const QString &appCode) { if (appCode == "birbank") { const auto thread = new QThread(nullptr); 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); thread->start(); } else if (appCode == "toss") { const auto thread = new QThread(nullptr); 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); thread->start(); } } void AccountSettingsWindow::sendAppStatus(const QString &deviceId, const QString &code, const QString &status) { QJsonObject obj; obj["code"] = code; obj["status"] = status; auto *paymentThread = new QThread; auto *networkService = new NetworkService; networkService->moveToThread(paymentThread); networkService->setDeviceId(deviceId); networkService->setPayload(QJsonDocument(obj).toJson()); QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAppStatus); QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit); QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater); QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater); paymentThread->start(); } void AccountSettingsWindow::updateAccountData(const AccountInfo &account) { QJsonArray list; QJsonObject obj; obj["appName"] = account.appCode; obj["lastNumbers"] = account.lastNumbers; obj["amount"] = account.amount; obj["description"] = account.description; obj["currency"] = account.currency; obj["status"] = accountStatusToString(account.status); list.append(obj); auto *paymentThread = new QThread; auto *networkService = new NetworkService; networkService->moveToThread(paymentThread); networkService->setDeviceId(account.deviceId); networkService->setPayload(QJsonDocument(list).toJson()); QObject::connect(paymentThread, &QThread::started, networkService, &NetworkService::postAccountsData); QObject::connect(networkService, &NetworkService::finished, paymentThread, &QThread::quit); QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater); QObject::connect(paymentThread, &QThread::finished, paymentThread, &QThread::deleteLater); paymentThread->start(); } void AccountSettingsWindow::reloadContent(QTableWidget *tableWidget) { QList accounts = AccountDAO::getAccounts(m_deviceId, m_applicationInfo.code); tableWidget->clearContents(); tableWidget->setRowCount(accounts.length()); tableWidget->setColumnCount(7); tableWidget->setHorizontalHeaderLabels({ "Время обновления", "Номер", "", "Сумма", "Валюта", "Статус", "" }); tableWidget->setWordWrap(true); tableWidget->setTextElideMode(Qt::ElideNone); tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter); tableWidget->horizontalHeader()->setSectionResizeMode(5, QHeaderView::ResizeToContents); tableWidget->verticalHeader()->setSectionResizeMode(6, QHeaderView::ResizeToContents); tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); for (int k = 0; k < accounts.size(); ++k) { const AccountInfo &account = accounts[k]; QTableWidgetItem *time = new QTableWidgetItem(account.updateTime.toString("dd.MM.yyyy HH:mm:ss")); time->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); time->setFlags(time->flags() & ~Qt::ItemIsEditable); tableWidget->setItem(k, 0, time); QTableWidgetItem *desc = new QTableWidgetItem(account.description); desc->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); desc->setFlags(desc->flags() & ~Qt::ItemIsEditable); tableWidget->setItem(k, 1, desc); QTableWidgetItem *lastNumbers = new QTableWidgetItem(account.lastNumbers); lastNumbers->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); lastNumbers->setFlags(lastNumbers->flags() & ~Qt::ItemIsEditable); tableWidget->setItem(k, 2, lastNumbers); QTableWidgetItem *amount = new QTableWidgetItem(QString::number(account.amount)); amount->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); amount->setFlags(amount->flags() & ~Qt::ItemIsEditable); tableWidget->setItem(k, 3, amount); QTableWidgetItem *currency = new QTableWidgetItem(account.currency); currency->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); currency->setFlags(currency->flags() & ~Qt::ItemIsEditable); tableWidget->setItem(k, 4, currency); QTableWidgetItem *status = new QTableWidgetItem(accountStatusToUiString(account.status)); status->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); status->setFlags(status->flags() & ~Qt::ItemIsEditable); if (account.status != AccountStatus::Active) { status->setForeground(QBrush(Qt::red)); } tableWidget->setItem(k, 5, status); auto *editBankAccountBtn = new QPushButton("Редактировать", tableWidget); tableWidget->setCellWidget(k, 6, editBankAccountBtn); connect(editBankAccountBtn, &QPushButton::clicked, this, [this, tableWidget, account]() { EditBankAccountDialog dlg(account, this); if (dlg.exec() == QDialog::Accepted) { const QString cardNumber = dlg.cardNumberValue(); const QString currency = dlg.currencyValue(); bool on = dlg.toggled(); if (!AccountDAO::updateAccountById(account.id, on ? "active" : "off", cardNumber, currency)) { qDebug() << "Cant update bank account data"; } else { reloadContent(tableWidget); AccountInfo accountInfo; accountInfo.currency = currency; accountInfo.description = cardNumber; accountInfo.amount = account.amount; accountInfo.currency = currency; accountInfo.appCode = m_applicationInfo.code; accountInfo.deviceId = m_deviceId; accountInfo.status = on ? AccountStatus::Active : AccountStatus::Off; accountInfo.lastNumbers = cardNumber.right(4); updateAccountData(accountInfo); } } }); } }