8 Commits

Author SHA1 Message Date
487707ba3e deployment 2025-03-17 00:06:19 +03:00
3dbc85f929 generate and show qr code 2025-03-15 15:12:53 +03:00
2b2127e3b5 restructure, change onDataDecode signal and succesfully parsing http request 2025-03-15 00:48:46 +03:00
f507ec8d67 starting http server with error handling 2025-03-14 18:24:42 +03:00
453f907bfa Merge pull request 'UI rework' (#3) from ui_rework into master 2025-03-14 01:27:59 +03:00
39c4bfb2fd fixed translations 2025-03-14 01:12:55 +03:00
33b54fb475 added ofd scene, working http server 2025-03-14 00:44:14 +03:00
b305fba2fd russian grammar 2025-03-12 12:53:43 +03:00
21 changed files with 765 additions and 169 deletions

View File

@@ -4,6 +4,10 @@ project(checks-parser VERSION 0.1 LANGUAGES CXX)
option(BUILD_TRANSLATIONS "Build translations?" ON)
include(FetchContent)
SET(CMAKE_BUILD_TYPE Debug)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC OFF)
@@ -40,7 +44,9 @@ set(PROJECT_SOURCES
ocrscene.h ocrscene.cpp scenes/ocrscene.ui
ofdscene.h ofdscene.cpp scenes/ofdscene.ui
outputdialog.h outputdialog.cpp scenes/outputdialog.ui
# adjustpicturedialog.h adjustpicturedialog.cpp scenes/adjustpicturedialog.ui
adjustpicturedialog.h adjustpicturedialog.cpp scenes/adjustpicturedialog.ui
image_redactor/imageredactor.h image_redactor/imageredactor.cpp
solvecaptchadialog.h solvecaptchadialog.cpp scenes/solvecaptchadialog.ui
)
set(TRANSLATION_SOURCES
@@ -50,7 +56,8 @@ set(TRANSLATION_SOURCES
ocrscene.cpp ocrscene.h scenes/ocrscene.ui
ofdscene.cpp ofdscene.h scenes/ofdscene.ui
outputdialog.h outputdialog.cpp scenes/outputdialog.ui
# adjustpicturedialog.h adjustpicturedialog.cpp scenes/adjustpicturedialog.ui
adjustpicturedialog.h adjustpicturedialog.cpp scenes/adjustpicturedialog.ui
solvecaptchadialog.h solvecaptchadialog.cpp scenes/solvecaptchadialog.ui
)
set(TS_FILES
@@ -126,14 +133,29 @@ if(WIN32)
set(OpenCV_DIR /usr/local/lib/cmake/opencv4)
endif()
FetchContent_Declare(httplib SYSTEM
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib
GIT_TAG c765584e6b1055fe0dfe3e9e6d1b4b09aa305070
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(httplib)
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs)
find_package(PkgConfig)
pkg_check_modules(QRENCODE REQUIRED libqrencode)
include_directories(${QRENCODE_INCLUDE_DIRS})
link_directories(${QRENCODE_LIBRARY_DIRS})
target_link_libraries(checks-parser PRIVATE ${QRENCODE_LIBRARIES})
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_include_directories(checks-parser PUBLIC ${OpenCV_INCLUDE_DIRS})
target_link_libraries(checks-parser PRIVATE -lzbar)
target_link_libraries(checks-parser PRIVATE -ltesseract)
target_link_libraries(checks-parser PRIVATE -lcurl)
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS} )
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS})
target_link_libraries(checks-parser PRIVATE httplib)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8)
target_link_libraries(checks-parser PRIVATE -lstdc++fs)
endif()

View File

