42 Commits

Author SHA1 Message Date
64da9e9327 fixed language settings 2024-12-05 14:53:20 +03:00
b7b7c054d3 fixed loading system locale from wrong place 2024-12-05 13:58:23 +03:00
c478dcf8d4 embeding translations into qrc 2024-12-05 03:48:20 +03:00
7959bc5492 added language combo box in preferences 2024-12-04 18:44:40 +03:00
031c1d5792 translations 2024-12-04 04:35:51 +03:00
cca20abbfd pretty-printing settings.json 2024-12-04 04:05:02 +03:00
988dc0e133 upload icons 2024-12-04 01:08:08 +03:00
888f658a9c added icon 2024-12-04 01:07:48 +03:00
17a03606c5 fixed wrong setting 2024-12-03 15:24:21 +03:00
83351698d6 readme & todo updated 2024-12-03 15:02:54 +03:00
2c99f422d3 appimage deployment 2024-12-03 03:45:58 +03:00
41463c7f87 packing ocr data and handling escape on chose files 2024-12-02 14:12:03 +03:00
c941264346 remove unneeded, update gitignore 2024-12-02 13:10:36 +03:00
c471cb3f62 fixed captcha not showing up in appimage 2024-12-02 13:09:48 +03:00
7c021c90ee TOOD update 2024-12-02 12:45:20 +03:00
e6cc4b9117 using linuxdeployqt for appimage deployment 2024-12-02 03:21:24 +03:00
c8e4f5ac54 gitignore update 2024-12-02 01:14:42 +03:00
daa7d43c1b removed unneeded 2024-12-02 00:14:44 +03:00
b9a7808960 appimage deployment 2024-12-02 00:14:12 +03:00
1a0f756efc fixes building 2024-12-01 20:04:51 +03:00
362c70e695 ensured building on latest archlinux system 2024-12-01 19:37:17 +03:00
88d849bee9 ensured building on ubuntu 18.04 2024-12-01 18:53:16 +03:00
b59b42a40c translations 2024-12-01 15:01:55 +03:00
fdfeb57049 added translation 2024-11-29 17:01:39 +03:00
22c6bed407 readme changes 2024-11-28 02:07:45 +03:00
d4b5b8d068 fixed too much precision 2024-11-28 02:06:46 +03:00
54020c0925 cleanup 2024-11-28 00:29:49 +03:00
4d658a817b handling incorrect captcha and check not found cases 2024-11-28 00:28:37 +03:00
47dfc19395 requests to ofd 2024-11-27 01:46:36 +03:00
1843479e6b cleanup 2024-11-26 01:09:21 +03:00
8f511789d9 readme changes 2024-11-25 04:31:08 +03:00
a39a34852c implemented contrast slider 2024-11-25 04:07:56 +03:00
3106479fcc completed requests to ofd.ru 2024-11-24 19:07:28 +03:00
48885daed5 rm unneeded 2024-11-22 23:30:04 +03:00
be1e131fa7 update gitignore 2024-11-22 23:29:49 +03:00
9ba8a513e5 remove ignored pt.2 2024-11-22 23:26:42 +03:00
63e4c1382f rm ingored 2024-11-22 23:26:07 +03:00
5450d1756f update gitignore 2024-11-22 23:24:02 +03:00
e0347d161e . 2024-11-22 23:22:37 +03:00
5c468ba0ea removed CMakeFiles 2024-11-22 23:20:49 +03:00
2b9ad2fcae a lot of stuff related to ocr/ofd method 2024-11-22 23:19:04 +03:00
02e4465075 remade text type switch as tabview 2024-10-22 13:18:19 +03:00
49 changed files with 2792 additions and 976 deletions

45
.gitignore vendored
View File

@@ -35,6 +35,8 @@ Thumbs.db
/.qmake.cache /.qmake.cache
/.qmake.stash /.qmake.stash
*.qrc.depends
# qtcreator generated files # qtcreator generated files
*.pro.user* *.pro.user*
CMakeLists.txt.user* CMakeLists.txt.user*
@@ -78,3 +80,46 @@ build/
*.AppImage *.AppImage
*.appimage *.appimage
CMakeFiles
# Build directories
build/
CMakeFiles/
Makefile
cmake_install.cmake
# Generated files
*.o
*.obj
*.exe
*.so
*.dylib
*.a
# Qt-specific files
*.moc
*.moc.cpp
*.qrc.cpp
# CMake-specific files
CMakeCache.txt
install_manifest.txt
# IDE-specific files
.idea/
.vscode/
.kdev4/
.kateproject
# Other files
*.user
*.pro.user
*.suo
*.sdf
checks-parser_autogen
checks-parser
deploy/appimage/AppDir/usr/share/doc/
deploy/appimage/AppDir/usr/share/

View File

View File

View File

@@ -1,42 +1,61 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.10)
project(checks-parser VERSION 0.1 LANGUAGES CXX) project(checks-parser VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC 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 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(Qt5 COMPONENTS LinguistTools)
set(PROJECT_SOURCES set(PROJECT_SOURCES
main.cpp main.cpp
mainwindow.cpp mainwindow.cpp
mainwindow.h mainwindow.h
mainwindow.ui mainwindow.ui
# Add other source files here that contain translatable strings
) )
# 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
# Add other .cpp or .ui files that need translation here
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(checks-parser qt_add_executable(checks-parser
MANUAL_FINALIZATION MANUAL_FINALIZATION
${PROJECT_SOURCES} ${PROJECT_SOURCES}
) )
# Define target properties for Android with Qt 6 as:
# set_property(TARGET checks-parser APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # Generate translation files for Qt 6
# ${CMAKE_CURRENT_SOURCE_DIR}/android) qt_add_translation(TRANSLATIONS "${TRANSLATION_SOURCES}")
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else() else()
if(ANDROID) if(ANDROID)
add_library(checks-parser SHARED add_library(checks-parser SHARED
${PROJECT_SOURCES} ${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() 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)
qt5_add_resources(TRANSLATIONQRC translations.qrc)
add_executable(checks-parser add_executable(checks-parser
${PROJECT_SOURCES} ${PROJECT_SOURCES}
goods/goods.h goods/goods.cpp goods/goods.h goods/goods.cpp
@@ -46,19 +65,28 @@ else()
outputdialog.h outputdialog.cpp outputdialog.ui outputdialog.h outputdialog.cpp outputdialog.ui
output/output_options.h output/output_options.cpp output/output_options.h output/output_options.cpp
ofd/ofd.h ofd/ofd.cpp
ofd/module.h ofd/module.cpp
utils/utils.h utils/utils.cpp utils/utils.h utils/utils.cpp
image/checkimage.h image/checkimage.cpp image/checkimage.h image/checkimage.cpp
net/net.h net/net.cpp net/net.h net/net.cpp
settings/settings.h settings/settings.cpp settings/settings.h settings/settings.cpp
settingsdialog.h settingsdialog.cpp settingsdialog.ui 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}
# ${TS_FILES}
translations.qrc
${TRANSLATIONQRC}
) )
# configure_file(translations.qrc ${CMAKE_BINARY_DIR} COPYONLY)
# QT5_ADD_TRANSLATION(TRANSLATIONS ${CMAKE_SOURCE_DIR} translations/en_US.ts)
endif() endif()
endif() endif()
target_link_libraries(checks-parser PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) target_link_libraries(checks-parser PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # 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 # If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though. # explicit, fixed bundle identifier manually though.
@@ -84,12 +112,13 @@ if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(checks-parser) qt_finalize_executable(checks-parser)
endif() endif()
find_package(PkgConfig REQUIRED)
find_package(OpenCV REQUIRED) find_package(OpenCV REQUIRED)
include_directories("/usr/include/opencv4") 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 -ltesseract)
target_link_libraries(checks-parser PRIVATE -lcurl) target_link_libraries(checks-parser PRIVATE -lcurl)
target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS}) target_link_libraries(checks-parser PRIVATE ${OpenCV_LIBS} )
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8)
target_link_libraries(checks-parser PRIVATE -lstdc++fs)
endif()

122
CMakeLists.txt.bck Normal file
View File

@@ -0,0 +1,122 @@
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} )

View File

@@ -1,422 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 14.0.1, 2024-10-05T17:58:40. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{89a86e95-b67c-4d0a-8a71-fee1196f09b5}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="qlonglong">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
<value type="bool" key="AutoTest.Framework.Boost">true</value>
<value type="bool" key="AutoTest.Framework.CTest">false</value>
<value type="bool" key="AutoTest.Framework.Catch">true</value>
<value type="bool" key="AutoTest.Framework.GTest">true</value>
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
</valuemap>
<value type="bool" key="AutoTest.ApplyFilter">false</value>
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
<value type="int" key="AutoTest.RunAfterBuild">0</value>
<value type="bool" key="AutoTest.UseGlobal">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">4</value>
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{b0aed07e-a2ab-40fb-a18d-c8de07b1c053}</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="CMake.Build.Type">Debug</value>
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_BUILD_TYPE:STRING=Debug
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/leca/projects/qt/checks-parser/build/Desktop-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="CMake.Build.Type">Release</value>
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_BUILD_TYPE:STRING=Release
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/leca/projects/qt/checks-parser/build/Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/leca/projects/qt/checks-parser/build/Desktop-RelWithDebInfo</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/leca/projects/qt/checks-parser/build/Desktop-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
<value type="QString" key="CMake.Build.Type">MinSizeRel</value>
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_BUILD_TYPE:STRING=MinSizeRel
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/leca/projects/qt/checks-parser/build/Desktop-MinSizeRel</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Minimum Size Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">5</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">checks-parser</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.checks-parser</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">checks-parser</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/leca/projects/qt/checks-parser/build/Desktop-Debug/bin</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="qlonglong">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>

