285 lines
9.4 KiB
C++
285 lines
9.4 KiB
C++
#include <mainwindow.h>
|
|
#include "ui_mainwindow.h"
|
|
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QPixmap>
|
|
#include <settingsdialog.h>
|
|
|
|
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
|
# include <adjustpicturedialog.h>
|
|
#endif
|
|
|
|
#include <outputdialog.h>
|
|
#include <solvecaptchadialog.h>
|
|
#include <net/net.h>
|
|
#include <utils/utils.h>
|
|
#include <exceptions/ofdrequestexception.h>
|
|
#include <checklistviewwidget.h>
|
|
|
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
|
# include <qrencode.h>
|
|
# include <stdlib.h>
|
|
# include <unistd.h>
|
|
# include <sys/types.h>
|
|
# include <sys/socket.h>
|
|
# include <netinet/in.h>
|
|
#endif
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QWidget(parent)
|
|
, ui(new Ui::MainWindow) {
|
|
ui->setupUi(this);
|
|
ui->stop_server_button->hide();
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout;
|
|
ui->scrollAreaWidgetContents->setLayout(layout);
|
|
QLabel a = QLabel("123");
|
|
layout->addWidget(&a);
|
|
// ui->checks_to_parse_label->hide();
|
|
// ui->checks_scroll_area->hide();
|
|
|
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
|
QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure);
|
|
connect(this, SIGNAL(httpNewMessage(QString)), this, SLOT(httpNewMessageHandler(QString)));
|
|
#endif
|
|
|
|
#ifndef BUILD_EMAIL_MODE
|
|
ui->parse_email_button->hide();
|
|
ui->or_label_2->hide();
|
|
#endif
|
|
|
|
#ifndef BUILD_OFD_BINARYEYE_SCAN
|
|
ui->or_label_2->hide();
|
|
ui->binary_eye_button->hide();
|
|
#endif
|
|
#ifndef BUILD_OFD_LOCAL_QR_SCAN
|
|
ui->or_label_1->hide();
|
|
ui->choose_image_button->hide();
|
|
#endif
|
|
|
|
QObject::connect(ui->settings_button, &QPushButton::clicked, [&]() {
|
|
SettingsDialog d;
|
|
d.show();
|
|
d.exec();
|
|
});
|
|
}
|
|
|
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
|
void MainWindow::startHttpServer() {
|
|
server = new HttpServer(this);
|
|
|
|
if (server->start() < 0) {
|
|
emit httpErrorOccured();
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_binary_eye_button_clicked() {
|
|
httpServerThread = new std::thread(&MainWindow::startHttpServer, this);
|
|
ui->binary_eye_button->setEnabled(false);
|
|
ui->stop_server_button->show();
|
|
|
|
while (!server->isStarted()) {}
|
|
|
|
std::string localIp;
|
|
try {
|
|
localIp = get_local_ip_address();
|
|
} catch(std::exception e) {
|
|
std::cerr << e.what() << std::endl;
|
|
return;
|
|
}
|
|
|
|
std::string connectionString = "binaryeye://scan?ret=http://" + localIp + ":" + std::to_string(server->getPort()) + "/?result={RESULT}";
|
|
|
|
generate_qr_code(connectionString);
|
|
|
|
QMessageBox infoDialog = QMessageBox();
|
|
infoDialog.setText(QString::fromStdString(connectionString));
|
|
infoDialog.setIconPixmap(QPixmap(QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/binaryeye_connection.png"))).scaled(400, 400, Qt::KeepAspectRatio));
|
|
infoDialog.setWindowTitle(tr("QR code for binaryeye to connect"));
|
|
infoDialog.setButtonText(1, tr("I've scanned"));
|
|
infoDialog.exec();
|
|
}
|
|
|
|
void MainWindow::notifyHttpServerFailure() {
|
|
QMessageBox infoDialog = QMessageBox();
|
|
infoDialog.setText(tr("Could not start http server. 10 times in a row random port was occupied. Either you should run for a lottery ticket, or the problem is in the program. If the lottery ticket wasn't lucky, please, contact the developer."));
|
|
infoDialog.setIcon(QMessageBox::Warning);
|
|
infoDialog.setWindowTitle(tr("Could not start http server."));
|
|
infoDialog.exec();
|
|
}
|
|
|
|
void MainWindow::on_stop_server_button_clicked() {
|
|
delete server;
|
|
ui->stop_server_button->hide();
|
|
ui->binary_eye_button->setEnabled(true);
|
|
}
|
|
|
|
void MainWindow::httpNewMessageHandler(QString message) {
|
|
std::string parametersString = split(message.toStdString(), " ")[1];
|
|
|
|
//erase /?result= from the string
|
|
parametersString.erase(0, parametersString.find("=") + 1);
|
|
|
|
std::vector<std::string> parameters = split(parametersString, "&");
|
|
|
|
std::map<std::string, std::string> paramsMap;
|
|
|
|
for (auto ¶meter : parameters) {
|
|
std::vector<std::string> values = split(parameter, "=");
|
|
paramsMap.insert(std::pair<std::string, std::string> (values[0], values[1]));
|
|
}
|
|
|
|
emit onDataDecode(paramsMap);
|
|
}
|
|
|
|
|
|
#endif //ifdef BUILD_OFD_BINARYEYE_SCAN
|
|
|
|
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
|
void MainWindow::on_choose_image_button_clicked() {
|
|
QString filename = QFileDialog::getOpenFileName();
|
|
|
|
if (filename == "") {
|
|
QMessageBox infoDialog;
|
|
infoDialog.setText(tr("Please, select a picture where QR code that contains info about check is present"));
|
|
infoDialog.setIcon(QMessageBox::Critical);
|
|
infoDialog.setWindowTitle(tr("Picture was not selected"));
|
|
infoDialog.exec();
|
|
return;
|
|
}
|
|
|
|
ui->info_label->setText(tr("Selected image: ") + filename);
|
|
|
|
AdjustPictureDialog dialog = AdjustPictureDialog(this, filename.toStdString());
|
|
connect(&dialog, &AdjustPictureDialog::decodedData, this, &MainWindow::onDataDecode);
|
|
dialog.exec();
|
|
}
|
|
#endif //ifdef BUILD_OFD_LOCAL_QR_SCAN
|
|
|
|
void MainWindow::onDataDecode(std::map<std::string, std::string> data) {
|
|
ui->fn_line_edit->setText(QString::fromStdString(data["fn"]));
|
|
ui->fd_line_edit->setText(QString::fromStdString(data["i"]));
|
|
ui->fi_line_edit->setText(QString::fromStdString(data["fp"]));
|
|
|
|
QString extractedDateTime = QString::fromStdString(data["t"]);
|
|
//TODO: some QRs contain datetime in format yyyyMMddThhmmss. Perhaps there is more different formats, should write function to detect them.
|
|
QDateTime datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmm");
|
|
if (datetime == QDateTime::fromString(extractedDateTime, "20000101T1200")) {
|
|
datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmmss");
|
|
}
|
|
ui->purchase_datetime_edit->setDateTime(datetime);
|
|
|
|
int type = std::stoi(data["n"]);
|
|
ui->operation_type_combo_box->setCurrentIndex(type - 1);
|
|
|
|
std::string total = data["s"];
|
|
|
|
ui->total_spin_box->setValue(std::stod(total));
|
|
}
|
|
|
|
#ifdef BUILD_EMAIL_MODE
|
|
|
|
void MainWindow::on_parse_email_button_clicked() {
|
|
QMessageBox infoDialog;
|
|
infoDialog.setText(tr("This feature is under development. Wait it to appear in next updates."));
|
|
infoDialog.setIcon(QMessageBox::Warning);
|
|
infoDialog.setWindowTitle(tr("Under development"));
|
|
infoDialog.exec();
|
|
return;
|
|
}
|
|
|
|
|
|
#endif // ifdef BUILD_EMAIL_MODE
|
|
|
|
void MainWindow::on_parse_button_clicked() {
|
|
// if (checks.empty()) {
|
|
// QMessageBox infoDialog;
|
|
// infoDialog.setText(tr("Please, add check(s) to parse"));
|
|
// infoDialog.setIcon(QMessageBox::Warning);
|
|
// infoDialog.setWindowTitle(tr("No checks to parse"));
|
|
// infoDialog.exec();
|
|
// return;
|
|
// }
|
|
|
|
OutputDialog d = OutputDialog(this, &checks);
|
|
d.exec();
|
|
}
|
|
|
|
void MainWindow::on_add_new_check_button_clicked() {
|
|
Check *new_check = parse_new_check();
|
|
if (new_check == nullptr) {
|
|
return;
|
|
}
|
|
|
|
checks.push_back(*new_check);
|
|
|
|
CheckListViewWidget check_list_widget(this, *new_check);
|
|
|
|
auto a = QLabel("123");
|
|
ui->scrollAreaWidgetContents->layout()->addWidget(&a);
|
|
|
|
delete new_check;
|
|
|
|
if (checks.size() == 1) {
|
|
ui->checks_scroll_area->show();
|
|
ui->checks_to_parse_label->show();
|
|
}
|
|
}
|
|
|
|
Check *MainWindow::parse_new_check() {
|
|
Net net;
|
|
std::string solved_captcha = "";
|
|
|
|
for (unsigned short i = 0; i < 5; i ++) {
|
|
// Will be repaced with neural network to solve captchas as soon as I train it.
|
|
net.get_captcha_from_ofdru();
|
|
SolveCaptchaDialog dialog = SolveCaptchaDialog(this, &solved_captcha);
|
|
dialog.exec();
|
|
Check* check = new Check();
|
|
|
|
try {
|
|
std::string check_content = net.fetch_check_data_from_ofdru(
|
|
ui->fn_line_edit->text().toStdString(),
|
|
ui->fd_line_edit->text().toStdString(),
|
|
ui->fi_line_edit->text().toStdString(),
|
|
ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString(),
|
|
ui->operation_type_combo_box->currentIndex() + 1,
|
|
// In the request to ofd.ru, total is in a format with 2 last digits represent decimal part of a number.
|
|
ui->total_spin_box->text().toDouble() * 100,
|
|
solved_captcha);
|
|
|
|
(*check) = parseOfdRuAnswer(check_content);
|
|
return check;
|
|
} catch(OfdRequestException e) {
|
|
if (!strcmp(e.what(), "Incorrect captcha")) {
|
|
QMessageBox infoDialog;
|
|
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
|
infoDialog.setIcon(QMessageBox::Critical);
|
|
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
|
infoDialog.exec();
|
|
continue;
|
|
} else if (!strcmp(e.what(), "Internal server error")) {
|
|
QMessageBox infoDialog;
|
|
infoDialog.setText(tr("Internal server error. Please, try again later."));
|
|
infoDialog.setIcon(QMessageBox::Critical);
|
|
infoDialog.setWindowTitle(tr("Internal server error"));
|
|
infoDialog.exec();
|
|
return nullptr;
|
|
} else if (!strcmp(e.what(), "Does not exist")) {
|
|
QMessageBox infoDialog;
|
|
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
|
infoDialog.setIcon(QMessageBox::Critical);
|
|
infoDialog.setWindowTitle(tr("Check was not found"));
|
|
infoDialog.exec();
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
MainWindow::~MainWindow() {
|
|
delete ui;
|
|
}
|