Refactor device and account data handling, enhance UI.
Introduced a new `NetworkService` for posting account and device data efficiently. Improved the transaction UI with styled tables and added lazy content loading. Changed screenshot handling to return JPEG data directly, and restructured device processing for better error handling and data integration.
This commit is contained in:
parent
c4f171259b
commit
edcd931e66
@ -22,6 +22,7 @@ elseif (APPLE)
|
||||
endif ()
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS
|
||||
Network
|
||||
Widgets
|
||||
Sql
|
||||
Xml
|
||||
@ -66,6 +67,7 @@ if (WIN32)
|
||||
Qt6::Widgets
|
||||
Qt6::Xml
|
||||
Qt6::Sql
|
||||
Qt6::Network
|
||||
Tesseract::libtesseract
|
||||
)
|
||||
|
||||
@ -79,6 +81,7 @@ elseif (APPLE)
|
||||
Qt6::Widgets
|
||||
Qt6::Sql
|
||||
Qt6::Xml
|
||||
Qt6::Network
|
||||
tesseract
|
||||
)
|
||||
endif ()
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "GetLastDaysHistoryScript.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QRandomGenerator>
|
||||
#include <QThread>
|
||||
#include <utility>
|
||||
@ -10,6 +12,7 @@
|
||||
#include "dao/DeviceDAO.h"
|
||||
#include "dao/TransactionDAO.h"
|
||||
#include "db/DeviceInfo.h"
|
||||
#include "net/NetworkService.h"
|
||||
#include "time/DateUtils.h"
|
||||
|
||||
GetLastDaysHistoryScript::GetLastDaysHistoryScript(
|
||||
@ -134,6 +137,35 @@ bool GetLastDaysHistoryScript::openAndSaveDitailInfo(TransactionInfo &transactio
|
||||
return false;
|
||||
}
|
||||
|
||||
void postAccountsData(const QList<QPair<AccountInfo, Node> > &accounts) {
|
||||
if (accounts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *thread = new QThread;
|
||||
auto *worker = new NetworkService;
|
||||
|
||||
QJsonArray list;
|
||||
for (const QPair<AccountInfo, Node> &pair: accounts) {
|
||||
QJsonObject obj;
|
||||
AccountInfo account = pair.first;
|
||||
obj["appName"] = account.appName;
|
||||
obj["lastNumbers"] = account.lastNumbers;
|
||||
obj["amount"] = account.amount;
|
||||
obj["description"] = account.description;
|
||||
|
||||
list.append(obj);
|
||||
}
|
||||
worker->setDeviceData("DT88bokcwQ", accounts.first().first.deviceId);
|
||||
worker->setPayload(QJsonDocument(list).toJson());
|
||||
worker->moveToThread(thread);
|
||||
QObject::connect(thread, &QThread::started, worker, &NetworkService::postAccountsData);
|
||||
QObject::connect(worker, &NetworkService::finished, thread, &QThread::quit);
|
||||
QObject::connect(worker, &NetworkService::finished, worker, &QObject::deleteLater);
|
||||
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void GetLastDaysHistoryScript::doStart() {
|
||||
// берем все транзакции из БД
|
||||
QList<TransactionInfo> localTransactions = TransactionDAO::getTransactionsWithinHours(m_account.id, 48);
|
||||
@ -141,8 +173,17 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
if (xmlScreenParser.isHomeScreen()) {
|
||||
// парсим все транзакции
|
||||
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
|
||||
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
|
||||
for (auto &[account, node]: accounts) {
|
||||
account.deviceId = m_account.deviceId;
|
||||
account.appName = m_account.appName;
|
||||
if (!AccountDAO::upsertAccount(account)) {
|
||||
qDebug() << "Not updated: " << account.lastNumbers;
|
||||
}
|
||||
}
|
||||
postAccountsData(accounts);
|
||||
|
||||
findAndTapOnAccount(device.id, m_account.lastNumbers);
|
||||
|
||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
|
||||
@ -339,7 +380,6 @@ void GetLastDaysHistoryScript::doStart() {
|
||||
|
||||
// Если по карте, мы знаем ток дату + сумма
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
qDebug() << "--- home screen not found";
|
||||
|
||||
Binary file not shown.
33
main.cpp
33
main.cpp
@ -75,7 +75,7 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) {
|
||||
const QString phoneNumber = "79641815146";
|
||||
const QString bankName = "Альфа-Банк";
|
||||
// const QString bankName = "Сбербанк";
|
||||
const double amount = 440;
|
||||
const double amount = 520;
|
||||
|
||||
const AccountInfo account = AccountDAO::findAppAccount(appName, cardNumber);
|
||||
if (account.id != -1) {
|
||||
@ -136,31 +136,10 @@ void setupScriptAutoPaymentAndThread(QCoreApplication &app) {
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// QList<Card> cards = AccountInfoScreener::parseCardData(QByteArray());
|
||||
// for (const Card &card: cards) {
|
||||
// AccountInfo info;
|
||||
// info.deviceId = "6edc4a47";
|
||||
// info.appName = "bank";
|
||||
// info.cardName = card.name;
|
||||
// info.amount = card.amount;
|
||||
// info.description = card.description;
|
||||
// info.status = "active";
|
||||
// info.updateTime = QDateTime::currentDateTime();
|
||||
// qDebug() << "Account info: " << AccountDAO::upsertAccount(info);
|
||||
// }
|
||||
setupWorkerAndThreadHistory(app);
|
||||
setupWorkerAndThread(app);
|
||||
|
||||
setupScriptAutoPaymentAndThread(app);
|
||||
|
||||
// setupWorkerAndThread(app);
|
||||
//
|
||||
// const QDateTime current = QDateTime::currentDateTimeUtc();
|
||||
// qDebug() << "Обновление lastScan:" << CommonDataDAO::updateLastScan(current);
|
||||
//
|
||||
// const QDateTime savedTime = CommonDataDAO::getLastScan();
|
||||
// qDebug() << "Сохранившееся время:" << savedTime.toString();
|
||||
//
|
||||
//
|
||||
// MainWindow window;
|
||||
// window.show();
|
||||
return app.exec();
|
||||
MainWindow window;
|
||||
window.show();
|
||||
return QApplication::exec();
|
||||
}
|
||||
|
||||
@ -4,8 +4,14 @@
|
||||
#include <QProcess>
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <qeventloop.h>
|
||||
#include <QThread>
|
||||
#include <QImage>
|
||||
#include <QHttpMultiPart>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <dao/DeviceDAO.h>
|
||||
#include <db/DeviceInfo.h>
|
||||
|
||||
@ -14,27 +20,107 @@ DeviceScreener::DeviceScreener(QObject *parent) : QObject(parent) {
|
||||
|
||||
DeviceScreener::~DeviceScreener() = default;
|
||||
|
||||
void postDevicesData(const QList<DeviceInfo> &devices) {
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
QHttpPart jsonPart;
|
||||
jsonPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8");
|
||||
jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="metadata")");
|
||||
|
||||
QJsonArray list;
|
||||
for (const DeviceInfo &device: devices) {
|
||||
QJsonObject obj;
|
||||
obj["uniqueName"] = device.id;
|
||||
obj["status"] = device.status;
|
||||
obj["name"] = device.name;
|
||||
obj["screenWidth"] = device.screenWidth;
|
||||
obj["screenHeight"] = device.screenHeight;
|
||||
obj["battery"] = device.battery;
|
||||
|
||||
list.append(obj);
|
||||
}
|
||||
|
||||
jsonPart.setBody(QJsonDocument(list).toJson());
|
||||
multiPart->append(jsonPart);
|
||||
|
||||
|
||||
for (const DeviceInfo &device: devices) {
|
||||
QHttpPart imagePart;
|
||||
QString imageHeader = QStringLiteral("form-data; name=files; filename=%1.jpg").arg(device.id);
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/jpeg");
|
||||
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, imageHeader.toUtf8());
|
||||
imagePart.setBody(device.image);
|
||||
multiPart->append(imagePart);
|
||||
}
|
||||
|
||||
QHttpPart uniquePart;
|
||||
uniquePart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="uniqueName")");
|
||||
uniquePart.setBody("DT88bokcwQ");
|
||||
|
||||
multiPart->append(uniquePart);
|
||||
|
||||
QNetworkAccessManager manager; // создаём внутри потока
|
||||
QUrl url("http://localhost:9999/api/v1/app/update");
|
||||
QNetworkRequest request(url);
|
||||
|
||||
// делаем запрос
|
||||
QNetworkReply *reply = manager.post(request, multiPart);
|
||||
multiPart->setParent(reply); // multiPart удалится, когда придёт ответ
|
||||
|
||||
// локальный цикл — ждём, пока придёт finished()
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
QObject::connect(reply, &QNetworkReply::errorOccurred, [&loop](QNetworkReply::NetworkError) {
|
||||
loop.quit();
|
||||
});
|
||||
loop.exec(); // <- здесь и запускается event-loop потока
|
||||
|
||||
// обрабатываем результат
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
QByteArray raw = reply->readAll();
|
||||
QJsonParseError err;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(raw, &err);
|
||||
if (err.error == QJsonParseError::NoError && doc.isObject()) {
|
||||
QJsonObject root = doc.object();
|
||||
qDebug() << "Успешный ответ: " << root.value("success").toBool();
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Ошибка:" << reply->errorString();
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void DeviceScreener::start() {
|
||||
qDebug() << "Worker started in thread:" << QThread::currentThread();
|
||||
while (m_running) {
|
||||
QList<QPair<QString, QString> > devices = readAdbDevices();
|
||||
QStringList onlineIds;
|
||||
QList<DeviceInfo> deviceInfos;
|
||||
for (const auto &[id, status]: devices) {
|
||||
qDebug() << "Id:" << id << ", Status:" << status;
|
||||
|
||||
DeviceInfo device;
|
||||
device.id = id;
|
||||
|
||||
|
||||
if (status == "device") {
|
||||
onlineIds << device.id;
|
||||
device = readDeviceInfo(id);
|
||||
takeScreenshot(id);
|
||||
device.image = takeScreenshot(id);
|
||||
if (!DeviceDAO::updateImage(id, device.image)) {
|
||||
qDebug() << "Cant update screenshot";
|
||||
}
|
||||
}
|
||||
device.status = status;
|
||||
device.updateTime = QDateTime::currentDateTime();
|
||||
qDebug() << "Update device: " << DeviceDAO::upsertDevice(device);
|
||||
deviceInfos.append(device);
|
||||
if (!DeviceDAO::upsertDevice(device)) {
|
||||
qDebug() << "Cant update devive";
|
||||
}
|
||||
}
|
||||
|
||||
postDevicesData(deviceInfos);
|
||||
|
||||
if (!DeviceDAO::markDevicesOfflineExcept(onlineIds)) {
|
||||
qDebug() << "Cant mark devices offline";
|
||||
}
|
||||
qDebug() << "All devices offline: " << DeviceDAO::markDevicesOfflineExcept(onlineIds);
|
||||
QThread::sleep(3);
|
||||
}
|
||||
emit finished();
|
||||
@ -47,11 +133,6 @@ QByteArray convertPngToJpeg(const QByteArray& pngData, const int quality = 90) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// if (!image.save("test.jpg", "JPG", quality)) {
|
||||
// qWarning() << "Не удалось сохранить как JPG:" << "test.jpg";
|
||||
// return {};
|
||||
// }
|
||||
|
||||
QByteArray jpgData;
|
||||
QBuffer buffer(&jpgData);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
@ -59,7 +140,7 @@ QByteArray convertPngToJpeg(const QByteArray& pngData, const int quality = 90) {
|
||||
return jpgData;
|
||||
}
|
||||
|
||||
bool DeviceScreener::takeScreenshot(const QString& deviceId) {
|
||||
QByteArray DeviceScreener::takeScreenshot(const QString &deviceId) {
|
||||
QProcess process;
|
||||
QStringList arguments;
|
||||
|
||||
@ -68,24 +149,17 @@ bool DeviceScreener::takeScreenshot(const QString& deviceId) {
|
||||
|
||||
if (!process.waitForFinished(5000)) {
|
||||
qWarning() << "ADB скриншот не завершился для" << deviceId;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
const QByteArray imageData = process.readAllStandardOutput();
|
||||
|
||||
if (imageData.isEmpty()) {
|
||||
qWarning() << "Скриншот пустой для " << deviceId;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
// Обновляем изображение в БД
|
||||
if (!DeviceDAO::updateImage(deviceId, convertPngToJpeg(imageData, 90))) {
|
||||
qWarning() << "Не удалось записать изображение в БД для" << deviceId;
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Screenshot saved, device: " << deviceId;
|
||||
return true;
|
||||
return convertPngToJpeg(imageData, 90);
|
||||
}
|
||||
|
||||
QList<QPair<QString, QString> > DeviceScreener::readAdbDevices() {
|
||||
@ -94,7 +168,6 @@ QList<QPair<QString, QString>> DeviceScreener::readAdbDevices() {
|
||||
process.waitForFinished();
|
||||
|
||||
const QString output = process.readAllStandardOutput();
|
||||
// qDebug() << "[adb devices output]:\n" << output;
|
||||
QList<QPair<QString, QString> > devices;
|
||||
const QStringList lines = output.split('\n');
|
||||
for (int i = 1; i < lines.size(); ++i) {
|
||||
|
||||
@ -24,7 +24,7 @@ private:
|
||||
|
||||
static QList<QPair<QString, QString> > readAdbDevices();
|
||||
|
||||
static bool takeScreenshot(const QString &deviceId);
|
||||
static QByteArray takeScreenshot(const QString &deviceId);
|
||||
|
||||
static DeviceInfo readDeviceInfo(const QString &deviceId);
|
||||
};
|
||||
|
||||
69
services/net/NetworkService.cpp
Normal file
69
services/net/NetworkService.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "NetworkService.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QHttpPart>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonObject>
|
||||
|
||||
NetworkService::NetworkService(QObject *parent) : QObject(parent) {
|
||||
}
|
||||
|
||||
NetworkService::~NetworkService() = default;
|
||||
|
||||
|
||||
void NetworkService::postAccountsData() {
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
QHttpPart jsonPart;
|
||||
jsonPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8");
|
||||
jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="metadata")");
|
||||
|
||||
jsonPart.setBody(m_json);
|
||||
multiPart->append(jsonPart);
|
||||
|
||||
|
||||
QHttpPart desktopUniqueName;
|
||||
desktopUniqueName.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="desktopUniqueName")");
|
||||
desktopUniqueName.setBody(m_desktopId.toUtf8());
|
||||
multiPart->append(desktopUniqueName);
|
||||
|
||||
|
||||
QHttpPart androidUniqueName;
|
||||
androidUniqueName.setHeader(QNetworkRequest::ContentDispositionHeader, R"(form-data; name="androidUniqueName")");
|
||||
androidUniqueName.setBody(m_deviceId.toUtf8());
|
||||
multiPart->append(androidUniqueName);
|
||||
|
||||
QNetworkAccessManager manager; // создаём внутри потока
|
||||
const QUrl url("http://localhost:9999/api/v1/account/update");
|
||||
const QNetworkRequest request(url);
|
||||
|
||||
QNetworkReply *reply = manager.post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
QEventLoop loop;
|
||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
connect(reply, &QNetworkReply::errorOccurred, [&loop](QNetworkReply::NetworkError) {
|
||||
loop.quit();
|
||||
});
|
||||
loop.exec(); // <- здесь и запускается event-loop потока
|
||||
|
||||
// обрабатываем результат
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
const QByteArray raw = reply->readAll();
|
||||
QJsonParseError err;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(raw, &err);
|
||||
if (err.error == QJsonParseError::NoError && doc.isObject()) {
|
||||
const QJsonObject root = doc.object();
|
||||
qDebug() << "Успешный ответ: " << root.value("success").toBool();
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Ошибка:" << reply->errorString();
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void NetworkService::stop() {
|
||||
m_running = false;
|
||||
}
|
||||
32
services/net/NetworkService.h
Normal file
32
services/net/NetworkService.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
class NetworkService final : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetworkService(QObject *parent = nullptr);
|
||||
|
||||
~NetworkService() override;
|
||||
|
||||
void setPayload(const QByteArray &json) { m_json = json; }
|
||||
|
||||
void setDeviceData(const QString &desktopId, const QString &deviceId) {
|
||||
m_desktopId = desktopId;
|
||||
m_deviceId = deviceId;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void postAccountsData();
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
QByteArray m_json;
|
||||
QString m_deviceId;
|
||||
QString m_desktopId;
|
||||
bool m_running = true;
|
||||
};
|
||||
@ -30,7 +30,7 @@ AccountWindow::AccountWindow(QWidget *parent): QWidget(parent) {
|
||||
QList<DeviceInfo> devices = DeviceDAO::getAllDevices(false);
|
||||
for (int i = 0; i < devices.size(); ++i) {
|
||||
DeviceInfo device = devices[i];
|
||||
QList<AccountInfo> accounts = AccountDAO::getAccounts(device.id, "bank");
|
||||
QList<AccountInfo> accounts = AccountDAO::getAccounts(device.id, "rshb");
|
||||
// Текст перед первой таблицей
|
||||
QString title = QString("%1 [%2] | %3").arg(device.name, device.id, device.status);
|
||||
QLabel *label = new QLabel(title, this);
|
||||
|
||||
@ -13,7 +13,7 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
|
||||
img.loadFromData(device.image, "JPG");
|
||||
|
||||
auto *imageLabel = new QLabel(this);
|
||||
qDebug() << "imageLabel" << img.width() ;
|
||||
// qDebug() << "imageLabel" << img.width() ;
|
||||
imageLabel->setPixmap(QPixmap::fromImage(img).scaled(200, 350, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
imageLabel->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(imageLabel);
|
||||
|
||||
@ -21,12 +21,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
|
||||
|
||||
createDevicePage();
|
||||
stackedWidget->addWidget(devicePage);
|
||||
// stackedWidget->setCurrentWidget(devicePage); FIXME
|
||||
stackedWidget->setCurrentWidget(devicePage);
|
||||
|
||||
// FIXME переделать на ленивое создание
|
||||
accountPage = new AccountWindow(this);
|
||||
stackedWidget->addWidget(accountPage);
|
||||
stackedWidget->setCurrentWidget(accountPage);
|
||||
// stackedWidget->setCurrentWidget(accountPage);
|
||||
|
||||
resize(800, 600);
|
||||
|
||||
|
||||
@ -1,21 +1,159 @@
|
||||
#include "TransactionWindow.h"
|
||||
|
||||
#include <qabstractitemview.h>
|
||||
#include <QHeaderView>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QScrollArea>
|
||||
#include <QTableWidget>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "dao/AccountDAO.h"
|
||||
#include "dao/TransactionDAO.h"
|
||||
|
||||
class AmountDelegate : public QStyledItemDelegate {
|
||||
public:
|
||||
explicit AmountDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
|
||||
// Получаем значение суммы
|
||||
QString text = index.data().toString();
|
||||
bool isNegative = text.toDouble() < 0;
|
||||
|
||||
// Настраиваем цвета
|
||||
if (isNegative) {
|
||||
opt.backgroundBrush = QColor(255, 230, 230); // Светло-красный фон
|
||||
opt.palette.setColor(QPalette::Text, QColor(255, 0, 0)); // Красный текст
|
||||
} else {
|
||||
opt.backgroundBrush = QColor(230, 255, 230); // Светло-зеленый фон
|
||||
opt.palette.setColor(QPalette::Text, QColor(0, 128, 0)); // Зеленый текст
|
||||
}
|
||||
|
||||
// Рисуем ячейку
|
||||
QStyledItemDelegate::paint(painter, opt, index);
|
||||
}
|
||||
};
|
||||
|
||||
QTableWidgetItem *createTableWidget(const QString &text) {
|
||||
QTableWidgetItem *item = new QTableWidgetItem(text);
|
||||
item->setTextAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
return item;
|
||||
}
|
||||
|
||||
TransactionWindow::TransactionWindow(const int accountId, QWidget *parent): QDialog(parent) {
|
||||
setWindowTitle("Транзакции");
|
||||
setMinimumSize(300, 200); // минимальный размер
|
||||
setMaximumSize(800, 400); // максимальный размер
|
||||
setMinimumSize(1000, 600); // минимальный размер
|
||||
setMaximumSize(1000, 600); // максимальный размер
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->setAlignment(Qt::AlignCenter);
|
||||
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);
|
||||
|
||||
AccountInfo account = AccountDAO::getAccountById(accountId);
|
||||
QList<TransactionInfo> transactions = TransactionDAO::getTransactions(accountId);
|
||||
|
||||
QLabel *label = new QLabel(QString("*%1 | %2").arg(account.lastNumbers, account.description), this);
|
||||
layout->addWidget(label);
|
||||
QTableWidget *tableWidget = new QTableWidget(this);
|
||||
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: 4px;"
|
||||
" border: none;"
|
||||
" text-align: left top;"
|
||||
"}"
|
||||
"QTableWidget::item:selected {"
|
||||
" background-color: #cce5ff;"
|
||||
" color: #003366;"
|
||||
"}"
|
||||
"QTableCornerButton::section {"
|
||||
" background-color: #e0e0e0;"
|
||||
" border: 1px solid grey;"
|
||||
"}"
|
||||
);
|
||||
|
||||
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
||||
tableWidget->setRowCount(transactions.length());
|
||||
tableWidget->setColumnCount(6);
|
||||
tableWidget->setHorizontalHeaderLabels({
|
||||
"Дата и время",
|
||||
"Сумма",
|
||||
"Банк",
|
||||
"Телефон",
|
||||
"Статус",
|
||||
"Описание"
|
||||
});
|
||||
tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(5, QHeaderView::Stretch);
|
||||
// tableWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
|
||||
tableWidget->setItemDelegateForColumn(1, new AmountDelegate(tableWidget));
|
||||
|
||||
for (int k = 0; k < transactions.size(); ++k) {
|
||||
TransactionInfo tr = transactions[k];
|
||||
tableWidget->setItem(k, 0, createTableWidget(tr.timestamp.toString("dd.MM.yyyy HH:mm:ss")));
|
||||
tableWidget->setItem(k, 1, createTableWidget(QString::number(tr.amount)));
|
||||
tableWidget->setItem(k, 2, createTableWidget(tr.bankName));
|
||||
tableWidget->setItem(k, 3, createTableWidget(tr.phone));
|
||||
tableWidget->setItem(k, 4, createTableWidget(transactionStatusToString(tr.status)));
|
||||
|
||||
QTableWidgetItem *item = new QTableWidgetItem(tr.description);
|
||||
item->setTextAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||
item->setSizeHint(QSize(100, tr.description.length() / 2)); // Минимальная высота ячейки для переноса
|
||||
tableWidget->setItem(k, 5, item);
|
||||
}
|
||||
layout->addWidget(tableWidget);
|
||||
tableWidget->resizeRowsToContents();
|
||||
|
||||
// for (int row = 0; row < tableWidget->rowCount(); ++row) {
|
||||
// for (int col = 0; col < tableWidget->columnCount(); ++col) {
|
||||
// QTableWidgetItem *item = tableWidget->item(row, col);
|
||||
// if (item) {
|
||||
// item->setTextAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Добавим вертикальный 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);
|
||||
setWindowTitle("Транзакции");
|
||||
|
||||
setModal(true);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user