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
|
||||
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/outputcolumnmodel.h widgets/outputcolumnmodel.cpp
|
||||
|
||||
@@ -116,7 +116,7 @@ if (BUILD_OFD_BINARYEYE_SCAN)
|
||||
endif()
|
||||
|
||||
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)
|
||||
endif()
|
||||
|
||||
@@ -165,6 +165,8 @@ else()
|
||||
add_executable(checks-parser
|
||||
${PROJECT_SOURCES}
|
||||
${SOURCES}
|
||||
widgets/checkqueuetablemodel.h widgets/checkqueuetablemodel.cpp
|
||||
# widgets/checkqueuetableview.h widgets/checkqueuetableview.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -205,9 +207,9 @@ if (BUILD_OFD_BINARYEYE_SCAN)
|
||||
link_directories(${QRENCODE_LIBRARY_DIRS})
|
||||
target_link_libraries(checks-parser PRIVATE ${QRENCODE_LIBRARIES})
|
||||
endif()
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||
endif()
|
||||
# if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
# target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||
# endif()
|
||||
|
||||
target_link_libraries(checks-parser PRIVATE -lcurl)
|
||||
|
||||
@@ -220,7 +222,7 @@ include_directories(${Boost_INCLUDE_DIRS})
|
||||
target_link_libraries(checks-parser PUBLIC ${Boost_LIBRARIES})
|
||||
|
||||
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_include_directories(checks-parser PUBLIC ${OpenCV_INCLUDE_DIRS})
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
|
||||
67
README.md
67
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)<--
|
||||
|
||||
# Checks parser
|
||||
checks parser is a program that help parsing different checks to csv.
|
||||
|
||||
!!!CURRENTLY SUPPORTED ONLY RUSSIAN CHECKS!!!
|
||||
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)
|
||||
|
||||
### Input
|
||||
## Input
|
||||
|
||||
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 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)).
|
||||
|
||||
### 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.
|
||||
|
||||
# Installing
|
||||
## Building
|
||||
## Installing
|
||||
|
||||
### 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...):
|
||||
|
||||
* boost
|
||||
* tesseract (you also have to install appropriate for your needs language data)
|
||||
* opencv
|
||||
@@ -33,8 +46,11 @@ In general, you need to install following dependencies in order to build that ap
|
||||
* qrencode
|
||||
|
||||
Please, do not hesitate to open an issue if you cannot build that. I will help and if you are building on a distro that is not listed there, we can append that list as soon as we will solve your problem!
|
||||
### Linux
|
||||
|
||||
#### Linux
|
||||
|
||||
##### 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 ¯\\\_(ツ)\_/¯
|
||||
```
|
||||
#Install dependencies
|
||||
@@ -49,17 +65,24 @@ make -j{nproc}
|
||||
#If you wish to install that program system-wide, run
|
||||
sudo make install
|
||||
```
|
||||
|
||||
##### Debian-based
|
||||
|
||||
In debian-based distributions most, but not every, package names are the same.
|
||||
|
||||
Installation of dependencies for different debian-based distros:
|
||||
|
||||
###### Ubuntu 18.04
|
||||
|
||||
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libtesseract-dev libqrencode-dev libboost-regex-dev```
|
||||
|
||||
###### Ubuntu 20.04, LMDE (tested only 6), Debian (tested only 12)
|
||||
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json3-dev libcurl4-openssl-dev libtesseract-dev 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
|
||||
```
|
||||
|
||||
```sh
|
||||
#Clone and compile an app
|
||||
git clone https://git.foxarmy.org/leca/checks-parser
|
||||
cd checks-parser
|
||||
@@ -69,36 +92,42 @@ make -j{nproc}
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Windows
|
||||
#### Windows
|
||||
|
||||
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!
|
||||
|
||||
## Precompiled binaries
|
||||
### Precompiled binaries
|
||||
|
||||
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!
|
||||
|
||||
# Special thanks
|
||||
## Special thanks
|
||||
|
||||
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:
|
||||
## 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!
|
||||
## 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!
|
||||
|
||||
## 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!
|
||||
|
||||
## Donate
|
||||
### Donate
|
||||
|
||||
```XMR 45ZjyH5YWdRfKxLoKEBYaiHUTcP5Z8Gv64QQxmabbooPAa7KPBxZLmqft5ohKXn5VpHiVj1x9JKCcAcAjdu9jA8b5N8XqR7```
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#include "adjustpicturedialog.h"
|
||||
#include "ui_adjustpicturedialog.h"
|
||||
#include "utils/utils.h"
|
||||
#include <utils/utils.h>
|
||||
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <string>
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <zbar.h>
|
||||
|
||||
using cv::QRCodeDetector, cv::Mat;
|
||||
|
||||
AdjustPictureDialog::AdjustPictureDialog(QWidget *parent, std::string imagePath)
|
||||
: QDialog(parent)
|
||||
@@ -54,24 +57,26 @@ void AdjustPictureDialog::accept() {
|
||||
}
|
||||
|
||||
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;
|
||||
scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
|
||||
// zbar::ImageScanner scanner;
|
||||
// scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
|
||||
|
||||
cv::Mat imGray;
|
||||
cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);
|
||||
// cv::Mat imGray;
|
||||
// cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);
|
||||
|
||||
zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
|
||||
scanner.scan(image);
|
||||
// zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
|
||||
// scanner.scan(image);
|
||||
|
||||
std::string result = "";
|
||||
// std::string result = "";
|
||||
|
||||
for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
|
||||
result = symbol->get_data();
|
||||
}
|
||||
// for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
|
||||
// result = symbol->get_data();
|
||||
// }
|
||||
|
||||
return result;
|
||||
// return result;
|
||||
}
|
||||
|
||||
void AdjustPictureDialog::computeContrastLookupTable() {
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
#include "check.h"
|
||||
#include "../goods/goods.h"
|
||||
#include <iostream>
|
||||
#include <QObject>
|
||||
|
||||
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) {
|
||||
this->goods.push_back(goods);
|
||||
this->total = this->calculae_total_price();
|
||||
@@ -25,46 +35,24 @@ double Check::calculae_total_price() {
|
||||
return total;
|
||||
}
|
||||
|
||||
std::vector<Goods>& Check::get_goods() {
|
||||
return goods;
|
||||
}
|
||||
std::vector<Goods>& Check::get_goods() { return goods; }
|
||||
|
||||
void Check::set_fn(std::string fn) {
|
||||
this->fn = fn;
|
||||
}
|
||||
void Check::set_fn(std::string 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) {
|
||||
this->fd = fd;
|
||||
}
|
||||
|
||||
void Check::set_fi(std::string fi) {
|
||||
this->fi = fi;
|
||||
}
|
||||
|
||||
std::string Check::get_date() {
|
||||
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;
|
||||
}
|
||||
OperationType Check::get_operationType() { return operation_type; }
|
||||
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_goods(std::vector<Goods> goods) { this->goods = goods; }
|
||||
std::string Check::get_fn() { return fn; }
|
||||
std::string Check::get_fd() { return fd; }
|
||||
std::string Check::get_fi() { return fi; }
|
||||
double Check::get_total() { return total; }
|
||||
|
||||
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
|
||||
this->date == c.date &&
|
||||
this->fd == c.fd &&
|
||||
@@ -75,13 +63,6 @@ bool Check::operator==(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
|
||||
this->date == c.date &&
|
||||
this->fd == c.fd &&
|
||||
@@ -90,3 +71,5 @@ bool Check::operator==(const Check &c) {
|
||||
this->operation_type == c.operation_type &&
|
||||
this->total == c.total;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Check)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef CHECK_H
|
||||
#define CHECK_H
|
||||
#include "../goods/goods.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef enum OperationTypes {
|
||||
@@ -23,6 +24,7 @@ class Check {
|
||||
|
||||
public:
|
||||
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(std::vector<Goods> &goods);
|
||||
|
||||
@@ -37,6 +39,8 @@ public:
|
||||
void set_operation_type(OperationType);
|
||||
void set_total(double);
|
||||
|
||||
void set_goods(std::vector<Goods>);
|
||||
|
||||
std::string get_fn();
|
||||
std::string get_fd();
|
||||
std::string get_fi();
|
||||
@@ -48,4 +52,5 @@ public:
|
||||
bool operator==(const Check &);
|
||||
};
|
||||
|
||||
|
||||
#endif // CHECK_H
|
||||
|
||||
@@ -8,10 +8,10 @@ arch=('x86_64')
|
||||
url="https://git.foxarmy.org/leca/checks-parser"
|
||||
license=('GPL-3.0-or-later')
|
||||
groups=()
|
||||
depends=('qt5-base' 'opencv' 'zbar' 'nlohmann-json' 'tesseract' 'qrencode' 'boost')
|
||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt5-tools')
|
||||
depends=('qt6-base' 'opencv' 'nlohmann-json' 'qrencode' 'boost')
|
||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt6-tools')
|
||||
checkdepends=()
|
||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
||||
optdepends=()
|
||||
provides=()
|
||||
conflicts=("checks-parser-git")
|
||||
replaces=()
|
||||
|
||||
@@ -8,10 +8,10 @@ arch=('x86_64')
|
||||
url="https://git.foxarmy.org/leca/checks-parser"
|
||||
license=('GPL-3.0-or-later')
|
||||
groups=()
|
||||
depends=('qt5-base' 'opencv' 'zbar' 'nlohmann-json' 'tesseract' 'qrencode' 'boost')
|
||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt5-tools')
|
||||
depends=('qt6-base' 'opencv' 'nlohmann-json' 'qrencode' 'boost')
|
||||
makedepends=('cmake' 'make' 'gcc' 'git' 'qt6-tools')
|
||||
checkdepends=()
|
||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
||||
optdepends=()
|
||||
provides=()
|
||||
conflicts=("checks-parser-bin")
|
||||
replaces=()
|
||||
@@ -25,12 +25,15 @@ sha256sums=('SKIP')
|
||||
|
||||
build() {
|
||||
cd "$pkgname"
|
||||
cmake -DBUILD_TRANSLATIONS=on .
|
||||
mkdir build && cd build
|
||||
cmake -DBUILD_TRANSLATIONS=on ..
|
||||
make -j ${nproc}
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname"
|
||||
cd "$pkgname"
|
||||
cd build
|
||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
##install -Dm755
|
||||
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
|
||||
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
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
#include "utils/utils.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/base64.h>
|
||||
#include <check/check.h>
|
||||
#include <boost/regex.hpp>
|
||||
#include <sstream>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <iostream>
|
||||
#include <bits/stdc++.h>
|
||||
#include <fstream>
|
||||
|
||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
using namespace std::experimental::filesystem;
|
||||
@@ -16,165 +23,189 @@
|
||||
using namespace std::filesystem;
|
||||
#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() {
|
||||
|
||||
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::vector<int> content_type_positions = {};
|
||||
boost::regex image_content_type_regex("Content-Type: image/.*");
|
||||
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 {
|
||||
std::map<std::string, std::string> EmailParser::parse(std::string &email_content) {
|
||||
std::string parameters;
|
||||
parameters = search_in_images(email_content);
|
||||
|
||||
if (parameters != "") {
|
||||
return get_params_from_string(parameters);
|
||||
}
|
||||
|
||||
// std::string payload = get_payload_in_email(email_content);
|
||||
// Check c;
|
||||
parameters = search_in_text(email_content);
|
||||
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;
|
||||
|
||||
// if (payload == "")
|
||||
// return c;
|
||||
|
||||
|
||||
|
||||
// return c;
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
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);
|
||||
// unsigned int body_start = -1;
|
||||
// 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 (boost::sregex_iterator it{content.begin(), content.end(), start_regex}, end{}; it != end; it ++) {
|
||||
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[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);
|
||||
// const unsigned int size = std::filesystem::file_size(path);
|
||||
// std::string content(size, '\0');
|
||||
// ifile.read(content.data(), size);
|
||||
// return parse(content);
|
||||
return Check();
|
||||
return parts;
|
||||
}
|
||||
|
||||
std::string EmailParser::find_check_parameters(std::string &part) {
|
||||
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);
|
||||
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 <map>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
class EmailParser {
|
||||
std::string get_payload_in_email(std::string &email_content);
|
||||
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);
|
||||
boost::regex headings_regex, end_marker_regex, part_end_regex;
|
||||
public:
|
||||
EmailParser();
|
||||
Check parse(std::string &email_content);
|
||||
Check parse_file(std::string path);
|
||||
std::map<std::string, std::string> parse(std::string &email_content);
|
||||
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
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "goods.h"
|
||||
#include <string>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
Goods::Goods() { }
|
||||
|
||||
Goods::Goods(std::string name, double price_per_unit, std::string net_weight, double quantity) :
|
||||
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(QString name) { this->name = name.toStdString(); }
|
||||
|
||||
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(QString net_weight) { this->net_weight = net_weight.toStdString(); }
|
||||
|
||||
void Goods::set_price_per_unit(double 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
|
||||
#define GOODS_H
|
||||
|
||||
#include <QDataStream>
|
||||
#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:
|
||||
Goods(std::string name, double quantity, std::string net_weight, double price_per_unit);
|
||||
double calculate_total_price();
|
||||
Goods();
|
||||
Goods(std::string name, double quantity, std::string net_weight,
|
||||
double price_per_unit);
|
||||
double calculate_total_price();
|
||||
|
||||
std::string get_name();
|
||||
double get_quantity();
|
||||
std::string get_net_weight();
|
||||
double get_price_per_unit();
|
||||
std::string get_name();
|
||||
double get_quantity();
|
||||
std::string get_net_weight();
|
||||
double get_price_per_unit();
|
||||
|
||||
void set_name(std::string);
|
||||
void set_quantity(double);
|
||||
void set_net_weight(std::string);
|
||||
void set_price_per_unit(double);
|
||||
void set_name(std::string);
|
||||
void set_name(QString);
|
||||
void set_quantity(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
|
||||
|
||||
20
main.cpp
20
main.cpp
@@ -1,4 +1,3 @@
|
||||
#include "email_parser/emailparser.h"
|
||||
#include <mainwindow.h>
|
||||
#include <net/net.h>
|
||||
#include <settings/settings.h>
|
||||
@@ -15,24 +14,21 @@
|
||||
# include <filesystem>
|
||||
using namespace std::filesystem;
|
||||
#endif
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QStackedLayout>
|
||||
#include <QTextStream>
|
||||
#ifdef BUILD_TRANSLATIONS
|
||||
# include <QTranslator>
|
||||
#endif
|
||||
#include <settingsdialog.h>
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
// #include <vmime/vmime.hpp>
|
||||
# include <email_parser/emailparser.h>
|
||||
#endif
|
||||
#include <QPushButton>
|
||||
|
||||
#include <utils/base64.h>
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
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");
|
||||
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;
|
||||
|
||||
translator.load(":/translation/" + lang + ".qm");
|
||||
if (!translator.load(":/translation/" + lang + ".qm")) {
|
||||
std::cerr << "Could not load translation!!" << std::endl;
|
||||
}
|
||||
app.installTranslator(&translator);
|
||||
#endif
|
||||
MainWindow w;
|
||||
|
||||
191
mainwindow.cpp
191
mainwindow.cpp
@@ -5,9 +5,12 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPixmap>
|
||||
#include <settingsdialog.h>
|
||||
#include <string>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
# include <adjustpicturedialog.h>
|
||||
# include <checkqueuetablemodel.h>
|
||||
#endif
|
||||
|
||||
#include <outputdialog.h>
|
||||
@@ -15,7 +18,6 @@
|
||||
#include <net/net.h>
|
||||
#include <utils/utils.h>
|
||||
#include <exceptions/ofdrequestexception.h>
|
||||
#include <checklistviewwidget.h>
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
# include <qrencode.h>
|
||||
@@ -24,6 +26,7 @@
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#include <email_parser/emailparser.h>
|
||||
#endif
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
@@ -32,18 +35,24 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
ui->setupUi(this);
|
||||
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_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
|
||||
QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure);
|
||||
connect(this, SIGNAL(httpNewMessage(QString)), this, SLOT(httpNewMessageHandler(QString)));
|
||||
#else
|
||||
ui->or_label_2->hide();
|
||||
ui->binary_eye_button->hide();
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_EMAIL_MODE
|
||||
@@ -51,10 +60,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
ui->or_label_2->hide();
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_OFD_BINARYEYE_SCAN
|
||||
ui->or_label_2->hide();
|
||||
ui->binary_eye_button->hide();
|
||||
#endif
|
||||
#ifndef BUILD_OFD_LOCAL_QR_SCAN
|
||||
ui->or_label_1->hide();
|
||||
ui->choose_image_button->hide();
|
||||
@@ -122,32 +127,17 @@ void MainWindow::httpNewMessageHandler(QString message) {
|
||||
|
||||
//erase /?result= from the string
|
||||
parametersString.erase(0, parametersString.find("=") + 1);
|
||||
|
||||
std::vector<std::string> parameters = split(parametersString, "&");
|
||||
|
||||
std::map<std::string, std::string> paramsMap;
|
||||
|
||||
for (auto ¶meter : parameters) {
|
||||
std::vector<std::string> values = split(parameter, "=");
|
||||
paramsMap.insert(std::pair<std::string, std::string> (values[0], values[1]));
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> paramsMap = get_params_from_string(parametersString);
|
||||
emit onDataDecode(paramsMap);
|
||||
}
|
||||
|
||||
|
||||
#endif //ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
|
||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
void MainWindow::on_choose_image_button_clicked() {
|
||||
QString filename = QFileDialog::getOpenFileName();
|
||||
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("Images (*.jpg *.jpeg *.png)"));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -160,95 +150,70 @@ void MainWindow::on_choose_image_button_clicked() {
|
||||
#endif //ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
|
||||
void MainWindow::onDataDecode(std::map<std::string, std::string> data) {
|
||||
ui->fn_line_edit->setText(QString::fromStdString(data["fn"]));
|
||||
ui->fd_line_edit->setText(QString::fromStdString(data["i"]));
|
||||
ui->fi_line_edit->setText(QString::fromStdString(data["fp"]));
|
||||
|
||||
QString extractedDateTime = QString::fromStdString(data["t"]);
|
||||
//TODO: some QRs contain datetime in format yyyyMMddThhmmss. Perhaps there is more different formats, should write function to detect them.
|
||||
QDateTime datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmm");
|
||||
if (datetime == QDateTime::fromString(extractedDateTime, "20000101T1200")) {
|
||||
datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmmss");
|
||||
}
|
||||
ui->purchase_datetime_edit->setDateTime(datetime);
|
||||
|
||||
int type = std::stoi(data["n"]);
|
||||
ui->operation_type_combo_box->setCurrentIndex(type - 1);
|
||||
|
||||
std::string total = data["s"];
|
||||
|
||||
ui->total_spin_box->setValue(std::stod(total));
|
||||
set_check_params(data);
|
||||
}
|
||||
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
|
||||
void MainWindow::on_parse_email_button_clicked() {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("This feature is under development. Wait it to appear in next updates."));
|
||||
infoDialog.setIcon(QMessageBox::Warning);
|
||||
infoDialog.setWindowTitle(tr("Under development"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("E-Mail files (*.eml)"));
|
||||
|
||||
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
|
||||
|
||||
void MainWindow::on_parse_button_clicked() {
|
||||
// if (checks.empty()) {
|
||||
// QMessageBox infoDialog;
|
||||
// infoDialog.setText(tr("Please, add check(s) to parse"));
|
||||
// infoDialog.setIcon(QMessageBox::Warning);
|
||||
// infoDialog.setWindowTitle(tr("No checks to parse"));
|
||||
// infoDialog.exec();
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (checks.empty()) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Please, add check(s) to parse"));
|
||||
infoDialog.setIcon(QMessageBox::Warning);
|
||||
infoDialog.setWindowTitle(tr("No checks to parse"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
OutputDialog d = OutputDialog(this, &checks);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
void MainWindow::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() {
|
||||
Check *new_check = parse_new_check();
|
||||
if (new_check == nullptr) {
|
||||
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;
|
||||
|
||||
if (checks.size() == 1) {
|
||||
ui->checks_scroll_area->show();
|
||||
if (checks.size() > 0) {
|
||||
ui->checkQueueTable->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,
|
||||
// In the request to ofd.ru, total is in a format with 2 last digits represent decimal part of a number.
|
||||
ui->total_spin_box->text().toDouble() * 100,
|
||||
solved_captcha);
|
||||
solved_captcha
|
||||
);
|
||||
|
||||
(*check) = parseOfdRuAnswer(check_content);
|
||||
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_fi(ui->fi_line_edit->text().toStdString());
|
||||
check->set_operation_type(OperationType(ui->operation_type_combo_box->currentIndex() + 1));
|
||||
|
||||
return check;
|
||||
} catch(OfdRequestException e) {
|
||||
QMessageBox infoDialog;
|
||||
if (!strcmp(e.what(), "Incorrect captcha")) {
|
||||
QMessageBox infoDialog;
|
||||
|
||||
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
||||
infoDialog.exec();
|
||||
continue;
|
||||
} else if (!strcmp(e.what(), "Internal server error")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Internal server error. Please, try again later."));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Internal server error"));
|
||||
infoDialog.exec();
|
||||
return nullptr;
|
||||
} else if (!strcmp(e.what(), "Does not exist")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Check was not found"));
|
||||
@@ -312,3 +278,40 @@ Check *MainWindow::parse_new_check() {
|
||||
MainWindow::~MainWindow() {
|
||||
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 <QEvent>
|
||||
#include <thread>
|
||||
#include <checkqueuetablemodel.h>
|
||||
|
||||
#include <http_server/http_server.h>
|
||||
|
||||
@@ -22,6 +23,7 @@ public:
|
||||
~MainWindow();
|
||||
|
||||
Check *parse_new_check();
|
||||
CheckQueueTableModel *model;
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
void startHttpServer();
|
||||
@@ -47,12 +49,15 @@ private slots:
|
||||
void on_stop_server_button_clicked();
|
||||
|
||||
void httpNewMessageHandler(QString message);
|
||||
void deleteCheckFromListHandler(Check&);
|
||||
// void deleteCheckFromListHandler(Check&);
|
||||
#endif
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
void on_parse_email_button_clicked();
|
||||
#endif
|
||||
void on_add_new_check_button_clicked();
|
||||
|
||||
void on_deleteSelectedButton_clicked();
|
||||
void set_check_params(std::map<std::string, std::string>);
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
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 totalSize = size * nmemb;
|
||||
((std::string*)userp)->append(std::string((char*)contents));
|
||||
((std::string*)userp)->append(std::string((char *)contents));
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
size_t write_data(void *buffer, size_t size, size_t nmemb, void *filename) {
|
||||
FILE *f = fopen(((std::string *)filename)->c_str(), "w");
|
||||
size_t written = fwrite(buffer, size, nmemb, f);
|
||||
// size_t write_data_to_file(void *buffer, size_t size, size_t nmemb, void *filename) {
|
||||
// FILE *f = fopen(((std::string *)filename)->c_str(), "wb");
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
CURL *handle = curl_easy_init();
|
||||
|
||||
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_WRITEDATA, &filename);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, f);
|
||||
|
||||
auto success = curl_easy_perform(handle);
|
||||
|
||||
fclose(f);
|
||||
curl_easy_cleanup(handle);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string>
|
||||
#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);
|
||||
|
||||
class Net
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
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);
|
||||
void get_captcha_from_ofdru();
|
||||
std::string get_data(std::string url);
|
||||
};
|
||||
|
||||
#endif // NET_H
|
||||
|
||||
@@ -11,51 +11,50 @@
|
||||
#include <outputcolumnmodel.h>
|
||||
#include "settings/settings.h"
|
||||
#include "utils/utils.h"
|
||||
#include <map>
|
||||
|
||||
OutputDialog::OutputDialog(QWidget *parent, std::vector<Check> *checks)
|
||||
: QDialog(parent), ui(new Ui::OutputDialog), checks(checks),
|
||||
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);
|
||||
|
||||
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->push_back(OutputColumn(tr("Date"), ColumnType::date));
|
||||
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);
|
||||
OutputColumnModel *model = new OutputColumnModel(columns, this);
|
||||
|
||||
ui->listView->setModel(model);
|
||||
|
||||
// ui->tableWidget->item(0, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["date"]["name"]));
|
||||
// ui->tableWidget->item(0, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["date"]["position"]));
|
||||
for (unsigned short i = 0; i < 6; i ++)
|
||||
columns->push_back(OutputColumn(tr("Кто здесь?"), ColumnType::date));
|
||||
|
||||
// ui->tableWidget->item(1, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_name"]["name"]));
|
||||
// ui->tableWidget->item(1, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_name"]["position"]));
|
||||
for (auto &column : column_names) {
|
||||
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"]));
|
||||
// ui->tableWidget->item(3, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_quantity"]["position"]));
|
||||
for (unsigned short i = 0; i < 6; i ++)
|
||||
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->tableWidget->item(4, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]));
|
||||
|
||||
// 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"]);
|
||||
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() {
|
||||
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 (int i = 0; i < columns->size(); i ++) {
|
||||
OutputColumn &column = columns->at(i);
|
||||
std::cout << column.get_text().toStdString() << std::endl;
|
||||
switch (column.get_column_type()) {
|
||||
case ColumnType::date:
|
||||
if (row_number == 0) output_file << check.get_date();
|
||||
@@ -90,7 +88,7 @@ void OutputDialog::on_buttonBox_accepted() {
|
||||
}
|
||||
|
||||
if (i < columns->size() - 1) {
|
||||
output_file << ",";
|
||||
output_file << "|";
|
||||
} else {
|
||||
output_file << "\n";
|
||||
}
|
||||
@@ -102,22 +100,9 @@ void OutputDialog::on_buttonBox_accepted() {
|
||||
}
|
||||
}
|
||||
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() {
|
||||
QString filename = QFileDialog::getSaveFileName();
|
||||
this->options.set_path(filename.toStdString());
|
||||
@@ -139,8 +124,18 @@ void OutputDialog::print_header(std::ofstream *output_file) {
|
||||
(*output_file) << column.get_text().toStdString()
|
||||
<< (i == columns->size() - 1
|
||||
? ""
|
||||
: ",");
|
||||
: "|");
|
||||
}
|
||||
*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;
|
||||
std::vector<Check> *checks;
|
||||
std::vector<OutputColumn> *columns;
|
||||
Settings *settings;
|
||||
|
||||
public:
|
||||
explicit OutputDialog(QWidget *parent = nullptr, std::vector<Check> *checks = nullptr);
|
||||
@@ -35,6 +36,8 @@ private:
|
||||
Ui::OutputDialog *ui;
|
||||
|
||||
void print_header(std::ofstream *output_file);
|
||||
|
||||
void save_settings();
|
||||
};
|
||||
|
||||
#endif // OUTPUTDIALOG_H
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1269</width>
|
||||
<height>490</height>
|
||||
<width>987</width>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -26,23 +26,23 @@
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="or_label_1">
|
||||
<item row="8" column="2" colspan="4">
|
||||
<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">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>or</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>
|
||||
<string>Add to queue</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -59,155 +59,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2" colspan="3">
|
||||
<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">
|
||||
<item row="7" column="2" colspan="4">
|
||||
<widget class="QComboBox" name="operation_type_combo_box">
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -231,14 +83,200 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="operation_type_label">
|
||||
<item row="0" column="5">
|
||||
<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>Operation type</string>
|
||||
<string>Stop server</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
@@ -251,48 +289,62 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="clear_button">
|
||||
<item row="5" column="0">
|
||||
<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">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
<string>FN (Fiscal Number)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="fi_line_edit"/>
|
||||
</item>
|
||||
<item row="9" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="add_new_check_button">
|
||||
<item row="0" column="8">
|
||||
<widget class="QPushButton" name="deleteSelectedButton">
|
||||
<property name="text">
|
||||
<string>Add new check</string>
|
||||
<string>Delete selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="fd_line_edit"/>
|
||||
</item>
|
||||
<item row="1" column="5" rowspan="9">
|
||||
<widget class="QScrollArea" name="checks_scroll_area">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
<item row="1" column="6">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>273</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -24,14 +30,28 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>659</width>
|
||||
<height>634</height>
|
||||
<width>673</width>
|
||||
<height>554</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<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">
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -45,161 +65,52 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<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">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="print_header_label">
|
||||
<property name="text">
|
||||
<string>Print header</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<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">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="printTotalCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<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">
|
||||
<widget class="QLabel" name="language_label">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Goods net weight alias</string>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QListView" name="outputOptionsListView">
|
||||
<property name="sizePolicy">
|
||||
<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>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
#include <settings/settings.h>
|
||||
#include <utils/utils.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <outputcolumnmodel.h>
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::settingsdialog),
|
||||
@@ -15,23 +14,24 @@ SettingsDialog::SettingsDialog(QWidget *parent)
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->goodsNamePositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_name"]["position"]);
|
||||
ui->goodsNameAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_name"]["name"]));
|
||||
columns = new std::vector<OutputColumn>;
|
||||
|
||||
ui->goodsPricePerUnitPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"]);
|
||||
ui->goodsPricePerUnitAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"]));
|
||||
OutputColumnModel *model = new OutputColumnModel(columns, this);
|
||||
|
||||
ui->goodsQuantityPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_quantity"]["position"]);
|
||||
ui->goodsQuantityAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_quantity"]["name"]));
|
||||
ui->outputOptionsListView->setModel(model);
|
||||
|
||||
ui->goodsNetWeightPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]);
|
||||
ui->goodsNetWeightAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_net_weight"]["name"]));
|
||||
for (unsigned short i = 0; i < 6; i ++)
|
||||
columns->push_back(OutputColumn(tr("Кто здесь?"), ColumnType::date));
|
||||
|
||||
ui->goodsTotalPositionSpin->setValue(this->settings.get_all_settings()["output_order"]["goods_total"]["position"]);
|
||||
ui->goodsTotalAliasEdit->setText(QString::fromStdString(this->settings.get_all_settings()["output_order"]["goods_total"]["name"]));
|
||||
for (auto &column : column_names) {
|
||||
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->printTotalCheckBox->setChecked(this->settings.get_all_settings()["print_total"]);
|
||||
ui->printHeaderCheckBox->setChecked(settings.get_all_settings()["print_header"]);
|
||||
ui->printTotalCheckBox->setChecked(settings.get_all_settings()["print_total"]);
|
||||
|
||||
int currentLanguageIndex = 0;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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(); }
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define SETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <outputcolumn.h>
|
||||
#include <settings/settings.h>
|
||||
|
||||
namespace Ui {
|
||||
@@ -11,28 +12,13 @@ class settingsdialog;
|
||||
class SettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
Settings settings;
|
||||
std::vector<OutputColumn> *columns;
|
||||
|
||||
public:
|
||||
explicit SettingsDialog(QWidget *parent = nullptr);
|
||||
~SettingsDialog();
|
||||
|
||||
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_printHeaderCheckBox_stateChanged(int arg1);
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<translation>Please, zoom to qr code and adjust contrast so that qr code looks sharp</translation>
|
||||
</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>
|
||||
<translation>QR code was not detected on that image. Please edit it again or enter data manually</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="41"/>
|
||||
<location filename="../adjustpicturedialog.cpp" line="44"/>
|
||||
<source>No QR code</source>
|
||||
<translation>No QR code</translation>
|
||||
</message>
|
||||
@@ -70,9 +70,8 @@
|
||||
<translation type="vanished">Store type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Parse</source>
|
||||
<translation>Parse</translation>
|
||||
<translation type="vanished">Parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Preferences</source>
|
||||
@@ -113,7 +112,7 @@
|
||||
<translation type="vanished">0000000000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="322"/>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translatorcomment>FN = Фискальный Номер</translatorcomment>
|
||||
<translation>FN (Fiscal Number)</translation>
|
||||
@@ -133,93 +132,119 @@
|
||||
<translation type="obsolete">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Stop server</source>
|
||||
<translation>Stop server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="167"/>
|
||||
<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>
|
||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="118"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="173"/>
|
||||
<source>or</source>
|
||||
<translation>or</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="141"/>
|
||||
<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>
|
||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="295"/>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translatorcomment>FI = Фискальный Признак</translatorcomment>
|
||||
<translation>FI (Fiscal Identifier)</translation>
|
||||
</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>
|
||||
<translation>Add new check</translation>
|
||||
<translation type="vanished">Add new check</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
||||
<source>Clear</source>
|
||||
<translation>Clear</translation>
|
||||
<translation type="vanished">Clear</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="105"/>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation>Date and time of purchase</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="309"/>
|
||||
<source>Operation type</source>
|
||||
<translation>Operation type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="288"/>
|
||||
<source>Parse an E-Mail</source>
|
||||
<translation>Parse an E-Mail</translation>
|
||||
</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>
|
||||
<translatorcomment>Приход средств</translatorcomment>
|
||||
<translation>Funds income</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="71"/>
|
||||
<source>Funds return</source>
|
||||
<translatorcomment>Возврат средств</translatorcomment>
|
||||
<translation>Funds return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="76"/>
|
||||
<source>Funds spend</source>
|
||||
<translatorcomment>Расход средств</translatorcomment>
|
||||
<translation>Funds spend</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="81"/>
|
||||
<source>Spends return</source>
|
||||
<translatorcomment>Возврат расхода</translatorcomment>
|
||||
<translation>Spends return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="144"/>
|
||||
<source>Checks to parse</source>
|
||||
<translation>Checks to parse</translation>
|
||||
</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>
|
||||
<translation>Settings</translation>
|
||||
</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>
|
||||
<translation>Total</translation>
|
||||
</message>
|
||||
@@ -228,75 +253,95 @@
|
||||
<translation type="vanished">checks parser</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="101"/>
|
||||
<location filename="../mainwindow.cpp" line="106"/>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation>QR code for binaryeye to connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="102"/>
|
||||
<location filename="../mainwindow.cpp" line="107"/>
|
||||
<source>I've scanned</source>
|
||||
<translation>I've scanned</translation>
|
||||
</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>
|
||||
<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>
|
||||
<location filename="../mainwindow.cpp" line="110"/>
|
||||
<location filename="../mainwindow.cpp" line="115"/>
|
||||
<source>Could not start http server.</source>
|
||||
<translation>Could not start http server.</translation>
|
||||
</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>
|
||||
<translation>Selected image: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="187"/>
|
||||
<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>
|
||||
<location filename="../mainwindow.cpp" line="189"/>
|
||||
<source>Under development</source>
|
||||
<translation>Under development</translation>
|
||||
<translation type="vanished">Under development</translation>
|
||||
</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>
|
||||
<translation type="vanished">Please, add check(s) to parse</translation>
|
||||
<translation>Please, add check(s) to parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="188"/>
|
||||
<source>No checks to parse</source>
|
||||
<translation type="vanished">No checks to parse</translation>
|
||||
<translation>No checks to parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="287"/>
|
||||
<location filename="../mainwindow.cpp" line="255"/>
|
||||
<source>Captcha was not solved correctly!</source>
|
||||
<translation>Captcha was not solved correctly!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="289"/>
|
||||
<location filename="../mainwindow.cpp" line="257"/>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation>Captcha is incorrect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="294"/>
|
||||
<location filename="../mainwindow.cpp" line="261"/>
|
||||
<source>Internal server error. Please, try again later.</source>
|
||||
<translation>Internal server error. Please, try again later.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="296"/>
|
||||
<location filename="../mainwindow.cpp" line="263"/>
|
||||
<source>Internal server error</source>
|
||||
<translation>Internal server error</translation>
|
||||
</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>
|
||||
<translation>Check not found. Please, ensure correctness of entered data.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="303"/>
|
||||
<location filename="../mainwindow.cpp" line="269"/>
|
||||
<source>Check was not found</source>
|
||||
<translation>Check was not found</translation>
|
||||
</message>
|
||||
@@ -309,14 +354,12 @@
|
||||
<translation type="vanished">Error in parsing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="147"/>
|
||||
<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>
|
||||
<location filename="../mainwindow.cpp" line="149"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation>Picture was not selected</translation>
|
||||
<translation type="vanished">Picture was not selected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture to scan</source>
|
||||
@@ -532,43 +575,33 @@
|
||||
<translation>Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="76"/>
|
||||
<source>Print header</source>
|
||||
<translation>Print header</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="24"/>
|
||||
<source>Date</source>
|
||||
<translation>Date</translation>
|
||||
<translation type="vanished">Date</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="25"/>
|
||||
<source>Goods name</source>
|
||||
<translation>Goods name</translation>
|
||||
<translation type="vanished">Goods name</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Goods price</source>
|
||||
<translation type="vanished">Goods price</translation>
|
||||
</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>
|
||||
<translation>Goods quantity</translation>
|
||||
<translation type="vanished">Goods quantity</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="28"/>
|
||||
<source>Goods net weight</source>
|
||||
<translation>Goods net weight</translation>
|
||||
<translation type="vanished">Goods net weight</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="29"/>
|
||||
<source>Goods total</source>
|
||||
<translation>Goods total</translation>
|
||||
<translation type="vanished">Goods total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>position</source>
|
||||
@@ -627,11 +660,16 @@
|
||||
<source>Print total</source>
|
||||
<translation>Print total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="37"/>
|
||||
<source>Кто здесь?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="64"/>
|
||||
<location filename="../main.cpp" line="60"/>
|
||||
<source>Using locale: </source>
|
||||
<translation>Using locale: </translation>
|
||||
</message>
|
||||
@@ -639,12 +677,17 @@
|
||||
<context>
|
||||
<name>SettingsDialog</name>
|
||||
<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>
|
||||
<translation>You need to restart program to apply language changes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.cpp" line="135"/>
|
||||
<location filename="../settingsdialog.cpp" line="91"/>
|
||||
<source>Restart required</source>
|
||||
<translation>Restart required</translation>
|
||||
</message>
|
||||
@@ -675,41 +718,37 @@
|
||||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
||||
<source>Goods name position</source>
|
||||
<translation>Goods name position</translation>
|
||||
<translation type="vanished">Goods name position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
||||
<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>
|
||||
<location filename="../scenes/settingsdialog.ui" line="124"/>
|
||||
<source>Date name position</source>
|
||||
<translation>Date name position</translation>
|
||||
<translation type="vanished">Date name position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="85"/>
|
||||
<source>Language</source>
|
||||
<translation>Language</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="196"/>
|
||||
<source>Date name alias</source>
|
||||
<translation>Date name alias</translation>
|
||||
<translation type="vanished">Date name alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TextLabel</source>
|
||||
<translation type="vanished">Language</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="38"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="58"/>
|
||||
<source>en_US</source>
|
||||
<translation>en_US</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="63"/>
|
||||
<source>ru_RU</source>
|
||||
<translation>ru_RU</translation>
|
||||
</message>
|
||||
@@ -718,33 +757,29 @@
|
||||
<translation type="vanished">Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="71"/>
|
||||
<source>Print header</source>
|
||||
<translation>Print header</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
||||
<source>Goods net weight alias</source>
|
||||
<translation>Goods net weight alias</translation>
|
||||
<translation type="vanished">Goods net weight alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stores modules url</source>
|
||||
<translation type="vanished">Stores modules url</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
||||
<source>Goods total alias</source>
|
||||
<translation>Goods total alias</translation>
|
||||
<translation type="vanished">Goods total alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
||||
<source>Goods name alias</source>
|
||||
<translation>Goods name alias</translation>
|
||||
<translation type="vanished">Goods name alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
||||
<source>Goods quantity alias</source>
|
||||
<translation>Goods quantity alias</translation>
|
||||
<translation type="vanished">Goods quantity alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stores modules directory</source>
|
||||
@@ -755,31 +790,27 @@
|
||||
<translation type="vanished">OFD modules directory</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
||||
<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>
|
||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
||||
<source>Goods net weight position</source>
|
||||
<translation>Goods net weight position</translation>
|
||||
<translation type="vanished">Goods net weight position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OFD modules url</source>
|
||||
<translation type="vanished">OFD modules url</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
||||
<source>Goods total position</source>
|
||||
<translation>Goods total position</translation>
|
||||
<translation type="vanished">Goods total position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
||||
<source>Goods quantity position</source>
|
||||
<translation>Goods quantity position</translation>
|
||||
<translation type="vanished">Goods quantity position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="50"/>
|
||||
<source>Print total</source>
|
||||
<translation>Print total</translation>
|
||||
</message>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<translation>Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
|
||||
</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>
|
||||
<translation>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="41"/>
|
||||
<location filename="../adjustpicturedialog.cpp" line="44"/>
|
||||
<source>No QR code</source>
|
||||
<translation>QR код не найден</translation>
|
||||
</message>
|
||||
@@ -70,9 +70,8 @@
|
||||
<translation type="vanished">Магазин</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Parse</source>
|
||||
<translation>Парсить</translation>
|
||||
<translation type="vanished">Парсить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Preferences</source>
|
||||
@@ -113,7 +112,7 @@
|
||||
<translation type="vanished">0000000000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="322"/>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translatorcomment>Фискальный Норма</translatorcomment>
|
||||
<translation>ФН</translation>
|
||||
@@ -133,89 +132,107 @@
|
||||
<translation type="obsolete">Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Stop server</source>
|
||||
<translation>Остановить сервер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="167"/>
|
||||
<source>Choose image on your PC</source>
|
||||
<translation>Выбрать изображение на компьютере</translation>
|
||||
<translation type="vanished">Выбрать изображение на компьютере</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="118"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="173"/>
|
||||
<source>or</source>
|
||||
<translation>или</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="141"/>
|
||||
<source>Use your phone as a QR code scanner</source>
|
||||
<translation>Использовать телефон как сканнер QR</translation>
|
||||
<translation type="vanished">Использовать телефон как сканнер QR</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="295"/>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translatorcomment>Фискальный Признак</translatorcomment>
|
||||
<translation>ФП</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="273"/>
|
||||
<source>Add new check</source>
|
||||
<location filename="../scenes/mainwindow.ui" line="329"/>
|
||||
<source>Delete selected</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
||||
<source>Clear</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="105"/>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation>Дата и время покупки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="309"/>
|
||||
<source>Operation type</source>
|
||||
<translation>Тип операции</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="288"/>
|
||||
<source>Parse an E-Mail</source>
|
||||
<translation>Парсить E-Mail</translation>
|
||||
</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>
|
||||
<translation>Приход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="71"/>
|
||||
<source>Funds return</source>
|
||||
<translation>Возврат средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="76"/>
|
||||
<source>Funds spend</source>
|
||||
<translation>Расход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="81"/>
|
||||
<source>Spends return</source>
|
||||
<translation>Возврат расхода</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="144"/>
|
||||
<source>Checks to parse</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation>Настройки</translation>
|
||||
</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>
|
||||
<translation>Итого</translation>
|
||||
</message>
|
||||
@@ -224,67 +241,87 @@
|
||||
<translation type="vanished">Парсер чеков</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="101"/>
|
||||
<location filename="../mainwindow.cpp" line="106"/>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation>QR код для подключения BinaryEye</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="102"/>
|
||||
<location filename="../mainwindow.cpp" line="107"/>
|
||||
<source>I've scanned</source>
|
||||
<translation>Просканировал</translation>
|
||||
</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>
|
||||
<translation>Не смог поднять HTTP сервер. 10 раз подряд случайно выбранный порт был занят. Либо Вам следует бежать за лоттерейным билетом, или в программе баг. Если лотерейный билет не был выигрышным, пожалуйста, сообщите разработчику.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="110"/>
|
||||
<location filename="../mainwindow.cpp" line="115"/>
|
||||
<source>Could not start http server.</source>
|
||||
<translation>Не получилось запустить HTTP сервер.</translation>
|
||||
</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>
|
||||
<translation>Выбранное изображение: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="187"/>
|
||||
<source>This feature is under development. Wait it to appear in next updates.</source>
|
||||
<location filename="../mainwindow.cpp" line="159"/>
|
||||
<source>E-Mail files (*.eml)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="189"/>
|
||||
<source>Under development</source>
|
||||
<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="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>
|
||||
<translation>Капча была решена неверно!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="289"/>
|
||||
<location filename="../mainwindow.cpp" line="257"/>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation>Капча введена неверно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="294"/>
|
||||
<location filename="../mainwindow.cpp" line="261"/>
|
||||
<source>Internal server error. Please, try again later.</source>
|
||||
<translation>Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="296"/>
|
||||
<location filename="../mainwindow.cpp" line="263"/>
|
||||
<source>Internal server error</source>
|
||||
<translation>Внутренняя ошибка сервера</translation>
|
||||
</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>
|
||||
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="303"/>
|
||||
<location filename="../mainwindow.cpp" line="269"/>
|
||||
<source>Check was not found</source>
|
||||
<translation>Чек не найден</translation>
|
||||
</message>
|
||||
@@ -297,14 +334,12 @@
|
||||
<translation type="vanished">Ошибка в парсинге</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="147"/>
|
||||
<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>
|
||||
<location filename="../mainwindow.cpp" line="149"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation>Изображение не было выбрано</translation>
|
||||
<translation type="vanished">Изображение не было выбрано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture to scan</source>
|
||||
@@ -520,38 +555,29 @@
|
||||
<translation>Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="76"/>
|
||||
<source>Print header</source>
|
||||
<translation>Печатать заголовок</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="25"/>
|
||||
<source>Goods name</source>
|
||||
<translation>Имя товара</translation>
|
||||
<translation type="vanished">Имя товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Goods price</source>
|
||||
<translation type="vanished">Цена товара</translation>
|
||||
</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>
|
||||
<translation>Количество товара</translation>
|
||||
<translation type="vanished">Количество товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="28"/>
|
||||
<source>Goods net weight</source>
|
||||
<translation>Масса нетто товара</translation>
|
||||
<translation type="vanished">Масса нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="29"/>
|
||||
<source>Goods total</source>
|
||||
<translation>Всего за товар</translation>
|
||||
<translation type="vanished">Всего за товар</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>position</source>
|
||||
@@ -611,15 +637,15 @@
|
||||
<translation>Печатать Итого</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="24"/>
|
||||
<source>Date</source>
|
||||
<location filename="../outputdialog.cpp" line="37"/>
|
||||
<source>Кто здесь?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="64"/>
|
||||
<location filename="../main.cpp" line="60"/>
|
||||
<source>Using locale: </source>
|
||||
<translation>Использую локаль: </translation>
|
||||
</message>
|
||||
@@ -627,12 +653,17 @@
|
||||
<context>
|
||||
<name>SettingsDialog</name>
|
||||
<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>
|
||||
<translation>Требуется перезагрузить программу, чтобы применить изменения языка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.cpp" line="135"/>
|
||||
<location filename="../settingsdialog.cpp" line="91"/>
|
||||
<source>Restart required</source>
|
||||
<translation>Требуется перезагрузка</translation>
|
||||
</message>
|
||||
@@ -663,41 +694,29 @@
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
||||
<source>Goods name position</source>
|
||||
<translation>Позиция имени товара</translation>
|
||||
<translation type="vanished">Позиция имени товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
||||
<source>Goods price per unit alias</source>
|
||||
<translation>Алиас цены товара</translation>
|
||||
<translation type="vanished">Алиас цены товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="124"/>
|
||||
<source>Date name position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="85"/>
|
||||
<source>Language</source>
|
||||
<translation>Язык</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="196"/>
|
||||
<source>Date name alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TextLabel</source>
|
||||
<translation type="vanished">Язык</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="38"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="58"/>
|
||||
<source>en_US</source>
|
||||
<translation>en_US</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="63"/>
|
||||
<source>ru_RU</source>
|
||||
<translation>ru_RU</translation>
|
||||
</message>
|
||||
@@ -706,33 +725,29 @@
|
||||
<translation type="vanished">Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="71"/>
|
||||
<source>Print header</source>
|
||||
<translation>Печатать заголовок</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
||||
<source>Goods net weight alias</source>
|
||||
<translation>Алиас массы нетто товара</translation>
|
||||
<translation type="vanished">Алиас массы нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stores modules url</source>
|
||||
<translation type="vanished">URL модулей магазина</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
||||
<source>Goods total alias</source>
|
||||
<translation>Алиас всего за продукт</translation>
|
||||
<translation type="vanished">Алиас всего за продукт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
||||
<source>Goods name alias</source>
|
||||
<translation>Алиас имени товара</translation>
|
||||
<translation type="vanished">Алиас имени товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
||||
<source>Goods quantity alias</source>
|
||||
<translation>Алиас количества товара</translation>
|
||||
<translation type="vanished">Алиас количества товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stores modules directory</source>
|
||||
@@ -743,31 +758,27 @@
|
||||
<translation type="vanished">Директория модулей ОФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
||||
<source>Goods price per unit position</source>
|
||||
<translation>Позиция центы товара</translation>
|
||||
<translation type="vanished">Позиция центы товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
||||
<source>Goods net weight position</source>
|
||||
<translation>Позиция массы нетто товара</translation>
|
||||
<translation type="vanished">Позиция массы нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OFD modules url</source>
|
||||
<translation type="vanished">URL модулей ОФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
||||
<source>Goods total position</source>
|
||||
<translation>Позиция всего за товар</translation>
|
||||
<translation type="vanished">Позиция всего за товар</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
||||
<source>Goods quantity position</source>
|
||||
<translation>Позиция количества товара</translation>
|
||||
<translation type="vanished">Позиция количества товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="50"/>
|
||||
<source>Print total</source>
|
||||
<translation>Печатать Итого</translation>
|
||||
</message>
|
||||
|
||||
110
utils/utils.cpp
110
utils/utils.cpp
@@ -1,3 +1,4 @@
|
||||
#include "output/output_options.h"
|
||||
#include <utils/utils.h>
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
# include <arpa/inet.h>
|
||||
@@ -24,6 +25,9 @@
|
||||
#include <boost/regex.hpp>
|
||||
#include <net/net.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
|
||||
std::string get_local_ip_address() {
|
||||
@@ -41,6 +45,7 @@ std::string get_local_ip_address() {
|
||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
std::string value(addressBuffer);
|
||||
//TODO: better way to determine local IP address
|
||||
if (!strncmp(value.c_str(), "192.168", 7)) {
|
||||
return value;
|
||||
}
|
||||
@@ -67,6 +72,26 @@ std::string get_path_relative_to_home(std::string 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>
|
||||
bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
|
||||
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());
|
||||
}
|
||||
|
||||
// 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 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);
|
||||
// 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> result;
|
||||
size_t pos = 0;
|
||||
@@ -152,33 +197,39 @@ std::wstring trim_html_response(std::wstring& check) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_in_html(std::string& html, std::string regex, std::string html_start, std::string html_end) {
|
||||
boost::regex searching_regex(regex);
|
||||
std::vector<std::wstring> find_in_html(std::string& html, std::string regex) {
|
||||
boost::regex searching_regex(regex, boost::match_flag_type::match_single_line);
|
||||
|
||||
std::vector<std::wstring> parsed;
|
||||
for (boost::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
|
||||
it != end; it++) {
|
||||
|
||||
std::wstring found_entry = from_utf8(it->str());
|
||||
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::cout << "Extracted: " << to_utf8(extracted) << std::endl;
|
||||
parsed.push_back(extracted);
|
||||
// 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::wstring extracted = substring_from_to(found_entry, from_utf8(html_start), from_utf8(html_end));
|
||||
// std::cout << "Extracted: " << to_utf8(extracted) << std::endl;
|
||||
// parsed.push_back(extracted);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
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> founds = find_in_html(html, "<div><span>\\d+(\\.|\\,)?\\d{0,3}<\\/span>", "<span>", "<\\/span>");
|
||||
for (auto &found : founds) {
|
||||
std::replace(found.begin(), found.end(), ',', '.');
|
||||
}
|
||||
|
||||
return founds;
|
||||
return find_in_html(html, "(?<=<div><span>)\\d+(\\.|\\,)?\\d{0,3}(?=<\\/span>)");
|
||||
}
|
||||
|
||||
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> founds = find_in_html(html, "X <\\/span><span>\\d+(\\.|,)\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
|
||||
for (auto &found : founds) {
|
||||
std::replace(found.begin(), found.end(), ',', '.');
|
||||
}
|
||||
|
||||
return founds;
|
||||
return find_in_html(html, "(?<=X <\\/span><span>)\\d+(\\.|,)\\d{2}(?=<\\/span>)");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (int i = 0; i < products.size(); i ++) {
|
||||
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 << "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::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]));
|
||||
c.add_goods(goods);
|
||||
}
|
||||
@@ -310,14 +357,13 @@ void generate_qr_code(std::string data) {
|
||||
#endif // ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
std::vector<std::string> read_file(std::string path) {
|
||||
std::ifstream stream(path);
|
||||
std::vector<std::string> lines;
|
||||
std::string buffer;
|
||||
while(getline(stream, buffer)) {
|
||||
lines.push_back(buffer);
|
||||
}
|
||||
stream.close();
|
||||
return lines;
|
||||
std::string read_file(std::string &path) {
|
||||
std::ifstream ifile(path, std::ios::in | std::ios::binary);
|
||||
const unsigned int size = std::filesystem::file_size(path);
|
||||
std::string content(size, '\0');
|
||||
ifile.read(content.data(), size);
|
||||
ifile.close();
|
||||
return content;
|
||||
}
|
||||
#endif // ifdef BUILD_EMAIL_MODE
|
||||
|
||||
|
||||
@@ -3,12 +3,30 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "../check/check.h"
|
||||
#include "output/output_options.h"
|
||||
|
||||
std::string to_utf8(std::wstring wide_string);
|
||||
std::wstring from_utf8(std::string string);
|
||||
|
||||
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>
|
||||
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();
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
std::vector<std::string> read_file(std::string path);
|
||||
std::string read_file(std::string &path);
|
||||
#endif
|
||||
#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 <QObject>
|
||||
#include <outputcolumn.h>
|
||||
#include <QJsonObject>
|
||||
#include <QMimeData>
|
||||
#include <QIODevice>
|
||||
#include <outputcolumn.h>
|
||||
|
||||
OutputColumnModel::OutputColumnModel(std::vector<OutputColumn> *columns, QObject *parent)
|
||||
: columns(columns), QAbstractListModel{parent} { }
|
||||
@@ -139,8 +138,7 @@ bool OutputColumnModel::dropMimeData(const QMimeData *data, Qt::DropAction actio
|
||||
}
|
||||
|
||||
insertRows(row, rows, QModelIndex());
|
||||
for (const OutputColumn &column : newItems)
|
||||
{
|
||||
for (const OutputColumn &column : newItems) {
|
||||
QModelIndex idx = index(row, 0, QModelIndex());
|
||||
setData(idx, QVariant::fromValue(column), 0x102);
|
||||
row++;
|
||||
|
||||
@@ -30,8 +30,8 @@ public:
|
||||
|
||||
QStringList mimeTypes() const override;
|
||||
bool canDropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex&);
|
||||
QMimeData* mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
QMimeData* mimeData(const QModelIndexList &indexes) const override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
};
|
||||
|
||||
#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