diff --git a/.clang-format b/.clang-format index 2c120cc..b8140ac 100644 --- a/.clang-format +++ b/.clang-format @@ -1,43 +1,58 @@ +--- Language: Cpp # BasedOnStyle: LLVM -AccessModifierOffset: -2 +AccessModifierOffset: -4 AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None AlignEscapedNewlines: Right -AlignOperands: true +AlignOperands: Align AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability BinPackArguments: true BinPackParameters: true -BraceWrapping: +BraceWrapping: + AfterCaseLabel: false AfterClass: true - AfterControlStatement: false + AfterControlStatement: Never AfterEnum: false - AfterFunction: false - AfterNamespace: false + AfterFunction: true + AfterNamespace: true AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None -BreakBeforeBraces: Linux +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon @@ -50,35 +65,56 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true +DeriveLineEnding: true DerivePointerAlignment: false DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true -ForEachMacros: +ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE IncludeBlocks: Preserve -IncludeCategories: +IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 + SortPriority: 0 + CaseSensitive: false - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 + SortPriority: 0 + CaseSensitive: false - Regex: '.*' Priority: 1 + SortPriority: 0 + CaseSensitive: false IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false IndentWidth: 4 IndentWrappedFunctionNames: false +InsertTrailingCommas: None JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 @@ -86,24 +122,57 @@ PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer ReflowComments: true -SortIncludes: true +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before SortUsingDeclarations: true SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: false +SpacesInAngles: Never +SpacesInConditionalStatement: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 SpacesInParentheses: false SpacesInSquareBrackets: false -Standard: Auto +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION TabWidth: 8 +UseCRLF: false UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... diff --git a/.gitignore b/.gitignore index e447088..6e490ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build .vscode/ipch/* .kdev4 +.cache \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 672e543..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +0,0 @@ -[submodule "subprojects/nlohmann_json"] - path = subprojects/nlohmann_json - url = https://github.com/nlohmann/json.git -[submodule "subprojects/singleapplication"] - path = subprojects/singleapplication/singleapplication.git - url = https://github.com/itay-grudev/SingleApplication.git -[submodule "subprojects/csv-parser"] - path = subprojects/csv-parser - url = https://github.com/vincentlaucsb/csv-parser.git diff --git a/.vscode/launch.json b/.vscode/launch.json index 17dfcc6..fb0e8c6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,7 +21,8 @@ "text": "-enable-pretty-printing", "ignoreFailures": true } - ] + ], + "visualizerFile": "/home/brodbemn/.config/Code - OSS/User/workspaceStorage/d64ec049841ecb3d43e402bb3c167cb5/tonka3000.qtvsctools/qt.natvis.xml" } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 0b81f37..41f34ac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,9 +65,47 @@ "condition_variable": "cpp", "mutex": "cpp", "hash_map": "cpp", - "future": "cpp" + "future": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "forward_list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_set": "cpp", + "iterator": "cpp", + "memory_resource": "cpp", + "random": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "__verbose_abort": "cpp", + "format": "cpp", + "ios": "cpp", + "locale": "cpp" }, "C_Cpp.clang_format_path": "/usr/bin/clang-format", "cmake.configureOnOpen": true, - "C_Cpp.configurationWarnings": "Disabled" + "C_Cpp.configurationWarnings": "Disabled", + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/node_modules/*/**": true, + "**/.hg/store/**": true, + ".flatpak/**": true, + "_build/**": true + } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4489b2f..86b072a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,14 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.30) -project(kima2 VERSION 1.5.3) +project(kima2 VERSION 1.9.2) set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake") -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -#include(InstallRequiredSystemLibraries) +# For SingleApplication and nlohmann_json +include(FetchContent) if(MSVC) add_compile_options(/W4 /WX) @@ -17,6 +18,7 @@ else() endif() configure_file(config.h.in ${PROJECT_BINARY_DIR}/config.h) +configure_file(de.rustysoft.kima2.metainfo.xml.in ${PROJECT_BINARY_DIR}/de.rustysoft.kima2.metainfo.xml) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -28,7 +30,6 @@ if(KIMA2_USE_EXTERNAL_JSON) find_package(nlohmann_json REQUIRED) endif() -add_subdirectory(subprojects) add_subdirectory(src) #if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE MATCHES Debug) @@ -79,6 +80,8 @@ else(WIN32 AND NOT UNIX) DESTINATION share/${PROJECT_NAME}) install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg" DESTINATION share/icons/hicolor/scalable/apps) + install(FILES de.rustysoft.kima2.metainfo.xml + DESTINATION share/metainfo) endif (WIN32 AND NOT UNIX) if( MINGW ) @@ -87,19 +90,19 @@ if( MINGW ) set( CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${MINGW_PATH}/libstdc++-6.dll ${MINGW_PATH}/libgcc_s_seh-1.dll - ${MINGW_PATH}/Qt5Core.dll - ${MINGW_PATH}/Qt5Gui.dll - ${MINGW_PATH}/Qt5Widgets.dll - ${MINGW_PATH}/Qt5PrintSupport.dll - ${MINGW_PATH}/Qt5Network.dll + ${MINGW_PATH}/Qt6Core.dll + ${MINGW_PATH}/Qt6Gui.dll + ${MINGW_PATH}/Qt6Widgets.dll + ${MINGW_PATH}/Qt6PrintSupport.dll + ${MINGW_PATH}/Qt6Network.dll ${MINGW_PATH}/libwinpthread-1.dll ${MINGW_PATH}/libsqlite3-0.dll ${MINGW_PATH}/libusb-1.0.dll - ${MINGW_PATH}/libxlnt.dll - ${MINGW_PATH}/libicuuc65.dll - ${MINGW_PATH}/libicuin65.dll - ${MINGW_PATH}/libicudt65.dll + ${MINGW_PATH}/libicuuc76.dll + ${MINGW_PATH}/libicuin76.dll + ${MINGW_PATH}/libicudt76.dll ${MINGW_PATH}/libpcre2-16-0.dll + ${MINGW_PATH}/libpcre2-8-0.dll ${MINGW_PATH}/zlib1.dll ${MINGW_PATH}/libharfbuzz-0.dll ${MINGW_PATH}/libpng16-16.dll @@ -108,23 +111,26 @@ if( MINGW ) ${MINGW_PATH}/libgraphite2.dll ${MINGW_PATH}/libbz2-1.dll ${MINGW_PATH}/libintl-8.dll - ${MINGW_PATH}/libpcre-1.dll ${MINGW_PATH}/libdouble-conversion.dll ${MINGW_PATH}/libzstd.dll + ${MINGW_PATH}/libmd4c.dll + ${MINGW_PATH}/libbrotlicommon.dll + ${MINGW_PATH}/libbrotlidec.dll + #${MINGW_PATH}/libfmt.dll + ${MINGW_PATH}/libb2-1.dll ${MINGW_PATH}/libiconv-2.dll) - install(FILES ${MINGW_PATH}/../share/qt5/plugins/platforms/qwindows.dll - ${MINGW_PATH}/../share/qt5/plugins/platforms/qminimal.dll + install(FILES ${MINGW_PATH}/../share/qt6/plugins/platforms/qwindows.dll + ${MINGW_PATH}/../share/qt6/plugins/platforms/qminimal.dll DESTINATION bin/platforms) - install(FILES ${MINGW_PATH}/../share/qt5/plugins/printsupport/windowsprintersupport.dll - DESTINATION bin/printsupport) - install(FILES ${MINGW_PATH}/../share/qt5/translations/qtbase_de.qm - ${MINGW_PATH}/../share/qt5/translations/qt_de.qm - ${MINGW_PATH}/../share/qt5/translations/qt_help_de.qm - ${MINGW_PATH}/../share/qt5/translations/qtmultimedia_de.qm - ${MINGW_PATH}/../share/qt5/translations/qtquickcontrols_de.qm - ${MINGW_PATH}/../share/qt5/translations/qtscript_de.qm - ${MINGW_PATH}/../share/qt5/translations/qtxmlpatterns_de.qm - DESTINATION bin/translations) + #install(FILES ${MINGW_PATH}/../share/qt6/plugins/printsupport/windowsprintersupport.dll + # DESTINATION bin/printsupport) + install(FILES ${MINGW_PATH}/../share/qt6/translations/qtbase_de.qm + ${MINGW_PATH}/../share/qt6/translations/qt_de.qm + ${MINGW_PATH}/../share/qt6/translations/qt_help_de.qm + ${MINGW_PATH}/../share/qt6/translations/qtmultimedia_de.qm + DESTINATION bin/share/qt6/translations) + install(FILES ${MINGW_PATH}/../share/qt6/plugins/styles/qmodernwindowsstyle.dll + DESTINATION bin/styles) endif( MINGW ) include(InstallRequiredSystemLibraries) diff --git a/LICENSE b/LICENSE index c8865df..0b127da 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright © 2018-2021 Martin Brodbeck +Copyright © 2018-2025 Martin Brodbeck Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, diff --git a/README.md b/README.md index 7e2bc98..3c0dd87 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,16 @@ Verkaufsdaten nach dem Verkaufsende auszutauschen. Ebenso können über einen ESC/POS-Drucker Quittungen ausgestellt werden. ## Installation -Auf [rustysoft.de](https://www.rustysoft.de/?01_kima2) werden verschiedene Installationspakete (Arch Linux, -Ubuntu, Windows) angeboten. Bitte die Hinweise dort beachten. +Auf [rustysoft.de](https://www.rustysoft.de/software/kima2/) werden die Installationsmöglichkeiten (Flatpak, Windows-Installer) erläutert. Bitte die Hinweise dort beachten. -### Selbst compilieren +## Selbst compilieren KIMA2 benötigt folgende Libraries: -* Qt5 -* boost >= 1.62 +* Qt 6 +* boost >= 1.80 * libusb-1.0 -* xlnt >= 1.3.0 * nlohmann-json (als 3rdparty submodule vorhanden) -Da Features aus C++17 verwendet werden sowie std::filesystem, sollte als Compiler mindestens -GCC 8 verwendet werden. +Da Features aus C++20 sowie von neueren Compilern verwendet werden, sollte als Compiler mindestens GCC 14 verwendet werden. Die Installationsschritte unter Linux sind wie folgt: ``` @@ -37,4 +34,4 @@ sudo make install ``` Unter Windows muss vorab MinGW eingerichtet werden (z. B. MSYS2). Nach der Compilierung kann mit -`cpack -G NSIS` ein Installationspaket erstellt werden. \ No newline at end of file +`cpack -G NSIS` ein Installationspaket erstellt werden. diff --git a/de.rustysoft.kima2.metainfo.xml.in b/de.rustysoft.kima2.metainfo.xml.in new file mode 100644 index 0000000..9f228f7 --- /dev/null +++ b/de.rustysoft.kima2.metainfo.xml.in @@ -0,0 +1,27 @@ + + + de.rustysoft.kima2 + + KIMA2 + A small cash point program for children’s stuff markets + + MIT + GPL-3.0-or-later + + + + + + +

+ A small cash point program for children's stuff markets. German language only. +

