10 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
1ae724f925 added functionality to email text and ocr scenes 2025-03-11 23:31:08 +03:00
4c7a25c53e added ui for ofd 2025-03-11 19:37:58 +03:00
37 changed files with 1824 additions and 366 deletions

View File

@@ -4,6 +4,10 @@ project(checks-parser VERSION 0.1 LANGUAGES CXX)
option(BUILD_TRANSLATIONS "Build translations?" ON) option(BUILD_TRANSLATIONS "Build translations?" ON)
include(FetchContent)
SET(CMAKE_BUILD_TYPE Debug)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC OFF) set(CMAKE_AUTORCC OFF)
@@ -38,6 +42,11 @@ set(PROJECT_SOURCES
emailtextscene.h emailtextscene.cpp scenes/emailtextscene.ui emailtextscene.h emailtextscene.cpp scenes/emailtextscene.ui
ocrscene.h ocrscene.cpp scenes/ocrscene.ui 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
image_redactor/imageredactor.h image_redactor/imageredactor.cpp
solvecaptchadialog.h solvecaptchadialog.cpp scenes/solvecaptchadialog.ui
) )
set(TRANSLATION_SOURCES set(TRANSLATION_SOURCES
@@ -45,6 +54,10 @@ set(TRANSLATION_SOURCES
mainwindow.cpp mainwindow.h scenes/mainwindow.ui mainwindow.cpp mainwindow.h scenes/mainwindow.ui
emailtextscene.cpp emailtextscene.h scenes/emailtextscene.ui emailtextscene.cpp emailtextscene.h scenes/emailtextscene.ui
ocrscene.cpp ocrscene.h scenes/ocrscene.ui 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
solvecaptchadialog.h solvecaptchadialog.cpp scenes/solvecaptchadialog.ui
) )
set(TS_FILES set(TS_FILES
@@ -120,14 +133,29 @@ if(WIN32)
set(OpenCV_DIR /usr/local/lib/cmake/opencv4) set(OpenCV_DIR /usr/local/lib/cmake/opencv4)
endif() 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(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} ) 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 -lzbar)
target_link_libraries(checks-parser PRIVATE -ltesseract) target_link_libraries(checks-parser PRIVATE -ltesseract)
target_link_libraries(checks-parser PRIVATE -lcurl) 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) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8)
target_link_libraries(checks-parser PRIVATE -lstdc++fs) target_link_libraries(checks-parser PRIVATE -lstdc++fs)
endif() endif()

View File

@@ -29,6 +29,7 @@ In general, you need to install following dependencies in order to build that ap
* curl * curl
* nlohmann-json * nlohmann-json
* qt5 * 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! 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 ### 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 ¯\\\_()\_ I recommend using aur helper (I use yay) to install dependencies. Or, if you're masochist, you can build all by yourself ¯\\\_()\_
``` ```
#Install dependencies #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 #Install a language package for OCR. Replace ``LANG` to your language. For example, ``tesseract-data-rus`` for russian language
yay -S tesseract-data-LANG yay -S tesseract-data-LANG
#Clone and compile an app #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: Installation of dependencies for different debian-based distros:
###### Ubuntu 18.04 ###### 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) ###### 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 Next steps are identical for every debian-based distro
``` ```

View File