View File

@@ -1,13 +1,16 @@
# Checks parser # Checks parser
checks parser is a program that help parsing different formats of checks to csv. 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)
# Usage # Usage
### Input ### Input
Ways you can input a check to this programm: Ways you can input a check to this programm:
* Via image (it uses OCR(Optical Character Recognition) to parse check content. The picture of a check must be contrast and well-lined (text must be perpendicular to right and left borders of an image) enough in order to be parsed well.) * 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 plaintext, copied from an E-Mail. Just copy&paste text from your email, pick a correct store type (autodetect is in my plans!) and parse. * Via plaintext, copied from an E-Mail. Just copy&paste text from your email, pick a correct store type (autodetect is in my plans!) and parse.
* Via E-Mail file (.eml) **[!NOT IMPLEMENTED YET!]** * 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)). **[!NOT IMPLEMENTED YET!]** * Via QrCode on check (OFD (ОФД, Оператор Фискальных Данных in Russian)).
### Output ### Output
At the start of writing this program, I considered 3 or more output formats: csv, xlsx and ods. But throught the development I understood that most of modern table processor (i.e. electronic tables) can import csv much better than I'd be writing a shitty export module, adding more dependencies and shitty code to the codebase. So I decided that there's no need to use anything other than csv format. At the start of writing this program, I considered 3 or more output formats: csv, xlsx and ods. But throught the development I understood that most of modern table processor (i.e. electronic tables) can import csv much better than I'd be writing a shitty export module, adding more dependencies and shitty code to the codebase. So I decided that there's no need to use anything other than csv format.
@@ -16,36 +19,71 @@ To export, you need to specify an output file path and, if you wish, you can cha
# Installing # Installing
## Building ## Building
In general, you need to install following dependencies in order to build that app(I suppose you have install all the build necessaries such as cmake, make, gcc, git, etc...): In general, you need to install following dependencies in order to build that app(I suppose you have installed all the build necessaries such as cmake, make, gcc, git, etc...):
* tesseract (you also have to install appropriate for your needs language data) * tesseract (you also have to install appropriate for your needs language data)
* opencv * opencv
* zbar
* curl * curl
* nlohmann-json * nlohmann-json
* qt5 * qt5
* vtk
Please, do not hesitate to open an issue if you cannot build that. I will help and if you are building on a distro that is not listed there, we can append that list as soon as we will solve your problem! Please, do not hesitate to open an issue if you cannot build that. I will help and if you are building on a distro that is not listed there, we can append that list as soon as we will solve your problem!
### Linux ### Linux
##### Arch Linux ##### 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 /shrug
``` ```
#Install dependencies #Install dependencies
yay -S sudo cmake git coreutils base-devel eigen qt5-base mbedtls gtkglext opencv opencv2 nlohmann-json tesseract tesseract-data-rus yay -S sudo cmake git coreutils base-devel eigen qt5-base mbedtls gtkglext opencv opencv2 zbar nlohmann-json tesseract tesseract-data-rus vtk
#Clone and compile an app #Clone and compile an app
git clone https://git.foxarmy.org/leca/checks-parser git clone https://git.foxarmy.org/leca/checks-parser
cd checks-parser cd checks-parser
mkdir build cmake .
cd build
cmake ..
make -j{nproc} make -j{nproc}
#If you wish to install that program system-wide, run #If you wish to install that program system-wide, run
sudo make install sudo make install
``` ```
##### Debian ##### Debian-based
TODO 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```
###### 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```
Next steps are identical for every debian-based distro
```
#Clone and compile an app
git clone https://git.foxarmy.org/leca/checks-parser
cd checks-parser
cmake .
make -j{nproc}
#If you wish to install that program system-wide, run
sudo make install
```
### Windows ### Windows
Maybe Maybe
### Mac OS ### Mac OS
Probably not, I do not have nor desire or time. But if you can maintain that program on Mac, I'd be grateful! Please, contact me, if you can! Probably not, I do not have nor desire or time. But if you can maintain that program on Mac, I'd be grateful! Please, contact me, if you can!
## Precompiled ## 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 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
# Contribution
If you want to contribute to the project, you can do it by some of the following:
## Checks from different countries
I live in Russia and only know how Russian state checks system works. If you live in another country and want to help me with adding support to checks from your country - feel free to contact me!
## Issues and PRs
If you have found a bug, or want to suggest a feature - don't hesitate to open an issue / 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```

23
TODO
View File

@@ -1,19 +1,30 @@
Complete module "export": Complete module "export": [done]
make UI; [done] make UI; [done]
make export to .csv [done] make export to .csv [done]
Complete module "image-to-text":
Complete module "image-to-text": [done]
make UI; [done] make UI; [done]
make use of tesseract/opencv (https://learnopencv.com/deep-learning-based-text-recognition-ocr-using-tesseract-and-opencv/); [done] make use of tesseract/opencv (https://learnopencv.com/deep-learning-based-text-recognition-ocr-using-tesseract-and-opencv/); [done]
Add features: Add features:
autodetect store type autodetect store type
auto download of stores modules [done] auto download of stores modules [done]
auto download of ofd modules [done] auto download of ofd modules [done]
settings, a window for editing settings. [done] settings, a window for editing settings. [done]
add ability to control contrast and rotation of a check image before passing it to OCR 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: Refactor:
Get rid of CPR, use libcurl instead [done] Get rid of CPR, use libcurl instead [done]
Build: Build:
Write script for AppImage deployment Write script for AppImage deployment [done]
Find out dependencies packet names on different distros Find out dependencies packet names on different distros [done for arch, ubuntu]
Ensure success of building on most popular distros Ensure success of building on most popular distros [done for arch, ubuntu]
Try to compile it on Windows 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]

102
adjustpicturedialog.cpp Normal file
View File

@@ -0,0 +1,102 @@
#include "adjustpicturedialog.h"
#include "ui_adjustpicturedialog.h"
#include "utils/utils.h"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <string>
#include <opencv2/core/mat.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include <zbar.h>
AdjustPictureDialog::AdjustPictureDialog(QWidget *parent, std::string imagePath)
: QDialog(parent)
, ui(new Ui::AdjustPictureDialog)
, pixmap(QString::fromStdString(imagePath))
, img(pixmap.toImage()){
ui->setupUi(this);
computeContrastLookupTable();
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
scene->addPixmap(pixmap);
}
AdjustPictureDialog::~AdjustPictureDialog() {
delete ui;
}
void AdjustPictureDialog::accept() {
QPixmap pixMap = ui->graphicsView->grab();
pixMap.save(QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/temp.png")));
std::string result = decode();
if (result == "") {
QMessageBox infoDialog;
infoDialog.setText(tr("QR code was not detected on that image. Please edit it again or enter data manually"));
infoDialog.setIcon(QMessageBox::Warning);
infoDialog.setWindowTitle(tr("No QR code"));
infoDialog.exec();
} else {
emit decodedData(result);
QDialog::accept();
}
}
std::string AdjustPictureDialog::decode() {
cv::Mat im = cv::imread(get_path_relative_to_home(".local/share/checks_parser/temp.png"));
zbar::ImageScanner scanner;
scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
cv::Mat imGray;
cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY);
zbar::Image image(im.cols, im.rows, "Y800", (uchar *) imGray.data, im.cols * im.rows);
scanner.scan(image);
std::string result = "";
for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
result = symbol->get_data();
}
return result;
}
void AdjustPictureDialog::computeContrastLookupTable() {
for (int contrastValue = 0; contrastValue < 100; ++contrastValue) {
double contrast = contrastValue / 50.0;
for (int i = 0; i < 256; ++i) {
unsigned short correctedValue = std::clamp(static_cast<int>(128 + contrast * (i - 128)), 0, 255);
contrastLUT[contrastValue].push_back(correctedValue);
}
}
}
void AdjustPictureDialog::on_contrastSlider_sliderMoved(int position) {
QImage image = img.copy();
uint32_t* pixels = reinterpret_cast<uint32_t*>(image.bits());
int width = image.width();
int height = image.height();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
QRgb rgb = pixels[y * width + x];
pixels[y * width + x] = qRgba(
contrastLUT[position][qRed(rgb)],
contrastLUT[position][qGreen(rgb)],
contrastLUT[position][qBlue(rgb)],
qAlpha(rgb));
}
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image));
}

