Compare commits
81 Commits
alpha-0.0.
...
b67d575645
| Author | SHA1 | Date | |
|---|---|---|---|
| b67d575645 | |||
| 33ea7ff459 | |||
| f32da712e8 | |||
| 463edd3df9 | |||
| 86a11faf70 | |||
| 6706cbec45 | |||
| 5f4a86cee8 | |||
| a73bf1fc53 | |||
| 7275892b04 | |||
| e749c21a61 | |||
| f483c97935 | |||
| dda40e11b8 | |||
| 7822984ff0 | |||
| c17af59358 | |||
| 6b815dbe0a | |||
| 5600e03ce1 | |||
| 7d71cb016a | |||
| 7a52905cff | |||
| 3b26dbc29d | |||
| 754700edfb | |||
| 9094d3c997 | |||
| 1b32774e55 | |||
| d17695a7fa | |||
| e58d6068e0 | |||
| 80e9397e01 | |||
| ba8fc1079a | |||
| e49a078c80 | |||
| 64f081b522 | |||
| b19c92079d | |||
| a342d78df7 | |||
| 59315f9445 | |||
| d83f106a91 | |||
| 1fa69c3a69 | |||
| 89afe836be | |||
| 51d8600be0 | |||
| 229a6bcc9e | |||
| 17fd9da3e6 | |||
| 33f819a09d | |||
| a87869ca7f | |||
| b57a542161 | |||
| b966d7fcf5 | |||
| cb8041c928 | |||
| 5209b7bf22 | |||
| b86514b030 | |||
| 31f4ca26fb | |||
| 993cf4d69c | |||
| 487707ba3e | |||
| 3dbc85f929 | |||
| 2b2127e3b5 | |||
| f507ec8d67 | |||
| 453f907bfa | |||
| 39c4bfb2fd | |||
| 33b54fb475 | |||
| b305fba2fd | |||
| 1ae724f925 | |||
| 4c7a25c53e | |||
| cb3d6c2a3f | |||
| 4f75e88b69 | |||
| 29b9b58759 | |||
| df522f07f7 | |||
| d41accd111 | |||
| 957ccc9946 | |||
| 7d42cbd111 | |||
| 05563a5f82 | |||
| 5ca16a4f76 | |||
| e60aafd653 | |||
| a10271e595 | |||
| 3a2901b49c | |||
| 22922aecaa | |||
| baa8ae6e65 | |||
| 2ebcf68838 | |||
| b135f8a94d | |||
| 7290769750 | |||
| 64da9e9327 | |||
| b7b7c054d3 | |||
| c478dcf8d4 | |||
| 7959bc5492 | |||
| 031c1d5792 | |||
| cca20abbfd | |||
| 988dc0e133 | |||
| 888f658a9c |
5
.gitignore
vendored
@@ -35,6 +35,8 @@ Thumbs.db
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
*.qrc.depends
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
CMakeLists.txt.user*
|
||||
@@ -121,3 +123,6 @@ checks-parser
|
||||
|
||||
deploy/appimage/AppDir/usr/share/doc/
|
||||
deploy/appimage/AppDir/usr/share/
|
||||
*.deb
|
||||
|
||||
binaries
|
||||
|
||||
267
CMakeLists.txt
@@ -1,97 +1,183 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(checks-parser VERSION 0.1 LANGUAGES CXX)
|
||||
project(checks-parser VERSION 0.0.4 LANGUAGES CXX)
|
||||
|
||||
option(BUILD_TRANSLATIONS "Build translations?" ON)
|
||||
option(BUILD_EMAIL_MODE "Build email mode?" ON)
|
||||
option(BUILD_OFD_LOCAL_QR_SCAN "Build OFDs' local qr scanner?" ON)
|
||||
option(BUILD_OFD_BINARYEYE_SCAN "Build OFDs' binaryeye scanner?" ON)
|
||||
|
||||
if (NOT (BUILD_EMAIL_MODE OR BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN))
|
||||
message(FATAL_ERROR "You must specify at least one of the modes of data input!")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (BUILD_TRANSLATIONS)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
add_definitions(-DBUILD_TRANSLATIONS)
|
||||
else()
|
||||
add_compile_definitions(BUILD_TRANSLATIONS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
add_definitions(-DBUILD_OFD_MODE)
|
||||
else()
|
||||
add_compile_definitions(BUILD_OFD_MODE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_EMAIL_MODE)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
add_definitions(-DBUILD_EMAIL_MODE)
|
||||
else()
|
||||
add_compile_definitions(BUILD_EMAIL_MODE)
|
||||
endif()
|
||||
endif()
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
add_definitions(-DBUILD_OFD_LOCAL_QR_SCAN)
|
||||
else()
|
||||
add_compile_definitions(BUILD_OFD_LOCAL_QR_SCAN)
|
||||
endif()
|
||||
endif()
|
||||
if (BUILD_OFD_BINARYEYE_SCAN)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
add_definitions(-DBUILD_OFD_BINARYEYE_SCAN)
|
||||
else()
|
||||
add_compile_definitions(BUILD_OFD_BINARYEYE_SCAN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
SET(CMAKE_BUILD_TYPE Debug)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTORCC OFF)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS Designer)
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS scenes)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt5 COMPONENTS LinguistTools)
|
||||
find_package(Qt6Core REQUIRED)
|
||||
if (BUILD_TRANSLATIONS)
|
||||
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
|
||||
endif()
|
||||
find_package(Qt6Gui REQUIRED)
|
||||
find_package(Qt6Widgets REQUIRED)
|
||||
|
||||
set(TRANSLATION_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h scenes/mainwindow.ui
|
||||
outputdialog.h outputdialog.cpp scenes/outputdialog.ui
|
||||
settingsdialog.h settingsdialog.cpp scenes/settingsdialog.ui
|
||||
)
|
||||
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
list(APPEND TRANSLATION_SOURCES adjustpicturedialog.h adjustpicturedialog.cpp scenes/adjustpicturedialog.ui)
|
||||
endif()
|
||||
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN)
|
||||
list(APPEND TRANSLATION_SOURCES solvecaptchadialog.h solvecaptchadialog.cpp scenes/solvecaptchadialog.ui)
|
||||
endif()
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
mainwindow.ui
|
||||
goods/goods.h goods/goods.cpp
|
||||
check/check.h check/check.cpp
|
||||
|
||||
# Add other source files here that contain translatable strings
|
||||
output/output_options.h output/output_options.cpp
|
||||
|
||||
utils/utils.h utils/utils.cpp
|
||||
|
||||
net/net.h net/net.cpp
|
||||
settings/settings.h settings/settings.cpp
|
||||
|
||||
|
||||
widgets/checklistviewwidget.h widgets/checklistviewwidget.cpp
|
||||
widgets/outputcolumn.h widgets/outputcolumn.cpp
|
||||
widgets/outputcolumnmodel.h widgets/outputcolumnmodel.cpp
|
||||
|
||||
${TRANSLATION_SOURCES}
|
||||
)
|
||||
|
||||
# Specify the UI files and source files for translation
|
||||
set(TRANSLATION_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h mainwindow.ui
|
||||
outputdialog.cpp outputdialog.h outputdialog.ui
|
||||
settingsdialog.cpp settingsdialog.h settingsdialog.ui
|
||||
solvecaptchadialog.cpp solvecaptchadialog.h solvecaptchadialog.ui
|
||||
adjustpicturedialog.cpp adjustpicturedialog.h adjustpicturedialog.ui
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
list(APPEND PROJECT_SOURCES image_redactor/imageredactor.h image_redactor/imageredactor.cpp)
|
||||
endif()
|
||||
|
||||
# Add other .cpp or .ui files that need translation here
|
||||
)
|
||||
if (BUILD_OFD_BINARYEYE_SCAN OR BUILD_OFD_LOCAL_QR_SCAN)
|
||||
list(APPEND PROJECT_SOURCES exceptions/ofdrequestexception.h exceptions/ofdrequestexception.cpp)
|
||||
endif()
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(checks-parser
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
if (BUILD_OFD_BINARYEYE_SCAN)
|
||||
list(APPEND PROJECT_SOURCES http_server/http_server.h http_server/http_server.cpp)
|
||||
endif()
|
||||
|
||||
if (BUILD_EMAIL_MODE)
|
||||
# list(APPEND PROJECT_SOURCES email_parser/emailparser.h email_parser/emailparser.cpp)
|
||||
list(APPEND PROJECT_SOURCES utils/base64.h utils/base64.cpp)
|
||||
endif()
|
||||
|
||||
if (BUILD_TRANSLATIONS)
|
||||
|
||||
set(TS_FILES
|
||||
translations/en_US.ts
|
||||
translations/ru_RU.ts
|
||||
)
|
||||
|
||||
# Generate translation files for Qt 6
|
||||
qt_add_translation(TRANSLATIONS "${TRANSLATION_SOURCES}")
|
||||
qt_create_translation(QM_FILES "${TRANSLATION_SOURCES}" ${TS_FILES})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/translations.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc COPYONLY)
|
||||
qt_add_resources(TRANSLATIONQRC ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
|
||||
add_custom_target(translations ALL DEPENDS ${QM_FILES})
|
||||
add_custom_target(resources ALL DEPENDS ${TRANSLATIONQRC})
|
||||
add_dependencies(resources translations)
|
||||
endif()
|
||||
|
||||
# Media QRC
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/media.qrc ${CMAKE_CURRENT_BINARY_DIR}/media.qrc COPYONLY)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
qt_add_resources(MEDIAQRC ${CMAKE_CURRENT_BINARY_DIR}/media.qrc)
|
||||
add_custom_target(mediaresource ALL DEPENDS ${MEDIAQRC})
|
||||
|
||||
#Scenes QRC
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scenes.qrc ${CMAKE_CURRENT_BINARY_DIR}/scenes.qrc COPYONLY)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/scenes DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
qt_add_resources(SCENESQRC ${CMAKE_CURRENT_BINARY_DIR}/scenes.qrc)
|
||||
add_custom_target(scenessource ALL DEPENDS ${SCENESQRC})
|
||||
|
||||
set(SOURCES "")
|
||||
|
||||
list(APPEND SOURCES ${MEDIAQRC})
|
||||
list(APPEND SOURCES ${SCENESQRC})
|
||||
|
||||
if (BUILD_TRANSLATIONS)
|
||||
list(APPEND SOURCES ${TRANSLATIONQRC})
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
add_library(checks-parser SHARED
|
||||
${PROJECT_SOURCES}
|
||||
${SOURCES}
|
||||
)
|
||||
else()
|
||||
if(ANDROID)
|
||||
add_library(checks-parser SHARED
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
||||
else()
|
||||
# Generate translation files for Qt 5
|
||||
# QT5_ADD_TRANSLATION()
|
||||
qt5_create_translation(QM_FILES "${TRANSLATION_SOURCES}" translations/en_US.ts translations/ru_RU.ts)
|
||||
add_executable(checks-parser
|
||||
${PROJECT_SOURCES}
|
||||
goods/goods.h goods/goods.cpp
|
||||
check/check.h check/check.cpp
|
||||
parser/parser.h parser/parser.cpp
|
||||
parser/module.h parser/module.cpp
|
||||
|
||||
outputdialog.h outputdialog.cpp outputdialog.ui
|
||||
output/output_options.h output/output_options.cpp
|
||||
|
||||
utils/utils.h utils/utils.cpp
|
||||
image/checkimage.h image/checkimage.cpp
|
||||
net/net.h net/net.cpp
|
||||
settings/settings.h settings/settings.cpp
|
||||
settingsdialog.h settingsdialog.cpp settingsdialog.ui
|
||||
adjustpicturedialog.h adjustpicturedialog.cpp adjustpicturedialog.ui
|
||||
image_redactor/imageredactor.h image_redactor/imageredactor.cpp
|
||||
solvecaptchadialog.h solvecaptchadialog.cpp solvecaptchadialog.ui
|
||||
exceptions/ofdrequestexception.h exceptions/ofdrequestexception.cpp
|
||||
${QM_FILES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
# configure_file(translations.qrc ${CMAKE_BINARY_DIR} COPYONLY)
|
||||
# QT5_ADD_TRANSLATION(TRANSLATIONS ${CMAKE_SOURCE_DIR} translations/en_US.ts)
|
||||
endif()
|
||||
add_executable(checks-parser
|
||||
${PROJECT_SOURCES}
|
||||
${SOURCES}
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(checks-parser PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
target_link_libraries(checks-parser PRIVATE Qt6::Widgets)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.checks-parser)
|
||||
target_include_directories(checks-parser PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/widgets)
|
||||
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
target_include_directories(checks-parser PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/image_redactor)
|
||||
endif()
|
||||
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER org.foxarmy.checks-parser)
|
||||
|
||||
set_target_properties(checks-parser PROPERTIES
|
||||
${BUNDLE_ID_OPTION}
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
@@ -107,17 +193,44 @@ install(TARGETS checks-parser
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(checks-parser)
|
||||
if(WIN32)
|
||||
#????
|
||||
set(OpenCV_DIR /usr/local/lib/cmake/opencv4)
|
||||
endif()
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
if (BUILD_OFD_BINARYEYE_SCAN)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(QRENCODE REQUIRED libqrencode)
|
||||
include_directories(${QRENCODE_INCLUDE_DIRS})
|
||||
link_directories(${QRENCODE_LIBRARY_DIRS})
|
||||
target_link_libraries(checks-parser PRIVATE ${QRENCODE_LIBRARIES})
|
||||
endif()
|
||||
if (BUILD_OFD_LOCAL_QR_SCAN)
|
||||
target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||
endif()
|
||||
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||
target_link_libraries(checks-parser PRIVATE -ltesseract)
|
||||
target_link_libraries(checks-parser PRIVATE -lcurl)
|
||||
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS} )
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 3.30)
|
||||
find_package(Boost 1.45.0 REQUIRED COMPONENTS regex)
|
||||
else()
|
||||
find_package(Boost 1.45.0 CONFIG REQUIRED COMPONENTS regex)
|
||||
endif()
|
||||
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)
|
||||
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS})
|
||||
target_include_directories(checks-parser PUBLIC ${OpenCV_INCLUDE_DIRS})
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
endif()
|
||||
|
||||
# if (BUILD_EMAIL_MODE)
|
||||
# find_package(vmime REQUIRED)
|
||||
# target_link_libraries(checks-parser PRIVATE vmime)
|
||||
# endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
|
||||
target_link_libraries(checks-parser PRIVATE -lstdc++fs)
|
||||
endif()
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(checks-parser VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS Designer)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
mainwindow.ui
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(checks-parser
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
||||
SET (LANGUAGES rus eng)
|
||||
SET (TRANSLATIONS_PATH "./translations")
|
||||
|
||||
foreach (LANGUAGE ${LANGUAGES})
|
||||
set (TS ${TRANSLATIONS_PATH}/${LANGUAGE}.ts)
|
||||
set (QM ${TRANSLATIONS_PATH}/${LANGUAGE}.qm)
|
||||
set (TRANSLATIONS ${TRANSLATIONS} ${TS})
|
||||
set (TRANSLATIONS_BINARY ${TRANSLATIONS_BINARY} ${QM})
|
||||
add_custom_command(
|
||||
OUTPUT ${QM}
|
||||
COMMAND ${QT_LRELEASE_EXECUTABLE} ${TS}
|
||||
MAIN_DEPENDENCY ${TS}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} translations/english.ts)
|
||||
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET checks-parser APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||
else()
|
||||
if(ANDROID)
|
||||
add_library(checks-parser SHARED
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||
else()
|
||||
add_executable(checks-parser
|
||||
${PROJECT_SOURCES}
|
||||
goods/goods.h goods/goods.cpp
|
||||
check/check.h check/check.cpp
|
||||
parser/parser.h parser/parser.cpp
|
||||
parser/module.h parser/module.cpp
|
||||
|
||||
outputdialog.h outputdialog.cpp outputdialog.ui
|
||||
output/output_options.h output/output_options.cpp
|
||||
|
||||
utils/utils.h utils/utils.cpp
|
||||
image/checkimage.h image/checkimage.cpp
|
||||
net/net.h net/net.cpp
|
||||
settings/settings.h settings/settings.cpp
|
||||
settingsdialog.h settingsdialog.cpp settingsdialog.ui
|
||||
adjustpicturedialog.h adjustpicturedialog.cpp adjustpicturedialog.ui
|
||||
imageview/imageview.h imageview/imageview.cpp
|
||||
image_redactor/imageredactor.h image_redactor/imageredactor.cpp
|
||||
solvecaptchadialog.h solvecaptchadialog.cpp solvecaptchadialog.ui
|
||||
exceptions/ofdrequestexception.h exceptions/ofdrequestexception.cpp
|
||||
${TRANSLATIONS}
|
||||
${QM_FILES}
|
||||
${QM}
|
||||
${TS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_target(translations DEPENDS ${QM_FILES})
|
||||
add_dependencies(checks-parser translations)
|
||||
|
||||
target_link_libraries(checks-parser PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.checks-parser)
|
||||
endif()
|
||||
set_target_properties(checks-parser PROPERTIES
|
||||
${BUNDLE_ID_OPTION}
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS checks-parser
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(checks-parser)
|
||||
endif()
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
target_link_libraries(checks-parser PRIVATE -lzbar)
|
||||
target_link_libraries(checks-parser PRIVATE -ltesseract)
|
||||
target_link_libraries(checks-parser PRIVATE -lcurl)
|
||||
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS} )
|
||||
39
README.md
@@ -1,16 +1,19 @@
|
||||
-->[Русская версия](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](#Checks-from-different-countries)
|
||||
To know why, see [this section](https://git.foxarmy.org/leca/checks-parser#checks-from-different-countries)
|
||||
|
||||
# Usage
|
||||
For more detailed description, please, refer to [the wiki](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BEN%5D)
|
||||
|
||||
### 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.)
|
||||
* 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 a picture of a check. Be sure to make the image straight and sharp. OCR is not a magic wand :(
|
||||
* Via QrCode on check (OFD (ОФД, Оператор Фискальных Данных in Russian)).
|
||||
* 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.
|
||||
@@ -20,21 +23,24 @@ To export, you need to specify an output file path and, if you wish, you can cha
|
||||
# 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
|
||||
* zbar
|
||||
* curl
|
||||
* nlohmann-json
|
||||
* qt5
|
||||
* vtk
|
||||
* 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
|
||||
##### 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 /shrug
|
||||
I recommend using aur helper (I use yay) to install dependencies. Or, if you're masochist, you can build all by yourself ¯\\\_(ツ)\_/¯
|
||||
```
|
||||
#Install dependencies
|
||||
yay -S sudo cmake git coreutils base-devel eigen qt5-base mbedtls gtkglext opencv opencv2 zbar nlohmann-json tesseract tesseract-data-rus vtk
|
||||
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract qrencode boost
|
||||
#Install a language package for OCR. Replace ``LANG` to your language. For example, ``tesseract-data-rus`` for russian language
|
||||
yay -S tesseract-data-LANG
|
||||
#Clone and compile an app
|
||||
git clone https://git.foxarmy.org/leca/checks-parser
|
||||
cd checks-parser
|
||||
@@ -48,9 +54,9 @@ In debian-based distributions most, but not every, package names are the same.
|
||||
|
||||
Installation of dependencies for different debian-based distros:
|
||||
###### Ubuntu 18.04
|
||||
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libtesseract-dev```
|
||||
```apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libtesseract-dev libqrencode-dev 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```
|
||||
```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```
|
||||
|
||||
Next steps are identical for every debian-based distro
|
||||
```
|
||||
@@ -64,12 +70,20 @@ sudo make install
|
||||
```
|
||||
|
||||
### Windows
|
||||
Maybe
|
||||
See [Precompiled binaries](https://git.foxarmy.org/leca/checks-parser#precompiled-binaries)
|
||||
### 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
|
||||
I plan to make precompiled binaries for Linux and Windows. Maybe I will put it on AUR. I also think that I will be making an AppImage
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
# Contribution
|
||||
|
||||
@@ -79,11 +93,12 @@ If you want to contribute to the project, you can do it by some of the following
|
||||
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
|
||||
|
||||
If you have found a bug, or want to suggest a feature - don't hesitate to open an issue / PR!
|
||||
If you have found a bug, or want to suggest a feature - don't hesitate to open an issue / a PR!
|
||||
|
||||
## 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
|
||||
|
||||
```XMR 45ZjyH5YWdRfKxLoKEBYaiHUTcP5Z8Gv64QQxmabbooPAa7KPBxZLmqft5ohKXn5VpHiVj1x9JKCcAcAjdu9jA8b5N8XqR7```
|
||||
|
||||
105
README.ru.md
Normal file
@@ -0,0 +1,105 @@
|
||||
-->[English version](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.md)<--
|
||||
|
||||
# Чек парсер
|
||||
Чек парсер - это приложение, позволяющее доставать содержимое чека и переводить его в .csv файлы.
|
||||
|
||||
!!!НА ДАННЫЙ МОМЕНТ ПОДДЕРЖИВАЮТСЯ ТОЛЬКО РУССКИЕ ЧЕКИ!!!
|
||||
Чтобы узнать почему [смотрите здесь](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md#checks-from-different-countries)
|
||||
|
||||
# Пользование
|
||||
Для более детального описания, пожалуйста, обратитесь к [вики](https://git.foxarmy.org/leca/checks-parser/wiki/Description-%5BRU%5D)
|
||||
|
||||
### Ввод данных
|
||||
Доступны следующие способы ввода данных:
|
||||
* Через изображениие (используется OCR(Optical Character Recognition, Оптическое распознавание символов), чтобы прочитать содержимое чека. Изображение чека должно быть контрастным и выровненным (текст обязан быть перпендикулярным к границам изображения) хорошо, чтобы нормально прочитаться. OCR - не волшебная палочка :(
|
||||
* Через простой текст, скопированный из эл. письма. Скопируйте и вставьте текст с вашего письма, выберите подходящий магазин (автодетект в планах!) и парсите.
|
||||
* Через QRCode на чеке (этот метод запрашивает данные у ОФД (Оператор Фискальных Данных), в данном конкретном случае, к ofd.ru).
|
||||
|
||||
### Вывод данных
|
||||
На начальном этапе разработки программы, Я задумывался о 3-х или более форматов вывода: csv, xlsx и ods. Но, по мере разработки, я понял, что большинство современных табличных процессоров (электронных таблиц) способны импортировать в себя csv гораздо лучше, чем смог бы написать я сам. Так что я решил не делать вывод во все остальные форматы, кроме csv.
|
||||
|
||||
Чтобы экспортировать вам нужно: указать путь до файла, если вы желаете, вы можете изменить порядок и/или переименовать (алиасы) столбцы, выбрать печатать или не печатать заголовок (алиасы столбцов) и "итого".
|
||||
|
||||
# Установка
|
||||
## Сборка из исходников
|
||||
В целом, вам нужно установить следующие зависимости, чтобы собрать приложение (я предполагаю, что вы уже имеете на системе базовые пакеты вроде cmake, make, gcc, git и так далее):
|
||||
* boost
|
||||
* tesseract (также вам нужно будет установить языковой пакет для него, например tesseract-data-rus на Arch Linux или tesseract-ocr-rus на Debian Linux.)
|
||||
* opencv
|
||||
* zbar
|
||||
* curl
|
||||
* nlohmann-json
|
||||
* qt5
|
||||
* qrencode
|
||||
|
||||
Пожалуйста, не стесняйтесь и открывайте issue, если вы не можете собрать приложение. Я помогу вам, и если вы собираете приложение на дистрибутиве, который здесь не перечислен, как только мы решим вашу проблему, я добавлю новый дистрибутив в этот список!
|
||||
|
||||
### Linux
|
||||
##### Arch Linux и ответвления
|
||||
Я рекомендую использовать помощник для АУРа (я использую yay) чтобы установить зависимости. Или, если вы мазохист, можете собрать все зависимости ручками ¯\\\_(ツ)\_/¯
|
||||
```
|
||||
#Установка зависимостей
|
||||
yay -S base-devel qt5-base opencv zbar nlohmann-json tesseract qrencode boost
|
||||
#Установка языкового пакета для OCR. Замените ``LANG` на желаемый язык. Например, ``tesseract-data-rus`` для русского языка
|
||||
yay -S tesseract-data-LANG
|
||||
#Загрузка исходгого кода и сборка приложения
|
||||
git clone https://git.foxarmy.org/leca/checks-parser
|
||||
cd checks-parser
|
||||
cmake .
|
||||
make -j{nproc}
|
||||
#Если вы хотите скопировать запускной файл в свою систему, исполните:
|
||||
sudo make install
|
||||
```
|
||||
##### Debian и ответвления
|
||||
В debian и ответвлениях большинство, но не все, имена пакетов одинаковы.
|
||||
|
||||
Установка зависимостей для различных debian дистрибутивов:
|
||||
###### 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 (проверил только 6), Debian (проверил только 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```
|
||||
|
||||
Следующие шаги идеинтичны для всех дистрибутивов, основанных на debian:
|
||||
```
|
||||
#Загрузка исходного кода и сборка приложения
|
||||
git clone https://git.foxarmy.org/leca/checks-parser
|
||||
cd checks-parser
|
||||
cmake .
|
||||
make -j{nproc}
|
||||
#Если вы хотите скопировать запускной файл в свою систему, исполните:
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Windows
|
||||
Смотрите [бинарники](https://git.foxarmy.org/leca/checks-parser/src/branch/master/README.ru.md#бинарники)
|
||||
### Mac OS
|
||||
Скорее всего нет, у меня нет ни времени, ни желания, ни устройства. Но если вы можете собирать программу на Mac OS, я буду рад, если вы поможете. Пожалуйста, свяжитесь со мной, если можете!
|
||||
|
||||
## Бинарники
|
||||
На текущий момент я опубликовал программу в [АУР](https://aur.archlinux.org/packages/checks-parser-git).
|
||||
|
||||
Каждый релиз будет содержать AppImage и арчёвский tarball. Я работаю над бинарниками для Windows и .deb пакетами. Ожидайте их в следующих релизах!
|
||||
|
||||
# Особое спасибо
|
||||
|
||||
HyperFlint (@hyperflint:foxarmy.org) - за гениальную идею использовать ОФД и огромную помощь в подготовке проекта к релизу!
|
||||
|
||||
https://check.ofd.ru - за способ вытаскивать данные о чеках из ФНС.
|
||||
|
||||
# Помощь
|
||||
|
||||
Если вы хотите помочь проекту, вы можете сделать это следующими способами:
|
||||
## Чеки из других стран
|
||||
|
||||
Я живу в России и знаком только с местной системой чеков. Если вы живёте в другой стране и хотите помочь мне с поддержкой чеков из Вашей страны - свяжитесь со мной!
|
||||
## Issues и PRs
|
||||
|
||||
Если вы нашли баг или хотите предложить что-то в программу - не стесняйтесь и открывайте issue или PR!
|
||||
|
||||
## Рассказать друзьями
|
||||
|
||||
Вы можете помочь проекту, распространяя программу. Если вы знаете людей, которые ищут подобную программу, пожалуйста, дайте им знать о существовании таковой!
|
||||
|
||||
## Пожертвования
|
||||
|
||||
```XMR 45ZjyH5YWdRfKxLoKEBYaiHUTcP5Z8Gv64QQxmabbooPAa7KPBxZLmqft5ohKXn5VpHiVj1x9JKCcAcAjdu9jA8b5N8XqR7```
|
||||
30
TODO
@@ -1,30 +0,0 @@
|
||||
Complete module "export": [done]
|
||||
make UI; [done]
|
||||
make export to .csv [done]
|
||||
|
||||
Complete module "image-to-text": [done]
|
||||
make UI; [done]
|
||||
make use of tesseract/opencv (https://learnopencv.com/deep-learning-based-text-recognition-ocr-using-tesseract-and-opencv/); [done]
|
||||
|
||||
Add features:
|
||||
autodetect store type
|
||||
auto download of stores modules [done]
|
||||
auto download of ofd modules [done]
|
||||
settings, a window for editing settings. [done]
|
||||
add ability to control contrast and rotation of a check image before passing it to OCR [done]
|
||||
add ability to scan a qr code and request data from ofd.ru [done]
|
||||
add ability to change language from preferences
|
||||
|
||||
Refactor:
|
||||
Get rid of CPR, use libcurl instead [done]
|
||||
|
||||
Build:
|
||||
Write script for AppImage deployment [done]
|
||||
Find out dependencies packet names on different distros [done for arch, ubuntu]
|
||||
Ensure success of building on most popular distros [done for arch, ubuntu]
|
||||
Try to compile it on Windows
|
||||
|
||||
Issues:
|
||||
Captcha is not showing when running in appimage [solved]
|
||||
Stores modules are not being downloaded
|
||||
I need to pack tesseract data for ru, en [solved]
|
||||
@@ -41,7 +41,13 @@ void AdjustPictureDialog::accept() {
|
||||
infoDialog.setWindowTitle(tr("No QR code"));
|
||||
infoDialog.exec();
|
||||
} else {
|
||||
emit decodedData(result);
|
||||
std::map<std::string, std::string> paramsMap;
|
||||
std::vector<std::string> dataSplit = split(result, "&");
|
||||
for (std::string &pair : dataSplit) {
|
||||
std::vector<std::string> values = split(pair, "=");
|
||||
paramsMap.insert(std::pair<std::string, std::string>(values[0], values[1]));
|
||||
}
|
||||
emit decodedData(paramsMap);
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
void computeContrastLookupTable();
|
||||
std::vector<unsigned short> contrastLUT[100];
|
||||
signals:
|
||||
void decodedData(std::string data);
|
||||
void decodedData(std::map<std::string, std::string> data);
|
||||
|
||||
private slots:
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdjustPictureDialog</class>
|
||||
<widget class="QDialog" name="AdjustPictureDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>825</width>
|
||||
<height>497</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>450</x>
|
||||
<y>450</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="contrastSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>460</y>
|
||||
<width>591</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>511</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Please, zoom to qr code and adjust contrast so that qr code looks sharp</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="ImageRedactor" name="graphicsView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>41</y>
|
||||
<width>791</width>
|
||||
<height>391</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>buttonBox</zorder>
|
||||
<zorder>label</zorder>
|
||||
<zorder>contrastSlider</zorder>
|
||||
<zorder>graphicsView</zorder>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ImageRedactor</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>../../image_redactor/imageredactor.h</header>
|
||||
<slots>
|
||||
<slot>slot1()</slot>
|
||||
</slots>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AdjustPictureDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AdjustPictureDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
131
assets/icons/OCR.svg
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="159.62572mm"
|
||||
height="146.77805mm"
|
||||
viewBox="0 0 159.62572 146.77805"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="OCR.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.50000001"
|
||||
inkscape:cx="187"
|
||||
inkscape:cy="261.99999"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer4" />
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="swatch50"
|
||||
inkscape:swatch="solid">
|
||||
<stop
|
||||
style="stop-color:#00b2c3;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop50" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5"
|
||||
id="radialGradient6"
|
||||
cx="178.3111"
|
||||
cy="60.733166"
|
||||
fx="178.3111"
|
||||
fy="60.733166"
|
||||
r="14.328103"
|
||||
gradientTransform="matrix(1,0,0,0.566866,0,26.305599)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="eye"
|
||||
transform="translate(-20.738154,-52.70636)">
|
||||
<ellipse
|
||||
style="display:none;fill:#ffffff;fill-opacity:1;stroke:url(#radialGradient6);stroke-width:0.418956;stroke-opacity:1"
|
||||
id="ellipse5"
|
||||
ry="7.9126363"
|
||||
rx="16.896055"
|
||||
cy="60.733166"
|
||||
cx="178.3111"
|
||||
inkscape:label="inner" />
|
||||
<path
|
||||
id="path48"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 163.03445,62.853096 c -5.5416,0.04533 -10.97868,2.888123 -16.31735,8.383468 -0.12314,0.157876 0.0243,0.318843 0.0243,0.318843 11.50919,11.568278 22.55969,11.493788 33.23673,0 0.18303,-0.169745 0.18055,-0.163774 -0.005,-0.331246 -5.75329,-5.664436 -11.39834,-8.416392 -16.93902,-8.371065 z"
|
||||
inkscape:label="outer"
|
||||
sodipodi:nodetypes="sccccss" />
|
||||
<ellipse
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.0723045"
|
||||
id="ellipse4"
|
||||
inkscape:label="pupil"
|
||||
ry="1.7112623"
|
||||
rx="1.9444314"
|
||||
cy="72.71582"
|
||||
cx="160.92181" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-20.738154,-52.70636)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999"
|
||||
id="rect1"
|
||||
width="101.46883"
|
||||
height="146.27805"
|
||||
x="21.108479"
|
||||
y="52.95636"
|
||||
ry="0"
|
||||
inkscape:label="receipt" />
|
||||
<path
|
||||
style="fill:#ee0000;fill-opacity:0.51545;stroke:none;stroke-width:0.499999"
|
||||
d="M 20.738154,121.46633 160.93664,72.756923 122.6633,120.9805 Z"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:label="scan_ray" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:13.7201px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.16063"
|
||||
x="47.53178"
|
||||
y="66.945511"
|
||||
id="text2"
|
||||
inkscape:label="receipt text"><tspan
|
||||
sodipodi:role="line"
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:2.16064"
|
||||
x="47.53178"
|
||||
y="66.945511"
|
||||
id="tspan3">Receipt</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
181
assets/icons/OFD.svg
Normal file
@@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="180.75754mm"
|
||||
height="172.34297mm"
|
||||
viewBox="0 0 180.75754 172.34297"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="OFD.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0104048"
|
||||
inkscape:cx="241.98222"
|
||||
inkscape:cy="365.20017"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="marker13"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Wide arrow"
|
||||
markerWidth="1"
|
||||
markerHeight="1"
|
||||
viewBox="0 0 1 1"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid">
|
||||
<path
|
||||
style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
|
||||
d="M 3,-3 0,0 3,3"
|
||||
transform="rotate(180,0.125,0)"
|
||||
sodipodi:nodetypes="ccc"
|
||||
id="path13" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="ArrowWide"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Wide arrow"
|
||||
markerWidth="1"
|
||||
markerHeight="1"
|
||||
viewBox="0 0 1 1"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid">
|
||||
<path
|
||||
style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
|
||||
d="M 3,-3 0,0 3,3"
|
||||
transform="rotate(180,0.125,0)"
|
||||
sodipodi:nodetypes="ccc"
|
||||
id="path1" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-12.622354,-8.2059073)">
|
||||
<g
|
||||
id="g3"
|
||||
inkscape:label="laptop"
|
||||
transform="translate(3.1423049,5.2371749)">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
id="rect1"
|
||||
width="83.00206"
|
||||
height="51.927536"
|
||||
x="12.220698"
|
||||
y="109.98628"
|
||||
ry="2.8804462" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:4;stroke-dasharray:none"
|
||||
id="rect2"
|
||||
width="85.730049"
|
||||
height="4.8142142"
|
||||
x="11.480049"
|
||||
y="168.4975"
|
||||
ry="2.4071071" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0;stroke-dasharray:none"
|
||||
id="rect3"
|
||||
width="8.389514"
|
||||
height="1.2071242"
|
||||
x="49.959942"
|
||||
y="161.32069"
|
||||
ry="0.60356212" />
|
||||
</g>
|
||||
<path
|
||||
id="rect5"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.77913;stroke-dasharray:none"
|
||||
d="m 135.00181,57.565658 c -1.57959,0 -2.85099,1.271404 -2.85099,2.850988 v 8.277531 c 0,1.579585 1.2714,2.851506 2.85099,2.851506 h 26.56478 v 3.891752 h -26.56478 c -1.57959,0 -2.85099,1.271404 -2.85099,2.850989 v 8.277531 c 0,1.579586 1.2714,2.851506 2.85099,2.851506 h 26.56478 v 3.575495 h -26.56478 c -1.57959,0 -2.85099,1.27141 -2.85099,2.85099 v 8.277534 c 0,1.57959 1.2714,2.85151 2.85099,2.85151 h 26.56478 v 7.61504 a 4.0588107,4.0588107 0 0 0 -1.20923,0.30489 4.0588107,4.0588107 0 0 0 -2.42569,3.32434 h -23.53344 c -1.66831,0 -3.01119,0.24778 -3.01119,0.55552 0,0.30774 1.34288,0.55552 3.01119,0.55552 h 23.57478 a 4.0588107,4.0588107 0 0 0 0.25477,0.88936 l 0.0114,0.0269 a 4.0588107,4.0588107 0 0 0 5.33611,2.10065 4.0588107,4.0588107 0 0 0 2.38073,-3.01688 h 23.52311 c 1.6683,0 3.01119,-0.24778 3.01119,-0.55552 0,-0.30774 -1.34289,-0.55552 -3.01119,-0.55552 h -23.48177 a 4.0588107,4.0588107 0 0 0 -0.31161,-1.20406 4.0588107,4.0588107 0 0 0 -3.20239,-2.40864 v -7.63157 h 26.2816 c 1.57959,0 2.85099,-1.27192 2.85099,-2.85151 v -8.277534 c 0,-1.57958 -1.2714,-2.85099 -2.85099,-2.85099 h -26.2816 v -3.575495 h 26.2816 c 1.57959,0 2.85099,-1.27192 2.85099,-2.851506 v -8.277531 c 0,-1.579585 -1.2714,-2.850989 -2.85099,-2.850989 h -26.2816 v -3.891752 h 26.2816 c 1.57959,0 2.85099,-1.271921 2.85099,-2.851506 v -8.277561 c 0,-1.579584 -1.2714,-2.850988 -2.85099,-2.850988 z"
|
||||
inkscape:label="OFD" />
|
||||
<path
|
||||
id="path9"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.77913;stroke-dasharray:none"
|
||||
d="m 34.83473,9.0954723 c -1.57959,0 -2.85099,1.2714037 -2.85099,2.8509877 v 8.277531 c 0,1.579585 1.2714,2.851506 2.85099,2.851506 h 26.56478 v 3.891752 H 34.83473 c -1.57959,0 -2.85099,1.271404 -2.85099,2.850989 v 8.277531 c 0,1.579586 1.2714,2.851506 2.85099,2.851506 H 61.39951 V 44.52277 H 34.83473 c -1.57959,0 -2.85099,1.27141 -2.85099,2.85099 v 8.27753 c 0,1.57959 1.2714,2.85151 2.85099,2.85151 h 26.56478 v 7.61504 a 4.0588107,4.0588107 0 0 0 -1.20923,0.30489 4.0588107,4.0588107 0 0 0 -2.42569,3.32434 H 34.23115 c -1.66831,0 -3.01119,0.24778 -3.01119,0.55552 0,0.30774 1.34288,0.55552 3.01119,0.55552 h 23.57478 a 4.0588107,4.0588107 0 0 0 0.25477,0.88936 l 0.0114,0.0269 a 4.0588107,4.0588107 0 0 0 5.33611,2.10065 4.0588107,4.0588107 0 0 0 2.38073,-3.01688 h 23.523106 c 1.6683,0 3.01119,-0.24778 3.01119,-0.55552 0,-0.30774 -1.34289,-0.55552 -3.01119,-0.55552 H 65.83028 A 4.0588107,4.0588107 0 0 0 65.51867,68.54304 4.0588107,4.0588107 0 0 0 62.31628,66.1344 v -7.63157 h 26.281596 c 1.57959,0 2.85099,-1.27192 2.85099,-2.85151 v -8.27753 c 0,-1.57958 -1.2714,-2.85099 -2.85099,-2.85099 H 62.31628 v -3.575495 h 26.281596 c 1.57959,0 2.85099,-1.27192 2.85099,-2.851506 v -8.277531 c 0,-1.579585 -1.2714,-2.850989 -2.85099,-2.850989 H 62.31628 v -3.891752 h 26.281596 c 1.57959,0 2.85099,-1.271921 2.85099,-2.851506 V 11.94646 c 0,-1.579584 -1.2714,-2.8509877 -2.85099,-2.8509877 z"
|
||||
inkscape:label="FNS" />
|
||||
<g
|
||||
id="g13"
|
||||
inkscape:label="two arrows">
|
||||
<path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-start:url(#ArrowWide)"
|
||||
d="m 100.17269,112.57855 25.9227,-13.146507 z"
|
||||
id="path10" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-end:url(#marker13)"
|
||||
d="m 128.92299,105.88982 -25.9227,13.14651 z"
|
||||
id="path10-5" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:13.7103px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;stroke:none;stroke-width:1;stroke-dasharray:none;fill-opacity:1"
|
||||
x="144.47009"
|
||||
y="86.974228"
|
||||
id="text10"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan10"
|
||||
style="stroke-width:1;stroke-dasharray:none;stroke:none;fill:#000000;fill-opacity:1"
|
||||
x="144.47009"
|
||||
y="86.974228">ofd.ru</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:13.3232px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;stroke:none;stroke-width:1;stroke-dasharray:none;fill-opacity:1"
|
||||
x="46.742268"
|
||||
y="38.150463"
|
||||
id="text11"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan11"
|
||||
style="stroke-width:1;stroke-dasharray:none;stroke:none;fill:#000000;fill-opacity:1"
|
||||
x="46.742268"
|
||||
y="38.150463">ФНС</tspan></text>
|
||||
<g
|
||||
id="g15"
|
||||
inkscape:label="two arrows"
|
||||
transform="rotate(45.923414,168.3245,81.037241)">
|
||||
<path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-start:url(#ArrowWide)"
|
||||
d="m 100.17269,112.57855 25.9227,-13.146507 z"
|
||||
id="path14" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-end:url(#marker13)"
|
||||
d="m 128.92299,105.88982 -25.9227,13.14651 z"
|
||||
id="path15" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:11.8523px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;stroke:none;stroke-width:1;stroke-dasharray:none;fill-opacity:1"
|
||||
x="18.578594"
|
||||
y="144.58119"
|
||||
id="text15"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan15"
|
||||
style="stroke-width:1;stroke-dasharray:none;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="18.578594"
|
||||
y="144.58119">Checks parser</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
285
assets/icons/email-text.svg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/icons/icon.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
116
assets/icons/icon.svg
Normal file
|
After Width: | Height: | Size: 649 KiB |
78
assets/icons/settings.svg
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="115.83108mm"
|
||||
height="115.8316mm"
|
||||
viewBox="0 0 115.83108 115.8316"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="settings.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.67565763"
|
||||
inkscape:cx="-76.962055"
|
||||
inkscape:cy="230.88617"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1">
|
||||
<inkscape:grid
|
||||
id="grid4"
|
||||
units="mm"
|
||||
originx="-47.084513"
|
||||
originy="-90.584188"
|
||||
spacingx="0.99999998"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="5"
|
||||
enabled="true"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-47.084512,-90.584183)">
|
||||
<rect
|
||||
style="display:none;fill:#37f500;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:0.075573"
|
||||
id="rect11"
|
||||
width="169.95171"
|
||||
height="169.95171"
|
||||
x="20.362879"
|
||||
y="61.871819"
|
||||
ry="8.590621" />
|
||||
<path
|
||||
id="path10"
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:0.075573"
|
||||
inkscape:label="gear"
|
||||
d="m 75.96901,0.80545601 c -11.155773,5e-7 -3.381873,12.02630099 -10.5755,17.65980599 2.26264,2.865218 2.781879,6.635337 1.536071,9.912568 l 0.842199,0.8422 a 23.648779,23.648779 0 0 1 8.720476,-1.56428 23.648779,23.648779 0 0 1 21.188309,14.268711 23.648779,23.648779 0 0 1 0.433613,17.637966 l 8.483422,8.483422 c 0.001,-1.137526 0.23505,-2.370832 0.79807,-3.730066 4.67012,-11.27469 19.06665,-0.813378 19.06665,-13.017015 0,-12.203637 -14.39653,-1.742323 -19.06665,-13.017014 -4.67013,-11.27469 12.9067,-14.057796 4.27742,-22.68707 -8.62927,-8.6292737 -11.41192,8.948014 -22.686611,4.277884 C 77.711789,15.202439 88.172646,0.80545546 75.96901,0.80545601 Z M 106.5976,68.045849 c -0.009,8.298119 12.66446,11.368041 5.07549,18.957003 -7.59196,7.591964 -10.66109,-5.094535 -18.966554,-5.075493 l 16.355784,16.355783 c 2.70707,2.707048 7.06538,2.707048 9.77243,0 l 4.11408,-4.114084 c 2.70705,-2.707068 2.70705,-7.065327 0,-9.77243 z M 92.706536,81.927359 84.164419,73.385241 A 23.648779,23.648779 0 0 1 54.292034,60.751335 l -0.0678,-0.156519 A 23.648779,23.648779 0 0 1 53.850687,43.071964 l -0.808075,-0.808075 c -3.276856,1.245655 -7.046115,0.726779 -9.911204,-1.53516 -5.635193,7.18452 -17.655256,-0.582996 -17.655256,10.570039 1e-6,12.203638 14.396527,1.742324 19.066657,13.017015 4.67013,11.274689 -12.907157,14.057795 -4.277883,22.687069 8.629275,8.629275 11.412378,-8.948013 22.687069,-4.277883 11.27469,4.670129 0.813378,19.067111 13.017015,19.067111 12.203637,0 1.742778,-14.396981 13.017469,-19.067111 1.355311,-0.561389 2.58526,-0.795009 3.720057,-0.79761 z M 43.131408,40.728729 c 0.530828,-0.676772 1.009354,-1.476346 1.411401,-2.446975 1.382806,-3.338388 0.796238,-5.922366 -0.464097,-8.143995 -5.610754,-0.603322 -9.948354,-8.65044 -17.091514,-10.361651 -0.190642,2.831294 0.790952,5.725383 2.964307,7.898752 l 12.263539,12.263539 c 0.290197,0.290195 0.602358,0.542427 0.916364,0.79033 z m 0.947304,-10.59097 c 2.166221,0.232933 4.522048,-0.640922 7.302705,-3.421578 2.784135,-2.78414 3.656675,-5.142371 3.420669,-7.310895 -5.277946,-2.997957 -8.46522,-9.8825424 -14.53716,-3.810602 -6.074184,6.074185 0.81761,9.261629 3.813786,14.543075 z M 54.802086,19.405286 c 2.222924,1.262656 4.808593,1.851301 8.149909,0.467282 0.968102,-0.401001 1.765816,-0.878149 2.441515,-1.407306 -0.247687,-0.313651 -0.499528,-0.625564 -0.78942,-0.915455 L 52.340551,5.2862683 C 50.34246,3.2881697 47.734568,2.2888648 45.127026,2.2887468 v 4.55e-4 c -0.228937,-1.05e-5 -0.457614,0.017002 -0.686136,0.032305 1.710334,7.1397402 9.75097,11.4767772 10.361196,17.0837792 z M 53.850687,43.071964 84.164419,73.385241 A 23.648779,23.648779 0 0 0 85.382901,72.993034 23.648779,23.648779 0 0 0 98.114178,59.562427 L 67.77178,29.22003 a 23.648779,23.648779 0 0 0 -1.137947,0.350348 23.648779,23.648779 0 0 0 -12.783146,13.501586 z"
|
||||
transform="matrix(1.1357528,0,0,1.1357528,18.717777,90.23726)" />
|
||||
<path
|
||||
id="path11"
|
||||
style="display:none;fill:#f50000;fill-opacity:1;stroke:#000000;stroke-width:1.51285;stroke-opacity:0.075573"
|
||||
d="m 63.089959,81.902523 c -0.311091,-1.7e-5 -0.621755,0.02326 -0.932283,0.04412 3.222959,13.454148 22.996087,19.583657 9.430752,33.149007 -13.565319,13.56532 -19.694039,-6.20771 -33.148136,-9.43075 -0.259055,3.84733 1.074576,7.78001 4.02786,10.73331 l 16.664641,16.66466 c 3.992393,3.99236 9.772658,5.03826 14.71346,3.16006 l 76.122907,76.12203 c 3.67851,3.67851 9.60071,3.67851 13.27922,0 l 5.59023,-5.59023 c 3.6785,-3.67853 3.6785,-9.60066 0,-13.27923 L 92.71658,117.35349 c 1.878195,-4.9408 0.832348,-10.72105 -3.16008,-14.71346 L 72.891859,85.975392 c -2.715126,-2.715126 -6.258615,-4.072783 -9.8019,-4.072937 z"
|
||||
inkscape:label="wrench" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
219
assets/icons/using_binary_eye.svg
Normal file
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="182.87955mm"
|
||||
height="144.54501mm"
|
||||
viewBox="0 0 182.87955 144.54501"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="using_binary_eye.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.5052024"
|
||||
inkscape:cx="555.22302"
|
||||
inkscape:cy="211.7963"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3" /><defs
|
||||
id="defs1"><marker
|
||||
style="overflow:visible"
|
||||
id="ArrowWide"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Wide arrow"
|
||||
markerWidth="1"
|
||||
markerHeight="1"
|
||||
viewBox="0 0 1 1"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid"><path
|
||||
style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
|
||||
d="M 3,-3 0,0 3,3"
|
||||
transform="rotate(180,0.125,0)"
|
||||
sodipodi:nodetypes="ccc"
|
||||
id="path1" /></marker><marker
|
||||
style="overflow:visible"
|
||||
id="marker13"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Wide arrow"
|
||||
markerWidth="1"
|
||||
markerHeight="1"
|
||||
viewBox="0 0 1 1"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid"><path
|
||||
style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
|
||||
d="M 3,-3 0,0 3,3"
|
||||
transform="rotate(180,0.125,0)"
|
||||
sodipodi:nodetypes="ccc"
|
||||
id="path13" /></marker></defs><g
|
||||
inkscape:label="Phone"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-25.853363,-48.893891)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
|
||||
id="rect1"
|
||||
width="57.029922"
|
||||
height="97.02494"
|
||||
x="26.353363"
|
||||
y="95.913963"
|
||||
rx="7.7330093"
|
||||
ry="7.3138995"
|
||||
inkscape:label="border" /><g
|
||||
id="g1837"
|
||||
inkscape:label="binary eye logo"
|
||||
transform="translate(-69.392567,-90.079408)"><circle
|
||||
r="23.283333"
|
||||
cy="234.73807"
|
||||
cx="123.78944"
|
||||
id="circle-1"
|
||||
style="fill:#a6c45f;fill-opacity:1;stroke:none;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><circle
|
||||
style="fill:#b6d46f;fill-opacity:1;stroke:none;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle-2"
|
||||
cx="123.78944"
|
||||
cy="234.20889"
|
||||
r="23.283333" /><path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.12549;fill-rule:nonzero;stroke:none;stroke-width:2.27733;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 124.32389,217.397 c -4.43071,0 -8.86142,1.68857 -12.2391,5.06624 -6.7556,6.75587 -6.7556,17.72311 0,24.47872 l 10.48915,10.48941 c 0.40454,0.0307 0.80989,0.0511 1.21549,0.0609 12.85901,0 23.28333,-10.42432 23.28333,-23.28333 -0.003,-0.42731 -0.0185,-0.85461 -0.0455,-1.28112 l -10.46453,-10.46453 c -3.37767,-3.37767 -7.80838,-5.06624 -12.23883,-5.06624 z"
|
||||
id="path-1" /><circle
|
||||
r="17.155054"
|
||||
cy="234.55074"
|
||||
cx="124.12916"
|
||||
id="circle-3"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><path
|
||||
d="m 136.31216,234.55073 c 0,2.98132 -1.07077,5.71262 -2.84903,7.83008 v -15.66016 c 1.77826,2.11746 2.84903,4.84875 2.84903,7.83008 z m -12.183,12.183 c -0.34925,0 -0.69506,-0.0148 -1.0369,-0.0434 v -24.27922 c 0.34184,-0.0286 0.68765,-0.0434 1.0369,-0.0434 0.34925,0 0.69506,0.0148 1.0369,0.0434 v 24.27922 c -0.34184,0.0286 -0.68765,0.0434 -1.0369,0.0434 z m -12.18301,-12.183 c 0,-2.98133 1.07077,-5.71262 2.84904,-7.83008 v 15.66016 c -1.77827,-2.11746 -2.84904,-4.84876 -2.84904,-7.83008 z m 17.36858,11.02757 c -0.6612,0.31141 -1.35494,0.56515 -2.0746,0.75459 v -23.56432 c 0.71966,0.18944 1.4134,0.44317 2.0746,0.75459 z m -8.29707,0.75459 c -1.51898,-0.40005 -2.92206,-1.08612 -4.14788,-1.99708 v -19.57017 c 1.22582,-0.91096 2.6289,-1.59702 4.14788,-1.99707 z"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle-6" /></g></g><g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="QR code"
|
||||
transform="translate(-30.254583,-85.236427)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
|
||||
id="rect1837"
|
||||
width="14.072319"
|
||||
height="14.072319"
|
||||
x="42.246078"
|
||||
y="85.736427"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.484034;stroke-opacity:1"
|
||||
id="rect1838"
|
||||
width="6.8114772"
|
||||
height="6.8114772"
|
||||
x="45.876503"
|
||||
y="89.366852"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
|
||||
id="rect1839"
|
||||
width="14.072319"
|
||||
height="14.072319"
|
||||
x="62.243584"
|
||||
y="85.736427"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.484034;stroke-opacity:1"
|
||||
id="rect1840"
|
||||
width="6.8114772"
|
||||
height="6.8114772"
|
||||
x="65.874008"
|
||||
y="89.366852"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
|
||||
id="rect1841"
|
||||
width="14.072319"
|
||||
height="14.072319"
|
||||
x="42.246078"
|
||||
y="105.54877"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.484034;stroke-opacity:1"
|
||||
id="rect1842"
|
||||
width="6.8114772"
|
||||
height="6.8114772"
|
||||
x="45.876503"
|
||||
y="109.17919"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.484034;stroke-opacity:1"
|
||||
id="rect1844"
|
||||
width="6.8114772"
|
||||
height="6.8114772"
|
||||
x="61.846733"
|
||||
y="105.52224"
|
||||
rx="0"
|
||||
ry="0" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.484034;stroke-opacity:1"
|
||||
id="rect1845"
|
||||
width="6.8114772"
|
||||
height="6.8114772"
|
||||
x="69.130707"
|
||||
y="112.81159"
|
||||
rx="0"
|
||||
ry="0" /><g
|
||||
id="g3"
|
||||
inkscape:label="laptop"
|
||||
transform="translate(82.762838,125.57409)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1-6"
|
||||
width="83.00206"
|
||||
height="51.927536"
|
||||
x="43.381889"
|
||||
y="35.094681"
|
||||
ry="2.8804462" /><rect
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:4;stroke-dasharray:none"
|
||||
id="rect2"
|
||||
width="85.730049"
|
||||
height="4.8142142"
|
||||
x="42.641239"
|
||||
y="93.605896"
|
||||
ry="2.4071071" /><rect
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0;stroke-dasharray:none"
|
||||
id="rect3"
|
||||
width="8.389514"
|
||||
height="1.2071242"
|
||||
x="81.12114"
|
||||
y="86.429092"
|
||||
ry="0.60356212" /><g
|
||||
id="g1"
|
||||
transform="translate(27.69601,-81.170421)"><text
|
||||
xml:space="preserve"
|
||||
style="font-size:11.8523px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-dasharray:none"
|
||||
x="18.578594"
|
||||
y="144.58119"
|
||||
id="text15"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan15"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-dasharray:none"
|
||||
x="18.578594"
|
||||
y="144.58119">Checks parser</tspan></text></g><g
|
||||
id="g13"
|
||||
inkscape:label="two arrows"
|
||||
transform="rotate(30,151.73824,-82.354999)"><path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-start:url(#ArrowWide)"
|
||||
d="m 100.17269,112.57855 25.9227,-13.146507 z"
|
||||
id="path10" /><path
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:1.5;stroke-dasharray:none;marker-end:url(#marker13)"
|
||||
d="m 128.92299,105.88982 -25.9227,13.14651 z"
|
||||
id="path10-5" /></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 9.9 KiB |
@@ -1,20 +1,92 @@
|
||||
#include "check.h"
|
||||
#include "../goods/goods.h"
|
||||
#include <iostream>
|
||||
|
||||
Check::Check() {}
|
||||
|
||||
void Check::add_goods(Goods goods) { this->goods.push_back(goods); }
|
||||
void Check::add_goods(Goods goods) {
|
||||
this->goods.push_back(goods);
|
||||
this->total = this->calculae_total_price();
|
||||
}
|
||||
|
||||
void Check::add_goods(std::vector<Goods> &goods) {
|
||||
for (auto &g : goods) {
|
||||
this->goods.push_back(g);
|
||||
}
|
||||
this->total = this->calculae_total_price();
|
||||
}
|
||||
|
||||
double Check::calculae_total_price() {
|
||||
double total = 0.0;
|
||||
|
||||
for (Goods g : this->goods) {
|
||||
for (Goods &g : goods) {
|
||||
total += g.calculate_total_price();
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
std::vector<Goods>& Check::get_goods() {
|
||||
return goods;
|
||||
}
|
||||
|
||||
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_date(std::string date) {
|
||||
this->date = date;
|
||||
}
|
||||
|
||||
void Check::set_operation_type(OperationType t) {
|
||||
this->operation_type = t;
|
||||
}
|
||||
|
||||
double Check::get_total() {
|
||||
return total;
|
||||
}
|
||||
|
||||
bool Check::operator==(Check &c) {
|
||||
// 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 &&
|
||||
this->fi == c.fi &&
|
||||
this->fn == c.fn &&
|
||||
this->operation_type == c.operation_type &&
|
||||
this->total == c.total;
|
||||
}
|
||||
|
||||
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 &&
|
||||
this->fi == c.fi &&
|
||||
this->fn == c.fn &&
|
||||
this->operation_type == c.operation_type &&
|
||||
this->total == c.total;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,49 @@
|
||||
#include "../goods/goods.h"
|
||||
#include <vector>
|
||||
|
||||
typedef enum OperationTypes {
|
||||
funds_income, // Приход средств
|
||||
funds_return, // Возврат прихода
|
||||
funds_spend, // Расход средств
|
||||
spends_return // Возврат расхода
|
||||
} OperationType;
|
||||
|
||||
class Check {
|
||||
std::string fn; // Fiscal Number = Фискальный номер
|
||||
std::string fd; // Fiscal Document = Фискальный документ
|
||||
std::string fi; // Fiscal Identifier = Фискальный признак
|
||||
|
||||
std::string date;
|
||||
OperationType operation_type;
|
||||
double total;
|
||||
|
||||
std::vector<Goods> goods;
|
||||
|
||||
public:
|
||||
Check();
|
||||
void add_goods(Goods);
|
||||
void add_goods(std::vector<Goods> &goods);
|
||||
|
||||
double calculae_total_price();
|
||||
|
||||
std::vector<Goods> &get_goods();
|
||||
|
||||
void set_fn(std::string);
|
||||
void set_fd(std::string);
|
||||
void set_fi(std::string);
|
||||
void set_date(std::string);
|
||||
void set_operation_type(OperationType);
|
||||
void set_total(double);
|
||||
|
||||
std::string get_fn();
|
||||
std::string get_fd();
|
||||
std::string get_fi();
|
||||
std::string get_date();
|
||||
OperationType get_operationType();
|
||||
double get_total();
|
||||
|
||||
bool operator==(Check &);
|
||||
bool operator==(const Check &);
|
||||
};
|
||||
|
||||
#endif // CHECK_H
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
FROM archlinux
|
||||
|
||||
#Update
|
||||
RUN pacman --noconfirm -Sy
|
||||
|
||||
#Build dependencies
|
||||
RUN pacman --noconfirm -S sudo cmake git coreutils base-devel eigen
|
||||
|
||||
#Dependencies from repos
|
||||
RUN pacman --noconfirm -S qt5-base mbedtls
|
||||
|
||||
RUN echo "MAKEFLAGS=\"-j${nproc}\"" >> /etc/makepkg.conf
|
||||
|
||||
RUN useradd -ms /bin/bash checks-parser
|
||||
RUN usermod -a -G wheel checks-parser
|
||||
|
||||
RUN echo "checks-parser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
USER checks-parser
|
||||
WORKDIR /home/checks-parser
|
||||
|
||||
#Dependencies from sources
|
||||
RUN git clone https://aur.archlinux.org/yay.git && \
|
||||
cd yay && \
|
||||
makepkg -si --noconfirm && \
|
||||
cd .. && sudo rm -rf yay
|
||||
|
||||
RUN yay -Sy --noconfirm gtkglext
|
||||
RUN yay -S --noconfirm cpr opencv opencv2 nlohmann-json tesseract tesseract-data-rus
|
||||
|
||||
#building
|
||||
WORKDIR /home/checks-parser
|
||||
RUN git clone https://git.foxarmy.org/leca/checks-parser && \
|
||||
cd checks-parser && \
|
||||
mkdir build && cd build && \
|
||||
cmake .. && \
|
||||
make -j ${nproc} && \
|
||||
sudo make install
|
||||
|
||||
ENTRYPOINT ["checks-parser"]
|
||||
@@ -1,34 +0,0 @@
|
||||
FROM debian:bullseye
|
||||
|
||||
#Update
|
||||
RUN apt update -y && apt upgrade -y
|
||||
|
||||
#Build dependencies
|
||||
RUN apt install -y git build-essential cmake
|
||||
|
||||
#Dependencies from repos (qt5, openssl, tesseract and lang package)
|
||||
RUN apt install -y qtbase5-dev openssl libmbedtls-dev tesseract-ocr tesseract-ocr-rus libopencv-dev
|
||||
|
||||
#Dependencies from sources
|
||||
#cpr
|
||||
WORKDIR /root
|
||||
RUN git clone https://github.com/whoshuu/cpr.git && \
|
||||
cd cpr && \
|
||||
mkdir build && cd build && \
|
||||
cmake .. && \
|
||||
make -j ${nproc} && \
|
||||
make install && \
|
||||
cd /root && rm -rf cpr
|
||||
|
||||
|
||||
#building
|
||||
|
||||
WORKDIR /root
|
||||
RUN git clone https://git.foxarmy.org/leca/checks-parser && \
|
||||
cd checks-parser && \
|
||||
mkdir build && cd build &&\
|
||||
cmake .. && \
|
||||
make -j ${nproc} && \
|
||||
make install && \
|
||||
|
||||
ENTRYPOINT ["checks-parser"]
|
||||
|
Before Width: | Height: | Size: 627 KiB |
|
Before Width: | Height: | Size: 627 KiB |
@@ -1,7 +0,0 @@
|
||||
# Generated by linuxdeployqt
|
||||
# https://github.com/probonopd/linuxdeployqt/
|
||||
[Paths]
|
||||
Prefix = ./
|
||||
Plugins = plugins
|
||||
Imports = qml
|
||||
Qml2Imports = qml
|
||||
@@ -1,7 +0,0 @@
|
||||
# Generated by linuxdeployqt
|
||||
# https://github.com/probonopd/linuxdeployqt/
|
||||
[Paths]
|
||||
Prefix = ../
|
||||
Plugins = plugins
|
||||
Imports = qml
|
||||
Qml2Imports = qml
|
||||
1
deploy/appimage/AppDir/AppRun → deploy/appimage/AppRun
Executable file → Normal file
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
export TESSDATA_PREFIX=$APPDIR/usr/share/tesseract-ocr/4.00/tessdata
|
||||
export LD_LIBRARY_PATH=$APPDIR/usr/lib
|
||||
|
||||
$APPDIR/usr/bin/checks-parser
|
||||
31
deploy/appimage/Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
FROM checks_parser_base_ubuntu
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt update
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt install -y wget git cmake make gcc g++ fuse libboost-regex-dev
|
||||
|
||||
ARG pkgname=$name
|
||||
ARG pkgver=$version
|
||||
ARG revision
|
||||
|
||||
WORKDIR /
|
||||
|
||||
# Download linuxdeployqt
|
||||
RUN wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage -O /usr/bin/linuxdeployqt && \
|
||||
chmod +x /usr/bin/linuxdeployqt
|
||||
|
||||
# Prepare AppDir and its files
|
||||
WORKDIR /app
|
||||
|
||||
RUN mkdir -p AppDir/usr/bin
|
||||
|
||||
COPY deploy/appimage/checks-parser.desktop AppDir
|
||||
COPY assets/icons/icon.png AppDir/checks-parser.png
|
||||
COPY deploy/appimage/AppRun AppDir
|
||||
RUN chmod +x AppDir/AppRun
|
||||
RUN cp build/checks-parser /app/AppDir/usr/bin
|
||||
|
||||
RUN PATH=/usr/lib/qt5/bin/:$PATH linuxdeployqt --appimage-extract-and-run AppDir/usr/bin/checks-parser -no-copy-copyright-files -appimage
|
||||
RUN mkdir -p /output
|
||||
RUN echo "cp Checks_parser-x86_64.AppImage /output/Checks_parser-x86_64_${pkgver}-${revision}.AppImage" > /deploy.sh
|
||||
RUN chmod +x /deploy.sh
|
||||
ENTRYPOINT ["bash", "/deploy.sh"]
|
||||
@@ -4,4 +4,3 @@ Exec=usr/bin/checks-parser
|
||||
Icon=checks-parser
|
||||
Type=Application
|
||||
Categories=Utility;
|
||||
X-AppImage-Version=41463c7
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
mkdir -p AppDir/usr/bin
|
||||
mkdir -p AppDir/usr/lib
|
||||
mkdir -p AppDir/usr/share/tesseract-ocr/4.00/tessdata
|
||||
cp -r /usr/share/tesseract-ocr/4.00/tessdata/* AppDir/usr/share/tesseract-ocr/4.00/tessdata
|
||||
cp ../../checks-parser AppDir/usr/bin
|
||||
|
||||
echo \
|
||||
"[Desktop Entry]
|
||||
Name=Checks parser
|
||||
Exec=usr/bin/checks-parser
|
||||
Icon=checks-parser
|
||||
Type=Application
|
||||
Categories=Utility;" \
|
||||
> AppDir/checks-parser.desktop
|
||||
|
||||
echo \
|
||||
"#!/bin/bash
|
||||
export TESSDATA_PREFIX=\$APPDIR/usr/share/tesseract-ocr/4.00/tessdata
|
||||
|
||||
\$APPDIR/usr/bin/checks-parser" \
|
||||
> AppDir/AppRun
|
||||
|
||||
chmod +x AppDir/AppRun
|
||||
cp ../../checks-parser AppDir/usr/bin
|
||||
linuxdeployqt AppDir/usr/bin/checks-parser -no-copy-copyright-files -appimage
|
||||
28
deploy/archlinux/bin/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM archlinux:latest
|
||||
|
||||
ARG pkgname=$name
|
||||
ARG pkgver=$version
|
||||
ARG revision
|
||||
|
||||
RUN mkdir -p /output
|
||||
|
||||
RUN pacman --noconfirm -Syu base base-devel sudo
|
||||
RUN echo "sudo cp ${pkgname}-bin-${pkgver}-$revision-x86_64.pkg.tar.zst /output" > /deploy.sh
|
||||
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
|
||||
#ENTRYPOINT ["bash"]
|
||||
ENTRYPOINT ["bash", "/deploy.sh"]
|
||||
40
deploy/archlinux/bin/PKGBUILD
Normal file
@@ -0,0 +1,40 @@
|
||||
# Maintainer: Leca <leca@foxarmy.org>
|
||||
pkgname=$pkgname
|
||||
pkgver=$pkgver
|
||||
pkgrel=$pkgrel
|
||||
epoch=
|
||||
pkgdesc="Utility for parsing checks(receipts) to csv"
|
||||
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')
|
||||
checkdepends=()
|
||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
||||
provides=()
|
||||
conflicts=("checks-parser-git")
|
||||
replaces=()
|
||||
backup=()
|
||||
options=()
|
||||
install=
|
||||
changelog=
|
||||
_releasesurl=https://git.foxarmy.org/leca/checks-parser/releases/download/$pkgver
|
||||
source=("checks-parser-bin::https+$releaseurl/checks-parser-git-${pkgver}_nightly-$pkgrel-x86_64.pkg.tar.zst")
|
||||
noextract=()
|
||||
sha256sums=('SKIP')
|
||||
|
||||
build() {
|
||||
cd "$pkgname"
|
||||
mkdir build && cd build
|
||||
cmake -DBUILD_TRANSLATIONS=on ..
|
||||
make -j ${nproc}
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname"
|
||||
cd build
|
||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
##install -Dm755
|
||||
make DESTDIR="$pkgdir/" PREFIX="/usr" install
|
||||
}
|
||||
28
deploy/archlinux/git/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM archlinux:latest
|
||||
|
||||
ARG pkgname=$name
|
||||
ARG pkgver=$version
|
||||
ARG revision
|
||||
|
||||
RUN mkdir -p /output
|
||||
|
||||
RUN pacman --noconfirm -Syu base base-devel sudo
|
||||
RUN echo "sudo cp ${pkgname}-git-${pkgver}_nightly-$revision-x86_64.pkg.tar.zst /output" > /deploy.sh
|
||||
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/git/PKGBUILD PKGBUILD
|
||||
RUN sed -i "s|\$pkgname|${pkgname}-git|g" PKGBUILD
|
||||
RUN sed -i "s|\$pkgver|${pkgver}_nightly|g" PKGBUILD
|
||||
RUN sed -i "s|\$pkgrel|$revision|g" PKGBUILD
|
||||
|
||||
RUN makepkg -s --noconfirm
|
||||
#ENTRYPOINT ["bash"]
|
||||
ENTRYPOINT ["bash", "/deploy.sh"]
|
||||
36
deploy/archlinux/git/PKGBUILD
Normal file
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Leca <leca@foxarmy.org>
|
||||
pkgname=$pkgname
|
||||
pkgver=$pkgver
|
||||
pkgrel=$pkgrel
|
||||
epoch=
|
||||
pkgdesc="Utility for parsing checks(receipts) to csv"
|
||||
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')
|
||||
checkdepends=()
|
||||
optdepends=('tesseract-data-rus: scan russian checks with OCR')
|
||||
provides=()
|
||||
conflicts=("checks-parser-bin")
|
||||
replaces=()
|
||||
backup=()
|
||||
options=()
|
||||
install=
|
||||
changelog=
|
||||
source=("checks-parser-git::git+$url")
|
||||
noextract=()
|
||||
sha256sums=('SKIP')
|
||||
|
||||
build() {
|
||||
cd "$pkgname"
|
||||
cmake -DBUILD_TRANSLATIONS=on .
|
||||
make -j ${nproc}
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname"
|
||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
make DESTDIR="$pkgdir/" PREFIX="/usr" install
|
||||
}
|
||||
33
deploy/base-docker/ubuntu/Dockerfile
Normal file
@@ -0,0 +1,33 @@
|
||||
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 wget git cmake make gcc g++ fuse libboost-regex-dev
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
#Copy only necessities
|
||||
COPY assets ./assets
|
||||
COPY check ./check
|
||||
COPY exceptions ./exceptions
|
||||
COPY goods ./goods
|
||||
COPY image_redactor ./image_redactor
|
||||
COPY output ./output
|
||||
COPY settings ./settings
|
||||
COPY scenes ./scenes
|
||||
COPY net ./net
|
||||
COPY translations ./translations
|
||||
COPY http_server ./http_server
|
||||
COPY utils ./utils
|
||||
COPY widgets ./widgets
|
||||
COPY email_parser ./email_parser
|
||||
|
||||
COPY ./*.h ./*cpp ./*.ui ./*.qrc CMakeLists.txt .
|
||||
|
||||
WORKDIR /app/build
|
||||
|
||||
RUN cmake -DBUILD_TRANSLATIONS=on .. && make -j 8
|
||||
|
||||
ENTRYPOINT ["bash"]
|
||||
29
deploy/debian/Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
||||
FROM checks_parser_base_ubuntu
|
||||
|
||||
#for envsubst
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt install -y gettext
|
||||
|
||||
ARG pkgname=$name
|
||||
ARG pkgver=$version
|
||||
ARG revision
|
||||
|
||||
ARG pkg=${pkgname}_$pkgver-$revision
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN mkdir -p $pkg/DEBIAN
|
||||
RUN mkdir -p $pkg/usr/bin
|
||||
RUN mkdir -p /output
|
||||
COPY deploy/debian/control $pkg/DEBIAN/control
|
||||
COPY deploy/debian/copy.sh .
|
||||
|
||||
RUN envsubst < $pkg/DEBIAN/control | tee $pkg/DEBIAN/control.output && mv $pkg/DEBIAN/control.output $pkg/DEBIAN/control
|
||||
RUN envsubst < copy.sh | tee copy.sh.output && mv copy.sh.output copy.sh
|
||||
|
||||
RUN chmod +x copy.sh
|
||||
|
||||
RUN cp /app/build/checks-parser $pkg/usr/bin
|
||||
|
||||
RUN dpkg-deb --build $pkg
|
||||
|
||||
ENTRYPOINT ["./copy.sh"]
|
||||
10
deploy/debian/control
Normal file
@@ -0,0 +1,10 @@
|
||||
Package: checks-parser
|
||||
Version: 3.0-1
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Homepage: https://git.foxarmy.org/checks-parser
|
||||
Depends: libc, 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
|
||||
Maintainer: Leca <leca@foxarmy.org>
|
||||
Description: Utility for parsing checks(receipts) to csv
|
||||
Utility for extraction of content of a check(receipt) using plaintext, OCR or request to FTS (Federal Taxation Service)
|
||||
2
deploy/debian/copy.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
cp $pkg.deb /output
|
||||
9
deploy/windows/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM checks_parser_base_ubuntu
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt install -y autoconf automake autopoint bash bison bzip2 flex g++ g++-multilib gettext git gperf intltool libc6-dev-i386 libgdk-pixbuf2.0-dev libltdl-dev libgl-dev libpcre3-dev libssl-dev libtool-bin libxml-parser-perl lzip make openssl p7zip-full patch perl python3 python3-distutils python3-mako python3-packaging python3-pkg-resources python3-setuptools python-is-python3 ruby sed sqlite3 unzip wget xz-utils
|
||||
|
||||
WORKDIR /
|
||||
|
||||
RUN git clone https://github.com/mxe/mxe.git
|
||||
|
||||
RUN cd mxe && make qt
|
||||
46
docker-compose.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
services:
|
||||
base_ubuntu:
|
||||
image: checks_parser_base_ubuntu:latest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: deploy/base-docker/ubuntu/Dockerfile
|
||||
appimage:
|
||||
image: checks_parser_appimage:latest
|
||||
env_file: .env
|
||||
build:
|
||||
dockerfile: deploy/appimage/Dockerfile
|
||||
context: .
|
||||
args:
|
||||
- pkgname=$name
|
||||
- pkgver=$version
|
||||
- revision=$revision
|
||||
volumes:
|
||||
- ./binaries:/output
|
||||
depends_on:
|
||||
- base_ubuntu
|
||||
debian:
|
||||
image: checks_parser_debian:latest
|
||||
env_file: .env
|
||||
build:
|
||||
dockerfile: deploy/debian/Dockerfile
|
||||
context: .
|
||||
args:
|
||||
- pkgname=$name
|
||||
- pkgver=$version
|
||||
- revision=$revision
|
||||
volumes:
|
||||
- ./binaries:/output
|
||||
depends_on:
|
||||
- base_ubuntu
|
||||
archlinux:
|
||||
image: checks_parser_base_arch:latest
|
||||
env_file: .env
|
||||
build:
|
||||
dockerfile: deploy/archlinux/git/Dockerfile
|
||||
context: .
|
||||
args:
|
||||
- pkgname=$name
|
||||
- pkgver=$version
|
||||
- revision=$revision
|
||||
volumes:
|
||||
- ./binaries:/output
|
||||
180
email_parser/emailparser.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "utils/utils.h"
|
||||
#include <email_parser/emailparser.h>
|
||||
|
||||
#include <utils/utils.h>
|
||||
#include <check/check.h>
|
||||
#include <boost/regex.hpp>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <bits/stdc++.h>
|
||||
#include <fstream>
|
||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
using namespace std::experimental::filesystem;
|
||||
#else
|
||||
# include <filesystem>
|
||||
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() {
|
||||
|
||||
}
|
||||
|
||||
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::string payload = get_payload_in_email(email_content);
|
||||
// Check c;
|
||||
|
||||
// std::cout << payload << std::endl;
|
||||
|
||||
// if (payload == "")
|
||||
// return c;
|
||||
|
||||
|
||||
|
||||
// return c;
|
||||
}
|
||||
|
||||
Check EmailParser::parse_file(std::string path) {
|
||||
|
||||
// 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 (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;
|
||||
|
||||
}
|
||||
std::cout << content_type.first << ": " << content_type.second << std::endl;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
19
email_parser/emailparser.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef CHECKS_PARSER_EMAIL_PARSER
|
||||
#define CHECKS_PARSER_EMAIL_PARSER
|
||||
|
||||
#include <check/check.h>
|
||||
#include <map>
|
||||
|
||||
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);
|
||||
public:
|
||||
EmailParser();
|
||||
Check parse(std::string &email_content);
|
||||
Check parse_file(std::string path);
|
||||
|
||||
};
|
||||
|
||||
#endif // CHECKS_PARSER_EMAIL_PARSER
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "goods.h"
|
||||
#include <string>
|
||||
|
||||
Goods::Goods(std::string name, double price_per_unit, double quantity) {
|
||||
this->name = name;
|
||||
this->price_per_unit = price_per_unit;
|
||||
this->quantity = quantity;
|
||||
}
|
||||
Goods::Goods(std::string name, double price_per_unit, std::string net_weight, double quantity) :
|
||||
name(name), price_per_unit(price_per_unit),
|
||||
net_weight(net_weight), quantity(quantity) {}
|
||||
|
||||
double Goods::calculate_total_price() {
|
||||
return this->price_per_unit * this->quantity;
|
||||
@@ -15,12 +13,16 @@ std::string Goods::get_name() { return this->name; }
|
||||
|
||||
double Goods::get_quantity() { return this->quantity; }
|
||||
|
||||
std::string Goods::get_net_weight() { return this->net_weight; }
|
||||
|
||||
double Goods::get_price_per_unit() { return this->price_per_unit; }
|
||||
|
||||
void Goods::set_name(std::string name) { this->name = name; }
|
||||
|
||||
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_price_per_unit(double price_per_unit) {
|
||||
this->price_per_unit = price_per_unit;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,20 @@ 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, double, double);
|
||||
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();
|
||||
|
||||
void set_name(std::string);
|
||||
void set_quantity(double);
|
||||
void set_net_weight(std::string);
|
||||
void set_price_per_unit(double);
|
||||
};
|
||||
|
||||
|
||||
113
http_server/http_server.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include "http_server.h"
|
||||
|
||||
#include <qobjectdefs.h>
|
||||
#include <unistd.h>
|
||||
#include <utils/utils.h>
|
||||
#include <iostream>
|
||||
#include <mainwindow.h>
|
||||
#include <thread>
|
||||
|
||||
void HttpServer::generateRandomPort() {
|
||||
port = rand() % (65535 - 1024) + 1024;
|
||||
}
|
||||
|
||||
HttpServer::HttpServer(QWidget *caller) : caller(caller) {
|
||||
started = false;
|
||||
port = 8080;
|
||||
}
|
||||
|
||||
HttpServer::~HttpServer() {
|
||||
started = false;
|
||||
shutdown(serverSocket, SHUT_RDWR);
|
||||
close(serverSocket);
|
||||
|
||||
for (auto &thread : clientHandlersThreads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
listenClientsThread.join();
|
||||
}
|
||||
|
||||
int HttpServer::start() {
|
||||
unsigned short number_of_retries = 0;
|
||||
|
||||
while (number_of_retries < 10) {
|
||||
|
||||
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket < 0) {
|
||||
std::cerr << QObject::tr("Could not obtain socket.").toStdString() << std::endl;
|
||||
number_of_retries ++;
|
||||
continue;
|
||||
}
|
||||
serverAddress.sin_family = AF_INET;
|
||||
serverAddress.sin_port = htons(port);
|
||||
serverAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (bind(serverSocket, (sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
|
||||
std::cerr << QObject::tr("Port ").toStdString() << port << QObject::tr(" seems to be occupied. Trying to generate another one").toStdString() << std::endl;
|
||||
number_of_retries ++;
|
||||
generateRandomPort();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listen(serverSocket, 1) < 0) {
|
||||
std::cerr << QObject::tr("Could not listen port.").toStdString() << std::endl;
|
||||
number_of_retries ++;
|
||||
generateRandomPort();
|
||||
continue;
|
||||
}
|
||||
started = true;
|
||||
std::cout << QObject::tr("Listening on port: ").toStdString() << port << std::endl;
|
||||
listenClientsThread = std::thread(&HttpServer::acceptClients, this);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void HttpServer::handleClient(int clientSocket) {
|
||||
std::string localIp;
|
||||
try {
|
||||
localIp = get_local_ip_address();
|
||||
} catch(std::exception e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
close(clientSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[256] = {0};
|
||||
|
||||
recv(clientSocket, buffer, 256, 0);
|
||||
|
||||
std::string response = "HTTP/1.1 301 Moved Permanently\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"Keep-Alive: timeout=5, max=100\r\n"
|
||||
"Location: binaryeye://scan/?ret=http://" + get_local_ip_address() + ":" + std::to_string(port) + "/?result={RESULT}\r\n"
|
||||
"\r\n";
|
||||
|
||||
if (send(clientSocket, response.c_str(), response.length(), 0) < 0) {
|
||||
std::cerr << response.c_str() << std::endl;
|
||||
std::cerr << response.length() << std::endl;
|
||||
std::cerr << QObject::tr("Could not send message").toStdString() << std::endl;
|
||||
}
|
||||
emit ((MainWindow *)caller)->httpNewMessage(QString::fromStdString(std::string(buffer)));
|
||||
}
|
||||
|
||||
void HttpServer::acceptClients() {
|
||||
while (true) {
|
||||
if (!started) return;
|
||||
int clientSocket = accept(serverSocket, nullptr, nullptr);
|
||||
if (!started) return;
|
||||
|
||||
clientHandlersThreads.push_back (
|
||||
std::thread(&HttpServer::handleClient, this, clientSocket)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short HttpServer::getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
bool HttpServer::isStarted() {
|
||||
return started;
|
||||
}
|
||||
37
http_server/http_server.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CHECKS_PARSER_HTTP_SERVER
|
||||
#define CHECKS_PARSER_HTTP_SERVER
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <QWidget>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class HttpServer {
|
||||
private:
|
||||
unsigned short port;
|
||||
int serverSocket;
|
||||
sockaddr_in serverAddress;
|
||||
|
||||
QWidget* caller;
|
||||
|
||||
std::thread listenClientsThread;
|
||||
std::vector<std::thread> clientHandlersThreads;
|
||||
|
||||
bool started;
|
||||
|
||||
void generateRandomPort();
|
||||
public:
|
||||
HttpServer(QWidget *caller);
|
||||
~HttpServer();
|
||||
int start();
|
||||
void stop();
|
||||
void handleClient(int clientSocket);
|
||||
void acceptClients();
|
||||
|
||||
unsigned short getPort();
|
||||
|
||||
bool isStarted();
|
||||
};
|
||||
|
||||
#endif //CHECKS_PARSER_HTTP_SERVER
|
||||
@@ -1,23 +0,0 @@
|
||||
#include <string>
|
||||
#include <tesseract/baseapi.h>
|
||||
#include <leptonica/allheaders.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "checkimage.h"
|
||||
|
||||
CheckImage::CheckImage(std::string path) {
|
||||
this->path = path;
|
||||
}
|
||||
|
||||
std::string CheckImage::parse_text() {
|
||||
std::string result;
|
||||
|
||||
tesseract::TessBaseAPI *ocr = new tesseract::TessBaseAPI();
|
||||
ocr->Init(NULL, "rus", tesseract::OEM_LSTM_ONLY);
|
||||
ocr->SetPageSegMode(tesseract::PSM_AUTO);
|
||||
|
||||
cv::Mat im = cv::imread(this->path, cv::IMREAD_COLOR);
|
||||
ocr->SetImage(im.data, im.cols, im.rows, 3, im.step);
|
||||
result = std::string(ocr->GetUTF8Text());
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef CHECKIMAGE_H
|
||||
#define CHECKIMAGE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class CheckImage {
|
||||
std::string path;
|
||||
public:
|
||||
CheckImage(std::string path);
|
||||
|
||||
std::string parse_text();
|
||||
|
||||
};
|
||||
|
||||
#endif // CHECKIMAGE_H
|
||||
@@ -32,8 +32,7 @@ void ImageRedactor::wheelEvent(QWheelEvent *event) {
|
||||
void ImageRedactor::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
// Pan the image
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
setDragMode(QGraphicsView::ScrollHandDrag);
|
||||
}
|
||||
}
|
||||
@@ -41,8 +40,7 @@ void ImageRedactor::mousePressEvent(QMouseEvent *event)
|
||||
void ImageRedactor::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
// Reset the drag mode
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
setDragMode(QGraphicsView::NoDrag);
|
||||
}
|
||||
}
|
||||
|
||||
77
main.cpp
@@ -1,9 +1,12 @@
|
||||
#include "mainwindow.h"
|
||||
#include "net/net.h"
|
||||
#include "settings/settings.h"
|
||||
#include "utils/utils.h"
|
||||
#include "email_parser/emailparser.h"
|
||||
#include <mainwindow.h>
|
||||
#include <net/net.h>
|
||||
#include <settings/settings.h>
|
||||
#include <utils/utils.h>
|
||||
#include <QApplication>
|
||||
#include <curl/curl.h>
|
||||
#ifdef BUILD_OFD_MODE
|
||||
# include <curl/curl.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
@@ -12,44 +15,62 @@
|
||||
# include <filesystem>
|
||||
using namespace std::filesystem;
|
||||
#endif
|
||||
#include <QTranslator>
|
||||
#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>
|
||||
#endif
|
||||
#include <QPushButton>
|
||||
|
||||
#include <utils/base64.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
|
||||
std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser");
|
||||
create_directories(program_data_path);
|
||||
|
||||
srand(time(0));
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
std::string settings_file_path =
|
||||
get_path_relative_to_home(".local/share/checks_parser/settings.json");
|
||||
|
||||
Settings s(settings_file_path);
|
||||
Net n;
|
||||
|
||||
Parser p;
|
||||
std::vector<std::string> stores_updates = p.check_updates();
|
||||
for (const std::string &update : stores_updates) {
|
||||
std::cout << "Downloading "
|
||||
<< s.get_setting("stores_modules_url") + update << " to "
|
||||
<< get_path_relative_to_home(s.get_setting("stores_modules_dir") +
|
||||
"/" + update)
|
||||
<< std::endl;
|
||||
|
||||
n.get_file(s.get_setting("stores_modules_url") + "/" + update,
|
||||
get_path_relative_to_home(s.get_setting("stores_modules_dir") +
|
||||
"/" + update));
|
||||
}
|
||||
|
||||
QApplication a(argc, argv);
|
||||
|
||||
#ifdef BUILD_TRANSLATIONS
|
||||
QTranslator translator;
|
||||
if(!translator.load(QLocale::system().name())) {
|
||||
translator.load("en_US");
|
||||
QString lang = "en_US";
|
||||
|
||||
bool languageSettingPresent = false;
|
||||
languageSettingPresent = s.get_all_settings().find("language") != s.get_all_settings().end();
|
||||
|
||||
if (languageSettingPresent) {
|
||||
lang = QString::fromStdString(s.get_all_settings()["language"]);
|
||||
} else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
|
||||
lang = QLocale::system().name();
|
||||
} else {
|
||||
lang = QString::fromStdString("en_US");
|
||||
}
|
||||
a.installTranslator(&translator);
|
||||
|
||||
std::cout << QObject::tr("Using locale: ").toStdString() << lang.toStdString() << std::endl;
|
||||
|
||||
if (!translator.load(":/translation/" + lang + ".qm")) {
|
||||
std::cerr << "Could not load translation!!" << std::endl;
|
||||
}
|
||||
app.installTranslator(&translator);
|
||||
#endif
|
||||
MainWindow w;
|
||||
w.update();
|
||||
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
450
mainwindow.cpp
@@ -1,208 +1,314 @@
|
||||
#include "mainwindow.h"
|
||||
#include "./ui_mainwindow.h"
|
||||
#include "check/check.h"
|
||||
#include "exceptions/ofdrequestexception.h"
|
||||
#include "goods/goods.h"
|
||||
#include "outputdialog.h"
|
||||
#include "adjustpicturedialog.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "solvecaptchadialog.h"
|
||||
#include <mainwindow.h>
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include "image/checkimage.h"
|
||||
#include "utils/utils.h"
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <zbar.h>
|
||||
#include <QPixmap>
|
||||
#include <settingsdialog.h>
|
||||
|
||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
# include <adjustpicturedialog.h>
|
||||
#endif
|
||||
|
||||
#include <outputdialog.h>
|
||||
#include <solvecaptchadialog.h>
|
||||
#include <net/net.h>
|
||||
#include <utils/utils.h>
|
||||
#include <exceptions/ofdrequestexception.h>
|
||||
#include <checklistviewwidget.h>
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
# include <qrencode.h>
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::MainWindow) {
|
||||
ui->setupUi(this);
|
||||
this->setupStoresList();
|
||||
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();
|
||||
|
||||
connect(this, &MainWindow::deleteCheckFromList, this, &MainWindow::deleteCheckFromListHandler);
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure);
|
||||
connect(this, SIGNAL(httpNewMessage(QString)), this, SLOT(httpNewMessageHandler(QString)));
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_EMAIL_MODE
|
||||
ui->parse_email_button->hide();
|
||||
ui->or_label_2->hide();
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_OFD_BINARYEYE_SCAN
|
||||
ui->or_label_2->hide();
|
||||
ui->binary_eye_button->hide();
|
||||
#endif
|
||||
#ifndef BUILD_OFD_LOCAL_QR_SCAN
|
||||
ui->or_label_1->hide();
|
||||
ui->choose_image_button->hide();
|
||||
#endif
|
||||
|
||||
QObject::connect(ui->settings_button, &QPushButton::clicked, [&]() {
|
||||
SettingsDialog d;
|
||||
d.show();
|
||||
d.exec();
|
||||
});
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() { delete ui; }
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
void MainWindow::startHttpServer() {
|
||||
server = new HttpServer(this);
|
||||
|
||||
void MainWindow::setupStoresList() {
|
||||
parser = *(new Parser());
|
||||
|
||||
std::vector<std::string> modules_names = parser.search_modules();
|
||||
|
||||
for (std::string name : modules_names) {
|
||||
StoreModule m(name);
|
||||
std::wstring module_name = m.get_name();
|
||||
|
||||
QString s = QString::fromStdWString(module_name);
|
||||
ui->storeType->addItem(s);
|
||||
if (server->start() < 0) {
|
||||
emit httpErrorOccured();
|
||||
}
|
||||
}
|
||||
|
||||
std::string MainWindow::makeRequestToOfd(std::string captcha) {
|
||||
std::string checkContent = Net().fetch_check_data_from_ofdru(
|
||||
ui->fn_edit->text().toStdString(),
|
||||
ui->fd_edit->text().toStdString(),
|
||||
ui->fi_edit->text().toStdString(),
|
||||
ui->dateTimeEdit->dateTime().toString(Qt::ISODate).toStdString(),
|
||||
ui->fundIncomeCombo->currentIndex() + 1,
|
||||
// In the request to ofd.ru, total is in a strange format, like a string of a format where 2 last digits represent decimal part of a number.
|
||||
ui->total_edit->text().toDouble() * 100,
|
||||
captcha);
|
||||
void MainWindow::on_binary_eye_button_clicked() {
|
||||
httpServerThread = new std::thread(&MainWindow::startHttpServer, this);
|
||||
ui->binary_eye_button->setEnabled(false);
|
||||
ui->stop_server_button->show();
|
||||
|
||||
return checkContent;
|
||||
}
|
||||
|
||||
void MainWindow::on_parseButton_clicked() {
|
||||
QString s;
|
||||
switch (ui->tabWidget->currentIndex()) {
|
||||
case 0:
|
||||
s = ui->checkContent->toPlainText();
|
||||
break;
|
||||
case 1:
|
||||
s = ui->checkContentFromImage->toPlainText();
|
||||
break;
|
||||
case 2:
|
||||
Net().get_captcha_from_ofdru();
|
||||
|
||||
std::string solved_captcha = "";
|
||||
bool success = true;
|
||||
bool is_captcha_solved = true;
|
||||
|
||||
do {
|
||||
SolveCaptchaDialog dialog = SolveCaptchaDialog(this, &solved_captcha);
|
||||
dialog.exec();
|
||||
is_captcha_solved = true;
|
||||
|
||||
try {
|
||||
std::string check_content = makeRequestToOfd(solved_captcha);
|
||||
check = parseOfdRuAnswer(check_content);
|
||||
} catch(OfdRequestException e) {
|
||||
success = false;
|
||||
if (!strcmp(e.what(), "Incorrect captcha")) {
|
||||
is_captcha_solved = false;
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
||||
infoDialog.exec();
|
||||
break;
|
||||
} else if (!strcmp(e.what(), "Does not exist")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Check was not found"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (!is_captcha_solved);
|
||||
|
||||
if (success) {
|
||||
OutputDialog d = OutputDialog(this, check);
|
||||
d.exec();
|
||||
}
|
||||
while (!server->isStarted()) {}
|
||||
|
||||
std::string localIp;
|
||||
try {
|
||||
localIp = get_local_ip_address();
|
||||
} catch(std::exception e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring check_plaintext = s.toStdWString();
|
||||
parser.set_module(parser.search_modules()[0]);
|
||||
std::string connectionString = "binaryeye://scan?ret=http://" + localIp + ":" + std::to_string(server->getPort()) + "/?result={RESULT}";
|
||||
|
||||
std::vector<Goods> c = parser.parse(check_plaintext);
|
||||
generate_qr_code(connectionString);
|
||||
|
||||
if (c.size() == 0) {
|
||||
std::cerr << "An error has occured. Check was matched incorrectly. Vector sizes are different" << std::endl;
|
||||
QMessageBox infoDialog = QMessageBox();
|
||||
infoDialog.setText(QString::fromStdString(connectionString));
|
||||
infoDialog.setIconPixmap(QPixmap(QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/binaryeye_connection.png"))).scaled(400, 400, Qt::KeepAspectRatio));
|
||||
infoDialog.setWindowTitle(tr("QR code for binaryeye to connect"));
|
||||
infoDialog.addButton(tr("I've scanned"), QMessageBox::ButtonRole::AcceptRole);
|
||||
infoDialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::notifyHttpServerFailure() {
|
||||
QMessageBox infoDialog = QMessageBox();
|
||||
infoDialog.setText(tr("Could not start http server. 10 times in a row random port was occupied. Either you should run for a lottery ticket, or the problem is in the program. If the lottery ticket wasn't lucky, please, contact the developer."));
|
||||
infoDialog.setIcon(QMessageBox::Warning);
|
||||
infoDialog.setWindowTitle(tr("Could not start http server."));
|
||||
infoDialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_stop_server_button_clicked() {
|
||||
delete server;
|
||||
ui->stop_server_button->hide();
|
||||
ui->binary_eye_button->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::httpNewMessageHandler(QString message) {
|
||||
std::string parametersString = split(message.toStdString(), " ")[1];
|
||||
|
||||
//erase /?result= from the string
|
||||
parametersString.erase(0, parametersString.find("=") + 1);
|
||||
|
||||
std::vector<std::string> parameters = split(parametersString, "&");
|
||||
|
||||
std::map<std::string, std::string> paramsMap;
|
||||
|
||||
for (auto ¶meter : parameters) {
|
||||
std::vector<std::string> values = split(parameter, "=");
|
||||
paramsMap.insert(std::pair<std::string, std::string> (values[0], values[1]));
|
||||
}
|
||||
|
||||
emit onDataDecode(paramsMap);
|
||||
}
|
||||
|
||||
|
||||
#endif //ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
|
||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
void MainWindow::on_choose_image_button_clicked() {
|
||||
QString filename = QFileDialog::getOpenFileName();
|
||||
|
||||
if (filename == "") {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Please, select a picture where QR code that contains info about check is present"));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Picture was not selected"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& g : c) {
|
||||
check.add_goods(g);
|
||||
}
|
||||
ui->info_label->setText(tr("Selected image: ") + filename);
|
||||
|
||||
OutputDialog d = OutputDialog(this, check);
|
||||
d.show();
|
||||
AdjustPictureDialog dialog = AdjustPictureDialog(this, filename.toStdString());
|
||||
connect(&dialog, &AdjustPictureDialog::decodedData, this, &MainWindow::onDataDecode);
|
||||
dialog.exec();
|
||||
}
|
||||
#endif //ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
|
||||
void MainWindow::onDataDecode(std::map<std::string, std::string> data) {
|
||||
ui->fn_line_edit->setText(QString::fromStdString(data["fn"]));
|
||||
ui->fd_line_edit->setText(QString::fromStdString(data["i"]));
|
||||
ui->fi_line_edit->setText(QString::fromStdString(data["fp"]));
|
||||
|
||||
QString extractedDateTime = QString::fromStdString(data["t"]);
|
||||
//TODO: some QRs contain datetime in format yyyyMMddThhmmss. Perhaps there is more different formats, should write function to detect them.
|
||||
QDateTime datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmm");
|
||||
if (datetime == QDateTime::fromString(extractedDateTime, "20000101T1200")) {
|
||||
datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmmss");
|
||||
}
|
||||
ui->purchase_datetime_edit->setDateTime(datetime);
|
||||
|
||||
int type = std::stoi(data["n"]);
|
||||
ui->operation_type_combo_box->setCurrentIndex(type - 1);
|
||||
|
||||
std::string total = data["s"];
|
||||
|
||||
ui->total_spin_box->setValue(std::stod(total));
|
||||
}
|
||||
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
|
||||
void MainWindow::on_parse_email_button_clicked() {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("This feature is under development. Wait it to appear in next updates."));
|
||||
infoDialog.setIcon(QMessageBox::Warning);
|
||||
infoDialog.setWindowTitle(tr("Under development"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#endif // ifdef BUILD_EMAIL_MODE
|
||||
|
||||
void MainWindow::on_parse_button_clicked() {
|
||||
// if (checks.empty()) {
|
||||
// QMessageBox infoDialog;
|
||||
// infoDialog.setText(tr("Please, add check(s) to parse"));
|
||||
// infoDialog.setIcon(QMessageBox::Warning);
|
||||
// infoDialog.setWindowTitle(tr("No checks to parse"));
|
||||
// infoDialog.exec();
|
||||
// return;
|
||||
// }
|
||||
|
||||
OutputDialog d = OutputDialog(this, &checks);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_storeType_currentIndexChanged(int index) {
|
||||
std::string module = parser.search_modules()[index];
|
||||
parser.set_module(module);
|
||||
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;
|
||||
}
|
||||
|
||||
void MainWindow::on_preferencesButton_clicked() {
|
||||
SettingsDialog s = SettingsDialog();
|
||||
s.show();
|
||||
s.exec();
|
||||
checks.push_back(*new_check);
|
||||
|
||||
CheckListViewWidget *check_list_widget = new CheckListViewWidget(this, *new_check);
|
||||
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget(check_list_widget);
|
||||
|
||||
delete new_check;
|
||||
|
||||
if (checks.size() == 1) {
|
||||
ui->checks_scroll_area->show();
|
||||
ui->checks_to_parse_label->show();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_chooseImageButton_ofd_clicked() {
|
||||
QString filename = QFileDialog::getOpenFileName();
|
||||
Check *MainWindow::parse_new_check() {
|
||||
Net net;
|
||||
std::string solved_captcha = "";
|
||||
|
||||
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;
|
||||
}
|
||||
for (unsigned short i = 0; i < 5; i ++) {
|
||||
// Will be repaced with neural network to solve captchas as soon as I train it.
|
||||
net.get_captcha_from_ofdru();
|
||||
SolveCaptchaDialog dialog = SolveCaptchaDialog(this, &solved_captcha);
|
||||
dialog.exec();
|
||||
Check* check = new Check();
|
||||
|
||||
std::string new_text = "Selected: " + filename.toStdString();
|
||||
ui->pathLabel_ofd->setText(QString::fromStdString(new_text));
|
||||
try {
|
||||
std::string check_content = net.fetch_check_data_from_ofdru(
|
||||
ui->fn_line_edit->text().toStdString(),
|
||||
ui->fd_line_edit->text().toStdString(),
|
||||
ui->fi_line_edit->text().toStdString(),
|
||||
ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString(),
|
||||
ui->operation_type_combo_box->currentIndex() + 1,
|
||||
// In the request to ofd.ru, total is in a format with 2 last digits represent decimal part of a number.
|
||||
ui->total_spin_box->text().toDouble() * 100,
|
||||
solved_captcha);
|
||||
|
||||
AdjustPictureDialog dialog = AdjustPictureDialog(this, filename.toStdString());
|
||||
connect(&dialog, &AdjustPictureDialog::decodedData, this, &MainWindow::onDecodedData);
|
||||
dialog.exec();
|
||||
|
||||
ui->picture_ofd->setPixmap(QPixmap(filename));
|
||||
ui->picture_ofd->setScaledContents(true);
|
||||
(*check) = parseOfdRuAnswer(check_content);
|
||||
check->set_date(ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString());
|
||||
check->set_fn(ui->fn_line_edit->text().toStdString());
|
||||
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) {
|
||||
if (!strcmp(e.what(), "Incorrect captcha")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Captcha was not solved correctly!"));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Captcha is incorrect"));
|
||||
infoDialog.exec();
|
||||
continue;
|
||||
} else if (!strcmp(e.what(), "Internal server error")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Internal server error. Please, try again later."));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Internal server error"));
|
||||
infoDialog.exec();
|
||||
return nullptr;
|
||||
} else if (!strcmp(e.what(), "Does not exist")) {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Check not found. Please, ensure correctness of entered data."));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Check was not found"));
|
||||
infoDialog.exec();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::onDecodedData(std::string data) {
|
||||
std::string delimiter = "&";
|
||||
std::vector<std::string> dataSplit = split(data, delimiter);
|
||||
|
||||
std::cout << data << std::endl;
|
||||
|
||||
ui->fn_edit->setText(QString::fromStdString(dataSplit[2]));
|
||||
ui->fd_edit->setText(QString::fromStdString(dataSplit[3]));
|
||||
ui->fi_edit->setText(QString::fromStdString(dataSplit[4]));
|
||||
|
||||
QString extractedDateTime = QString::fromStdString(split(dataSplit[0], "=")[1]);
|
||||
QDateTime datetime = QDateTime::fromString(extractedDateTime, "yyyyMMddThhmm");
|
||||
ui->dateTimeEdit->setDateTime(datetime);
|
||||
|
||||
int type = std::stoi(split(dataSplit[5], "=")[1]);
|
||||
ui->fundIncomeCombo->setCurrentIndex(type - 1);
|
||||
|
||||
std::string total = split(dataSplit[1], "=")[1];
|
||||
|
||||
ui->total_edit->setText(QString::fromStdString(total));
|
||||
MainWindow::~MainWindow() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::on_chooseImageButton_ocr_clicked()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName();
|
||||
|
||||
if (filename == "") {
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("Please, select a picture to scan"));
|
||||
infoDialog.setIcon(QMessageBox::Critical);
|
||||
infoDialog.setWindowTitle(tr("Picture was not selected"));
|
||||
infoDialog.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string new_text = "Selected: " + filename.toStdString();
|
||||
ui->pathLabel_ocr->setText(QString::fromStdString(new_text));
|
||||
|
||||
CheckImage i(filename.toStdString());
|
||||
std::string parsed = i.parse_text();
|
||||
|
||||
ui->picture_ocr->setPixmap(QPixmap(filename));
|
||||
ui->picture_ocr->setScaledContents(true);
|
||||
ui->checkContentFromImage->setPlainText(QString::fromStdString(parsed));
|
||||
}
|
||||
|
||||
|
||||
61
mainwindow.h
@@ -1,44 +1,65 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
#include <thread>
|
||||
|
||||
#include "check/check.h"
|
||||
#include "parser/parser.h"
|
||||
#include <http_server/http_server.h>
|
||||
|
||||
#include <check/check.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
class MainWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Check check;
|
||||
Parser parser;
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
void setupStoresList();
|
||||
|
||||
Check get_check();
|
||||
void onDecodedData(std::string);
|
||||
Check *parse_new_check();
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
void startHttpServer();
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void httpNewMessage(QString message);
|
||||
void httpErrorOccured();
|
||||
void deleteCheckFromList(Check&);
|
||||
|
||||
std::string makeRequestToOfd(std::string captcha);
|
||||
private slots:
|
||||
void on_parseButton_clicked();
|
||||
#ifdef BUILD_OFD_LOCAL_QR_SCAN
|
||||
void on_choose_image_button_clicked();
|
||||
#endif
|
||||
|
||||
void on_storeType_currentIndexChanged(int index);
|
||||
void onDataDecode(std::map<std::string, std::string>);
|
||||
void on_parse_button_clicked();
|
||||
|
||||
void on_preferencesButton_clicked();
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
|
||||
void on_chooseImageButton_ofd_clicked();
|
||||
|
||||
void on_chooseImageButton_ocr_clicked();
|
||||
void on_binary_eye_button_clicked();
|
||||
void notifyHttpServerFailure();
|
||||
void on_stop_server_button_clicked();
|
||||
|
||||
void httpNewMessageHandler(QString message);
|
||||
void deleteCheckFromListHandler(Check&);
|
||||
#endif
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
void on_parse_email_button_clicked();
|
||||
#endif
|
||||
void on_add_new_check_button_clicked();
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
std::vector<Check> checks;
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
std::thread *httpServerThread;
|
||||
HttpServer *server = NULL;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
401
mainwindow.ui
@@ -1,401 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>817</width>
|
||||
<height>659</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<widget class="QComboBox" name="storeType">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>10</y>
|
||||
<width>211</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="storeTypeLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>81</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Store type</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="parseButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>560</y>
|
||||
<width>80</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Parse</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="preferencesButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>730</x>
|
||||
<y>0</y>
|
||||
<width>81</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>801</width>
|
||||
<height>511</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Text">
|
||||
<attribute name="title">
|
||||
<string>Text</string>
|
||||
</attribute>
|
||||
<widget class="QLabel" name="checkContentLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>101</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Check content</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="checkContent">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>611</width>
|
||||
<height>441</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="OCR">
|
||||
<attribute name="title">
|
||||
<string>OCR</string>
|
||||
</attribute>
|
||||
<widget class="QPushButton" name="chooseImageButton_ocr">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>80</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="checkContentFromImage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>60</y>
|
||||
<width>511</width>
|
||||
<height>401</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="pathLabel_ocr">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>100</x>
|
||||
<y>0</y>
|
||||
<width>381</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path to image: </string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>571</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Here is recognised check text. Please, edit it if something's wrong:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="picture_ocr">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>490</x>
|
||||
<y>10</y>
|
||||
<width>291</width>
|
||||
<height>421</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="OFD">
|
||||
<attribute name="title">
|
||||
<string>OFD</string>
|
||||
</attribute>
|
||||
<widget class="QLabel" name="picture_ofd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>490</x>
|
||||
<y>10</y>
|
||||
<width>291</width>
|
||||
<height>421</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="pathLabel_ofd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>100</x>
|
||||
<y>0</y>
|
||||
<width>381</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path to image: </string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="chooseImageButton_ofd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>80</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="fn_edit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>50</y>
|
||||
<width>261</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000000000000000</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="fn_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>161</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FN (Fiscal Number)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="fd_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>161</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FD (Fiscal Document)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="fd_edit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>90</y>
|
||||
<width>261</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000000000</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="fi_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>130</y>
|
||||
<width>161</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FI (Fiscal Identifier)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="fi_edit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>130</y>
|
||||
<width>261</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>0000000000</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QDateTimeEdit" name="dateTimeEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>170</y>
|
||||
<width>194</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="fundIncomeCombo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>210</y>
|
||||
<width>191</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds income</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds return</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds spend</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Spends return</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="total_edit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>250</y>
|
||||
<width>113</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="total_label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>250</y>
|
||||
<width>66</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>817</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuchecks_parser">
|
||||
<property name="title">
|
||||
<string>checks parser</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuchecks_parser"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
10
media.qrc
Normal file
@@ -0,0 +1,10 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>assets/icons/email-text.svg</file>
|
||||
<file>assets/icons/OCR.svg</file>
|
||||
<file>assets/icons/OFD.svg</file>
|
||||
<file>assets/icons/icon.png</file>
|
||||
<file>assets/icons/icon.svg</file>
|
||||
<file>assets/icons/settings.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name":"Магнит",
|
||||
"goods_name_regex": "([\\(\\)\\%\\*a-zA-Z0-9\u0401\u0451\u0410-\u044f \\.\\-\/]{17,100})",
|
||||
"goods_price_regex": "[0-9]{0,4}[^%]\\.[0-9]{2} ",
|
||||
"goods_quantity_regex": "([0-9]{0,4}[^%]\\.[0-9]{3} )|(\t\\d )",
|
||||
"check_start_regex": "",
|
||||
"check_end_regex":""
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name":"Пятёрочка",
|
||||
"goods_name_regex": "([\\(\\)\\%\\*a-zA-Z0-9\u0401\u0451\u0410-\u044f \\.\\-\/]{17,100})",
|
||||
"goods_price_regex": "[0-9]{0,4}[^%]\\.[0-9]{2} ",
|
||||
"goods_quantity_regex": "([0-9]{0,4}[^%]\\.[0-9]{3} )|(\t\\d )",
|
||||
"check_start_regex": "КАССОВЫЙ ЧЕК\nприход",
|
||||
"check_end_regex": "Итог\\:.{0,3}[0-9]{0,6}\\.[0-9]{2}"
|
||||
}
|
||||
52
net/net.cpp
@@ -1,11 +1,15 @@
|
||||
#include "net.h"
|
||||
#include <net/net.h>
|
||||
#include <curl/curl.h>
|
||||
#include "../utils/utils.h"
|
||||
#include <utils/utils.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
|
||||
struct data {};
|
||||
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));
|
||||
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");
|
||||
@@ -16,44 +20,6 @@ size_t write_data(void *buffer, size_t size, size_t nmemb, void *filename) {
|
||||
return written;
|
||||
}
|
||||
|
||||
Net::Net() {}
|
||||
|
||||
void write_modules(void *buffer, size_t size, size_t nmemb, void *modules) {
|
||||
std::vector<std::string> *modules_vector =
|
||||
(std::vector<std::string> *)modules;
|
||||
std::string to_parse = std::string((char*)buffer);
|
||||
|
||||
std::regex r("(?!\\\")\\w+\\.json(?!\\\")", std::regex::collate);
|
||||
std::smatch res;
|
||||
|
||||
std::string::const_iterator search(to_parse.cbegin());
|
||||
while (std::regex_search(search, to_parse.cend(), res, r)) {
|
||||
modules_vector->push_back(res[0]);
|
||||
search = res.suffix().first;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
std::vector<std::string> Net::get_all_modules(std::string url) {
|
||||
CURL *handle = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_modules);
|
||||
|
||||
std::vector<std::string> modules {};
|
||||
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &modules);
|
||||
|
||||
curl_easy_perform(handle);
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
void Net::get_file(std::string url, std::string filename) {
|
||||
CURL *handle = curl_easy_init();
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#include <vector>
|
||||
|
||||
size_t write_data(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
|
||||
{
|
||||
public:
|
||||
Net();
|
||||
std::vector<std::string> get_all_modules(std::string url);
|
||||
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();
|
||||
|
||||
@@ -2,58 +2,12 @@
|
||||
|
||||
OutputOptions::OutputOptions() {}
|
||||
|
||||
void OutputOptions::add_or_update_column(Column &column) {
|
||||
if (column_exist(column.type)) {
|
||||
update_column(column, find_column(column.type));
|
||||
} else {
|
||||
this->order.push_back(column);
|
||||
}
|
||||
}
|
||||
|
||||
void OutputOptions::update_column(Column &column, unsigned short index) {
|
||||
this->order[index] = column;
|
||||
}
|
||||
|
||||
void OutputOptions::remove_column(unsigned short index) {
|
||||
this->order.erase(this->order.begin() + index);
|
||||
}
|
||||
void OutputOptions::remove_column(ColumnType t) {
|
||||
this->order.erase(this->order.begin() + find_column(t));
|
||||
}
|
||||
|
||||
unsigned short OutputOptions::find_column(ColumnType t) {
|
||||
for (unsigned short i = 0; i < this->order.size(); i++) {
|
||||
if (this->order[i].type == t)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool OutputOptions::column_exist(ColumnType t) {
|
||||
for (unsigned short i = 0; i < this->order.size(); i++) {
|
||||
if (this->order[i].type == t)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Column &OutputOptions::get_column(ColumnType t) {
|
||||
return this->order[find_column(t)];
|
||||
}
|
||||
|
||||
std::vector<Column> &OutputOptions::get_columns() { return this->order; }
|
||||
|
||||
void OutputOptions::set_print_header(bool value) { this->print_header = value; }
|
||||
bool OutputOptions::get_print_header() { return this->print_header; }
|
||||
|
||||
void OutputOptions::set_print_total(bool value) { this->print_total = value; }
|
||||
bool OutputOptions::get_print_total() { return this->print_total; }
|
||||
|
||||
OutputFormat OutputOptions::get_output_format() { return this->format; }
|
||||
void OutputOptions::set_output_format(OutputFormat format) {
|
||||
this->format = format;
|
||||
}
|
||||
|
||||
void OutputOptions::set_path(std::string path) { this->path = path; }
|
||||
std::string &OutputOptions::get_path() { return this->path; }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#if __GNUC__ < 8
|
||||
#if __GNUC__ <= 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
#else
|
||||
# include <filesystem>
|
||||
@@ -14,7 +14,8 @@
|
||||
#include "../net/net.h"
|
||||
#include "../settings/settings.h"
|
||||
|
||||
enum class ColumnType {
|
||||
enum ColumnType {
|
||||
date,
|
||||
goods_name,
|
||||
goods_price_per_unit,
|
||||
goods_quantity,
|
||||
@@ -22,45 +23,36 @@ enum class ColumnType {
|
||||
goods_total
|
||||
};
|
||||
|
||||
struct Column { // Example:
|
||||
ColumnType type; // goods_name
|
||||
std::string name; // "Товар"
|
||||
unsigned int position; // "0" <-- 0 = "A", 1 = "B", etc.. column letter in
|
||||
// table processor (i.e. excel or libreoffice)
|
||||
} typedef Column;
|
||||
enum class OutputFormat { csv, ods, xlsx, plaintext } typedef OutputFormat;
|
||||
// Q_DECLARE_METATYPE(ColumnType);
|
||||
|
||||
// struct Column { // Example:
|
||||
// ColumnType type; // goods_name
|
||||
// std::string name; // "Товар"
|
||||
// unsigned int position; // "0" <-- 0 = "A", 1 = "B", etc.. column letter in
|
||||
// // table processor (i.e. excel or libreoffice)
|
||||
// } typedef Column;
|
||||
|
||||
class OutputOptions {
|
||||
|
||||
std::vector<Column> order;
|
||||
bool print_header;
|
||||
bool print_total;
|
||||
OutputFormat format;
|
||||
std::string path;
|
||||
|
||||
public:
|
||||
OutputOptions();
|
||||
|
||||
void add_or_update_column(Column &);
|
||||
void update_column(Column&, unsigned short);
|
||||
void remove_column(unsigned short);
|
||||
void remove_column(ColumnType);
|
||||
unsigned short find_column(ColumnType);
|
||||
bool column_exist(ColumnType);
|
||||
Column& get_column(ColumnType);
|
||||
std::vector<Column>& get_columns();
|
||||
|
||||
void set_print_header(bool);
|
||||
bool get_print_header();
|
||||
|
||||
void set_print_total(bool);
|
||||
bool get_print_total();
|
||||
|
||||
void set_output_format(OutputFormat);
|
||||
OutputFormat get_output_format();
|
||||
|
||||
void set_path(std::string);
|
||||
std::string &get_path();
|
||||
};
|
||||
|
||||
#endif // OUTPUT_OPTIONS_H
|
||||
|
||||
|
||||
|
||||
169
outputdialog.cpp
@@ -3,121 +3,93 @@
|
||||
#include "output/output_options.h"
|
||||
#include "ui_outputdialog.h"
|
||||
#include <QFileDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QMainWindow>
|
||||
#include <QStandardItemModel>
|
||||
#include <fstream>
|
||||
#include <outputcolumn.h>
|
||||
#include <outputcolumnmodel.h>
|
||||
#include "settings/settings.h"
|
||||
#include "utils/utils.h"
|
||||
#include <map>
|
||||
|
||||
OutputDialog::OutputDialog(QWidget *parent, Check &check)
|
||||
: QDialog(parent), ui(new Ui::OutputDialog), check(check),
|
||||
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);
|
||||
|
||||
ui->tableWidget->item(0, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_name"]["name"]));
|
||||
ui->tableWidget->item(0, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_name"]["position"]));
|
||||
columns = new std::vector<OutputColumn>;
|
||||
|
||||
ui->tableWidget->item(1, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"]));
|
||||
ui->tableWidget->item(1, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"]));
|
||||
OutputColumnModel *model = new OutputColumnModel(&(*columns), this);
|
||||
|
||||
ui->tableWidget->item(2, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_quantity"]["name"]));
|
||||
ui->tableWidget->item(2, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_quantity"]["position"]));
|
||||
ui->listView->setModel(model);
|
||||
|
||||
ui->tableWidget->item(3, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_net_weight"]["name"]));
|
||||
ui->tableWidget->item(3, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]));
|
||||
for (unsigned short i = 0; i < 6; i ++)
|
||||
columns->push_back(OutputColumn(tr("Кто здесь?"), ColumnType::date));
|
||||
|
||||
ui->tableWidget->item(4, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_total"]["name"]));
|
||||
ui->tableWidget->item(4, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_total"]["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->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; }
|
||||
|
||||
bool compare_position(Column &c1, Column &c2) {
|
||||
return c1.position < c2.position;
|
||||
OutputDialog::~OutputDialog() {
|
||||
delete settings;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void OutputDialog::on_buttonBox_accepted() {
|
||||
std::ofstream output_file(this->options.get_path());
|
||||
|
||||
for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
|
||||
int position = ui->tableWidget->item(i, 0)->text().toInt();
|
||||
std::string name = ui->tableWidget->item(i, 1)->text().toStdString();
|
||||
print_header(&output_file);
|
||||
|
||||
Column c;
|
||||
c.type = static_cast<ColumnType>(i);
|
||||
c.position = position;
|
||||
c.name = name;
|
||||
for (Check &check : *checks) {
|
||||
int row_number = 0;
|
||||
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);
|
||||
switch (column.get_column_type()) {
|
||||
case ColumnType::date:
|
||||
if (row_number == 0) output_file << check.get_date();
|
||||
break;
|
||||
case ColumnType::goods_name:
|
||||
output_file << it->get_name();
|
||||
break;
|
||||
case ColumnType::goods_price_per_unit:
|
||||
output_file << std::fixed << std::setprecision(2) << it->get_price_per_unit();
|
||||
break;
|
||||
case ColumnType::goods_quantity:
|
||||
output_file << std::fixed << std::setprecision(2) << it->get_quantity();
|
||||
break;
|
||||
case ColumnType::goods_net_weight:
|
||||
output_file << it->get_net_weight();
|
||||
break;
|
||||
case ColumnType::goods_total:
|
||||
output_file << std::fixed << std::setprecision(2) << it->calculate_total_price();
|
||||
break;
|
||||
}
|
||||
|
||||
this->options.add_or_update_column(c);
|
||||
}
|
||||
|
||||
std::sort(this->options.get_columns().begin(),
|
||||
this->options.get_columns().end(), compare_position);
|
||||
|
||||
if (options.get_print_header()) {
|
||||
for (auto &column : this->options.get_columns()) {
|
||||
output_file << column.name
|
||||
<< (column.position == this->options.get_columns().size()
|
||||
? ""
|
||||
: ",");
|
||||
}
|
||||
output_file << std::endl;
|
||||
}
|
||||
|
||||
for (auto goods : this->check.get_goods()) {
|
||||
for (auto &column : this->options.get_columns()) {
|
||||
switch (column.type) {
|
||||
case ColumnType::goods_name:
|
||||
output_file << goods.get_name();
|
||||
break;
|
||||
case ColumnType::goods_price_per_unit:
|
||||
output_file << std::fixed << std::setprecision(2) << goods.get_price_per_unit();
|
||||
break;
|
||||
case ColumnType::goods_quantity:
|
||||
output_file << std::fixed << std::setprecision(2) << goods.get_quantity();
|
||||
break;
|
||||
case ColumnType::goods_net_weight:
|
||||
output_file << "TODO";
|
||||
// TODO
|
||||
break;
|
||||
case ColumnType::goods_total:
|
||||
output_file << std::fixed << std::setprecision(2) << goods.calculate_total_price();
|
||||
break;
|
||||
}
|
||||
|
||||
if (column.position != this->options.get_columns().size()) {
|
||||
output_file << ",";
|
||||
} else {
|
||||
output_file << "\n";
|
||||
if (i < columns->size() - 1) {
|
||||
output_file << ",";
|
||||
} else {
|
||||
output_file << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->options.get_print_total()) {
|
||||
output_file << "Total: " << std::fixed << std::setprecision(2) << check.calculae_total_price() << std::endl;
|
||||
if (this->options.get_print_total()) {
|
||||
output_file << "Total: " << std::fixed << std::setprecision(2) << check.calculae_total_price() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
output_file.close();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
save_settings();
|
||||
}
|
||||
|
||||
void OutputDialog::on_chooseFileButton_clicked() {
|
||||
@@ -133,3 +105,26 @@ void OutputDialog::on_printHeaderCheckBox_stateChanged(int value) {
|
||||
void OutputDialog::on_printTotalCheckBox_stateChanged(int value) {
|
||||
this->options.set_print_total(value);
|
||||
}
|
||||
|
||||
void OutputDialog::print_header(std::ofstream *output_file) {
|
||||
if (options.get_print_header()) {
|
||||
for (unsigned int i = 0; i < columns->size(); i ++) {
|
||||
OutputColumn column = columns->at(i);
|
||||
(*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();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "output/output_options.h"
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <outputcolumn.h>
|
||||
|
||||
namespace Ui {
|
||||
class OutputDialog;
|
||||
@@ -14,10 +15,21 @@ class OutputDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
OutputOptions options;
|
||||
Check ✓
|
||||
std::vector<Check> *checks;
|
||||
std::vector<OutputColumn> *columns;
|
||||
Settings *settings;
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
public:
|
||||
explicit OutputDialog(QWidget *parent = nullptr, Check & = *(new Check()));
|
||||
explicit OutputDialog(QWidget *parent = nullptr, std::vector<Check> *checks = nullptr);
|
||||
~OutputDialog();
|
||||
|
||||
private slots:
|
||||
@@ -31,6 +43,10 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::OutputDialog *ui;
|
||||
|
||||
void print_header(std::ofstream *output_file);
|
||||
|
||||
void save_settings();
|
||||
};
|
||||
|
||||
#endif // OUTPUTDIALOG_H
|
||||
|
||||
215
outputdialog.ui
@@ -1,215 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OutputDialog</class>
|
||||
<widget class="QDialog" name="OutputDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>586</width>
|
||||
<height>431</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>410</x>
|
||||
<y>390</y>
|
||||
<width>166</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="pathLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>271</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path to export: </string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="chooseFileButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>290</x>
|
||||
<y>20</y>
|
||||
<width>80</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="printHeaderCheckBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>111</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Print header</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>130</y>
|
||||
<width>401</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Goods name</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Goods price</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Goods quantity</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Goods net weight</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Goods total</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>position</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>name</string>
|
||||
</property>
|
||||
</column>
|
||||
<item row="0" column="0">
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<property name="text">
|
||||
<string>2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<property name="text">
|
||||
<string>Price</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<property name="text">
|
||||
<string>Quantity</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<property name="text">
|
||||
<string>Net weight</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<property name="text">
|
||||
<string>5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<property name="text">
|
||||
<string>Total price</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="printTotalCheckBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>111</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Print total</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>OutputDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>OutputDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,93 +0,0 @@
|
||||
#include "module.h"
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include "../utils/utils.h"
|
||||
|
||||
StoreModule::StoreModule() {}
|
||||
|
||||
StoreModule::StoreModule(std::string path) {
|
||||
std::ifstream settings_file(path);
|
||||
nlohmann::json settings = nlohmann::json::parse(settings_file);
|
||||
|
||||
this->name = from_utf8(settings["name"]);
|
||||
this->goods_name_regex = from_utf8(settings["goods_name_regex"]);
|
||||
this->goods_price_regex = from_utf8(settings["goods_price_regex"]);
|
||||
this->goods_quantity_regex = from_utf8(settings["goods_quantity_regex"]);
|
||||
this->check_start_regex = from_utf8(settings["check_start_regex"]);
|
||||
this->check_end_regex = from_utf8(settings["check_end_regex"]);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::wcout << "Name: " << this->name << std::endl;
|
||||
std::wcout << "Goods name regex: " << this->goods_name_regex << std::endl;
|
||||
std::wcout << "Goods price regex: " << this->goods_price_regex << std::endl;
|
||||
std::wcout << "Goods quantity regex: " << this->goods_quantity_regex
|
||||
<< std::endl;
|
||||
std::wcout << "Check start regex: " << this->check_start_regex << std::endl;
|
||||
std::wcout << "Check end regex: " << this->check_end_regex << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_name(std::wstring str) {
|
||||
std::vector<std::string> result;
|
||||
std::wregex r(this->goods_name_regex, std::regex::collate);
|
||||
|
||||
for (std::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_price(std::wstring str) {
|
||||
std::vector<std::string> result;
|
||||
std::wregex r(this->goods_price_regex, std::regex::collate);
|
||||
|
||||
for (std::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_quantity(std::wstring str) {
|
||||
std::vector<std::string> result;
|
||||
std::wregex r(this->goods_quantity_regex, std::regex::collate);
|
||||
|
||||
for (std::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring StoreModule::trim_check(std::wstring& check) {
|
||||
unsigned int start_pos;
|
||||
unsigned int end_pos;
|
||||
|
||||
std::wregex start_regex(this->check_start_regex, std::regex::collate);
|
||||
std::wregex end_regex(this->check_end_regex, std::regex::collate);
|
||||
|
||||
for (std::wsregex_iterator it{check.begin(), check.end(), start_regex}, end{};
|
||||
it != end; it++) {
|
||||
start_pos = it->position() + it->str().size();
|
||||
break;
|
||||
}
|
||||
|
||||
check = check.substr(start_pos, check.size());
|
||||
|
||||
for (std::wsregex_iterator it{check.begin(), check.end(), end_regex}, end{};
|
||||
it != end; it++) {
|
||||
end_pos = it->position() - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
check = check.substr(0, end_pos);
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
std::wstring StoreModule::get_name() { return this->name; }
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef STORE_MODULE_H
|
||||
#define STORE_MODULE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class StoreModule {
|
||||
std::string path;
|
||||
std::wstring name;
|
||||
std::wstring goods_name_regex;
|
||||
std::wstring goods_price_regex;
|
||||
std::wstring goods_quantity_regex;
|
||||
std::wstring check_start_regex;
|
||||
std::wstring check_end_regex;
|
||||
public:
|
||||
StoreModule(std::string);
|
||||
StoreModule();
|
||||
|
||||
std::vector<std::string> parse_name(std::wstring);
|
||||
std::vector<std::string> parse_price(std::wstring);
|
||||
std::vector<std::string> parse_quantity(std::wstring);
|
||||
std::wstring trim_check(std::wstring&);
|
||||
|
||||
|
||||
std::wstring get_name();
|
||||
};
|
||||
|
||||
#endif // STORE_MODULE_H
|
||||
@@ -1,103 +0,0 @@
|
||||
#include "parser.h"
|
||||
#include "../goods/goods.h"
|
||||
#include "../net/net.h"
|
||||
#include "../settings/settings.h"
|
||||
#include "../utils/utils.h"
|
||||
#include <iostream>
|
||||
|
||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
using namespace std::experimental;
|
||||
using namespace std::experimental::filesystem;
|
||||
#else
|
||||
# include <filesystem>
|
||||
using namespace std::filesystem;
|
||||
#endif
|
||||
|
||||
Parser::Parser() {}
|
||||
|
||||
std::vector<std::string> Parser::search_modules() {
|
||||
Settings s(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
|
||||
std::string path = get_path_relative_to_home(s.get_setting("stores_modules_dir"));//std::string(std::getenv("HOME")) + "/" + STORES_MODULES_DIR;
|
||||
directory_entry modules_dir(path);
|
||||
|
||||
if (!exists(modules_dir)) {
|
||||
create_directories(path);
|
||||
std::cout << "No modules directory found. Created one at " << path
|
||||
<< std::endl;
|
||||
std::cout << "Please, download modules to that directory from my git."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::vector<std::string> modules_files;
|
||||
|
||||
for (auto file : directory_iterator(path)) {
|
||||
modules_files.push_back(file.path());
|
||||
}
|
||||
|
||||
return modules_files;
|
||||
}
|
||||
|
||||
void Parser::set_module(std::string path) { module = StoreModule(path); }
|
||||
|
||||
std::vector<Goods> Parser::parse(std::wstring check_plaintext) {
|
||||
std::vector<Goods> result;
|
||||
|
||||
module.trim_check(check_plaintext);
|
||||
|
||||
std::vector<std::string> goods_names = module.parse_name(check_plaintext);
|
||||
std::vector<std::string> goods_prices = module.parse_price(check_plaintext);
|
||||
std::vector<std::string> goods_quantities =
|
||||
module.parse_quantity(check_plaintext);
|
||||
|
||||
if (goods_names.size() != goods_prices.size() ||
|
||||
goods_names.size() != goods_quantities.size() ||
|
||||
goods_prices.size() != goods_quantities.size()) {
|
||||
//Error. Amount of names, prices or quantities are not equal. That means, that some regex(es) has mismatched.
|
||||
return {};
|
||||
}
|
||||
short goods_amount = goods_names.size();
|
||||
|
||||
for (short i = 0; i < goods_amount; i++) {
|
||||
Goods goods(goods_names[i], std::stof(goods_prices[i]), std::stof(goods_quantities[i]));
|
||||
|
||||
result.push_back(goods);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> Parser::check_updates() {
|
||||
std::cout << "Checking updates for stores modules" << std::endl;
|
||||
Settings s(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
|
||||
std::string path = get_path_relative_to_home(s.get_setting("stores_modules_dir"));
|
||||
|
||||
std::vector<std::string> to_download;
|
||||
std::vector<std::string> stored_modules;
|
||||
|
||||
directory_entry modules_dir(path);
|
||||
if (!exists(modules_dir)) {
|
||||
create_directories(path);
|
||||
}
|
||||
for (const auto& file : directory_iterator(path)) {
|
||||
if (!is_regular_file(file)) continue;
|
||||
stored_modules.push_back(file.path().filename());
|
||||
std::cout << file.path().filename() << " detected store module" << std::endl;
|
||||
}
|
||||
Net n;
|
||||
std::cerr << "Downloading modules list from: " << s.get_setting("stores_modules_url") << std::endl;
|
||||
std::vector<std::string> remote_modules = n.get_all_modules(s.get_setting("stores_modules_url"));
|
||||
if (stored_modules.empty()) {
|
||||
std::cout << "I need to download everything" << std::endl;
|
||||
to_download = remote_modules;
|
||||
} else {
|
||||
for (const std::string& module : remote_modules) {
|
||||
if (!vector_contains_element(stored_modules, module)) {
|
||||
std::cout << "I need to download store module " << module << std::endl;
|
||||
to_download.push_back(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to_download;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include "../goods/goods.h"
|
||||
#include "module.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Parser {
|
||||
|
||||
StoreModule module;
|
||||
|
||||
public:
|
||||
Parser();
|
||||
|
||||
std::vector<std::string> search_modules();
|
||||
|
||||
std::vector<std::string> check_updates();
|
||||
|
||||
void set_module(std::string);
|
||||
|
||||
std::vector<Goods> parse(std::wstring);
|
||||
};
|
||||
|
||||
#endif // PARSER_H
|
||||
8
scenes.qrc
Normal file
@@ -0,0 +1,8 @@
|
||||
<RCC>
|
||||
<qresource prefix="/scenes">
|
||||
<file>scenes/outputdialog.ui</file>
|
||||
<file>scenes/mainwindow.ui</file>
|
||||
<file>scenes/settingsdialog.ui</file>
|
||||
<file>scenes/solvecaptchadialog.ui</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
95
scenes/adjustpicturedialog.ui
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdjustPictureDialog</class>
|
||||
<widget class="QDialog" name="AdjustPictureDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>825</width>
|
||||
<height>497</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="ImageRedactor" name="graphicsView"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSlider" name="contrastSlider">
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please, zoom to qr code and adjust contrast so that qr code looks sharp</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>label</zorder>
|
||||
<zorder>contrastSlider</zorder>
|
||||
<zorder>graphicsView</zorder>
|
||||
<zorder>buttonBox</zorder>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ImageRedactor</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header location="global">imageredactor.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AdjustPictureDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AdjustPictureDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
301
scenes/mainwindow.ui
Normal file
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QWidget" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1269</width>
|
||||
<height>490</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>971</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="or_label_1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>or</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="datetime_label">
|
||||
<property name="text">
|
||||
<string>Date and time of purchase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="fd_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FD (Fiscal Document)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="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">
|
||||
<widget class="QComboBox" name="operation_type_combo_box">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds income</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds return</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Funds spend</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Spends return</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="operation_type_label">
|
||||
<property name="text">
|
||||
<string>Operation type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="parse_email_button">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Parse an E-Mail</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<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</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">
|
||||
<property name="text">
|
||||
<string>Add new check</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>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
114
scenes/outputdialog.ui
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OutputDialog</class>
|
||||
<widget class="QDialog" name="OutputDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>892</width>
|
||||
<height>537</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="pathLabel">
|
||||
<property name="text">
|
||||
<string>Path to export: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="printTotalCheckBox">
|
||||
<property name="text">
|
||||
<string>Print total</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="chooseFileButton">
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QListView" name="listView">
|
||||
<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::TargetMoveAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="printHeaderCheckBox">
|
||||
<property name="text">
|
||||
<string>Print header</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>OutputDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>OutputDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
256
scenes/settingsdialog.ui
Normal file
@@ -0,0 +1,256 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>settingsdialog</class>
|
||||
<widget class="QDialog" name="settingsdialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>693</width>
|
||||
<height>616</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>659</width>
|
||||
<height>634</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="14" column="1">
|
||||
<widget class="QComboBox" name="languageComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>en_US</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ru_RU</string>
|
||||
</property>
|
||||
</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">
|
||||
<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">
|
||||
<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">
|
||||
<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>
|
||||
</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>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>settingsdialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>settingsdialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -2,9 +2,8 @@
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include "../utils/utils.h"
|
||||
|
||||
#if __GNUC__ < 8 && __clang_major__ < 17
|
||||
#if __GNUC__ <= 8 && __clang_major__ < 17
|
||||
# include <experimental/filesystem>
|
||||
using namespace std::experimental;
|
||||
using namespace std::experimental::filesystem;
|
||||
@@ -20,37 +19,37 @@ Settings::Settings(std::string path) {
|
||||
std::ofstream output(path);
|
||||
|
||||
nlohmann::json settings = R"({
|
||||
"ofds_modules_dir":".local/share/checks_parser/modules/ofd",
|
||||
"stores_modules_dir":".local/share/checks_parser/modules/stores",
|
||||
"ofds_modules_url":"https://foxarmy.org/checks-parser/modules/ofd/",
|
||||
"stores_modules_url":"https://foxarmy.org/checks-parser/modules/stores/",
|
||||
"print_header": true,
|
||||
"print_total": true,
|
||||
"output_order": {
|
||||
"goods_name": {
|
||||
"date" : {
|
||||
"position":1,
|
||||
"name": "Date"
|
||||
},
|
||||
"goods_name": {
|
||||
"position":2,
|
||||
"name":"Goods name"
|
||||
},
|
||||
"goods_price_per_unit": {
|
||||
"position":2,
|
||||
"position":3,
|
||||
"name":"Goods price per unit"
|
||||
},
|
||||
"goods_quantity": {
|
||||
"position":3,
|
||||
"position":4,
|
||||
"name":"Goods quantity"
|
||||
},
|
||||
"goods_net_weight": {
|
||||
"position":4,
|
||||
"position":5,
|
||||
"name":"Goods net weight"
|
||||
},
|
||||
"goods_total": {
|
||||
"position":5,
|
||||
"position":6,
|
||||
"name":"Goods total"
|
||||
}
|
||||
}
|
||||
})"_json;
|
||||
|
||||
output << settings;
|
||||
output << settings.dump(4);
|
||||
output.flush();
|
||||
output.close();
|
||||
this->settings = settings;
|
||||
@@ -60,9 +59,6 @@ Settings::Settings(std::string path) {
|
||||
nlohmann::json settings = nlohmann::json::parse(input);
|
||||
this->settings = settings;
|
||||
}
|
||||
|
||||
create_directories(get_path_relative_to_home(this->settings["ofds_modules_dir"]));
|
||||
create_directories(get_path_relative_to_home(this->settings["stores_modules_dir"]));
|
||||
}
|
||||
|
||||
void Settings::write_setting(std::string setting, std::string value) {
|
||||
@@ -70,7 +66,7 @@ void Settings::write_setting(std::string setting, std::string value) {
|
||||
|
||||
this->settings[setting] = value;
|
||||
|
||||
output << this->settings;
|
||||
output << this->settings.dump(4);
|
||||
}
|
||||
std::string Settings::get_setting(std::string setting) {
|
||||
return this->settings[setting];
|
||||
@@ -93,5 +89,5 @@ void Settings::alter_setting(std::string setting, std::string value) {
|
||||
void Settings::flush() {
|
||||
std::ofstream output(this->settings_file_path, std::fstream::trunc);
|
||||
|
||||
output << this->settings;
|
||||
output << this->settings.dump(4);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#include "settingsdialog.h"
|
||||
#include "settings/settings.h"
|
||||
#include "ui_settingsdialog.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include <settings/settings.h>
|
||||
#include <utils/utils.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::settingsdialog),
|
||||
@@ -10,11 +15,6 @@ SettingsDialog::SettingsDialog(QWidget *parent)
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->OFDModulesDirEdit->setText(QString::fromStdString(settings.get_all_settings()["ofds_modules_dir"]));
|
||||
ui->OFDModulesURLEdit->setText(QString::fromStdString(settings.get_all_settings()["ofds_modules_url"]));
|
||||
ui->storesModulesDirEdit->setText(QString::fromStdString(settings.get_all_settings()["stores_modules_dir"]));
|
||||
ui->storesModulesURLEdit->setText(QString::fromStdString(settings.get_all_settings()["stores_modules_url"]));
|
||||
|
||||
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"]));
|
||||
|
||||
@@ -32,28 +32,23 @@ SettingsDialog::SettingsDialog(QWidget *parent)
|
||||
|
||||
ui->printHeaderCheckBox->setChecked(this->settings.get_all_settings()["print_header"]);
|
||||
ui->printTotalCheckBox->setChecked(this->settings.get_all_settings()["print_total"]);
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog() { delete ui; }
|
||||
int currentLanguageIndex = 0;
|
||||
bool languageSettingPresent = false;
|
||||
|
||||
void SettingsDialog::on_OFDModulesDirEdit_editingFinished() {
|
||||
this->settings.alter_setting("ofds_modules_dir",
|
||||
ui->OFDModulesDirEdit->text().toStdString());
|
||||
}
|
||||
languageSettingPresent = settings.get_all_settings().find("language") != settings.get_all_settings().end();
|
||||
|
||||
void SettingsDialog::on_storesModulesDirEdit_editingFinished() {
|
||||
this->settings.alter_setting("stores_modules_dir",
|
||||
ui->storesModulesDirEdit->text().toStdString());
|
||||
}
|
||||
if (languageSettingPresent) {
|
||||
currentLanguageIndex = ui->languageComboBox->findText(QString::fromStdString(this->settings.get_all_settings()["language"]));
|
||||
|
||||
void SettingsDialog::on_OFDModulesURLEdit_editingFinished() {
|
||||
this->settings.alter_setting("ofds_modules_url",
|
||||
ui->OFDModulesURLEdit->text().toStdString());
|
||||
}
|
||||
} else {
|
||||
currentLanguageIndex = ui->languageComboBox->findText(QLocale::system().name());
|
||||
if (currentLanguageIndex < 0) {
|
||||
currentLanguageIndex = ui->languageComboBox->findText("en_US");
|
||||
}
|
||||
}
|
||||
ui->languageComboBox->setCurrentIndex(currentLanguageIndex);
|
||||
|
||||
void SettingsDialog::on_storesModulesURLEdit_editingFinished() {
|
||||
this->settings.alter_setting("stores_modules_url",
|
||||
ui->storesModulesURLEdit->text().toStdString());
|
||||
}
|
||||
|
||||
void SettingsDialog::on_goodsNamePositionSpin_valueChanged(int value) {
|
||||
@@ -121,4 +116,26 @@ void SettingsDialog::on_buttonBox_accepted() { this->settings.flush(); }
|
||||
|
||||
void SettingsDialog::on_buttonBox_rejected() { this->close(); }
|
||||
|
||||
void SettingsDialog::on_languageComboBox_currentTextChanged(const QString &changed) {
|
||||
bool languageSettingPresent = false;
|
||||
|
||||
languageSettingPresent = settings.get_all_settings().find("language") != settings.get_all_settings().end();
|
||||
|
||||
if (languageSettingPresent) {
|
||||
if (changed == QString::fromStdString(this->settings.get_all_settings()["language"])) return;
|
||||
} else {
|
||||
if (changed == QLocale::system().name()) return;
|
||||
}
|
||||
|
||||
this->settings.get_all_settings()["language"] = changed.toStdString();
|
||||
|
||||
QMessageBox infoDialog;
|
||||
infoDialog.setText(tr("You need to restart program to apply language changes"));
|
||||
infoDialog.setIcon(QMessageBox::Information);
|
||||
infoDialog.setWindowTitle(tr("Restart required"));
|
||||
infoDialog.exec();
|
||||
}
|
||||
|
||||
|
||||
SettingsDialog::~SettingsDialog() { delete ui; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define SETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "settings/settings.h"
|
||||
#include <settings/settings.h>
|
||||
|
||||
namespace Ui {
|
||||
class settingsdialog;
|
||||
@@ -16,44 +16,35 @@ public:
|
||||
~SettingsDialog();
|
||||
|
||||
private slots:
|
||||
void on_OFDModulesDirEdit_editingFinished();
|
||||
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_storesModulesDirEdit_editingFinished();
|
||||
|
||||
void on_OFDModulesURLEdit_editingFinished();
|
||||
|
||||
void on_storesModulesURLEdit_editingFinished();
|
||||
|
||||
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_goodsTotalPositionSpin_valueChanged(int arg1);
|
||||
void on_goodsTotalAliasEdit_editingFinished();
|
||||
|
||||
void on_printTotalCheckBox_stateChanged(int arg1);
|
||||
void on_printHeaderCheckBox_stateChanged(int arg1);
|
||||
|
||||
void on_printTotalCheckBox_stateChanged(int arg1);
|
||||
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
void on_languageComboBox_currentTextChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
Ui::settingsdialog *ui;
|
||||
public:
|
||||
bool settingsExist();
|
||||
};
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
||||
|
||||
@@ -1,285 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>settingsdialog</class>
|
||||
<widget class="QDialog" name="settingsdialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>599</width>
|
||||
<height>727</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>310</x>
|
||||
<y>690</y>
|
||||
<width>251</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>541</width>
|
||||
<height>661</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>539</width>
|
||||
<height>659</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QWidget" name="gridLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>531</width>
|
||||
<height>651</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="11" column="1">
|
||||
<widget class="QLineEdit" name="goodsNetWeightAliasEdit"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="storesModulesDirEdit"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Goods name position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Goods price per unit alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="storedModulesDirChooseButton">
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QLineEdit" name="goodsTotalAliasEdit"/>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Print header</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Goods net weight alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Stores modules url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="storesModulesURLEdit"/>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Goods total alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Goods name alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QSpinBox" name="goodsTotalPositionSpin"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Goods quantity alias</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Stores modules directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="goodsNameAliasEdit"/>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="goodsNetWeightPositionSpin"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>OFD modules directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="goodsNamePositionSpin"/>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="goodsQuantityAliasEdit"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="goodsPricePerUnitAliasEdit"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Goods price per unit position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Goods net weight position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>OFD modules url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="OFDModulesDirEdit"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Goods total position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Goods quantity position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="OFDModulesURLEdit"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="goodsQuantityPositionSpin"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="OFDModulesDirChooseButton">
|
||||
<property name="text">
|
||||
<string>Choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="goodsPricePerUnitPositionSpin"/>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Print total</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="printHeaderCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QCheckBox" name="printTotalCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>settingsdialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>settingsdialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -11,7 +11,6 @@ SolveCaptchaDialog::SolveCaptchaDialog(QWidget *parent, std::string* solved_capt
|
||||
ui->setupUi(this);
|
||||
|
||||
QString captcha_path = QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/captcha.jpg"));
|
||||
std::cout << captcha_path.toStdString() << std::endl;
|
||||
ui->captcha_picture->setPixmap(captcha_path);
|
||||
ui->captcha_picture->setScaledContents(true);
|
||||
}
|
||||
|
||||
6
translations.qrc
Normal file
@@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/translation">
|
||||
<file>en_US.qm</file>
|
||||
<file>ru_RU.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,404 +1,782 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<TS version="2.1" language="en_US">
|
||||
<context>
|
||||
<name>AdjustPictureDialog</name>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.ui" line="14"/>
|
||||
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.ui" line="58"/>
|
||||
<location filename="../scenes/adjustpicturedialog.ui" line="33"/>
|
||||
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Please, zoom to qr code and adjust contrast so that qr code looks sharp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="39"/>
|
||||
<source>QR code was not detected on that image. Please edit it again or enter data manually</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>QR code was not detected on that image. Please edit it again or enter data manually</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="41"/>
|
||||
<source>No QR code</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>No QR code</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EmailTextScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store type</source>
|
||||
<translation type="obsolete">Store type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check content</source>
|
||||
<translation type="vanished">Check content</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store:</source>
|
||||
<translation type="vanished">Store:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Error in parsing</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="14"/>
|
||||
<source>MainWindow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Главное окно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="37"/>
|
||||
<source>Store type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Store type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="50"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Parse</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="63"/>
|
||||
<source>Preferences</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Preferences</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="80"/>
|
||||
<source>Text</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Text</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="92"/>
|
||||
<source>Check content</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Check content</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>OCR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>OCR = Optical Character Recognition</translatorcomment>
|
||||
<translation type="vanished">OCR</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="120"/>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="143"/>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>Path to image: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Path to image: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="156"/>
|
||||
<source>Here is recognised check text. Please, edit it if something's wrong:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Here is recognised check text. Please, edit it if something's wrong:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="175"/>
|
||||
<source>OFD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>OFD = Оператор Фискальных Данных</translatorcomment>
|
||||
<translation type="vanished">OFD</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="226"/>
|
||||
<source>0000000000000000</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">0000000000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="245"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>FN = Фискальный Номер</translatorcomment>
|
||||
<translation>FN (Fiscal Number)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="264"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="58"/>
|
||||
<source>FD (Fiscal Document)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>FD = Фискальный Документ</translatorcomment>
|
||||
<translation>FD (Fiscal Document)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="277"/>
|
||||
<location filename="../mainwindow.ui" line="309"/>
|
||||
<source>0000000000</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="296"/>
|
||||
<source>Back</source>
|
||||
<translation type="obsolete">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
||||
<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>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
||||
<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>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>FI = Фискальный Признак</translatorcomment>
|
||||
<translation>FI (Fiscal Identifier)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="333"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="273"/>
|
||||
<source>Add new check</source>
|
||||
<translation>Add new check</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
||||
<source>Clear</source>
|
||||
<translation>Clear</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation>Date and time of purchase</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
||||
<source>Operation type</source>
|
||||
<translation>Operation type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
||||
<source>Parse an E-Mail</source>
|
||||
<translation>Parse an E-Mail</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="214"/>
|
||||
<source>Funds income</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Приход средств</translatorcomment>
|
||||
<translation>Funds income</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
||||
<source>Funds return</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Возврат средств</translatorcomment>
|
||||
<translation>Funds return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="343"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
||||
<source>Funds spend</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Расход средств</translatorcomment>
|
||||
<translation>Funds spend</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="348"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
||||
<source>Spends return</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Возврат расхода</translatorcomment>
|
||||
<translation>Spends return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="375"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
||||
<source>Checks to parse</source>
|
||||
<translation>Checks to parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="108"/>
|
||||
<source>Settings</source>
|
||||
<translation>Settings</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="128"/>
|
||||
<source>Total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>checks parser</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">checks parser</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="85"/>
|
||||
<location filename="../mainwindow.cpp" line="101"/>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation>QR code for binaryeye to connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="102"/>
|
||||
<source>I've scanned</source>
|
||||
<translation>I've scanned</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="108"/>
|
||||
<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"/>
|
||||
<source>Could not start http server.</source>
|
||||
<translation>Could not start http server.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="154"/>
|
||||
<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>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="189"/>
|
||||
<source>Under development</source>
|
||||
<translation>Under development</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, add check(s) to parse</source>
|
||||
<translation type="vanished">Please, add check(s) to parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No checks to parse</source>
|
||||
<translation type="vanished">No checks to parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="287"/>
|
||||
<source>Captcha was not solved correctly!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Captcha was not solved correctly!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="87"/>
|
||||
<location filename="../mainwindow.cpp" line="289"/>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Captcha is incorrect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="92"/>
|
||||
<location filename="../mainwindow.cpp" line="294"/>
|
||||
<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"/>
|
||||
<source>Internal server error</source>
|
||||
<translation>Internal server error</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="301"/>
|
||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Check not found. Please, ensure correctness of entered data.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="94"/>
|
||||
<location filename="../mainwindow.cpp" line="303"/>
|
||||
<source>Check was not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Check was not found</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="145"/>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Error in parsing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="147"/>
|
||||
<location filename="../mainwindow.cpp" line="193"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation>Please, select a picture where QR code that contains info about check is present</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="149"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation>Picture was not selected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="191"/>
|
||||
<source>Please, select a picture to scan</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Please, select a picture to scan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="26"/>
|
||||
<source>Form</source>
|
||||
<translation>Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Optical Character Recognition</source>
|
||||
<translation type="vanished">Optical Character Recognition</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text from E-Mail</source>
|
||||
<translation type="vanished">Text from E-Mail</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OCRScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Choose</source>
|
||||
<translation type="vanished">Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Path to image:</source>
|
||||
<translation type="vanished">Path to image:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store:</source>
|
||||
<translation type="vanished">Store:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Recognized text will be shown below as soon as image will be processed. Please, edit it</source>
|
||||
<translation type="vanished">Recognized text will be shown below as soon as image will be processed. Please, edit it</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Error in parsing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture to scan</source>
|
||||
<translation type="vanished">Please, select a picture to scan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="vanished">Picture was not selected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Path to image: </source>
|
||||
<translation type="vanished">Path to image: </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OFDScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Total</source>
|
||||
<translation type="vanished">Total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>or</source>
|
||||
<translation type="vanished">or</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FD (Fiscal Document)</source>
|
||||
<translation type="vanished">FD (Fiscal Document)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation type="vanished">Date and time of purchase</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop server</source>
|
||||
<translation type="vanished">Stop server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds income</source>
|
||||
<translation type="vanished">Funds income</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds return</source>
|
||||
<translation type="vanished">Funds return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds spend</source>
|
||||
<translation type="vanished">Funds spend</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Spends return</source>
|
||||
<translation type="vanished">Spends return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use your phone as a QR code scanner</source>
|
||||
<translation type="vanished">Use your phone as a QR code scanner</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translation type="vanished">FN (Fiscal Number)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translation type="vanished">FI (Fiscal Identifier)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Choose image on your PC</source>
|
||||
<translation type="vanished">Choose image on your PC</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Operation type</source>
|
||||
<translation type="vanished">Operation type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Parse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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 type="vanished">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>
|
||||
<source>Could not start http server.</source>
|
||||
<translation type="vanished">Could not start http server.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation type="vanished">Please, select a picture where QR code that contains info about check is present</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="vanished">Picture was not selected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected image: </source>
|
||||
<translation type="vanished">Selected image: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Captcha was not solved correctly!</source>
|
||||
<translation type="vanished">Captcha was not solved correctly!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation type="vanished">Captcha is incorrect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal server error. Please, try again later.</source>
|
||||
<translation type="vanished">Internal server error. Please, try again later.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal server error</source>
|
||||
<translation type="vanished">Internal server error</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||
<translation type="vanished">Check not found. Please, ensure correctness of entered data.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check was not found</source>
|
||||
<translation type="vanished">Check was not found</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation type="vanished">QR code for binaryeye to connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>I've scanned</source>
|
||||
<translation type="vanished">I've scanned</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>123 123</source>
|
||||
<translation type="obsolete">123 123</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OutputDialog</name>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="14"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="42"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="20"/>
|
||||
<source>Path to export: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Path to export: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="55"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="34"/>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="68"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
||||
<source>Print header</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Print header</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Date</source>
|
||||
<translation type="vanished">Date</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="82"/>
|
||||
<source>Goods name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Goods name</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="87"/>
|
||||
<source>Goods price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Goods price</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="92"/>
|
||||
<source>Goods quantity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Goods quantity</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="97"/>
|
||||
<source>Goods net weight</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Goods net weight</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="102"/>
|
||||
<source>Goods total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Goods total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="107"/>
|
||||
<source>position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="112"/>
|
||||
<source>name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">name</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="117"/>
|
||||
<source>1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="122"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Name</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="127"/>
|
||||
<source>2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="132"/>
|
||||
<source>Price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Price</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="137"/>
|
||||
<source>3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="142"/>
|
||||
<source>Quantity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Quantity</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="147"/>
|
||||
<source>4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="152"/>
|
||||
<source>Net weight</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Net Weight</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="157"/>
|
||||
<source>5</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">5</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>6</source>
|
||||
<translation type="vanished">6</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="162"/>
|
||||
<source>Total price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Total price</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="176"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="27"/>
|
||||
<source>Print total</source>
|
||||
<translation>Print total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="30"/>
|
||||
<source>Кто здесь?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="64"/>
|
||||
<source>Using locale: </source>
|
||||
<translation>Using locale: </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsDialog</name>
|
||||
<message>
|
||||
<location filename="../settingsdialog.cpp" line="133"/>
|
||||
<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"/>
|
||||
<source>Restart required</source>
|
||||
<translation>Restart required</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SolveCaptchaDialog</name>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.ui" line="14"/>
|
||||
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="23"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="22"/>
|
||||
<source>Please, enter a valid captcha</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Please, enter a valid captcha</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="25"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="24"/>
|
||||
<source>No captcha</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>No captcha</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>settingsdialog</name>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="14"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="72"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
||||
<source>Goods name position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods name position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="79"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
||||
<source>Goods price per unit alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>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>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
||||
<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>
|
||||
</message>
|
||||
<message>
|
||||
<source>TextLabel</source>
|
||||
<translation type="vanished">Language</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="38"/>
|
||||
<source>en_US</source>
|
||||
<translation>en_US</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
||||
<source>ru_RU</source>
|
||||
<translation>ru_RU</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="86"/>
|
||||
<location filename="../settingsdialog.ui" line="217"/>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Choose</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="96"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
||||
<source>Print header</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Print header</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="103"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
||||
<source>Goods net weight alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods net weight alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="110"/>
|
||||
<source>Stores modules url</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Stores modules url</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="120"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
||||
<source>Goods total alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods total alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="127"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
||||
<source>Goods name alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods name alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="137"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
||||
<source>Goods quantity alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods quantity alias</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="144"/>
|
||||
<source>Stores modules directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Stores modules directory</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="157"/>
|
||||
<source>OFD modules directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">OFD modules directory</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="173"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
||||
<source>Goods price per unit position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods price per unit position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="180"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
||||
<source>Goods net weight position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods net weight position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="187"/>
|
||||
<source>OFD modules url</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">OFD modules url</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="197"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
||||
<source>Goods total position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods total position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="204"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
||||
<source>Goods quantity position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Goods quantity position</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="227"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
||||
<source>Print total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Print total</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
@@ -4,401 +4,763 @@
|
||||
<context>
|
||||
<name>AdjustPictureDialog</name>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.ui" line="14"/>
|
||||
<location filename="../scenes/adjustpicturedialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.ui" line="58"/>
|
||||
<location filename="../scenes/adjustpicturedialog.ui" line="33"/>
|
||||
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Пожалуйста, приблизьте QR код и настройте контраст, чтобы он читался</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="39"/>
|
||||
<source>QR code was not detected on that image. Please edit it again or enter data manually</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../adjustpicturedialog.cpp" line="41"/>
|
||||
<source>No QR code</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>QR код не найден</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EmailTextScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Форма</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store type</source>
|
||||
<translation type="obsolete">Магазин</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check content</source>
|
||||
<translation type="vanished">Контент чека</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Парсить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store:</source>
|
||||
<translation type="vanished">Магазин:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Ошибка в парсинге</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="14"/>
|
||||
<source>MainWindow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">ГлавноеОкно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="37"/>
|
||||
<source>Store type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Магазин</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="50"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="95"/>
|
||||
<source>Parse</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Парсить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="63"/>
|
||||
<source>Preferences</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Настройки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="80"/>
|
||||
<source>Text</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Текст</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="92"/>
|
||||
<source>Check content</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Контент чека</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>OCR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Оптическое Распознавание Символов</translatorcomment>
|
||||
<translation type="vanished">ОРС</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="120"/>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="143"/>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>Path to image: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Путь к изображению: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="156"/>
|
||||
<source>Here is recognised check text. Please, edit it if something's wrong:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Ниже приведён распознанный текст. Пожалуйста, отредактируйте его:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="175"/>
|
||||
<source>OFD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Оператор Фискальных Данных</translatorcomment>
|
||||
<translation type="vanished">ОФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="226"/>
|
||||
<source>0000000000000000</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">0000000000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="245"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="121"/>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Фискальный Норма</translatorcomment>
|
||||
<translation>ФН</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="264"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="58"/>
|
||||
<source>FD (Fiscal Document)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translatorcomment>Фискальный Документ</translatorcomment>
|
||||
<translation>ФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="277"/>
|
||||
<location filename="../mainwindow.ui" line="309"/>
|
||||
<source>0000000000</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">000000000</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="296"/>
|
||||
<source>Back</source>
|
||||
<translation type="obsolete">Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="206"/>
|
||||
<source>Stop server</source>
|
||||
<translation>Остановить сервер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="167"/>
|
||||
<source>Choose image on your PC</source>
|
||||
<translation>Выбрать изображение на компьютере</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="38"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="154"/>
|
||||
<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>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="82"/>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translatorcomment>Фискальный Признак</translatorcomment>
|
||||
<translation>ФП</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="273"/>
|
||||
<source>Add new check</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="333"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="263"/>
|
||||
<source>Clear</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="45"/>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation>Дата и время покупки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="237"/>
|
||||
<source>Operation type</source>
|
||||
<translation>Тип операции</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="250"/>
|
||||
<source>Parse an E-Mail</source>
|
||||
<translation>Парсить E-Mail</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="214"/>
|
||||
<source>Funds income</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Приход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="219"/>
|
||||
<source>Funds return</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Возврат средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="343"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="224"/>
|
||||
<source>Funds spend</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Расход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="348"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="229"/>
|
||||
<source>Spends return</source>
|
||||
<translation>Возврат расхода</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="72"/>
|
||||
<source>Checks to parse</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="375"/>
|
||||
<location filename="../scenes/mainwindow.ui" line="108"/>
|
||||
<source>Settings</source>
|
||||
<translation>Настройки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="128"/>
|
||||
<source>Total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Итого</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>checks parser</source>
|
||||
<translation type="vanished">Парсер чеков</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="101"/>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation>QR код для подключения BinaryEye</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="102"/>
|
||||
<source>I've scanned</source>
|
||||
<translation>Просканировал</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="108"/>
|
||||
<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"/>
|
||||
<source>Could not start http server.</source>
|
||||
<translation>Не получилось запустить HTTP сервер.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="154"/>
|
||||
<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>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="85"/>
|
||||
<location filename="../mainwindow.cpp" line="189"/>
|
||||
<source>Under development</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="287"/>
|
||||
<source>Captcha was not solved correctly!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Капча была решена неверно!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="87"/>
|
||||
<location filename="../mainwindow.cpp" line="289"/>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Капча введена неверно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="92"/>
|
||||
<location filename="../mainwindow.cpp" line="294"/>
|
||||
<source>Internal server error. Please, try again later.</source>
|
||||
<translation>Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="296"/>
|
||||
<source>Internal server error</source>
|
||||
<translation>Внутренняя ошибка сервера</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="301"/>
|
||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="94"/>
|
||||
<location filename="../mainwindow.cpp" line="303"/>
|
||||
<source>Check was not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Чек не найден</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="145"/>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Ошибка в парсинге</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="147"/>
|
||||
<location filename="../mainwindow.cpp" line="193"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation>Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="149"/>
|
||||
<source>Picture was not selected</source>
|
||||
<translation>Изображение не было выбрано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="191"/>
|
||||
<source>Please, select a picture to scan</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Пожалуйста, выберете изображение для сканирования</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/mainwindow.ui" line="26"/>
|
||||
<source>Form</source>
|
||||
<translation>Форма</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Optical Character Recognition</source>
|
||||
<translation type="vanished">Оптическое распознавание символов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text from E-Mail</source>
|
||||
<translation type="vanished">Текст из электронного письма</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OCRScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Форма</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Choose</source>
|
||||
<translation type="vanished">Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Path to image:</source>
|
||||
<translation type="vanished">Путь к изображению:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Store:</source>
|
||||
<translation type="vanished">Магазин:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Recognized text will be shown below as soon as image will be processed. Please, edit it</source>
|
||||
<translation type="vanished">Распознанный текст будет показан ниже как только изображение обработается. Пожалуйста, отредактируйте</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Парсить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
|
||||
<translation type="vanished">Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error in parsing</source>
|
||||
<translation type="vanished">Ошибка в парсинге</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture to scan</source>
|
||||
<translation type="vanished">Пожалуйста, выберете изображение для сканирования</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="vanished">Изображение не было выбрано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Path to image: </source>
|
||||
<translation type="vanished">Путь к изображению: </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OFDScene</name>
|
||||
<message>
|
||||
<source>Form</source>
|
||||
<translation type="vanished">Форма</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Total</source>
|
||||
<translation type="vanished">Итого</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="vanished">Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>or</source>
|
||||
<translation type="vanished">или</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FD (Fiscal Document)</source>
|
||||
<translation type="vanished">ФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Date and time of purchase</source>
|
||||
<translation type="vanished">Дата и время покупки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop server</source>
|
||||
<translation type="vanished">Остановить сервер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds income</source>
|
||||
<translation type="vanished">Приход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds return</source>
|
||||
<translation type="vanished">Возврат средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Funds spend</source>
|
||||
<translation type="vanished">Расход средств</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Spends return</source>
|
||||
<translation type="vanished">Возврат расхода</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use your phone as a QR code scanner</source>
|
||||
<translation type="vanished">Использовать телефон как сканнер QR</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FN (Fiscal Number)</source>
|
||||
<translation type="vanished">ФН</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FI (Fiscal Identifier)</source>
|
||||
<translation type="vanished">ФП</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Choose image on your PC</source>
|
||||
<translation type="vanished">Выбрать изображение на компьютере</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Operation type</source>
|
||||
<translation type="vanished">Тип операции</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Parse</source>
|
||||
<translation type="vanished">Парсить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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 type="vanished">Не смог поднять HTTP сервер. 10 раз подряд случайно выбранный порт был занят. Либо Вам следует бежать за лоттерейным билетом, или в программе баг. Если лотерейный билет не был выигрышным, пожалуйста, сообщите разработчику.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not start http server.</source>
|
||||
<translation type="vanished">Не получилось запустить HTTP сервер.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please, select a picture where QR code that contains info about check is present</source>
|
||||
<translation type="vanished">Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Picture was not selected</source>
|
||||
<translation type="vanished">Изображение не было выбрано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected image: </source>
|
||||
<translation type="vanished">Выбранное изображение: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Captcha was not solved correctly!</source>
|
||||
<translation type="vanished">Капча была решена неверно!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Captcha is incorrect</source>
|
||||
<translation type="vanished">Капча введена неверно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal server error. Please, try again later.</source>
|
||||
<translation type="vanished">Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal server error</source>
|
||||
<translation type="vanished">Внутренняя ошибка сервера</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check not found. Please, ensure correctness of entered data.</source>
|
||||
<translation type="vanished">Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Check was not found</source>
|
||||
<translation type="vanished">Чек не найден</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>QR code for binaryeye to connect</source>
|
||||
<translation type="vanished">QR код для подключения BinaryEye</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>I've scanned</source>
|
||||
<translation type="vanished">Просканировал</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>123 123</source>
|
||||
<translation type="obsolete">123 123</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OutputDialog</name>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="14"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="42"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="20"/>
|
||||
<source>Path to export: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Путь для экспорта: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="55"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="34"/>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="68"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="73"/>
|
||||
<source>Print header</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Печатать заголовок</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="82"/>
|
||||
<source>Goods name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Имя товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="87"/>
|
||||
<source>Goods price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Цена товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="92"/>
|
||||
<source>Goods quantity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Количество товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="97"/>
|
||||
<source>Goods net weight</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Масса нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="102"/>
|
||||
<source>Goods total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Всего за товар</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="107"/>
|
||||
<source>position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">позиция</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="112"/>
|
||||
<source>name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">алиас</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="117"/>
|
||||
<source>1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="122"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Имя</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="127"/>
|
||||
<source>2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="132"/>
|
||||
<source>Price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Цена</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="137"/>
|
||||
<source>3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="142"/>
|
||||
<source>Quantity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Количество</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="147"/>
|
||||
<source>4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="152"/>
|
||||
<source>Net weight</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Масса нетто</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="157"/>
|
||||
<source>5</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">5</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>6</source>
|
||||
<translation type="obsolete">6</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="162"/>
|
||||
<source>Total price</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Всего</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.ui" line="176"/>
|
||||
<location filename="../scenes/outputdialog.ui" line="27"/>
|
||||
<source>Print total</source>
|
||||
<translation>Печатать Итого</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../outputdialog.cpp" line="30"/>
|
||||
<source>Кто здесь?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="64"/>
|
||||
<source>Using locale: </source>
|
||||
<translation>Использую локаль: </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsDialog</name>
|
||||
<message>
|
||||
<location filename="../settingsdialog.cpp" line="133"/>
|
||||
<source>You need to restart program to apply language changes</source>
|
||||
<translation>Требуется перезагрузить программу, чтобы применить изменения языка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.cpp" line="135"/>
|
||||
<source>Restart required</source>
|
||||
<translation>Требуется перезагрузка</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SolveCaptchaDialog</name>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.ui" line="14"/>
|
||||
<location filename="../scenes/solvecaptchadialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="23"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="22"/>
|
||||
<source>Please, enter a valid captcha</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Пожалуйста, введите верную капчу</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="25"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="24"/>
|
||||
<source>No captcha</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Нет капчи</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>settingsdialog</name>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="14"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="14"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="72"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="110"/>
|
||||
<source>Goods name position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Позиция имени товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="79"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="70"/>
|
||||
<source>Goods price per unit alias</source>
|
||||
<translation>Алиас цены товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="124"/>
|
||||
<source>Date name position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="86"/>
|
||||
<location filename="../settingsdialog.ui" line="217"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="182"/>
|
||||
<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"/>
|
||||
<source>en_US</source>
|
||||
<translation>en_US</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../scenes/settingsdialog.ui" line="43"/>
|
||||
<source>ru_RU</source>
|
||||
<translation>ru_RU</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Choose</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Выбрать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="96"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="80"/>
|
||||
<source>Print header</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Печатать заголовок</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="103"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="189"/>
|
||||
<source>Goods net weight alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Алиас массы нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="110"/>
|
||||
<source>Stores modules url</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">URL модулей магазина</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="120"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="165"/>
|
||||
<source>Goods total alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Алиас всего за продукт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="127"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="155"/>
|
||||
<source>Goods name alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Алиас имени товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="137"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="51"/>
|
||||
<source>Goods quantity alias</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Алиас количества товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="144"/>
|
||||
<source>Stores modules directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Директория модулей магазина</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="157"/>
|
||||
<source>OFD modules directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">Директория модулей ОФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="173"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="131"/>
|
||||
<source>Goods price per unit position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Позиция центы товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="180"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="97"/>
|
||||
<source>Goods net weight position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Позиция массы нетто товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="187"/>
|
||||
<source>OFD modules url</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="vanished">URL модулей ОФД</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="197"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="145"/>
|
||||
<source>Goods total position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Позиция всего за товар</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="204"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="87"/>
|
||||
<source>Goods quantity position</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Позиция количества товара</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsdialog.ui" line="227"/>
|
||||
<location filename="../scenes/settingsdialog.ui" line="117"/>
|
||||
<source>Print total</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Печатать Итого</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
79
utils/base64.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
|
||||
#include <utils/base64.h>
|
||||
#include <string>
|
||||
|
||||
static const std::string base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (std::isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string const& encoded_string) {
|
||||
int in_len = encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++)
|
||||
char_array_4[i] = base64_chars.find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j <4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
char_array_4[j] = base64_chars.find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
29
utils/base64.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
#include <string>
|
||||
|
||||
std::string base64_decode(std::string const& encoded_string);
|
||||
231
utils/utils.cpp
@@ -1,12 +1,58 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include "output/output_options.h"
|
||||
#include <utils/utils.h>
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
# include <arpa/inet.h>
|
||||
# include <qrencode.h>
|
||||
# include <ifaddrs.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef BUILD_OFD_MODE
|
||||
# include <exceptions/ofdrequestexception.h>
|
||||
# include <fstream>
|
||||
#endif
|
||||
#include <codecvt>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <regex>
|
||||
#if defined(BUILD_OCR_MODE) || defined(BUILD_OFD_MODE)
|
||||
# include <opencv2/core/mat.hpp>
|
||||
# include <opencv2/imgcodecs.hpp>
|
||||
# include <opencv2/imgproc.hpp>
|
||||
#endif
|
||||
#include <string>
|
||||
#include "../exceptions/ofdrequestexception.h"
|
||||
#include <QWidget>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <net/net.h>
|
||||
#include <settings/settings.h>
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
std::string get_local_ip_address() {
|
||||
struct ifaddrs * ifAddrStruct=NULL;
|
||||
struct ifaddrs * ifa=NULL;
|
||||
void * tmpAddrPtr=NULL;
|
||||
|
||||
getifaddrs(&ifAddrStruct);
|
||||
|
||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == nullptr) continue;
|
||||
if (ifa->ifa_addr->sa_family==AF_INET) {
|
||||
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
|
||||
char addressBuffer[128];
|
||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
std::string value(addressBuffer);
|
||||
if (!strncmp(value.c_str(), "192.168", 7)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ifAddrStruct!=NULL)
|
||||
freeifaddrs(ifAddrStruct);
|
||||
|
||||
throw std::runtime_error(QWidget::tr("Could not find any usable local IP address. If you beleive that this is problem with the program, please, contact the developer.").toStdString());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string to_utf8(std::wstring wide_string) {
|
||||
static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
||||
@@ -29,9 +75,36 @@ bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template<class T>
|
||||
bool areAllSizesEqual(const std::vector<T>& v1, const std::vector<T>& v2,
|
||||
const std::vector<T>& v3, const std::vector<T>& v4) {
|
||||
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;
|
||||
@@ -47,16 +120,30 @@ std::vector<std::string> split(std::string s, std::string delimiter) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> split(std::wstring s, std::wstring delimiter) {
|
||||
std::vector<std::wstring> result;
|
||||
size_t pos = 0;
|
||||
std::wstring token;
|
||||
while ((pos = s.find(delimiter)) != std::string::npos) {
|
||||
token = s.substr(0, pos);
|
||||
result.push_back(token);
|
||||
s.erase(0, pos + delimiter.length());
|
||||
}
|
||||
result.push_back(s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring substring_from_to(std::wstring& text, std::wstring from, std::wstring to) {
|
||||
unsigned int start_pos = 0;
|
||||
unsigned int end_pos = 0;
|
||||
|
||||
std::wstring substring;
|
||||
|
||||
std::wregex start_regex(from);
|
||||
std::wregex end_regex(to);
|
||||
boost::wregex start_regex(from);
|
||||
boost::wregex end_regex(to);
|
||||
|
||||
for (std::wsregex_iterator it{text.begin(), text.end(), start_regex}, end{};
|
||||
for (boost::wsregex_iterator it{text.begin(), text.end(), start_regex}, end{};
|
||||
it != end; it++) {
|
||||
start_pos = it->position() + it->str().size();
|
||||
break;
|
||||
@@ -65,7 +152,7 @@ std::wstring substring_from_to(std::wstring& text, std::wstring from, std::wstri
|
||||
if(text == from_utf8("")) return text;
|
||||
substring = text.substr(start_pos, text.size());
|
||||
|
||||
for (std::wsregex_iterator it{substring.begin(), substring.end(), end_regex}, end{};
|
||||
for (boost::wsregex_iterator it{substring.begin(), substring.end(), end_regex}, end{};
|
||||
it != end; it++) {
|
||||
end_pos = it->position();
|
||||
break;
|
||||
@@ -77,7 +164,7 @@ std::wstring substring_from_to(std::wstring& text, std::wstring from, std::wstri
|
||||
|
||||
return substring;
|
||||
}
|
||||
|
||||
#ifdef BUILD_OFD_MODE
|
||||
std::wstring trim_html_response(std::wstring& check) {
|
||||
std::wstring begin_check_marker = from_utf8("<!-- Products -->");
|
||||
std::wstring end_check_marker = from_utf8("<!-- \\/Products -->");
|
||||
@@ -87,30 +174,91 @@ std::wstring trim_html_response(std::wstring& check) {
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_in_html(std::string& html, std::string regex, std::string html_start, std::string html_end) {
|
||||
std::regex searching_regex(regex);
|
||||
boost::regex searching_regex(regex);
|
||||
|
||||
std::vector<std::wstring> parsed;
|
||||
for (std::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
|
||||
for (boost::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
|
||||
it != end; it++) {
|
||||
|
||||
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);
|
||||
}
|
||||
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>.*<\\/b><\\/div>", "<div class=\"ifw-col ifw-col-1 text-left\"><b>", "<\\/b><\\/div>");
|
||||
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>");
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_amounts_in_html(std::string html) {
|
||||
return find_in_html(html, "<span>\\d+<\\/span>", "<span>", "<\\/span>");
|
||||
std::vector<std::wstring> founds = find_in_html(html, "<div><span>\\d+(\\.|\\,)?\\d{0,3}<\\/span>", "<span>", "<\\/span>");
|
||||
for (auto &found : founds) {
|
||||
std::replace(found.begin(), found.end(), ',', '.');
|
||||
}
|
||||
|
||||
return founds;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_net_weights_in_names(std::vector<std::wstring> &names) {
|
||||
std::vector<std::wstring> result;
|
||||
for (std::wstring &name : names ) {
|
||||
boost::wregex regexp(from_utf8("((\\d+(\\.|,)?\\d{0,}((м|)л|(к|м|)г|т|ц|шт|(pc|)s|(m|k|)g|(m|)l|t))(\\s|\\t){0,})+"), boost::regex_constants::collate);
|
||||
bool found = false;
|
||||
for (boost::wsregex_iterator it{name.begin(), name.end(), regexp}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(it->str());
|
||||
found = true;
|
||||
name.erase(it->position(), it->str().length());
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
result.push_back(from_utf8("?"));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &entry : result) {
|
||||
std::replace(entry.begin(), entry.end(), ',', '.');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_prices_in_html(std::string html) {
|
||||
return find_in_html(html, "X <\\/span><span>\\d+\\.\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
|
||||
std::vector<std::wstring> founds = find_in_html(html, "X <\\/span><span>\\d+(\\.|,)\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
|
||||
for (auto &found : founds) {
|
||||
std::replace(found.begin(), found.end(), ',', '.');
|
||||
}
|
||||
|
||||
return founds;
|
||||
}
|
||||
|
||||
void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::wstring> &amounts, std::vector<std::wstring> &net_weights, std::vector<std::wstring> &prices) {
|
||||
std::cerr << "Products: ";
|
||||
for (auto &product : products) {
|
||||
std::cerr << to_utf8(product) << "|[]|";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Amounts: ";
|
||||
for (auto &amount : amounts) {
|
||||
std::wcerr << amount << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Net weights: ";
|
||||
for (auto &net_weight : net_weights) {
|
||||
std::wcerr << net_weight << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Prices: ";
|
||||
for (auto &price : prices) {
|
||||
std::wcerr << price << " ";
|
||||
}
|
||||
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
Check parseOfdRuAnswer(std::string html) {
|
||||
@@ -119,11 +267,14 @@ Check parseOfdRuAnswer(std::string html) {
|
||||
|
||||
std::vector<std::wstring> products = find_products_in_html(trimmed);
|
||||
std::vector<std::wstring> amounts = find_amounts_in_html(trimmed);
|
||||
std::vector<std::wstring> net_weights = find_net_weights_in_names(products);
|
||||
std::vector<std::wstring> prices = find_prices_in_html(trimmed);
|
||||
|
||||
if ((products.size() + amounts.size() + prices.size()) == 0) {
|
||||
if (html == "Bad Request4") { // Failed to solve a captcha
|
||||
throw OfdRequestException("Incorrect captcha");
|
||||
} else if (html.find("500 - Internal server error.") != std::string::npos) {
|
||||
throw OfdRequestException("Internal server error");
|
||||
} else { // Most likely that the check does not exist
|
||||
throw OfdRequestException("Does not exist");
|
||||
}
|
||||
@@ -131,6 +282,10 @@ Check parseOfdRuAnswer(std::string html) {
|
||||
}
|
||||
|
||||
if ((products.size() + amounts.size() + prices.size())/products.size() != 3) {
|
||||
dumpVectorsToStderr(products, amounts, net_weights, prices);
|
||||
//TOOD: make new setting "app_home" and get all path using it.
|
||||
std::ofstream error_log(get_path_relative_to_home(".local/share/checks_parser/error_log.txt"), std::ios_base::app);
|
||||
error_log << trimmed << std::endl;
|
||||
std::cerr << "An error has occured during the parsing of html. Please, contact the developer." << std::endl;
|
||||
std::exit(-1);
|
||||
}
|
||||
@@ -138,9 +293,53 @@ Check parseOfdRuAnswer(std::string html) {
|
||||
Check c;
|
||||
|
||||
for (int i = 0; i < products.size(); i ++) {
|
||||
Goods goods(to_utf8(products[i]), std::stod(prices[i]), std::stod(amounts[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;
|
||||
Goods goods(to_utf8(products[i]), std::stod(prices[i]), to_utf8(net_weights[i]), std::stod(amounts[i]));
|
||||
c.add_goods(goods);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif // ifdef BUILD_OFD_MODE
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
void generate_qr_code(std::string data) {
|
||||
QRcode *qrCode = QRcode_encodeString(data.c_str(), 2, QR_ECLEVEL_L, QR_MODE_8, 1);
|
||||
if (qrCode == NULL) {
|
||||
std::cerr << "Error on generating qr code" << std::endl;
|
||||
}
|
||||
|
||||
cv::Mat qrCodeImage = cv::Mat::zeros(qrCode->width, qrCode->width, CV_8UC3);
|
||||
|
||||
for (int y = 0; y < qrCode->width; y++) {
|
||||
for (int x = 0; x < qrCode->width; x++) {
|
||||
cv::rectangle(
|
||||
qrCodeImage,
|
||||
cv::Point(x, y),
|
||||
cv::Point(x + 1, y + 1),
|
||||
((qrCode->data[y * qrCode->width + x] & 1) ?
|
||||
cv::Scalar(255., 255., 255.) : cv::Scalar(0., 0., 0.)
|
||||
),
|
||||
-1
|
||||
);
|
||||
}
|
||||
}
|
||||
cv::imwrite(get_path_relative_to_home(".local/share/checks_parser/binaryeye_connection.png"), qrCodeImage);
|
||||
QRcode_free(qrCode);
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#endif // ifdef BUILD_EMAIL_MODE
|
||||
|
||||
|
||||
@@ -3,20 +3,41 @@
|
||||
|
||||
#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);
|
||||
|
||||
// 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);
|
||||
template <class T>
|
||||
bool areAllSizesEqual(const std::vector<T>& v1, const std::vector<T>& v2,
|
||||
const std::vector<T>& v3, const std::vector<T>& v4);
|
||||
|
||||
std::vector<std::string> split(std::string, std::string);
|
||||
std::vector<std::wstring> split(std::wstring s, std::wstring delimiter);
|
||||
|
||||
#ifdef BUILD_OFD_MODE
|
||||
Check parseOfdRuAnswer(std::string);
|
||||
|
||||
std::wstring trim_html_response(std::wstring& check);
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
void generate_qr_code(std::string data);
|
||||
std::string get_local_ip_address();
|
||||
#endif
|
||||
|
||||
void fetch_and_download_modules();
|
||||
#ifdef BUILD_EMAIL_MODE
|
||||
std::vector<std::string> read_file(std::string path);
|
||||
#endif
|
||||
#endif // UTILS_H
|
||||
|
||||
34
widgets/checklistviewwidget.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#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);
|
||||
}
|
||||
24
widgets/checklistviewwidget.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#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
|
||||
17
widgets/outputcolumn.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "outputcolumn.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
OutputColumn::OutputColumn() { }
|
||||
|
||||
OutputColumn::OutputColumn(QString text, ColumnType type)
|
||||
: text(text), type(type) { }
|
||||
|
||||
void OutputColumn::set_column_type(ColumnType type) { this->type = type; }
|
||||
ColumnType OutputColumn::get_column_type() { return type; }
|
||||
|
||||
void OutputColumn::set_text(const QString &text) { this->text = text; }
|
||||
QString OutputColumn::get_text() { return text; }
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(OutputColumn)
|
||||
23
widgets/outputcolumn.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef OUTPUTCOLUMN_H
|
||||
#define OUTPUTCOLUMN_H
|
||||
|
||||
#include "output/output_options.h"
|
||||
#include <QLineEdit>
|
||||
#include <QStandardItem>
|
||||
|
||||
class OutputColumn
|
||||
{
|
||||
QString text;
|
||||
ColumnType type;
|
||||
public:
|
||||
OutputColumn();
|
||||
OutputColumn(QString text, ColumnType type);
|
||||
|
||||
void set_column_type(ColumnType type);
|
||||
ColumnType get_column_type();
|
||||
|
||||
void set_text(const QString &text);
|
||||
QString get_text();
|
||||
};
|
||||
|
||||
#endif // OUTPUTCOLUMN_H
|
||||
150
widgets/outputcolumnmodel.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "outputcolumnmodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMimeData>
|
||||
#include <QIODevice>
|
||||
#include <outputcolumn.h>
|
||||
|
||||
OutputColumnModel::OutputColumnModel(std::vector<OutputColumn> *columns, QObject *parent)
|
||||
: columns(columns), QAbstractListModel{parent} { }
|
||||
|
||||
int OutputColumnModel::rowCount(const QModelIndex &parent) const {
|
||||
return columns->size();
|
||||
}
|
||||
|
||||
QVariant OutputColumnModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid() || index.row() >= columns->size())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
return QVariant::fromValue(columns->at(index.row()).get_text());
|
||||
else if (role == 0x0101)
|
||||
return QVariant::fromValue(columns->at(index.row()).get_column_type());
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant OutputColumnModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
return QObject::tr("Column type alias");
|
||||
else
|
||||
return QStringLiteral("Position %1").arg(section);
|
||||
}
|
||||
|
||||
bool OutputColumnModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (index.isValid()) {
|
||||
OutputColumn &column = columns->at(index.row());
|
||||
if (role == 0x102) {
|
||||
OutputColumn data = value.value<OutputColumn>();
|
||||
column.set_text(data.get_text());
|
||||
column.set_column_type(data.get_column_type());
|
||||
} else {
|
||||
QString data = value.value<QString>();
|
||||
column.set_text(data);
|
||||
}
|
||||
|
||||
(*columns)[index.row()] = column;
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::DropActions OutputColumnModel::supportedDropActions() const {
|
||||
return Qt::MoveAction;
|
||||
}
|
||||
|
||||
bool OutputColumnModel::insertRows(int position, int rows, const QModelIndex &index) {
|
||||
beginInsertRows(QModelIndex(), position, position+rows-1);
|
||||
|
||||
for (int row = 0; row < rows; ++row)
|
||||
columns->emplace(columns->begin() + position, OutputColumn("Чё зыришь глаза пузыришь?", ColumnType::date));
|
||||
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OutputColumnModel::removeRows(int position, int rows, const QModelIndex &parent) {
|
||||
beginRemoveRows(QModelIndex(), position, position+rows-1);
|
||||
|
||||
for (int row = 0; row < rows; ++row)
|
||||
columns->erase(std::next(columns->begin(), position));
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList OutputColumnModel::mimeTypes() const {
|
||||
QStringList types;
|
||||
types << OutputColumnModel::MimeType;
|
||||
return types;
|
||||
}
|
||||
|
||||
bool OutputColumnModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &) {
|
||||
if ( action != Qt::MoveAction || !data->hasFormat(OutputColumnModel::MimeType))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags OutputColumnModel::flags (const QModelIndex & index) const {
|
||||
Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
|
||||
|
||||
if (index.isValid())
|
||||
return Qt::ItemIsDragEnabled | Qt::ItemIsEditable | defaultFlags;
|
||||
else
|
||||
return Qt::ItemIsDropEnabled | defaultFlags;
|
||||
}
|
||||
|
||||
QMimeData* OutputColumnModel::mimeData(const QModelIndexList &indexes) const {
|
||||
QMimeData* mimeData = new QMimeData;
|
||||
QByteArray encodedData;
|
||||
|
||||
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.isValid()) {
|
||||
QString text = data(index, Qt::DisplayRole).toString();
|
||||
ColumnType type = ColumnType(data(index, 0x0101).toInt());
|
||||
stream << text << type;
|
||||
}
|
||||
}
|
||||
mimeData->setData(OutputColumnModel::MimeType, encodedData);
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool OutputColumnModel::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;
|
||||
|
||||
QByteArray encodedData = data->data(OutputColumnModel::MimeType);
|
||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||
std::vector<OutputColumn> newItems;
|
||||
int rows = 0;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
QString text;
|
||||
ColumnType type;
|
||||
stream >> text >> type;
|
||||
newItems.push_back(OutputColumn(text, type));
|
||||
++rows;
|
||||
}
|
||||
|
||||
insertRows(row, rows, QModelIndex());
|
||||
for (const OutputColumn &column : newItems)
|
||||
{
|
||||
QModelIndex idx = index(row, 0, QModelIndex());
|
||||
setData(idx, QVariant::fromValue(column), 0x102);
|
||||
row++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
37
widgets/outputcolumnmodel.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef OUTPUTCOLUMNMODEL_H
|
||||
#define OUTPUTCOLUMNMODEL_H
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QAbstractListModel>
|
||||
#include <outputcolumn.h>
|
||||
|
||||
class OutputColumnModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
static constexpr const char* MimeType = "application/output.column.model";
|
||||
std::vector<OutputColumn> *columns;
|
||||
|
||||
public:
|
||||
OutputColumnModel(std::vector<OutputColumn> *columns, QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
Qt::ItemFlags flags (const QModelIndex& index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) 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 *, 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);
|
||||
};
|
||||
|
||||
#endif // OUTPUTCOLUMNMODEL_H
|
||||