Compare commits
28 Commits
f32da712e8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d3d9441cb4 | |||
| 66ffe47fb8 | |||
| dd06dfa30a | |||
| b06e2f8ef2 | |||
| 37a77d7228 | |||
| 373c51f0b8 | |||
| 91ca01b255 | |||
| a3ecaeef55 | |||
| 94acf816ea | |||
| 4c262de8a4 | |||
| 55d75f413c | |||
| 0a7018d13a | |||
| 07c7e49a21 | |||
| 5afaf6a94f | |||
| c9f447009b | |||
| 9da589839c | |||
| 259b8543a4 | |||
| 896b81c999 | |||
| 1507faef6e | |||
| 20b08f493d | |||
| ac355b7d9e | |||
| 84261d20e5 | |||
| c21166fc5b | |||
| ca52ddf33c | |||
| a8549c838c | |||
| d10dfc07b6 | |||
| b67d575645 | |||
| 33ea7ff459 |
@@ -95,8 +95,8 @@ set(PROJECT_SOURCES
|
|||||||
net/net.h net/net.cpp
|
net/net.h net/net.cpp
|
||||||
settings/settings.h settings/settings.cpp
|
settings/settings.h settings/settings.cpp
|
||||||
|
|
||||||
widgets/tablewidgetmovable.hpp widgets/tablewidgetmovable.cpp
|
|
||||||
widgets/checklistviewwidget.h widgets/checklistviewwidget.cpp
|
|
||||||
widgets/outputcolumn.h widgets/outputcolumn.cpp
|
widgets/outputcolumn.h widgets/outputcolumn.cpp
|
||||||
widgets/outputcolumnmodel.h widgets/outputcolumnmodel.cpp
|
widgets/outputcolumnmodel.h widgets/outputcolumnmodel.cpp
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ if (BUILD_OFD_BINARYEYE_SCAN)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_EMAIL_MODE)
|
if (BUILD_EMAIL_MODE)
|
||||||
# list(APPEND PROJECT_SOURCES email_parser/emailparser.h email_parser/emailparser.cpp)
|
list(APPEND PROJECT_SOURCES email_parser/emailparser.h email_parser/emailparser.cpp)
|
||||||
list(APPEND PROJECT_SOURCES utils/base64.h utils/base64.cpp)
|
list(APPEND PROJECT_SOURCES utils/base64.h utils/base64.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -165,6 +165,8 @@ else()
|
|||||||
add_executable(checks-parser
|
add_executable(checks-parser
|
||||||
${PROJECT_SOURCES}
|
${PROJECT_SOURCES}
|
||||||
${SOURCES}
|
${SOURCES}
|
||||||
|
widgets/checkqueuetablemodel.h widgets/checkqueuetablemodel.cpp
|
||||||
|
# widgets/checkqueuetableview.h widgets/checkqueuetableview.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -205,9 +207,9 @@ if (BUILD_OFD_BINARYEYE_SCAN)
|
|||||||
link_directories(${QRENCODE_LIBRARY_DIRS})
|
link_directories(${QRENCODE_LIBRARY_DIRS})
|
||||||
target_link_libraries(checks-parser PRIVATE ${QRENCODE_LIBRARIES})
|
target_link_libraries(checks-parser PRIVATE ${QRENCODE_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
# if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||||
target_link_libraries(checks-parser PRIVATE -lzbar)
|
# target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
target_link_libraries(checks-parser PRIVATE -lcurl)
|
target_link_libraries(checks-parser PRIVATE -lcurl)
|
||||||
|
|
||||||
@@ -220,7 +222,7 @@ include_directories(${Boost_INCLUDE_DIRS})
|
|||||||
target_link_libraries(checks-parser PUBLIC ${Boost_LIBRARIES})
|
target_link_libraries(checks-parser PUBLIC ${Boost_LIBRARIES})
|
||||||
|
|
||||||
if (BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN)
|
if (BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN)
|
||||||
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs)
|
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs opencv_objdetect videoio)
|
||||||
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS})
|
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS})
|
||||||
target_include_directories(checks-parser PUBLIC ${OpenCV_INCLUDE_DIRS})
|
target_include_directories(checks-parser PUBLIC ${OpenCV_INCLUDE_DIRS})
|
||||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||||
|
|||||||
65
README.md
65
README.md
@@ -1,28 +1,41 @@
|
|||||||
|
# Checks parser
|
||||||
|
|
||||||
|
# /!\ The project is frozen! /!\
|
||||||
|
|
||||||
|
It is completed at about 80-90%, but I don't have time nor desire to complete it.
|
||||||
|
Perhaps, I could resume it sometime.
|
||||||
|
|
||||||
-->[Русская версия](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md)<--
|
-->[Русская версия](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md)<--
|
||||||
|
|
||||||
# Checks parser
|
|
||||||
checks parser is a program that help parsing different checks to csv.
|
checks parser is a program that help parsing different checks to csv.
|
||||||
|
|
||||||
!!!CURRENTLY SUPPORTED ONLY RUSSIAN CHECKS!!!
|
!!!CURRENTLY SUPPORTED ONLY RUSSIAN CHECKS!!!
|
||||||
To know why, see [this section](https://git.foxarmy.org/leca/checks-parser#checks-from-different-countries)
|
To know why, see [this section](https://git.foxarmy.org/leca/checks-parser#checks-from-different-countries)
|
||||||
|
|
||||||
# Usage
|
## Usage
|
||||||
|
|
||||||
For more detailed description, please, refer to [the wiki](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BEN%5D)
|
For more detailed description, please, refer to [the wiki](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BEN%5D)
|
||||||
|
|
||||||
### Input
|
## Input
|
||||||
|
|
||||||
Ways you can input a check to this programm:
|
Ways you can input a check to this programm:
|
||||||
|
|
||||||
* Via image (it uses OCR(Optical Character Recognition) to parse check content. The picture of a check must be contrast and well-lined (text must be perpendicular to right and left borders of an image) enough in order to be parsed well.) OCR is not a magic wand :(
|
* Via image (it uses OCR(Optical Character Recognition) to parse check content. The picture of a check must be contrast and well-lined (text must be perpendicular to right and left borders of an image) enough in order to be parsed well.) OCR is not a magic wand :(
|
||||||
* Via plaintext, copied from an E-Mail. Just copy&paste text from your email, pick a correct store type (autodetect is in my plans!) and parse.
|
* Via plaintext, copied from an E-Mail. Just copy&paste text from your email, pick a correct store type (autodetect is in my plans!) and parse.
|
||||||
* Via QRCode on check (this method queries check content from OFD (ОФД, Оператор Фискальных Данных in Russian) (My program makes requests to ofd.ru)).
|
* Via QRCode on check (this method queries check content from OFD (ОФД, Оператор Фискальных Данных in Russian) (My program makes requests to ofd.ru)).
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
|
||||||
At the start of writing this program, I considered 3 or more output formats: csv, xlsx and ods. But throught the development I understood that most of modern table processor (i.e. electronic tables) can import csv much better than I'd be writing a shitty export module, adding more dependencies and shitty code to the codebase. So I decided that there's no need to use anything other than csv format.
|
At the start of writing this program, I considered 3 or more output formats: csv, xlsx and ods. But throught the development I understood that most of modern table processor (i.e. electronic tables) can import csv much better than I'd be writing a shitty export module, adding more dependencies and shitty code to the codebase. So I decided that there's no need to use anything other than csv format.
|
||||||
|
|
||||||
To export, you need to specify an output file path and, if you wish, you can change order and/or rename columns, choose to print or not to print header (column names) and total.
|
To export, you need to specify an output file path and, if you wish, you can change order and/or rename columns, choose to print or not to print header (column names) and total.
|
||||||
|
|
||||||
# Installing
|
## Installing
|
||||||
## Building
|
|
||||||
|
### Building
|
||||||
|
|
||||||
In general, you need to install following dependencies in order to build that app(I suppose you have installed all the build necessaries such as cmake, make, gcc, git, etc...):
|
In general, you need to install following dependencies in order to build that app(I suppose you have installed all the build necessaries such as cmake, make, gcc, git, etc...):
|
||||||
|
|
||||||
* boost
|
* boost
|
||||||
* tesseract (you also have to install appropriate for your needs language data)
|
* tesseract (you also have to install appropriate for your needs language data)
|
||||||
* opencv
|
* opencv
|
||||||
@@ -33,8 +46,11 @@ In general, you need to install following dependencies in order to build that ap
|
|||||||
* qrencode
|
* 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
|
||||||
|
|
||||||
##### Arch Linux-based
|
##### Arch Linux-based
|
||||||
|
|
||||||
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
|
||||||
@@ -49,17 +65,24 @@ make -j{nproc}
|
|||||||
#If you wish to install that program system-wide, run
|
#If you wish to install that program system-wide, run
|
||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Debian-based
|
##### Debian-based
|
||||||
|
|
||||||
In debian-based distributions most, but not every, package names are the same.
|
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 libqrencode-dev libboost-regex-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 libboost-regex-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 libqrencode-dev libboost-regex-dev```
|
|
||||||
|
```apt install -y qt6-base-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev qt6-tools-dev nlohmann-json3-dev libcurl4-openssl-dev libqrencode-dev libboost-regex-dev```
|
||||||
|
|
||||||
Next steps are identical for every debian-based distro
|
Next steps are identical for every debian-based distro
|
||||||
```
|
|
||||||
|
```sh
|
||||||
#Clone and compile an app
|
#Clone and compile an app
|
||||||
git clone https://git.foxarmy.org/leca/checks-parser
|
git clone https://git.foxarmy.org/leca/checks-parser
|
||||||
cd checks-parser
|
cd checks-parser
|
||||||
@@ -69,36 +92,42 @@ make -j{nproc}
|
|||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
#### Windows
|
||||||
|
|
||||||
See [Precompiled binaries](https://git.foxarmy.org/leca/checks-parser#precompiled-binaries)
|
See [Precompiled binaries](https://git.foxarmy.org/leca/checks-parser#precompiled-binaries)
|
||||||
### Mac OS
|
|
||||||
|
#### Mac OS
|
||||||
|
|
||||||
Probably not, I do not have nor desire or time. But if you can maintain that program on Mac, I'd be grateful! Please, contact me, if you can!
|
Probably not, I do not have nor desire or time. But if you can maintain that program on Mac, I'd be grateful! Please, contact me, if you can!
|
||||||
|
|
||||||
## Precompiled binaries
|
### Precompiled binaries
|
||||||
|
|
||||||
Currently I have published the program to the [AUR](https://aur.archlinux.org/packages/checks-parser-git).
|
Currently I have published the program to the [AUR](https://aur.archlinux.org/packages/checks-parser-git).
|
||||||
|
|
||||||
Every new release will certainly contain AppImage and tarball. I am working towards binaries for Windows and deb packets. Expect them to appear in next releases!
|
Every new release will certainly contain AppImage and tarball. I am working towards binaries for Windows and deb packets. Expect them to appear in next releases!
|
||||||
|
|
||||||
# Special thanks
|
## Special thanks
|
||||||
|
|
||||||
HyperFlint (@hyperflint:foxarmy.org) - for the great idea to use OFD and a huge help in release preparations!
|
HyperFlint (@hyperflint:foxarmy.org) - for the great idea to use OFD and a huge help in release preparations!
|
||||||
|
|
||||||
https://check.ofd.ru - for providing a way to request data from FNS.
|
[ofd.ru](https://check.ofd.ru) - for providing a way to request data from FNS.
|
||||||
|
|
||||||
# Contribution
|
## Contribution
|
||||||
|
|
||||||
If you want to contribute to the project, you can do it by some of the following:
|
If you want to contribute to the project, you can do it by some of the following:
|
||||||
## Checks from different countries
|
|
||||||
|
### Checks from different countries
|
||||||
|
|
||||||
I live in Russia and only know how Russian state checks system works. If you live in another country and want to help me with adding support to checks from your country - feel free to contact me!
|
I live in Russia and only know how Russian state checks system works. If you live in another country and want to help me with adding support to checks from your country - feel free to contact me!
|
||||||
## Issues and PRs
|
|
||||||
|
### Issues and PRs
|
||||||
|
|
||||||
If you have found a bug, or want to suggest a feature - don't hesitate to open an issue / a PR!
|
If you have found a bug, or want to suggest a feature - don't hesitate to open an issue / a PR!
|
||||||
|
|
||||||
## Tell friends
|
### Tell friends
|
||||||
|
|
||||||
You can help me by distributing that program. If you know people that are in search of such program, please let them know about its existance!
|
You can help me by distributing that program. If you know people that are in search of such program, please let them know about its existance!
|
||||||
|
|
||||||
## Donate
|
### Donate
|
||||||
|
|
||||||
```XMR 45ZjyH5YWdRfKxLoKEBYaiHUTcP5Z8Gv64QQxmabbooPAa7KPBxZLmqft5ohKXn5VpHiVj1x9JKCcAcAjdu9jA8b5N8XqR7```
|
```XMR 45ZjyH5YWdRfKxLoKEBYaiHUTcP5Z8Gv64QQxmabbooPAa7KPBxZLmqft5ohKXn5VpHiVj1x9JKCcAcAjdu9jA8b5N8XqR7```
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
#include "adjustpicturedialog.h"
|
#include "adjustpicturedialog.h"
|
||||||
#include "ui_adjustpicturedialog.h"
|
#include "ui_adjustpicturedialog.h"
|
||||||
#include "utils/utils.h"
|
#include <utils/utils.h>
|
||||||
|
|
||||||
|
#include <opencv2/objdetect.hpp>
|
||||||
#include <opencv2/imgcodecs.hpp>
|
#include <opencv2/imgcodecs.hpp>
|
||||||
#include <opencv2/imgproc.hpp>
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <opencv2/core/mat.hpp>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <zbar.h>
|
|
||||||
|
using cv::QRCodeDetector, cv::Mat;
|
||||||
|
|
||||||
AdjustPictureDialog::AdjustPictureDialog(QWidget *parent, std::string imagePath)
|
AdjustPictureDialog::AdjustPictureDialog(QWidget *parent, std::string imagePath)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
@@ -54,24 +57,26 @@ void AdjustPictureDialog::accept() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string AdjustPictureDialog::decode() {
|
std::string AdjustPictureDialog::decode() {
|
||||||
cv::Mat im = cv::imread(get_path_relative_to_home(".local/share/checks_parser/temp.png"));
|
Mat im = cv::imread(get_path_relative_to_home(".local/share/checks_parser/temp.png"));
|
||||||
|
QRCodeDetector qrDecoder = QRCodeDetector();
|
||||||
|
return qrDecoder.detectAndDecode(im);
|
||||||
|
|
||||||
zbar::ImageScanner scanner;
|
// zbar::ImageScanner scanner;
|
||||||
scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
|
// scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
|
||||||
|
|
||||||
cv::Mat imGray;
|
// cv::Mat imGray;
|
||||||
cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);
|
// cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);
|
||||||
|
|
||||||
zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
|
// zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
|
||||||
scanner.scan(image);
|
// scanner.scan(image);
|
||||||
|
|
||||||
std::string result = "";
|
// std::string result = "";
|
||||||
|
|
||||||
for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
|
// for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
|
||||||
result = symbol->get_data();
|
// result = symbol->get_data();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return result;
|
// return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustPictureDialog::computeContrastLookupTable() {
|
void AdjustPictureDialog::computeContrastLookupTable() {
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "../goods/goods.h"
|
#include "../goods/goods.h"
|
||||||
#include <iostream>
|
#include <QObject>
|
||||||
|
|
||||||
Check::Check() {}
|
Check::Check() {}
|
||||||
|
|
||||||
|
Check::Check(std::string date, double total, OperationType type, std::string fn, std::string fd, std::string fi, std::vector<Goods> goods) {
|
||||||
|
set_date(date);
|
||||||
|
set_total(total);
|
||||||
|
set_operation_type(type);
|
||||||
|
set_fn(fn);
|
||||||
|
set_fd(fd);
|
||||||
|
set_fi(fi);
|
||||||
|
set_goods(goods);
|
||||||
|
}
|
||||||
|
|
||||||
void Check::add_goods(Goods goods) {
|
void Check::add_goods(Goods goods) {
|
||||||
this->goods.push_back(goods);
|
this->goods.push_back(goods);
|
||||||
this->total = this->calculae_total_price();
|
this->total = this->calculae_total_price();
|
||||||
@@ -25,46 +35,24 @@ double Check::calculae_total_price() {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Goods>& Check::get_goods() {
|
std::vector<Goods>& Check::get_goods() { return goods; }
|
||||||
return goods;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Check::set_fn(std::string fn) {
|
void Check::set_fn(std::string fn) { this->fn = fn; }
|
||||||
this->fn = fn;
|
void Check::set_fd(std::string fd) { this->fd = fd; }
|
||||||
}
|
void Check::set_fi(std::string fi) { this->fi = fi; }
|
||||||
|
std::string Check::get_date() { return date; }
|
||||||
|
|
||||||
void Check::set_fd(std::string fd) {
|
OperationType Check::get_operationType() { return operation_type; }
|
||||||
this->fd = fd;
|
void Check::set_date(std::string date) { this->date = date; }
|
||||||
}
|
void Check::set_operation_type(OperationType t) { this->operation_type = t; }
|
||||||
|
void Check::set_total(double total) { this->total = total; }
|
||||||
void Check::set_fi(std::string fi) {
|
void Check::set_goods(std::vector<Goods> goods) { this->goods = goods; }
|
||||||
this->fi = fi;
|
std::string Check::get_fn() { return fn; }
|
||||||
}
|
std::string Check::get_fd() { return fd; }
|
||||||
|
std::string Check::get_fi() { return fi; }
|
||||||
std::string Check::get_date() {
|
double Check::get_total() { return total; }
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Check::set_date(std::string date) {
|
|
||||||
this->date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Check::set_operation_type(OperationType t) {
|
|
||||||
this->operation_type = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Check::get_total() {
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Check::operator==(Check &c) {
|
bool Check::operator==(Check &c) {
|
||||||
// std::cout << "Comparing" << std::endl;
|
|
||||||
// std::cout << this->date << " <>" << c.date << std::endl;
|
|
||||||
// std::cout << this->fd << " <>" << c.fd << std::endl;
|
|
||||||
// std::cout << this->fi<< " <>" << c.fi << std::endl;
|
|
||||||
// std::cout << this->fn<< " <>" << c.fn << std::endl;
|
|
||||||
// std::cout << this->operation_type << " <>" << c.operation_type << std::endl;
|
|
||||||
// std::cout << this->total<< " <>" << c.total<< std::endl;
|
|
||||||
return
|
return
|
||||||
this->date == c.date &&
|
this->date == c.date &&
|
||||||
this->fd == c.fd &&
|
this->fd == c.fd &&
|
||||||
@@ -75,13 +63,6 @@ bool Check::operator==(Check &c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Check::operator==(const Check &c) {
|
bool Check::operator==(const Check &c) {
|
||||||
// std::cout << "Comparing" << std::endl;
|
|
||||||
// std::cout << this->date << " <>" << c.date << std::endl;
|
|
||||||
// std::cout << this->fd << " <>" << c.fd << std::endl;
|
|
||||||
// std::cout << this->fi<< " <>" << c.fi << std::endl;
|
|
||||||
// std::cout << this->fn<< " <>" << c.fn << std::endl;
|
|
||||||
// std::cout << this->operation_type << " <>" << c.operation_type << std::endl;
|
|
||||||
// std::cout << this->total<< " <>" << c.total<< std::endl;
|
|
||||||
return
|
return
|
||||||
this->date == c.date &&
|
this->date == c.date &&
|
||||||
this->fd == c.fd &&
|
this->fd == c.fd &&
|
||||||
@@ -90,3 +71,5 @@ bool Check::operator==(const Check &c) {
|
|||||||
this->operation_type == c.operation_type &&
|
this->operation_type == c.operation_type &&
|
||||||
this->total == c.total;
|
this->total == c.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Check)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef CHECK_H
|
#ifndef CHECK_H
|
||||||
#define CHECK_H
|
#define CHECK_H
|
||||||
#include "../goods/goods.h"
|
#include "../goods/goods.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef enum OperationTypes {
|
typedef enum OperationTypes {
|
||||||
@@ -23,6 +24,7 @@ class Check {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Check();
|
Check();
|
||||||
|
Check(std::string date, double total, OperationType type, std::string fn, std::string fd, std::string fi, std::vector<Goods> goods);
|
||||||
void add_goods(Goods);
|
void add_goods(Goods);
|
||||||
void add_goods(std::vector<Goods> &goods);
|
void add_goods(std::vector<Goods> &goods);
|
||||||
|
|
||||||
@@ -37,6 +39,8 @@ public:
|
|||||||
void set_operation_type(OperationType);
|
void set_operation_type(OperationType);
|
||||||
void set_total(double);
|
void set_total(double);
|
||||||
|
|
||||||
|
void set_goods(std::vector<Goods>);
|
||||||
|
|
||||||
std::string get_fn();
|
std::string get_fn();
|
||||||
std::string get_fd();
|
std::string get_fd();
|
||||||
std::string get_fi();
|
std::string get_fi();
|
||||||
@@ -48,4 +52,5 @@ public:
|
|||||||
bool operator==(const Check &);
|
bool operator==(const Check &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // CHECK_H
|
#endif // CHECK_H
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ arch=('x86_64')
|
|||||||
url="https://git.foxarmy.org/leca/checks-parser"
|
url="https://git.foxarmy.org/leca/checks-parser"
|
||||||
license=('GPL-3.0-or-later')
|
license=('GPL-3.0-or-later')
|
||||||
groups=()
|
groups=()
|
||||||
depends=('qt5-base' 'opencv' 'zbar' 'nlohmann-json' 'tesseract' 'qrencode' 'boost')
|
depends=('qt6-base' 'opencv' 'nlohmann-json' 'qrencode' 'boost')
|
||||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt5-tools')
|
makedepends=('cmake' 'make' 'gcc' 'git' 'qt6-tools')
|
||||||
checkdepends=()
|
checkdepends=()
|
||||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
optdepends=()
|
||||||
provides=()
|
provides=()
|
||||||
conflicts=("checks-parser-git")
|
conflicts=("checks-parser-git")
|
||||||
replaces=()
|
replaces=()
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ arch=('x86_64')
|
|||||||
url="https://git.foxarmy.org/leca/checks-parser"
|
url="https://git.foxarmy.org/leca/checks-parser"
|
||||||
license=('GPL-3.0-or-later')
|
license=('GPL-3.0-or-later')
|
||||||
groups=()
|
groups=()
|
||||||
depends=('qt5-base' 'opencv' 'zbar' 'nlohmann-json' 'tesseract' 'qrencode' 'boost')
|
depends=('qt6-base' 'opencv' 'nlohmann-json' 'qrencode' 'boost')
|
||||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt5-tools')
|
makedepends=('cmake' 'make' 'gcc' 'git' 'qt6-tools')
|
||||||
checkdepends=()
|
checkdepends=()
|
||||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
optdepends=()
|
||||||
provides=()
|
provides=()
|
||||||
conflicts=("checks-parser-bin")
|
conflicts=("checks-parser-bin")
|
||||||
replaces=()
|
replaces=()
|
||||||
@@ -25,12 +25,15 @@ sha256sums=('SKIP')
|
|||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "$pkgname"
|
cd "$pkgname"
|
||||||
cmake -DBUILD_TRANSLATIONS=on .
|
mkdir build && cd build
|
||||||
|
cmake -DBUILD_TRANSLATIONS=on ..
|
||||||
make -j ${nproc}
|
make -j ${nproc}
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
cd "$pkgname"
|
cd "$pkgname"
|
||||||
|
cd build
|
||||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||||
|
##install -Dm755
|
||||||
make DESTDIR="$pkgdir/" PREFIX="/usr" install
|
make DESTDIR="$pkgdir/" PREFIX="/usr" install
|
||||||
}
|
}
|
||||||
|
|||||||
30
deploy/base-docker/archlinux/Dockerfile
Normal file
30
deploy/base-docker/archlinux/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FROM archlinux:latest
|
||||||
|
|
||||||
|
ARG pkgname=$name
|
||||||
|
ARG pkgver=$version
|
||||||
|
ARG revision
|
||||||
|
|
||||||
|
RUN mkdir -p /output
|
||||||
|
|
||||||
|
RUN pacman --noconfirm -Syu base base-devel sudo
|
||||||
|
|
||||||
|
RUN chmod +x /deploy.sh
|
||||||
|
|
||||||
|
# RUN useradd -m builder
|
||||||
|
# RUN usermod -a -G wheel builder
|
||||||
|
# RUN chown -R builder:builder /output
|
||||||
|
# RUN echo "%wheel ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
|
# USER builder
|
||||||
|
|
||||||
|
# WORKDIR /home/builder/checks-parser
|
||||||
|
|
||||||
|
COPY deploy/archlinux/bin/PKGBUILD PKGBUILD
|
||||||
|
RUN sed -i "s|\$pkgname|${pkgname}-bin|g" PKGBUILD
|
||||||
|
RUN sed -i "s|\$pkgver|${pkgver}|g" PKGBUILD
|
||||||
|
RUN sed -i "s|\$pkgrel|$revision|g" PKGBUILD
|
||||||
|
|
||||||
|
RUN makepkg -s --noconfirm
|
||||||
|
|
||||||
|
RUN echo "sudo cp ${pkgname}-bin-${pkgver}-$revision-x86_64.pkg.tar.zst /output" > /deploy.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["bash", "/deploy.sh"]
|
||||||
@@ -3,7 +3,7 @@ FROM ubuntu:24.04
|
|||||||
# Installing dependencies
|
# Installing dependencies
|
||||||
RUN apt update
|
RUN apt update
|
||||||
|
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt install -y qt6-base-dev qt6-tools-dev openssl libmbedtls-dev libopencv-dev libzbar-dev nlohmann-json3-dev libcurl4-openssl-dev libqrencode-dev
|
RUN DEBIAN_FRONTEND=noninteractive apt install -y qt6-base-dev qt6-tools-dev openssl libmbedtls-dev libopencv-dev nlohmann-json3-dev libcurl4-openssl-dev libqrencode-dev
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt install -y wget git cmake make gcc g++ fuse libboost-regex-dev
|
RUN DEBIAN_FRONTEND=noninteractive apt install -y wget git cmake make gcc g++ fuse libboost-regex-dev
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
#include "utils/utils.h"
|
|
||||||
#include <email_parser/emailparser.h>
|
#include <email_parser/emailparser.h>
|
||||||
|
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <opencv2/imgcodecs.hpp>
|
||||||
|
#include <opencv2/objdetect.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/videoio.hpp>
|
||||||
|
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
|
#include <utils/base64.h>
|
||||||
#include <check/check.h>
|
#include <check/check.h>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <sstream>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <bits/stdc++.h>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||||
# include <experimental/filesystem>
|
# include <experimental/filesystem>
|
||||||
using namespace std::experimental::filesystem;
|
using namespace std::experimental::filesystem;
|
||||||
@@ -16,165 +23,189 @@
|
|||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string EmailParser::get_payload_in_email(std::string &email_content) {
|
|
||||||
boost::regex content_type_and_transfer_encoding_regex("Content-Type");
|
|
||||||
// boost::regex body_start_regex("\r\n\r\n"); //boost::regex_constants::egrep
|
|
||||||
// boost::smatch smatch;
|
|
||||||
// if (boost::regex_search(email_content, smatch, body_start_regex)) {
|
|
||||||
// return email_content.substr(smatch.position(), email_content.length());
|
|
||||||
// }
|
|
||||||
// return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::multimap<std::string, std::string> EmailParser::parse_email_content_types(std::string path) {
|
|
||||||
std::ifstream input_file(path, std::ios::in);
|
|
||||||
|
|
||||||
std::string line = "";
|
|
||||||
std::multimap<std::string, std::string> mail_options;
|
|
||||||
std::string latest_key;
|
|
||||||
while(std::getline(input_file, line)) {
|
|
||||||
// ;
|
|
||||||
|
|
||||||
char first_char = line.substr(0, 1)[0];
|
|
||||||
// if (line == "\0") {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
std::vector<std::string> split_by_colon = split(line, ":");
|
|
||||||
std::string key = split_by_colon[0];
|
|
||||||
std::string value = "";
|
|
||||||
|
|
||||||
for (int i = 1; i < split_by_colon.size(); i ++) value += split_by_colon[i];
|
|
||||||
if (key != "Content-Type" ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first_char == '\t') {
|
|
||||||
mail_options.emplace(std::make_pair(latest_key, line));
|
|
||||||
} else {
|
|
||||||
// std::cout << "key: " << key << "\nvalue: " << value << std::endl;
|
|
||||||
mail_options.emplace(std::make_pair(key, value));
|
|
||||||
latest_key = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mail_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::vector<int> EmailParser::find_base64_blocks_in_email(std::string &email_content) {
|
|
||||||
// std::string glued_together;
|
|
||||||
// for (auto c : email_content) {
|
|
||||||
// if (c == '\n') continue;
|
|
||||||
// glued_together.push_back(c);
|
|
||||||
// }
|
|
||||||
// boost::regex base64_regex("^[-A-Za-z0-9+/]*={0,3}$");
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EmailParser::EmailParser() {
|
EmailParser::EmailParser() {
|
||||||
|
headings_regex = boost::regex("([\\w-]+:\\s*.{2,64}\\r\\n)+");
|
||||||
|
end_marker_regex = boost::regex("--[^\\n\\r<>]{5,57}");
|
||||||
|
part_end_regex = boost::regex("--[^\\n\\r<> ]{5,57}");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> search_content_types_in_email_content(std::string& email_content) {
|
std::map<std::string, std::string> EmailParser::parse(std::string &email_content) {
|
||||||
std::vector<int> content_type_positions = {};
|
std::string parameters;
|
||||||
boost::regex image_content_type_regex("Content-Type: image/.*");
|
parameters = search_in_images(email_content);
|
||||||
for (boost::sregex_iterator it{email_content.begin(), email_content.end(), image_content_type_regex}, end{};
|
|
||||||
it != end; it++) {
|
|
||||||
content_type_positions.push_back(it->position());
|
|
||||||
}
|
|
||||||
return content_type_positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// void find_and_decode_email_content()
|
|
||||||
|
|
||||||
Check EmailParser::parse(std::string &email_content) {
|
|
||||||
//1. Search "Content-Type: image/.*" in the .eml file.
|
|
||||||
// 1.1 If found 0, go to [2]
|
|
||||||
// 1.2 If found 1, try decoding it, if it's not a QR code, go to [2]
|
|
||||||
// 1.3 Loop through every found entry. If not found in any, go to [2]
|
|
||||||
//2. Try decoding content of the e-mail
|
|
||||||
//3. Search "t=\d{8}T\d{4,6}&s=\d{1,6}\.\d{1,2}&fn=\d{10,16}&i=\d{6}&fp=\d{10}&n=\d". Note that in some emails = and & signs could be replaced with its code in HTTP requests: %3D, %26
|
|
||||||
// 3.1 If not found, notify the user that we could not parse the .eml file
|
|
||||||
std::vector<int> content_type_positions = search_content_types_in_email_content(email_content);
|
|
||||||
|
|
||||||
if (content_type_positions.size() < 0) {
|
|
||||||
|
|
||||||
} else if (content_type_positions.size() == 1) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
if (parameters != "") {
|
||||||
|
return get_params_from_string(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::string payload = get_payload_in_email(email_content);
|
parameters = search_in_text(email_content);
|
||||||
// Check c;
|
if (parameters != "") {
|
||||||
|
return get_params_from_string(parameters);
|
||||||
|
}
|
||||||
|
std::cout << "Failed to parse" << std::endl;
|
||||||
|
/* If the code has reached this part and found nothing, it's most likely that there are no QR codes at all. */
|
||||||
|
|
||||||
// std::cout << payload << std::endl;
|
return std::map<std::string, std::string>();
|
||||||
|
|
||||||
// if (payload == "")
|
|
||||||
// return c;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Check EmailParser::parse_file(std::string path) {
|
std::map<std::string, std::string> EmailParser::parse_file(std::string path) {
|
||||||
|
std::cout << "Parsing file " << path << std::endl;
|
||||||
|
std::string content = read_file(path);
|
||||||
|
return parse(content);
|
||||||
|
return std::map<std::string, std::string>();
|
||||||
|
}
|
||||||
|
std::vector<std::pair<int, int>> EmailParser::find_parts(const boost::regex &start_regex, const boost::regex &end_regex, const std::string &content) {
|
||||||
|
std::vector<std::pair<int, int>> parts = {};
|
||||||
|
|
||||||
// std::vector<std::string> contents = read_file(path);
|
for (boost::sregex_iterator it{content.begin(), content.end(), start_regex}, end{}; it != end; it ++) {
|
||||||
// unsigned int body_start = -1;
|
unsigned int start_position = it->position(), end_position = content.length();
|
||||||
// for (unsigned int i = 0; i < contents.size(); i ++) {
|
|
||||||
// std::string &line = contents[i];
|
|
||||||
// if (line == "\r") {
|
|
||||||
// body_start = i;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (body_start == (unsigned int) -1) throw "Not an E-Mail";
|
|
||||||
|
|
||||||
// for (unsigned int i = 0; i < contents.size(); i ++) {
|
|
||||||
// std::string &line = contents[i];
|
|
||||||
// if (line[0] == '\t') {
|
|
||||||
// contents[i - 1] += " " + contents[i];
|
|
||||||
// contents.erase(remove(contents.begin(), contents.end(), line), contents.end());
|
|
||||||
// i -= 2;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (auto &line : contents) {
|
|
||||||
// std::cout << line << std::endl;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// std::cout << contents[body_start + 1] << std::endl;
|
|
||||||
// unsigned int body_start = contents.find("\r\n\r\n");
|
|
||||||
// if (body_start == (unsigned int)-1)
|
|
||||||
// throw "Not a E-Mail file";
|
|
||||||
// std::cout << contents.erase(0, body_start + 4);
|
|
||||||
// std::cout << contents << std::endl;
|
|
||||||
|
|
||||||
// std::vector<std::tuple<int, int>> message_parts_positions;
|
|
||||||
|
|
||||||
// while (contents.find("--") > 0) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
return Check();
|
|
||||||
|
|
||||||
std::multimap<std::string, std::string> content_types = parse_email_content_types(path);
|
|
||||||
bool found_qr_image = false;
|
|
||||||
for (auto &content_type : content_types) {
|
|
||||||
boost::regex image_content_type_regex("image\\/(png|gif|jpg|jpeg)");
|
|
||||||
boost::cmatch cmatch;
|
|
||||||
if (boost::regex_match(content_type.second.c_str(), cmatch, image_content_type_regex)) {
|
|
||||||
std::cout << cmatch << std::endl;
|
|
||||||
|
|
||||||
|
for (boost::sregex_iterator it2{content.begin() + start_position, content.end(), end_regex}, end2{}; it2 != end2; it2++) {
|
||||||
|
end_position = it2->position();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
std::cout << content_type.first << ": " << content_type.second << std::endl;
|
parts.push_back(std::pair<int, int>(start_position, end_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::ifstream ifile(path, std::ios::in | std::ios::binary);
|
return parts;
|
||||||
// const unsigned int size = std::filesystem::file_size(path);
|
}
|
||||||
// std::string content(size, '\0');
|
|
||||||
// ifile.read(content.data(), size);
|
std::string EmailParser::find_check_parameters(std::string &part) {
|
||||||
// return parse(content);
|
boost::regex params_regex ("t(=|(%|=)3d)\\d+T\\d+(&(amp;)?|%26)s\\1\\d+\\.\\d+\\3fn\\1\\d{16}\\3i\\1\\d{3,6}\\3fp\\1\\d{9,10}\\3n\\1\\d", boost::regex::icase);
|
||||||
return Check();
|
boost::smatch matched;
|
||||||
|
if (boost::regex_search(part, matched, params_regex))
|
||||||
|
return matched[0].str();
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EmailParser::extract_qr_url_from_img(std::string &part) {
|
||||||
|
boost::regex img_url_regex("(?<=<img src=\")https:\\/\\/[^\\n\\r\"]*\\/qr(code)?[^\\n\\r\"]*", boost::regex::icase);
|
||||||
|
boost::smatch matched;
|
||||||
|
if (boost::regex_search(part, matched, img_url_regex))
|
||||||
|
return matched[0].str();
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EmailParser::extract_content_transfer_encoding(std::string &part) {
|
||||||
|
boost::regex content_transfer_encoding_regex("(?<=content-transfer-encoding: ).{0,20}(?=\\r\\n)", boost::regex::icase);
|
||||||
|
boost::smatch matched;
|
||||||
|
std::string transfer_encoding = "";
|
||||||
|
|
||||||
|
if (boost::regex_search(part, matched, content_transfer_encoding_regex))
|
||||||
|
transfer_encoding = matched[0].str();
|
||||||
|
|
||||||
|
if (transfer_encoding == "") return "";
|
||||||
|
std::transform(transfer_encoding.begin(), transfer_encoding.end(), transfer_encoding.begin(), ::tolower);
|
||||||
|
boost::trim(transfer_encoding);
|
||||||
|
return transfer_encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> EmailParser::extract_qr_embeddings_from_part(std::string &part) {
|
||||||
|
std::vector<std::string> embeddings = {};
|
||||||
|
boost::regex img_base64_regex("(?<=<img src=\"data:image\\/(png|jpg);base64,)[^\n\r\"]*", boost::regex::icase);
|
||||||
|
boost::smatch matched;
|
||||||
|
if (boost::regex_search(part, matched, img_base64_regex)) {
|
||||||
|
for (unsigned int i = 0; i < matched.size(); i ++) {
|
||||||
|
embeddings.push_back(matched[i].str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return embeddings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EmailParser::search_in_images(std::string &content) {
|
||||||
|
boost::regex images_content_type_regex("Content-Type: image/(gif|png|jpg)", boost::regex::icase);
|
||||||
|
std::vector<std::pair<int, int>> images_content_parts = find_parts(images_content_type_regex, part_end_regex, content);
|
||||||
|
|
||||||
|
/* iterate through found image content-types and try searching qr codes, decode them and see if it's the needed data */
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < images_content_parts.size(); i ++) {
|
||||||
|
|
||||||
|
std::string part = content.substr(images_content_parts[i].first, images_content_parts[i].second);
|
||||||
|
boost::erase_regex(part, headings_regex);
|
||||||
|
boost::erase_regex(part, end_marker_regex);
|
||||||
|
boost::erase_all_regex(part, boost::regex("\\r\\n"));
|
||||||
|
std::string decoded = base64_decode(part);
|
||||||
|
return handle_image(decoded);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EmailParser::search_in_text(std::string &content) {
|
||||||
|
boost::regex text_content_types_regex("Content-Type: text\\/(html|plain)", boost::regex::icase);
|
||||||
|
/* If the E-Mail has no QR code in it as a separate part, there's posibilly a QR code inserted using html's tag <img> with base64-encoded image. Try searching it */
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> texts_content_parts = find_parts(text_content_types_regex, part_end_regex, content);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < texts_content_parts.size(); i ++) {
|
||||||
|
|
||||||
|
std::string part = content.substr(texts_content_parts[i].first, texts_content_parts[i].second);
|
||||||
|
std::string transfer_encoding = extract_content_transfer_encoding(part);
|
||||||
|
|
||||||
|
boost::erase_regex(part, headings_regex);
|
||||||
|
boost::erase_regex(part, end_marker_regex);
|
||||||
|
|
||||||
|
if (transfer_encoding == "quoted-printable") {
|
||||||
|
boost::erase_all_regex(part, boost::regex("=\\r\\n"));
|
||||||
|
} else if (transfer_encoding == "base64") {
|
||||||
|
boost::erase_all_regex(part, boost::regex("\\r\\n"));
|
||||||
|
part = base64_decode(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try searching parameters just in plain html. Will help if there's a link to a QR code with it's parameters passed in request.
|
||||||
|
std::string parameters = find_check_parameters(part);
|
||||||
|
|
||||||
|
if (parameters != "") return parameters;
|
||||||
|
|
||||||
|
// If there's no, try search anything that looks like a link to a qr code.
|
||||||
|
std::string url = extract_qr_url_from_img(part);
|
||||||
|
if (url != "") {
|
||||||
|
Net n;
|
||||||
|
std::string path = get_path_relative_to_home(".local/share/checks_parser/tmp");
|
||||||
|
n.get_file(url, path);
|
||||||
|
|
||||||
|
std::string qr_code_contents = read_file(path);
|
||||||
|
parameters = handle_image(qr_code_contents);
|
||||||
|
}
|
||||||
|
if (parameters != "") return parameters;
|
||||||
|
|
||||||
|
// if there's no any link that looks like a link to QR code, maybe the qr code is encoded as base64 inside an img tag.
|
||||||
|
|
||||||
|
std::vector<std::string> embeddings = extract_qr_embeddings_from_part(part);
|
||||||
|
for (std::string &embedding : embeddings) {
|
||||||
|
std::string decoded = base64_decode(embedding);
|
||||||
|
parameters = handle_image(decoded);
|
||||||
|
if (parameters != "") return parameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EmailParser::handle_image(std::string &content) {
|
||||||
|
cv::Mat image;
|
||||||
|
|
||||||
|
if (content.substr(1, 3) == "PNG" || content.substr(1, 3) == "JPG" || content.substr(6, 4) == "JFIF") {
|
||||||
|
std::vector<uchar> data(content.begin(), content.end());
|
||||||
|
image = cv::imdecode(cv::Mat(data), 1);
|
||||||
|
} else if (content.substr(0, 3) == "GIF") {
|
||||||
|
std::string gif_file_path = get_application_home_path() + "/temp.gif";
|
||||||
|
|
||||||
|
std::ofstream gif_output(gif_file_path, std::ios::binary);
|
||||||
|
gif_output << content;
|
||||||
|
gif_output.close();
|
||||||
|
cv::VideoCapture gif(gif_file_path, cv::CAP_FFMPEG);
|
||||||
|
gif.read(image);
|
||||||
|
}
|
||||||
|
if (image.empty()) return "";
|
||||||
|
|
||||||
|
if (image.rows >= 500 || image.cols >= 500) {
|
||||||
|
cv::Mat copy(image);
|
||||||
|
cv::resize(copy, image, cv::Size(150, 150), cv::INTER_LINEAR);
|
||||||
|
cv::imwrite(get_path_relative_to_home(".local/share/checks_parser/tmp.jpg"), image);
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::QRCodeDetector qrDecoder = cv::QRCodeDetector();
|
||||||
|
std::string decoded_qr = qrDecoder.detectAndDecode(image);
|
||||||
|
return find_check_parameters(decoded_qr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,24 @@
|
|||||||
|
|
||||||
#include <check/check.h>
|
#include <check/check.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
class EmailParser {
|
class EmailParser {
|
||||||
std::string get_payload_in_email(std::string &email_content);
|
boost::regex headings_regex, end_marker_regex, part_end_regex;
|
||||||
std::multimap<std::string, std::string> parse_email_content_types(std::string path);
|
|
||||||
|
|
||||||
// std::vector<int> find_base64_blocks_in_email(std::string &email_content);
|
|
||||||
public:
|
public:
|
||||||
EmailParser();
|
EmailParser();
|
||||||
Check parse(std::string &email_content);
|
std::map<std::string, std::string> parse(std::string &email_content);
|
||||||
Check parse_file(std::string path);
|
std::map<std::string, std::string> parse_file(std::string path);
|
||||||
|
std::vector<std::pair<int, int>> find_parts(const boost::regex &start_regex, const boost::regex &end_regex, const std::string &content);
|
||||||
|
std::string find_check_parameters(std::string &part);
|
||||||
|
std::string extract_qr_url_from_img(std::string &part);
|
||||||
|
std::string extract_content_transfer_encoding(std::string &part);
|
||||||
|
std::vector<std::string> extract_qr_embeddings_from_part(std::string &part);
|
||||||
|
|
||||||
|
std::string search_in_images(std::string &content);
|
||||||
|
std::string search_in_text(std::string &content);
|
||||||
|
|
||||||
|
std::string handle_image(std::string &content);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHECKS_PARSER_EMAIL_PARSER
|
#endif // CHECKS_PARSER_EMAIL_PARSER
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
#include "goods.h"
|
#include "goods.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <QString>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
Goods::Goods() { }
|
||||||
|
|
||||||
Goods::Goods(std::string name, double price_per_unit, std::string net_weight, double quantity) :
|
Goods::Goods(std::string name, double price_per_unit, std::string net_weight, double quantity) :
|
||||||
name(name), price_per_unit(price_per_unit),
|
name(name), price_per_unit(price_per_unit),
|
||||||
@@ -19,10 +23,53 @@ double Goods::get_price_per_unit() { return this->price_per_unit; }
|
|||||||
|
|
||||||
void Goods::set_name(std::string name) { this->name = name; }
|
void Goods::set_name(std::string name) { this->name = name; }
|
||||||
|
|
||||||
|
void Goods::set_name(QString name) { this->name = name.toStdString(); }
|
||||||
|
|
||||||
void Goods::set_quantity(double quantity) { this->quantity = quantity; }
|
void Goods::set_quantity(double quantity) { this->quantity = quantity; }
|
||||||
|
|
||||||
void Goods::set_net_weight(std::string net_weight) { this->net_weight = net_weight; }
|
void Goods::set_net_weight(std::string net_weight) { this->net_weight = net_weight; }
|
||||||
|
|
||||||
|
void Goods::set_net_weight(QString net_weight) { this->net_weight = net_weight.toStdString(); }
|
||||||
|
|
||||||
void Goods::set_price_per_unit(double price_per_unit) {
|
void Goods::set_price_per_unit(double price_per_unit) {
|
||||||
this->price_per_unit = price_per_unit;
|
this->price_per_unit = price_per_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Goods)
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &in, Goods &goods) {
|
||||||
|
in << QString::fromStdString(goods.get_name()) << goods.get_quantity() << QString::fromStdString(goods.get_net_weight()) << goods.get_price_per_unit();
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &out, Goods &goods) {
|
||||||
|
QString name, net_weight;
|
||||||
|
double quantity, price_per_unit;
|
||||||
|
out >> name >> quantity >> net_weight >> price_per_unit;
|
||||||
|
goods.set_name(name);
|
||||||
|
goods.set_quantity(quantity);
|
||||||
|
goods.set_net_weight(net_weight);
|
||||||
|
goods.set_price_per_unit(price_per_unit);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &stream, std::vector<Goods> &goods) {
|
||||||
|
stream << (unsigned int )goods.size();
|
||||||
|
for (Goods &g : goods) {
|
||||||
|
stream << g;
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &stream, std::vector<Goods> &goods) {
|
||||||
|
unsigned int size;
|
||||||
|
stream >> size;
|
||||||
|
for (unsigned int i = 0 ; i < size; i ++) {
|
||||||
|
Goods g = Goods();
|
||||||
|
stream >> g;
|
||||||
|
goods.push_back(g);
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,38 @@
|
|||||||
#ifndef GOODS_H
|
#ifndef GOODS_H
|
||||||
#define GOODS_H
|
#define GOODS_H
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Goods {
|
||||||
|
std::string name;
|
||||||
|
double quantity; // by weight or by the piece
|
||||||
|
std::string net_weight; // will contain values like "5мл" or "10г"
|
||||||
|
double price_per_unit;
|
||||||
|
|
||||||
class Goods
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
double quantity; // by weight or by the piece
|
|
||||||
std::string net_weight; // will contain values like "5мл" or "10г"
|
|
||||||
double price_per_unit;
|
|
||||||
public:
|
public:
|
||||||
Goods(std::string name, double quantity, std::string net_weight, double price_per_unit);
|
Goods();
|
||||||
double calculate_total_price();
|
Goods(std::string name, double quantity, std::string net_weight,
|
||||||
|
double price_per_unit);
|
||||||
|
double calculate_total_price();
|
||||||
|
|
||||||
std::string get_name();
|
std::string get_name();
|
||||||
double get_quantity();
|
double get_quantity();
|
||||||
std::string get_net_weight();
|
std::string get_net_weight();
|
||||||
double get_price_per_unit();
|
double get_price_per_unit();
|
||||||
|
|
||||||
void set_name(std::string);
|
void set_name(std::string);
|
||||||
void set_quantity(double);
|
void set_name(QString);
|
||||||
void set_net_weight(std::string);
|
void set_quantity(double);
|
||||||
void set_price_per_unit(double);
|
void set_net_weight(std::string);
|
||||||
|
void set_net_weight(QString);
|
||||||
|
void set_price_per_unit(double);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &, Goods &);
|
||||||
|
QDataStream &operator>>(QDataStream &, Goods &);
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &, std::vector<Goods> &);
|
||||||
|
QDataStream &operator>>(QDataStream &, std::vector<Goods> &);
|
||||||
#endif // GOODS_H
|
#endif // GOODS_H
|
||||||
|
|||||||
20
main.cpp
20
main.cpp
@@ -1,4 +1,3 @@
|
|||||||
#include "email_parser/emailparser.h"
|
|
||||||
#include <mainwindow.h>
|
#include <mainwindow.h>
|
||||||
#include <net/net.h>
|
#include <net/net.h>
|
||||||
#include <settings/settings.h>
|
#include <settings/settings.h>
|
||||||
@@ -15,24 +14,21 @@
|
|||||||
# include <filesystem>
|
# include <filesystem>
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
#endif
|
#endif
|
||||||
#include <QDateTime>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QStackedLayout>
|
|
||||||
#include <QTextStream>
|
|
||||||
#ifdef BUILD_TRANSLATIONS
|
#ifdef BUILD_TRANSLATIONS
|
||||||
# include <QTranslator>
|
# include <QTranslator>
|
||||||
#endif
|
#endif
|
||||||
#include <settingsdialog.h>
|
|
||||||
#ifdef BUILD_EMAIL_MODE
|
#ifdef BUILD_EMAIL_MODE
|
||||||
// #include <vmime/vmime.hpp>
|
# include <email_parser/emailparser.h>
|
||||||
#endif
|
#endif
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
#include <utils/base64.h>
|
#include <opencv2/dnn.hpp>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
// cv::dnn::readNetFromTensorflow("/home/leca/model.keras");
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
qRegisterMetaType<Check>("Check");
|
||||||
|
|
||||||
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);
|
||||||
@@ -63,7 +59,9 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
std::cout << QObject::tr("Using locale: ").toStdString() << lang.toStdString() << std::endl;
|
std::cout << QObject::tr("Using locale: ").toStdString() << lang.toStdString() << std::endl;
|
||||||
|
|
||||||
translator.load(":/translation/" + lang + ".qm");
|
if (!translator.load(":/translation/" + lang + ".qm")) {
|
||||||
|
std::cerr << "Could not load translation!!" << std::endl;
|
||||||
|
}
|
||||||
app.installTranslator(&translator);
|
app.installTranslator(&translator);
|
||||||
#endif
|
#endif
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
|
|||||||
191
mainwindow.cpp
191
mainwindow.cpp
@@ -5,9 +5,12 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <settingsdialog.h>
|
#include <settingsdialog.h>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||||
# include <adjustpicturedialog.h>
|
# include <adjustpicturedialog.h>
|
||||||
|
# include <checkqueuetablemodel.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <outputdialog.h>
|
#include <outputdialog.h>
|
||||||
@@ -15,7 +18,6 @@
|
|||||||
#include <net/net.h>
|
#include <net/net.h>
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
#include <exceptions/ofdrequestexception.h>
|
#include <exceptions/ofdrequestexception.h>
|
||||||
#include <checklistviewwidget.h>
|
|
||||||
|
|
||||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
# include <qrencode.h>
|
# include <qrencode.h>
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
|
#include <email_parser/emailparser.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
@@ -32,18 +35,24 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->stop_server_button->hide();
|
ui->stop_server_button->hide();
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
|
||||||
|
|
||||||
ui->checks_scroll_area->setLayout(layout);
|
|
||||||
ui->scrollAreaWidgetContents->setLayout(layout);
|
|
||||||
ui->checks_to_parse_label->hide();
|
ui->checks_to_parse_label->hide();
|
||||||
ui->checks_scroll_area->hide();
|
ui->checkQueueTable->hide();
|
||||||
|
ui->deleteSelectedButton->hide();
|
||||||
|
ui->parse_button->hide();
|
||||||
|
|
||||||
connect(this, &MainWindow::deleteCheckFromList, this, &MainWindow::deleteCheckFromListHandler);
|
model = new CheckQueueTableModel(&checks, this);
|
||||||
|
ui->checkQueueTable->setModel(model);
|
||||||
|
ui->checkQueueTable->viewport()->setAcceptDrops(true);
|
||||||
|
ui->checkQueueTable->setDragDropMode(QAbstractItemView::DragDrop);
|
||||||
|
|
||||||
|
ui->checkQueueTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
|
||||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure);
|
QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure);
|
||||||
connect(this, SIGNAL(httpNewMessage(QString)), this, SLOT(httpNewMessageHandler(QString)));
|
connect(this, SIGNAL(httpNewMessage(QString)), this, SLOT(httpNewMessageHandler(QString)));
|
||||||
|
#else
|
||||||
|
ui->or_label_2->hide();
|
||||||
|
ui->binary_eye_button->hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BUILD_EMAIL_MODE
|
#ifndef BUILD_EMAIL_MODE
|
||||||
@@ -51,10 +60,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
ui->or_label_2->hide();
|
ui->or_label_2->hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BUILD_OFD_BINARYEYE_SCAN
|
|
||||||
ui->or_label_2->hide();
|
|
||||||
ui->binary_eye_button->hide();
|
|
||||||
#endif
|
|
||||||
#ifndef BUILD_OFD_LOCAL_QR_SCAN
|
#ifndef BUILD_OFD_LOCAL_QR_SCAN
|
||||||
ui->or_label_1->hide();
|
ui->or_label_1->hide();
|
||||||
ui->choose_image_button->hide();
|
ui->choose_image_button->hide();
|
||||||
@@ -122,32 +127,17 @@ void MainWindow::httpNewMessageHandler(QString message) {
|
|||||||
|
|
||||||
//erase /?result= from the string
|
//erase /?result= from the string
|
||||||
parametersString.erase(0, parametersString.find("=") + 1);
|
parametersString.erase(0, parametersString.find("=") + 1);
|
||||||
|
std::map<std::string, std::string> paramsMap = get_params_from_string(parametersString);
|
||||||
std::vector<std::string> parameters = split(parametersString, "&");
|
|
||||||
|
|
||||||
std::map<std::string, std::string> paramsMap;
|
|
||||||
|
|
||||||
for (auto ¶meter : parameters) {
|
|
||||||
std::vector<std::string> values = split(parameter, "=");
|
|
||||||
paramsMap.insert(std::pair<std::string, std::string> (values[0], values[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
emit onDataDecode(paramsMap);
|
emit onDataDecode(paramsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //ifdef BUILD_OFD_BINARYEYE_SCAN
|
#endif //ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
|
|
||||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||||
void MainWindow::on_choose_image_button_clicked() {
|
void MainWindow::on_choose_image_button_clicked() {
|
||||||
QString filename = QFileDialog::getOpenFileName();
|
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("Images (*.jpg *.jpeg *.png)"));
|
||||||
|
|
||||||
if (filename == "") {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,95 +150,70 @@ void MainWindow::on_choose_image_button_clicked() {
|
|||||||
#endif //ifdef BUILD_OFD_LOCAL_QR_SCAN
|
#endif //ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||||
|
|
||||||
void MainWindow::onDataDecode(std::map<std::string, std::string> data) {
|
void MainWindow::onDataDecode(std::map<std::string, std::string> data) {
|
||||||
ui->fn_line_edit->setText(QString::fromStdString(data["fn"]));
|
set_check_params(data);
|
||||||
ui->fd_line_edit->setText(QString::fromStdString(data["i"]));
|
|
||||||
ui->fi_line_edit->setText(QString::fromStdString(data["fp"]));
|
|
||||||
|
|
||||||
QString extractedDateTime = QString::fromStdString(data["t"]);
|
|
||||||
//TODO: some QRs contain datetime in format yyyyMMddThhmmss. Perhaps there is more different formats, should write function to detect them.
|
|
||||||
QDateTime datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmm");
|
|
||||||
if (datetime == QDateTime::fromString(extractedDateTime, "20000101T1200")) {
|
|
||||||
datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmmss");
|
|
||||||
}
|
|
||||||
ui->purchase_datetime_edit->setDateTime(datetime);
|
|
||||||
|
|
||||||
int type = std::stoi(data["n"]);
|
|
||||||
ui->operation_type_combo_box->setCurrentIndex(type - 1);
|
|
||||||
|
|
||||||
std::string total = data["s"];
|
|
||||||
|
|
||||||
ui->total_spin_box->setValue(std::stod(total));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILD_EMAIL_MODE
|
#ifdef BUILD_EMAIL_MODE
|
||||||
|
|
||||||
void MainWindow::on_parse_email_button_clicked() {
|
void MainWindow::on_parse_email_button_clicked() {
|
||||||
QMessageBox infoDialog;
|
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("E-Mail files (*.eml)"));
|
||||||
infoDialog.setText(tr("This feature is under development. Wait it to appear in next updates."));
|
|
||||||
infoDialog.setIcon(QMessageBox::Warning);
|
|
||||||
infoDialog.setWindowTitle(tr("Under development"));
|
|
||||||
infoDialog.exec();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (filename == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailParser email_parser;
|
||||||
|
std::map<std::string, std::string> paramsMap = email_parser.parse_file(filename.toStdString());
|
||||||
|
|
||||||
|
if (paramsMap.empty()) {
|
||||||
|
QMessageBox infoDialog;
|
||||||
|
infoDialog.setText(tr("QR code in this E-Mail was not found. If you are sure that the e-mail you supplied has qr code, please, contact the developer and send him the .eml file."));
|
||||||
|
infoDialog.setIcon(QMessageBox::Critical);
|
||||||
|
infoDialog.setWindowTitle(tr("QR code was not found in E-Mail"));
|
||||||
|
infoDialog.exec();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_check_params(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ifdef BUILD_EMAIL_MODE
|
#endif // ifdef BUILD_EMAIL_MODE
|
||||||
|
|
||||||
void MainWindow::on_parse_button_clicked() {
|
void MainWindow::on_parse_button_clicked() {
|
||||||
// if (checks.empty()) {
|
|
||||||
// QMessageBox infoDialog;
|
if (checks.empty()) {
|
||||||
// infoDialog.setText(tr("Please, add check(s) to parse"));
|
QMessageBox infoDialog;
|
||||||
// infoDialog.setIcon(QMessageBox::Warning);
|
infoDialog.setText(tr("Please, add check(s) to parse"));
|
||||||
// infoDialog.setWindowTitle(tr("No checks to parse"));
|
infoDialog.setIcon(QMessageBox::Warning);
|
||||||
// infoDialog.exec();
|
infoDialog.setWindowTitle(tr("No checks to parse"));
|
||||||
// return;
|
infoDialog.exec();
|
||||||
// }
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OutputDialog d = OutputDialog(this, &checks);
|
OutputDialog d = OutputDialog(this, &checks);
|
||||||
d.exec();
|
d.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::deleteCheckFromListHandler(Check &check) {
|
|
||||||
for (unsigned int i = 0; i < ui->scrollAreaWidgetContents->layout()->count(); i ++) {
|
|
||||||
QLayoutItem *item = ui->scrollAreaWidgetContents->layout()->itemAt(i);
|
|
||||||
QObject *child = item->widget();
|
|
||||||
CheckListViewWidget *c = (CheckListViewWidget *)child;
|
|
||||||
if (c->get_check() == check) {
|
|
||||||
ui->scrollAreaWidgetContents->layout()->removeItem(item);
|
|
||||||
delete item;
|
|
||||||
delete child;
|
|
||||||
ui->scrollAreaWidgetContents->layout()->update();
|
|
||||||
ui->scrollAreaWidgetContents->update();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int position = std::find(checks.begin(), checks.end(), check) - checks.begin() - 1;
|
|
||||||
checks.erase(checks.begin() + position);
|
|
||||||
|
|
||||||
if (ui->scrollAreaWidgetContents->layout()->count() == 0) {
|
|
||||||
ui->checks_to_parse_label->hide();
|
|
||||||
ui->checks_scroll_area->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_add_new_check_button_clicked() {
|
void MainWindow::on_add_new_check_button_clicked() {
|
||||||
Check *new_check = parse_new_check();
|
Check *new_check = parse_new_check();
|
||||||
if (new_check == nullptr) {
|
if (new_check == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
checks.push_back(*new_check);
|
unsigned int newRowIndex = checks.size();
|
||||||
|
model->insertRows(newRowIndex, 1);
|
||||||
|
|
||||||
CheckListViewWidget *check_list_widget = new CheckListViewWidget(this, *new_check);
|
checks.at(newRowIndex) = *new_check;
|
||||||
|
|
||||||
ui->scrollAreaWidgetContents->layout()->addWidget(check_list_widget);
|
emit model->dataChanged(model->index(newRowIndex, 0), model->index(newRowIndex, 1));
|
||||||
|
|
||||||
delete new_check;
|
delete new_check;
|
||||||
|
|
||||||
if (checks.size() == 1) {
|
if (checks.size() > 0) {
|
||||||
ui->checks_scroll_area->show();
|
ui->checkQueueTable->show();
|
||||||
ui->checks_to_parse_label->show();
|
ui->checks_to_parse_label->show();
|
||||||
|
ui->deleteSelectedButton->show();
|
||||||
|
ui->parse_button->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +237,8 @@ Check *MainWindow::parse_new_check() {
|
|||||||
ui->operation_type_combo_box->currentIndex() + 1,
|
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.
|
// 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,
|
ui->total_spin_box->text().toDouble() * 100,
|
||||||
solved_captcha);
|
solved_captcha
|
||||||
|
);
|
||||||
|
|
||||||
(*check) = parseOfdRuAnswer(check_content);
|
(*check) = parseOfdRuAnswer(check_content);
|
||||||
check->set_date(ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString());
|
check->set_date(ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString());
|
||||||
@@ -280,24 +246,24 @@ Check *MainWindow::parse_new_check() {
|
|||||||
check->set_fd(ui->fd_line_edit->text().toStdString());
|
check->set_fd(ui->fd_line_edit->text().toStdString());
|
||||||
check->set_fi(ui->fi_line_edit->text().toStdString());
|
check->set_fi(ui->fi_line_edit->text().toStdString());
|
||||||
check->set_operation_type(OperationType(ui->operation_type_combo_box->currentIndex() + 1));
|
check->set_operation_type(OperationType(ui->operation_type_combo_box->currentIndex() + 1));
|
||||||
|
|
||||||
return check;
|
return check;
|
||||||
} catch(OfdRequestException e) {
|
} catch(OfdRequestException e) {
|
||||||
|
QMessageBox infoDialog;
|
||||||
if (!strcmp(e.what(), "Incorrect captcha")) {
|
if (!strcmp(e.what(), "Incorrect captcha")) {
|
||||||
QMessageBox infoDialog;
|
|
||||||
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
||||||
infoDialog.setIcon(QMessageBox::Critical);
|
infoDialog.setIcon(QMessageBox::Critical);
|
||||||
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
||||||
infoDialog.exec();
|
infoDialog.exec();
|
||||||
continue;
|
continue;
|
||||||
} else if (!strcmp(e.what(), "Internal server error")) {
|
} else if (!strcmp(e.what(), "Internal server error")) {
|
||||||
QMessageBox infoDialog;
|
|
||||||
infoDialog.setText(tr("Internal server error. Please, try again later."));
|
infoDialog.setText(tr("Internal server error. Please, try again later."));
|
||||||
infoDialog.setIcon(QMessageBox::Critical);
|
infoDialog.setIcon(QMessageBox::Critical);
|
||||||
infoDialog.setWindowTitle(tr("Internal server error"));
|
infoDialog.setWindowTitle(tr("Internal server error"));
|
||||||
infoDialog.exec();
|
infoDialog.exec();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (!strcmp(e.what(), "Does not exist")) {
|
} else if (!strcmp(e.what(), "Does not exist")) {
|
||||||
QMessageBox infoDialog;
|
|
||||||
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
||||||
infoDialog.setIcon(QMessageBox::Critical);
|
infoDialog.setIcon(QMessageBox::Critical);
|
||||||
infoDialog.setWindowTitle(tr("Check was not found"));
|
infoDialog.setWindowTitle(tr("Check was not found"));
|
||||||
@@ -312,3 +278,40 @@ Check *MainWindow::parse_new_check() {
|
|||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_deleteSelectedButton_clicked() {
|
||||||
|
QItemSelectionModel *select = ui->checkQueueTable->selectionModel();
|
||||||
|
std::vector<unsigned int> to_delete_positions = {};
|
||||||
|
for (auto &row : select->selectedIndexes()) {
|
||||||
|
if (row.column() != 0) continue;
|
||||||
|
to_delete_positions.push_back(row.row());
|
||||||
|
}
|
||||||
|
std::sort(to_delete_positions.begin(), to_delete_positions.end(), std::greater<unsigned int>());
|
||||||
|
for (unsigned int position : to_delete_positions) {
|
||||||
|
model->removeRows(position, 1);
|
||||||
|
}
|
||||||
|
emit model->dataChanged(model->index(checks.size(), 0), model->index(checks.size() + to_delete_positions.size(), 1));
|
||||||
|
ui->checkQueueTable->clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::set_check_params(std::map<std::string, std::string> paramsMap) {
|
||||||
|
ui->fn_line_edit->setText(QString::fromStdString(paramsMap["fn"]));
|
||||||
|
ui->fd_line_edit->setText(QString::fromStdString(paramsMap["i"]));
|
||||||
|
ui->fi_line_edit->setText(QString::fromStdString(paramsMap["fp"]));
|
||||||
|
|
||||||
|
QString extractedDateTime = QString::fromStdString(paramsMap["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(paramsMap["n"]);
|
||||||
|
ui->operation_type_combo_box->setCurrentIndex(type - 1);
|
||||||
|
|
||||||
|
std::string total = paramsMap["s"];
|
||||||
|
|
||||||
|
ui->total_spin_box->setValue(std::stod(total));
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <checkqueuetablemodel.h>
|
||||||
|
|
||||||
#include <http_server/http_server.h>
|
#include <http_server/http_server.h>
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ public:
|
|||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
Check *parse_new_check();
|
Check *parse_new_check();
|
||||||
|
CheckQueueTableModel *model;
|
||||||
|
|
||||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
void startHttpServer();
|
void startHttpServer();
|
||||||
@@ -47,12 +49,15 @@ private slots:
|
|||||||
void on_stop_server_button_clicked();
|
void on_stop_server_button_clicked();
|
||||||
|
|
||||||
void httpNewMessageHandler(QString message);
|
void httpNewMessageHandler(QString message);
|
||||||
void deleteCheckFromListHandler(Check&);
|
// void deleteCheckFromListHandler(Check&);
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUILD_EMAIL_MODE
|
#ifdef BUILD_EMAIL_MODE
|
||||||
void on_parse_email_button_clicked();
|
void on_parse_email_button_clicked();
|
||||||
#endif
|
#endif
|
||||||
void on_add_new_check_button_clicked();
|
void on_add_new_check_button_clicked();
|
||||||
|
|
||||||
|
void on_deleteSelectedButton_clicked();
|
||||||
|
void set_check_params(std::map<std::string, std::string>);
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
std::vector<Check> checks;
|
std::vector<Check> checks;
|
||||||
|
|||||||
27
net/net.cpp
27
net/net.cpp
@@ -7,29 +7,42 @@ Net::Net() {}
|
|||||||
|
|
||||||
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
|
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||||
size_t totalSize = size * nmemb;
|
size_t totalSize = size * nmemb;
|
||||||
((std::string*)userp)->append(std::string((char*)contents));
|
((std::string*)userp)->append(std::string((char *)contents));
|
||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write_data(void *buffer, size_t size, size_t nmemb, void *filename) {
|
// size_t write_data_to_file(void *buffer, size_t size, size_t nmemb, void *filename) {
|
||||||
FILE *f = fopen(((std::string *)filename)->c_str(), "w");
|
// FILE *f = fopen(((std::string *)filename)->c_str(), "wb");
|
||||||
size_t written = fwrite(buffer, size, nmemb, f);
|
// size_t written = fwrite(buffer, size, nmemb, f);
|
||||||
|
|
||||||
fclose(f);
|
// fclose(f);
|
||||||
|
|
||||||
|
// return written;
|
||||||
|
// }
|
||||||
|
|
||||||
|
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||||
|
size_t written;
|
||||||
|
written = fwrite(ptr, size, nmemb, stream);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// size_t write_data(void *buffer, size_t size, size_t nmemb, void *string_buffer) {
|
||||||
|
// *(std::string *)string_buffer = std::string((char *)buffer);
|
||||||
|
// std::cout << (char*)buffer << std::endl;
|
||||||
|
// return size;
|
||||||
|
// }
|
||||||
|
|
||||||
void Net::get_file(std::string url, std::string filename) {
|
void Net::get_file(std::string url, std::string filename) {
|
||||||
CURL *handle = curl_easy_init();
|
CURL *handle = curl_easy_init();
|
||||||
|
|
||||||
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
||||||
|
FILE *f = fopen(filename.c_str(), "wb");
|
||||||
|
|
||||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
|
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
|
||||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &filename);
|
curl_easy_setopt(handle, CURLOPT_WRITEDATA, f);
|
||||||
|
|
||||||
auto success = curl_easy_perform(handle);
|
auto success = curl_easy_perform(handle);
|
||||||
|
fclose(f);
|
||||||
curl_easy_cleanup(handle);
|
curl_easy_cleanup(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
|
size_t write_data_to_file(void *buffer, size_t size, size_t nmemb, void *userp);
|
||||||
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp);
|
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp);
|
||||||
|
|
||||||
class Net
|
class Net
|
||||||
@@ -14,6 +14,7 @@ public:
|
|||||||
void get_file(std::string url, std::string filename);
|
void get_file(std::string url, std::string filename);
|
||||||
std::string fetch_check_data_from_ofdru(std::string fn, std::string fd, std::string fi, std::string datetime, int operation, int total, std::string captcha);
|
std::string fetch_check_data_from_ofdru(std::string fn, std::string fd, std::string fi, std::string datetime, int operation, int total, std::string captcha);
|
||||||
void get_captcha_from_ofdru();
|
void get_captcha_from_ofdru();
|
||||||
|
std::string get_data(std::string url);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NET_H
|
#endif // NET_H
|
||||||
|
|||||||
@@ -11,51 +11,50 @@
|
|||||||
#include <outputcolumnmodel.h>
|
#include <outputcolumnmodel.h>
|
||||||
#include "settings/settings.h"
|
#include "settings/settings.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
OutputDialog::OutputDialog(QWidget *parent, std::vector<Check> *checks)
|
OutputDialog::OutputDialog(QWidget *parent, std::vector<Check> *checks)
|
||||||
: QDialog(parent), ui(new Ui::OutputDialog), checks(checks),
|
: QDialog(parent), ui(new Ui::OutputDialog), checks(checks),
|
||||||
options(OutputOptions()) {
|
options(OutputOptions()) {
|
||||||
Settings settings(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
|
settings = new Settings(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
for (Check &c : *checks) {
|
||||||
|
std::cout << "Check: " << c.get_date() << " " << c.get_total() << std::endl;
|
||||||
|
for (Goods &g : c.get_goods()) {
|
||||||
|
std::cout << g.get_name() << " " << g.get_net_weight() << " " << g.get_price_per_unit() << " " << g.get_quantity() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
columns = new std::vector<OutputColumn>;
|
columns = new std::vector<OutputColumn>;
|
||||||
|
|
||||||
columns->push_back(OutputColumn(tr("Date"), ColumnType::date));
|
OutputColumnModel *model = new OutputColumnModel(columns, this);
|
||||||
columns->push_back(OutputColumn(tr("Goods name"), ColumnType::goods_name));
|
|
||||||
columns->push_back(OutputColumn(tr("Goods price per unit"), ColumnType::goods_price_per_unit));
|
|
||||||
columns->push_back(OutputColumn(tr("Goods quantity"), ColumnType::goods_quantity));
|
|
||||||
columns->push_back(OutputColumn(tr("Goods net weight"), ColumnType::goods_net_weight));
|
|
||||||
columns->push_back(OutputColumn(tr("Goods total"), ColumnType::goods_total));
|
|
||||||
|
|
||||||
OutputColumnModel *model = new OutputColumnModel(&(*columns), this);
|
|
||||||
|
|
||||||
ui->listView->setModel(model);
|
ui->listView->setModel(model);
|
||||||
|
|
||||||
// ui->tableWidget->item(0, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["date"]["name"]));
|
for (unsigned short i = 0; i < 6; i ++)
|
||||||
// ui->tableWidget->item(0, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["date"]["position"]));
|
columns->push_back(OutputColumn(tr("Кто здесь?"), ColumnType::date));
|
||||||
|
|
||||||
// ui->tableWidget->item(1, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_name"]["name"]));
|
for (auto &column : column_names) {
|
||||||
// ui->tableWidget->item(1, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_name"]["position"]));
|
std::string name = settings->get_all_settings()["output_order"][column.first]["name"];
|
||||||
|
unsigned short position = settings->get_all_settings()["output_order"][column.first]["position"];
|
||||||
|
ColumnType type = column.second;
|
||||||
|
columns->at(position - 1) = (OutputColumn(QString::fromStdString(name), type));
|
||||||
|
|
||||||
// ui->tableWidget->item(2, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"]));
|
}
|
||||||
// ui->tableWidget->item(2, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"]));
|
|
||||||
|
|
||||||
// ui->tableWidget->item(3, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_quantity"]["name"]));
|
for (unsigned short i = 0; i < 6; i ++)
|
||||||
// ui->tableWidget->item(3, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_quantity"]["position"]));
|
emit model->dataChanged(model->index(i, 0), model->index(i, 0));
|
||||||
|
|
||||||
// ui->tableWidget->item(4, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_net_weight"]["name"]));
|
ui->printHeaderCheckBox->setChecked(settings->get_all_settings()["print_header"]);
|
||||||
// ui->tableWidget->item(4, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]));
|
ui->printTotalCheckBox->setChecked(settings->get_all_settings()["print_total"]);
|
||||||
|
|
||||||
// ui->tableWidget->item(5, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_total"]["name"]));
|
|
||||||
// ui->tableWidget->item(5, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_total"]["position"]));
|
|
||||||
|
|
||||||
|
|
||||||
ui->printHeaderCheckBox->setChecked(settings.get_all_settings()["print_header"]);
|
|
||||||
ui->printTotalCheckBox->setChecked(settings.get_all_settings()["print_total"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputDialog::~OutputDialog() { delete ui; }
|
OutputDialog::~OutputDialog() {
|
||||||
|
delete settings;
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
void OutputDialog::on_buttonBox_accepted() {
|
void OutputDialog::on_buttonBox_accepted() {
|
||||||
std::ofstream output_file(this->options.get_path());
|
std::ofstream output_file(this->options.get_path());
|
||||||
@@ -67,7 +66,6 @@ void OutputDialog::on_buttonBox_accepted() {
|
|||||||
for (auto it = check.get_goods().begin(); it != check.get_goods().end(); it++, row_number++) {
|
for (auto it = check.get_goods().begin(); it != check.get_goods().end(); it++, row_number++) {
|
||||||
for (int i = 0; i < columns->size(); i ++) {
|
for (int i = 0; i < columns->size(); i ++) {
|
||||||
OutputColumn &column = columns->at(i);
|
OutputColumn &column = columns->at(i);
|
||||||
std::cout << column.get_text().toStdString() << std::endl;
|
|
||||||
switch (column.get_column_type()) {
|
switch (column.get_column_type()) {
|
||||||
case ColumnType::date:
|
case ColumnType::date:
|
||||||
if (row_number == 0) output_file << check.get_date();
|
if (row_number == 0) output_file << check.get_date();
|
||||||
@@ -90,7 +88,7 @@ void OutputDialog::on_buttonBox_accepted() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i < columns->size() - 1) {
|
if (i < columns->size() - 1) {
|
||||||
output_file << ",";
|
output_file << "|";
|
||||||
} else {
|
} else {
|
||||||
output_file << "\n";
|
output_file << "\n";
|
||||||
}
|
}
|
||||||
@@ -102,22 +100,9 @@ void OutputDialog::on_buttonBox_accepted() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
output_file.close();
|
output_file.close();
|
||||||
|
save_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
// void update_settings(OutputOptions &options, ColumnType t, std::string name,
|
|
||||||
// int value) {
|
|
||||||
// Column column;
|
|
||||||
// column.type = t;
|
|
||||||
// column.name = name;
|
|
||||||
// column.position = value;
|
|
||||||
|
|
||||||
// if (value) {
|
|
||||||
// options.add_or_update_column(column);
|
|
||||||
// } else {
|
|
||||||
// options.remove_column(t);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void OutputDialog::on_chooseFileButton_clicked() {
|
void OutputDialog::on_chooseFileButton_clicked() {
|
||||||
QString filename = QFileDialog::getSaveFileName();
|
QString filename = QFileDialog::getSaveFileName();
|
||||||
this->options.set_path(filename.toStdString());
|
this->options.set_path(filename.toStdString());
|
||||||
@@ -139,8 +124,18 @@ void OutputDialog::print_header(std::ofstream *output_file) {
|
|||||||
(*output_file) << column.get_text().toStdString()
|
(*output_file) << column.get_text().toStdString()
|
||||||
<< (i == columns->size() - 1
|
<< (i == columns->size() - 1
|
||||||
? ""
|
? ""
|
||||||
: ",");
|
: "|");
|
||||||
}
|
}
|
||||||
*output_file << std::endl;
|
*output_file << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OutputDialog::save_settings() {
|
||||||
|
for (int i = 0; i < columns->size(); i ++) {
|
||||||
|
OutputColumn &column = columns->at(i);
|
||||||
|
std::string key = find_key_by_value(column_names, column.get_column_type());
|
||||||
|
settings->get_all_settings()["output_order"][key]["name"] = column.get_text().toStdString();
|
||||||
|
settings->get_all_settings()["output_order"][key]["position"] = i + 1;
|
||||||
|
}
|
||||||
|
settings->flush();
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class OutputDialog : public QDialog {
|
|||||||
OutputOptions options;
|
OutputOptions options;
|
||||||
std::vector<Check> *checks;
|
std::vector<Check> *checks;
|
||||||
std::vector<OutputColumn> *columns;
|
std::vector<OutputColumn> *columns;
|
||||||
|
Settings *settings;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OutputDialog(QWidget *parent = nullptr, std::vector<Check> *checks = nullptr);
|
explicit OutputDialog(QWidget *parent = nullptr, std::vector<Check> *checks = nullptr);
|
||||||
@@ -35,6 +36,8 @@ private:
|
|||||||
Ui::OutputDialog *ui;
|
Ui::OutputDialog *ui;
|
||||||
|
|
||||||
void print_header(std::ofstream *output_file);
|
void print_header(std::ofstream *output_file);
|
||||||
|
|
||||||
|
void save_settings();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OUTPUTDIALOG_H
|
#endif // OUTPUTDIALOG_H
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1269</width>
|
<width>987</width>
|
||||||
<height>490</height>
|
<height>426</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -26,23 +26,23 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="1" column="1">
|
<item row="8" column="2" colspan="4">
|
||||||
<widget class="QLabel" name="or_label_1">
|
<widget class="QDoubleSpinBox" name="total_spin_box">
|
||||||
|
<property name="maximum">
|
||||||
|
<double>4294967296.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="2" colspan="4">
|
||||||
|
<widget class="QPushButton" name="add_new_check_button">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>or</string>
|
<string>Add to queue</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>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -59,155 +59,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="2" colspan="3">
|
<item row="7" column="2" colspan="4">
|
||||||
<widget class="QDoubleSpinBox" name="total_spin_box">
|
|
||||||
<property name="maximum">
|
|
||||||
<double>4294967296.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="5">
|
|
||||||
<widget class="QLabel" name="checks_to_parse_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Checks to parse</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
||||||
</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="9" column="4">
|
|
||||||
<widget class="QPushButton" name="parse_button">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Parse</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QPushButton" name="settings_button">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Settings</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="8" column="0">
|
|
||||||
<widget class="QLabel" name="total_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Total</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QPushButton" name="binary_eye_button">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Use your phone as a QR code scanner</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QLabel" name="or_label_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>or</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QPushButton" name="choose_image_button">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Choose image on your PC</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2" colspan="3">
|
|
||||||
<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="6" column="2" colspan="3">
|
|
||||||
<widget class="QDateTimeEdit" name="purchase_datetime_edit"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="5">
|
|
||||||
<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="0" column="4">
|
|
||||||
<widget class="QPushButton" name="stop_server_button">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Stop server</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="2" colspan="3">
|
|
||||||
<widget class="QComboBox" name="operation_type_combo_box">
|
<widget class="QComboBox" name="operation_type_combo_box">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -231,14 +83,200 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="0" column="5">
|
||||||
<widget class="QLabel" name="operation_type_label">
|
<widget class="QPushButton" name="stop_server_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Operation type</string>
|
<string>Stop server</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="5" column="2" colspan="4">
|
||||||
|
<widget class="QLineEdit" name="fi_line_edit"/>
|
||||||
|
</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="1" column="1" colspan="2">
|
||||||
|
<widget class="QLabel" name="or_label_1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>or</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2" colspan="4">
|
||||||
|
<widget class="QLineEdit" name="fd_line_edit"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="6">
|
||||||
|
<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="0" column="7">
|
||||||
|
<widget class="QLabel" name="checks_to_parse_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Checks to parse</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="7" colspan="2">
|
||||||
|
<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 queue</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QLabel" name="or_label_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>or</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QPushButton" name="choose_image_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>QR image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2" colspan="4">
|
||||||
|
<widget class="QLineEdit" name="fn_line_edit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5">
|
||||||
|
<widget class="QPushButton" name="binary_eye_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Scan QR using phone</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPushButton" name="settings_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Settings</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QPushButton" name="clear_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear data</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="7" rowspan="8" colspan="2">
|
||||||
|
<widget class="QTableView" name="checkQueueTable">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed</set>
|
||||||
|
</property>
|
||||||
|
<property name="tabKeyNavigation">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropOverwriteMode">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::DropAction::MoveAction</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::SelectionMode::MultiSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="2" colspan="4">
|
||||||
|
<widget class="QDateTimeEdit" name="purchase_datetime_edit"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
<widget class="QPushButton" name="parse_email_button">
|
<widget class="QPushButton" name="parse_email_button">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
@@ -251,48 +289,62 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0" colspan="2">
|
<item row="5" column="0">
|
||||||
<widget class="QPushButton" name="clear_button">
|
<widget class="QLabel" name="fi_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>FI (Fiscal Identifier)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="total_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Total</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="3" column="0">
|
||||||
|
<widget class="QLabel" name="fn_label">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Clear</string>
|
<string>FN (Fiscal Number)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="2" colspan="3">
|
<item row="0" column="8">
|
||||||
<widget class="QLineEdit" name="fi_line_edit"/>
|
<widget class="QPushButton" name="deleteSelectedButton">
|
||||||
</item>
|
|
||||||
<item row="9" column="2" colspan="2">
|
|
||||||
<widget class="QPushButton" name="add_new_check_button">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add new check</string>
|
<string>Delete selected</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2" colspan="3">
|
<item row="1" column="6">
|
||||||
<widget class="QLineEdit" name="fd_line_edit"/>
|
<spacer name="horizontalSpacer">
|
||||||
</item>
|
<property name="orientation">
|
||||||
<item row="1" column="5" rowspan="9">
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
<widget class="QScrollArea" name="checks_scroll_area">
|
|
||||||
<property name="widgetResizable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
<property name="sizeType">
|
||||||
<property name="geometry">
|
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
|
||||||
<rect>
|
</property>
|
||||||
<x>0</x>
|
<property name="sizeHint" stdset="0">
|
||||||
<y>0</y>
|
<size>
|
||||||
<width>273</width>
|
<width>40</width>
|
||||||
<height>404</height>
|
<height>20</height>
|
||||||
</rect>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</spacer>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
|||||||
@@ -37,6 +37,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="3">
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QListView" name="listView">
|
<widget class="QListView" name="listView">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed</set>
|
||||||
|
</property>
|
||||||
<property name="dragEnabled">
|
<property name="dragEnabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QScrollArea" name="scrollArea">
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="widgetResizable">
|
<property name="widgetResizable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -24,14 +30,28 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>659</width>
|
<width>673</width>
|
||||||
<height>634</height>
|
<height>554</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="14" column="1">
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="printHeaderCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="print_total_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Print total</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
<widget class="QComboBox" name="languageComboBox">
|
<widget class="QComboBox" name="languageComboBox">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -45,161 +65,52 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QLabel" name="print_header_label">
|
||||||
<property name="text">
|
|
||||||
<string>Goods quantity alias</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLineEdit" name="goodsQuantityAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QSpinBox" name="goodsPricePerUnitPositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QSpinBox" name="goodsNamePositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QSpinBox" name="goodsNetWeightPositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods price per unit alias</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="1">
|
|
||||||
<widget class="QLineEdit" name="goodsTotalAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Print header</string>
|
<string>Print header</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="label_13">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods quantity position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="10" column="1">
|
|
||||||
<widget class="QSpinBox" name="goodsTotalPositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_15">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods net weight position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QSpinBox" name="dateNamePositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QLineEdit" name="goodsPricePerUnitAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods name position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Print total</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Date name position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_11">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods price per unit position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="1">
|
|
||||||
<widget class="QCheckBox" name="printTotalCheckBox">
|
<widget class="QCheckBox" name="printTotalCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="0">
|
|
||||||
<widget class="QLabel" name="label_17">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods total position</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QSpinBox" name="goodsQuantityPositionSpin"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="language_label">
|
||||||
<property name="text">
|
|
||||||
<string>Goods name alias</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<widget class="QLineEdit" name="goodsNetWeightAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0">
|
|
||||||
<widget class="QLabel" name="label_18">
|
|
||||||
<property name="text">
|
|
||||||
<string>Goods total alias</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="goodsNameAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="1">
|
|
||||||
<widget class="QCheckBox" name="printHeaderCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Language</string>
|
<string>Language</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="label_16">
|
<widget class="QListView" name="outputOptionsListView">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Goods net weight alias</string>
|
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="dragEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::DropAction::TargetMoveAction</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Date name alias</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="dateNameAliasEdit"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
#include <settings/settings.h>
|
#include <settings/settings.h>
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <outputcolumnmodel.h>
|
||||||
|
|
||||||
SettingsDialog::SettingsDialog(QWidget *parent)
|
SettingsDialog::SettingsDialog(QWidget *parent)
|
||||||
: QDialog(parent), ui(new Ui::settingsdialog),
|
: QDialog(parent), ui(new Ui::settingsdialog),
|
||||||
@@ -15,23 +14,24 @@ SettingsDialog::SettingsDialog(QWidget *parent)
|
|||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
ui->goodsNamePositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_name"]["position"]);
|
columns = new std::vector<OutputColumn>;
|
||||||
ui->goodsNameAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_name"]["name"]));
|
|
||||||
|
|
||||||
ui->goodsPricePerUnitPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"]);
|
OutputColumnModel *model = new OutputColumnModel(columns, this);
|
||||||
ui->goodsPricePerUnitAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"]));
|
|
||||||
|
|
||||||
ui->goodsQuantityPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_quantity"]["position"]);
|
ui->outputOptionsListView->setModel(model);
|
||||||
ui->goodsQuantityAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_quantity"]["name"]));
|
|
||||||
|
|
||||||
ui->goodsNetWeightPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]);
|
for (unsigned short i = 0; i < 6; i ++)
|
||||||
ui->goodsNetWeightAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_net_weight"]["name"]));
|
columns->push_back(OutputColumn(tr("Кто здесь?"), ColumnType::date));
|
||||||
|
|
||||||
ui->goodsTotalPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_total"]["position"]);
|
for (auto &column : column_names) {
|
||||||
ui->goodsTotalAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_total"]["name"]));
|
std::string name = settings.get_all_settings()["output_order"][column.first]["name"];
|
||||||
|
unsigned short position = settings.get_all_settings()["output_order"][column.first]["position"];
|
||||||
|
ColumnType type = column.second;
|
||||||
|
columns->at(position - 1) = (OutputColumn(QString::fromStdString(name), type));
|
||||||
|
}
|
||||||
|
|
||||||
ui->printHeaderCheckBox->setChecked(this->settings.get_all_settings()["print_header"]);
|
ui->printHeaderCheckBox->setChecked(settings.get_all_settings()["print_header"]);
|
||||||
ui->printTotalCheckBox->setChecked(this->settings.get_all_settings()["print_total"]);
|
ui->printTotalCheckBox->setChecked(settings.get_all_settings()["print_total"]);
|
||||||
|
|
||||||
int currentLanguageIndex = 0;
|
int currentLanguageIndex = 0;
|
||||||
bool languageSettingPresent = false;
|
bool languageSettingPresent = false;
|
||||||
@@ -51,59 +51,6 @@ SettingsDialog::SettingsDialog(QWidget *parent)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::on_goodsNamePositionSpin_valueChanged(int value) {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_name"]["position"] =
|
|
||||||
value;
|
|
||||||
}
|
|
||||||
void SettingsDialog::on_goodsNameAliasEdit_editingFinished() {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_name"]["name"] =
|
|
||||||
ui->goodsNameAliasEdit->text().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsPricePerUnitPositionSpin_valueChanged(int value) {
|
|
||||||
this->settings
|
|
||||||
.get_all_settings()["output_order"]["goods_price_per_unit"]["position"] =
|
|
||||||
value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsPricePerUnitAliasEdit_editingFinished() {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"] =
|
|
||||||
ui->goodsPricePerUnitAliasEdit->text().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsQuantityPositionSpin_valueChanged(int value) {
|
|
||||||
this->settings
|
|
||||||
.get_all_settings()["output_order"]["goods_quantity"]["position"] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsQuantityAliasEdit_editingFinished() {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_quantity"]["name"] =
|
|
||||||
ui->goodsQuantityAliasEdit->text().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsNetWeightPositionSpin_valueChanged(int value) {
|
|
||||||
this->settings
|
|
||||||
.get_all_settings()["output_order"]["goods_net_weight"]["position"] =
|
|
||||||
value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsNetWeightAliasEdit_editingFinished() {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_net_weight"]["name"] =
|
|
||||||
ui->goodsNetWeightAliasEdit->text().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsTotalPositionSpin_valueChanged(int value) {
|
|
||||||
this->settings
|
|
||||||
.get_all_settings()["output_order"]["goods_total"]["position"] =
|
|
||||||
value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_goodsTotalAliasEdit_editingFinished() {
|
|
||||||
this->settings.get_all_settings()["output_order"]["goods_total"]["name"] =
|
|
||||||
ui->goodsTotalAliasEdit->text().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsDialog::on_printHeaderCheckBox_stateChanged(int value) {
|
void SettingsDialog::on_printHeaderCheckBox_stateChanged(int value) {
|
||||||
this->settings.get_all_settings()["print_header"] = (value? true : false);
|
this->settings.get_all_settings()["print_header"] = (value? true : false);
|
||||||
}
|
}
|
||||||
@@ -112,7 +59,16 @@ void SettingsDialog::on_printTotalCheckBox_stateChanged(int value) {
|
|||||||
this->settings.get_all_settings()["print_total"] = (value? true : false);
|
this->settings.get_all_settings()["print_total"] = (value? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::on_buttonBox_accepted() { this->settings.flush(); }
|
void SettingsDialog::on_buttonBox_accepted() {
|
||||||
|
for (int i = 0; i < columns->size(); i ++) {
|
||||||
|
OutputColumn &column = columns->at(i);
|
||||||
|
std::string key = find_key_by_value(column_names, column.get_column_type());
|
||||||
|
settings.get_all_settings()["output_order"][key]["name"] = column.get_text().toStdString();
|
||||||
|
settings.get_all_settings()["output_order"][key]["position"] = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->settings.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsDialog::on_buttonBox_rejected() { this->close(); }
|
void SettingsDialog::on_buttonBox_rejected() { this->close(); }
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define SETTINGSDIALOG_H
|
#define SETTINGSDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <outputcolumn.h>
|
||||||
#include <settings/settings.h>
|
#include <settings/settings.h>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@@ -11,28 +12,13 @@ class settingsdialog;
|
|||||||
class SettingsDialog : public QDialog {
|
class SettingsDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
std::vector<OutputColumn> *columns;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SettingsDialog(QWidget *parent = nullptr);
|
explicit SettingsDialog(QWidget *parent = nullptr);
|
||||||
~SettingsDialog();
|
~SettingsDialog();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_goodsNamePositionSpin_valueChanged(int arg1);
|
|
||||||
void on_goodsNameAliasEdit_editingFinished();
|
|
||||||
|
|
||||||
void on_goodsPricePerUnitPositionSpin_valueChanged(int arg1);
|
|
||||||
void on_goodsPricePerUnitAliasEdit_editingFinished();
|
|
||||||
|
|
||||||
void on_goodsQuantityPositionSpin_valueChanged(int arg1);
|
|
||||||
void on_goodsQuantityAliasEdit_editingFinished();
|
|
||||||
|
|
||||||
void on_goodsNetWeightPositionSpin_valueChanged(int arg1);
|
|
||||||
void on_goodsNetWeightAliasEdit_editingFinished();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void on_goodsTotalPositionSpin_valueChanged(int arg1);
|
|
||||||
void on_goodsTotalAliasEdit_editingFinished();
|
|
||||||
|
|
||||||
void on_printTotalCheckBox_stateChanged(int arg1);
|
void on_printTotalCheckBox_stateChanged(int arg1);
|
||||||
void on_printHeaderCheckBox_stateChanged(int arg1);
|
void on_printHeaderCheckBox_stateChanged(int arg1);
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
<translation>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"/>
|
<location filename="../adjustpicturedialog.cpp" line="42"/>
|
||||||
<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>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"/>
|
<location filename="../adjustpicturedialog.cpp" line="44"/>
|
||||||
<source>No QR code</source>
|
<source>No QR code</source>
|
||||||
<translation>No QR code</translation>
|
<translation>No QR code</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -70,9 +70,8 @@
|
|||||||
<translation type="vanished">Store type</translation>
|
<translation type="vanished">Store type</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
|
||||||
<source>Parse</source>
|
<source>Parse</source>
|
||||||
<translation>Parse</translation>
|
<translation type="vanished">Parse</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Preferences</source>
|
<source>Preferences</source>
|
||||||
@@ -113,7 +112,7 @@
|
|||||||
<translation type="vanished">0000000000000000</translation>
|
<translation type="vanished">0000000000000000</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
<location filename="../scenes/mainwindow.ui" line="322"/>
|
||||||
<source>FN (Fiscal Number)</source>
|
<source>FN (Fiscal Number)</source>
|
||||||
<translatorcomment>FN = Фискальный Номер</translatorcomment>
|
<translatorcomment>FN = Фискальный Номер</translatorcomment>
|
||||||
<translation>FN (Fiscal Number)</translation>
|
<translation>FN (Fiscal Number)</translation>
|
||||||
@@ -133,93 +132,119 @@
|
|||||||
<translation type="obsolete">Back</translation>
|
<translation type="obsolete">Back</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||||
<source>Stop server</source>
|
<source>Stop server</source>
|
||||||
<translation>Stop server</translation>
|
<translation>Stop server</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="167"/>
|
|
||||||
<source>Choose image on your PC</source>
|
<source>Choose image on your PC</source>
|
||||||
<translation>Choose image on your PC</translation>
|
<translation type="vanished">Choose image on your PC</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
<location filename="../scenes/mainwindow.ui" line="118"/>
|
||||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
<location filename="../scenes/mainwindow.ui" line="173"/>
|
||||||
<source>or</source>
|
<source>or</source>
|
||||||
<translation>or</translation>
|
<translation>or</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="141"/>
|
|
||||||
<source>Use your phone as a QR code scanner</source>
|
<source>Use your phone as a QR code scanner</source>
|
||||||
<translation>Use your phone as a QR code scanner</translation>
|
<translation type="vanished">Use your phone as a QR code scanner</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
<location filename="../scenes/mainwindow.ui" line="295"/>
|
||||||
<source>FI (Fiscal Identifier)</source>
|
<source>FI (Fiscal Identifier)</source>
|
||||||
<translatorcomment>FI = Фискальный Признак</translatorcomment>
|
<translatorcomment>FI = Фискальный Признак</translatorcomment>
|
||||||
<translation>FI (Fiscal Identifier)</translation>
|
<translation>FI (Fiscal Identifier)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="273"/>
|
<location filename="../scenes/mainwindow.ui" line="329"/>
|
||||||
|
<source>Delete selected</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
<source>Add new check</source>
|
<source>Add new check</source>
|
||||||
<translation>Add new check</translation>
|
<translation type="vanished">Add new check</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
|
||||||
<source>Clear</source>
|
<source>Clear</source>
|
||||||
<translation>Clear</translation>
|
<translation type="vanished">Clear</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
<location filename="../scenes/mainwindow.ui" line="105"/>
|
||||||
<source>Date and time of purchase</source>
|
<source>Date and time of purchase</source>
|
||||||
<translation>Date and time of purchase</translation>
|
<translation>Date and time of purchase</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
<location filename="../scenes/mainwindow.ui" line="309"/>
|
||||||
<source>Operation type</source>
|
<source>Operation type</source>
|
||||||
<translation>Operation type</translation>
|
<translation>Operation type</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
<location filename="../scenes/mainwindow.ui" line="288"/>
|
||||||
<source>Parse an E-Mail</source>
|
<source>Parse an E-Mail</source>
|
||||||
<translation>Parse an E-Mail</translation>
|
<translation>Parse an E-Mail</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="214"/>
|
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||||
|
<source>Add to queue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="66"/>
|
||||||
<source>Funds income</source>
|
<source>Funds income</source>
|
||||||
<translatorcomment>Приход средств</translatorcomment>
|
<translatorcomment>Приход средств</translatorcomment>
|
||||||
<translation>Funds income</translation>
|
<translation>Funds income</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
<location filename="../scenes/mainwindow.ui" line="71"/>
|
||||||
<source>Funds return</source>
|
<source>Funds return</source>
|
||||||
<translatorcomment>Возврат средств</translatorcomment>
|
<translatorcomment>Возврат средств</translatorcomment>
|
||||||
<translation>Funds return</translation>
|
<translation>Funds return</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
<location filename="../scenes/mainwindow.ui" line="76"/>
|
||||||
<source>Funds spend</source>
|
<source>Funds spend</source>
|
||||||
<translatorcomment>Расход средств</translatorcomment>
|
<translatorcomment>Расход средств</translatorcomment>
|
||||||
<translation>Funds spend</translation>
|
<translation>Funds spend</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
<location filename="../scenes/mainwindow.ui" line="81"/>
|
||||||
<source>Spends return</source>
|
<source>Spends return</source>
|
||||||
<translatorcomment>Возврат расхода</translatorcomment>
|
<translatorcomment>Возврат расхода</translatorcomment>
|
||||||
<translation>Spends return</translation>
|
<translation>Spends return</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
<location filename="../scenes/mainwindow.ui" line="144"/>
|
||||||
<source>Checks to parse</source>
|
<source>Checks to parse</source>
|
||||||
<translation>Checks to parse</translation>
|
<translation>Checks to parse</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="108"/>
|
<location filename="../scenes/mainwindow.ui" line="160"/>
|
||||||
|
<source>Parse queue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="186"/>
|
||||||
|
<source>QR image</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="212"/>
|
||||||
|
<source>Scan QR using phone</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="225"/>
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<translation>Settings</translation>
|
<translation>Settings</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="128"/>
|
<location filename="../scenes/mainwindow.ui" line="238"/>
|
||||||
|
<source>Clear data</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="302"/>
|
||||||
<source>Total</source>
|
<source>Total</source>
|
||||||
<translation>Total</translation>
|
<translation>Total</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -228,75 +253,95 @@
|
|||||||
<translation type="vanished">checks parser</translation>
|
<translation type="vanished">checks parser</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="101"/>
|
<location filename="../mainwindow.cpp" line="106"/>
|
||||||
<source>QR code for binaryeye to connect</source>
|
<source>QR code for binaryeye to connect</source>
|
||||||
<translation>QR code for binaryeye to connect</translation>
|
<translation>QR code for binaryeye to connect</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="102"/>
|
<location filename="../mainwindow.cpp" line="107"/>
|
||||||
<source>I've scanned</source>
|
<source>I've scanned</source>
|
||||||
<translation>I've scanned</translation>
|
<translation>I've scanned</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="108"/>
|
<location filename="../mainwindow.cpp" line="113"/>
|
||||||
<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't lucky, please, contact the developer.</source>
|
<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't lucky, please, contact the developer.</source>
|
||||||
<translation>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.</translation>
|
<translation>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.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="110"/>
|
<location filename="../mainwindow.cpp" line="115"/>
|
||||||
<source>Could not start http server.</source>
|
<source>Could not start http server.</source>
|
||||||
<translation>Could not start http server.</translation>
|
<translation>Could not start http server.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="154"/>
|
<location filename="../mainwindow.cpp" line="138"/>
|
||||||
|
<source>Images (*.jpg *.jpeg *.png)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="144"/>
|
||||||
<source>Selected image: </source>
|
<source>Selected image: </source>
|
||||||
<translation>Selected image: </translation>
|
<translation>Selected image: </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="187"/>
|
|
||||||
<source>This feature is under development. Wait it to appear in next updates.</source>
|
<source>This feature is under development. Wait it to appear in next updates.</source>
|
||||||
<translation>This feature is under development. Wait for it to appear in next updates.</translation>
|
<translation type="vanished">This feature is under development. Wait for it to appear in next updates.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="189"/>
|
|
||||||
<source>Under development</source>
|
<source>Under development</source>
|
||||||
<translation>Under development</translation>
|
<translation type="vanished">Under development</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="159"/>
|
||||||
|
<source>E-Mail files (*.eml)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="170"/>
|
||||||
|
<source>QR code in this E-Mail was not found. If you are sure that the e-mail you supplied has qr code, please, contact the developer and send him the .eml file.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="172"/>
|
||||||
|
<source>QR code was not found in E-Mail</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="186"/>
|
||||||
<source>Please, add check(s) to parse</source>
|
<source>Please, add check(s) to parse</source>
|
||||||
<translation type="vanished">Please, add check(s) to parse</translation>
|
<translation>Please, add check(s) to parse</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="188"/>
|
||||||
<source>No checks to parse</source>
|
<source>No checks to parse</source>
|
||||||
<translation type="vanished">No checks to parse</translation>
|
<translation>No checks to parse</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="287"/>
|
<location filename="../mainwindow.cpp" line="255"/>
|
||||||
<source>Captcha was not solved correctly!</source>
|
<source>Captcha was not solved correctly!</source>
|
||||||
<translation>Captcha was not solved correctly!</translation>
|
<translation>Captcha was not solved correctly!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="289"/>
|
<location filename="../mainwindow.cpp" line="257"/>
|
||||||
<source>Captcha is incorrect</source>
|
<source>Captcha is incorrect</source>
|
||||||
<translation>Captcha is incorrect</translation>
|
<translation>Captcha is incorrect</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="294"/>
|
<location filename="../mainwindow.cpp" line="261"/>
|
||||||
<source>Internal server error. Please, try again later.</source>
|
<source>Internal server error. Please, try again later.</source>
|
||||||
<translation>Internal server error. Please, try again later.</translation>
|
<translation>Internal server error. Please, try again later.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="296"/>
|
<location filename="../mainwindow.cpp" line="263"/>
|
||||||
<source>Internal server error</source>
|
<source>Internal server error</source>
|
||||||
<translation>Internal server error</translation>
|
<translation>Internal server error</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="301"/>
|
<location filename="../mainwindow.cpp" line="267"/>
|
||||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||||
<translation>Check not found. Please, ensure correctness of entered data.</translation>
|
<translation>Check not found. Please, ensure correctness of entered data.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="303"/>
|
<location filename="../mainwindow.cpp" line="269"/>
|
||||||
<source>Check was not found</source>
|
<source>Check was not found</source>
|
||||||
<translation>Check was not found</translation>
|
<translation>Check was not found</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -309,14 +354,12 @@
|
|||||||
<translation type="vanished">Error in parsing</translation>
|
<translation type="vanished">Error in parsing</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="147"/>
|
|
||||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
<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>
|
<translation type="vanished">Please, select a picture where QR code that contains info about check is present</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="149"/>
|
|
||||||
<source>Picture was not selected</source>
|
<source>Picture was not selected</source>
|
||||||
<translation>Picture was not selected</translation>
|
<translation type="vanished">Picture was not selected</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Please, select a picture to scan</source>
|
<source>Please, select a picture to scan</source>
|
||||||
@@ -532,43 +575,33 @@
|
|||||||
<translation>Choose</translation>
|
<translation>Choose</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
<location filename="../scenes/outputdialog.ui" line="76"/>
|
||||||
<source>Print header</source>
|
<source>Print header</source>
|
||||||
<translation>Print header</translation>
|
<translation>Print header</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="24"/>
|
|
||||||
<source>Date</source>
|
<source>Date</source>
|
||||||
<translation>Date</translation>
|
<translation type="vanished">Date</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="25"/>
|
|
||||||
<source>Goods name</source>
|
<source>Goods name</source>
|
||||||
<translation>Goods name</translation>
|
<translation type="vanished">Goods name</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Goods price</source>
|
<source>Goods price</source>
|
||||||
<translation type="vanished">Goods price</translation>
|
<translation type="vanished">Goods price</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="26"/>
|
|
||||||
<source>Goods price per unit</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../outputdialog.cpp" line="27"/>
|
|
||||||
<source>Goods quantity</source>
|
<source>Goods quantity</source>
|
||||||
<translation>Goods quantity</translation>
|
<translation type="vanished">Goods quantity</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="28"/>
|
|
||||||
<source>Goods net weight</source>
|
<source>Goods net weight</source>
|
||||||
<translation>Goods net weight</translation>
|
<translation type="vanished">Goods net weight</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="29"/>
|
|
||||||
<source>Goods total</source>
|
<source>Goods total</source>
|
||||||
<translation>Goods total</translation>
|
<translation type="vanished">Goods total</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>position</source>
|
<source>position</source>
|
||||||
@@ -627,11 +660,16 @@
|
|||||||
<source>Print total</source>
|
<source>Print total</source>
|
||||||
<translation>Print total</translation>
|
<translation>Print total</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../outputdialog.cpp" line="37"/>
|
||||||
|
<source>Кто здесь?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../main.cpp" line="64"/>
|
<location filename="../main.cpp" line="60"/>
|
||||||
<source>Using locale: </source>
|
<source>Using locale: </source>
|
||||||
<translation>Using locale: </translation>
|
<translation>Using locale: </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -639,12 +677,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>SettingsDialog</name>
|
<name>SettingsDialog</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settingsdialog.cpp" line="133"/>
|
<location filename="../settingsdialog.cpp" line="24"/>
|
||||||
|
<source>Кто здесь?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settingsdialog.cpp" line="89"/>
|
||||||
<source>You need to restart program to apply language changes</source>
|
<source>You need to restart program to apply language changes</source>
|
||||||
<translation>You need to restart program to apply language changes</translation>
|
<translation>You need to restart program to apply language changes</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settingsdialog.cpp" line="135"/>
|
<location filename="../settingsdialog.cpp" line="91"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation>Restart required</translation>
|
<translation>Restart required</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -675,41 +718,37 @@
|
|||||||
<translation>Dialog</translation>
|
<translation>Dialog</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
|
||||||
<source>Goods name position</source>
|
<source>Goods name position</source>
|
||||||
<translation>Goods name position</translation>
|
<translation type="vanished">Goods name position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
|
||||||
<source>Goods price per unit alias</source>
|
<source>Goods price per unit alias</source>
|
||||||
<translation>Goods price per unit alias</translation>
|
<translation type="vanished">Goods price per unit alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="124"/>
|
|
||||||
<source>Date name position</source>
|
<source>Date name position</source>
|
||||||
<translation>Date name position</translation>
|
<translation type="vanished">Date name position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
<location filename="../scenes/settingsdialog.ui" line="85"/>
|
||||||
<source>Language</source>
|
<source>Language</source>
|
||||||
<translation>Language</translation>
|
<translation>Language</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="196"/>
|
|
||||||
<source>Date name alias</source>
|
<source>Date name alias</source>
|
||||||
<translation>Date name alias</translation>
|
<translation type="vanished">Date name alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>TextLabel</source>
|
<source>TextLabel</source>
|
||||||
<translation type="vanished">Language</translation>
|
<translation type="vanished">Language</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="38"/>
|
<location filename="../scenes/settingsdialog.ui" line="58"/>
|
||||||
<source>en_US</source>
|
<source>en_US</source>
|
||||||
<translation>en_US</translation>
|
<translation>en_US</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
<location filename="../scenes/settingsdialog.ui" line="63"/>
|
||||||
<source>ru_RU</source>
|
<source>ru_RU</source>
|
||||||
<translation>ru_RU</translation>
|
<translation>ru_RU</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -718,33 +757,29 @@
|
|||||||
<translation type="vanished">Choose</translation>
|
<translation type="vanished">Choose</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
<location filename="../scenes/settingsdialog.ui" line="71"/>
|
||||||
<source>Print header</source>
|
<source>Print header</source>
|
||||||
<translation>Print header</translation>
|
<translation>Print header</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
|
||||||
<source>Goods net weight alias</source>
|
<source>Goods net weight alias</source>
|
||||||
<translation>Goods net weight alias</translation>
|
<translation type="vanished">Goods net weight alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Stores modules url</source>
|
<source>Stores modules url</source>
|
||||||
<translation type="vanished">Stores modules url</translation>
|
<translation type="vanished">Stores modules url</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
|
||||||
<source>Goods total alias</source>
|
<source>Goods total alias</source>
|
||||||
<translation>Goods total alias</translation>
|
<translation type="vanished">Goods total alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
|
||||||
<source>Goods name alias</source>
|
<source>Goods name alias</source>
|
||||||
<translation>Goods name alias</translation>
|
<translation type="vanished">Goods name alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
|
||||||
<source>Goods quantity alias</source>
|
<source>Goods quantity alias</source>
|
||||||
<translation>Goods quantity alias</translation>
|
<translation type="vanished">Goods quantity alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Stores modules directory</source>
|
<source>Stores modules directory</source>
|
||||||
@@ -755,31 +790,27 @@
|
|||||||
<translation type="vanished">OFD modules directory</translation>
|
<translation type="vanished">OFD modules directory</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
|
||||||
<source>Goods price per unit position</source>
|
<source>Goods price per unit position</source>
|
||||||
<translation>Goods price per unit position</translation>
|
<translation type="vanished">Goods price per unit position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
|
||||||
<source>Goods net weight position</source>
|
<source>Goods net weight position</source>
|
||||||
<translation>Goods net weight position</translation>
|
<translation type="vanished">Goods net weight position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>OFD modules url</source>
|
<source>OFD modules url</source>
|
||||||
<translation type="vanished">OFD modules url</translation>
|
<translation type="vanished">OFD modules url</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
|
||||||
<source>Goods total position</source>
|
<source>Goods total position</source>
|
||||||
<translation>Goods total position</translation>
|
<translation type="vanished">Goods total position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
|
||||||
<source>Goods quantity position</source>
|
<source>Goods quantity position</source>
|
||||||
<translation>Goods quantity position</translation>
|
<translation type="vanished">Goods quantity position</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
<location filename="../scenes/settingsdialog.ui" line="50"/>
|
||||||
<source>Print total</source>
|
<source>Print total</source>
|
||||||
<translation>Print total</translation>
|
<translation>Print total</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
<translation>Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
|
<translation>Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../adjustpicturedialog.cpp" line="39"/>
|
<location filename="../adjustpicturedialog.cpp" line="42"/>
|
||||||
<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>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
|
<translation>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../adjustpicturedialog.cpp" line="41"/>
|
<location filename="../adjustpicturedialog.cpp" line="44"/>
|
||||||
<source>No QR code</source>
|
<source>No QR code</source>
|
||||||
<translation>QR код не найден</translation>
|
<translation>QR код не найден</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -70,9 +70,8 @@
|
|||||||
<translation type="vanished">Магазин</translation>
|
<translation type="vanished">Магазин</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
|
||||||
<source>Parse</source>
|
<source>Parse</source>
|
||||||
<translation>Парсить</translation>
|
<translation type="vanished">Парсить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Preferences</source>
|
<source>Preferences</source>
|
||||||
@@ -113,7 +112,7 @@
|
|||||||
<translation type="vanished">0000000000000000</translation>
|
<translation type="vanished">0000000000000000</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
<location filename="../scenes/mainwindow.ui" line="322"/>
|
||||||
<source>FN (Fiscal Number)</source>
|
<source>FN (Fiscal Number)</source>
|
||||||
<translatorcomment>Фискальный Норма</translatorcomment>
|
<translatorcomment>Фискальный Норма</translatorcomment>
|
||||||
<translation>ФН</translation>
|
<translation>ФН</translation>
|
||||||
@@ -133,89 +132,107 @@
|
|||||||
<translation type="obsolete">Назад</translation>
|
<translation type="obsolete">Назад</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||||
<source>Stop server</source>
|
<source>Stop server</source>
|
||||||
<translation>Остановить сервер</translation>
|
<translation>Остановить сервер</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="167"/>
|
|
||||||
<source>Choose image on your PC</source>
|
<source>Choose image on your PC</source>
|
||||||
<translation>Выбрать изображение на компьютере</translation>
|
<translation type="vanished">Выбрать изображение на компьютере</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
<location filename="../scenes/mainwindow.ui" line="118"/>
|
||||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
<location filename="../scenes/mainwindow.ui" line="173"/>
|
||||||
<source>or</source>
|
<source>or</source>
|
||||||
<translation>или</translation>
|
<translation>или</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="141"/>
|
|
||||||
<source>Use your phone as a QR code scanner</source>
|
<source>Use your phone as a QR code scanner</source>
|
||||||
<translation>Использовать телефон как сканнер QR</translation>
|
<translation type="vanished">Использовать телефон как сканнер QR</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
<location filename="../scenes/mainwindow.ui" line="295"/>
|
||||||
<source>FI (Fiscal Identifier)</source>
|
<source>FI (Fiscal Identifier)</source>
|
||||||
<translatorcomment>Фискальный Признак</translatorcomment>
|
<translatorcomment>Фискальный Признак</translatorcomment>
|
||||||
<translation>ФП</translation>
|
<translation>ФП</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="273"/>
|
<location filename="../scenes/mainwindow.ui" line="329"/>
|
||||||
<source>Add new check</source>
|
<source>Delete selected</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
<location filename="../scenes/mainwindow.ui" line="105"/>
|
||||||
<source>Clear</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
|
||||||
<source>Date and time of purchase</source>
|
<source>Date and time of purchase</source>
|
||||||
<translation>Дата и время покупки</translation>
|
<translation>Дата и время покупки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
<location filename="../scenes/mainwindow.ui" line="309"/>
|
||||||
<source>Operation type</source>
|
<source>Operation type</source>
|
||||||
<translation>Тип операции</translation>
|
<translation>Тип операции</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
<location filename="../scenes/mainwindow.ui" line="288"/>
|
||||||
<source>Parse an E-Mail</source>
|
<source>Parse an E-Mail</source>
|
||||||
<translation>Парсить E-Mail</translation>
|
<translation>Парсить E-Mail</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="214"/>
|
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||||
|
<source>Add to queue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="66"/>
|
||||||
<source>Funds income</source>
|
<source>Funds income</source>
|
||||||
<translation>Приход средств</translation>
|
<translation>Приход средств</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
<location filename="../scenes/mainwindow.ui" line="71"/>
|
||||||
<source>Funds return</source>
|
<source>Funds return</source>
|
||||||
<translation>Возврат средств</translation>
|
<translation>Возврат средств</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
<location filename="../scenes/mainwindow.ui" line="76"/>
|
||||||
<source>Funds spend</source>
|
<source>Funds spend</source>
|
||||||
<translation>Расход средств</translation>
|
<translation>Расход средств</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
<location filename="../scenes/mainwindow.ui" line="81"/>
|
||||||
<source>Spends return</source>
|
<source>Spends return</source>
|
||||||
<translation>Возврат расхода</translation>
|
<translation>Возврат расхода</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
<location filename="../scenes/mainwindow.ui" line="144"/>
|
||||||
<source>Checks to parse</source>
|
<source>Checks to parse</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="108"/>
|
<location filename="../scenes/mainwindow.ui" line="160"/>
|
||||||
|
<source>Parse queue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="186"/>
|
||||||
|
<source>QR image</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="212"/>
|
||||||
|
<source>Scan QR using phone</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="225"/>
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<translation>Настройки</translation>
|
<translation>Настройки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/mainwindow.ui" line="128"/>
|
<location filename="../scenes/mainwindow.ui" line="238"/>
|
||||||
|
<source>Clear data</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../scenes/mainwindow.ui" line="302"/>
|
||||||
<source>Total</source>
|
<source>Total</source>
|
||||||
<translation>Итого</translation>
|
<translation>Итого</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -224,67 +241,87 @@
|
|||||||
<translation type="vanished">Парсер чеков</translation>
|
<translation type="vanished">Парсер чеков</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="101"/>
|
<location filename="../mainwindow.cpp" line="106"/>
|
||||||
<source>QR code for binaryeye to connect</source>
|
<source>QR code for binaryeye to connect</source>
|
||||||
<translation>QR код для подключения BinaryEye</translation>
|
<translation>QR код для подключения BinaryEye</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="102"/>
|
<location filename="../mainwindow.cpp" line="107"/>
|
||||||
<source>I've scanned</source>
|
<source>I've scanned</source>
|
||||||
<translation>Просканировал</translation>
|
<translation>Просканировал</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="108"/>
|
<location filename="../mainwindow.cpp" line="113"/>
|
||||||
<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't lucky, please, contact the developer.</source>
|
<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't lucky, please, contact the developer.</source>
|
||||||
<translation>Не смог поднять HTTP сервер. 10 раз подряд случайно выбранный порт был занят. Либо Вам следует бежать за лоттерейным билетом, или в программе баг. Если лотерейный билет не был выигрышным, пожалуйста, сообщите разработчику.</translation>
|
<translation>Не смог поднять HTTP сервер. 10 раз подряд случайно выбранный порт был занят. Либо Вам следует бежать за лоттерейным билетом, или в программе баг. Если лотерейный билет не был выигрышным, пожалуйста, сообщите разработчику.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="110"/>
|
<location filename="../mainwindow.cpp" line="115"/>
|
||||||
<source>Could not start http server.</source>
|
<source>Could not start http server.</source>
|
||||||
<translation>Не получилось запустить HTTP сервер.</translation>
|
<translation>Не получилось запустить HTTP сервер.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="154"/>
|
<location filename="../mainwindow.cpp" line="138"/>
|
||||||
|
<source>Images (*.jpg *.jpeg *.png)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="144"/>
|
||||||
<source>Selected image: </source>
|
<source>Selected image: </source>
|
||||||
<translation>Выбранное изображение: </translation>
|
<translation>Выбранное изображение: </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="187"/>
|
<location filename="../mainwindow.cpp" line="159"/>
|
||||||
<source>This feature is under development. Wait it to appear in next updates.</source>
|
<source>E-Mail files (*.eml)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="189"/>
|
<location filename="../mainwindow.cpp" line="170"/>
|
||||||
<source>Under development</source>
|
<source>QR code in this E-Mail was not found. If you are sure that the e-mail you supplied has qr code, please, contact the developer and send him the .eml file.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="287"/>
|
<location filename="../mainwindow.cpp" line="172"/>
|
||||||
|
<source>QR code was not found in E-Mail</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="186"/>
|
||||||
|
<source>Please, add check(s) to parse</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="188"/>
|
||||||
|
<source>No checks to parse</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="255"/>
|
||||||
<source>Captcha was not solved correctly!</source>
|
<source>Captcha was not solved correctly!</source>
|
||||||
<translation>Капча была решена неверно!</translation>
|
<translation>Капча была решена неверно!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="289"/>
|
<location filename="../mainwindow.cpp" line="257"/>
|
||||||
<source>Captcha is incorrect</source>
|
<source>Captcha is incorrect</source>
|
||||||
<translation>Капча введена неверно</translation>
|
<translation>Капча введена неверно</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="294"/>
|
<location filename="../mainwindow.cpp" line="261"/>
|
||||||
<source>Internal server error. Please, try again later.</source>
|
<source>Internal server error. Please, try again later.</source>
|
||||||
<translation>Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
|
<translation>Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="296"/>
|
<location filename="../mainwindow.cpp" line="263"/>
|
||||||
<source>Internal server error</source>
|
<source>Internal server error</source>
|
||||||
<translation>Внутренняя ошибка сервера</translation>
|
<translation>Внутренняя ошибка сервера</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="301"/>
|
<location filename="../mainwindow.cpp" line="267"/>
|
||||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||||
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
|
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="303"/>
|
<location filename="../mainwindow.cpp" line="269"/>
|
||||||
<source>Check was not found</source>
|
<source>Check was not found</source>
|
||||||
<translation>Чек не найден</translation>
|
<translation>Чек не найден</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -297,14 +334,12 @@
|
|||||||
<translation type="vanished">Ошибка в парсинге</translation>
|
<translation type="vanished">Ошибка в парсинге</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="147"/>
|
|
||||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||||
<translation>Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке</translation>
|
<translation type="vanished">Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="149"/>
|
|
||||||
<source>Picture was not selected</source>
|
<source>Picture was not selected</source>
|
||||||
<translation>Изображение не было выбрано</translation>
|
<translation type="vanished">Изображение не было выбрано</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Please, select a picture to scan</source>
|
<source>Please, select a picture to scan</source>
|
||||||
@@ -520,38 +555,29 @@
|
|||||||
<translation>Выбрать</translation>
|
<translation>Выбрать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
<location filename="../scenes/outputdialog.ui" line="76"/>
|
||||||
<source>Print header</source>
|
<source>Print header</source>
|
||||||
<translation>Печатать заголовок</translation>
|
<translation>Печатать заголовок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="25"/>
|
|
||||||
<source>Goods name</source>
|
<source>Goods name</source>
|
||||||
<translation>Имя товара</translation>
|
<translation type="vanished">Имя товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Goods price</source>
|
<source>Goods price</source>
|
||||||
<translation type="vanished">Цена товара</translation>
|
<translation type="vanished">Цена товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="26"/>
|
|
||||||
<source>Goods price per unit</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../outputdialog.cpp" line="27"/>
|
|
||||||
<source>Goods quantity</source>
|
<source>Goods quantity</source>
|
||||||
<translation>Количество товара</translation>
|
<translation type="vanished">Количество товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="28"/>
|
|
||||||
<source>Goods net weight</source>
|
<source>Goods net weight</source>
|
||||||
<translation>Масса нетто товара</translation>
|
<translation type="vanished">Масса нетто товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="29"/>
|
|
||||||
<source>Goods total</source>
|
<source>Goods total</source>
|
||||||
<translation>Всего за товар</translation>
|
<translation type="vanished">Всего за товар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>position</source>
|
<source>position</source>
|
||||||
@@ -611,15 +637,15 @@
|
|||||||
<translation>Печатать Итого</translation>
|
<translation>Печатать Итого</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../outputdialog.cpp" line="24"/>
|
<location filename="../outputdialog.cpp" line="37"/>
|
||||||
<source>Date</source>
|
<source>Кто здесь?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../main.cpp" line="64"/>
|
<location filename="../main.cpp" line="60"/>
|
||||||
<source>Using locale: </source>
|
<source>Using locale: </source>
|
||||||
<translation>Использую локаль: </translation>
|
<translation>Использую локаль: </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -627,12 +653,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>SettingsDialog</name>
|
<name>SettingsDialog</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settingsdialog.cpp" line="133"/>
|
<location filename="../settingsdialog.cpp" line="24"/>
|
||||||
|
<source>Кто здесь?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settingsdialog.cpp" line="89"/>
|
||||||
<source>You need to restart program to apply language changes</source>
|
<source>You need to restart program to apply language changes</source>
|
||||||
<translation>Требуется перезагрузить программу, чтобы применить изменения языка</translation>
|
<translation>Требуется перезагрузить программу, чтобы применить изменения языка</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settingsdialog.cpp" line="135"/>
|
<location filename="../settingsdialog.cpp" line="91"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation>Требуется перезагрузка</translation>
|
<translation>Требуется перезагрузка</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -663,41 +694,29 @@
|
|||||||
<translation>Диалог</translation>
|
<translation>Диалог</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
|
||||||
<source>Goods name position</source>
|
<source>Goods name position</source>
|
||||||
<translation>Позиция имени товара</translation>
|
<translation type="vanished">Позиция имени товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
|
||||||
<source>Goods price per unit alias</source>
|
<source>Goods price per unit alias</source>
|
||||||
<translation>Алиас цены товара</translation>
|
<translation type="vanished">Алиас цены товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="124"/>
|
<location filename="../scenes/settingsdialog.ui" line="85"/>
|
||||||
<source>Date name position</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
|
||||||
<source>Language</source>
|
<source>Language</source>
|
||||||
<translation>Язык</translation>
|
<translation>Язык</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../scenes/settingsdialog.ui" line="196"/>
|
|
||||||
<source>Date name alias</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>TextLabel</source>
|
<source>TextLabel</source>
|
||||||
<translation type="vanished">Язык</translation>
|
<translation type="vanished">Язык</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="38"/>
|
<location filename="../scenes/settingsdialog.ui" line="58"/>
|
||||||
<source>en_US</source>
|
<source>en_US</source>
|
||||||
<translation>en_US</translation>
|
<translation>en_US</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
<location filename="../scenes/settingsdialog.ui" line="63"/>
|
||||||
<source>ru_RU</source>
|
<source>ru_RU</source>
|
||||||
<translation>ru_RU</translation>
|
<translation>ru_RU</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -706,33 +725,29 @@
|
|||||||
<translation type="vanished">Выбрать</translation>
|
<translation type="vanished">Выбрать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
<location filename="../scenes/settingsdialog.ui" line="71"/>
|
||||||
<source>Print header</source>
|
<source>Print header</source>
|
||||||
<translation>Печатать заголовок</translation>
|
<translation>Печатать заголовок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
|
||||||
<source>Goods net weight alias</source>
|
<source>Goods net weight alias</source>
|
||||||
<translation>Алиас массы нетто товара</translation>
|
<translation type="vanished">Алиас массы нетто товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Stores modules url</source>
|
<source>Stores modules url</source>
|
||||||
<translation type="vanished">URL модулей магазина</translation>
|
<translation type="vanished">URL модулей магазина</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
|
||||||
<source>Goods total alias</source>
|
<source>Goods total alias</source>
|
||||||
<translation>Алиас всего за продукт</translation>
|
<translation type="vanished">Алиас всего за продукт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
|
||||||
<source>Goods name alias</source>
|
<source>Goods name alias</source>
|
||||||
<translation>Алиас имени товара</translation>
|
<translation type="vanished">Алиас имени товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
|
||||||
<source>Goods quantity alias</source>
|
<source>Goods quantity alias</source>
|
||||||
<translation>Алиас количества товара</translation>
|
<translation type="vanished">Алиас количества товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Stores modules directory</source>
|
<source>Stores modules directory</source>
|
||||||
@@ -743,31 +758,27 @@
|
|||||||
<translation type="vanished">Директория модулей ОФД</translation>
|
<translation type="vanished">Директория модулей ОФД</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
|
||||||
<source>Goods price per unit position</source>
|
<source>Goods price per unit position</source>
|
||||||
<translation>Позиция центы товара</translation>
|
<translation type="vanished">Позиция центы товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
|
||||||
<source>Goods net weight position</source>
|
<source>Goods net weight position</source>
|
||||||
<translation>Позиция массы нетто товара</translation>
|
<translation type="vanished">Позиция массы нетто товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>OFD modules url</source>
|
<source>OFD modules url</source>
|
||||||
<translation type="vanished">URL модулей ОФД</translation>
|
<translation type="vanished">URL модулей ОФД</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
|
||||||
<source>Goods total position</source>
|
<source>Goods total position</source>
|
||||||
<translation>Позиция всего за товар</translation>
|
<translation type="vanished">Позиция всего за товар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
|
||||||
<source>Goods quantity position</source>
|
<source>Goods quantity position</source>
|
||||||
<translation>Позиция количества товара</translation>
|
<translation type="vanished">Позиция количества товара</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
<location filename="../scenes/settingsdialog.ui" line="50"/>
|
||||||
<source>Print total</source>
|
<source>Print total</source>
|
||||||
<translation>Печатать Итого</translation>
|
<translation>Печатать Итого</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
110
utils/utils.cpp
110
utils/utils.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
#include "output/output_options.h"
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
@@ -24,6 +25,9 @@
|
|||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <net/net.h>
|
#include <net/net.h>
|
||||||
#include <settings/settings.h>
|
#include <settings/settings.h>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
std::string get_local_ip_address() {
|
std::string get_local_ip_address() {
|
||||||
@@ -41,6 +45,7 @@ std::string get_local_ip_address() {
|
|||||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
std::string value(addressBuffer);
|
std::string value(addressBuffer);
|
||||||
|
//TODO: better way to determine local IP address
|
||||||
if (!strncmp(value.c_str(), "192.168", 7)) {
|
if (!strncmp(value.c_str(), "192.168", 7)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -67,6 +72,26 @@ std::string get_path_relative_to_home(std::string path) {
|
|||||||
return std::string(std::getenv("HOME")) + "/" + path;
|
return std::string(std::getenv("HOME")) + "/" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_application_home_path() {
|
||||||
|
return get_path_relative_to_home(".local/share/checks_parser");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::string> get_params_from_string(std::string parametersString) {
|
||||||
|
parametersString = boost::regex_replace(parametersString, boost::regex("%26"), "&");
|
||||||
|
parametersString = boost::regex_replace(parametersString, boost::regex("%3[Dd]"), "=");
|
||||||
|
|
||||||
|
std::vector<std::string> parameters = split(parametersString, "&");
|
||||||
|
|
||||||
|
std::map<std::string, std::string> paramsMap;
|
||||||
|
|
||||||
|
for (auto ¶meter : parameters) {
|
||||||
|
std::vector<std::string> values = split(parameter, "=");
|
||||||
|
paramsMap.insert(std::pair<std::string, std::string> (values[0], values[1]));
|
||||||
|
}
|
||||||
|
return paramsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
|
bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
|
||||||
for (const T& element : vector) {
|
for (const T& element : vector) {
|
||||||
@@ -80,11 +105,31 @@ bool areAllSizesEqual(const std::vector<T>& v1, const std::vector<T>& v2,
|
|||||||
return (v1.size() == v2.size() && v2.size() == v3.size() && v3.size() == v4.size());
|
return (v1.size() == v2.size() && v2.size() == v3.size() && v3.size() == v4.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template<typename K, typename V>
|
||||||
|
// K find_key_by_value(std::map<K, V> &m, V value) {
|
||||||
|
// for (auto& entry : m) {
|
||||||
|
// if (value == entry.second) {
|
||||||
|
// return entry.first;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return K();
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::string find_key_by_value(const std::map<std::string, ColumnType> &m, ColumnType value) {
|
||||||
|
for (auto& entry : m) {
|
||||||
|
if (value == entry.second) {
|
||||||
|
return entry.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
//ужас
|
//ужас
|
||||||
template bool vector_contains_element<std::string>(const std::vector<std::string>& vector, const std::string& to_find);
|
template bool vector_contains_element<std::string>(const std::vector<std::string>& vector, const std::string& to_find);
|
||||||
template bool areAllSizesEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2,
|
template bool areAllSizesEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2,
|
||||||
const std::vector<std::string>& v3, const std::vector<std::string>& v4);
|
const std::vector<std::string>& v3, const std::vector<std::string>& v4);
|
||||||
|
// template std::string find_key_by_value(std::map<std::string, ColumnType> &, ColumnType);
|
||||||
|
|
||||||
std::vector<std::string> split(std::string s, std::string delimiter) {
|
std::vector<std::string> split(std::string s, std::string delimiter) {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
@@ -152,33 +197,39 @@ std::wstring trim_html_response(std::wstring& check) {
|
|||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> find_in_html(std::string& html, std::string regex, std::string html_start, std::string html_end) {
|
std::vector<std::wstring> find_in_html(std::string& html, std::string regex) {
|
||||||
boost::regex searching_regex(regex);
|
boost::regex searching_regex(regex, boost::match_flag_type::match_single_line);
|
||||||
|
|
||||||
std::vector<std::wstring> parsed;
|
std::vector<std::wstring> parsed;
|
||||||
for (boost::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
|
for (boost::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
|
||||||
it != end; it++) {
|
it != end; it++) {
|
||||||
|
// std::wstring found_entry = from_utf8(it->str());
|
||||||
std::wstring found_entry = from_utf8(it->str());
|
parsed.push_back(from_utf8(it->str()));
|
||||||
std::cout << "Found: " << to_utf8(found_entry) << std::endl;
|
// std::cout << "Found: " << to_utf8(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::cout << "Extracted: " << to_utf8(extracted) << std::endl;
|
// std::cout << "Extracted: " << to_utf8(extracted) << std::endl;
|
||||||
parsed.push_back(extracted);
|
// parsed.push_back(extracted);
|
||||||
}
|
}
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> find_products_in_html(std::string html) {
|
std::vector<std::wstring> find_products_in_html(std::string html) {
|
||||||
return find_in_html(html, "<div class=\"ifw-col ifw-col-1 text-left\"><b>.{2,100}<\\/b><\\/div>", "<div class=\"ifw-col ifw-col-1 text-left\"><b>", "<\\/b><\\/div>");
|
boost::regex search_regex("(?<=\\n\\s{20}<div class=\"ifw-col ifw-col-1 text-left\">).{0,100}(?=(<\\/b>)?<\\/div>)");
|
||||||
|
boost::regex b_regex("(<b>)|(</b>)");
|
||||||
|
|
||||||
|
std::vector<std::wstring> parsed;
|
||||||
|
for (boost::sregex_iterator it{html.begin(), html.end(), search_regex}, end{};
|
||||||
|
it != end; it++) {
|
||||||
|
std::string found = it->str();
|
||||||
|
boost::erase_all_regex(found, b_regex);
|
||||||
|
found = boost::regex_replace(found, boost::regex(" "), "?");
|
||||||
|
parsed.push_back(from_utf8(found));
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> find_amounts_in_html(std::string html) {
|
std::vector<std::wstring> find_amounts_in_html(std::string html) {
|
||||||
std::vector<std::wstring> founds = find_in_html(html, "<div><span>\\d+(\\.|\\,)?\\d{0,3}<\\/span>", "<span>", "<\\/span>");
|
return find_in_html(html, "(?<=<div><span>)\\d+(\\.|\\,)?\\d{0,3}(?=<\\/span>)");
|
||||||
for (auto &found : founds) {
|
|
||||||
std::replace(found.begin(), found.end(), ',', '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return founds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> find_net_weights_in_names(std::vector<std::wstring> &names) {
|
std::vector<std::wstring> find_net_weights_in_names(std::vector<std::wstring> &names) {
|
||||||
@@ -205,12 +256,7 @@ std::vector<std::wstring> find_net_weights_in_names(std::vector<std::wstring> &n
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> find_prices_in_html(std::string html) {
|
std::vector<std::wstring> find_prices_in_html(std::string html) {
|
||||||
std::vector<std::wstring> founds = find_in_html(html, "X <\\/span><span>\\d+(\\.|,)\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
|
return find_in_html(html, "(?<=X <\\/span><span>)\\d+(\\.|,)\\d{2}(?=<\\/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> &net_weights, std::vector<std::wstring> &prices) {
|
void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::wstring> &amounts, std::vector<std::wstring> &net_weights, std::vector<std::wstring> &prices) {
|
||||||
@@ -272,8 +318,9 @@ Check parseOfdRuAnswer(std::string html) {
|
|||||||
Check c;
|
Check c;
|
||||||
|
|
||||||
for (int i = 0; i < products.size(); i ++) {
|
for (int i = 0; i < products.size(); i ++) {
|
||||||
std::cout << "Adding to check: ";
|
// std::cout << "Adding to check: ";
|
||||||
std::cout << to_utf8(products[i]) << " " << to_utf8(prices[i]) << " " << to_utf8(net_weights[i]) << " " << to_utf8(amounts[i]) << std::endl;
|
// std::cout << to_utf8(products[i]) << " " << to_utf8(prices[i]) << " " << to_utf8(net_weights[i]) << " " << to_utf8(amounts[i]) << std::endl;
|
||||||
|
std::replace(amounts[i].begin(), amounts[i].end(), from_utf8(",")[0], from_utf8(".")[0]);
|
||||||
Goods goods(to_utf8(products[i]), std::stod(prices[i]), to_utf8(net_weights[i]), std::stod(amounts[i]));
|
Goods goods(to_utf8(products[i]), std::stod(prices[i]), to_utf8(net_weights[i]), std::stod(amounts[i]));
|
||||||
c.add_goods(goods);
|
c.add_goods(goods);
|
||||||
}
|
}
|
||||||
@@ -310,14 +357,13 @@ void generate_qr_code(std::string data) {
|
|||||||
#endif // ifdef BUILD_OFD_BINARYEYE_SCAN
|
#endif // ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||||
|
|
||||||
#ifdef BUILD_EMAIL_MODE
|
#ifdef BUILD_EMAIL_MODE
|
||||||
std::vector<std::string> read_file(std::string path) {
|
std::string read_file(std::string &path) {
|
||||||
std::ifstream stream(path);
|
std::ifstream ifile(path, std::ios::in | std::ios::binary);
|
||||||
std::vector<std::string> lines;
|
const unsigned int size = std::filesystem::file_size(path);
|
||||||
std::string buffer;
|
std::string content(size, '\0');
|
||||||
while(getline(stream, buffer)) {
|
ifile.read(content.data(), size);
|
||||||
lines.push_back(buffer);
|
ifile.close();
|
||||||
}
|
return content;
|
||||||
stream.close();
|
|
||||||
return lines;
|
|
||||||
}
|
}
|
||||||
#endif // ifdef BUILD_EMAIL_MODE
|
#endif // ifdef BUILD_EMAIL_MODE
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,30 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#include "../check/check.h"
|
#include "../check/check.h"
|
||||||
|
#include "output/output_options.h"
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
std::string get_path_relative_to_home(std::string path);
|
std::string get_path_relative_to_home(std::string path);
|
||||||
|
std::string get_application_home_path();
|
||||||
|
|
||||||
|
std::map<std::string, std::string> get_params_from_string(std::string);
|
||||||
|
|
||||||
|
const std::map<std::string, ColumnType> column_names = {
|
||||||
|
{"date", ColumnType::date},
|
||||||
|
{"goods_name", ColumnType::goods_name},
|
||||||
|
{"goods_price_per_unit", ColumnType::goods_price_per_unit},
|
||||||
|
{"goods_quantity", ColumnType::goods_quantity},
|
||||||
|
{"goods_net_weight", ColumnType::goods_net_weight},
|
||||||
|
{"goods_total", ColumnType::goods_total}
|
||||||
|
};
|
||||||
|
|
||||||
|
// template <typename K, typename V>
|
||||||
|
// K find_key_by_value(std::map<K, V> &m, V value);
|
||||||
|
std::string find_key_by_value(const std::map<std::string, ColumnType> &m, ColumnType value);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool vector_contains_element(const std::vector<T> &vector, const T &to_find);
|
bool vector_contains_element(const std::vector<T> &vector, const T &to_find);
|
||||||
@@ -32,6 +50,6 @@ std::string get_local_ip_address();
|
|||||||
|
|
||||||
void fetch_and_download_modules();
|
void fetch_and_download_modules();
|
||||||
#ifdef BUILD_EMAIL_MODE
|
#ifdef BUILD_EMAIL_MODE
|
||||||
std::vector<std::string> read_file(std::string path);
|
std::string read_file(std::string &path);
|
||||||
#endif
|
#endif
|
||||||
#endif // UTILS_H
|
#endif // UTILS_H
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
#include "checklistviewwidget.h"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <check/check.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
CheckListViewWidget::CheckListViewWidget(QWidget *parent, Check check) : QWidget(parent), check(check) {
|
|
||||||
mw = (MainWindow*) parent;
|
|
||||||
QHBoxLayout *layout = new QHBoxLayout;
|
|
||||||
|
|
||||||
QLabel *date_label = new QLabel(QString::fromStdString(check.get_date()));
|
|
||||||
QLabel *summ_label = new QLabel(QString::number(check.get_total()));
|
|
||||||
|
|
||||||
QPushButton *deleteButton = new QPushButton(tr("Delete"));
|
|
||||||
|
|
||||||
deleteButton->connect(deleteButton, &QPushButton::clicked, this, &CheckListViewWidget::delete_button_pressed);
|
|
||||||
|
|
||||||
layout->addWidget(date_label);
|
|
||||||
layout->addWidget(summ_label);
|
|
||||||
layout->addSpacing(10);
|
|
||||||
layout->addWidget(deleteButton);
|
|
||||||
|
|
||||||
setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Check &CheckListViewWidget::get_check(){
|
|
||||||
return check;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckListViewWidget::delete_button_pressed() {
|
|
||||||
emit mw->deleteCheckFromList(this->check);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef CHECKLISTVIEWWIDGET_H
|
|
||||||
#define CHECKLISTVIEWWIDGET_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <mainwindow.h>
|
|
||||||
|
|
||||||
#include <check/check.h>
|
|
||||||
|
|
||||||
class CheckListViewWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Check check;
|
|
||||||
MainWindow* mw;
|
|
||||||
public:
|
|
||||||
explicit CheckListViewWidget(QWidget *parent = nullptr, Check check = Check());
|
|
||||||
|
|
||||||
Check &get_check();
|
|
||||||
void delete_button_pressed();
|
|
||||||
signals:
|
|
||||||
Check deleteButtonPressed();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CHECKLISTVIEWWIDGET_H
|
|
||||||
229
widgets/checkqueuetablemodel.cpp
Normal file
229
widgets/checkqueuetablemodel.cpp
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
#include "checkqueuetablemodel.h"
|
||||||
|
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QVector>
|
||||||
|
CheckQueueTableModel::CheckQueueTableModel(std::vector<Check> *checks, QObject *parent)
|
||||||
|
: checks(checks), QAbstractTableModel{parent}
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CheckQueueTableModel::rowCount(const QModelIndex &parent) const { return checks->size(); }
|
||||||
|
int CheckQueueTableModel::columnCount(const QModelIndex &parent) const { return 2; }
|
||||||
|
|
||||||
|
QVariant CheckQueueTableModel::data(const QModelIndex &index, int role) const {
|
||||||
|
if (!index.isValid() || index.row() >= checks->size())
|
||||||
|
return QVariant();
|
||||||
|
if (role != Qt::DisplayRole) return QVariant();
|
||||||
|
Check& c = checks->at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
return QVariant::fromValue(QString::fromStdString(c.get_date()));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return QVariant::fromValue(c.get_total());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||||
|
if (role == Qt::EditRole) {
|
||||||
|
if (!index.isValid() || index.row() >= checks->size())
|
||||||
|
return false;
|
||||||
|
unsigned int row = index.row();
|
||||||
|
Check &c = checks->at(row);
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
c.set_date(value.value<std::string>());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
c.set_total(value.value<double>());
|
||||||
|
break;
|
||||||
|
emit dataChanged(index, index, {role});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CheckQueueTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||||
|
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
||||||
|
switch (section) {
|
||||||
|
case 0:
|
||||||
|
return tr("Date&Time");
|
||||||
|
case 1:
|
||||||
|
return tr("Total");
|
||||||
|
}
|
||||||
|
} else if (role == Qt::DisplayRole && orientation == Qt::Vertical) {
|
||||||
|
return section + 1;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CheckQueueTableModel::flags(const QModelIndex &index) const {
|
||||||
|
auto flags = QAbstractItemModel::flags(index);
|
||||||
|
|
||||||
|
if (index.isValid())
|
||||||
|
flags |= Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
|
||||||
|
else
|
||||||
|
flags |= Qt::ItemIsDropEnabled;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions CheckQueueTableModel::supportedDropActions() const {
|
||||||
|
return Qt::DropActions() | Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::insertRows(int position, int rows, const QModelIndex &index) {
|
||||||
|
beginInsertRows(QModelIndex(), position, position+rows-1);
|
||||||
|
for (int i = 0; i < rows; ++i)
|
||||||
|
checks->emplace(checks->begin() + position, Check());
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::removeRows(int position, int rows, const QModelIndex &index) {
|
||||||
|
beginRemoveRows(QModelIndex(), position, position+rows-1);
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; ++row)
|
||||||
|
checks->erase(std::next(checks->begin(), position));
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CheckQueueTableModel::mimeTypes() const {
|
||||||
|
QStringList types;
|
||||||
|
types << CheckQueueTableModel::MimeType;
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int, const QModelIndex &) {
|
||||||
|
if (action != Qt::MoveAction || !data->hasFormat(CheckQueueTableModel::MimeType))
|
||||||
|
return false;
|
||||||
|
if (row > checks->size()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* CheckQueueTableModel::mimeData(const QModelIndexList &indexes) const {
|
||||||
|
QMimeData* mimeData = new QMimeData;
|
||||||
|
QByteArray encodedData;
|
||||||
|
|
||||||
|
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
for (const QModelIndex &i : indexes) {
|
||||||
|
if (i.isValid() && i.column() == 0) {
|
||||||
|
Check &c = checks->at(i.row());
|
||||||
|
QString date = QString::fromStdString(c.get_date()),
|
||||||
|
fn = QString::fromStdString(c.get_fn()),
|
||||||
|
fd = QString::fromStdString(c.get_fd()),
|
||||||
|
fi = QString::fromStdString(c.get_fi());
|
||||||
|
double total = c.get_total();
|
||||||
|
OperationType type = c.get_operationType();
|
||||||
|
std::vector<Goods> goods = c.get_goods();
|
||||||
|
|
||||||
|
stream << date << total << type << fn << fd << fi << goods;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mimeData->setData(CheckQueueTableModel::MimeType, encodedData);
|
||||||
|
return mimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
|
||||||
|
if (!canDropMimeData(data, action, row, column, parent)) return false;
|
||||||
|
if (action == Qt::IgnoreAction) return true;
|
||||||
|
else if (action != Qt::MoveAction) return false;
|
||||||
|
if (row > checks->size()) return false;
|
||||||
|
|
||||||
|
QByteArray encodedData = data->data(CheckQueueTableModel::MimeType);
|
||||||
|
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||||
|
std::vector<Check> newItems;
|
||||||
|
int rows = 0;
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
QString date, fn, fd, fi;
|
||||||
|
double total;
|
||||||
|
OperationType type;
|
||||||
|
std::vector<Goods> goods;
|
||||||
|
|
||||||
|
stream >> date >> total >> type >> fn >> fd >> fi >> goods;
|
||||||
|
Check c = Check(
|
||||||
|
date.toStdString(),
|
||||||
|
total,
|
||||||
|
type,
|
||||||
|
fn.toStdString(),
|
||||||
|
fd.toStdString(),
|
||||||
|
fi.toStdString(),
|
||||||
|
goods
|
||||||
|
);
|
||||||
|
newItems.push_back(c);
|
||||||
|
++rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertRows(row, rows, QModelIndex());
|
||||||
|
|
||||||
|
for (Check item : newItems) {
|
||||||
|
// (*checks)[row] = std::move(item);
|
||||||
|
Check &c = checks->at(row);
|
||||||
|
c.set_date(item.get_date());
|
||||||
|
c.set_total(item.get_total());
|
||||||
|
c.set_fn(item.get_fn());
|
||||||
|
c.set_fd(item.get_fd());
|
||||||
|
c.set_fi(item.get_fi());
|
||||||
|
c.set_operation_type(item.get_operationType());
|
||||||
|
for (Goods &g : item.get_goods()) {
|
||||||
|
c.add_goods(g);
|
||||||
|
}
|
||||||
|
emit dataChanged(index(row, 0), index(row, 1));
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckQueueTableModel::sort(int column, Qt::SortOrder order) {
|
||||||
|
beginResetModel();
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
std::sort(checks->begin(), checks->end(),
|
||||||
|
[&](const Check& a, const Check& b) {
|
||||||
|
if (order == Qt::AscendingOrder) {
|
||||||
|
return compare(a, b, column);
|
||||||
|
} else {
|
||||||
|
return !compare(a, b, column);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
std::sort(checks->begin(), checks->end(),
|
||||||
|
[&](const Check& a, const Check& b) {
|
||||||
|
if (order == Qt::AscendingOrder) {
|
||||||
|
return compare(a, b, column);
|
||||||
|
} else {
|
||||||
|
return !compare(a, b, column);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckQueueTableModel::compare(const Check &check_a, const Check &check_b, int column) {
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
return
|
||||||
|
QDateTime::fromString(QString::fromStdString(((Check &)check_a).get_date()), "yyyyMMddThhmm")
|
||||||
|
>
|
||||||
|
QDateTime::fromString(QString::fromStdString(((Check &)check_b).get_date()), "yyyyMMddThhmm");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return ((Check &)check_a).get_total() > ((Check &)check_b).get_total();
|
||||||
|
break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
widgets/checkqueuetablemodel.h
Normal file
41
widgets/checkqueuetablemodel.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef CHECKQUEUETABLEMODEL_H
|
||||||
|
#define CHECKQUEUETABLEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
#include <check/check.h>
|
||||||
|
|
||||||
|
class CheckQueueTableModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
static constexpr const char* MimeType = "application/check.queue.model";
|
||||||
|
public:
|
||||||
|
explicit CheckQueueTableModel(std::vector<Check> *checks, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
Qt::DropActions supportedDropActions() const override;
|
||||||
|
|
||||||
|
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
|
||||||
|
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
|
||||||
|
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
|
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &);
|
||||||
|
QMimeData* mimeData(const QModelIndexList &indexes) const override;
|
||||||
|
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
|
|
||||||
|
void sort(int column, Qt::SortOrder order) override;
|
||||||
|
private:
|
||||||
|
std::vector<Check> *checks;
|
||||||
|
bool compare(const Check& check_a, const Check& check_b, int column);
|
||||||
|
signals:
|
||||||
|
void editCompleted(const QString &);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHECKQUEUETABLEMODEL_H
|
||||||
47
widgets/checkqueuetableview.cpp
Normal file
47
widgets/checkqueuetableview.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "checkqueuetableview.h"
|
||||||
|
|
||||||
|
CheckQueueTableView::CheckQueueTableView(QWidget *parent)
|
||||||
|
: QTableView(parent), m_dropRow(0) {
|
||||||
|
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
setDragEnabled(true);
|
||||||
|
setAcceptDrops(true);
|
||||||
|
setDragDropMode(QAbstractItemView::DragDrop);
|
||||||
|
setDefaultDropAction(Qt::MoveAction);
|
||||||
|
setDragDropOverwriteMode(false);
|
||||||
|
setDropIndicatorShown(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckQueueTableView::selectedRow() const {
|
||||||
|
QItemSelectionModel *selection = selectionModel();
|
||||||
|
return selection->hasSelection() ? selection->selectedRows().front().row() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckQueueTableView::reset() {
|
||||||
|
QTableView::reset();
|
||||||
|
|
||||||
|
QObject::connect(model(), &QAbstractTableModel::rowsInserted, this, [this](const QModelIndex &parent, int first, int last) {
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
Q_UNUSED(last)
|
||||||
|
m_dropRow = first;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckQueueTableView::dropEvent(QDropEvent *e) {
|
||||||
|
if (e->source() != this || e->dropAction() != Qt::MoveAction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int dragRow = selectedRow();
|
||||||
|
|
||||||
|
QTableView::dropEvent(e); // m_dropRow is set by inserted row
|
||||||
|
|
||||||
|
if (m_dropRow > dragRow)
|
||||||
|
--m_dropRow;
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(this,
|
||||||
|
std::bind(&CheckQueueTableView::selectRow, this, m_dropRow),
|
||||||
|
Qt::QueuedConnection); // Postpones selection
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
19
widgets/checkqueuetableview.h
Normal file
19
widgets/checkqueuetableview.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef CHECKQUEUETABLEVIEW_H
|
||||||
|
#define CHECKQUEUETABLEVIEW_H
|
||||||
|
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QDropEvent>
|
||||||
|
|
||||||
|
class CheckQueueTableView : public QTableView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
int m_dropRow;
|
||||||
|
public:
|
||||||
|
CheckQueueTableView(QWidget *parent = nullptr);
|
||||||
|
Q_INVOKABLE int selectedRow() const;
|
||||||
|
void reset();
|
||||||
|
void dropEvent(QDropEvent *e);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHECKQUEUETABLEVIEW_H
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
#include "outputcolumnmodel.h"
|
#include "outputcolumnmodel.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <outputcolumn.h>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
|
#include <outputcolumn.h>
|
||||||
|
|
||||||
OutputColumnModel::OutputColumnModel(std::vector<OutputColumn> *columns, QObject *parent)
|
OutputColumnModel::OutputColumnModel(std::vector<OutputColumn> *columns, QObject *parent)
|
||||||
: columns(columns), QAbstractListModel{parent} { }
|
: columns(columns), QAbstractListModel{parent} { }
|
||||||
@@ -139,8 +138,7 @@ bool OutputColumnModel::dropMimeData(const QMimeData *data, Qt::DropAction actio
|
|||||||
}
|
}
|
||||||
|
|
||||||
insertRows(row, rows, QModelIndex());
|
insertRows(row, rows, QModelIndex());
|
||||||
for (const OutputColumn &column : newItems)
|
for (const OutputColumn &column : newItems) {
|
||||||
{
|
|
||||||
QModelIndex idx = index(row, 0, QModelIndex());
|
QModelIndex idx = index(row, 0, QModelIndex());
|
||||||
setData(idx, QVariant::fromValue(column), 0x102);
|
setData(idx, QVariant::fromValue(column), 0x102);
|
||||||
row++;
|
row++;
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ public:
|
|||||||
|
|
||||||
QStringList mimeTypes() const override;
|
QStringList mimeTypes() const override;
|
||||||
bool canDropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex&);
|
bool canDropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex&);
|
||||||
QMimeData* mimeData(const QModelIndexList &indexes) const;
|
QMimeData* mimeData(const QModelIndexList &indexes) const override;
|
||||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OUTPUTCOLUMNMODEL_H
|
#endif // OUTPUTCOLUMNMODEL_H
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
#include "tablewidgetmovable.hpp"
|
|
||||||
#include <QDropEvent>
|
|
||||||
#include <iostream>
|
|
||||||
#include <QTableWidget>
|
|
||||||
#include <qcoreevent.h>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
TableWidgetMovable::TableWidgetMovable(QWidget *parent) : QTableWidget(parent) { }
|
|
||||||
|
|
||||||
// void TableWidgetMovable::dropEvent(QDropEvent *event) {
|
|
||||||
// if (event->source() == this) {
|
|
||||||
// // Get the index of the row being dragged
|
|
||||||
// QModelIndex sourceIndex = currentIndex();
|
|
||||||
// if (!sourceIndex.isValid()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get the index of the target row
|
|
||||||
// QModelIndex targetIndex = indexAt(event->pos());
|
|
||||||
// if (!targetIndex.isValid()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// int sourceRow = sourceIndex.row();
|
|
||||||
// int targetRow = targetIndex.row();
|
|
||||||
|
|
||||||
// // Swap rows
|
|
||||||
// if (sourceRow != targetRow) {
|
|
||||||
// // Store the data of the source row
|
|
||||||
// QList<QTableWidgetItem*> itemsSource;
|
|
||||||
// for (int col = 0; col < columnCount(); ++col) {
|
|
||||||
// itemsSource.append(takeItem(sourceRow, col));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QList<QTableWidgetItem*> itemsTarget;
|
|
||||||
// for (int col = 0; col < columnCount(); ++col) {
|
|
||||||
// itemsTarget.append(takeItem(targetRow, col));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Insert the items into the target row
|
|
||||||
// for (int col = 0; col < columnCount(); ++col) {
|
|
||||||
// setItem(targetRow, col, itemsSource[col]);
|
|
||||||
// setItem(sourceRow, col, itemsTarget[col]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // for (int col = 0; col < columnCount(); ++col) {
|
|
||||||
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // Remove the original row
|
|
||||||
// // removeRow(sourceRow < targetRow ? sourceRow : sourceRow + 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// event->acceptProposedAction();
|
|
||||||
// } else {
|
|
||||||
// QTableWidget::dropEvent(event);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TOOD: fix None of these works. WIP
|
|
||||||
|
|
||||||
// void TableWidgetMovable::dropEvent(QDropEvent *event) {
|
|
||||||
// std::cout << event->type() << std::endl;
|
|
||||||
// if(event->source() == this && event->type() == QEvent::Type::Drop) {
|
|
||||||
// int oldRow = this->selectedItems()[0]->row();
|
|
||||||
// int oldColumn = this->selectedItems()[0]->column();
|
|
||||||
|
|
||||||
// int newRow = this->indexAt(event->pos()).row();
|
|
||||||
// int newColumn = this->indexAt(event->pos()).column();
|
|
||||||
|
|
||||||
// auto oldCell = this->cellWidget(oldRow, oldColumn);
|
|
||||||
// auto newCell = this->cellWidget(newRow, newColumn);
|
|
||||||
|
|
||||||
// this->removeCellWidget(oldRow, oldColumn);
|
|
||||||
// this->removeCellWidget(newRow, newColumn);
|
|
||||||
|
|
||||||
// this->setCellWidget(newRow, newColumn, oldCell);
|
|
||||||
// this->setCellWidget(oldRow, oldColumn, newCell);
|
|
||||||
// event->accept();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void TableWidgetMovable::dropEvent(QDropEvent *event) {
|
|
||||||
// std::cout << event->type() << std::endl;
|
|
||||||
// if(event->source() == this && event->type() == QEvent::Type::Drop) {
|
|
||||||
// int oldRow = this->selectedItems()[0]->row();
|
|
||||||
// int oldColumn = this->selectedItems()[0]->column();
|
|
||||||
|
|
||||||
// int newRow = this->indexAt(event->pos()).row();
|
|
||||||
// int newColumn = this->indexAt(event->pos()).column();
|
|
||||||
// std::cout << oldRow << " " << oldColumn<< " " << newRow << " " << newColumn << std::endl;
|
|
||||||
// QTableWidgetItem *from = this->itemAt(oldColumn, oldRow), *to = this->itemAt(newColumn, newRow);
|
|
||||||
|
|
||||||
// // QList<QTableWidgetItem*> selectedItems = this->selectedItems();
|
|
||||||
// if(newRow == -1) {
|
|
||||||
// std::cout << newRow << std::endl;
|
|
||||||
// // newRow = this->rowCount();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // QTableWidgetItem bufferTo, bufferFrom;
|
|
||||||
// QTableWidgetItem *bufferTo = new QTableWidgetItem("123"), *bufferFrom = new QTableWidgetItem("321");
|
|
||||||
// std::cout << to->text().toStdString() << " " << from->text().toStdString() << std::endl;
|
|
||||||
// *bufferTo = *to;
|
|
||||||
// *bufferFrom = *from;
|
|
||||||
// // this->setItem(newRow, newColumn, nullptr);
|
|
||||||
// // this->setItem(oldRow, oldColumn, nullptr);
|
|
||||||
// this->takeItem(newRow, newColumn);
|
|
||||||
// this->takeItem(oldRow, oldColumn);
|
|
||||||
// this->setItem(newRow, newColumn, from);
|
|
||||||
// // this->setItem(oldRow, oldColumn, to);
|
|
||||||
// // *to = *from;
|
|
||||||
// // *from = buffer;
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// // int i;
|
|
||||||
// // for(i = 0; i < selectedItems.length()/this->columnCount(); i++)
|
|
||||||
// // this->insertRow(newRow);
|
|
||||||
|
|
||||||
// // int currentOldRow = -1;
|
|
||||||
// // int currentNewRow = newRow-1;
|
|
||||||
// // QList<int> deleteRows;
|
|
||||||
// // foreach(selectedItem, selectedItems) {
|
|
||||||
// // int column = selectedItem->column();
|
|
||||||
// // if(selectedItem->row() != currentOldRow) {
|
|
||||||
// // currentOldRow = selectedItem->row();
|
|
||||||
// // deleteRows.append(currentOldRow);
|
|
||||||
// // currentNewRow++;
|
|
||||||
// // }
|
|
||||||
// // this->takeItem(currentOldRow, column);
|
|
||||||
// // this->setItem(currentNewRow, column, selectedItem);
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // for(i = deleteRows.count()-1; i>=0; i--)
|
|
||||||
// // this->removeRow(deleteRows.at(i));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef TABLEWIDGETMOVABLE_HPP
|
|
||||||
#define TABLEWIDGETMOVABLE_HPP
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QTableWidget>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class TableWidgetMovable : public QTableWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
TableWidgetMovable(QWidget *parent = nullptr);
|
|
||||||
// void dropEvent(QDropEvent *event);
|
|
||||||
// void swapRows(int row1, int row2);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TABLEWIDGETMOVABLE_HPP
|
|
||||||
Reference in New Issue
Block a user