39
adjustpicturedialog.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef ADJUSTPICTUREDIALOG_H
#define ADJUSTPICTUREDIALOG_H
#include <QDialog>
#include <QGraphicsScene>
namespace Ui {
class AdjustPictureDialog;
}
class AdjustPictureDialog : public QDialog
{
Q_OBJECT
public:
explicit AdjustPictureDialog(QWidget *parent = nullptr, std::string imagePath = "");
~AdjustPictureDialog();
std::string decode();
QPixmap pixmap;
QImage img;
void computeContrastLookupTable();
std::vector<unsigned short> contrastLUT[100];
signals:
void decodedData(std::string data);
private slots:
// void on_buttonBox_accepted();
void accept() override;
void on_contrastSlider_sliderMoved(int position);
private:
Ui::AdjustPictureDialog *ui;
QGraphicsScene *scene;
};
#endif // ADJUSTPICTUREDIALOG_H

121
adjustpicturedialog.ui Normal file
View File

@@ -0,0 +1,121 @@
<?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>

View File

@@ -1 +0,0 @@
checks-parser.png

View File

@@ -1 +0,0 @@
usr/bin/checks-parser

4
deploy/appimage/AppDir/AppRun Executable file
View File

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

View File

@@ -1,8 +1,6 @@
[Desktop Entry] [Desktop Entry]
Name=Checks parser Name=Checks parser
Type=Application Exec=usr/bin/checks-parser
Terminal=false
NoDisplay=false
Exec=checks-parser
Categories=Utility;
Icon=checks-parser Icon=checks-parser
Type=Application
Categories=Utility;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 627 KiB

After

Width:  |  Height:  |  Size: 138 KiB

31
deploy/appimage/deploy.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
rm -rf AppDir
mkdir -p AppDir
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
cp ../../icon.png AppDir/checks-parser.png
chmod +x AppDir/AppRun
cp ../../checks-parser AppDir/usr/bin
linuxdeployqt AppDir/usr/bin/checks-parser -no-copy-copyright-files -appimage

View File

@@ -0,0 +1,6 @@
#include "ofdrequestexception.h"
OfdRequestException::OfdRequestException(const char* msg) : message(msg) {}
const char* OfdRequestException::what() throw() {
return message.c_str();
}

View File

@@ -0,0 +1,16 @@
#ifndef OFDREQUESTEXCEPTION_H
#define OFDREQUESTEXCEPTION_H
#include <exception>
#include <string>
class OfdRequestException : public std::exception
{
private:
std::string message;
public:
OfdRequestException(const char* msg);
const char* what() throw();
};
#endif // OFDREQUESTEXCEPTION_H

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

116
icon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 649 KiB

View File

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

View File

@@ -0,0 +1,48 @@
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QPixmap>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QtMath>
#include "imageredactor.h"
ImageRedactor::ImageRedactor(QWidget *parent) : QGraphicsView(parent) {
scene = new QGraphicsScene(this);
setScene(scene);
// Load the image
QPixmap pixmap("image.jpg");
item = new QGraphicsPixmapItem(pixmap);
scene->addItem(item);
// Set the initial zoom level
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
}
void ImageRedactor::wheelEvent(QWheelEvent *event) {
// Zoom in/out
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
double angle = event->angleDelta().y();
double factor = qPow(1.2, angle / 240.0);
scale(factor, factor);
}
void ImageRedactor::mousePressEvent(QMouseEvent *event)
{
// Pan the image
if (event->button() == Qt::LeftButton)
{
setDragMode(QGraphicsView::ScrollHandDrag);
}
}
void ImageRedactor::mouseReleaseEvent(QMouseEvent *event)
{
// Reset the drag mode
if (event->button() == Qt::LeftButton)
{
setDragMode(QGraphicsView::NoDrag);
}
}

View File

@@ -0,0 +1,27 @@
#ifndef IMAGEREDACTOR_H
#define IMAGEREDACTOR_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QWheelEvent>
#include <QMouseEvent>
class ImageRedactor : public QGraphicsView
{
Q_OBJECT
public:
ImageRedactor(QWidget *parent = nullptr);
QGraphicsScene *scene;
protected:
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
QGraphicsPixmapItem *item;
};
#endif // IMAGEREDACTOR_H

View File

@@ -1,40 +1,35 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "net/net.h" #include "net/net.h"
#include "ofd/ofd.h"
#include "settings/settings.h" #include "settings/settings.h"
#include "utils/utils.h" #include "utils/utils.h"
#include <QApplication> #include <QApplication>
#include <curl/curl.h> #include <curl/curl.h>
#include <iostream> #include <iostream>
#include <filesystem> #if __GNUC__ < 8 && __clang_major__ < 17
# include <experimental/filesystem>
using namespace std::experimental::filesystem;
#else
# include <filesystem>
using namespace std::filesystem;
#endif
#include <QFile>
#include <QTextStream>
#include <QTranslator>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser"); std::string program_data_path = get_path_relative_to_home(".local/share/checks_parser");
std::filesystem::create_directories(program_data_path); create_directories(program_data_path);
std::string settings_file_path = std::string settings_file_path =
get_path_relative_to_home(".local/share/checks_parser/settings.json"); get_path_relative_to_home(".local/share/checks_parser/settings.json");
Settings s(settings_file_path); Settings s(settings_file_path);
OFD ofd;
Net n; Net n;
std::vector<std::string> ofd_updates = ofd.check_updates();
for (const std::string &update : ofd_updates) {
std::cout << "Downloading "
<< s.get_setting("ofds_modules_url") + update << " to "
<< get_path_relative_to_home(s.get_setting("ofds_modules_dir") +
"/" + update)
<< std::endl;
n.get_file(s.get_setting("ofds_modules_url") + "/" + update,
get_path_relative_to_home(s.get_setting("ofds_modules_dir") +
"/" + update));
}
Parser p; Parser p;
std::vector<std::string> stores_updates = p.check_updates();\ std::vector<std::string> stores_updates = p.check_updates();
for (const std::string &update : stores_updates) { for (const std::string &update : stores_updates) {
std::cout << "Downloading " std::cout << "Downloading "
<< s.get_setting("stores_modules_url") + update << " to " << s.get_setting("stores_modules_url") + update << " to "
@@ -48,7 +43,22 @@ int main(int argc, char *argv[]) {
} }
QApplication a(argc, argv); QApplication a(argc, argv);
QTranslator translator;
QString lang = "en_US";
if (s.get_all_settings().contains("language")) {
lang = QString::fromStdString(s.get_all_settings()["language"]);
} else if (translator.load(":/translation/"+QLocale::system().name()+".qm")) {
lang = QLocale::system().name();
} else {
lang = QString::fromStdString("en_US");
}
translator.load(":/translation/" + lang + ".qm");
a.installTranslator(&translator);
MainWindow w; MainWindow w;
w.update();
w.show(); w.show();
return a.exec(); return a.exec();

View File

@@ -1,12 +1,21 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "./ui_mainwindow.h" #include "./ui_mainwindow.h"
#include "check/check.h" #include "check/check.h"
#include "exceptions/ofdrequestexception.h"
#include "goods/goods.h" #include "goods/goods.h"
#include "outputdialog.h" #include "outputdialog.h"
#include "adjustpicturedialog.h"
#include "settingsdialog.h" #include "settingsdialog.h"
#include <iostream> #include "solvecaptchadialog.h"
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox>
#include "image/checkimage.h" #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>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) { : QMainWindow(parent), ui(new Ui::MainWindow) {
@@ -28,27 +37,73 @@ void MainWindow::setupStoresList() {
QString s = QString::fromStdWString(module_name); QString s = QString::fromStdWString(module_name);
ui->storeType->addItem(s); ui->storeType->addItem(s);
} }
#ifdef DEBUG
for (auto module : parser.search_modules()) {
std::cout << "Module: " << module << std::endl;
}
#endif
} }
void MainWindow::on_checkType_currentIndexChanged(int index) { std::string MainWindow::makeRequestToOfd(std::string captcha) {
ui->inputHolder->setCurrentIndex(index); 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);
return checkContent;
} }
void MainWindow::on_parseButton_clicked() { void MainWindow::on_parseButton_clicked() {
QString s; QString s;
switch (ui->checkType->currentIndex()) { switch (ui->tabWidget->currentIndex()) {
case 0: case 0:
s = ui->checkContent->toPlainText(); s = ui->checkContent->toPlainText();
break; break;
case 1: case 1:
s = ui->checkContentFromImage->toPlainText(); s = ui->checkContentFromImage->toPlainText();
break; 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();
}
return;
} }
std::wstring check_plaintext = s.toStdWString(); std::wstring check_plaintext = s.toStdWString();
@@ -57,12 +112,14 @@ void MainWindow::on_parseButton_clicked() {
std::vector<Goods> c = parser.parse(check_plaintext); std::vector<Goods> c = parser.parse(check_plaintext);
if (c.size() == 0) { if (c.size() == 0) {
std::cerr << "An error has occured. Check was matched incorrectly. Vector sizes are different" << std::endl; QMessageBox infoDialog;
infoDialog.setText(tr("An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer."));
infoDialog.setIcon(QMessageBox::Critical);
infoDialog.setWindowTitle(tr("Error in parsing"));
infoDialog.exec();
return; return;
} }
Check check;
for (auto& g : c) { for (auto& g : c) {
check.add_goods(g); check.add_goods(g);
} }
@@ -77,20 +134,6 @@ void MainWindow::on_storeType_currentIndexChanged(int index) {
parser.set_module(module); parser.set_module(module);
} }
void MainWindow::on_chooseImageButton_clicked() {
QString filename = QFileDialog::getOpenFileName();
std::cout << filename.toStdString() << std::endl;
// this->options.set_path(filename.toStdString());
std::string new_text = "Path to export: " + filename.toStdString();
ui->pathLabel->setText(QString::fromStdString(new_text));
CheckImage i(filename.toStdString());
std::string parsed = i.parse_text();
ui->checkContentFromImage->setPlainText(QString::fromStdString(parsed));
}
void MainWindow::on_preferencesButton_clicked() { void MainWindow::on_preferencesButton_clicked() {
SettingsDialog s = SettingsDialog(); SettingsDialog s = SettingsDialog();
@@ -98,3 +141,72 @@ void MainWindow::on_preferencesButton_clicked() {
s.exec(); s.exec();
} }
void MainWindow::on_chooseImageButton_ofd_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;
}
std::string new_text = "Selected: " + filename.toStdString();
ui->pathLabel_ofd->setText(QString::fromStdString(new_text));
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);
}
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));
}
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));
}