@@ -29,6 +29,7 @@ In general, you need to install following dependencies in order to build that ap
* curl
* nlohmann-json
* qt5
* qrencode
Please, do not hesitate to open an issue if you cannot build that. I will help and if you are building on a distro that is not listed there, we can append that list as soon as we will solve your problem!
### Linux
@@ -36,7 +37,7 @@ Please, do not hesitate to open an issue if you cannot build that. I will help a
I recommend using aur helper (I use yay) to install dependencies. Or, if you're masochist, you can build all by yourself ¯\\\_()\_
```
#Install dependencies
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract qrencode
#Install a language package for OCR. Replace ``LANG` to your language. For example, ``tesseract-data-rus`` for russian language
yay -S tesseract-data-LANG
#Clone and compile an app
@@ -52,9 +53,9 @@ In debian-based distributions most, but not every, package names are the same.
Installation of dependencies for different debian-based distros:
###### Ubuntu 18.04
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libtesseract-dev```
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libtesseract-dev libqrencode-dev```
###### Ubuntu 20.04, LMDE (tested only 6), Debian (tested only 12)
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json3-dev libcurl4-openssl-dev libtesseract-dev```
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json3-dev libcurl4-openssl-dev libtesseract-dev libqrencode-dev```
Next steps are identical for every debian-based distro
```

View File

@@ -4,25 +4,25 @@
Чек парсер - это приложение, позволяющее доставать содержимое чека и переводить его в .csv файлы.
!!!НА ДАННЫЙ МОМЕНТ ПОДДЕРЖИВАЮТСЯ ТОЛЬКО РУССКИЕ ЧЕКИ!!!
Чтобы узнать, почему [смотрите здесь](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md#checks-from-different-countries)
Чтобы узнать почему [смотрите здесь](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md#checks-from-different-countries)
# Пользование
Для более детального описания, пожалуйста, обратитесь к [вики](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BRU%5D)
### Ввод данных
Доступны следующие способы ввода данных:
* Через изображениие (используется OCR(Optical Character Recognition, Оптическое распознавание символов) чтобы прочитать содержимое чека. Изображение чека должно быть контрастным и выровненным (текст обязан быть перпендикулярным к границам изображения) хорошо, чтобы нормально прочитаться.) OCR - не волшебная палочка :(
* Через просто текст, скопированный из эл. письма. Просто скопируйте и вставьте текст с вашего письма, выберите подходящий магазин (автодетект в планах!) и парсите.
* Через QRCode на чеке (этот метод запрашивает данные у ОФД (Оператор Фискальных Данных) (В данном конкретном случае, к ofd.ru)).
* Через изображениие (используется OCR(Optical Character Recognition, Оптическое распознавание символов), чтобы прочитать содержимое чека. Изображение чека должно быть контрастным и выровненным (текст обязан быть перпендикулярным к границам изображения) хорошо, чтобы нормально прочитаться. OCR - не волшебная палочка :(
* Через простой текст, скопированный из эл. письма. Скопируйте и вставьте текст с вашего письма, выберите подходящий магазин (автодетект в планах!) и парсите.
* Через QRCode на чеке (этот метод запрашивает данные у ОФД (Оператор Фискальных Данных), в данном конкретном случае, к ofd.ru).
### Вывод данных
На начальном этапе разработки программы, Я задумывался о 3 или более форматов вывода: csv, xlsx и ods. Но по мере разработки, я понял, что большинство современных табличных процессоров (электронных таблиц) способны импортировать в себя csv гораздо лучше, чем смог бы написать я сам. Так что я решил не делать вывод во все остальные форматы, кроме csv.
На начальном этапе разработки программы, Я задумывался о 3-х или более форматов вывода: csv, xlsx и ods. Но, по мере разработки, я понял, что большинство современных табличных процессоров (электронных таблиц) способны импортировать в себя csv гораздо лучше, чем смог бы написать я сам. Так что я решил не делать вывод во все остальные форматы, кроме csv.
Чтобы экспортировать, вам нужно указать путь до файла, если вы желаете, вы можете изменить порядок и/или переименовать (алиасы) столбцы, выбрать печатать или не печатать заголовок (алиасы столбцов) и "итого"
Чтобы экспортировать вам нужно: указать путь до файла, если вы желаете, вы можете изменить порядок и/или переименовать (алиасы) столбцы, выбрать печатать или не печатать заголовок (алиасы столбцов) и "итого".
# Установка
## Сборка из исходников
В целом, вам нужно установить следующие зависимости чтобы собрать приложение (я предполагаю, что вы уже имеете на системе базовые пакеты вроде cmake, make, gcc, git и так далее):
В целом, вам нужно установить следующие зависимости, чтобы собрать приложение (я предполагаю, что вы уже имеете на системе базовые пакеты вроде cmake, make, gcc, git и так далее):
* tesseract (также вам нужно будет установить языковой пакет для него, например tesseract-data-rus на Arch Linux или tesseract-ocr-rus на Debian Linux.)
* opencv
* zbar
@@ -37,7 +37,7 @@
Я рекомендую использовать помощник для АУРа (я использую yay) чтобы установить зависимости. Или, если вы мазохист, можете собрать все зависимости ручками ¯\\\_()\_
```
#Установка зависимостей
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract qrencode
#Установка языкового пакета для OCR. Замените ``LANG` на желаемый язык. Например, ``tesseract-data-rus`` для русского языка
yay -S tesseract-data-LANG
#Загрузка исходгого кода и сборка приложения

View File

@@ -41,7 +41,13 @@ void AdjustPictureDialog::accept() {
infoDialog.setWindowTitle(tr("No QR code"));
infoDialog.exec();
} else {
emit decodedData(result);
std::map<std::string, std::string> paramsMap;
std::vector<std::string> dataSplit = split(result, "&");
for (std::string &pair : dataSplit) {
std::vector<std::string> values = split(pair, "=");
paramsMap.insert(std::pair<std::string, std::string>(values[0], values[1]));
}
emit decodedData(paramsMap);
QDialog::accept();
}

View File

@@ -22,7 +22,7 @@ public:
void computeContrastLookupTable();
std::vector<unsigned short> contrastLUT[100];
signals:
void decodedData(std::string data);
void decodedData(std::map<std::string, std::string> data);
private slots:

View File

@@ -1,4 +0,0 @@
#!/bin/bash
export TESSDATA_PREFIX=$APPDIR/usr/share/tesseract-ocr/4.00/tessdata
$APPDIR/usr/bin/checks-parser

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

4
deploy/appimage/AppRun Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
export TESSDATA_PREFIX=\$APPDIR/usr/share/tesseract-ocr/4.00/tessdata
\$APPDIR/usr/bin/checks-parser

View File