+
+ + de.rustysoft.kima2.desktop + + + https://rustysoft.de/images/software/kima2/screenshot.png + + +
diff --git a/manual/Benutzerhandbuch.odt b/manual/Benutzerhandbuch.odt index eefaccc..c2defc2 100644 Binary files a/manual/Benutzerhandbuch.odt and b/manual/Benutzerhandbuch.odt differ diff --git a/manual/Benutzerhandbuch.pdf b/manual/Benutzerhandbuch.pdf index df82fb4..793f996 100644 Binary files a/manual/Benutzerhandbuch.pdf and b/manual/Benutzerhandbuch.pdf differ diff --git a/meson.build b/meson.build deleted file mode 100644 index 8fa4367..0000000 --- a/meson.build +++ /dev/null @@ -1,33 +0,0 @@ -project('kima2', 'cpp', default_options : ['cpp_std=c++17'], version : '1.5.3') - -conf_data = configuration_data() -conf_data.set('PROJECT_VERSION', '"' + meson.project_version() + '"') -configure_file(output : 'config.h', - configuration : conf_data) -configuration_inc = include_directories('.') - -#csv = cmake.subproject('csv-parser') -#csv_lib = csv.dependency('csv') - -nlohmann_lib = dependency('nlohmann_json', version : '>=3.5.0', required : false) - -if not nlohmann_lib.found() - nlohmann_inc = include_directories('subprojects/nlohmann_json/single_include') - nlohmann_lib = declare_dependency(include_directories : nlohmann_inc) -endif - -csv_inc = include_directories('subprojects/csv-parser/single_include') -csv_dep = declare_dependency(include_directories : csv_inc) - -singleapp_proj = subproject('singleapplication') -singleapp_lib = singleapp_proj.get_variable('singleapp_lib') -singleapp_dep = singleapp_proj.get_variable('singleapp_dep') - -subdir('src') - -if build_machine.system() == 'linux' - install_data('misc/kima2.svg', install_dir : get_option('datadir') / 'icons/hicolor/scalable/apps') - install_data('misc/kima2.desktop', install_dir : get_option('datadir') / 'applications') - install_data('manual/Benutzerhandbuch.pdf', install_dir : get_option('datadir') / 'kima2') -endif - diff --git a/misc/PKGBUILD b/misc/PKGBUILD index f679f03..a50410c 100644 --- a/misc/PKGBUILD +++ b/misc/PKGBUILD @@ -1,21 +1,27 @@ # Maintainer: Martin Brodbeck pkgname=kima2 -pkgver=1.5.0 +pkgver=1.7.1 pkgrel=1 pkgdesc="A small cash point program for children's things markets (German only)" arch=('i686' 'x86_64') -url="http://www.rustysoft.de/?01_kima2" +url="http://www.rustysoft.de/software/kima2" license=('custom') -depends=('glibc' 'libusb' 'qt5-base' 'sqlite3' 'xlnt') +depends=('glibc' 'libusb' 'qt6-base' 'sqlite3') makedepends=('boost>=1.62') -source=($pkgname-$pkgver.tar.gz) -md5sums=('c0e6a64b5037675edce4ba8bc4639bd3') +source=(git+https://git.rustysoft.de/martin/kima2) +sha256sums=('SKIP') build() { - if [ ! -d $pkgname/build ]; then - mkdir $pkgname/build + cd $pkgname + + git checkout v$pkgver + git submodule init + git submodule update + + if [ -d build ]; then + rm -rf build fi - cd $pkgname/build + mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DKIMA2_USE_EXTERNAL_JSON=OFF .. make diff --git a/misc/kima2.desktop b/misc/kima2.desktop index 004ab5f..becabdf 100644 --- a/misc/kima2.desktop +++ b/misc/kima2.desktop @@ -3,8 +3,8 @@ Type=Application Name=KIMA2 GenericName=Cash Point Program GenericName[de]=Kassenprogramm -Comment=A small cash point program -Comment[de]=Ein kleines Kassenprogramm +Comment=A small cash point program for children's stuff markets +Comment[de]=Ein kleines Kassenprogramm für Kindersachenmärkte Exec=kima2 Icon=kima2 Categories=Office; diff --git a/misc/kima2.spec b/misc/kima2.spec index 0c3feff..2c586a8 100644 --- a/misc/kima2.spec +++ b/misc/kima2.spec @@ -13,7 +13,6 @@ BuildRequires: boost-date-time BuildRequires: sqlite-devel BuildRequires: libusb-devel BuildRequires: qt5-qtdeclarative-devel -#BuildRequires: pkgconfig(xlnt) #BuildRequires: pkgconfig(pthreads) %description diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0e4b100..681cf5c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,21 +1,14 @@ set(Boost_USE_STATIC_LIBS ON) -find_package(Boost 1.62 COMPONENTS date_time REQUIRED) +find_package(Boost 1.78 REQUIRED) find_package(SQLite3 REQUIRED) -# Because csv-parser needs threads: -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) +FetchContent_MakeAvailable(json) +add_library(core STATIC) -if (MINGW) - find_package(XLNT REQUIRED STATIC) -else (MINGW) - find_package(PkgConfig REQUIRED) - pkg_check_modules(XLNT REQUIRED xlnt>=1.3) -endif (MINGW) - -set(CORE_SOURCES +target_sources(core PRIVATE database.cpp entity.cpp entityint.cpp @@ -24,20 +17,16 @@ set(CORE_SOURCES article.cpp sale.cpp marketplace.cpp - excelreader.cpp csvreader.cpp jsonutil.cpp utils.cpp ) - -add_library(core STATIC ${CORE_SOURCES}) -target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/csv-parser/single_include) if (WIN32) - target_link_libraries(core PRIVATE Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARY} Threads::Threads) + target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json) target_link_libraries(core PRIVATE bcrypt) else() - target_link_libraries(core PRIVATE Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARIES} Threads::Threads) + target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json) endif() target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) diff --git a/src/core/article.cpp b/src/core/article.cpp index e17589b..6137549 100644 --- a/src/core/article.cpp +++ b/src/core/article.cpp @@ -5,34 +5,34 @@ #include #include -Article::Article(int price) : price_(price) {} +Article::Article(int price) : m_price(price) {} -void Article::setArticleNo(int articleNo) { articleNo_ = articleNo; } +void Article::setArticleNo(int articleNo) { m_articleNo = articleNo; } -void Article::setPrice(int price) { price_ = price; } +void Article::setPrice(int price) { m_price = price; } -void Article::setDescription(const std::string& description) { description_ = description; } +void Article::setDescription(const std::string &description) { m_description = description; } -void Article::setSale(Sale* salePtr) { salePtr_ = salePtr; } +void Article::setSale(Sale *salePtr) { m_salePtr = salePtr; } -void Article::setSeller(Seller* sellerPtr) { sellerPtr_ = sellerPtr; } +void Article::setSeller(Seller *sellerPtr) { m_sellerPtr = sellerPtr; } -bool Article::isSold() { return salePtr_ ? true : false; } +bool Article::isSold() { return m_salePtr ? true : false; } -std::string Article::getDescription() { return description_; } +std::string Article::getDescription() { return m_description; } -Seller* Article::getSeller() { return sellerPtr_; } -Sale* Article::getSale() { return salePtr_; } +Seller *Article::getSeller() { return m_sellerPtr; } +Sale *Article::getSale() { return m_salePtr; } -int Article::getPrice() const { return price_; } +int Article::getPrice() const { return m_price; } -std::string Article::getPriceAsString() const { return formatCentAsEuroString(price_); } +std::string Article::getPriceAsString() const { return formatCentAsEuroString(m_price); } -int Article::getArticleNo() const { return articleNo_; } +int Article::getArticleNo() const { return m_articleNo; } std::string Article::getCompleteArticleNo() const { std::stringstream artNoStream; - artNoStream << sourceNo_ << "K" << std::setfill('0') << std::setw(5) << articleNo_; + artNoStream << m_sourceNo << "K" << std::setfill('0') << std::setw(5) << m_articleNo; return artNoStream.str(); } diff --git a/src/core/article.h b/src/core/article.h index ab6be52..c9be086 100644 --- a/src/core/article.h +++ b/src/core/article.h @@ -11,34 +11,33 @@ class Sale; class Article : public EntityUuid { - public: +public: Article() = default; Article(int price); - Article(const Article&) = delete; + Article(const Article &) = delete; virtual ~Article() = default; void setArticleNo(int articleNo); void setPrice(int price); - void setDescription(const std::string& description); + void setDescription(const std::string &description); bool isSold(); - void setSale(Sale* salePtr); - void setSeller(Seller* sellerPtr); + void setSale(Sale *salePtr); + void setSeller(Seller *sellerPtr); int getArticleNo() const; std::string getCompleteArticleNo() const; std::string getDescription(); - Seller* getSeller(); - Sale* getSale(); + Seller *getSeller(); + Sale *getSale(); int getPrice() const; std::string getPriceAsString() const; - private: - Seller* sellerPtr_{}; - Sale* salePtr_{}; - int articleNo_{}; - int price_{}; - std::string description_{}; +private: + Seller *m_sellerPtr{}; + Sale *m_salePtr{}; + int m_articleNo{}; + int m_price{}; + std::string m_description{}; }; #endif - diff --git a/src/core/csvreader.cpp b/src/core/csvreader.cpp index 6c384f7..6c2cdf6 100644 --- a/src/core/csvreader.cpp +++ b/src/core/csvreader.cpp @@ -3,7 +3,8 @@ #include -#include +// #include +#include #ifdef DELETE #undef DELETE @@ -11,54 +12,68 @@ namespace fs = std::filesystem; -std::size_t CsvReader::readSellersFromFile(const fs::path& filePath, Marketplace* market) +std::size_t CsvReader::readSellersFromFile(const fs::path &filePath, Marketplace *market) { - csv::CSVFormat format; - format.delimiter(';'); #if defined(_WIN64) || defined(_WIN32) // Windows: Somhow this is necessary in order to open file names with umlauts auto wide = filePath.wstring(); std::string fileName(wide.begin(), wide.end()); - csv::CSVReader csvReader(fileName, format); + std::ifstream infile(fileName); #else - csv::CSVReader csvReader(filePath.string(), format); + // csv::CSVReader csvReader(filePath.string(), format); + std::ifstream infile(filePath.string()); #endif - for (auto& seller : market->getSellers()) { + for (auto &seller : market->getSellers()) { seller->setState(Seller::State::DELETE); } market->storeToDb(true); - - int rowCount{}; - for (csv::CSVRow &row : csvReader) { - if (!row[0].is_int()) { - ++rowCount; - continue; - } - if (row[2].get().empty() && row[3].get().empty()) { - ++rowCount; - continue; - } + std::string line; + + while (getline(infile, line)) { + std::vector strs; + boost::split(strs, line, boost::is_any_of(";")); auto seller = std::make_unique(); - seller->setSellerNo(row[0].get()); - if (row[1].is_int()) { - seller->setNumArticlesOffered(row[1].get()); - } else { - seller->setNumArticlesOffered(0); + + try { + int sellerNo = std::stoi(strs[0]); + seller->setSellerNo(sellerNo); + } catch (std::invalid_argument const &ex) { + continue; } - std::string firstName = row[2].get(); - seller->setFirstName(trim(firstName)); - std::string lastName = row[3].get(); - seller->setLastName(trim(lastName)); + + if (isNumber(strs[1])) + seller->setNumArticlesOffered(std::stoi(strs[1])); + else + seller->setNumArticlesOffered(0); + + // If both, first name and last name, are empty, use N. N. + // Else, use the real values. + if (strs[2].empty() && strs[2].empty()) { + seller->setFirstName("N."); + seller->setLastName("N."); + } else { + std::string firstName = strs[2]; + seller->setFirstName(trim(firstName)); + std::string lastName = strs[3]; + seller->setLastName(trim(lastName)); + } + market->getSellers().push_back(std::move(seller)); - rowCount++; } + // Add one additional seller "RESERVE RESERVE" + auto seller = std::make_unique(); + seller->setSellerNo(market->getNextSellerNo()); + seller->setFirstName("RESERVE"); + seller->setLastName("RESERVE"); + market->getSellers().push_back(std::move(seller)); + // If there was no special seller "Sonderkonto" in import data, then create one auto specialSeller = market->findSellerWithSellerNo(0); if (!specialSeller) { diff --git a/src/core/csvreader.h b/src/core/csvreader.h index 1f9d924..ff1901a 100644 --- a/src/core/csvreader.h +++ b/src/core/csvreader.h @@ -11,9 +11,9 @@ class CsvReader { - public: - static std::size_t readSellersFromFile(const std::filesystem::path& filePath, - Marketplace* market); +public: + static std::size_t readSellersFromFile(const std::filesystem::path &filePath, + Marketplace *market); }; #endif \ No newline at end of file diff --git a/src/core/database.cpp b/src/core/database.cpp index 9d0df7d..d6b7384 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -1,13 +1,13 @@ #include "database.h" +#include #include +#include #include #include #include -#include "boost/date_time/posix_time/posix_time.hpp" - -Database::Database(const std::string& dbname) +Database::Database(const std::string &dbname) { dbname_ = dbname; init(); @@ -28,7 +28,7 @@ Database::Database() if (!fs::exists(dbpath)) { try { fs::create_directories(dbpath); - } catch (fs::filesystem_error& err) { + } catch (fs::filesystem_error &err) { throw err; } } @@ -45,8 +45,11 @@ void Database::newDb() fs::path sourcePath = dbname_; fs::path destPath = sourcePath.parent_path() / sourcePath.stem(); - destPath += std::string("_") += - boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) += ".db"; + + auto chronoTime = std::chrono::system_clock::now(); + std::string timeString = std::format("{0:%FT%H-%M-%S}", chronoTime); + + destPath += std::string("_") += timeString += ".db"; fs::copy_file(sourcePath, destPath, fs::copy_options::overwrite_existing); @@ -57,13 +60,13 @@ void Database::newDb() Database::~Database() { sqlite3_close(db_); } -void Database::exec(const std::string& sql) +void Database::exec(const std::string &sql) { - char* errMsg; + char *errMsg; const int errCode = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errMsg); if (errCode) { std::string errMsgString(errMsg); // Make a C++ string of the errMsg, so that we can call - // sqlite3_free() before throwing the exception + // sqlite3_free() before throwing the exception sqlite3_free(errMsg); throw std::runtime_error("Error in SQL execution: " + errMsgString); } @@ -120,7 +123,7 @@ void Database::createNew() sqlStrings.push_back(sqlInitialEntries); beginTransaction(); - for (const auto& sql : sqlStrings) { + for (const auto &sql : sqlStrings) { exec(sql); } endTransaction(); @@ -173,7 +176,7 @@ void Database::init() int Database::getVersion() { int retCode{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; // Check if there's already a kima2 table available. // If not, return version == 0. @@ -220,15 +223,15 @@ void Database::beginTransaction() { exec("BEGIN TRANSACTION"); } void Database::endTransaction() { exec("END TRANSACTION"); } -unsigned int Database::storeSellers(std::vector>& sellers, bool onlyDelete) +unsigned int Database::storeSellers(std::vector> &sellers, bool onlyDelete) { int retCode{}; int count{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; beginTransaction(); - for (auto& seller : sellers) { + for (auto &seller : sellers) { if (seller->getState() == Seller::State::NEW && !onlyDelete) { retCode = sqlite3_prepare_v2( db_, @@ -323,12 +326,12 @@ unsigned int Database::storeSellers(std::vector>& seller // Everything went fine, so we can now update our objects sellers.erase(std::remove_if(sellers.begin(), sellers.end(), - [](const std::unique_ptr& seller) { + [](const std::unique_ptr &seller) { return (seller->getState() == Seller::State::DELETE); }), sellers.end()); - for (auto& seller : sellers) { + for (auto &seller : sellers) { seller->cleanupArticles(); seller->setState(Seller::State::OK); } @@ -336,13 +339,13 @@ unsigned int Database::storeSellers(std::vector>& seller return count; } -unsigned int Database::storeArticles(std::vector articles) +unsigned int Database::storeArticles(std::vector
articles) { int retCode{}; int count{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; - for (auto& article : articles) { + for (auto &article : articles) { if (article->getState() == Article::State::NEW) { retCode = sqlite3_prepare_v2( db_, @@ -441,18 +444,18 @@ unsigned int Database::storeArticles(std::vector articles) return count; } -unsigned int Database::storeSales(std::vector>& sales) +unsigned int Database::storeSales(std::vector> &sales) { int retCode{}; int count{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; if (sales.size() == 0) return 0; beginTransaction(); - for (auto& sale : sales) { + for (auto &sale : sales) { if (sale->getState() == Sale::State::NEW) { retCode = sqlite3_prepare_v2(db_, "INSERT INTO sales" @@ -482,7 +485,7 @@ unsigned int Database::storeSales(std::vector>& sales) ++count; sqlite3_finalize(stmt); - for (const auto& article : sale->getArticles()) { + for (const auto &article : sale->getArticles()) { retCode = sqlite3_prepare_v2(db_, "INSERT INTO sales_items" " (sale_id, article_id)" @@ -535,21 +538,21 @@ unsigned int Database::storeSales(std::vector>& sales) // Everything went fine, so we can now update our objects sales.erase( std::remove_if(sales.begin(), sales.end(), - [](const auto& sale) { return (sale->getState() == Sale::State::DELETE); }), + [](const auto &sale) { return (sale->getState() == Sale::State::DELETE); }), sales.end()); - for (auto& sale : sales) { + for (auto &sale : sales) { sale->setState(Sale::State::OK); } return count; } -unsigned int Database::loadSellers(std::vector>& sellers) +unsigned int Database::loadSellers(std::vector> &sellers) { int retCode{}; int count{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; retCode = sqlite3_prepare_v2(db_, "SELECT seller_no, first_name, last_name, " @@ -566,8 +569,8 @@ unsigned int Database::loadSellers(std::vector>& sellers ++count; auto seller = std::make_unique(); seller->setSellerNo(sqlite3_column_int(stmt, 0)); - seller->setFirstName(reinterpret_cast(sqlite3_column_text(stmt, 1))); - seller->setLastName(reinterpret_cast(sqlite3_column_text(stmt, 2))); + seller->setFirstName(reinterpret_cast(sqlite3_column_text(stmt, 1))); + seller->setLastName(reinterpret_cast(sqlite3_column_text(stmt, 2))); seller->setNumArticlesOffered(sqlite3_column_int(stmt, 3)); seller->setState(Seller::State::OK); sellers.push_back(std::move(seller)); @@ -577,7 +580,7 @@ unsigned int Database::loadSellers(std::vector>& sellers sqlite3_finalize(stmt); - for (auto& seller : sellers) { + for (auto &seller : sellers) { retCode = sqlite3_prepare_v2(db_, "SELECT id, source_no, article_no, description, price" " FROM articles" @@ -594,11 +597,12 @@ unsigned int Database::loadSellers(std::vector>& sellers while (retCode != SQLITE_DONE) { ++count; auto article = std::make_unique
(); - article->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); + article->setUuidFromString( + reinterpret_cast(sqlite3_column_text(stmt, 0))); article->setSeller(seller.get()); article->setSourceNo(sqlite3_column_int(stmt, 1)); article->setArticleNo(sqlite3_column_int(stmt, 2)); - article->setDescription(reinterpret_cast(sqlite3_column_text(stmt, 3))); + article->setDescription(reinterpret_cast(sqlite3_column_text(stmt, 3))); article->setPrice(sqlite3_column_int(stmt, 4)); article->setState(Article::State::OK); @@ -613,12 +617,12 @@ unsigned int Database::loadSellers(std::vector>& sellers return count; } -unsigned int Database::loadSales(std::vector>& sales, - std::vector>& sellers) +unsigned int Database::loadSales(std::vector> &sales, + std::vector> &sellers) { int retCode{}; int count{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; retCode = sqlite3_prepare_v2(db_, "SELECT id, source_no, sold_at" @@ -631,13 +635,13 @@ unsigned int Database::loadSales(std::vector>& sales, sales.clear(); - std::map saleMap; + std::map saleMap; while (retCode != SQLITE_DONE) { ++count; auto sale = std::make_unique(); - sale->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); + sale->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); sale->setSourceNo(sqlite3_column_int(stmt, 1)); - sale->setTimestamp(reinterpret_cast(sqlite3_column_text(stmt, 2))); + sale->setTimestamp(reinterpret_cast(sqlite3_column_text(stmt, 2))); sale->setState(Sale::State::OK); saleMap.insert(std::make_pair(sale->getUuidAsString(), sale.get())); sales.push_back(std::move(sale)); @@ -647,8 +651,8 @@ unsigned int Database::loadSales(std::vector>& sales, sqlite3_finalize(stmt); - std::map artMap; - for (const auto& seller : sellers) { + std::map artMap; + for (const auto &seller : sellers) { for (const auto article : seller->getArticles(false)) { artMap.insert(std::make_pair(article->getUuidAsString(), article)); } @@ -664,8 +668,8 @@ unsigned int Database::loadSales(std::vector>& sales, retCode = sqlite3_step(stmt); while (retCode != SQLITE_DONE) { - saleMap[reinterpret_cast(sqlite3_column_text(stmt, 0))]->addArticle( - artMap[reinterpret_cast(sqlite3_column_text(stmt, 1))]); + saleMap[reinterpret_cast(sqlite3_column_text(stmt, 0))]->addArticle( + artMap[reinterpret_cast(sqlite3_column_text(stmt, 1))]); retCode = sqlite3_step(stmt); } @@ -678,7 +682,7 @@ unsigned int Database::loadSales(std::vector>& sales, void Database::updateCashPointNo(int oldCashPointNo, int newCashPointNo) { int retCode{}; - sqlite3_stmt* stmt; + sqlite3_stmt *stmt; // Check if the new no ist already in use retCode = sqlite3_prepare_v2(db_, "SELECT COUNT() FROM articles WHERE source_no = :source_no", diff --git a/src/core/database.h b/src/core/database.h index 2cf1b63..af39f23 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -10,33 +10,33 @@ class Database { - public: - enum class InitResult {OK, OUTDATED_REPLACED}; - explicit Database(const std::string& dbname); +public: + enum class InitResult { OK, OUTDATED_REPLACED }; + explicit Database(const std::string &dbname); Database(); ~Database(); - Database(const Database&) = delete; - Database& operator=(const Database&) = delete; - void exec(const std::string& sql); - unsigned int storeSellers(std::vector>& sellers, + Database(const Database &) = delete; + Database &operator=(const Database &) = delete; + void exec(const std::string &sql); + unsigned int storeSellers(std::vector> &sellers, bool onlyDelete = false); - unsigned int loadSellers(std::vector>& sellers); - unsigned int storeSales(std::vector>& sales); - unsigned int loadSales(std::vector>& sales, - std::vector>& sellers); + unsigned int loadSellers(std::vector> &sellers); + unsigned int storeSales(std::vector> &sales); + unsigned int loadSales(std::vector> &sales, + std::vector> &sellers); void updateCashPointNo(int oldCashPointNo, int newCashPointNo); void newDb(); - InitResult getInitResult() {return initResult_;} + InitResult getInitResult() { return initResult_; } - private: - sqlite3* db_{nullptr}; +private: + sqlite3 *db_{nullptr}; std::string dbname_; void init(); void beginTransaction(); void endTransaction(); void createNew(); int getVersion(); - unsigned int storeArticles(std::vector articles); + unsigned int storeArticles(std::vector
articles); void updateDbToVer2(); void updateDbToVer3(); InitResult initResult_{InitResult::OK}; diff --git a/src/core/entity.cpp b/src/core/entity.cpp index 4a8cfb4..9f07489 100644 --- a/src/core/entity.cpp +++ b/src/core/entity.cpp @@ -1,6 +1,3 @@ #include "entity.h" -Entity::State Entity::getState() const -{ - return state_; -} +Entity::State Entity::getState() const { return m_state; } diff --git a/src/core/entity.h b/src/core/entity.h index a0eb97c..3b049ba 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -3,14 +3,14 @@ class Entity { - public: +public: enum class State { NEW, UPDATE, DELETE, OK }; virtual ~Entity() = default; - void setState(State state) { state_ = state; } + void setState(State state) { m_state = state; } virtual State getState() const; - private: - State state_{State::NEW}; +private: + State m_state{State::NEW}; }; #endif // ENTITY_H diff --git a/src/core/entityint.cpp b/src/core/entityint.cpp index 28e210e..2d0f6af 100644 --- a/src/core/entityint.cpp +++ b/src/core/entityint.cpp @@ -1,5 +1,5 @@ #include "entityint.h" -EntityInt::EntityInt(int id) { id_ = id; } +EntityInt::EntityInt(int id) { m_id = id; } -void EntityInt::setId(int id) { id_ = id; } +void EntityInt::setId(int id) { m_id = id; } diff --git a/src/core/entityint.h b/src/core/entityint.h index 06a332b..82fac50 100644 --- a/src/core/entityint.h +++ b/src/core/entityint.h @@ -5,15 +5,15 @@ class EntityInt : public Entity { - public: +public: EntityInt() = default; virtual ~EntityInt() = default; EntityInt(int id); void setId(int id); - int getId() const { return id_; }; + int getId() const { return m_id; }; - protected: - int id_{}; +protected: + int m_id{}; }; #endif // ENTITY_INT_H diff --git a/src/core/entityuuid.cpp b/src/core/entityuuid.cpp index 570c624..eade2ac 100644 --- a/src/core/entityuuid.cpp +++ b/src/core/entityuuid.cpp @@ -8,15 +8,15 @@ void EntityUuid::createUuid() { static boost::uuids::random_generator generator{}; - uuid_ = generator(); + m_uuid = generator(); } -void EntityUuid::setUuidFromString(const std::string& uuidString) +void EntityUuid::setUuidFromString(const std::string &uuidString) { boost::uuids::string_generator generator{}; - uuid_ = generator(uuidString); + m_uuid = generator(uuidString); } -void EntityUuid::setSourceNo(int sourceNo) { sourceNo_ = sourceNo; } +void EntityUuid::setSourceNo(int sourceNo) { m_sourceNo = sourceNo; } -int EntityUuid::getSourceNo() const { return sourceNo_; } +int EntityUuid::getSourceNo() const { return m_sourceNo; } diff --git a/src/core/entityuuid.h b/src/core/entityuuid.h index c9491a6..11b99d5 100644 --- a/src/core/entityuuid.h +++ b/src/core/entityuuid.h @@ -10,23 +10,23 @@ class EntityUuid : public Entity { - public: +public: EntityUuid() = default; virtual ~EntityUuid() = default; void createUuid(); - void setUuidFromString(const std::string& uuidString); + void setUuidFromString(const std::string &uuidString); void setSourceNo(int sourceNo); - const boost::uuids::uuid& getUuid() const { return uuid_; }; - std::string getUuidAsString() const { return boost::uuids::to_string(uuid_); } + const boost::uuids::uuid &getUuid() const { return m_uuid; }; + std::string getUuidAsString() const { return boost::uuids::to_string(m_uuid); } virtual int getSourceNo() const; - protected: - int sourceNo_{}; +protected: + int m_sourceNo{}; - private: - boost::uuids::uuid uuid_{}; +private: + boost::uuids::uuid m_uuid{}; }; #endif // ENTITY_UUID_H diff --git a/src/core/excelreader.cpp b/src/core/excelreader.cpp deleted file mode 100644 index 7c6abe2..0000000 --- a/src/core/excelreader.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "excelreader.h" -#include "utils.h" - -#include -#include - -namespace fs = std::filesystem; - -std::size_t ExcelReader::readSellersFromFile(const fs::path& filePath, Marketplace* market) -{ - xlnt::workbook wb; - std::ifstream mystream(filePath, std::ios::binary); - if (!mystream.is_open()) { - throw std::runtime_error("Could not open Excel file"); - } - wb.load(mystream); - - for (auto& seller : market->getSellers()) { - seller->setState(Seller::State::DELETE); - } - - market->storeToDb(true); - auto ws = wb.sheet_by_index(0); - - for (auto row : ws.rows(true)) { - // Skip the row if the first value is not a number (= seller no) - if (row[0].data_type() != xlnt::cell::type::number) { - continue; - } - - //Skip the row if the seller has neither a first name nor a surname - if (row[2].value().empty() && row[3].value().empty()) { - continue; - } - auto seller = std::make_unique(); - seller->setSellerNo(row[0].value()); - seller->setNumArticlesOffered(row[1].value()); - std::string firstName = row[2].value(); - seller->setFirstName(trim(firstName)); - std::string lastName = row[3].value(); - seller->setLastName(trim(lastName)); - market->getSellers().push_back(std::move(seller)); - } - - // If there was no special seller "Sonderkonto" in import data, then create one - auto specialSeller = market->findSellerWithSellerNo(0); - if (!specialSeller) { - auto seller = std::make_unique(); - seller->setSellerNo(0); - seller->setLastName("Sonderkonto"); - seller->setFirstName("Sonderkonto"); - seller->setNumArticlesOffered(0); - market->getSellers().push_back(std::move(seller)); - } - - market->sortSellers(); - market->storeToDb(); - - return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller -} diff --git a/src/core/excelreader.h b/src/core/excelreader.h deleted file mode 100644 index 62f06c4..0000000 --- a/src/core/excelreader.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef EXCEL_READER_H -#define EXCEL_READER_H - -#include "marketplace.h" -#include "seller.h" - -#include -#include -#include -#include - -class ExcelReader -{ - public: - static std::size_t readSellersFromFile(const std::filesystem::path& filePath, - Marketplace* market); -}; - -#endif \ No newline at end of file diff --git a/src/core/jsonutil.cpp b/src/core/jsonutil.cpp index 9a20603..095a7b0 100644 --- a/src/core/jsonutil.cpp +++ b/src/core/jsonutil.cpp @@ -5,15 +5,14 @@ #include -namespace fs = std::filesystem; using json = nlohmann::json; -void JsonUtil::exportSellers(const std::filesystem::path& filePath, Marketplace* market) +void JsonUtil::exportSellers(const std::filesystem::path &filePath, Marketplace *market) { json root; std::ofstream file(filePath); - for (const auto& seller : market->getSellers()) { + for (const auto &seller : market->getSellers()) { json newEntry; newEntry["seller_no"] = seller->getSellerNo(); newEntry["last_name"] = seller->getLastName(); @@ -25,9 +24,9 @@ void JsonUtil::exportSellers(const std::filesystem::path& filePath, Marketplace* file << root.dump(4) << std::endl; } -std::size_t JsonUtil::importSellers(const std::filesystem::path& filePath, Marketplace* market) +std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marketplace *market) { - for (auto& seller : market->getSellers()) { + for (auto &seller : market->getSellers()) { seller->setState(Seller::State::DELETE); } market->storeToDb(true); @@ -61,7 +60,7 @@ std::size_t JsonUtil::importSellers(const std::filesystem::path& filePath, Marke return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller } -void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* market, +void JsonUtil::exportSales(const std::filesystem::path &filePath, Marketplace *market, int cashPointNo) { json root; @@ -69,7 +68,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m root["source_no"] = cashPointNo; - for (const auto& sale : market->getSales()) { + for (const auto &sale : market->getSales()) { if (sale->getSourceNo() != cashPointNo) continue; @@ -77,7 +76,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m newSale["uuid"] = sale->getUuidAsString(); newSale["timestamp"] = sale->getTimestamp(); - for (const auto& article : sale->getArticles()) { + for (const auto &article : sale->getArticles()) { json newArticle; newArticle["uuid"] = article->getUuidAsString(); newArticle["seller_no"] = article->getSeller()->getSellerNo(); @@ -95,7 +94,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m file << root.dump(4) << std::endl; } -void JsonUtil::importSales(const std::filesystem::path& filePath, Marketplace* market, +void JsonUtil::importSales(const std::filesystem::path &filePath, Marketplace *market, int cashPointNo) { std::ifstream file(filePath); @@ -103,19 +102,21 @@ void JsonUtil::importSales(const std::filesystem::path& filePath, Marketplace* m int source_no = jsonValues["source_no"]; if (source_no == cashPointNo) { - throw std::runtime_error("Die Kassen-Nr. der zu imporierenden Daten wird von dieser Kasse " - "hier bereits verwendet."); + std::string ret = "Die Kassen-Nr. "; + ret += std::to_string(source_no); + ret += " der zu imporierenden Daten wird von dieser Kasse hier bereits verwendet."; + throw std::runtime_error(ret); } market->setSalesToDelete(jsonValues["source_no"]); market->storeToDb(); - for (const auto& valSale : jsonValues["sales"]) { + for (const auto &valSale : jsonValues["sales"]) { auto sale = std::make_unique(); sale->setUuidFromString(valSale["uuid"]); sale->setSourceNo(jsonValues["source_no"]); sale->setTimestamp(valSale["timestamp"]); - for (const auto& valArticle : valSale["articles"]) { + for (const auto &valArticle : valSale["articles"]) { auto article = std::make_unique
(); article->setUuidFromString(valArticle["uuid"]); article->setSourceNo(jsonValues["source_no"]); diff --git a/src/core/jsonutil.h b/src/core/jsonutil.h index 2cc33a2..37190a0 100644 --- a/src/core/jsonutil.h +++ b/src/core/jsonutil.h @@ -8,12 +8,12 @@ class JsonUtil { - public: - static void exportSellers(const std::filesystem::path& filePath, Marketplace* market); - static std::size_t importSellers(const std::filesystem::path& filePath, Marketplace* market); - static void exportSales(const std::filesystem::path& filePath, Marketplace* market, +public: + static void exportSellers(const std::filesystem::path &filePath, Marketplace *market); + static std::size_t importSellers(const std::filesystem::path &filePath, Marketplace *market); + static void exportSales(const std::filesystem::path &filePath, Marketplace *market, int cashPointNo); - static void importSales(const std::filesystem::path& filePath, Marketplace* market, + static void importSales(const std::filesystem::path &filePath, Marketplace *market, int cashPointNo); }; diff --git a/src/core/marketplace.cpp b/src/core/marketplace.cpp index 3fe234a..a68242b 100644 --- a/src/core/marketplace.cpp +++ b/src/core/marketplace.cpp @@ -33,15 +33,15 @@ Database::InitResult Marketplace::loadFromDb() return db.getInitResult(); } -SellersVec& Marketplace::getSellers() { return sellers_; } +SellersVec &Marketplace::getSellers() { return sellers_; } -SalesVec& Marketplace::getSales() { return sales_; } +SalesVec &Marketplace::getSales() { return sales_; } int Marketplace::getNextSellerNo() { auto iter = std::max_element( sellers_.begin(), sellers_.end(), - [](const auto& a, const auto& b) -> bool { return a->getSellerNo() < b->getSellerNo(); }); + [](const auto &a, const auto &b) -> bool { return a->getSellerNo() < b->getSellerNo(); }); if (iter == sellers_.end()) return 1; return (*iter)->getSellerNo() + 1; @@ -53,14 +53,14 @@ int Marketplace::getNextArticleNo() int maxArtNoInBasket{0}; auto iter = std::max_element(sellers_.begin(), sellers_.end(), - [](const auto& a, const auto& b) -> bool { + [](const auto &a, const auto &b) -> bool { return a->getMaxArticleNo() < b->getMaxArticleNo(); }); if (iter != sellers_.end()) maxArtNoInDb = (*iter)->getMaxArticleNo(); auto iter2 = - std::max_element(basket_.begin(), basket_.end(), [](const auto& a, const auto& b) -> bool { + std::max_element(basket_.begin(), basket_.end(), [](const auto &a, const auto &b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); @@ -73,13 +73,13 @@ int Marketplace::getNextArticleNo() int Marketplace::getNumSellersDelete() { int count = std::count_if(sellers_.begin(), sellers_.end(), - [](const auto& a) { return a->getState() == Seller::State::DELETE; }); + [](const auto &a) { return a->getState() == Seller::State::DELETE; }); return count; } int Marketplace::getNumArticlesSold() { - int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) { + int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto &seller) { return a + seller->numArticlesSold(); }); return sum; @@ -87,7 +87,7 @@ int Marketplace::getNumArticlesSold() int Marketplace::getNumArticlesOffered() { - int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) { + int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto &seller) { return a + seller->numArticlesOffered(); }); return sum; @@ -95,10 +95,10 @@ int Marketplace::getNumArticlesOffered() void Marketplace::sortSellers() { std::sort(sellers_.begin(), sellers_.end()); } -Seller* Marketplace::findSellerWithSellerNo(int sellerNo) +Seller *Marketplace::findSellerWithSellerNo(int sellerNo) { auto iter = std::find_if(sellers_.begin(), sellers_.end(), - [sellerNo](const auto& a) { return a->getSellerNo() == sellerNo; }); + [sellerNo](const auto &a) { return a->getSellerNo() == sellerNo; }); if (iter == sellers_.end()) return nullptr; return (*iter).get(); @@ -129,12 +129,12 @@ void Marketplace::finishCurrentSale(std::unique_ptr sale) storeToDb(); } -BasketVec& Marketplace::getBasket() { return basket_; } +BasketVec &Marketplace::getBasket() { return basket_; } int Marketplace::getBasketSumInCent() { int sum = std::accumulate(basket_.begin(), basket_.end(), 0, - [](int a, const auto& b) { return a + b->getPrice(); }); + [](int a, const auto &b) { return a + b->getPrice(); }); return sum; } @@ -148,23 +148,23 @@ std::string Marketplace::getBasketSumAsString() void Marketplace::removeSale(boost::uuids::uuid uuid) { sales_.erase(std::remove_if(sales_.begin(), sales_.end(), - [&uuid](const auto& a) { return a->getUuid() == uuid; }), + [&uuid](const auto &a) { return a->getUuid() == uuid; }), sales_.end()); } void Marketplace::setSalesToDelete(int cashPointNo) { - std::for_each(sales_.begin(), sales_.end(), [cashPointNo](auto& sale) { + std::for_each(sales_.begin(), sales_.end(), [cashPointNo](auto &sale) { if (sale->getSourceNo() == cashPointNo) { sale->setState(Sale::State::DELETE); - for (auto& article : sale->getArticles()) { + for (auto &article : sale->getArticles()) { article->setState(Article::State::DELETE); } } }); } -void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent, int maxFeeInEuro) +void Marketplace::exportReportToCSV(const fs::path &filePath, int feeInPercent, int maxFeeInEuro) { const char delimiter = ';'; std::ofstream file(filePath); @@ -173,7 +173,7 @@ void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent, << "Anz. gemeldet" << delimiter << "Anz. verkauft" << delimiter << "Umsatz" << delimiter << "Auszahlung\n"; - for (const auto& seller : sellers_) { + for (const auto &seller : sellers_) { file << seller->getSellerNo() << delimiter << escapeCsvValue(seller->getLastName(), delimiter) << delimiter << escapeCsvValue(seller->getFirstName(), delimiter) << delimiter @@ -189,7 +189,7 @@ void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent, int Marketplace::getOverallSumInCent() { int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, - [](int a, const auto& b) { return a + b->sumInCents(); }); + [](int a, const auto &b) { return a + b->sumInCents(); }); return sum; } @@ -202,7 +202,7 @@ std::string Marketplace::getOverallSumAsString() int Marketplace::getOverallPaymentInCent(int percent, int maxFee) { int sum = std::accumulate( - sellers_.begin(), sellers_.end(), 0, [percent, maxFee](int a, const auto& b) { + sellers_.begin(), sellers_.end(), 0, [percent, maxFee](int a, const auto &b) { return a + b->sumInCents() - marketFee(b->sumInCents(), percent, maxFee); }); return sum; @@ -240,7 +240,7 @@ std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent) return formatCentAsEuroString(sumInCent - marketFee(sumInCent, percent, maxFeeInCent)); } -std::string escapeCsvValue(const std::string& value, const char delimiter) +std::string escapeCsvValue(const std::string &value, const char delimiter) { std::stringstream output; bool containsDelim{false}; @@ -250,7 +250,7 @@ std::string escapeCsvValue(const std::string& value, const char delimiter) output << '"'; } - for (auto& symbol : value) { + for (auto &symbol : value) { if (symbol == '"') { output << '"' << symbol; } else { diff --git a/src/core/marketplace.h b/src/core/marketplace.h index fe45e02..71a7aa6 100644 --- a/src/core/marketplace.h +++ b/src/core/marketplace.h @@ -20,26 +20,26 @@ using BasketVec = std::vector>; class Marketplace { - public: +public: Marketplace(); void storeToDb(bool onlyDelete = false); Database::InitResult loadFromDb(); - SellersVec& getSellers(); - SalesVec& getSales(); + SellersVec &getSellers(); + SalesVec &getSales(); int getNextSellerNo(); int getNextArticleNo(); int getNumSellersDelete(); int getNumArticlesSold(); int getNumArticlesOffered(); - BasketVec& getBasket(); + BasketVec &getBasket(); int getBasketSumInCent(); std::string getBasketSumAsString(); void sortSellers(); - Seller* findSellerWithSellerNo(int sellerNo); - Seller* findSellerWithUuid(const std::string& uuid); + Seller *findSellerWithSellerNo(int sellerNo); + Seller *findSellerWithUuid(const std::string &uuid); void addArticleToBasket(std::unique_ptr
article); size_t basketSize(); void finishCurrentSale(std::unique_ptr sale); @@ -54,12 +54,12 @@ class Marketplace void clear(); - void exportReportToCSV(const std::filesystem::path& filePath, int feeInPercent, + void exportReportToCSV(const std::filesystem::path &filePath, int feeInPercent, int maxFeeInEuro); friend class ExcelReader; - private: +private: SellersVec sellers_; SalesVec sales_; BasketVec basket_; @@ -68,6 +68,6 @@ class Marketplace double marketFee(int sumInCent, int percent, int maxFeeInCent); std::string marketFeeAsString(int sumInCent, int percent, int maxFeeInCent); std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent); -std::string escapeCsvValue(const std::string& value, const char delimiter); +std::string escapeCsvValue(const std::string &value, const char delimiter); #endif diff --git a/src/core/meson.build b/src/core/meson.build deleted file mode 100644 index b54f484..0000000 --- a/src/core/meson.build +++ /dev/null @@ -1,13 +0,0 @@ -boost = dependency('boost', modules: ['date_time'], static: true) -xlnt = dependency('xlnt') -sqlite = dependency('sqlite3') - -src = ['database.cpp', 'entity.cpp', 'entityint.cpp', 'entityuuid.cpp', - 'seller.cpp', 'article.cpp', 'sale.cpp', 'marketplace.cpp', - 'excelreader.cpp', 'csvreader.cpp', 'jsonutil.cpp', 'utils.cpp'] - -core_inc = include_directories('..') - -core_lib = static_library('core', src, dependencies: [boost, xlnt, sqlite, nlohmann_lib, csv_dep]) - -core_dep = declare_dependency(link_with: core_lib, include_directories : core_inc) diff --git a/src/core/sale.cpp b/src/core/sale.cpp index 1fce577..60e041a 100644 --- a/src/core/sale.cpp +++ b/src/core/sale.cpp @@ -3,41 +3,41 @@ #include -void Sale::addArticle(Article* articlePtr) +void Sale::addArticle(Article *articlePtr) { articlePtr->setSale(this); - articles_.push_back(articlePtr); + m_articles.push_back(articlePtr); } -ArticlesVec& Sale::getArticles() { return articles_; } +ArticlesVec &Sale::getArticles() { return m_articles; } -void Sale::removeArticle(const Article* articlePtr) +void Sale::removeArticle(const Article *articlePtr) { - auto it = std::find(articles_.begin(), articles_.end(), articlePtr); + auto it = std::find(m_articles.begin(), m_articles.end(), articlePtr); - if (it != articles_.end()) { + if (it != m_articles.end()) { (*it)->setSale(nullptr); (*it)->setState( Article::State::DELETE); // since we only have ad-hoc articles, that have all been sold - articles_.erase(it); + m_articles.erase(it); } } int Sale::sumInCents() { - int sum = std::accumulate(articles_.begin(), articles_.end(), 0, - [](int a, const Article* b) { return a + b->getPrice(); }); + int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0, + [](int a, const Article *b) { return a + b->getPrice(); }); return sum; } std::string Sale::sumAsString() { return formatCentAsEuroString(sumInCents()); } -std::string Sale::getTimestamp() const { return timestamp_; } +std::string Sale::getTimestamp() const { return m_timestamp; } -void Sale::setTimestamp(const std::string& timestamp) { timestamp_ = timestamp; } +void Sale::setTimestamp(const std::string ×tamp) { m_timestamp = timestamp; } std::string Sale::getTimestampFormatted() const { - boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(timestamp_); + boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(m_timestamp); return boost::posix_time::to_simple_string(time); } diff --git a/src/core/sale.h b/src/core/sale.h index 02a960d..dd54f58 100644 --- a/src/core/sale.h +++ b/src/core/sale.h @@ -11,30 +11,30 @@ namespace { -using ArticlesVec = std::vector; +using ArticlesVec = std::vector
; } class Sale : public EntityUuid { - public: +public: Sale() = default; - Sale(const Sale&) = delete; + Sale(const Sale &) = delete; virtual ~Sale() = default; - void addArticle(Article* articlePtr); - void setTimestamp(const std::string& timestamp); + void addArticle(Article *articlePtr); + void setTimestamp(const std::string ×tamp); - ArticlesVec& getArticles(); + ArticlesVec &getArticles(); std::string getTimestamp() const; std::string getTimestampFormatted() const; int sumInCents(); std::string sumAsString(); - void removeArticle(const Article* articlePtr); + void removeArticle(const Article *articlePtr); - private: - std::string timestamp_{ +private: + std::string m_timestamp{ boost::posix_time::to_iso_extended_string(boost::posix_time::second_clock::local_time())}; - mutable ArticlesVec articles_{}; + mutable ArticlesVec m_articles{}; }; #endif diff --git a/src/core/seller.cpp b/src/core/seller.cpp index cc053ce..9cbb88d 100644 --- a/src/core/seller.cpp +++ b/src/core/seller.cpp @@ -5,32 +5,32 @@ #include #include -Seller::Seller(const std::string& firstName, const std::string& lastName, int sellerNo, +Seller::Seller(const std::string &firstName, const std::string &lastName, int sellerNo, int numArticlesOffered) : EntityInt(sellerNo) { - firstName_ = firstName; - lastName_ = lastName; - numArticlesOffered_ = numArticlesOffered; + m_firstName = firstName; + m_lastName = lastName; + m_numArticlesOffered = numArticlesOffered; } void Seller::setSellerNo(int seller_no) { setId(seller_no); } -void Seller::setFirstName(const std::string& firstName) { firstName_ = firstName; } +void Seller::setFirstName(const std::string &firstName) { m_firstName = firstName; } -void Seller::setLastName(const std::string& lastName) { lastName_ = lastName; } +void Seller::setLastName(const std::string &lastName) { m_lastName = lastName; } -void Seller::setNumArticlesOffered(int number) { numArticlesOffered_ = number; } +void Seller::setNumArticlesOffered(int number) { m_numArticlesOffered = number; } void Seller::addArticle(std::unique_ptr
article) { article->setSeller(this); - articles_.push_back(std::move(article)); + m_articles.push_back(std::move(article)); } -std::string Seller::getFirstName() const { return firstName_; } +std::string Seller::getFirstName() const { return m_firstName; } -std::string Seller::getLastName() const { return lastName_; } +std::string Seller::getLastName() const { return m_lastName; } int Seller::getSellerNo() const { return getId(); } @@ -38,16 +38,16 @@ std::string Seller::getSellerNoAsString() const { std::stringstream selNoStr; - selNoStr << std::setfill('0') << std::setw(3) << id_; + selNoStr << std::setfill('0') << std::setw(3) << m_id; return selNoStr.str(); ; } -std::vector Seller::getArticles(bool onlySold) const +std::vector
Seller::getArticles(bool onlySold) const { - std::vector articles; - for (const auto& article : articles_) { + std::vector
articles; + for (const auto &article : m_articles) { if (onlySold && article->isSold()) { articles.push_back(article.get()); } else if (!onlySold) { @@ -57,54 +57,54 @@ std::vector Seller::getArticles(bool onlySold) const return articles; } -Article* Seller::getArticleByUuid(const std::string& uuidString) +Article *Seller::getArticleByUuid(const std::string &uuidString) { - auto iter = std::find_if(articles_.begin(), articles_.end(), [&uuidString](const auto& art) { + auto iter = std::find_if(m_articles.begin(), m_articles.end(), [&uuidString](const auto &art) { return art->getUuidAsString() == uuidString; }); - if (iter == articles_.end()) + if (iter == m_articles.end()) return nullptr; return (*iter).get(); } int Seller::numArticlesSold() const { return static_cast(getArticles(true).size()); } -int Seller::numArticlesOffered() const { return numArticlesOffered_; } +int Seller::numArticlesOffered() const { return m_numArticlesOffered; } int Seller::getMaxArticleNo() const { auto iter = std::max_element( - articles_.begin(), articles_.end(), - [](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); - if (iter == articles_.end()) + m_articles.begin(), m_articles.end(), + [](const auto &a, const auto &b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); + if (iter == m_articles.end()) return 0; return (*iter)->getArticleNo(); } void Seller::cleanupArticles() { - articles_.erase(std::remove_if(articles_.begin(), articles_.end(), - [](const auto& article) { + m_articles.erase(std::remove_if(m_articles.begin(), m_articles.end(), + [](const auto &article) { return article->getState() == Article::State::DELETE; }), - articles_.end()); + m_articles.end()); - for (auto& article : articles_) { + for (auto &article : m_articles) { article->setState(Article::State::OK); } } int Seller::sumInCents() { - int sum = std::accumulate(articles_.begin(), articles_.end(), 0, - [](int a, const auto& b) { return a + b->getPrice(); }); + int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0, + [](int a, const auto &b) { return a + b->getPrice(); }); return sum; } std::string Seller::sumAsString() { return formatCentAsEuroString(sumInCents()); } -bool operator<(const Seller& li, const Seller& re) { return li.id_ < re.id_; } -bool operator<(const std::unique_ptr& li, const std::unique_ptr& re) +bool operator<(const Seller &li, const Seller &re) { return li.m_id < re.m_id; } +bool operator<(const std::unique_ptr &li, const std::unique_ptr &re) { - return li->id_ < re->id_; + return li->m_id < re->m_id; } diff --git a/src/core/seller.h b/src/core/seller.h index e3dda18..f71b1eb 100644 --- a/src/core/seller.h +++ b/src/core/seller.h @@ -12,16 +12,16 @@ class Seller : public EntityInt { - public: +public: Seller() = default; - Seller(const Seller&) = delete; + Seller(const Seller &) = delete; virtual ~Seller() = default; - Seller(const std::string& firstName, const std::string& lastName, int sellerNo = 0, + Seller(const std::string &firstName, const std::string &lastName, int sellerNo = 0, int numArticlesOffered = 0); void setSellerNo(int sellerNo); - void setFirstName(const std::string& firstName); - void setLastName(const std::string& lastName); + void setFirstName(const std::string &firstName); + void setLastName(const std::string &lastName); void setNumArticlesOffered(int number); void addArticle(std::unique_ptr
article); void cleanupArticles(); @@ -32,20 +32,20 @@ class Seller : public EntityInt std::string getSellerNoAsString() const; int numArticlesOffered() const; int numArticlesSold() const; - std::vector getArticles(bool onlySold = true) const; - Article* getArticleByUuid(const std::string& uuidString); + std::vector
getArticles(bool onlySold = true) const; + Article *getArticleByUuid(const std::string &uuidString); int getMaxArticleNo() const; int sumInCents(); std::string sumAsString(); - friend bool operator<(const Seller& li, const Seller& re); - friend bool operator<(const std::unique_ptr& li, const std::unique_ptr& re); + friend bool operator<(const Seller &li, const Seller &re); + friend bool operator<(const std::unique_ptr &li, const std::unique_ptr &re); - private: - int numArticlesOffered_{}; - std::string firstName_{}; - std::string lastName_{}; - std::vector> articles_{}; +private: + int m_numArticlesOffered{}; + std::string m_firstName{}; + std::string m_lastName{}; + std::vector> m_articles{}; }; #endif diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 83c7a3a..1725924 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -1,39 +1,53 @@ #include "utils.h" #include +#include +#include #include #include +#include + +//using namespace fmt; + std::string formatCentAsEuroString(const int cent, int width) { - std::stringstream currStream; + /*std::stringstream currStream; try { std::locale myLocale("de_DE.utf8"); currStream.imbue(myLocale); + std::cout << ">>> " << fmt::format(myLocale, "{:6.2Lf}", 1.12345) << '\n'; currStream << std::right << std::setw(width) << std::showbase << std::put_money(cent, false); - } catch (std::runtime_error& err) { + } catch (std::runtime_error &err) { currStream << std::fixed << std::setw(width >= 4 ? width - 4 : width) << std::setprecision(2) << cent / 100.0L << " €"; } - return currStream.str(); + return currStream.str();*/ + +#if defined(_WIN64) || defined(_WIN32) + std::locale myLocale; +#else + std::locale myLocale{"de_DE.utf8"}; +#endif + return std::format(myLocale, "{:{}.2Lf} €", cent / 100.0L, width); } -std::string& ltrim(std::string& str, const std::string& chars) +std::string <rim(std::string &str, const std::string &chars) { str.erase(0, str.find_first_not_of(chars)); return str; } -std::string& rtrim(std::string& str, const std::string& chars) +std::string &rtrim(std::string &str, const std::string &chars) { str.erase(str.find_last_not_of(chars) + 1); return str; } -std::string& trim(std::string& str, const std::string& chars) +std::string &trim(std::string &str, const std::string &chars) { return ltrim(rtrim(str, chars), chars); } @@ -47,3 +61,10 @@ bool case_insensitive_match(std::string s1, std::string s2) return true; // The strings are same return false; // not matched } + +bool isNumber(const std::string &str) +{ + return !str.empty() && std::find_if(str.begin(), str.end(), [](unsigned char c) { + return !std::isdigit(c); + }) == str.end(); +} \ No newline at end of file diff --git a/src/core/utils.h b/src/core/utils.h index 9ca2d32..0adfd75 100644 --- a/src/core/utils.h +++ b/src/core/utils.h @@ -5,10 +5,11 @@ #include #include -std::string formatCentAsEuroString(const int cent, int width = 10); -std::string& ltrim(std::string& str, const std::string& chars = "\t\n\v\f\r "); -std::string& rtrim(std::string& str, const std::string& chars = "\t\n\v\f\r "); -std::string& trim(std::string& str, const std::string& chars = "\t\n\v\f\r "); +std::string formatCentAsEuroString(const int cent, int width = 6); +std::string <rim(std::string &str, const std::string &chars = "\t\n\v\f\r "); +std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r "); +std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r "); bool case_insensitive_match(std::string s1, std::string s2); +bool isNumber(const std::string &str); #endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 3f62bef..edd2102 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -8,39 +8,45 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) # Find the QtWidgets library -find_package(Qt5Widgets CONFIG REQUIRED) -find_package(Qt5PrintSupport CONFIG REQUIRED) +find_package(Qt6 COMPONENTS Widgets Network PrintSupport CONFIG REQUIRED) # For SingleApplication: -find_package(Qt5Network CONFIG REQUIRED) -set(QAPPLICATION_CLASS QApplication) +set(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use, defaults to 6") +set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication") +FetchContent_Declare( + SingleApplication + GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication + GIT_TAG v3.5.2 +) +FetchContent_MakeAvailable(SingleApplication) add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS}) -set(GUI_SOURCES - kima2.cpp - mainwindow.cpp - mainwindow.ui - sellerdialog.cpp - sellerdialog.ui - sellermodel.cpp - pricedialog.cpp - pricedialog.ui - basketmodel.cpp - salemodel.cpp - reportdialog.cpp - reportdialog.ui - reportmodel.cpp - settingsdialog.cpp - settingsdialog.ui - ../../kima2.qrc - ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git/singleapplication.cpp - ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git/singleapplication_p.cpp +add_executable(kima2) + +target_sources(kima2 PRIVATE + kima2.cpp + mainwindow.cpp + mainwindow.ui + sellerdialog.cpp + sellerdialog.ui + sellermodel.cpp + pricedialog.cpp + pricedialog.ui + basketmodel.cpp + salemodel.cpp + reportdialog.cpp + reportdialog.ui + reportmodel.cpp + settingsdialog.cpp + settingsdialog.ui + ../../kima2.qrc + kima2.rc ) -add_executable(kima2 ${GUI_SOURCES} kima2.rc) target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR}) -target_include_directories(kima2 PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git) -target_link_libraries(kima2 core printer Qt5::Widgets Qt5::PrintSupport Qt5::Network stdc++fs) + +target_link_libraries(kima2 core printer Qt::Core Qt::PrintSupport Qt::Network SingleApplication::SingleApplication) + if(WIN32) set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows") endif(WIN32) diff --git a/src/gui/basketmodel.cpp b/src/gui/basketmodel.cpp index d693782..789d64b 100644 --- a/src/gui/basketmodel.cpp +++ b/src/gui/basketmodel.cpp @@ -5,13 +5,13 @@ #include BasketModel::BasketModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), marketplace_(market) + : QAbstractTableModel(parent), m_marketplace(market) { } int BasketModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return static_cast(marketplace_->basketSize()); + return static_cast(m_marketplace->basketSize()); } int BasketModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 4; } @@ -46,10 +46,10 @@ QVariant BasketModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (marketplace_->basketSize() == 0) + if (m_marketplace->basketSize() == 0) return QVariant(); - Article* article = marketplace_->getBasket().at(index.row()).get(); + Article* article = m_marketplace->getBasket().at(index.row()).get(); switch (index.column()) { case 0: @@ -92,45 +92,45 @@ QVariant BasketModel::headerData(int section, Qt::Orientation orientation, int r void BasketModel::addArticle(Seller* seller, int price, const std::string& desc) { - emit beginInsertRows(QModelIndex(), marketplace_->getBasket().size(), - marketplace_->getBasket().size()); + emit beginInsertRows(QModelIndex(), m_marketplace->getBasket().size(), + m_marketplace->getBasket().size()); auto article = std::make_unique
(price); article->createUuid(); article->setDescription(desc); - article->setArticleNo(marketplace_->getNextArticleNo()); + article->setArticleNo(m_marketplace->getNextArticleNo()); article->setSourceNo(QSettings().value("global/cashPointNo").toInt()); article->setSeller(seller); - marketplace_->addArticleToBasket(std::move(article)); + m_marketplace->addArticleToBasket(std::move(article)); emit endInsertRows(); } void BasketModel::finishSale() { - emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); + emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1); auto sale = std::make_unique(); sale->createUuid(); sale->setSourceNo(QSettings().value("global/cashPointNo").toInt()); - marketplace_->finishCurrentSale(std::move(sale)); + m_marketplace->finishCurrentSale(std::move(sale)); emit endRemoveRows(); emit basketDataChanged(); } void BasketModel::cancelSale() { - emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); - marketplace_->getBasket().clear(); + emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1); + m_marketplace->getBasket().clear(); emit endRemoveRows(); } bool BasketModel::removeRows(int row, int count, const QModelIndex& parent) { - auto article = marketplace_->getBasket().at(row).get(); + auto article = m_marketplace->getBasket().at(row).get(); emit beginRemoveRows(parent, row, row + count - 1); - marketplace_->getBasket().erase( - std::remove_if(marketplace_->getBasket().begin(), marketplace_->getBasket().end(), + m_marketplace->getBasket().erase( + std::remove_if(m_marketplace->getBasket().begin(), m_marketplace->getBasket().end(), [&article](const auto& a) { return a->getUuid() == article->getUuid(); }), - marketplace_->getBasket().end()); + m_marketplace->getBasket().end()); emit endRemoveRows(); return true; } diff --git a/src/gui/basketmodel.h b/src/gui/basketmodel.h index 7c1858c..81ad858 100644 --- a/src/gui/basketmodel.h +++ b/src/gui/basketmodel.h @@ -24,7 +24,7 @@ class BasketModel : public QAbstractTableModel void basketDataChanged(); private: - Marketplace* marketplace_; + Marketplace* m_marketplace; }; #endif diff --git a/src/gui/kima2.cpp b/src/gui/kima2.cpp index 20fb3ba..d2826bd 100644 --- a/src/gui/kima2.cpp +++ b/src/gui/kima2.cpp @@ -7,30 +7,28 @@ #include #include #include -#include #include +#include #include +#include -int main(int argc, char* argv[]) +using namespace Qt::Literals::StringLiterals; + +int main(int argc, char *argv[]) { - SingleApplication kimaApp(argc, argv); + SingleApplication kimaApp(argc, argv, false, SingleApplication::Mode::User | SingleApplication::ExcludeAppPath | SingleApplication::ExcludeAppVersion); // QCoreApplication::setOrganizationName("RustySoft"); QCoreApplication::setOrganizationDomain("rustysoft.de"); QCoreApplication::setApplicationName("kima2"); - QTranslator qTranslator; - QLocale german(QLocale::German); -#ifdef __linux__ - qTranslator.load("qt_" + german.name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); -#endif -#ifdef _WIN32 - QApplication::setStyle(QStyleFactory::create("Fusion")); - qTranslator.load("qt_" + german.name(), - QApplication::applicationDirPath() + QDir::separator() + "translations"); -#endif - kimaApp.installTranslator(&qTranslator); + QTranslator qtTranslator; + + if (qtTranslator.load(QLocale::system(), u"qtbase"_s, u"_"_s, + QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { + kimaApp.installTranslator(&qtTranslator); + } QSettings settings{}; while (!settings.contains("global/cashPointNo")) { diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 0d727b8..ca9031e 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,15 +1,14 @@ #include "mainwindow.h" #include "basketmodel.h" -#include #include "pricedialog.h" #include "reportdialog.h" #include "salemodel.h" #include "sellerdialog.h" #include "settingsdialog.h" +#include #include -#include #include #include #include @@ -32,82 +31,81 @@ constexpr int STATUSBAR_TIMEOUT = 5000; MainWindow::MainWindow() { - ui_.setupUi(this); + m_ui.setupUi(this); - marketplace_ = std::make_unique(); - Database::InitResult res = marketplace_->loadFromDb(); + m_marketplace = std::make_unique(); + Database::InitResult res = m_marketplace->loadFromDb(); if (res == Database::InitResult::OUTDATED_REPLACED) { QMessageBox(QMessageBox::Icon::Information, "Datenbankinformation", "Es wurde eine veraltete Datenbankdatei erkannt.
Diese wurde " "umbenannt und eine neue Datei wurde erstellt.") - .exec(); + .exec(); } statusBar()->showMessage("Gespeicherte Daten wurden geladen.", STATUSBAR_TIMEOUT); - BasketModel* model = new BasketModel(getMarketplace(), ui_.basketView); - ui_.basketView->setModel(model); - ui_.basketView->setColumnHidden(0, true); // hide the uuid + BasketModel *model = new BasketModel(getMarketplace(), m_ui.basketView); + m_ui.basketView->setModel(model); + m_ui.basketView->setColumnHidden(0, true); // hide the uuid setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString()); - ui_.salesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + m_ui.salesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); setSaleModel(); - connect(ui_.actionQuit, &QAction::triggered, qApp, QApplication::closeAllWindows, + connect(m_ui.actionQuit, &QAction::triggered, qApp, QApplication::closeAllWindows, Qt::QueuedConnection); - connect(ui_.newAction, &QAction::triggered, this, [=]() { - if (marketplace_->getSellers().size() == 0 && marketplace_->getSales().size() == 0) { + connect(m_ui.newAction, &QAction::triggered, this, [this]() { + if (m_marketplace->getSellers().size() == 0 && m_marketplace->getSales().size() == 0) { return; } auto dlgResult = QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", "Möchten Sie wirklich alle gespeicherten Daten verwerfen?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) - .exec(); + .exec(); if (dlgResult == QMessageBox::No) return; - delete ui_.salesView->model(); - dynamic_cast(ui_.basketView->model())->cancelSale(); - marketplace_->clear(); + delete m_ui.salesView->model(); + dynamic_cast(m_ui.basketView->model())->cancelSale(); + m_marketplace->clear(); setSaleModel(); updateStatLabel(); }); - ui_.sellerNoEdit->installEventFilter(this); - ui_.givenSpinBox->installEventFilter(this); + m_ui.sellerNoEdit->installEventFilter(this); + m_ui.givenSpinBox->installEventFilter(this); - connect(ui_.actionEditSeller, &QAction::triggered, this, + connect(m_ui.actionEditSeller, &QAction::triggered, this, &MainWindow::onActionEditSellerTriggered); - connect(ui_.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered); - connect(ui_.givenSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, + connect(m_ui.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered); + connect(m_ui.givenSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &MainWindow::onGivenSpinBoxValueChanged); - connect(ui_.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(m_ui.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onBasketViewSelectionChanged); - connect(ui_.cancelArticleButton, &QPushButton::clicked, this, + connect(m_ui.cancelArticleButton, &QPushButton::clicked, this, &MainWindow::onCancelArticleButtonClicked); - connect(ui_.cancelSaleButton, &QPushButton::clicked, this, + connect(m_ui.cancelSaleButton, &QPushButton::clicked, this, &MainWindow::onCancelSaleButtonClicked); - connect(ui_.printSaleReceiptButton, &QPushButton::clicked, this, + connect(m_ui.printSaleReceiptButton, &QPushButton::clicked, this, &MainWindow::onPrintSaleReceiptButtonClicked); - connect(ui_.cancelAllArticlesButton, &QPushButton::clicked, this, + connect(m_ui.cancelAllArticlesButton, &QPushButton::clicked, this, &MainWindow::onCancelAllArticlesButtonClicked); - connect(ui_.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt); - connect(ui_.aboutAction, &QAction::triggered, this, &MainWindow::onAbout); - connect(ui_.openManualAction, &QAction::triggered, this, []() { - auto locations = QStandardPaths::standardLocations(QStandardPaths::DataLocation); + connect(m_ui.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt); + connect(m_ui.aboutAction, &QAction::triggered, this, &MainWindow::onAbout); + connect(m_ui.openManualAction, &QAction::triggered, this, []() { + auto locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); for (auto location : locations) { if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) { QDesktopServices::openUrl( - QUrl(QString("file:///") + location + QString("/Benutzerhandbuch.pdf"), - QUrl::TolerantMode)); + QUrl::fromLocalFile(location + QString("/Benutzerhandbuch.pdf"))); } } }); - connect(ui_.licenseAction, &QAction::triggered, this, [=]() { + connect(m_ui.licenseAction, &QAction::triggered, this, [this]() { QString licenseText( - "Copyright © 2018-2021 Martin Brodbeck\n\n" + "Copyright © 2018-2025 Martin Brodbeck\n\n" "Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der " "zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, " "sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, " @@ -126,36 +124,30 @@ MainWindow::MainWindow() "SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN."); QMessageBox::information(this, "Lizenzinformation", licenseText); }); - connect(ui_.reportAction, &QAction::triggered, this, [=]() { - ReportDialog(this).exec(); - }); - connect(ui_.configAction, &QAction::triggered, this, [=]() { + connect(m_ui.reportAction, &QAction::triggered, this, [this]() { ReportDialog(this).exec(); }); + connect(m_ui.configAction, &QAction::triggered, this, [this]() { int result = SettingsDialog(this).exec(); if (result == QDialog::Accepted) { - delete ui_.salesView->model(); - marketplace_->loadFromDb(); + delete m_ui.salesView->model(); + m_marketplace->loadFromDb(); setSaleModel(); } this->setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString()); }); - connect(ui_.importSellerExcelAction, &QAction::triggered, this, - &MainWindow::onImportSellerExcelActionTriggered); - connect(ui_.importSellerJsonAction, &QAction::triggered, this, - &MainWindow::onImportSellerJsonActionTriggered); - connect(ui_.exportSellerJsonAction, &QAction::triggered, this, - &MainWindow::onExportSellerJsonActionTriggered); - connect(ui_.exportSalesJsonAction, &QAction::triggered, this, + connect(m_ui.importSellerAction, &QAction::triggered, this, + &MainWindow::onImportSellerActionTriggered); + connect(m_ui.exportSalesJsonAction, &QAction::triggered, this, &MainWindow::onExportSalesJsonActionTriggered); - connect(ui_.importSalesJsonAction, &QAction::triggered, this, + connect(m_ui.importSalesJsonAction, &QAction::triggered, this, &MainWindow::onImportSalesJsonActionTriggered); readGeometry(); setWindowIcon(QIcon(":/misc/kima2.ico")); updateStatLabel(); - ui_.lastPriceLabel1->setText(formatCentAsEuroString(0).c_str()); - ui_.lastPriceLabel2->setText(formatCentAsEuroString(0).c_str()); + m_ui.lastPriceLabel1->setText(formatCentAsEuroString(0).c_str()); + m_ui.lastPriceLabel2->setText(formatCentAsEuroString(0).c_str()); } void MainWindow::onActionEditSellerTriggered() @@ -163,11 +155,11 @@ void MainWindow::onActionEditSellerTriggered() auto dialog = std::make_unique(this); int retCode = dialog->exec(); - delete ui_.salesView->model(); + delete m_ui.salesView->model(); if (retCode == QDialog::Accepted) { - marketplace_->sortSellers(); - marketplace_->storeToDb(); + m_marketplace->sortSellers(); + m_marketplace->storeToDb(); statusBar()->showMessage("Änderungen an den Verkäufer-Stammdaten gespeichert.", STATUSBAR_TIMEOUT); } else { @@ -181,42 +173,42 @@ void MainWindow::onActionEditSellerTriggered() void MainWindow::setSaleModel() { - ui_.salesView->setModel(new SaleModel(getMarketplace(), ui_.salesView)); - ui_.salesView->setColumnHidden(2, true); - ui_.salesView->resizeColumnToContents(0); - ui_.salesView->resizeColumnToContents(1); + m_ui.salesView->setModel(new SaleModel(getMarketplace(), m_ui.salesView)); + m_ui.salesView->setColumnHidden(2, true); + m_ui.salesView->resizeColumnToContents(0); + m_ui.salesView->resizeColumnToContents(1); - ui_.printSaleReceiptButton->setEnabled(false); - ui_.cancelSaleButton->setEnabled(false); + m_ui.printSaleReceiptButton->setEnabled(false); + m_ui.cancelSaleButton->setEnabled(false); - connect(static_cast(ui_.basketView->model()), &BasketModel::basketDataChanged, - static_cast(ui_.salesView->model()), &SaleModel::onBasketDataChanged); - connect(ui_.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(static_cast(m_ui.basketView->model()), &BasketModel::basketDataChanged, + static_cast(m_ui.salesView->model()), &SaleModel::onBasketDataChanged); + connect(m_ui.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onSalesViewSelectionChanged); } void MainWindow::onPaidButtonTriggered() { - if (marketplace_->basketSize() > 0) { - QString lastPrice{marketplace_->getBasketSumAsString().c_str()}; - dynamic_cast(ui_.basketView->model())->finishSale(); - ui_.salesView->resizeColumnToContents(0); - ui_.lastPriceLabel1->setText(lastPrice); - ui_.lastPriceLabel2->setText(lastPrice); - ui_.basketSumLabel->setText(formatCentAsEuroString(0).c_str()); - ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); - ui_.drawbackContainerWidget->setEnabled(false); - ui_.sellerNoEdit->setFocus(); + if (m_marketplace->basketSize() > 0) { + QString lastPrice{m_marketplace->getBasketSumAsString().c_str()}; + dynamic_cast(m_ui.basketView->model())->finishSale(); + m_ui.salesView->resizeColumnToContents(0); + m_ui.lastPriceLabel1->setText(lastPrice); + m_ui.lastPriceLabel2->setText(lastPrice); + m_ui.basketSumLabel->setText(formatCentAsEuroString(0).c_str()); + m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); + m_ui.drawbackContainerWidget->setEnabled(false); + m_ui.sellerNoEdit->setFocus(); statusBar()->showMessage("Verkaufsvorgang erfolgreich durchgeführt.", STATUSBAR_TIMEOUT); updateStatLabel(); } } -bool MainWindow::eventFilter(QObject* target, QEvent* event) +bool MainWindow::eventFilter(QObject *target, QEvent *event) { - if (target == ui_.sellerNoEdit) { + if (target == m_ui.sellerNoEdit) { if (event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); + QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { if (keyEvent->modifiers() & Qt::ControlModifier) { checkSellerNo(true); @@ -227,18 +219,18 @@ bool MainWindow::eventFilter(QObject* target, QEvent* event) return true; } } - } else if (target == ui_.givenSpinBox) { + } else if (target == m_ui.givenSpinBox) { if (event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast(event); + QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { if (keyEvent->modifiers() & Qt::ControlModifier) { onPaidButtonTriggered(); return true; } } else if (keyEvent->key() == Qt::Key::Key_Escape) { - ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); - ui_.drawbackContainerWidget->setEnabled(false); - ui_.sellerNoEdit->setFocus(); + m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); + m_ui.drawbackContainerWidget->setEnabled(false); + m_ui.sellerNoEdit->setFocus(); } } } @@ -249,15 +241,15 @@ void MainWindow::checkSellerNo(bool ctrlPressed) { using std::regex, std::regex_match, std::smatch; - auto inputText = ui_.sellerNoEdit->text().toStdString(); + auto inputText = m_ui.sellerNoEdit->text().toStdString(); if (inputText.empty()) { if (ctrlPressed == false) { onPaidButtonTriggered(); - } else if (marketplace_->getBasket().size() > 0) { - ui_.drawbackContainerWidget->setEnabled(true); - ui_.givenSpinBox->setFocus(); - ui_.givenSpinBox->selectAll(); + } else if (m_marketplace->getBasket().size() > 0) { + m_ui.drawbackContainerWidget->setEnabled(true); + m_ui.givenSpinBox->setFocus(); + m_ui.givenSpinBox->selectAll(); } return; } @@ -266,13 +258,13 @@ void MainWindow::checkSellerNo(bool ctrlPressed) smatch result; if (!regex_match(inputText, result, pattern)) { - ui_.sellerNoEdit->clear(); + m_ui.sellerNoEdit->clear(); return; } int sellerNo = std::stoi(result[0]); - auto seller = marketplace_->findSellerWithSellerNo(sellerNo); + auto seller = m_marketplace->findSellerWithSellerNo(sellerNo); if (seller) { PriceDialog priceDialog(this); if (sellerNo == 0) { @@ -282,52 +274,52 @@ void MainWindow::checkSellerNo(bool ctrlPressed) if (dialogResult == QDialog::Accepted) { int price = priceDialog.getPrice(); std::string desc = priceDialog.getDescription(); - dynamic_cast(ui_.basketView->model())->addArticle(seller, price, desc); - ui_.basketView->resizeColumnToContents(1); - ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); + dynamic_cast(m_ui.basketView->model())->addArticle(seller, price, desc); + m_ui.basketView->resizeColumnToContents(1); + m_ui.basketSumLabel->setText(m_marketplace->getBasketSumAsString().c_str()); } } - ui_.sellerNoEdit->clear(); + m_ui.sellerNoEdit->clear(); } void MainWindow::onGivenSpinBoxValueChanged(double value) { int givenInCent = std::round(value * 100); - int basketSumInCent = marketplace_->getBasketSumInCent(); + int basketSumInCent = m_marketplace->getBasketSumInCent(); int drawback = givenInCent - basketSumInCent; - ui_.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str()); + m_ui.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str()); } -void MainWindow::onBasketViewSelectionChanged(const QItemSelection& selected, - [[maybe_unused]] const QItemSelection& deselected) +void MainWindow::onBasketViewSelectionChanged(const QItemSelection &selected, + [[maybe_unused]] const QItemSelection &deselected) { if (selected.size() > 0) { - ui_.cancelArticleButton->setEnabled(true); + m_ui.cancelArticleButton->setEnabled(true); } else { - ui_.cancelArticleButton->setEnabled(false); + m_ui.cancelArticleButton->setEnabled(false); } } -void MainWindow::onSalesViewSelectionChanged(const QItemSelection& selected, - [[maybe_unused]] const QItemSelection& deselected) +void MainWindow::onSalesViewSelectionChanged(const QItemSelection &selected, + [[maybe_unused]] const QItemSelection &deselected) { if (selected.size() > 0) { - ui_.cancelSaleButton->setEnabled(true); + m_ui.cancelSaleButton->setEnabled(true); if (!selected.indexes()[0].parent().isValid()) - ui_.printSaleReceiptButton->setEnabled(true); + m_ui.printSaleReceiptButton->setEnabled(true); else - ui_.printSaleReceiptButton->setEnabled(false); + m_ui.printSaleReceiptButton->setEnabled(false); } else { - ui_.cancelSaleButton->setEnabled(false); - ui_.printSaleReceiptButton->setEnabled(false); + m_ui.cancelSaleButton->setEnabled(false); + m_ui.printSaleReceiptButton->setEnabled(false); } } void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) { - auto selModel = ui_.basketView->selectionModel(); + auto selModel = m_ui.basketView->selectionModel(); if (selModel->hasSelection() == false) return; @@ -335,7 +327,7 @@ void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", "Möchten Sie wirklich den Artikel stornieren?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) - .exec(); + .exec(); if (dlgResult == QMessageBox::No) return; @@ -344,16 +336,17 @@ void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - ui_.basketView->model()->removeRow(iter->row()); + m_ui.basketView->model()->removeRow(iter->row()); } - ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum - ui_.sellerNoEdit->setFocus(); + m_ui.basketSumLabel->setText( + m_marketplace->getBasketSumAsString().c_str()); // Update basket sum + m_ui.sellerNoEdit->setFocus(); } void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) { - auto selModel = ui_.salesView->selectionModel(); + auto selModel = m_ui.salesView->selectionModel(); if (selModel->hasSelection() == false) return; @@ -361,7 +354,7 @@ void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", "Möchten Sie wirklich aus abgeschlossenen Verkäufen stornieren?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) - .exec(); + .exec(); if (dlgResult == QMessageBox::No) return; @@ -370,25 +363,25 @@ void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - ui_.salesView->model()->removeRow(iter->row(), iter->parent()); + m_ui.salesView->model()->removeRow(iter->row(), iter->parent()); } - ui_.salesView->collapseAll(); + m_ui.salesView->collapseAll(); QString lastPriceValue(formatCentAsEuroString(0).c_str()); - if (ui_.salesView->model()->rowCount() > 0) { + if (m_ui.salesView->model()->rowCount() > 0) { lastPriceValue = - ui_.salesView->model()->data(ui_.salesView->model()->index(0, 1)).toString(); + m_ui.salesView->model()->data(m_ui.salesView->model()->index(0, 1)).toString(); } - ui_.lastPriceLabel1->setText(lastPriceValue); - ui_.lastPriceLabel2->setText(lastPriceValue); + m_ui.lastPriceLabel1->setText(lastPriceValue); + m_ui.lastPriceLabel2->setText(lastPriceValue); updateStatLabel(); } void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) { - auto selModel = ui_.salesView->selectionModel(); + auto selModel = m_ui.salesView->selectionModel(); if (selModel->hasSelection() == false) return; @@ -397,7 +390,7 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); auto indexes = selModel->selectedRows(); - auto& sale = marketplace_->getSales().at(indexes[0].row()); + auto &sale = m_marketplace->getSales().at(indexes[0].row()); auto printerDevice = convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); @@ -417,51 +410,50 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked) { - if (ui_.basketView->model()->rowCount() == 0) + if (m_ui.basketView->model()->rowCount() == 0) return; auto dlgResult = QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", "Möchten Sie wirklich *alle* Artikel des aktuellen Einkaufs stornieren?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) - .exec(); + .exec(); if (dlgResult == QMessageBox::No) return; - dynamic_cast(ui_.basketView->model())->cancelSale(); + dynamic_cast(m_ui.basketView->model())->cancelSale(); - ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum - ui_.sellerNoEdit->setFocus(); + m_ui.basketSumLabel->setText( + m_marketplace->getBasketSumAsString().c_str()); // Update basket sum + m_ui.sellerNoEdit->setFocus(); } -void MainWindow::onAboutQt() { - QMessageBox::aboutQt(this); -} +void MainWindow::onAboutQt() { QMessageBox::aboutQt(this); } void MainWindow::onAbout() { QMessageBox::about( this, "Über", QString("

KIMA2 - Version ") + PROJECT_VERSION + - "

" - "

KIMA2 ist ein kleines Kassenprogramm für Kindersachenmärkte.

" - "

Copyright © Martin Brodbeck <info@rustysoft.de>

"); + "

" + "

KIMA2 ist ein kleines Kassenprogramm für Kindersachenmärkte.

" + "

Copyright © Martin Brodbeck <info@rustysoft.de>

"); } -void MainWindow::onImportSellerExcelActionTriggered() +void MainWindow::onImportSellerActionTriggered() { - if (!marketplace_->getSales().empty()) { + if (!m_marketplace->getSales().empty()) { QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", "Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.", QMessageBox::StandardButton::Ok, this) - .exec(); + .exec(); return; } - auto filename = QFileDialog::getOpenFileName( - this, "Verkäufer importieren", QString(), - "Alle unterstützte Dateien (*.xlsx *.csv);;Excel Dateien (*.xlsx);;CSV Dateien (*.csv)"); + auto filename = + QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(), + "Alle unterstützte Dateien (*.csv);;CSV Dateien (*.csv)"); if (filename.isEmpty()) return; @@ -473,83 +465,17 @@ void MainWindow::onImportSellerExcelActionTriggered() #endif std::size_t numImported{}; - if (case_insensitive_match(filePath.extension().string(), std::string(".xlsx"))) { - try { - numImported = ExcelReader::readSellersFromFile(filePath, marketplace_.get()); - } catch (const std::exception& e) { - QMessageBox(QMessageBox::Icon::Critical, "Fehler beim Importieren", - "Beim Import aus der Excel-Datei ist ein Fehler aufgetreten. " - "Sie könnten ggf. versuchen, die Daten aus einer .csv Datei zu imporieren.", - QMessageBox::StandardButton::Ok, this).exec(); - std::cerr << e.what() << std::endl; - return; - } - } else { - numImported = CsvReader::readSellersFromFile(filePath, marketplace_.get()); - } + numImported = CsvReader::readSellersFromFile(filePath, m_marketplace.get()); updateStatLabel(); using namespace std::string_literals; std::ostringstream msg; - msg << "Aus der Excel/CSV-Datei wurden "s << std::to_string(numImported) + msg << "Aus der CSV-Datei wurden "s << std::to_string(numImported) << " Verkäufer importiert."; QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert", msg.str().c_str(), QMessageBox::StandardButton::Ok, this) - .exec(); -} - -void MainWindow::onImportSellerJsonActionTriggered() -{ - if (!marketplace_->getSales().empty()) { - QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", - "Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.", - QMessageBox::StandardButton::Ok, this) .exec(); - return; - } - - auto filename = QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(), - "JSON Dateien (*.json)"); - - if (filename.isEmpty()) - return; - -#if defined(_WIN64) || defined(_WIN32) - fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif - - std::size_t numImported{}; - numImported = JsonUtil::importSellers(filePath, marketplace_.get()); - - updateStatLabel(); - - using namespace std::string_literals; - std::ostringstream msg; - msg << "Aus der JSON-Datei wurden "s << std::to_string(numImported) - << " Verkäufer importiert."; - QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert", - msg.str().c_str(), QMessageBox::StandardButton::Ok, this) - .exec(); -} - -void MainWindow::onExportSellerJsonActionTriggered() -{ - auto filename = QFileDialog::getSaveFileName( - this, "Verkäufer exportieren", QString("kima2_verkaeufer.json"), "JSON Dateien (*.json)"); - - if (filename.isEmpty()) - return; - -#if defined(_WIN64) || defined(_WIN32) - fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif - - JsonUtil::exportSellers(filePath, marketplace_.get()); } void MainWindow::onExportSalesJsonActionTriggered() @@ -557,9 +483,9 @@ void MainWindow::onExportSalesJsonActionTriggered() QSettings settings; auto filename = QFileDialog::getSaveFileName( - this, "Umsätze/Transaktionen exportieren", - QString("kima2_umsaetze_kasse") + settings.value("global/cashPointNo").toString() + ".json", - "JSON Dateien (*.json)"); + this, "Umsätze/Transaktionen exportieren", + QString("kima2_umsaetze_kasse") + settings.value("global/cashPointNo").toString() + ".json", + "JSON Dateien (*.json)"); if (filename.isEmpty()) return; @@ -570,7 +496,7 @@ void MainWindow::onExportSalesJsonActionTriggered() fs::path filePath(filename.toStdString()); #endif - JsonUtil::exportSales(filePath, marketplace_.get(), + JsonUtil::exportSales(filePath, m_marketplace.get(), settings.value("global/cashPointNo").toInt()); } @@ -578,27 +504,30 @@ void MainWindow::onImportSalesJsonActionTriggered() { QSettings settings; - auto filename = QFileDialog::getOpenFileName(this, "Umsätze/Transaktionen importieren", - QString(), "JSON Dateien (*.json)"); + auto filenames = QFileDialog::getOpenFileNames(this, "Umsätze/Transaktionen importieren", + QString(), "JSON Dateien (*.json)"); - if (filename.isEmpty()) + if (filenames.isEmpty()) return; + for(auto filename: filenames) { #if defined(_WIN64) || defined(_WIN32) - fs::path filePath(filename.toStdWString()); + fs::path filePath(filename.toStdWString()); #else - fs::path filePath(filename.toStdString()); + fs::path filePath(filename.toStdString()); #endif - delete ui_.salesView->model(); - try { - JsonUtil::importSales(filePath, marketplace_.get(), - settings.value("global/cashPointNo").toInt()); - } catch (std::runtime_error& err) { - QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, - this) - .exec(); + delete m_ui.salesView->model(); + try { + JsonUtil::importSales(filePath, m_marketplace.get(), + settings.value("global/cashPointNo").toInt()); + } catch (std::runtime_error &err) { + QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, + this) + .exec(); + } } + setSaleModel(); updateStatLabel(); } @@ -623,7 +552,7 @@ void MainWindow::readGeometry() settings.endGroup(); } -void MainWindow::closeEvent(QCloseEvent* event) +void MainWindow::closeEvent(QCloseEvent *event) { writeGeometry(); event->accept(); @@ -633,9 +562,9 @@ void MainWindow::updateStatLabel() { std::string statistics("KIMA2 - Version "); statistics += PROJECT_VERSION; - statistics += "
Verkäufer: " + std::to_string(marketplace_->getSellers().size() - 1); - statistics += "
Kunden: " + std::to_string(marketplace_->getSales().size()); - statistics += "
Umsatz: " + marketplace_->getOverallSumAsString(); + statistics += "

Verkäufer: " + std::to_string(m_marketplace->getSellers().size() - 1); + statistics += "
Kunden: " + std::to_string(m_marketplace->getSales().size()); + statistics += "
Umsatz: " + m_marketplace->getOverallSumAsString(); - ui_.statLabel->setText(statistics.c_str()); + m_ui.statLabel->setText(statistics.c_str()); } diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 12f9689..42ac25f 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -16,7 +16,7 @@ class MainWindow : public QMainWindow public: MainWindow(); - Marketplace* getMarketplace() { return marketplace_.get(); } + Marketplace* getMarketplace() { return m_marketplace.get(); } private slots: void onBasketViewSelectionChanged(const QItemSelection& selected, @@ -39,9 +39,7 @@ class MainWindow : public QMainWindow void checkSellerNo(bool ctrlPressed = false); void onPaidButtonTriggered(); void onGivenSpinBoxValueChanged(double value); - void onImportSellerExcelActionTriggered(); - void onImportSellerJsonActionTriggered(); - void onExportSellerJsonActionTriggered(); + void onImportSellerActionTriggered(); void onExportSalesJsonActionTriggered(); void onImportSalesJsonActionTriggered(); void setSaleModel(); @@ -49,8 +47,8 @@ class MainWindow : public QMainWindow void readGeometry(); void updateStatLabel(); - Ui::MainWindow ui_; - std::unique_ptr marketplace_; + Ui::MainWindow m_ui; + std::unique_ptr m_marketplace; }; #endif diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index a77a297..49ba0fc 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -423,7 +423,7 @@ drucken 0 0 817 - 30 + 24 @@ -440,16 +440,8 @@ drucken &Verkäufer - - - Importieren - - - - - - + @@ -513,9 +505,9 @@ drucken Exportieren für andere Kasse (JSON) - + - Aus Excel/CSV-Datei (initial) + Aus CSV-Datei (initial) @@ -548,6 +540,11 @@ drucken Lizenz + + + Importieren (aus CSV-Datei) + + diff --git a/src/gui/meson.build b/src/gui/meson.build deleted file mode 100644 index 18bfcee..0000000 --- a/src/gui/meson.build +++ /dev/null @@ -1,23 +0,0 @@ -qt5 = import('qt5') -qt5_dep = dependency('qt5', modules: ['Core', 'Gui', 'PrintSupport', 'Network']) - -thread_dep = dependency('threads') - - -src = ['kima2.cpp', 'mainwindow.cpp', 'sellerdialog.cpp', 'sellermodel.cpp', - 'pricedialog.cpp', 'basketmodel.cpp', 'salemodel.cpp', 'reportdialog.cpp', - 'reportmodel.cpp', 'settingsdialog.cpp'] - -ui = ['mainwindow.ui', 'sellerdialog.ui', 'pricedialog.ui', 'reportdialog.ui', 'settingsdialog.ui'] - -processed = qt5.preprocess(moc_headers : ['basketmodel.h', 'mainwindow.h', 'pricedialog.h', - 'reportdialog.h', 'sellerdialog.h', 'settingsdialog.h', - 'sellermodel.h', 'salemodel.h'], - ui_files : ui, - qresources : '../../kima2.qrc', - dependencies: qt5_dep) - -kima2 = executable('kima2', sources : [src, processed], - dependencies : [qt5_dep, singleapp_dep, core_dep, printer_dep, thread_dep], - include_directories : [configuration_inc], - install : true) diff --git a/src/gui/pricedialog.cpp b/src/gui/pricedialog.cpp index 93a7223..46546c8 100644 --- a/src/gui/pricedialog.cpp +++ b/src/gui/pricedialog.cpp @@ -6,31 +6,31 @@ PriceDialog::PriceDialog(QWidget* parent, bool forceDesc, Qt::WindowFlags f) : QDialog(parent, f) { - forceDesc_ = forceDesc; - ui_.setupUi(this); - ui_.priceSpinBox->setFocus(); + m_forceDesc = forceDesc; + m_ui.setupUi(this); + m_ui.priceSpinBox->setFocus(); } -int PriceDialog::getPrice() const { return static_cast(ui_.priceSpinBox->value() * 100); } +int PriceDialog::getPrice() const { return static_cast(m_ui.priceSpinBox->value() * 100); } -std::string PriceDialog::getDescription() const { return ui_.descEdit->text().toStdString(); } +std::string PriceDialog::getDescription() const { return m_ui.descEdit->text().toStdString(); } void PriceDialog::accept() { - if (static_cast(std::round(ui_.priceSpinBox->value() * 100.0L)) % 50 != 0) { + if (static_cast(std::round(m_ui.priceSpinBox->value() * 100.0L)) % 50 != 0) { QMessageBox(QMessageBox::Icon::Warning, "Falsche Preiseingabe", "Es sind nur 0,50 Cent-Schritte erlaubt.", QMessageBox::StandardButton::Ok, this) .exec(); - } else if (forceDesc_ && ui_.descEdit->text().trimmed().isEmpty()) { + } else if (m_forceDesc && m_ui.descEdit->text().trimmed().isEmpty()) { QMessageBox(QMessageBox::Icon::Warning, "Artikelbeschreibung fehlt", "Da Sie auf das Sonderkonto buchen ist eine Artikelbeschreibung erforderlich.", QMessageBox::StandardButton::Ok, this) .exec(); - ui_.descEdit->setFocus(); + m_ui.descEdit->setFocus(); } else { QDialog::accept(); } } -void PriceDialog::setForceDesc(bool force) { forceDesc_ = force; } \ No newline at end of file +void PriceDialog::setForceDesc(bool force) { m_forceDesc = force; } \ No newline at end of file diff --git a/src/gui/pricedialog.h b/src/gui/pricedialog.h index 229d2f3..5d9cbdf 100644 --- a/src/gui/pricedialog.h +++ b/src/gui/pricedialog.h @@ -19,8 +19,8 @@ class PriceDialog : public QDialog private: void on_model_duplicateSellerNo(const QString& message); virtual void accept() override; - Ui::PriceDialog ui_; - bool forceDesc_; + Ui::PriceDialog m_ui; + bool m_forceDesc; }; #endif \ No newline at end of file diff --git a/src/gui/reportdialog.cpp b/src/gui/reportdialog.cpp index 02717aa..2c13baf 100644 --- a/src/gui/reportdialog.cpp +++ b/src/gui/reportdialog.cpp @@ -17,22 +17,22 @@ namespace fs = std::filesystem; -ReportDialog::ReportDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) +ReportDialog::ReportDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { - ui_.setupUi(this); - market_ = dynamic_cast(parent)->getMarketplace(); - model_ = std::make_unique(market_, ui_.reportView); - ui_.reportView->setModel(model_.get()); - ui_.reportView->hideColumn(0); - ui_.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user + m_ui.setupUi(this); + m_market = dynamic_cast(parent)->getMarketplace(); + m_model = std::make_unique(m_market, m_ui.reportView); + m_ui.reportView->setModel(m_model.get()); + m_ui.reportView->hideColumn(0); + m_ui.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user - connect(ui_.exportCsvButton, &QPushButton::clicked, this, + connect(m_ui.exportCsvButton, &QPushButton::clicked, this, &ReportDialog::onExportCsvButtonClicked); - connect(ui_.printReportButton, &QPushButton::clicked, this, + connect(m_ui.printReportButton, &QPushButton::clicked, this, &ReportDialog::onPrintReportButtonClicked); - connect(ui_.printSellerReceiptButton, &QPushButton::clicked, this, + connect(m_ui.printSellerReceiptButton, &QPushButton::clicked, this, &ReportDialog::onPrintSellerReceiptButtonClicked); - connect(ui_.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(m_ui.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ReportDialog::onReportViewSelectionChanged); } @@ -54,7 +54,7 @@ void ReportDialog::onExportCsvButtonClicked() fs::path filePath(filename.toStdString()); #endif - market_->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro); + m_market->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro); } void ReportDialog::onPrintReportButtonClicked() @@ -75,8 +75,8 @@ void ReportDialog::onPrintReportButtonClicked() QPainter painter; int height = printer.height(); int width = printer.width(); - const double ENTRIES_PER_PAGE = 51; - const auto& sellers = market_->getSellers(); + const double ENTRIES_PER_PAGE = 45; + const auto &sellers = m_market->getSellers(); unsigned int numPages = std::ceil(sellers.size() / ENTRIES_PER_PAGE); painter.begin(&printer); @@ -126,7 +126,7 @@ void ReportDialog::onPrintReportButtonClicked() } // pieces booked on the special account "Sonderkonto" - const auto specialSeller = market_->findSellerWithSellerNo(0); + const auto specialSeller = m_market->findSellerWithSellerNo(0); if (specialSeller && specialSeller->numArticlesSold() > 0) { printer.newPage(); painter.setFont(QFont("Arial", 16, QFont::Bold)); @@ -136,7 +136,7 @@ void ReportDialog::onPrintReportButtonClicked() QString content("Einzelteile ohne Nummer\n=======================\n\n"); unsigned int lines{0}; unsigned int pages{1}; - for (const auto& article : specialSeller->getArticles(true)) { + for (const auto &article : specialSeller->getArticles(true)) { content += QString("- %1:").arg(article->getDescription().substr(0, 45).c_str(), -45); content += QString("%1\n").arg(article->getPriceAsString().c_str(), 11); ++lines; @@ -163,8 +163,8 @@ void ReportDialog::onPrintReportButtonClicked() "Auswertung Kindersachenmarkt"); painter.setFont(fixedFont); QString content("Gesamtstatistik\n===============\n\n"); - int numArticlesOffered = market_->getNumArticlesOffered(); - int numArticlesSold = market_->getNumArticlesSold(); + int numArticlesOffered = m_market->getNumArticlesOffered(); + int numArticlesSold = m_market->getNumArticlesSold(); double percentArticlesSold = (static_cast(numArticlesSold) / static_cast(numArticlesOffered)) * 100; content += QString("Registrierte Verkäufer: %1\n").arg(sellers.size() - 1, 6); @@ -172,14 +172,14 @@ void ReportDialog::onPrintReportButtonClicked() content += QString("Verkaufte Artikel: %1 (%L2 %)\n") .arg(numArticlesSold, 6) .arg(percentArticlesSold, 0, 'f', 2); - content += QString("Anzahl Kunden: %1\n\n").arg(market_->getSales().size(), 6); - content += QString("Gesamtumsatz: %1\n").arg(market_->getOverallSumAsString().c_str(), 10); + content += QString("Anzahl Kunden: %1\n\n").arg(m_market->getSales().size(), 6); + content += QString("Gesamtumsatz: %1\n").arg(m_market->getOverallSumAsString().c_str(), 10); content += QString("Ausgezahlt: %1\n") - .arg(market_->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); + .arg(m_market->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); content += QString("Verbleibend: %1\n\n") - .arg(market_->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); + .arg(m_market->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); content += QString("(Einbehaltener Prozentsatz: %1 %)\n").arg(feeInPercent, 3); content += QString("(Maximal einbehaltener Betrag: %1 €)\n").arg(maxFeeInEuro, 3); @@ -196,12 +196,12 @@ void ReportDialog::onPrintSellerReceiptButtonClicked() QString posPrinterDevice = settings.value("global/posPrinterDevice", "").toString(); QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); - auto selModel = ui_.reportView->selectionModel(); + auto selModel = m_ui.reportView->selectionModel(); if (selModel->hasSelection() == false) return; auto indexes = selModel->selectedRows(); - auto& seller = market_->getSellers().at(indexes[0].row()); + std::ranges::sort(indexes); auto printerDevice = convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); @@ -214,18 +214,22 @@ void ReportDialog::onPrintSellerReceiptButtonClicked() printer = std::make_unique(); } - if (printer->isValid()) - printer->printSellerReceipt( - seller.get(), feeInPercent, maxFeeInEuro * 100, - settings.value("global/commune", "Dettingen").toString().toStdString()); -} - -void ReportDialog::onReportViewSelectionChanged(const QItemSelection& selected, - [[maybe_unused]] const QItemSelection& deselected) -{ - if (selected.size() > 0) { - ui_.printSellerReceiptButton->setEnabled(true); - } else { - ui_.printSellerReceiptButton->setEnabled(false); + if (printer->isValid()) { + for (const auto &index : indexes) { + auto &seller = m_market->getSellers().at(index.row()); + printer->printSellerReceipt( + seller.get(), feeInPercent, maxFeeInEuro * 100, + settings.value("global/commune", "Dettingen").toString().toStdString()); + } + } +} + +void ReportDialog::onReportViewSelectionChanged(const QItemSelection &selected, + [[maybe_unused]] const QItemSelection &deselected) +{ + if (selected.size() > 0) { + m_ui.printSellerReceiptButton->setEnabled(true); + } else { + m_ui.printSellerReceiptButton->setEnabled(false); } } diff --git a/src/gui/reportdialog.h b/src/gui/reportdialog.h index 18e1802..33713d8 100644 --- a/src/gui/reportdialog.h +++ b/src/gui/reportdialog.h @@ -25,9 +25,9 @@ class ReportDialog : public QDialog const QItemSelection& deselected); private: - Ui::ReportDialog ui_; - Marketplace* market_; - std::unique_ptr model_; + Ui::ReportDialog m_ui; + Marketplace* m_market; + std::unique_ptr m_model; }; #endif diff --git a/src/gui/reportdialog.ui b/src/gui/reportdialog.ui index d5d27b6..5ac21c8 100644 --- a/src/gui/reportdialog.ui +++ b/src/gui/reportdialog.ui @@ -19,7 +19,7 @@ - QAbstractItemView::SingleSelection + QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows diff --git a/src/gui/reportmodel.cpp b/src/gui/reportmodel.cpp index 65d386f..20acadd 100644 --- a/src/gui/reportmodel.cpp +++ b/src/gui/reportmodel.cpp @@ -5,16 +5,16 @@ #include ReportModel::ReportModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), market_(market) + : QAbstractTableModel(parent), m_market(market) { QSettings settings; - feeInPercent_ = settings.value("global/feeInPercent").toInt(); - maxFeeInCent_ = settings.value("global/maxFeeInEuro").toInt() * 100; + m_feeInPercent = settings.value("global/feeInPercent").toInt(); + m_maxFeeInCent = settings.value("global/maxFeeInEuro").toInt() * 100; } int ReportModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return static_cast(market_->getSellers().size()); + return static_cast(m_market->getSellers().size()); } int ReportModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 7; } @@ -52,10 +52,10 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (market_->getSellers().size() == 0) + if (m_market->getSellers().size() == 0) return QVariant(); - Seller* seller = market_->getSellers().at(index.row()).get(); + Seller* seller = m_market->getSellers().at(index.row()).get(); switch (index.column()) { case 0: @@ -71,7 +71,7 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const case 5: return seller->sumAsString().c_str(); case 6: - return paymentAsString(seller->sumInCents(), feeInPercent_, maxFeeInCent_).c_str(); + return paymentAsString(seller->sumInCents(), m_feeInPercent, m_maxFeeInCent).c_str(); default: return "???"; } diff --git a/src/gui/reportmodel.h b/src/gui/reportmodel.h index 36855da..1bb8d3c 100644 --- a/src/gui/reportmodel.h +++ b/src/gui/reportmodel.h @@ -15,9 +15,9 @@ class ReportModel : public QAbstractTableModel virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; private: - Marketplace* market_; - int feeInPercent_{}; - int maxFeeInCent_{}; + Marketplace* m_market; + int m_feeInPercent{}; + int m_maxFeeInCent{}; }; #endif diff --git a/src/gui/salemodel.cpp b/src/gui/salemodel.cpp index 93289e1..71dfae9 100644 --- a/src/gui/salemodel.cpp +++ b/src/gui/salemodel.cpp @@ -9,7 +9,7 @@ SaleModel::SaleModel(Marketplace* market, QObject* parent) : QAbstractItemModel(parent) { - marketplace_ = market; + m_marketplace = market; } QModelIndex SaleModel::index(int row, int column, const QModelIndex& parent) const @@ -18,7 +18,7 @@ QModelIndex SaleModel::index(int row, int column, const QModelIndex& parent) con return QModelIndex(); if (!parent.isValid()) { - Sale* sale = marketplace_->getSales().at(row).get(); + Sale* sale = m_marketplace->getSales().at(row).get(); return createIndex(row, column, sale); } else if (!parent.parent().isValid()) { Sale* sale = static_cast(parent.internalPointer()); @@ -49,10 +49,10 @@ QModelIndex SaleModel::parent(const QModelIndex& index) const sale = dynamic_cast(ent); if (sale) { - if (sale == rootItem.get()) + if (sale == m_rootItem.get()) return QModelIndex(); else { - return createIndex(-1, 0, rootItem.get()); + return createIndex(-1, 0, m_rootItem.get()); } } else { article = dynamic_cast(ent); @@ -132,7 +132,7 @@ int SaleModel::rowCount(const QModelIndex& parent) const return 0; if (!parent.isValid()) { - return marketplace_->getSales().size(); + return m_marketplace->getSales().size(); } else if (!parent.parent().isValid()) { Sale* sale = static_cast(parent.internalPointer()); return sale->getArticles().size(); @@ -167,7 +167,7 @@ QVariant SaleModel::headerData(int section, Qt::Orientation orientation, int rol void SaleModel::onBasketDataChanged() { emit beginResetModel(); - auto& sales = marketplace_->getSales(); + auto& sales = m_marketplace->getSales(); std::sort(sales.begin(), sales.end(), [](const auto& lhs, const auto& rhs) { return lhs->getTimestamp() > rhs->getTimestamp(); }); @@ -179,11 +179,11 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent) if (!parent.isValid()) { // remove complete sale emit beginRemoveRows(parent, row, row + count - 1); - auto& sale = marketplace_->getSales().at(row); + auto& sale = m_marketplace->getSales().at(row); sale->setState(Sale::State::DELETE); std::for_each(sale->getArticles().begin(), sale->getArticles().end(), [](auto& a) { a->setState(Article::State::DELETE); }); - marketplace_->storeToDb(); + m_marketplace->storeToDb(); emit endRemoveRows(); } else if (!parent.parent().isValid()) { @@ -199,7 +199,7 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent) sale->setState(Sale::State::DELETE); } emit beginRemoveRows(parent.parent(), 0, 0); - marketplace_->storeToDb(); + m_marketplace->storeToDb(); emit endRemoveRows(); } diff --git a/src/gui/salemodel.h b/src/gui/salemodel.h index 6675bd6..29a13bf 100644 --- a/src/gui/salemodel.h +++ b/src/gui/salemodel.h @@ -24,8 +24,8 @@ class SaleModel : public QAbstractItemModel void onBasketDataChanged(); private: - Marketplace* marketplace_; - std::unique_ptr rootItem{new Sale()}; + Marketplace* m_marketplace; + std::unique_ptr m_rootItem{new Sale()}; }; #endif diff --git a/src/gui/sellerdialog.cpp b/src/gui/sellerdialog.cpp index 9ecf63f..0b678fd 100644 --- a/src/gui/sellerdialog.cpp +++ b/src/gui/sellerdialog.cpp @@ -7,25 +7,25 @@ SellerDialog::SellerDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) { - ui_.setupUi(this); - ui_.editButton->setVisible(false); - market_ = dynamic_cast(parent)->getMarketplace(); - model_ = std::make_unique(market_, ui_.tableView); - ui_.tableView->setModel(model_.get()); - ui_.tableView->setColumnHidden(0, true); // hide the uuid - ui_.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user - connect(ui_.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked); - connect(ui_.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked); - connect(model_.get(), &SellerModel::duplicateSellerNo, this, + m_ui.setupUi(this); + m_ui.editButton->setVisible(false); + m_market = dynamic_cast(parent)->getMarketplace(); + m_model = std::make_unique(m_market, m_ui.tableView); + m_ui.tableView->setModel(m_model.get()); + m_ui.tableView->setColumnHidden(0, true); // hide the uuid + m_ui.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user + connect(m_ui.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked); + connect(m_ui.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked); + connect(m_model.get(), &SellerModel::duplicateSellerNo, this, &SellerDialog::on_model_duplicateSellerNo); - connect(ui_.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(m_ui.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SellerDialog::onSellerViewSelectionChanged); } void SellerDialog::on_newButton_clicked() { // Don't allow new seller if market has already started - if (market_->getSales().size() > 0) { + if (m_market->getSales().size() > 0) { QMessageBox(QMessageBox::Icon::Warning, "Hinweis", "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "können Sie keine Verkäufer mehr hinzufügen.", @@ -34,22 +34,22 @@ void SellerDialog::on_newButton_clicked() return; } - ui_.tableView->reset(); - ui_.tableView->model()->insertRows(ui_.tableView->model()->rowCount(), 1); - ui_.tableView->scrollToBottom(); - ui_.tableView->selectRow(ui_.tableView->model()->rowCount() - 1); - QModelIndex idx = ui_.tableView->model()->index(ui_.tableView->model()->rowCount() - 1, 2); - ui_.tableView->setCurrentIndex(idx); - ui_.tableView->edit(idx); + m_ui.tableView->reset(); + m_ui.tableView->model()->insertRows(m_ui.tableView->model()->rowCount(), 1); + m_ui.tableView->scrollToBottom(); + m_ui.tableView->selectRow(m_ui.tableView->model()->rowCount() - 1); + QModelIndex idx = m_ui.tableView->model()->index(m_ui.tableView->model()->rowCount() - 1, 2); + m_ui.tableView->setCurrentIndex(idx); + m_ui.tableView->edit(idx); } void SellerDialog::on_deleteButton_clicked() { - auto selModel = ui_.tableView->selectionModel(); + auto selModel = m_ui.tableView->selectionModel(); if (selModel->hasSelection() == false) return; - if (market_->getSales().size() > 0) { + if (m_market->getSales().size() > 0) { QMessageBox(QMessageBox::Icon::Warning, "Hinweis", "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "können Sie keine Verkäufer mehr löschen.", @@ -72,7 +72,7 @@ void SellerDialog::on_deleteButton_clicked() // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - ui_.tableView->model()->removeRow(iter->row()); + m_ui.tableView->model()->removeRow(iter->row()); } } @@ -102,8 +102,8 @@ void SellerDialog::onSellerViewSelectionChanged(const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) { if (selected.size() > 0) { - ui_.deleteButton->setEnabled(true); + m_ui.deleteButton->setEnabled(true); } else { - ui_.deleteButton->setEnabled(false); + m_ui.deleteButton->setEnabled(false); } } \ No newline at end of file diff --git a/src/gui/sellerdialog.h b/src/gui/sellerdialog.h index 63e53fb..ea87d4d 100644 --- a/src/gui/sellerdialog.h +++ b/src/gui/sellerdialog.h @@ -26,9 +26,9 @@ class SellerDialog : public QDialog void on_deleteButton_clicked(); void on_model_duplicateSellerNo(const QString& message); virtual void accept() override; - Ui::SellerDialog ui_; - Marketplace* market_; - std::unique_ptr model_; + Ui::SellerDialog m_ui; + Marketplace* m_market; + std::unique_ptr m_model; }; #endif \ No newline at end of file diff --git a/src/gui/sellermodel.cpp b/src/gui/sellermodel.cpp index 63b939e..a93f2ba 100644 --- a/src/gui/sellermodel.cpp +++ b/src/gui/sellermodel.cpp @@ -5,13 +5,13 @@ #include SellerModel::SellerModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), marketplace_(market) + : QAbstractTableModel(parent), m_marketplace(market) { } int SellerModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return marketplace_->getSellers().size(); + return m_marketplace->getSellers().size(); } int SellerModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 5; } @@ -21,10 +21,10 @@ QVariant SellerModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (marketplace_->getSellers().size() == 0) + if (m_marketplace->getSellers().size() == 0) return QVariant(); - Seller* seller = marketplace_->getSellers().at(index.row()).get(); + Seller* seller = m_marketplace->getSellers().at(index.row()).get(); switch (index.column()) { case 0: @@ -78,7 +78,7 @@ bool SellerModel::setData(const QModelIndex& index, const QVariant& value, int r if (role != Qt::EditRole) return false; - Seller* seller = marketplace_->getSellers().at(index.row()).get(); + Seller* seller = m_marketplace->getSellers().at(index.row()).get(); switch (index.column()) { case 0: @@ -88,11 +88,11 @@ bool SellerModel::setData(const QModelIndex& index, const QVariant& value, int r if (value.toInt() < 0) return false; auto iter = - std::find_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), + std::find_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(), [&value](const std::unique_ptr& s) { return value.toInt() == s->getSellerNo(); }); - if (iter != marketplace_->getSellers().end()) { + if (iter != m_marketplace->getSellers().end()) { emit duplicateSellerNo( "Die Verkäufernummer muss eindeutig sein.\n(Möglicherweise wird die Nummer von " "einem (ausgeblendeten) Eintrag, der zum Löschen vorgemerkt ist, verwendet.)"); @@ -123,8 +123,8 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent) { emit beginInsertRows(parent, row, row + count - 1); auto seller = std::make_unique(); - seller->setSellerNo(marketplace_->getNextSellerNo()); - marketplace_->getSellers().push_back(std::move(seller)); + seller->setSellerNo(m_marketplace->getNextSellerNo()); + m_marketplace->getSellers().push_back(std::move(seller)); emit endInsertRows(); return true; @@ -132,21 +132,21 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent) bool SellerModel::removeRows(int row, int count, const QModelIndex& parent) { - auto seller = marketplace_->getSellers().at(row).get(); + auto seller = m_marketplace->getSellers().at(row).get(); if (seller->getState() == Seller::State::NEW) { emit beginRemoveRows(parent, row, row + count - 1); - marketplace_->getSellers().erase( - std::remove_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), + m_marketplace->getSellers().erase( + std::remove_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(), [&seller](const std::unique_ptr& a) { return a->getId() == seller->getId(); }), - marketplace_->getSellers().end()); + m_marketplace->getSellers().end()); emit endRemoveRows(); return true; } else { emit beginRemoveRows(parent, row, row + count - 1); seller->setState(Seller::State::DELETE); - marketplace_->storeToDb(true); + m_marketplace->storeToDb(true); emit endRemoveRows(); return true; } diff --git a/src/gui/sellermodel.h b/src/gui/sellermodel.h index 32b6b7d..52b99a7 100644 --- a/src/gui/sellermodel.h +++ b/src/gui/sellermodel.h @@ -9,23 +9,23 @@ class SellerModel : public QAbstractTableModel { Q_OBJECT - public: - explicit SellerModel(Marketplace* market, QObject* parent = nullptr); - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; +public: + explicit SellerModel(Marketplace *market, QObject *parent = nullptr); + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, + virtual Qt::ItemFlags flags(const QModelIndex &index) const override; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - signals: - void duplicateSellerNo(const QString& message); +signals: + void duplicateSellerNo(const QString &message); - private: - Marketplace* marketplace_; +private: + Marketplace *m_marketplace; }; #endif diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index 57bcc81..7dfee89 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -3,9 +3,9 @@ #include "mainwindow.h" #include +#include #include #include -#include #include #include @@ -13,9 +13,9 @@ #include #include -SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) +SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { - ui_.setupUi(this); + m_ui.setupUi(this); QSettings settings{}; int cashPointNo = settings.value("global/cashPointNo").toInt(); @@ -26,25 +26,25 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par int maxFeeInEuro = settings.value("global/maxFeeInEuro").toInt(); if (parent) - market_ = dynamic_cast(parent)->getMarketplace(); + m_market = dynamic_cast(parent)->getMarketplace(); - ui_.cashPointNoSpinBox->setValue(cashPointNo); - ui_.communeEdit->setText(commune); - ui_.posPrinterDeviceEdit->setText(posPrinterDevice); - ui_.posPrinterEndpointEdit->setText(posPrinterEndpoint); - ui_.feePercentSpinBox->setValue(feeInPercent); - ui_.maxFeeSpinBox->setValue(maxFeeInEuro); + m_ui.cashPointNoSpinBox->setValue(cashPointNo); + m_ui.communeEdit->setText(commune); + m_ui.posPrinterDeviceEdit->setText(posPrinterDevice); + m_ui.posPrinterEndpointEdit->setText(posPrinterEndpoint); + m_ui.feePercentSpinBox->setValue(feeInPercent); + m_ui.maxFeeSpinBox->setValue(maxFeeInEuro); - connect(ui_.testPosPrinterButton, &QPushButton::clicked, this, [=]() { + connect(m_ui.testPosPrinterButton, &QPushButton::clicked, this, [this]() { using namespace std::string_literals; try { - if (ui_.posPrinterDeviceEdit->text().isEmpty()) { + if (m_ui.posPrinterDeviceEdit->text().isEmpty()) { PosPrinter printer; printer.printTest(); } else { - std::string posPrinterDeviceString = ui_.posPrinterDeviceEdit->text().toStdString(); + std::string posPrinterDeviceString = m_ui.posPrinterDeviceEdit->text().toStdString(); std::string posPrinterEndpointString = - ui_.posPrinterEndpointEdit->text().toStdString(); + m_ui.posPrinterEndpointEdit->text().toStdString(); try { auto printerDevice = @@ -55,7 +55,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par printer.printTest(); } - } catch (std::exception&) { + } catch (std::exception &) { QMessageBox(QMessageBox::Icon::Warning, "Falsche Eingabe", QString("Eingabeformat für Device (hexadezimale IDs): " ":\nBeispiel: 0416:5011\n " @@ -65,7 +65,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par return; } } - } catch (std::runtime_error& err) { + } catch (std::runtime_error &err) { QMessageBox(QMessageBox::Icon::Warning, "Bondrucker Fehler", QString("Test schlug fehl: ") + err.what(), QMessageBox::StandardButton::Ok, this) @@ -80,17 +80,17 @@ void SettingsDialog::accept() QSettings settings; int oldCashPointNo = settings.value("global/cashPointNo").toInt(); - int newCashPointNo = ui_.cashPointNoSpinBox->value(); + int newCashPointNo = m_ui.cashPointNoSpinBox->value(); - settings.setValue("global/commune", ui_.communeEdit->text().trimmed()); - settings.setValue("global/posPrinterDevice", ui_.posPrinterDeviceEdit->text().trimmed()); - settings.setValue("global/posPrinterEndpoint", ui_.posPrinterEndpointEdit->text().trimmed()); - settings.setValue("global/feeInPercent", ui_.feePercentSpinBox->value()); - settings.setValue("global/maxFeeInEuro", ui_.maxFeeSpinBox->value()); + settings.setValue("global/commune", m_ui.communeEdit->text().trimmed()); + settings.setValue("global/posPrinterDevice", m_ui.posPrinterDeviceEdit->text().trimmed()); + settings.setValue("global/posPrinterEndpoint", m_ui.posPrinterEndpointEdit->text().trimmed()); + settings.setValue("global/feeInPercent", m_ui.feePercentSpinBox->value()); + settings.setValue("global/maxFeeInEuro", m_ui.maxFeeSpinBox->value()); if (oldCashPointNo != newCashPointNo) { int result{0}; - if (market_ && market_->getSales().size() > 0) { + if (m_market && m_market->getSales().size() > 0) { result = QMessageBox(QMessageBox::Icon::Question, "Sind Sie sicher?", "Möchten Sie die Kassen-Nr wirklich ändern? Diese muss über alle " "Installationen hinweg eindeutig sein.", @@ -103,7 +103,7 @@ void SettingsDialog::accept() if (result == QMessageBox::Yes) { try { Database().updateCashPointNo(oldCashPointNo, newCashPointNo); - } catch (std::exception& ex) { + } catch (std::exception &ex) { std::string errMsg("Das Ändern der Kassen-Nr. ist fehlgeschlagen: "); errMsg.append(ex.what()); QMessageBox(QMessageBox::Icon::Critical, "Fehler", errMsg.c_str(), @@ -112,7 +112,7 @@ void SettingsDialog::accept() QDialog::accept(); return; } - settings.setValue("global/cashPointNo", ui_.cashPointNoSpinBox->value()); + settings.setValue("global/cashPointNo", m_ui.cashPointNoSpinBox->value()); } } diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h index a1a7026..541cc80 100644 --- a/src/gui/settingsdialog.h +++ b/src/gui/settingsdialog.h @@ -19,8 +19,8 @@ class SettingsDialog : public QDialog void accept() override; private: - Ui::SettingsDialog ui_; - Marketplace* market_{}; + Ui::SettingsDialog m_ui; + Marketplace* m_market{}; }; #endif diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 439c81e..0000000 --- a/src/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -subdir('core') -subdir('printer') -subdir('gui') diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index 9dfaa3e..6205d41 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -1,6 +1,6 @@ set(Boost_USE_STATIC_LIBS ON) -find_package(Boost 1.62 REQUIRED) +find_package(Boost 1.78 REQUIRED) if(WIN32) find_package(LIBUSB REQUIRED) @@ -9,15 +9,15 @@ else() pkg_check_modules(LibUSB REQUIRED libusb-1.0) endif() -set(PRINTER_SOURCES - posprinter.cpp - utils.cpp +add_library(printer STATIC) +target_sources(printer PRIVATE + posprinter.cpp + utils.cpp ) -add_library(printer STATIC ${PRINTER_SOURCES}) if(WIN32) target_link_libraries(printer core ${LIBUSB_1_LIBRARIES}) else() target_link_libraries(printer core ${LibUSB_LIBRARIES}) endif() -target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) +target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ${Boost_INCLUDE_DIRS}) diff --git a/src/printer/meson.build b/src/printer/meson.build deleted file mode 100644 index 64f0602..0000000 --- a/src/printer/meson.build +++ /dev/null @@ -1,9 +0,0 @@ -libusb = dependency('libusb-1.0') - -src = ['posprinter.cpp', 'utils.cpp'] - -printer_inc = include_directories('..') - -printer_lib = static_library('printer', src, dependencies: [libusb, core_dep]) - -printer_dep = declare_dependency(link_with : printer_lib, include_directories : printer_inc) diff --git a/src/printer/posprinter.cpp b/src/printer/posprinter.cpp index 368d483..61926fc 100644 --- a/src/printer/posprinter.cpp +++ b/src/printer/posprinter.cpp @@ -19,6 +19,8 @@ const std::string PosPrinter::Command::RIGHT_ALIGN = {0x1b, 0x61, 0x02}; const std::string PosPrinter::Command::FONT_SIZE_BIG = {0x1b, 0x21, 0x10}; const std::string PosPrinter::Command::FONT_SIZE_NORMAL = {0x1b, 0x21, 0x00}; const std::string PosPrinter::Command::FEED = {0x1b, 0x64, 0x03}; +const std::string PosPrinter::Command::PARTIAL_CUT = {0x1b, 0x69}; +const std::string PosPrinter::Command::FULL_CUT = {0x1b, 0x6d}; PosPrinter::PosPrinter() : PosPrinter(PrinterDevice()) {} @@ -202,7 +204,7 @@ void PosPrinter::printSellerReceipt(Seller* seller, const int percent, const int << marketFeeAsString(seller->sumInCents(), percent, maxFeeInCent) << "\n"; commandStream << "\nAuszahlung............. " << paymentAsString(seller->sumInCents(), percent, maxFeeInCent) << "\n"; - commandStream << Command::FEED; + commandStream << Command::FEED << Command::FEED; write(commandStream.str()); } diff --git a/src/printer/posprinter.h b/src/printer/posprinter.h index 4ddd083..1cdbff6 100644 --- a/src/printer/posprinter.h +++ b/src/printer/posprinter.h @@ -49,6 +49,8 @@ class PosPrinter static const std::string FONT_SIZE_BIG; static const std::string FONT_SIZE_NORMAL; static const std::string FEED; + static const std::string PARTIAL_CUT; + static const std::string FULL_CUT; }; private: diff --git a/subprojects/CMakeLists.txt b/subprojects/CMakeLists.txt deleted file mode 100644 index 6ef42eb..0000000 --- a/subprojects/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -if(NOT KIMA2_USE_EXTERNAL_JSON) - set(JSON_BuildTests OFF CACHE INTERNAL "") - add_subdirectory(nlohmann_json EXCLUDE_FROM_ALL) -endif() -#add_subdirectory(csv-parser) diff --git a/subprojects/csv-parser b/subprojects/csv-parser deleted file mode 160000 index ea547fd..0000000 --- a/subprojects/csv-parser +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ea547fdb16c7baf99bd9ced5febba52cc5da3ca3 diff --git a/subprojects/nlohmann_json b/subprojects/nlohmann_json deleted file mode 160000 index db78ac1..0000000 --- a/subprojects/nlohmann_json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit db78ac1d7716f56fc9f1b030b715f872f93964e4 diff --git a/subprojects/singleapplication/meson.build b/subprojects/singleapplication/meson.build deleted file mode 100644 index 1b43463..0000000 --- a/subprojects/singleapplication/meson.build +++ /dev/null @@ -1,27 +0,0 @@ -project('singleapplication') - -qt5 = import('qt5') -dep_qt5 = dependency('qt5', modules: ['Core', 'Widgets', 'Network']) - -singleapp_inc = include_directories('singleapplication.git') - -singleapp_moc = qt5.preprocess( - moc_headers: ['singleapplication.git/singleapplication.h', 'singleapplication.git/singleapplication_p.h'], - moc_extra_arguments: ['-DQAPPLICATION_CLASS=QApplication'], - dependencies: dep_qt5 -) - -singleapp_lib = static_library('SingleApplication', - ['singleapplication.git/singleapplication.cpp', 'singleapplication.git/singleapplication_p.cpp', singleapp_moc], - include_directories: singleapp_inc, - cpp_args : '-DQAPPLICATION_CLASS=QApplication', - dependencies: dep_qt5 -) - -singleapp_dep = declare_dependency( - include_directories: singleapp_inc, - link_with: singleapp_lib -) - -# On windows, SingleApplication needs to be linked against advapi32. This is -# done by adding 'advapi32' to cpp_winlibs, where it should be by default. diff --git a/subprojects/singleapplication/singleapplication.git b/subprojects/singleapplication/singleapplication.git deleted file mode 160000 index 3d152b0..0000000 --- a/subprojects/singleapplication/singleapplication.git +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3d152b03d872b99d7f36e8463ac253e41194a17a