View File

@@ -24,17 +24,20 @@ public:
void setupStoresList(); void setupStoresList();
Check get_check(); Check get_check();
private slots: void onDecodedData(std::string);
void on_checkType_currentIndexChanged(int index);
std::string makeRequestToOfd(std::string captcha);
private slots:
void on_parseButton_clicked(); void on_parseButton_clicked();
void on_storeType_currentIndexChanged(int index); void on_storeType_currentIndexChanged(int index);
void on_chooseImageButton_clicked();
void on_preferencesButton_clicked(); void on_preferencesButton_clicked();
void on_chooseImageButton_ofd_clicked();
void on_chooseImageButton_ocr_clicked();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
}; };

View File

@@ -34,131 +34,9 @@
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">
<string>Store</string> <string>Store type</string>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="checkTypeLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>81</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Check type</string>
</property>
</widget>
<widget class="QComboBox" name="checkType">
<property name="geometry">
<rect>
<x>90</x>
<y>50</y>
<width>211</width>
<height>26</height>
</rect>
</property>
<item>
<property name="text">
<string>Text</string>
</property>
</item>
<item>
<property name="text">
<string>Image (OCR)</string>
</property>
</item>
</widget>
<widget class="QStackedWidget" name="inputHolder">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>501</width>
<height>471</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_5">
<widget class="QLabel" name="checkContentLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>10</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>10</x>
<y>50</y>
<width>431</width>
<height>401</height>
</rect>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_6">
<widget class="QLabel" name="pathLabel">
<property name="geometry">
<rect>
<x>110</x>
<y>20</y>
<width>381</width>
<height>18</height>
</rect>
</property>
<property name="text">
<string>Path to image: </string>
</property>
</widget>
<widget class="QPushButton" name="chooseImageButton">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>80</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>50</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="QPlainTextEdit" name="checkContentFromImage">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>471</width>
<height>371</height>
</rect>
</property>
</widget>
</widget>
</widget>
<widget class="QPushButton" name="parseButton"> <widget class="QPushButton" name="parseButton">
<property name="geometry"> <property name="geometry">
<rect> <rect>
@@ -185,6 +63,320 @@
<string>Preferences</string> <string>Preferences</string>
</property> </property>
</widget> </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>10</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>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">

View File

@@ -1,5 +1,6 @@
#include "net.h" #include "net.h"
#include <curl/curl.h> #include <curl/curl.h>
#include "../utils/utils.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <regex> #include <regex>
@@ -32,6 +33,12 @@ void write_modules(void *buffer, size_t size, size_t nmemb, void *modules) {
} }
} }
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) { std::vector<std::string> Net::get_all_modules(std::string url) {
CURL *handle = curl_easy_init(); CURL *handle = curl_easy_init();
@@ -47,7 +54,7 @@ std::vector<std::string> Net::get_all_modules(std::string url) {
return modules; return modules;
} }
std::string Net::get_file(std::string url, std::string filename) { void Net::get_file(std::string url, std::string filename) {
CURL *handle = curl_easy_init(); CURL *handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
@@ -58,6 +65,45 @@ std::string Net::get_file(std::string url, std::string filename) {
auto success = curl_easy_perform(handle); auto success = curl_easy_perform(handle);
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
}
return "";
std::string Net::fetch_check_data_from_ofdru(std::string fn, std::string fd, std::string fi, std::string datetime, int operation, int total, std::string captcha) {
CURL *handle = curl_easy_init();
if (handle == nullptr) {
std::cerr << "cannot initialize curl" << std::endl;
return "";
}
struct curl_slist *headers = NULL;
std::string readBuffer = "";
curl_easy_setopt(handle, CURLOPT_URL, "https://check.ofd.ru/Document/FetchReceiptFromFns");
headers = curl_slist_append(headers, "Content-Type: application/json;charset=UTF-8");
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
std::string dataJSON =
"{"
"\"TotalSum\":" + std::to_string(total) + ","
"\"FnNumber\":\"" + fn + "\","
"\"ReceiptOperationType\":\"" + std::to_string(operation) + "\","
"\"DocNumber\":\"" + fd + "\","
"\"DocFiscalSign\":\"" + fi + "\","
"\"Captcha\":\"" + captcha + "\","
"\"DocDateTime\":\"" + datetime + ".000Z\""
"}";
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, dataJSON.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &readBuffer);
auto answer = curl_easy_perform(handle);
delete headers;
curl_easy_cleanup(handle);
return readBuffer;
}
void Net::get_captcha_from_ofdru() {
get_file("https://check.ofd.ru/api/captcha/common/img", get_path_relative_to_home(".local/share/checks_parser/captcha.jpg"));
} }

View File

@@ -11,7 +11,9 @@ class Net
public: public:
Net(); Net();
std::vector<std::string> get_all_modules(std::string url); std::vector<std::string> get_all_modules(std::string url);
std::string get_file(std::string url, std::string filename); void get_file(std::string url, std::string filename);
std::string fetch_check_data_from_ofdru(std::string fn, std::string fd, std::string fi, std::string datetime, int operation, int total, std::string captcha);
void get_captcha_from_ofdru();
}; };
#endif // NET_H #endif // NET_H

View File

@@ -1,24 +0,0 @@
#include "module.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include "../utils/utils.h"
OFDModule::OFDModule() {}
OFDModule::OFDModule(std::string path) {
this->path = path;
std::ifstream settings_file(path);
nlohmann::json settings = nlohmann::json::parse(settings_file);
this->name = from_utf8(settings["name"]);
this->url = from_utf8(settings["url"]);
}
std::wstring OFDModule::get_name() {
return this->name;
}
std::wstring OFDModule::get_url() {
return this->url;
}

View File

@@ -1,18 +0,0 @@
#ifndef OFD_MODULE_H
#define OFD_MODULE_H
#include <string>
class OFDModule {
std::string path;
std::wstring name;
std::wstring url;
public:
OFDModule(std::string);
OFDModule();
std::wstring get_name();
std::wstring get_url();
};
#endif // OFDMODULE_H

View File