@@ -0,0 +1,71 @@
FROM ubuntu:20.04
# Installing dependencies
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json3-dev libcurl4-openssl-dev libtesseract-dev libqrencode-dev
RUN DEBIAN_FRONTEND=noninteractive apt install -y wget git cmake make gcc g++ fuse
# For gcc 12
RUN DEBIAN_FRONTEND=noninteractive apt install -y libmpc-dev libmpfr-dev libgmp-dev
# The program uses std::regex_constants::multiline and some other C++17 things that are not found in gcc for Ubuntu Focal. Thus, we should compile it.
WORKDIR /
RUN wget https://mirror.linux-ia64.org/gnu/gcc/releases/gcc-12.3.0/gcc-12.3.0.tar.gz
RUN tar xf gcc-12.3.0.tar.gz
WORKDIR /gcc-12.3.0
RUN ./configure --disable-multilib
RUN make -j $(nproc) && make install
WORKDIR /
RUN rm -rf gcc-12.3.0
ENTRYPOINT bash
# Download linuxdeployqt
RUN wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage -O /usr/bin/linuxdeployqt && \
chmod +x /usr/bin/linuxdeployqt
# Prepare AppDir and its files
WORKDIR /appimage
RUN mkdir -p AppDir
COPY deploy/appimage/checks-parser.desktop AppDir
COPY icon.png AppDir/checks-parser.png
COPY deploy/appimage/AppRun AppDir
RUN chmod +x AppDir/AppRun
#Copy only necessities
COPY assets ./assets
COPY check ./check
COPY exceptions ./exceptions
COPY goods ./goods
COPY image ./image
COPY image_redactor ./image_redactor
COPY output ./output
COPY parser ./parser
COPY settings ./settings
COPY scenes ./scenes
COPY net ./net
COPY translations ./translations
COPY utils ./utils
COPY ./*cpp ./*.h ./*.ui ./*.qrc CMakeLists.txt .
RUN mkdir build
WORKDIR /appimage/build
RUN cmake -DBUILD_TRANSLATIONS=on .. && make -j 8
WORKDIR /appimage/AppDir/usr/bin
RUN cp /appimage/build/checks-parser .
WORKDIR /appimage
RUN LD_LIBRARY_PATH=LD_LIBRARY_PATH=/usr/local/lib64 linuxdeployqt AppDir/usr/bin/checks-parser -no-copy-copyright-files -appimage
ENTRYPOINT bash

View File

@@ -1,7 +1,6 @@
#include <opencv2/imgcodecs.hpp>
#include <string>
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <opencv2/opencv.hpp>
#include "checkimage.h"
CheckImage::CheckImage(std::string path) {

View File

@@ -21,7 +21,6 @@
#include <ocrscene.h>
#include <ofdscene.h>
#include <qpushbutton.h>
#include <parser/parser.h>
static QWidget *loadUI(QWidget *parent, std::string filename) {
@@ -34,9 +33,33 @@ static QWidget *loadUI(QWidget *parent, std::string filename) {
}
int main(int argc, char *argv[]) {
QUiLoader loader;
srand(time(0));
QApplication app(argc, argv);
std::string settings_file_path =
get_path_relative_to_home(".local/share/checks_parser/settings.json");
Settings s(settings_file_path);
QTranslator translator;
QString lang = "en_US";
if (s.get_all_settings().contains("language")) {
lang = QString::fromStdString(s.get_all_settings()["language"]);
} else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
lang = QLocale::system().name();
} else {
lang = QString::fromStdString("en_US");
}
std::cout << "Using locale: " << lang.toStdString() << std::endl;
translator.load(":/translation/" + lang + ".qm");
app.installTranslator(&translator);
QUiLoader loader;
QWidget *window = new QWidget();
QStackedLayout *sceneLayout = new QStackedLayout;
@@ -61,26 +84,15 @@ int main(int argc, char *argv[]) {
});
QObject::connect(ofd_button, &QPushButton::clicked, [&]() {
// OCR scene
// OFD scene
sceneLayout->setCurrentIndex(3);
sceneLayout->widget(3)->show();
});
// // Text from email setup
// QWidget *emailtextscene = loadUI(window, ":/scenes/scenes/emailtextscene.ui");
// emailtextscene->show();
//OCR scene
// QWidget *ocrscene = loadUI(window, ":/scenes/scenes/ocrscene.ui");
//OFD scene
// QWidget *ofdscene = loadUI(window, ":/scenes/scenes/ofdscene.ui");
EmailTextScene *emailTextScene = new EmailTextScene();
OCRScene *ocrscene = new OCRScene();
OFDScene *ofdscene = new OFDScene();
sceneLayout->addWidget(mainwindowscene);
sceneLayout->addWidget(emailTextScene);
sceneLayout->addWidget(ocrscene);
@@ -98,6 +110,8 @@ int main(int argc, char *argv[]) {
});
}
window->setLayout(sceneLayout);
window->show();
@@ -147,10 +161,10 @@ int main(int argc, char *argv[]) {
std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser");
create_directories(program_data_path);
std::string settings_file_path =
get_path_relative_to_home(".local/share/checks_parser/settings.json");
// std::string settings_file_path =
// get_path_relative_to_home(".local/share/checks_parser/settings.json");
Settings s(settings_file_path);
// Settings s(settings_file_path);
Net n;
Parser p;
@@ -169,22 +183,22 @@ int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QTranslator translator;
QString lang = "en_US";
// QTranslator translator;
// QString lang = "en_US";
if (s.get_all_settings().contains("language")) {
lang = QString::fromStdString(s.get_all_settings()["language"]);
} else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
lang = QLocale::system().name();
} else {
lang = QString::fromStdString("en_US");
}
// if (s.get_all_settings().contains("language")) {
// lang = QString::fromStdString(s.get_all_settings()["language"]);
// } else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
// lang = QLocale::system().name();
// } else {
// lang = QString::fromStdString("en_US");
// }
std::cout << "Using locale: " << lang.toStdString() << std::endl;
// std::cout << "Using locale: " << lang.toStdString() << std::endl;
translator.load(":/translation/" + lang + ".qm");
// translator.load(":/translation/" + lang + ".qm");
a.installTranslator(&translator);
// a.installTranslator(&translator);
MainWindow w;
w.update();
w.show();

View File

@@ -1,12 +1,216 @@
#include "ofdscene.h"
#include "ui_ofdscene.h"
#include "utils/utils.h"
#include <QFileDialog>
#include <QMessageBox>
#include <adjustpicturedialog.h>
#include <httplib.h>
#include <outputdialog.h>
#include <qpixmap.h>
#include <solvecaptchadialog.h>
#include <net/net.h>
#include <exceptions/ofdrequestexception.h>
#include <bits/basic_string.h>
#include <qrencode.h>
#include <bits/basic_string.h>
OFDScene::OFDScene(QWidget *parent)
: QWidget(parent)
, ui(new Ui::OFDScene) {
ui->setupUi(this);
QObject::connect(this, &OFDScene::httpErrorOccured, this, &OFDScene::notifyHttpServerFailure);
}
OFDScene::~OFDScene() {
delete ui;
}
void OFDScene::startHttpServer() {
std::string localIp = "";
try {
localIp = get_local_ip_address();
} catch(std::exception e) {
std::cerr << e.what() << std::endl;
return;
}
unsigned short number_of_retries = 0;
do {
if (number_of_retries == 10) {
emit httpErrorOccured();
return;
}
this->port = rand() % (65535 - 1024) + 1024;
std::string connectionString = "binaryeye://scan/?ret=http://"+ localIp +":"+ std::to_string(port) +"/?result={RESULT}";
server.Get("/", [&](const httplib::Request &req, httplib::Response &res){
std::map<std::string, std::string> paramsMap;
if (req.params.size() < 1) {
res.set_redirect(connectionString, 301);
std::cerr << "Too few params: " << req.params.size() << std::endl;
return;
}
std::string result = req.params.find("result")->second;
std::vector<std::string> dataSplit = split(result, "&");
for (std::string &pair : dataSplit) {
std::vector<std::string> values = split(pair, "=");
paramsMap.insert(std::pair<std::string, std::string>(values[0], values[1]));
}
emit onDataDecode(paramsMap);
res.set_redirect(connectionString, 301);
});
std::cerr << "Listening on port: " << this->port << std::endl;
if (!server.listen("0.0.0.0", this->port)) {
std::cerr << "Random port seems to be occupied. Trying to generate another one" << std::endl;
number_of_retries ++;
continue;
}
} while(true);
}
void OFDScene::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, &OFDScene::onDataDecode);
dialog.exec();
}
void OFDScene::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));
}
void OFDScene::on_parse_button_clicked() {
Net net;
net.get_captcha_from_ofdru();
std::string solved_captcha = "";
bool success = true;
bool is_captcha_solved = true;
Check check;
do {
SolveCaptchaDialog dialog = SolveCaptchaDialog(this, &solved_captcha);
dialog.exec();
is_captcha_solved = true;
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);
} catch(OfdRequestException e) {
success = false;
if (!strcmp(e.what(), "Incorrect captcha")) {
is_captcha_solved = false;
QMessageBox infoDialog;
infoDialog.setText(tr("Captcha was not solved correctly!"));
infoDialog.setIcon(QMessageBox::Critical);
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
infoDialog.exec();
break;
} 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;
} 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;
}
}
} while (!is_captcha_solved);
if (success) {
OutputDialog d = OutputDialog(this, check);
d.exec();
}
}
void OFDScene::on_binary_eye_button_clicked() {
http_thread = new std::thread(&OFDScene::startHttpServer, this);
ui->binary_eye_button->setEnabled(false);
while (!server.is_running());
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(port) + "/?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 OFDScene::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();
}
unsigned int OFDScene::getPort() {
return port;
}

View File

@@ -2,6 +2,8 @@
#define OFDSCENE_H
#include <QWidget>
#include <httplib.h>
#include <thread>
namespace Ui {
class OFDScene;
@@ -14,9 +16,28 @@ class OFDScene : public QWidget
public:
explicit OFDScene(QWidget *parent = nullptr);
~OFDScene();
void startHttpServer();
unsigned int getPort();
private slots:
void on_choose_image_button_clicked();
void onDataDecode(std::map<std::string, std::string>);
void on_parse_button_clicked();
void on_binary_eye_button_clicked();
void notifyHttpServerFailure();
signals:
void httpErrorOccured();
private:
Ui::OFDScene *ui;
std::thread *http_thread;
unsigned int port;
httplib::Server server;
};
#endif // OFDSCENE_H

View File

@@ -5,5 +5,6 @@
<file>scenes/ocrscene.ui</file>
<file>scenes/mainwindow.ui</file>
<file>scenes/ofdscene.ui</file>
<file>scenes/solvecaptchadialog.ui</file>
</qresource>
</RCC>

View File

@@ -51,7 +51,11 @@
</widget>
</item>
<item row="8" column="2">
<widget class="QDoubleSpinBox" name="total_spin_box"/>
<widget class="QDoubleSpinBox" name="total_spin_box">
<property name="maximum">
<double>4294967296.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="fd_label">

View File

@@ -4,20 +4,24 @@
<context>
<name>AdjustPictureDialog</name>
<message>
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
<source>Dialog</source>
<translation type="vanished">Dialog</translation>
<translation>Dialog</translation>
</message>
<message>
<location filename="../scenes/adjustpicturedialog.ui" line="58"/>
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
<translation type="vanished">Please, zoom to qr code and adjust contrast so that qr code looks sharp</translation>
<translation>Please, zoom to qr code and adjust contrast so that qr code looks sharp</translation>
</message>
<message>
<location filename="../adjustpicturedialog.cpp" line="39"/>
<source>QR code was not detected on that image. Please edit it again or enter data manually</source>
<translation type="vanished">QR code was not detected on that image. Please edit it again or enter data manually</translation>
<translation>QR code was not detected on that image. Please edit it again or enter data manually</translation>
</message>
<message>
<location filename="../adjustpicturedialog.cpp" line="41"/>
<source>No QR code</source>
<translation type="vanished">No QR code</translation>
<translation>No QR code</translation>
</message>
</context>
<context>
@@ -25,7 +29,7 @@
<message>
<location filename="../scenes/emailtextscene.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Form</translation>
</message>
<message>
<source>Store type</source>
@@ -34,32 +38,32 @@
<message>
<location filename="../scenes/emailtextscene.ui" line="26"/>
<source>Check content</source>
<translation type="unfinished">Check content</translation>
<translation>Check content</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="33"/>
<source>Parse</source>
<translation type="unfinished">Parse</translation>
<translation>Parse</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="46"/>
<source>Store:</source>
<translation type="unfinished"></translation>
<translation>Store:</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="62"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Back</translation>
</message>
<message>
<location filename="../emailtextscene.cpp" line="31"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation type="unfinished">An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
<translation>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
</message>
<message>
<location filename="../emailtextscene.cpp" line="33"/>
<source>Error in parsing</source>
<translation type="unfinished">Error in parsing</translation>
<translation>Error in parsing</translation>
</message>
</context>
<context>
@@ -204,17 +208,17 @@
<message>
<location filename="../scenes/mainwindow.ui" line="26"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Form</translation>
</message>
<message>
<location filename="../scenes/mainwindow.ui" line="37"/>
<source>Optical Character Recognition</source>
<translation type="unfinished"></translation>
<translation>Optical Character Recognition</translation>
</message>
<message>
<location filename="../scenes/mainwindow.ui" line="63"/>
<source>Text from E-Mail</source>
<translation type="unfinished"></translation>
<translation>Text from E-Mail</translation>
</message>
</context>
<context>
@@ -222,62 +226,62 @@
<message>
<location filename="../scenes/ocrscene.ui" line="20"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Form</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="64"/>
<source>Choose</source>
<translation type="unfinished">Choose</translation>
<translation>Choose</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="103"/>
<source>Path to image:</source>
<translation type="unfinished"></translation>
<translation>Path to image:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="119"/>
<source>Store:</source>
<translation type="unfinished"></translation>
<translation>Store:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="90"/>
<source>Recognized text will be shown below as soon as image will be processed. Please, edit it</source>
<translation type="unfinished"></translation>
<translation>Recognized text will be shown below as soon as image will be processed. Please, edit it</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="77"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Back</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="45"/>
<source>Parse</source>
<translation type="unfinished">Parse</translation>
<translation>Parse</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="36"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation type="unfinished">An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
<translation>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="38"/>
<source>Error in parsing</source>
<translation type="unfinished">Error in parsing</translation>
<translation>Error in parsing</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="56"/>
<source>Please, select a picture to scan</source>
<translation type="unfinished">Please, select a picture to scan</translation>
<translation>Please, select a picture to scan</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="58"/>
<source>Picture was not selected</source>
<translation type="unfinished">Picture was not selected</translation>
<translation>Picture was not selected</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="64"/>
<source>Path to image: </source>
<translation type="unfinished">Path to image: </translation>
<translation>Path to image: </translation>
</message>
</context>
<context>
@@ -285,82 +289,151 @@
<message>
<location filename="../scenes/ofdscene.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Form</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="23"/>
<source>Total</source>
<translation type="unfinished">Total</translation>
<translation>Total</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="36"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Back</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="49"/>
<source>or</source>
<translation type="unfinished"></translation>
<translation>or</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="65"/>
<location filename="../scenes/ofdscene.ui" line="69"/>
<source>FD (Fiscal Document)</source>
<translation type="unfinished">FD (Fiscal Document)</translation>
<translation>FD (Fiscal Document)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="72"/>
<location filename="../scenes/ofdscene.ui" line="76"/>
<source>Date and time of purchase</source>
<translation type="unfinished"></translation>
<translation>Date and time of purchase</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="80"/>
<location filename="../scenes/ofdscene.ui" line="84"/>
<source>Funds income</source>
<translation type="unfinished">Funds income</translation>
<translation>Funds income</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="85"/>
<location filename="../scenes/ofdscene.ui" line="89"/>
<source>Funds return</source>
<translation type="unfinished">Funds return</translation>
<translation>Funds return</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="90"/>
<location filename="../scenes/ofdscene.ui" line="94"/>
<source>Funds spend</source>
<translation type="unfinished">Funds spend</translation>
<translation>Funds spend</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="95"/>
<location filename="../scenes/ofdscene.ui" line="99"/>
<source>Spends return</source>
<translation type="unfinished">Spends return</translation>
<translation>Spends return</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="132"/>
<location filename="../scenes/ofdscene.ui" line="136"/>
<source>Use your phone as a QR code scanner</source>
<translation type="unfinished"></translation>
<translation>Use your phone as a QR code scanner</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="145"/>
<location filename="../scenes/ofdscene.ui" line="149"/>
<source>FN (Fiscal Number)</source>
<translation type="unfinished">FN (Fiscal Number)</translation>
<translation>FN (Fiscal Number)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="152"/>
<location filename="../scenes/ofdscene.ui" line="156"/>
<source>FI (Fiscal Identifier)</source>
<translation type="unfinished">FI (Fiscal Identifier)</translation>
<translation>FI (Fiscal Identifier)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="162"/>
<location filename="../scenes/ofdscene.ui" line="166"/>
<source>Choose image on your PC</source>
<translation type="unfinished"></translation>
<translation>Choose image on your PC</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="169"/>
<location filename="../scenes/ofdscene.ui" line="173"/>
<source>Operation type</source>
<translation>Operation type</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="186"/>
<source>Parse</source>
<translation>Parse</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="205"/>
<source>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&apos;t lucky, please, contact the developer.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="182"/>
<source>Parse</source>
<translation type="unfinished">Parse</translation>
<location filename="../ofdscene.cpp" line="207"/>
<source>Could not start http server.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="84"/>
<source>Please, select a picture where QR code that contains info about check is present</source>
<translation>Please, select a picture where QR code that contains info about check is present</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="86"/>
<source>Picture was not selected</source>
<translation>Picture was not selected</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="91"/>
<source>Selected image: </source>
<translation>Selected image: </translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="150"/>
<source>Captcha was not solved correctly!</source>
<translation>Captcha was not solved correctly!</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="152"/>
<source>Captcha is incorrect</source>
<translation>Captcha is incorrect</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="157"/>
<source>Internal server error. Please, try again later.</source>
<translation>Internal server error. Please, try again later.</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="159"/>
<source>Internal server error</source>
<translation>Internal server error</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="164"/>
<source>Check not found. Please, ensure correctness of entered data.</source>
<translation>Check not found. Please, ensure correctness of entered data.</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="166"/>
<source>Check was not found</source>
<translation>Check was not found</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="198"/>
<source>QR code for binaryeye to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="199"/>
<source>I&apos;ve scanned</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>123 123</source>
<translation type="obsolete">123 123</translation>
</message>
</context>
<context>
@@ -490,16 +563,19 @@
<context>
<name>SolveCaptchaDialog</name>
<message>
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
<source>Dialog</source>
<translation type="vanished">Dialog</translation>
<translation>Dialog</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source>
<translation type="vanished">Please, enter a valid captcha</translation>
<translation>Please, enter a valid captcha</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source>
<translation type="vanished">No captcha</translation>
<translation>No captcha</translation>
</message>
</context>
<context>

View File

@@ -4,20 +4,24 @@
<context>
<name>AdjustPictureDialog</name>
<message>
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
<source>Dialog</source>
<translation type="vanished">Диалог</translation>
<translation>Диалог</translation>
</message>
<message>
<location filename="../scenes/adjustpicturedialog.ui" line="58"/>
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
<translation type="vanished">Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
<translation>Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
</message>
<message>
<location filename="../adjustpicturedialog.cpp" line="39"/>
<source>QR code was not detected on that image. Please edit it again or enter data manually</source>
<translation type="vanished">QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
<translation>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
</message>
<message>
<location filename="../adjustpicturedialog.cpp" line="41"/>
<source>No QR code</source>
<translation type="vanished">QR код не найден</translation>
<translation>QR код не найден</translation>
</message>
</context>
<context>
@@ -25,7 +29,7 @@
<message>
<location filename="../scenes/emailtextscene.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Форма</translation>
</message>
<message>
<source>Store type</source>
@@ -34,32 +38,32 @@
<message>
<location filename="../scenes/emailtextscene.ui" line="26"/>
<source>Check content</source>
<translation type="unfinished">Контент чека</translation>
<translation>Контент чека</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="33"/>
<source>Parse</source>
<translation type="unfinished">Парсить</translation>
<translation>Парсить</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="46"/>
<source>Store:</source>
<translation type="unfinished"></translation>
<translation>Магазин:</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="62"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Назад</translation>
</message>
<message>
<location filename="../emailtextscene.cpp" line="31"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation type="unfinished">Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
<translation>Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
</message>
<message>
<location filename="../emailtextscene.cpp" line="33"/>
<source>Error in parsing</source>
<translation type="unfinished">Ошибка в парсинге</translation>
<translation>Ошибка в парсинге</translation>
</message>
</context>
<context>
@@ -204,17 +208,17 @@
<message>
<location filename="../scenes/mainwindow.ui" line="26"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Форма</translation>
</message>
<message>
<location filename="../scenes/mainwindow.ui" line="37"/>
<source>Optical Character Recognition</source>
<translation type="unfinished"></translation>
<translation>Оптическое распознавание символов</translation>
</message>
<message>
<location filename="../scenes/mainwindow.ui" line="63"/>
<source>Text from E-Mail</source>
<translation type="unfinished"></translation>
<translation>Текст из электронного письма</translation>
</message>
</context>
<context>
@@ -222,62 +226,62 @@
<message>
<location filename="../scenes/ocrscene.ui" line="20"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Форма</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="64"/>
<source>Choose</source>
<translation type="unfinished">Выбрать</translation>
<translation>Выбрать</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="103"/>
<source>Path to image:</source>
<translation type="unfinished"></translation>
<translation>Путь к изображению:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="119"/>
<source>Store:</source>
<translation type="unfinished"></translation>
<translation>Магазин:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="90"/>
<source>Recognized text will be shown below as soon as image will be processed. Please, edit it</source>
<translation type="unfinished"></translation>
<translation>Распознанный текст будет показан ниже как только изображение обработается. Пожалуйста, отредактируйте</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="77"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Назад</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="45"/>
<source>Parse</source>
<translation type="unfinished">Парсить</translation>
<translation>Парсить</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="36"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation type="unfinished">Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
<translation>Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="38"/>
<source>Error in parsing</source>
<translation type="unfinished">Ошибка в парсинге</translation>
<translation>Ошибка в парсинге</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="56"/>
<source>Please, select a picture to scan</source>
<translation type="unfinished">Пожалуйста, выберете изображение для сканирования</translation>
<translation>Пожалуйста, выберете изображение для сканирования</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="58"/>
<source>Picture was not selected</source>
<translation type="unfinished">Изображение не было выбрано</translation>
<translation>Изображение не было выбрано</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="64"/>
<source>Path to image: </source>
<translation type="unfinished">Путь к изображению: </translation>
<translation>Путь к изображению: </translation>
</message>
</context>
<context>
@@ -285,82 +289,151 @@
<message>
<location filename="../scenes/ofdscene.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
<translation>Форма</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="23"/>
<source>Total</source>
<translation type="unfinished">Итого</translation>
<translation>Итого</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="36"/>
<source>Back</source>
<translation type="unfinished"></translation>
<translation>Назад</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="49"/>
<source>or</source>
<translation type="unfinished"></translation>
<translation>или</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="65"/>
<location filename="../scenes/ofdscene.ui" line="69"/>
<source>FD (Fiscal Document)</source>
<translation type="unfinished">ФД</translation>
<translation>ФД</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="72"/>
<location filename="../scenes/ofdscene.ui" line="76"/>
<source>Date and time of purchase</source>
<translation type="unfinished"></translation>
<translation>Дата и время покупки</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="80"/>
<location filename="../scenes/ofdscene.ui" line="84"/>
<source>Funds income</source>
<translation type="unfinished">Приход средств</translation>
<translation>Приход средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="85"/>
<location filename="../scenes/ofdscene.ui" line="89"/>
<source>Funds return</source>
<translation type="unfinished">Возврат средств</translation>
<translation>Возврат средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="90"/>
<location filename="../scenes/ofdscene.ui" line="94"/>
<source>Funds spend</source>
<translation type="unfinished">Расход средств</translation>
<translation>Расход средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="95"/>
<location filename="../scenes/ofdscene.ui" line="99"/>
<source>Spends return</source>
<translation type="unfinished">Возврат расхода</translation>
<translation>Возврат расхода</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="132"/>
<location filename="../scenes/ofdscene.ui" line="136"/>
<source>Use your phone as a QR code scanner</source>
<translation type="unfinished"></translation>
<translation>Использовать телефон как сканнер QR</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="145"/>
<location filename="../scenes/ofdscene.ui" line="149"/>
<source>FN (Fiscal Number)</source>
<translation type="unfinished">ФН</translation>
<translation>ФН</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="152"/>
<location filename="../scenes/ofdscene.ui" line="156"/>
<source>FI (Fiscal Identifier)</source>
<translation type="unfinished">ФП</translation>
<translation>ФП</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="162"/>
<location filename="../scenes/ofdscene.ui" line="166"/>
<source>Choose image on your PC</source>
<translation type="unfinished"></translation>
<translation>Выбрать изображение на компьютере</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="169"/>
<location filename="../scenes/ofdscene.ui" line="173"/>
<source>Operation type</source>
<translation>Тип операции</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="186"/>
<source>Parse</source>
<translation>Парсить</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="205"/>
<source>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&apos;t lucky, please, contact the developer.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="182"/>
<source>Parse</source>
<translation type="unfinished">Парсить</translation>
<location filename="../ofdscene.cpp" line="207"/>
<source>Could not start http server.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="84"/>
<source>Please, select a picture where QR code that contains info about check is present</source>
<translation>Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="86"/>
<source>Picture was not selected</source>
<translation>Изображение не было выбрано</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="91"/>
<source>Selected image: </source>
<translation>Выбранное изображение: </translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="150"/>
<source>Captcha was not solved correctly!</source>
<translation>Капча была решена неверно!</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="152"/>
<source>Captcha is incorrect</source>
<translation>Капча введена неверно</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="157"/>
<source>Internal server error. Please, try again later.</source>
<translation>Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="159"/>
<source>Internal server error</source>
<translation>Внутренняя ошибка сервера</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="164"/>
<source>Check not found. Please, ensure correctness of entered data.</source>
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="166"/>
<source>Check was not found</source>
<translation>Чек не найден</translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="198"/>
<source>QR code for binaryeye to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ofdscene.cpp" line="199"/>
<source>I&apos;ve scanned</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>123 123</source>
<translation type="obsolete">123 123</translation>
</message>
</context>
<context>
@@ -490,16 +563,19 @@
<context>
<name>SolveCaptchaDialog</name>
<message>
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
<source>Dialog</source>
<translation type="vanished">Диалог</translation>
<translation>Диалог</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source>
<translation type="vanished">Пожалуйста, введите верную капчу</translation>
<translation>Пожалуйста, введите верную капчу</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source>
<translation type="vanished">Нет капчи</translation>
<translation>Нет капчи</translation>
</message>
</context>
<context>

View File

@@ -1,12 +1,49 @@
#include "utils.h"
#include <arpa/inet.h>
#include <codecvt>
#include <cstring>
#include <iostream>
#include <locale>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <qrencode.h>
#include <regex>
#include <string>
#include "../exceptions/ofdrequestexception.h"
#include "settings/settings.h"
#include <QWidget>
#include <fstream>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <opencv2/opencv.hpp>
std::string get_local_ip_address() {
struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) continue;
if (ifa->ifa_addr->sa_family==AF_INET) {
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[128];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
std::string value(addressBuffer);
if (!strncmp(value.c_str(), "192.168", 7)) {
return value;
}
}
}
if (ifAddrStruct!=NULL)
freeifaddrs(ifAddrStruct);
throw std::runtime_error(QWidget::tr("Could not find any usable local IP address. If you beleive that this is problem with the program, please, contact the developer.").toStdString());
}
std::string to_utf8(std::wstring wide_string) {
static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
@@ -94,8 +131,9 @@ std::vector<std::wstring> find_in_html(std::string& html, std::string regex, std
it != end; it++) {
std::wstring found_entry = from_utf8(it->str());
std::wcout << "Found: " << found_entry << std::endl;
std::wstring extracted = substring_from_to(found_entry, from_utf8(html_start), from_utf8(html_end));
std::wcout << "Extracted: " << extracted << std::endl;
parsed.push_back(extracted);
}
return parsed;
@@ -106,11 +144,42 @@ std::vector<std::wstring> find_products_in_html(std::string html) {
}
std::vector<std::wstring> find_amounts_in_html(std::string html) {
return find_in_html(html, "<span>\\d+<\\/span>", "<span>", "<\\/span>");
std::vector<std::wstring> founds = find_in_html(html, "<div><span>\\d+(\\.|\\,)?\\d{0,3}<\\/span>", "<span>", "<\\/span>");
for (auto &found : founds) {
std::replace(found.begin(), found.end(), ',', '.');
}
return founds;
}
std::vector<std::wstring> find_prices_in_html(std::string html) {
return find_in_html(html, "X <\\/span><span>\\d+\\.\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
std::vector<std::wstring> founds = find_in_html(html, "X <\\/span><span>\\d+(\\.|,)\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
for (auto &found : founds) {
std::replace(found.begin(), found.end(), ',', '.');
}
return founds;
}
void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::wstring> &amounts, std::vector<std::wstring> &prices) {
std::cerr << "Products: ";
for (auto &product : products) {
std::cerr << to_utf8(product) << "|[]|";
}
std::cerr << std::endl;
std::cerr << "Amounts: ";
for (auto &amount : amounts) {
std::wcerr << amount << " ";
}
std::cerr << std::endl;
std::cerr << "Prices: ";
for (auto &price : prices) {
std::wcerr << price << " ";
}
std::cerr << std::endl;
}
Check parseOfdRuAnswer(std::string html) {
@@ -133,6 +202,10 @@ Check parseOfdRuAnswer(std::string html) {
}
if ((products.size() + amounts.size() + prices.size())/products.size() != 3) {
dumpVectorsToStderr(products, amounts, prices);
//TOOD: make new setting "app_home" and get all path using it.
std::ofstream error_log(get_path_relative_to_home(".local/share/checks_parser/error_log.txt"), std::ios_base::app);
error_log << trimmed << std::endl;
std::cerr << "An error has occured during the parsing of html. Please, contact the developer." << std::endl;
std::exit(-1);
}
@@ -146,3 +219,28 @@ Check parseOfdRuAnswer(std::string html) {
return c;
}
void generate_qr_code(std::string data) {
QRcode *qrCode = QRcode_encodeString(data.c_str(), 2, QR_ECLEVEL_L, QR_MODE_8, 1);
if (qrCode == NULL) {
std::cerr << "Error on generating qr code" << std::endl;
}
cv::Mat qrCodeImage = cv::Mat::zeros(qrCode->width, qrCode->width, CV_8UC3);
for (int y = 0; y < qrCode->width; y++) {
for (int x = 0; x < qrCode->width; x++) {
cv::rectangle(
qrCodeImage,
cv::Point(x, y),
cv::Point(x + 1, y + 1),
((qrCode->data[y * qrCode->width + x] & 1) ?
cv::Scalar(255., 255., 255.) : cv::Scalar(0., 0., 0.)
),
-1
);
}
}
cv::imwrite(get_path_relative_to_home(".local/share/checks_parser/binaryeye_connection.png"), qrCodeImage);
QRcode_free(qrCode);
}

View File

@@ -5,6 +5,7 @@
#include <vector>
#include "../check/check.h"
std::string get_local_ip_address();
std::string to_utf8(std::wstring wide_string);
std::wstring from_utf8(std::string string);
@@ -19,4 +20,6 @@ Check parseOfdRuAnswer(std::string);
std::wstring trim_html_response(std::wstring& check);
void generate_qr_code(std::string data);
#endif // UTILS_H