@@ -4,25 +4,25 @@
Чек парсер - это приложение, позволяющее доставать содержимое чека и переводить его в .csv файлы. Чек парсер - это приложение, позволяющее доставать содержимое чека и переводить его в .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) Для более детального описания, пожалуйста, обратитесь к [вики](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BRU%5D)
### Ввод данных ### Ввод данных
Доступны следующие способы ввода данных: Доступны следующие способы ввода данных:
* Через изображениие (используется OCR(Optical Character Recognition, Оптическое распознавание символов) чтобы прочитать содержимое чека. Изображение чека должно быть контрастным и выровненным (текст обязан быть перпендикулярным к границам изображения) хорошо, чтобы нормально прочитаться.) OCR - не волшебная палочка :( * Через изображениие (используется OCR(Optical Character Recognition, Оптическое распознавание символов), чтобы прочитать содержимое чека. Изображение чека должно быть контрастным и выровненным (текст обязан быть перпендикулярным к границам изображения) хорошо, чтобы нормально прочитаться. OCR - не волшебная палочка :(
* Через просто текст, скопированный из эл. письма. Просто скопируйте и вставьте текст с вашего письма, выберите подходящий магазин (автодетект в планах!) и парсите. * Через простой текст, скопированный из эл. письма. Скопируйте и вставьте текст с вашего письма, выберите подходящий магазин (автодетект в планах!) и парсите.
* Через QRCode на чеке (этот метод запрашивает данные у ОФД (Оператор Фискальных Данных) (В данном конкретном случае, к ofd.ru)). * Через 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.) * tesseract (также вам нужно будет установить языковой пакет для него, например tesseract-data-rus на Arch Linux или tesseract-ocr-rus на Debian Linux.)
* opencv * opencv
* zbar * zbar
@@ -37,7 +37,7 @@
Я рекомендую использовать помощник для АУРа (я использую yay) чтобы установить зависимости. Или, если вы мазохист, можете собрать все зависимости ручками ¯\\\_()\_ Я рекомендую использовать помощник для АУРа (я использую 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`` для русского языка #Установка языкового пакета для OCR. Замените ``LANG` на желаемый язык. Например, ``tesseract-data-rus`` для русского языка
yay -S tesseract-data-LANG yay -S tesseract-data-LANG
#Загрузка исходгого кода и сборка приложения #Загрузка исходгого кода и сборка приложения

View File

@@ -41,7 +41,13 @@ void AdjustPictureDialog::accept() {
infoDialog.setWindowTitle(tr("No QR code")); infoDialog.setWindowTitle(tr("No QR code"));
infoDialog.exec(); infoDialog.exec();
} else { } 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(); QDialog::accept();
} }

View File

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

View File

@@ -5,10 +5,16 @@ Check::Check() {}
void Check::add_goods(Goods goods) { this->goods.push_back(goods); } void Check::add_goods(Goods goods) { this->goods.push_back(goods); }
void Check::add_goods(std::vector<Goods> &goods) {
for (auto g : goods) {
this->goods.push_back(g);
}
}
double Check::calculae_total_price() { double Check::calculae_total_price() {
double total = 0.0; double total = 0.0;
for (Goods g : this->goods) { for (Goods &g : goods) {
total += g.calculate_total_price(); total += g.calculate_total_price();
} }

View File

@@ -9,6 +9,7 @@ class Check {
public: public:
Check(); Check();
void add_goods(Goods); void add_goods(Goods);
void add_goods(std::vector<Goods> &goods);
double calculae_total_price(); double calculae_total_price();

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,14 +1,45 @@
#include "emailtextscene.h" #include "emailtextscene.h"
#include "ui_emailtextscene.h" #include "ui_emailtextscene.h"
#include <QMessageBox>
#include <iostream>
#include <outputdialog.h>
#include <check/check.h>
EmailTextScene::EmailTextScene(QWidget *parent) EmailTextScene::EmailTextScene(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::EmailTextScene) , ui(new Ui::EmailTextScene) {
{
ui->setupUi(this); ui->setupUi(this);
auto modules = parser.get_modules_names();
for (auto &module : modules) {
ui->store_combo_box->addItem(QString::fromStdString(module));
}
} }
EmailTextScene::~EmailTextScene() EmailTextScene::~EmailTextScene() {
{
delete ui; delete ui;
} }
void EmailTextScene::on_parse_button_clicked() {
std::wstring checkContent = ui->check_content->toPlainText().toStdWString();
parser.set_module(parser.search_modules()[ui->store_combo_box->currentIndex()]);
std::vector<Goods> goods = parser.parse(checkContent);
if (goods.size() == 0) {
QMessageBox infoDialog;
infoDialog.setText(tr("An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer."));
infoDialog.setIcon(QMessageBox::Critical);
infoDialog.setWindowTitle(tr("Error in parsing"));
infoDialog.exec();
return;
}
Check check;
check.add_goods(goods);
OutputDialog d(this, check);
d.show();
d.exec();
}

View File

@@ -1,6 +1,7 @@
#ifndef EMAILTEXTSCENE_H #ifndef EMAILTEXTSCENE_H
#define EMAILTEXTSCENE_H #define EMAILTEXTSCENE_H
#include "parser/parser.h"
#include <QWidget> #include <QWidget>
namespace Ui { namespace Ui {
@@ -15,8 +16,12 @@ public:
explicit EmailTextScene(QWidget *parent = nullptr); explicit EmailTextScene(QWidget *parent = nullptr);
~EmailTextScene(); ~EmailTextScene();
private slots:
void on_parse_button_clicked();
private: private:
Ui::EmailTextScene *ui; Ui::EmailTextScene *ui;
Parser parser;
}; };
#endif // EMAILTEXTSCENE_H #endif // EMAILTEXTSCENE_H

View File

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

View File

@@ -17,8 +17,10 @@
#include <QStackedLayout> #include <QStackedLayout>
#include <QTextStream> #include <QTextStream>
#include <QTranslator> #include <QTranslator>
#include <emailtextscene.h>
#include <ocrscene.h>
#include <ofdscene.h>
#include <qpushbutton.h> #include <qpushbutton.h>
#include <parser/parser.h> #include <parser/parser.h>
static QWidget *loadUI(QWidget *parent, std::string filename) { static QWidget *loadUI(QWidget *parent, std::string filename) {
@@ -31,9 +33,33 @@ static QWidget *loadUI(QWidget *parent, std::string filename) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QUiLoader loader; srand(time(0));
QApplication app(argc, argv); 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(); QWidget *window = new QWidget();
QStackedLayout *sceneLayout = new QStackedLayout; QStackedLayout *sceneLayout = new QStackedLayout;
@@ -48,27 +74,29 @@ int main(int argc, char *argv[]) {
QObject::connect(text_from_email_button, &QPushButton::clicked, [&]() { QObject::connect(text_from_email_button, &QPushButton::clicked, [&]() {
// Text from email scene // Text from email scene
sceneLayout->setCurrentIndex(1); sceneLayout->setCurrentIndex(1);
sceneLayout->widget(1)->show();
}); });
QObject::connect(ocr_button, &QPushButton::clicked, [&]() { QObject::connect(ocr_button, &QPushButton::clicked, [&]() {
// OCR scene // OCR scene
sceneLayout->setCurrentIndex(2); sceneLayout->setCurrentIndex(2);
sceneLayout->widget(2)->show();
}); });
QObject::connect(ofd_button, &QPushButton::clicked, [&]() { QObject::connect(ofd_button, &QPushButton::clicked, [&]() {
// OCR scene // OFD scene
sceneLayout->setCurrentIndex(3); sceneLayout->setCurrentIndex(3);
sceneLayout->widget(3)->show();
}); });
// Text from email setup EmailTextScene *emailTextScene = new EmailTextScene();
QWidget *emailtextscene = loadUI(window, ":/scenes/scenes/emailtextscene.ui"); OCRScene *ocrscene = new OCRScene();
OFDScene *ofdscene = new OFDScene();
//OCR scene
QWidget *ocrscene = loadUI(window, ":/scenes/scenes/ocrscene.ui");
sceneLayout->addWidget(mainwindowscene); sceneLayout->addWidget(mainwindowscene);
sceneLayout->addWidget(emailtextscene); sceneLayout->addWidget(emailTextScene);
sceneLayout->addWidget(ocrscene); sceneLayout->addWidget(ocrscene);
sceneLayout->addWidget(ofdscene);
//Setting all back buttons //Setting all back buttons
for (uint32_t sceneIndex = 0; sceneIndex < sceneLayout->count(); sceneIndex ++) { for (uint32_t sceneIndex = 0; sceneIndex < sceneLayout->count(); sceneIndex ++) {
@@ -82,6 +110,8 @@ int main(int argc, char *argv[]) {
}); });
} }
window->setLayout(sceneLayout); window->setLayout(sceneLayout);
window->show(); window->show();
@@ -131,10 +161,10 @@ int main(int argc, char *argv[]) {
std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser"); std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser");
create_directories(program_data_path); create_directories(program_data_path);
std::string settings_file_path = // std::string settings_file_path =
get_path_relative_to_home(".local/share/checks_parser/settings.json"); // get_path_relative_to_home(".local/share/checks_parser/settings.json");
Settings s(settings_file_path); // Settings s(settings_file_path);
Net n; Net n;
Parser p; Parser p;
@@ -153,22 +183,22 @@ int main(int argc, char *argv[]) {
QApplication a(argc, argv); QApplication a(argc, argv);
QTranslator translator; // QTranslator translator;
QString lang = "en_US"; // QString lang = "en_US";
if (s.get_all_settings().contains("language")) { // if (s.get_all_settings().contains("language")) {
lang = QString::fromStdString(s.get_all_settings()["language"]); // lang = QString::fromStdString(s.get_all_settings()["language"]);
} else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) { // } else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
lang = QLocale::system().name(); // lang = QLocale::system().name();
} else { // } else {
lang = QString::fromStdString("en_US"); // 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; MainWindow w;
w.update(); w.update();
w.show(); w.show();

View File

@@ -1,10 +1,13 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <iostream>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::MainWindow) { , ui(new Ui::MainWindow) {
ui->setupUi(this); ui->setupUi(this);
std::cout << "test" << std::endl;
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {

View File

@@ -1,12 +1,73 @@
#include "ocrscene.h" #include "ocrscene.h"
#include "ui_ocrscene.h" #include "ui_ocrscene.h"
#include <QFileDialog>
#include <QMessageBox>
#include <outputdialog.h>
#include <image/checkimage.h>
#include <check/check.h>
OCRScene::OCRScene(QWidget *parent) OCRScene::OCRScene(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::OCRScene) { , ui(new Ui::OCRScene) {
ui->setupUi(this); ui->setupUi(this);
auto modules = parser.get_modules_names();
for (auto &module : modules) {
ui->store_combo_box->addItem(QString::fromStdString(module));
}
} }
OCRScene::~OCRScene() { OCRScene::~OCRScene() {
delete ui; delete ui;
} }
void OCRScene::on_parse_button_clicked() {
std::wstring checkContent = ui->check_text_edit->toPlainText().toStdWString();
parser.set_module(parser.search_modules()[ui->store_combo_box->currentIndex()]);
std::vector<Goods> goods = parser.parse(checkContent);
if (goods.size() == 0) {
QMessageBox infoDialog;
infoDialog.setText(tr("An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer."));
infoDialog.setIcon(QMessageBox::Critical);
infoDialog.setWindowTitle(tr("Error in parsing"));
infoDialog.exec();
return;
}
Check check;
check.add_goods(goods);
OutputDialog d(this, check);
d.show();
d.exec();
}
void OCRScene::on_choose_image_button_clicked() {
QString filename = QFileDialog::getOpenFileName();
if (filename == "") {
QMessageBox infoDialog;
infoDialog.setText(tr("Please, select a picture to scan"));
infoDialog.setIcon(QMessageBox::Critical);
infoDialog.setWindowTitle(tr("Picture was not selected"));
infoDialog.exec();
return;
}
std::string new_text = "Selected: " + filename.toStdString();
ui->path_to_image_label->setText(tr("Path to image: ")+ filename);
CheckImage i(filename.toStdString());
std::string parsed = i.parse_text();
ui->check_text_edit->setPlainText(QString::fromStdString(parsed));
}

View File

@@ -1,6 +1,7 @@
#ifndef OCRSCENE_H #ifndef OCRSCENE_H
#define OCRSCENE_H #define OCRSCENE_H
#include "parser/parser.h"
#include <QWidget> #include <QWidget>
namespace Ui { namespace Ui {
@@ -15,8 +16,14 @@ public:
explicit OCRScene(QWidget *parent = nullptr); explicit OCRScene(QWidget *parent = nullptr);
~OCRScene(); ~OCRScene();
private slots:
void on_parse_button_clicked();
void on_choose_image_button_clicked();
private: private:
Ui::OCRScene *ui; Ui::OCRScene *ui;
Parser parser;
}; };
#endif // OCRSCENE_H #endif // OCRSCENE_H

216
ofdscene.cpp Normal file
View File

@@ -0,0 +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;
}

43
ofdscene.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef OFDSCENE_H
#define OFDSCENE_H
#include <QWidget>
#include <httplib.h>
#include <thread>
namespace Ui {
class OFDScene;
}
class OFDScene : public QWidget
{
Q_OBJECT
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

@@ -73,7 +73,7 @@
</rect> </rect>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="Text"> <widget class="QWidget" name="Text">
<attribute name="title"> <attribute name="title">
@@ -384,7 +384,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>817</width> <width>817</width>
<height>23</height> <height>33</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuchecks_parser"> <widget class="QMenu" name="menuchecks_parser">

View File

@@ -1,215 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OutputDialog</class>
<widget class="QDialog" name="OutputDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>586</width>
<height>431</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>410</x>
<y>390</y>
<width>166</width>
<height>26</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="pathLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>271</width>
<height>18</height>
</rect>
</property>
<property name="text">
<string>Path to export: </string>
</property>
</widget>
<widget class="QPushButton" name="chooseFileButton">
<property name="geometry">
<rect>
<x>290</x>
<y>20</y>
<width>80</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
<widget class="QCheckBox" name="printHeaderCheckBox">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>371</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Print header</string>
</property>
</widget>
<widget class="QTableWidget" name="tableWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>130</y>
<width>401</width>
<height>221</height>
</rect>
</property>
<row>
<property name="text">
<string>Goods name</string>
</property>
</row>
<row>
<property name="text">
<string>Goods price</string>
</property>
</row>
<row>
<property name="text">
<string>Goods quantity</string>
</property>
</row>
<row>
<property name="text">
<string>Goods net weight</string>
</property>
</row>
<row>
<property name="text">
<string>Goods total</string>
</property>
</row>
<column>
<property name="text">
<string>position</string>
</property>
</column>
<column>
<property name="text">
<string>name</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>1</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>Name</string>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>2</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>Price</string>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>3</string>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>Quantity</string>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>4</string>
</property>
</item>
<item row="3" column="1">
<property name="text">
<string>Net weight</string>
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>5</string>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>Total price</string>
</property>
</item>
</widget>
<widget class="QCheckBox" name="printTotalCheckBox">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>381</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Print total</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>OutputDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OutputDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -31,7 +31,7 @@ StoreModule::StoreModule(std::string path) {
std::vector<std::string> StoreModule::parse_name(std::wstring str) { std::vector<std::string> StoreModule::parse_name(std::wstring str) {
std::vector<std::string> result; std::vector<std::string> result;
std::wregex r(this->goods_name_regex, std::regex::collate); std::wregex r(this->goods_name_regex, std::regex_constants::multiline);
for (std::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end; for (std::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
it++) { it++) {

View File

@@ -4,6 +4,7 @@
#include "../settings/settings.h" #include "../settings/settings.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include <iostream> #include <iostream>
#include <fstream>
#if __GNUC__ < 8 && __clang_major__ < 17 #if __GNUC__ < 8 && __clang_major__ < 17
# include <experimental/filesystem> # include <experimental/filesystem>
@@ -14,6 +15,27 @@
using namespace std::filesystem; using namespace std::filesystem;
#endif #endif
static void dumpVectorsToStdErr(std::vector<std::string> &goods_names, std::vector<std::string> &goods_prices, std::vector<std::string>& goods_quantities) {
std::cerr << goods_names.size() << " " << goods_prices.size() << " " << goods_quantities.size() << std::endl;
std::cerr << "Found goods names: ";
for (auto &goods_name : goods_names) {
std::cerr << goods_name << " ";
}
std::cerr << std::endl;
std::cerr << "Found goods prices: ";
for (auto &goods_price : goods_prices) {
std::cerr << goods_price << " ";
}
std::cerr << std::endl;
std::cerr << "Found goods names: ";
for (auto &goods_quantity : goods_quantities) {
std::cerr << goods_quantity << " ";
}
std::cerr << std::endl;
}
Parser::Parser() {} Parser::Parser() {}
std::vector<std::string> Parser::search_modules() { std::vector<std::string> Parser::search_modules() {
@@ -31,13 +53,28 @@ std::vector<std::string> Parser::search_modules() {
std::vector<std::string> modules_files; std::vector<std::string> modules_files;
for (auto file : directory_iterator(path)) { for (auto &file : directory_iterator(path)) {
modules_files.push_back(file.path()); modules_files.push_back(file.path());
} }
return modules_files; return modules_files;
} }
std::vector<std::string> Parser::get_modules_names() {
std::vector<std::string> modules = this->search_modules();
std::vector<std::string> names = {};
for (std::string &modulePath : modules) {
std::ifstream inputFile(modulePath);
nlohmann::json module = nlohmann::json::parse(inputFile);
std::string name = module["name"];
names.push_back(name);
}
return names;
}
void Parser::set_module(std::string path) { module = StoreModule(path); } void Parser::set_module(std::string path) { module = StoreModule(path); }
std::vector<Goods> Parser::parse(std::wstring check_plaintext) { std::vector<Goods> Parser::parse(std::wstring check_plaintext) {
@@ -53,6 +90,9 @@ std::vector<Goods> Parser::parse(std::wstring check_plaintext) {
if (goods_names.size() != goods_prices.size() || if (goods_names.size() != goods_prices.size() ||
goods_names.size() != goods_quantities.size() || goods_names.size() != goods_quantities.size() ||
goods_prices.size() != goods_quantities.size()) { goods_prices.size() != goods_quantities.size()) {
dumpVectorsToStdErr(goods_names, goods_prices, goods_quantities);
//Error. Amount of names, prices or quantities are not equal. That means, that some regex(es) has mismatched. //Error. Amount of names, prices or quantities are not equal. That means, that some regex(es) has mismatched.
return {}; return {};
} }

View File

@@ -15,6 +15,8 @@ public:
std::vector<std::string> search_modules(); std::vector<std::string> search_modules();
std::vector<std::string> get_modules_names();
std::vector<std::string> check_updates(); std::vector<std::string> check_updates();
void set_module(std::string); void set_module(std::string);

View File

@@ -1,7 +1,10 @@
<RCC> <RCC>
<qresource prefix="/scenes"> <qresource prefix="/scenes">
<file>scenes/outputdialog.ui</file>
<file>scenes/emailtextscene.ui</file> <file>scenes/emailtextscene.ui</file>
<file>scenes/ocrscene.ui</file> <file>scenes/ocrscene.ui</file>
<file>scenes/mainwindow.ui</file> <file>scenes/mainwindow.ui</file>
<file>scenes/ofdscene.ui</file>
<file>scenes/solvecaptchadialog.ui</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -6,21 +6,18 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>927</width> <width>1077</width>
<height>603</height> <height>608</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="1"> <item row="2" column="0" colspan="3">
<widget class="QTextEdit" name="check_content"/>
</item>
<item row="1" column="1">
<widget class="QLabel" name="check_content_label"> <widget class="QLabel" name="check_content_label">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@@ -28,19 +25,32 @@
<property name="text"> <property name="text">
<string>Check content</string> <string>Check content</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="0" colspan="3">
<widget class="QPushButton" name="parse_button"> <widget class="QPushButton" name="parse_button">
<property name="text"> <property name="text">
<string>Parse</string> <string>Parse</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="1" column="0">
<widget class="QLabel" name="store_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Store:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QTextEdit" name="check_content"/>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="back_button"> <widget class="QPushButton" name="back_button">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -53,6 +63,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QComboBox" name="store_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@@ -6,13 +6,121 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>992</width>
<height>300</height> <height>634</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout">
<property name="topMargin">
<number>8</number>
</property>
<item row="1" column="2">
<widget class="QComboBox" name="store_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QPushButton" name="parse_button">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Parse</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="choose_image_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QPushButton" name="back_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="instructions_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Recognized text will be shown below as soon as image will be processed. Please, edit it</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="path_to_image_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Path to image:</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QTextEdit" name="check_text_edit"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="store_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Store:</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

194
scenes/ofdscene.ui Normal file
View File

@@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OFDScene</class>
<widget class="QWidget" name="OFDScene">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>894</width>
<height>625</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<item row="8" column="0">
<widget class="QLabel" name="total_label">
<property name="text">
<string>Total</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="back_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="or_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>or</string>
</property>
</widget>
</item>
<item row="8" column="2">
<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">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>FD (Fiscal Document)</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="datetime_label">
<property name="text">
<string>Date and time of purchase</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QComboBox" name="operation_type_combo_box">
<item>
<property name="text">
<string>Funds income</string>
</property>
</item>
<item>
<property name="text">
<string>Funds return</string>
</property>
</item>
<item>
<property name="text">
<string>Funds spend</string>
</property>
</item>
<item>
<property name="text">
<string>Spends return</string>
</property>
</item>
</widget>
</item>
<item row="4" column="2">
<widget class="QLineEdit" name="fd_line_edit"/>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="info_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLineEdit" name="fn_line_edit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLineEdit" name="fi_line_edit"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="binary_eye_button">
<property name="text">
<string>Use your phone as a QR code scanner</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="fn_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>FN (Fiscal Number)</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="fi_label">
<property name="text">
<string>FI (Fiscal Identifier)</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QDateTimeEdit" name="purchase_datetime_edit"/>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="choose_image_button">
<property name="text">
<string>Choose image on your PC</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="operation_type_label">
<property name="text">
<string>Operation type</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="QPushButton" name="parse_button">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Parse</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

187
scenes/outputdialog.ui Normal file
View File

@@ -0,0 +1,187 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OutputDialog</class>
<widget class="QDialog" name="OutputDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>892</width>
<height>537</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>Path to export: </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="chooseFileButton">
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="printHeaderCheckBox">
<property name="text">
<string>Print header</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="printTotalCheckBox">
<property name="text">
<string>Print total</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QTableWidget" name="tableWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<row>
<property name="text">
<string>Goods name</string>
</property>
</row>
<row>
<property name="text">
<string>Goods price</string>
</property>
</row>
<row>
<property name="text">
<string>Goods quantity</string>
</property>
</row>
<row>
<property name="text">
<string>Goods net weight</string>
</property>
</row>
<row>
<property name="text">
<string>Goods total</string>
</property>
</row>
<column>
<property name="text">
<string>position</string>
</property>
</column>
<column>
<property name="text">
<string>name</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>1</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>Name</string>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>2</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>Price</string>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>3</string>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>Quantity</string>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>4</string>
</property>
</item>
<item row="3" column="1">
<property name="text">
<string>Net weight</string>
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>5</string>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>Total price</string>
</property>
</item>
</widget>
</item>
<item row="4" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>OutputDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OutputDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -4,20 +4,24 @@
<context> <context>
<name>AdjustPictureDialog</name> <name>AdjustPictureDialog</name>
<message> <message>
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Dialog</translation> <translation>Dialog</translation>
</message> </message>
<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> <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>
<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> <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>
<message> <message>
<location filename="../adjustpicturedialog.cpp" line="41"/>
<source>No QR code</source> <source>No QR code</source>
<translation type="vanished">No QR code</translation> <translation>No QR code</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -25,22 +29,41 @@
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="14"/> <location filename="../scenes/emailtextscene.ui" line="14"/>
<source>Form</source> <source>Form</source>
<translation type="unfinished"></translation> <translation>Form</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="29"/> <source>Store type</source>
<translation type="obsolete">Store type</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="26"/>
<source>Check content</source> <source>Check content</source>
<translation type="unfinished">Check content</translation> <translation>Check content</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="39"/> <location filename="../scenes/emailtextscene.ui" line="33"/>
<source>Parse</source> <source>Parse</source>
<translation type="unfinished">Parse</translation> <translation>Parse</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="52"/> <location filename="../scenes/emailtextscene.ui" line="46"/>
<source>Store:</source>
<translation>Store:</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="62"/>
<source>Back</source> <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>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>Error in parsing</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -185,116 +208,345 @@
<message> <message>
<location filename="../scenes/mainwindow.ui" line="26"/> <location filename="../scenes/mainwindow.ui" line="26"/>
<source>Form</source> <source>Form</source>
<translation type="unfinished"></translation> <translation>Form</translation>
</message> </message>
<message> <message>
<location filename="../scenes/mainwindow.ui" line="37"/> <location filename="../scenes/mainwindow.ui" line="37"/>
<source>Optical Character Recognition</source> <source>Optical Character Recognition</source>
<translation type="unfinished"></translation> <translation>Optical Character Recognition</translation>
</message> </message>
<message> <message>
<location filename="../scenes/mainwindow.ui" line="63"/> <location filename="../scenes/mainwindow.ui" line="63"/>
<source>Text from E-Mail</source> <source>Text from E-Mail</source>
<translation type="unfinished"></translation> <translation>Text from E-Mail</translation>
</message> </message>
</context> </context>
<context> <context>
<name>OCRScene</name> <name>OCRScene</name>
<message> <message>
<location filename="../scenes/ocrscene.ui" line="14"/> <location filename="../scenes/ocrscene.ui" line="20"/>
<source>Form</source> <source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="64"/>
<source>Choose</source>
<translation>Choose</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="103"/>
<source>Path to image:</source>
<translation>Path to image:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="119"/>
<source>Store:</source>
<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>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>Back</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="45"/>
<source>Parse</source>
<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>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>Error in parsing</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="56"/>
<source>Please, select a picture to scan</source>
<translation>Please, select a picture to scan</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="58"/>
<source>Picture was not selected</source>
<translation>Picture was not selected</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="64"/>
<source>Path to image: </source>
<translation>Path to image: </translation>
</message>
</context>
<context>
<name>OFDScene</name>
<message>
<location filename="../scenes/ofdscene.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="23"/>
<source>Total</source>
<translation>Total</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="36"/>
<source>Back</source>
<translation>Back</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="49"/>
<source>or</source>
<translation>or</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="69"/>
<source>FD (Fiscal Document)</source>
<translation>FD (Fiscal Document)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="76"/>
<source>Date and time of purchase</source>
<translation>Date and time of purchase</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="84"/>
<source>Funds income</source>
<translation>Funds income</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="89"/>
<source>Funds return</source>
<translation>Funds return</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="94"/>
<source>Funds spend</source>
<translation>Funds spend</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="99"/>
<source>Spends return</source>
<translation>Spends return</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="136"/>
<source>Use your phone as a QR code scanner</source>
<translation>Use your phone as a QR code scanner</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="149"/>
<source>FN (Fiscal Number)</source>
<translation>FN (Fiscal Number)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="156"/>
<source>FI (Fiscal Identifier)</source>
<translation>FI (Fiscal Identifier)</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="166"/>
<source>Choose image on your PC</source>
<translation>Choose image on your PC</translation>
</message>
<message>
<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> <translation type="unfinished"></translation>
</message> </message>
<message>
<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>
<context> <context>
<name>OutputDialog</name> <name>OutputDialog</name>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Dialog</translation> <translation>Dialog</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="20"/>
<source>Path to export: </source> <source>Path to export: </source>
<translation type="vanished">Path to export: </translation> <translation>Path to export: </translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="27"/>
<source>Choose</source> <source>Choose</source>
<translation type="vanished">Choose</translation> <translation>Choose</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="34"/>
<source>Print header</source> <source>Print header</source>
<translation type="vanished">Print header</translation> <translation>Print header</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="55"/>
<source>Goods name</source> <source>Goods name</source>
<translation type="vanished">Goods name</translation> <translation>Goods name</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="60"/>
<source>Goods price</source> <source>Goods price</source>
<translation type="vanished">Goods price</translation> <translation>Goods price</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="65"/>
<source>Goods quantity</source> <source>Goods quantity</source>
<translation type="vanished">Goods quality</translation> <translation>Goods quality</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="70"/>
<source>Goods net weight</source> <source>Goods net weight</source>
<translation type="vanished">Goods net weight</translation> <translation>Goods net weight</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="75"/>
<source>Goods total</source> <source>Goods total</source>
<translation type="vanished">Goods total</translation> <translation>Goods total</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="80"/>
<source>position</source> <source>position</source>
<translation type="vanished">position</translation> <translation>position</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="85"/>
<source>name</source> <source>name</source>
<translation type="vanished">name</translation> <translation>name</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="90"/>
<source>1</source> <source>1</source>
<translation type="vanished">1</translation> <translation>1</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="95"/>
<source>Name</source> <source>Name</source>
<translation type="vanished">Name</translation> <translation>Name</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="100"/>
<source>2</source> <source>2</source>
<translation type="vanished">2</translation> <translation>2</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="105"/>
<source>Price</source> <source>Price</source>
<translation type="vanished">Price</translation> <translation>Price</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="110"/>
<source>3</source> <source>3</source>
<translation type="vanished">3</translation> <translation>3</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="115"/>
<source>Quantity</source> <source>Quantity</source>
<translation type="vanished">Quantity</translation> <translation>Quantity</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="120"/>
<source>4</source> <source>4</source>
<translation type="vanished">4</translation> <translation>4</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="125"/>
<source>Net weight</source> <source>Net weight</source>
<translation type="vanished">Net Weight</translation> <translation>Net Weight</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="130"/>
<source>5</source> <source>5</source>
<translation type="vanished">5</translation> <translation>5</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="135"/>
<source>Total price</source> <source>Total price</source>
<translation type="vanished">Total price</translation> <translation>Total price</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="41"/>
<source>Print total</source> <source>Print total</source>
<translation type="vanished">Print total</translation> <translation>Print total</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -311,16 +563,19 @@
<context> <context>
<name>SolveCaptchaDialog</name> <name>SolveCaptchaDialog</name>
<message> <message>
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Dialog</translation> <translation>Dialog</translation>
</message> </message>
<message> <message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source> <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>
<message> <message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source> <source>No captcha</source>
<translation type="vanished">No captcha</translation> <translation>No captcha</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@@ -4,20 +4,24 @@
<context> <context>
<name>AdjustPictureDialog</name> <name>AdjustPictureDialog</name>
<message> <message>
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Диалог</translation> <translation>Диалог</translation>
</message> </message>
<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> <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>
<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> <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>
<message> <message>
<location filename="../adjustpicturedialog.cpp" line="41"/>
<source>No QR code</source> <source>No QR code</source>
<translation type="vanished">QR код не найден</translation> <translation>QR код не найден</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -25,22 +29,41 @@
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="14"/> <location filename="../scenes/emailtextscene.ui" line="14"/>
<source>Form</source> <source>Form</source>
<translation type="unfinished"></translation> <translation>Форма</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="29"/> <source>Store type</source>
<translation type="obsolete">Магазин</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="26"/>
<source>Check content</source> <source>Check content</source>
<translation type="unfinished">Контент чека</translation> <translation>Контент чека</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="39"/> <location filename="../scenes/emailtextscene.ui" line="33"/>
<source>Parse</source> <source>Parse</source>
<translation type="unfinished">Парсить</translation> <translation>Парсить</translation>
</message> </message>
<message> <message>
<location filename="../scenes/emailtextscene.ui" line="52"/> <location filename="../scenes/emailtextscene.ui" line="46"/>
<source>Store:</source>
<translation>Магазин:</translation>
</message>
<message>
<location filename="../scenes/emailtextscene.ui" line="62"/>
<source>Back</source> <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>Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
</message>
<message>
<location filename="../emailtextscene.cpp" line="33"/>
<source>Error in parsing</source>
<translation>Ошибка в парсинге</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -185,116 +208,345 @@
<message> <message>
<location filename="../scenes/mainwindow.ui" line="26"/> <location filename="../scenes/mainwindow.ui" line="26"/>
<source>Form</source> <source>Form</source>
<translation type="unfinished"></translation> <translation>Форма</translation>
</message> </message>
<message> <message>
<location filename="../scenes/mainwindow.ui" line="37"/> <location filename="../scenes/mainwindow.ui" line="37"/>
<source>Optical Character Recognition</source> <source>Optical Character Recognition</source>
<translation type="unfinished"></translation> <translation>Оптическое распознавание символов</translation>
</message> </message>
<message> <message>
<location filename="../scenes/mainwindow.ui" line="63"/> <location filename="../scenes/mainwindow.ui" line="63"/>
<source>Text from E-Mail</source> <source>Text from E-Mail</source>
<translation type="unfinished"></translation> <translation>Текст из электронного письма</translation>
</message> </message>
</context> </context>
<context> <context>
<name>OCRScene</name> <name>OCRScene</name>
<message> <message>
<location filename="../scenes/ocrscene.ui" line="14"/> <location filename="../scenes/ocrscene.ui" line="20"/>
<source>Form</source> <source>Form</source>
<translation>Форма</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="64"/>
<source>Choose</source>
<translation>Выбрать</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="103"/>
<source>Path to image:</source>
<translation>Путь к изображению:</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="119"/>
<source>Store:</source>
<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>Распознанный текст будет показан ниже как только изображение обработается. Пожалуйста, отредактируйте</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="77"/>
<source>Back</source>
<translation>Назад</translation>
</message>
<message>
<location filename="../scenes/ocrscene.ui" line="45"/>
<source>Parse</source>
<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>Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="38"/>
<source>Error in parsing</source>
<translation>Ошибка в парсинге</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="56"/>
<source>Please, select a picture to scan</source>
<translation>Пожалуйста, выберете изображение для сканирования</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="58"/>
<source>Picture was not selected</source>
<translation>Изображение не было выбрано</translation>
</message>
<message>
<location filename="../ocrscene.cpp" line="64"/>
<source>Path to image: </source>
<translation>Путь к изображению: </translation>
</message>
</context>
<context>
<name>OFDScene</name>
<message>
<location filename="../scenes/ofdscene.ui" line="14"/>
<source>Form</source>
<translation>Форма</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="23"/>
<source>Total</source>
<translation>Итого</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="36"/>
<source>Back</source>
<translation>Назад</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="49"/>
<source>or</source>
<translation>или</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="69"/>
<source>FD (Fiscal Document)</source>
<translation>ФД</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="76"/>
<source>Date and time of purchase</source>
<translation>Дата и время покупки</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="84"/>
<source>Funds income</source>
<translation>Приход средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="89"/>
<source>Funds return</source>
<translation>Возврат средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="94"/>
<source>Funds spend</source>
<translation>Расход средств</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="99"/>
<source>Spends return</source>
<translation>Возврат расхода</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="136"/>
<source>Use your phone as a QR code scanner</source>
<translation>Использовать телефон как сканнер QR</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="149"/>
<source>FN (Fiscal Number)</source>
<translation>ФН</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="156"/>
<source>FI (Fiscal Identifier)</source>
<translation>ФП</translation>
</message>
<message>
<location filename="../scenes/ofdscene.ui" line="166"/>
<source>Choose image on your PC</source>
<translation>Выбрать изображение на компьютере</translation>
</message>
<message>
<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> <translation type="unfinished"></translation>
</message> </message>
<message>
<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>
<context> <context>
<name>OutputDialog</name> <name>OutputDialog</name>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Диалог</translation> <translation>Диалог</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="20"/>
<source>Path to export: </source> <source>Path to export: </source>
<translation type="vanished">Путь для экспорта: </translation> <translation>Путь для экспорта: </translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="27"/>
<source>Choose</source> <source>Choose</source>
<translation type="vanished">Выбрать</translation> <translation>Выбрать</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="34"/>
<source>Print header</source> <source>Print header</source>
<translation type="vanished">Печатать заголовок</translation> <translation>Печатать заголовок</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="55"/>
<source>Goods name</source> <source>Goods name</source>
<translation type="vanished">Имя товара</translation> <translation>Имя товара</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="60"/>
<source>Goods price</source> <source>Goods price</source>
<translation type="vanished">Цена товара</translation> <translation>Цена товара</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="65"/>
<source>Goods quantity</source> <source>Goods quantity</source>
<translation type="vanished">Количество товара</translation> <translation>Количество товара</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="70"/>
<source>Goods net weight</source> <source>Goods net weight</source>
<translation type="vanished">Масса нетто товара</translation> <translation>Масса нетто товара</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="75"/>
<source>Goods total</source> <source>Goods total</source>
<translation type="vanished">Всего за товар</translation> <translation>Всего за товар</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="80"/>
<source>position</source> <source>position</source>
<translation type="vanished">позиция</translation> <translation>позиция</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="85"/>
<source>name</source> <source>name</source>
<translation type="vanished">алиас</translation> <translation>алиас</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="90"/>
<source>1</source> <source>1</source>
<translation type="vanished">1</translation> <translation>1</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="95"/>
<source>Name</source> <source>Name</source>
<translation type="vanished">Имя</translation> <translation>Имя</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="100"/>
<source>2</source> <source>2</source>
<translation type="vanished">2</translation> <translation>2</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="105"/>
<source>Price</source> <source>Price</source>
<translation type="vanished">Цена</translation> <translation>Цена</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="110"/>
<source>3</source> <source>3</source>
<translation type="vanished">3</translation> <translation>3</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="115"/>
<source>Quantity</source> <source>Quantity</source>
<translation type="vanished">Количество</translation> <translation>Количество</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="120"/>
<source>4</source> <source>4</source>
<translation type="vanished">4</translation> <translation>4</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="125"/>
<source>Net weight</source> <source>Net weight</source>
<translation type="vanished">Масса нетто</translation> <translation>Масса нетто</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="130"/>
<source>5</source> <source>5</source>
<translation type="vanished">5</translation> <translation>5</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="135"/>
<source>Total price</source> <source>Total price</source>
<translation type="vanished">Всего</translation> <translation>Всего</translation>
</message> </message>
<message> <message>
<location filename="../scenes/outputdialog.ui" line="41"/>
<source>Print total</source> <source>Print total</source>
<translation type="vanished">Печатать Итого</translation> <translation>Печатать Итого</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -311,16 +563,19 @@
<context> <context>
<name>SolveCaptchaDialog</name> <name>SolveCaptchaDialog</name>
<message> <message>
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
<source>Dialog</source> <source>Dialog</source>
<translation type="vanished">Диалог</translation> <translation>Диалог</translation>
</message> </message>
<message> <message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source> <source>Please, enter a valid captcha</source>
<translation type="vanished">Пожалуйста, введите верную капчу</translation> <translation>Пожалуйста, введите верную капчу</translation>
</message> </message>
<message> <message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source> <source>No captcha</source>
<translation type="vanished">Нет капчи</translation> <translation>Нет капчи</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@@ -1,12 +1,49 @@
#include "utils.h" #include "utils.h"
#include <arpa/inet.h>
#include <codecvt> #include <codecvt>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <locale> #include <locale>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <qrencode.h>
#include <regex> #include <regex>
#include <string> #include <string>
#include "../exceptions/ofdrequestexception.h" #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) { std::string to_utf8(std::wstring wide_string) {
static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv; 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++) { it != end; it++) {
std::wstring found_entry = from_utf8(it->str()); 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::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); parsed.push_back(extracted);
} }
return parsed; 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) { 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) { 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) { Check parseOfdRuAnswer(std::string html) {
@@ -133,6 +202,10 @@ Check parseOfdRuAnswer(std::string html) {
} }
if ((products.size() + amounts.size() + prices.size())/products.size() != 3) { 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::cerr << "An error has occured during the parsing of html. Please, contact the developer." << std::endl;
std::exit(-1); std::exit(-1);
} }
@@ -146,3 +219,28 @@ Check parseOfdRuAnswer(std::string html) {
return c; 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 <vector>
#include "../check/check.h" #include "../check/check.h"
std::string get_local_ip_address();
std::string to_utf8(std::wstring wide_string); std::string to_utf8(std::wstring wide_string);
std::wstring from_utf8(std::string string); std::wstring from_utf8(std::string string);
@@ -19,4 +20,6 @@ Check parseOfdRuAnswer(std::string);
std::wstring trim_html_response(std::wstring& check); std::wstring trim_html_response(std::wstring& check);
void generate_qr_code(std::string data);
#endif // UTILS_H #endif // UTILS_H