@@ -1,67 +0,0 @@
#include "ofd.h"
#include "../utils/utils.h"
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
#include "../net/net.h"
#include "../settings/settings.h"
OFD::OFD() {}
OFD::OFD(std::string path) { this->module = OFDModule(path); };
std::vector<std::string> OFD::search_ofds() {
Settings s(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
std::vector<std::string> result{};
std::string path = get_path_relative_to_home(s.get_setting("ods_modules_dir"));
std::filesystem::directory_entry modules_dir(path);
if (!modules_dir.exists()) {
std::filesystem::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;
}
for (auto file : std::filesystem::directory_iterator(path)) {
result.push_back(file.path());
}
return result;
}
void OFD::set_module(std::string path) { this->module = OFDModule(path); }
std::string OFD::get_check_data(std::string fn, std::string fd,
std::string fp) {
//TODO
return "";
}
std::vector<std::string> OFD::check_updates() {
Settings s(get_path_relative_to_home(".local/share/checks_parser/settings.json"));
std::string path = get_path_relative_to_home(s.get_setting("ofds_modules_dir"));
std::vector<std::string> to_download;
std::vector<std::string> stored_modules;
for (const auto& file : std::filesystem::directory_iterator(path)) {
if (!file.is_regular_file()) continue;
stored_modules.push_back(file.path().filename());
std::cout << "Detected OFD module" << file.path().filename() << std::endl;
}
Net n;
std::vector<std::string> remote_modules = n.get_all_modules(s.get_setting("ofds_modules_url"));
for (const std::string& module : remote_modules) {
if (!vector_contains_element(stored_modules, module)) {
to_download.push_back(module);
std::cout << "I need to download OFD module " << module << std::endl;
}
}
return to_download;
}

View File

@@ -1,23 +0,0 @@
#ifndef OFD_H
#define OFD_H
#include <string>
#include <vector>
#include "module.h"
class OFD {
OFDModule module;
public:
OFD();
OFD(std::string);
std::vector<std::string> search_ofds();
void set_module(std::string);
std::string get_check_data(std::string fn, std::string fd, std::string fp);
std::vector<std::string> check_updates();
};
#endif // OFD_H

View File

@@ -3,6 +3,16 @@
#include <string> #include <string>
#include <vector> #include <vector>
#if __GNUC__ < 8
# include <experimental/filesystem>
#else
# include <filesystem>
#endif
#include <iostream>
#include <string>
#include <vector>
#include "../net/net.h"
#include "../settings/settings.h"
enum class ColumnType { enum class ColumnType {
goods_name, goods_name,
@@ -18,7 +28,6 @@ struct Column { // Example:
unsigned int position; // "0" <-- 0 = "A", 1 = "B", etc.. column letter in unsigned int position; // "0" <-- 0 = "A", 1 = "B", etc.. column letter in
// table processor (i.e. excel or libreoffice) // table processor (i.e. excel or libreoffice)
} typedef Column; } typedef Column;
enum class OutputFormat { csv, ods, xlsx, plaintext } typedef OutputFormat; enum class OutputFormat { csv, ods, xlsx, plaintext } typedef OutputFormat;
class OutputOptions { class OutputOptions {

View File

@@ -5,7 +5,6 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMainWindow> #include <QMainWindow>
#include <fstream> #include <fstream>
#include <iostream>
#include "settings/settings.h" #include "settings/settings.h"
#include "utils/utils.h" #include "utils/utils.h"
@@ -17,20 +16,20 @@ OutputDialog::OutputDialog(QWidget *parent, Check &check)
ui->setupUi(this); ui->setupUi(this);
ui->tableWidget->item(0, 0)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_name"]["name"])); ui->tableWidget->item(0, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_name"]["name"]));
ui->tableWidget->item(0, 1)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_name"]["position"])); ui->tableWidget->item(0, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_name"]["position"]));
ui->tableWidget->item(1, 0)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"])); ui->tableWidget->item(1, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_price_per_unit"]["name"]));
ui->tableWidget->item(1, 1)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"])); ui->tableWidget->item(1, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_price_per_unit"]["position"]));
ui->tableWidget->item(2, 0)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_quantity"]["name"])); ui->tableWidget->item(2, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_quantity"]["name"]));
ui->tableWidget->item(2, 1)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_quantity"]["position"])); ui->tableWidget->item(2, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_quantity"]["position"]));
ui->tableWidget->item(3, 0)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_net_weight"]["name"])); ui->tableWidget->item(3, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_net_weight"]["name"]));
ui->tableWidget->item(3, 1)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_net_weight"]["position"])); ui->tableWidget->item(3, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_net_weight"]["position"]));
ui->tableWidget->item(4, 0)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_total"]["name"])); ui->tableWidget->item(4, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["goods_total"]["name"]));
ui->tableWidget->item(4, 1)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_total"]["position"])); ui->tableWidget->item(4, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["goods_total"]["position"]));
ui->printHeaderCheckBox->setChecked(settings.get_all_settings()["print_header"]); ui->printHeaderCheckBox->setChecked(settings.get_all_settings()["print_header"]);
@@ -73,38 +72,35 @@ void OutputDialog::on_buttonBox_accepted() {
for (auto goods : this->check.get_goods()) { for (auto goods : this->check.get_goods()) {
for (auto &column : this->options.get_columns()) { for (auto &column : this->options.get_columns()) {
std::string output_str;
switch (column.type) { switch (column.type) {
case ColumnType::goods_name: case ColumnType::goods_name:
output_str = goods.get_name(); output_file << goods.get_name();
break; break;
case ColumnType::goods_price_per_unit: case ColumnType::goods_price_per_unit:
output_str = std::to_string(goods.get_price_per_unit()); output_file << std::fixed << std::setprecision(2) << goods.get_price_per_unit();
break; break;
case ColumnType::goods_quantity: case ColumnType::goods_quantity:
output_str = std::to_string(goods.get_quantity()); output_file << std::fixed << std::setprecision(2) << goods.get_quantity();
break; break;
case ColumnType::goods_net_weight: case ColumnType::goods_net_weight:
output_str = "TODO"; output_file << "TODO";
// TODO // TODO
break; break;
case ColumnType::goods_total: case ColumnType::goods_total:
output_str = std::to_string(goods.calculate_total_price()); output_file << std::fixed << std::setprecision(2) << goods.calculate_total_price();
break; break;
} }
if (column.position != this->options.get_columns().size()) { if (column.position != this->options.get_columns().size()) {
output_str += ","; output_file << ",";
} else { } else {
output_str += "\n"; output_file << "\n";
} }
output_file << output_str;
} }
} }
if (this->options.get_print_total()) { if (this->options.get_print_total()) {
output_file << "Total: " << std::to_string(check.calculae_total_price()); output_file << "Total: " << std::fixed << std::setprecision(2) << check.calculae_total_price() << std::endl;
} }
output_file.close(); output_file.close();

View File

@@ -23,10 +23,10 @@
</rect> </rect>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="pathLabel"> <widget class="QLabel" name="pathLabel">
@@ -73,8 +73,8 @@
<rect> <rect>
<x>10</x> <x>10</x>
<y>130</y> <y>130</y>
<width>321</width> <width>401</width>
<height>181</height> <height>221</height>
</rect> </rect>
</property> </property>
<row> <row>

View File

@@ -3,18 +3,26 @@
#include "../net/net.h" #include "../net/net.h"
#include "../settings/settings.h" #include "../settings/settings.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include <filesystem>
#include <iostream> #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() {} Parser::Parser() {}
std::vector<std::string> Parser::search_modules() { std::vector<std::string> Parser::search_modules() {
Settings s(get_path_relative_to_home(".local/share/checks_parser/settings.json")); 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; std::string path = get_path_relative_to_home(s.get_setting("stores_modules_dir"));//std::string(std::getenv("HOME")) + "/" + STORES_MODULES_DIR;
std::filesystem::directory_entry modules_dir(path); directory_entry modules_dir(path);
if (!modules_dir.exists()) { if (!exists(modules_dir)) {
std::filesystem::create_directories(path); create_directories(path);
std::cout << "No modules directory found. Created one at " << path std::cout << "No modules directory found. Created one at " << path
<< std::endl; << std::endl;
std::cout << "Please, download modules to that directory from my git." std::cout << "Please, download modules to that directory from my git."
@@ -23,7 +31,7 @@ std::vector<std::string> Parser::search_modules() {
std::vector<std::string> modules_files; std::vector<std::string> modules_files;
for (auto file : std::filesystem::directory_iterator(path)) { for (auto file : directory_iterator(path)) {
modules_files.push_back(file.path()); modules_files.push_back(file.path());
} }
@@ -67,17 +75,17 @@ std::vector<std::string> Parser::check_updates() {
std::vector<std::string> to_download; std::vector<std::string> to_download;
std::vector<std::string> stored_modules; std::vector<std::string> stored_modules;
std::filesystem::directory_entry modules_dir(path); directory_entry modules_dir(path);
if (!modules_dir.exists()) { if (!exists(modules_dir)) {
std::filesystem::create_directories(path); create_directories(path);
} }
for (const auto& file : std::filesystem::directory_iterator(path)) { for (const auto& file : directory_iterator(path)) {
if (!file.is_regular_file()) continue; if (!is_regular_file(file)) continue;
stored_modules.push_back(file.path().filename()); stored_modules.push_back(file.path().filename());
std::cout << file.path().filename() << " detected store module" << std::endl; std::cout << file.path().filename() << " detected store module" << std::endl;
} }
Net n; Net n;
std::cerr << "Downloading modules list from: " << s.get_setting("stores_modules_url"); 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")); std::vector<std::string> remote_modules = n.get_all_modules(s.get_setting("stores_modules_url"));
if (stored_modules.empty()) { if (stored_modules.empty()) {
std::cout << "I need to download everything" << std::endl; std::cout << "I need to download everything" << std::endl;

View File

@@ -1,21 +1,29 @@
#include "settings.h" #include "settings.h"
#include <filesystem>
#include <fstream> #include <fstream>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
#include "../utils/utils.h" #include "../utils/utils.h"
#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
Settings::Settings(std::string path) { Settings::Settings(std::string path) {
this->settings_file_path = path; this->settings_file_path = path;
if (!std::filesystem::exists(path)) { if (!exists(path)) {
std::ofstream output(path); std::ofstream output(path);
nlohmann::json settings = R"({ nlohmann::json settings = R"({
"ofds_modules_dir":".local/share/checks_parser/modules/ofd", "ofds_modules_dir":".local/share/checks_parser/modules/ofd",
"stores_modules_dir":".local/share/checks_parser/modules/stores", "stores_modules_dir":".local/share/checks_parser/modules/stores",
"ofds_modules_url":"https://foxarmy.org/checks-parser/modules/ofd/", "ofds_modules_url":"https://foxarmy.org/checks-parser/modules/ofd/",
"stores_modules_url":"https://foxarmy.org/checks-parser/modules/modules/", "stores_modules_url":"https://foxarmy.org/checks-parser/modules/stores/",
"print_header": true, "print_header": true,
"print_total": true, "print_total": true,
"output_order": { "output_order": {
@@ -42,7 +50,7 @@ Settings::Settings(std::string path) {
} }
})"_json; })"_json;
output << settings; output << settings.dump(4);
output.flush(); output.flush();
output.close(); output.close();
this->settings = settings; this->settings = settings;
@@ -53,8 +61,8 @@ Settings::Settings(std::string path) {
this->settings = settings; this->settings = settings;
} }
std::filesystem::create_directories(get_path_relative_to_home(this->settings["ofds_modules_dir"])); create_directories(get_path_relative_to_home(this->settings["ofds_modules_dir"]));
std::filesystem::create_directories(get_path_relative_to_home(this->settings["stores_modules_dir"])); create_directories(get_path_relative_to_home(this->settings["stores_modules_dir"]));
} }
void Settings::write_setting(std::string setting, std::string value) { void Settings::write_setting(std::string setting, std::string value) {
@@ -62,7 +70,7 @@ void Settings::write_setting(std::string setting, std::string value) {
this->settings[setting] = value; this->settings[setting] = value;
output << this->settings; output << this->settings.dump(4);
} }
std::string Settings::get_setting(std::string setting) { std::string Settings::get_setting(std::string setting) {
return this->settings[setting]; return this->settings[setting];
@@ -85,5 +93,5 @@ void Settings::alter_setting(std::string setting, std::string value) {
void Settings::flush() { void Settings::flush() {
std::ofstream output(this->settings_file_path, std::fstream::trunc); std::ofstream output(this->settings_file_path, std::fstream::trunc);
output << this->settings; output << this->settings.dump(4);
} }

View File

@@ -2,7 +2,8 @@
#include "settings/settings.h" #include "settings/settings.h"
#include "ui_settingsdialog.h" #include "ui_settingsdialog.h"
#include "utils/utils.h" #include "utils/utils.h"
#include <iostream>
#include <QMessageBox>
SettingsDialog::SettingsDialog(QWidget *parent) SettingsDialog::SettingsDialog(QWidget *parent)
: QDialog(parent), ui(new Ui::settingsdialog), : QDialog(parent), ui(new Ui::settingsdialog),
@@ -33,6 +34,19 @@ SettingsDialog::SettingsDialog(QWidget *parent)
ui->printHeaderCheckBox->setChecked(this->settings.get_all_settings()["print_header"]); ui->printHeaderCheckBox->setChecked(this->settings.get_all_settings()["print_header"]);
ui->printTotalCheckBox->setChecked(this->settings.get_all_settings()["print_total"]); ui->printTotalCheckBox->setChecked(this->settings.get_all_settings()["print_total"]);
int currentLanguageIndex = 0;
if (!this->settings.get_all_settings().contains("language")) {
currentLanguageIndex = ui->languageComboBox->findText(QLocale::system().name());
if (currentLanguageIndex < 0) {
currentLanguageIndex = ui->languageComboBox->findText("en_US");
}
} else {
currentLanguageIndex = ui->languageComboBox->findText(QString::fromStdString(this->settings.get_all_settings()["language"]));
}
ui->languageComboBox->setCurrentIndex(currentLanguageIndex);
} }
SettingsDialog::~SettingsDialog() { delete ui; } SettingsDialog::~SettingsDialog() { delete ui; }
@@ -122,4 +136,19 @@ void SettingsDialog::on_buttonBox_accepted() { this->settings.flush(); }
void SettingsDialog::on_buttonBox_rejected() { this->close(); } void SettingsDialog::on_buttonBox_rejected() { this->close(); }
void SettingsDialog::on_languageComboBox_currentTextChanged(const QString &changed) {
if (this->settings.get_all_settings().contains("language")) {
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();
}

View File

@@ -52,6 +52,8 @@ private slots:
void on_buttonBox_rejected(); void on_buttonBox_rejected();
void on_languageComboBox_currentTextChanged(const QString &arg1);
private: private:
Ui::settingsdialog *ui; Ui::settingsdialog *ui;
}; };

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>599</width> <width>599</width>
<height>727</height> <height>799</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -17,16 +17,16 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>310</x> <x>310</x>
<y>690</y> <y>740</y>
<width>251</width> <width>251</width>
<height>32</height> <height>32</height>
</rect> </rect>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property> </property>
</widget> </widget>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
@@ -35,7 +35,7 @@
<x>10</x> <x>10</x>
<y>0</y> <y>0</y>
<width>541</width> <width>541</width>
<height>661</height> <height>741</height>
</rect> </rect>
</property> </property>
<property name="widgetResizable"> <property name="widgetResizable">
@@ -47,7 +47,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>539</width> <width>539</width>
<height>659</height> <height>739</height>
</rect> </rect>
</property> </property>
<widget class="QWidget" name="gridLayoutWidget"> <widget class="QWidget" name="gridLayoutWidget">
@@ -56,16 +56,126 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>531</width> <width>531</width>
<height>651</height> <height>731</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="11" column="1"> <item row="15" column="1">
<widget class="QLineEdit" name="goodsNetWeightAliasEdit"/> <widget class="QCheckBox" name="printTotalCheckBox">
<property name="text">
<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="4" column="1">
<widget class="QSpinBox" name="goodsNamePositionSpin"/>
</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="8" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Goods quantity position</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="OFDModulesDirEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>OFD modules url</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Print header</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="goodsPricePerUnitPositionSpin"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="storesModulesURLEdit"/>
</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="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>OFD modules directory</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="goodsNameAliasEdit"/>
</item>
<item row="15" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Print total</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QLineEdit" name="goodsTotalAliasEdit"/>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="goodsQuantityPositionSpin"/>
</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="10" column="1">
<widget class="QSpinBox" name="goodsNetWeightPositionSpin"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="OFDModulesURLEdit"/>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Goods total alias</string>
</property>
</widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="storesModulesDirEdit"/> <widget class="QLineEdit" name="storesModulesDirEdit"/>
</item> </item>
<item row="7" column="1">
<widget class="QLineEdit" name="goodsPricePerUnitAliasEdit"/>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="goodsQuantityAliasEdit"/>
</item>
<item row="11" column="1">
<widget class="QLineEdit" name="goodsNetWeightAliasEdit"/>
</item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
@@ -73,6 +183,51 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="1">
<widget class="QCheckBox" name="printHeaderCheckBox">
<property name="text">
<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="6" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Goods price per unit position</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="12" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Goods total position</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="OFDModulesDirChooseButton">
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QSpinBox" name="goodsTotalPositionSpin"/>
</item>
<item row="7" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_12"> <widget class="QLabel" name="label_12">
<property name="text"> <property name="text">
@@ -87,159 +242,25 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="1"> <item row="16" column="0">
<widget class="QLineEdit" name="goodsTotalAliasEdit"/> <widget class="QLabel" name="label_4">
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Print header</string> <string>TextLabel</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="16" column="1">
<widget class="QLabel" name="label_16"> <widget class="QComboBox" name="languageComboBox">
<property name="text"> <item>
<string>Goods net weight alias</string> <property name="text">
</property> <string>en_US</string>
</widget> </property>
</item> </item>
<item row="3" column="0"> <item>
<widget class="QLabel" name="label_8"> <property name="text">
<property name="text"> <string>ru_RU</string>
<string>Stores modules url</string> </property>
</property> </item>
</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> </widget>
</item> </item>
</layout> </layout>

36
solvecaptchadialog.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include "solvecaptchadialog.h"
#include "ui_solvecaptchadialog.h"
#include "utils/utils.h"
#include <iostream>
#include <QMessageBox>
SolveCaptchaDialog::SolveCaptchaDialog(QWidget *parent, std::string* solved_captcha) :
QDialog(parent),
ui(new Ui::SolveCaptchaDialog),
solved_captcha(solved_captcha) {
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);
}
void SolveCaptchaDialog::accept() {
std::string userInput = ui->captcha_edit->text().toStdString();
if (userInput.length() < 6) {
QMessageBox infoDialog;
infoDialog.setText(tr("Please, enter a valid captcha"));
infoDialog.setIcon(QMessageBox::Warning);
infoDialog.setWindowTitle(tr("No captcha"));
infoDialog.exec();
} else {
solved_captcha->erase();
solved_captcha->append(userInput);
QDialog::accept();
}
}
SolveCaptchaDialog::~SolveCaptchaDialog() {
delete ui;
}

26
solvecaptchadialog.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef SOLVECAPTCHADIALOG_H
#define SOLVECAPTCHADIALOG_H
#include <QDialog>
namespace Ui {
class SolveCaptchaDialog;
}
class SolveCaptchaDialog : public QDialog
{
Q_OBJECT
public:
explicit SolveCaptchaDialog(QWidget *parent = nullptr, std::string* = nullptr) ;
~SolveCaptchaDialog();
private:
Ui::SolveCaptchaDialog *ui;
std::string* solved_captcha;
private slots:
void accept() override;
};
#endif // SOLVECAPTCHADIALOG_H

91
solvecaptchadialog.ui Normal file
View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SolveCaptchaDialog</class>
<widget class="QDialog" name="SolveCaptchaDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>503</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>130</x>
<y>310</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="QLabel" name="captcha_picture">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>451</width>
<height>221</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLineEdit" name="captcha_edit">
<property name="geometry">
<rect>
<x>80</x>
<y>260</y>
<width>321</width>
<height>26</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SolveCaptchaDialog</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>SolveCaptchaDialog</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>

7
translations.qrc Normal file
View File

@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/translation">
<file>en_US.qm</file>
<file>ru_RU.qm</file>
</qresource>
<qresource prefix="/translations"/>
</RCC>

451
translations/en_US.ts Normal file
View File

@@ -0,0 +1,451 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>AdjustPictureDialog</name>
<message>
<location filename="../adjustpicturedialog.ui" line="14"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../adjustpicturedialog.ui" line="58"/>
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
<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>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>No QR code</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.ui" line="14"/>
<source>MainWindow</source>
<translation>Главное окно</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="37"/>
<source>Store type</source>
<translation>Store type</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="50"/>
<source>Parse</source>
<translation>Parse</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="63"/>
<source>Preferences</source>
<translation>Preferences</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="80"/>
<source>Text</source>
<translation>Text</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="92"/>
<source>Check content</source>
<translation>Check content</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="108"/>
<source>OCR</source>
<translatorcomment>OCR = Optical Character Recognition</translatorcomment>
<translation>OCR</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="120"/>
<location filename="../mainwindow.ui" line="213"/>
<source>Choose</source>
<translation>Choose</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="143"/>
<location filename="../mainwindow.ui" line="200"/>
<source>Path to image: </source>
<translation>Path to image: </translation>
</message>
<message>
<location filename="../mainwindow.ui" line="156"/>
<source>Here is recognised check text. Please, edit it if something&apos;s wrong:</source>
<translation>Here is recognised check text. Please, edit it if something&apos;s wrong:</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="175"/>
<source>OFD</source>
<translatorcomment>OFD = Оператор Фискальных Данных</translatorcomment>
<translation>OFD</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="226"/>
<source>0000000000000000</source>
<translation>0000000000000000</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="245"/>
<source>FN (Fiscal Number)</source>
<translatorcomment>FN = Фискальный Номер</translatorcomment>
<translation>FN (Fiscal Number)</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="264"/>
<source>FD (Fiscal Document)</source>
<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>000000000</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="296"/>
<source>FI (Fiscal Identifier)</source>
<translatorcomment>FI = Фискальный Признак</translatorcomment>
<translation>FI (Fiscal Identifier)</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="333"/>
<source>Funds income</source>
<translatorcomment>Приход средств</translatorcomment>
<translation>Funds incode</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="338"/>
<source>Funds return</source>
<translatorcomment>Возврат средств</translatorcomment>
<translation>Funds return</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="343"/>
<source>Funds spend</source>
<translatorcomment>Расход средств</translatorcomment>
<translation>Funds spend</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="348"/>
<source>Spends return</source>
<translatorcomment>Возврат расхода</translatorcomment>
<translation>Spends return</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="375"/>
<source>Total</source>
<translation>Total</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="392"/>
<source>checks parser</source>
<translation>checks parser</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="85"/>
<source>Captcha was not solved correctly!</source>
<translation>Captcha was not solved correctly!</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="87"/>
<source>Captcha is incorrect</source>
<translation>Captcha is incorrect</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="92"/>
<source>Check not found. Please, ensure correctness of entered data.</source>
<translation>Check not found. Please, ensure correctness of entered data.</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="94"/>
<source>Check was not found</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="116"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="118"/>
<source>Error in parsing</source>
<translation>Error in parsing</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="149"/>
<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="151"/>
<location filename="../mainwindow.cpp" line="197"/>
<source>Picture was not selected</source>
<translation>Picture was not selected</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="195"/>
<source>Please, select a picture to scan</source>
<translation>Please, select a picture to scan</translation>
</message>
</context>
<context>
<name>OutputDialog</name>
<message>
<location filename="../outputdialog.ui" line="14"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="42"/>
<source>Path to export: </source>
<translation>Path to export: </translation>
</message>
<message>
<location filename="../outputdialog.ui" line="55"/>
<source>Choose</source>
<translation>Choose</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="68"/>
<source>Print header</source>
<translation>Print header</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="82"/>
<source>Goods name</source>
<translation>Goods name</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="87"/>
<source>Goods price</source>
<translation>Goods price</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="92"/>
<source>Goods quantity</source>
<translation>Goods quality</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="97"/>
<source>Goods net weight</source>
<translation>Goods net weight</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="102"/>
<source>Goods total</source>
<translation>Goods total</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="107"/>
<source>position</source>
<translation>position</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="112"/>
<source>name</source>
<translation>name</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="117"/>
<source>1</source>
<translation>1</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="122"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="127"/>
<source>2</source>
<translation>2</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="132"/>
<source>Price</source>
<translation>Price</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="137"/>
<source>3</source>
<translation>3</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="142"/>
<source>Quantity</source>
<translation>Quantity</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="147"/>
<source>4</source>
<translation>4</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="152"/>
<source>Net weight</source>
<translation>Net Weight</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="157"/>
<source>5</source>
<translation>5</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="162"/>
<source>Total price</source>
<translation>Total price</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="176"/>
<source>Print total</source>
<translation>Print total</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="149"/>
<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="151"/>
<source>Restart required</source>
<translation>Restart required</translation>
</message>
</context>
<context>
<name>SolveCaptchaDialog</name>
<message>
<location filename="../solvecaptchadialog.ui" line="14"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source>
<translation>Please, enter a valid captcha</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source>
<translation>No captcha</translation>
</message>
</context>
<context>
<name>settingsdialog</name>
<message>
<location filename="../settingsdialog.ui" line="14"/>
<source>Dialog</source>
<translation>Dialog</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="182"/>
<source>Goods name position</source>
<translation>Goods name position</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="234"/>
<source>Goods price per unit alias</source>
<translation>Goods price per unit alias</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="248"/>
<source>TextLabel</source>
<translation>Language</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="256"/>
<source>en_US</source>
<translation>en_US</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="261"/>
<source>ru_RU</source>
<translation>ru_RU</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="224"/>
<location filename="../settingsdialog.ui" line="241"/>
<source>Choose</source>
<translation>Choose</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="107"/>
<source>Print header</source>
<translation>Print header</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="150"/>
<source>Goods net weight alias</source>
<translation>Goods net weight alias</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="83"/>
<source>Stores modules url</source>
<translation>Stores modules url</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="163"/>
<source>Goods total alias</source>
<translation>Goods total alias</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="196"/>
<source>Goods name alias</source>
<translation>Goods name alias</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="120"/>
<source>Goods quantity alias</source>
<translation>Goods quantity alias</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="210"/>
<source>Stores modules directory</source>
<translation>Stores modules directory</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="127"/>
<source>OFD modules directory</source>
<translation>OFD modules directory</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="203"/>
<source>Goods price per unit position</source>
<translation>Goods price per unit position</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="73"/>
<source>Goods net weight position</source>
<translation>Goods net weight position</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="100"/>
<source>OFD modules url</source>
<translation>OFD modules url</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="217"/>
<source>Goods total position</source>
<translation>Goods total position</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="90"/>
<source>Goods quantity position</source>
<translation>Goods quantity position</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="137"/>
<source>Print total</source>
<translation>Print total</translation>
</message>
</context>
</TS>

447
translations/ru_RU.ts Normal file
View File

@@ -0,0 +1,447 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>AdjustPictureDialog</name>
<message>
<location filename="../adjustpicturedialog.ui" line="14"/>
<source>Dialog</source>
<translation>Диалог</translation>
</message>
<message>
<location filename="../adjustpicturedialog.ui" line="58"/>
<source>Please, zoom to qr code and adjust contrast so that qr code looks sharp</source>
<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>QR код не найден на этом изображении. Пожалуйста, попытайтесь снова или введите данные вручную</translation>
</message>
<message>
<location filename="../adjustpicturedialog.cpp" line="41"/>
<source>No QR code</source>
<translation>QR код не найден</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.ui" line="14"/>
<source>MainWindow</source>
<translation>ГлавноеОкно</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="37"/>
<source>Store type</source>
<translation>Магазин</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="50"/>
<source>Parse</source>
<translation>Парсить</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="63"/>
<source>Preferences</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="80"/>
<source>Text</source>
<translation>Текст</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="92"/>
<source>Check content</source>
<translation>Контент чека</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="108"/>
<source>OCR</source>
<translatorcomment>Оптическое Распознавание Символов</translatorcomment>
<translation>ОСР</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="120"/>
<location filename="../mainwindow.ui" line="213"/>
<source>Choose</source>
<translation>Выбрать</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="143"/>
<location filename="../mainwindow.ui" line="200"/>
<source>Path to image: </source>
<translation>Путь к изображению: </translation>
</message>
<message>
<location filename="../mainwindow.ui" line="156"/>
<source>Here is recognised check text. Please, edit it if something&apos;s wrong:</source>
<translation>Ниже приведён распознанный текст. Пожалуйста, отредактируйте его:</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="175"/>
<source>OFD</source>
<translatorcomment>Оператор Фискальных Данных</translatorcomment>
<translation>ОФД</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="226"/>
<source>0000000000000000</source>
<translation>0000000000000000</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="245"/>
<source>FN (Fiscal Number)</source>
<translatorcomment>Фискальный Норма</translatorcomment>
<translation>ФН</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="264"/>
<source>FD (Fiscal Document)</source>
<translatorcomment>Фискальный Документ</translatorcomment>
<translation>ФД</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="277"/>
<location filename="../mainwindow.ui" line="309"/>
<source>0000000000</source>
<translation>000000000</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="296"/>
<source>FI (Fiscal Identifier)</source>
<translatorcomment>Фискальный Признак</translatorcomment>
<translation>ФП</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="333"/>
<source>Funds income</source>
<translation>Приход средств</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="338"/>
<source>Funds return</source>
<translation>Возврат средств</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="343"/>
<source>Funds spend</source>
<translation>Расход средств</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="348"/>
<source>Spends return</source>
<translation>Возврат расхода</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="375"/>
<source>Total</source>
<translation>Итого</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="392"/>
<source>checks parser</source>
<translation>Парсер чеков</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="85"/>
<source>Captcha was not solved correctly!</source>
<translation>Капча была решена неверно!</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="87"/>
<source>Captcha is incorrect</source>
<translation>Капча введена неверно</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="92"/>
<source>Check not found. Please, ensure correctness of entered data.</source>
<translation>Чек не найден. Пожалуйста, убедитесь в правильности введённых данных.</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="94"/>
<source>Check was not found</source>
<translation>Чек не найден</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="116"/>
<source>An error has occured. Check was matched incorrectly. Vector sizes are different. Please, contact the developer.</source>
<translation>Произошла ошибка. Чек был прочитан неверно. Размеры векторов различаются. Пожалуйста, сообщите об этом разработчику.</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="118"/>
<source>Error in parsing</source>
<translation>Ошибка в парсинге</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="149"/>
<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="151"/>
<location filename="../mainwindow.cpp" line="197"/>
<source>Picture was not selected</source>
<translation>Изображение не было выбрано</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="195"/>
<source>Please, select a picture to scan</source>
<translation>Пожалуйста, выберете изображение для сканирования</translation>
</message>
</context>
<context>
<name>OutputDialog</name>
<message>
<location filename="../outputdialog.ui" line="14"/>
<source>Dialog</source>
<translation>Диалог</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="42"/>
<source>Path to export: </source>
<translation>Путь для экспорта: </translation>
</message>
<message>
<location filename="../outputdialog.ui" line="55"/>
<source>Choose</source>
<translation>Выбрать</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="68"/>
<source>Print header</source>
<translation>Печатать заголовок</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="82"/>
<source>Goods name</source>
<translation>Имя товара</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="87"/>
<source>Goods price</source>
<translation>Цена товара</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="92"/>
<source>Goods quantity</source>
<translation>Количество товара</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="97"/>
<source>Goods net weight</source>
<translation>Масса нетто товара</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="102"/>
<source>Goods total</source>
<translation>Всего за товар</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="107"/>
<source>position</source>
<translation>позиция</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="112"/>
<source>name</source>
<translation>алиас</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="117"/>
<source>1</source>
<translation>1</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="122"/>
<source>Name</source>
<translation>Имя</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="127"/>
<source>2</source>
<translation>2</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="132"/>
<source>Price</source>
<translation>Цена</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="137"/>
<source>3</source>
<translation>3</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="142"/>
<source>Quantity</source>
<translation>Количество</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="147"/>
<source>4</source>
<translation>4</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="152"/>
<source>Net weight</source>
<translation>Масса нетто</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="157"/>
<source>5</source>
<translation>5</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="162"/>
<source>Total price</source>
<translation>Всего</translation>
</message>
<message>
<location filename="../outputdialog.ui" line="176"/>
<source>Print total</source>
<translation>Печатать Итого</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="149"/>
<source>You need to restart program to apply language changes</source>
<translation>Требуется перезагрузить программу, чтобы применить изменения языка</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="151"/>
<source>Restart required</source>
<translation>Требуется перезагрузка</translation>
</message>
</context>
<context>
<name>SolveCaptchaDialog</name>
<message>
<location filename="../solvecaptchadialog.ui" line="14"/>
<source>Dialog</source>
<translation>Диалог</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="23"/>
<source>Please, enter a valid captcha</source>
<translation>Пожалуйста, введите верную капчу</translation>
</message>
<message>
<location filename="../solvecaptchadialog.cpp" line="25"/>
<source>No captcha</source>
<translation>Нет капчи</translation>
</message>
</context>
<context>
<name>settingsdialog</name>
<message>
<location filename="../settingsdialog.ui" line="14"/>
<source>Dialog</source>
<translation>Диалог</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="182"/>
<source>Goods name position</source>
<translation>Позиция имени товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="234"/>
<source>Goods price per unit alias</source>
<translation>Алиас цены товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="248"/>
<source>TextLabel</source>
<translation>Язык</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="256"/>
<source>en_US</source>
<translation>en_US</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="261"/>
<source>ru_RU</source>
<translation>ru_RU</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="224"/>
<location filename="../settingsdialog.ui" line="241"/>
<source>Choose</source>
<translation>Выбрать</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="107"/>
<source>Print header</source>
<translation>Печатать заголовок</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="150"/>
<source>Goods net weight alias</source>
<translation>Алиас массы нетто товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="83"/>
<source>Stores modules url</source>
<translation>URL модулей магазина</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="163"/>
<source>Goods total alias</source>
<translation>Алиас всего за продукт</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="196"/>
<source>Goods name alias</source>
<translation>Алиас имени товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="120"/>
<source>Goods quantity alias</source>
<translation>Алиас количества товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="210"/>
<source>Stores modules directory</source>
<translation>Директория модулей магазина</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="127"/>
<source>OFD modules directory</source>
<translation>Директория модулей ОФД</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="203"/>
<source>Goods price per unit position</source>
<translation>Позиция центы товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="73"/>
<source>Goods net weight position</source>
<translation>Позиция массы нетто товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="100"/>
<source>OFD modules url</source>
<translation>URL модулей ОФД</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="217"/>
<source>Goods total position</source>
<translation>Позиция всего за товар</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="90"/>
<source>Goods quantity position</source>
<translation>Позиция количества товара</translation>
</message>
<message>
<location filename="../settingsdialog.ui" line="137"/>
<source>Print total</source>
<translation>Печатать Итого</translation>
</message>
</context>
</TS>

View File

@@ -1,8 +1,12 @@
#include "utils.h" #include "utils.h"
#include <codecvt> #include <codecvt>
#include <cstring>
#include <iostream>
#include <locale> #include <locale>
#include <regex>
#include <string> #include <string>
#include "../exceptions/ofdrequestexception.h"
std::string to_utf8(std::wstring wide_string) { std::string to_utf8(std::wstring wide_string) {
static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv; static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
@@ -28,3 +32,115 @@ bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
//ужас //ужас
template bool vector_contains_element<std::string>(const std::vector<std::string>& vector, const std::string& to_find); template bool vector_contains_element<std::string>(const std::vector<std::string>& vector, const std::string& to_find);
std::vector<std::string> split(std::string s, std::string delimiter) {
std::vector<std::string> result;
size_t pos = 0;
std::string 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);
for (std::wsregex_iterator it{text.begin(), text.end(), start_regex}, end{};
it != end; it++) {
start_pos = it->position() + it->str().size();
break;
}
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{};
it != end; it++) {
end_pos = it->position();
break;
}
if (end_pos == 0) return substring;
substring = substring.substr(0, end_pos);
return substring;
}
std::wstring trim_html_response(std::wstring& check) {
std::wstring begin_check_marker = from_utf8("<!-- Products -->");
std::wstring end_check_marker = from_utf8("<!-- \\/Products -->");
std::wstring trimmed = substring_from_to(check, begin_check_marker, end_check_marker);
trimmed += from_utf8("\n</div>");
return trimmed;
}
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);
std::vector<std::wstring> parsed;
for (std::sregex_iterator it{html.begin(), html.end(), searching_regex}, end{};
it != end; it++) {
std::wstring found_entry = from_utf8(it->str());
std::wstring extracted = substring_from_to(found_entry, from_utf8(html_start), from_utf8(html_end));
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>");
}
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> find_prices_in_html(std::string html) {
return find_in_html(html, "X <\\/span><span>\\d+\\.\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
}
Check parseOfdRuAnswer(std::string html) {
std::wstring wstr_html = from_utf8(html);
std::string trimmed = to_utf8(trim_html_response(wstr_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> 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 { // Most likely that the check does not exist
throw OfdRequestException("Does not exist");
}
return Check();
}
if ((products.size() + amounts.size() + prices.size())/products.size() != 3) {
std::cerr << "An error has occured during the parsing of html. Please, contact the developer." << std::endl;
std::exit(-1);
}
Check c;
for (int i = 0; i < products.size(); i ++) {
Goods goods(to_utf8(products[i]), std::stod(prices[i]), std::stod(amounts[i]));
c.add_goods(goods);
}
return c;
}

View File

@@ -3,6 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "../check/check.h"
std::string to_utf8(std::wstring wide_string); std::string to_utf8(std::wstring wide_string);
std::wstring from_utf8(std::string string); std::wstring from_utf8(std::string string);
@@ -12,4 +13,10 @@ std::string get_path_relative_to_home(std::string path);
template <typename T> template <typename T>
bool vector_contains_element(const std::vector<T> &vector, const T &to_find); bool vector_contains_element(const std::vector<T> &vector, const T &to_find);
std::vector<std::string> split(std::string, std::string);
Check parseOfdRuAnswer(std::string);
std::wstring trim_html_response(std::wstring& check);
#endif // UTILS_H #endif // UTILS_H