Compare commits

...

31 Commits

Author SHA1 Message Date
Martin Brodbeck 0c7f071b9d include dir for boost added. 2024-03-05 14:38:02 +01:00
Martin Brodbeck d0c50c9b9a qsingleapplication version bumped 2024-01-23 11:25:07 +01:00
Martin Brodbeck a17cb22e05 2023 → 2024 2024-01-23 11:22:51 +01:00
Martin Brodbeck 205dac5326 nlohmann updateted to 3.11.3 2024-01-23 11:20:39 +01:00
Martin Brodbeck b0d2d6b284 update to version 1.8 2024-01-23 10:46:49 +01:00
Martin Brodbeck 7f11ba4e5d new version 1.8.0 2024-01-23 10:42:04 +01:00
Martin Brodbeck 32d0ec7749 Allow import of multiple sales at once. 2024-01-23 10:39:43 +01:00
Martin Brodbeck 54e5c70447 Changed minimum versions 2024-01-23 10:06:01 +01:00
Martin Brodbeck 379fd4a73c Lib references for Windows updated 2023-09-21 15:00:18 +02:00
Martin Brodbeck 8a94b53379 Push boost version. 2023-05-02 11:07:15 +02:00
Martin Brodbeck d9b13d0e1a README updated. 2023-05-02 11:03:22 +02:00
Martin Brodbeck 6f885dd64e more on metainfo 2023-04-28 10:29:39 +02:00
Martin Brodbeck 1a698a6cd2 metainfo added 2023-04-28 10:12:10 +02:00
Martin Brodbeck ac9ae8b34e Add metainfo 2023-04-28 10:08:02 +02:00
Martin Brodbeck 4385624988 Merge branch 'master' of ssh://git.rustysoft.de/martin/kima2 2023-04-26 12:47:45 +02:00
Martin Brodbeck 4cfd8d5572 2022 → 2023 2023-04-26 12:47:41 +02:00
Martin Brodbeck 528ae1ff31 use QUrl::fromLocalFile 2023-04-26 12:46:35 +02:00
Martin Brodbeck 649c26db4b Updated for Windows installation 2023-04-26 08:53:13 +02:00
Martin Brodbeck 13a1d26d96 description updated 2023-04-26 08:36:03 +02:00
Martin Brodbeck f898844c7c remove obsolete lstdc++fs flag 2023-04-25 16:19:27 +02:00
Martin Brodbeck e6b71a7e4d Get rid of csv-parser 2023-04-25 16:11:34 +02:00
Martin Brodbeck f4b4ccbbea Revert "Remove fmt dependency"
This reverts commit 8efdf7b6fe.
2023-04-25 15:22:06 +02:00
Martin Brodbeck e79a81797c Increase version number 2023-04-21 21:35:46 +02:00
Martin Brodbeck 8efdf7b6fe Remove fmt dependency 2023-04-21 21:33:59 +02:00
Martin Brodbeck a46e8d89c9 remove xlnt stuff 2023-01-18 19:41:53 +01:00
Martin Brodbeck 3e293ba447 updated 2023-01-18 17:08:09 +01:00
Martin Brodbeck 245e41bbf0 Push to new version. 2023-01-18 17:06:02 +01:00
Martin Brodbeck b0444112a8 seller menu simplified. 2023-01-18 17:05:21 +01:00
Martin Brodbeck c4ccd43b45 Push to new version 2023-01-18 16:46:44 +01:00
Martin Brodbeck 16745a248c Update manual 2023-01-18 16:46:30 +01:00
Martin Brodbeck 19ea7f27de Excel stuff removed. 2023-01-18 16:35:28 +01:00
27 changed files with 159 additions and 266 deletions

5
.gitmodules vendored
View File

@ -3,7 +3,4 @@
url = https://github.com/nlohmann/json.git url = https://github.com/nlohmann/json.git
[submodule "subprojects/singleapplication"] [submodule "subprojects/singleapplication"]
path = subprojects/singleapplication/singleapplication.git path = subprojects/singleapplication/singleapplication.git
url = https://github.com/itay-grudev/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

32
.vscode/settings.json vendored
View File

@ -65,7 +65,37 @@
"condition_variable": "cpp", "condition_variable": "cpp",
"mutex": "cpp", "mutex": "cpp",
"hash_map": "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", "C_Cpp.clang_format_path": "/usr/bin/clang-format",
"cmake.configureOnOpen": true, "cmake.configureOnOpen": true,

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.10)
project(kima2 VERSION 1.6.1) project(kima2 VERSION 1.8.0)
set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake")
@ -17,6 +17,7 @@ else()
endif() endif()
configure_file(config.h.in ${PROJECT_BINARY_DIR}/config.h) 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_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
@ -79,6 +80,8 @@ else(WIN32 AND NOT UNIX)
DESTINATION share/${PROJECT_NAME}) DESTINATION share/${PROJECT_NAME})
install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg" install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg"
DESTINATION share/icons/hicolor/scalable/apps) DESTINATION share/icons/hicolor/scalable/apps)
install(FILES de.rustysoft.kima2.metainfo.xml
DESTINATION share/metainfo)
endif (WIN32 AND NOT UNIX) endif (WIN32 AND NOT UNIX)
if( MINGW ) if( MINGW )
@ -95,10 +98,9 @@ if( MINGW )
${MINGW_PATH}/libwinpthread-1.dll ${MINGW_PATH}/libwinpthread-1.dll
${MINGW_PATH}/libsqlite3-0.dll ${MINGW_PATH}/libsqlite3-0.dll
${MINGW_PATH}/libusb-1.0.dll ${MINGW_PATH}/libusb-1.0.dll
${MINGW_PATH}/libxlnt.dll ${MINGW_PATH}/libicuuc73.dll
${MINGW_PATH}/libicuuc71.dll ${MINGW_PATH}/libicuin73.dll
${MINGW_PATH}/libicuin71.dll ${MINGW_PATH}/libicudt73.dll
${MINGW_PATH}/libicudt71.dll
${MINGW_PATH}/libpcre2-16-0.dll ${MINGW_PATH}/libpcre2-16-0.dll
${MINGW_PATH}/libpcre2-8-0.dll ${MINGW_PATH}/libpcre2-8-0.dll
${MINGW_PATH}/zlib1.dll ${MINGW_PATH}/zlib1.dll
@ -123,7 +125,7 @@ if( MINGW )
DESTINATION bin/platforms) DESTINATION bin/platforms)
#install(FILES ${MINGW_PATH}/../share/qt6/plugins/printsupport/windowsprintersupport.dll #install(FILES ${MINGW_PATH}/../share/qt6/plugins/printsupport/windowsprintersupport.dll
# DESTINATION bin/printsupport) # DESTINATION bin/printsupport)
install(FILES ${MINGW_PATH}/../share/qt5/translations/qtbase_de.qm install(FILES ${MINGW_PATH}/../share/qt6/translations/qtbase_de.qm
${MINGW_PATH}/../share/qt6/translations/qt_de.qm ${MINGW_PATH}/../share/qt6/translations/qt_de.qm
${MINGW_PATH}/../share/qt6/translations/qt_help_de.qm ${MINGW_PATH}/../share/qt6/translations/qt_help_de.qm
${MINGW_PATH}/../share/qt6/translations/qtmultimedia_de.qm ${MINGW_PATH}/../share/qt6/translations/qtmultimedia_de.qm

View File

@ -1,4 +1,4 @@
Copyright © 2018-2022 Martin Brodbeck Copyright © 2018-2024 Martin Brodbeck
Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der
zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt,

View File

@ -19,14 +19,11 @@ Ubuntu, Windows) angeboten. Bitte die Hinweise dort beachten.
### Selbst compilieren ### Selbst compilieren
KIMA2 benötigt folgende Libraries: KIMA2 benötigt folgende Libraries:
* Qt 6 * Qt 6
* boost >= 1.62 * boost >= 1.80
* libusb-1.0 * libusb-1.0
* xlnt >= 1.5.0
* nlohmann-json (als 3rdparty submodule vorhanden) * nlohmann-json (als 3rdparty submodule vorhanden)
* csv-parser (als 3rdparty submodule vorhanden)
Da Features aus C++20 verwendet werden sowie std::filesystem, sollte als Compiler mindestens Da Features aus C++20 verwendet werden, sollte als Compiler mindestens GCC 12 verwendet werden.
GCC 12 verwendet werden.
Die Installationsschritte unter Linux sind wie folgt: Die Installationsschritte unter Linux sind wie folgt:
``` ```

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>de.rustysoft.kima2</id>
<name>KIMA2</name>
<summary>A small cash point program for childrens stuff markets</summary>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<releases>
<release version="@PROJECT_VERSION@" type="stable" date="2024-01-23" />
</releases>
<description>
<p>
A small cash point program for children's stuff markets. German language only.
</p>
</description>
<launchable type="desktop-id">de.rustysoft.kima2.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://rustysoft.de/images/software/kima2/screenshot.png</image>
</screenshot>
</screenshots>
</component>

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
project('kima2', 'cpp', default_options : ['cpp_std=c++20'], version : '1.6.1') project('kima2', 'cpp', default_options : ['cpp_std=c++20'], version : '1.8.0')
conf_data = configuration_data() conf_data = configuration_data()
conf_data.set('PROJECT_VERSION', '"' + meson.project_version() + '"') conf_data.set('PROJECT_VERSION', '"' + meson.project_version() + '"')

View File

@ -1,12 +1,12 @@
# Maintainer: Martin Brodbeck <martin at brodbeck-online dot de> # Maintainer: Martin Brodbeck <martin at brodbeck-online dot de>
pkgname=kima2 pkgname=kima2
pkgver=1.6.1 pkgver=1.7.1
pkgrel=1 pkgrel=1
pkgdesc="A small cash point program for children's things markets (German only)" pkgdesc="A small cash point program for children's things markets (German only)"
arch=('i686' 'x86_64') arch=('i686' 'x86_64')
url="http://www.rustysoft.de/software/kima2" url="http://www.rustysoft.de/software/kima2"
license=('custom') license=('custom')
depends=('glibc' 'libusb' 'qt6-base' 'sqlite3' 'xlnt') depends=('glibc' 'libusb' 'qt6-base' 'sqlite3')
makedepends=('boost>=1.62') makedepends=('boost>=1.62')
source=(git+https://git.rustysoft.de/martin/kima2) source=(git+https://git.rustysoft.de/martin/kima2)
sha256sums=('SKIP') sha256sums=('SKIP')

View File

@ -3,8 +3,8 @@ Type=Application
Name=KIMA2 Name=KIMA2
GenericName=Cash Point Program GenericName=Cash Point Program
GenericName[de]=Kassenprogramm GenericName[de]=Kassenprogramm
Comment=A small cash point program Comment=A small cash point program for children's stuff markets
Comment[de]=Ein kleines Kassenprogramm Comment[de]=Ein kleines Kassenprogramm für Kindersachenmärkte
Exec=kima2 Exec=kima2
Icon=kima2 Icon=kima2
Categories=Office; Categories=Office;

View File

@ -13,7 +13,6 @@ BuildRequires: boost-date-time
BuildRequires: sqlite-devel BuildRequires: sqlite-devel
BuildRequires: libusb-devel BuildRequires: libusb-devel
BuildRequires: qt5-qtdeclarative-devel BuildRequires: qt5-qtdeclarative-devel
#BuildRequires: pkgconfig(xlnt)
#BuildRequires: pkgconfig(pthreads) #BuildRequires: pkgconfig(pthreads)
%description %description

View File

@ -1,22 +1,12 @@
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.62 REQUIRED) find_package(Boost 1.78 REQUIRED)
find_package(SQLite3 REQUIRED) find_package(SQLite3 REQUIRED)
# Because csv-parser needs threads: # Because csv-parser needs threads:
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(fmt) find_package(fmt)
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 set(CORE_SOURCES
database.cpp database.cpp
entity.cpp entity.cpp
@ -26,7 +16,6 @@ set(CORE_SOURCES
article.cpp article.cpp
sale.cpp sale.cpp
marketplace.cpp marketplace.cpp
excelreader.cpp
csvreader.cpp csvreader.cpp
jsonutil.cpp jsonutil.cpp
utils.cpp utils.cpp
@ -34,12 +23,12 @@ set(CORE_SOURCES
add_library(core STATIC ${CORE_SOURCES}) add_library(core STATIC ${CORE_SOURCES})
target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/csv-parser/single_include) #target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/csv-parser/single_include)
if (WIN32) if (WIN32)
target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARY} Threads::Threads fmt::fmt) target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json fmt::fmt)
target_link_libraries(core PRIVATE bcrypt) target_link_libraries(core PRIVATE bcrypt)
else() else()
target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARIES} Threads::Threads fmt::fmt) target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json fmt::fmt)
endif() endif()
target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)

View File

@ -3,7 +3,8 @@
#include <fstream> #include <fstream>
#include <csv.hpp> // #include <csv.hpp>
#include <boost/algorithm/string.hpp>
#ifdef DELETE #ifdef DELETE
#undef DELETE #undef DELETE
@ -13,17 +14,16 @@ 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) #if defined(_WIN64) || defined(_WIN32)
// Windows: Somhow this is necessary in order to open file names with umlauts // Windows: Somhow this is necessary in order to open file names with umlauts
auto wide = filePath.wstring(); auto wide = filePath.wstring();
std::string fileName(wide.begin(), wide.end()); std::string fileName(wide.begin(), wide.end());
csv::CSVReader csvReader(fileName, format); std::ifstream infile(fileName);
#else #else
csv::CSVReader csvReader(filePath.string(), format); // csv::CSVReader csvReader(filePath.string(), format);
std::ifstream infile(filePath.string());
#endif #endif
for (auto &seller : market->getSellers()) { for (auto &seller : market->getSellers()) {
@ -32,28 +32,35 @@ std::size_t CsvReader::readSellersFromFile(const fs::path &filePath, Marketplace
market->storeToDb(true); market->storeToDb(true);
for (csv::CSVRow &row : csvReader) { std::string line;
if (!row[0].is_int()) {
while (getline(infile, line)) {
std::vector<std::string> strs;
boost::split(strs, line, boost::is_any_of(";"));
auto seller = std::make_unique<Seller>();
try {
int sellerNo = std::stoi(strs[0]);
seller->setSellerNo(sellerNo);
} catch (std::invalid_argument const &ex) {
continue; continue;
} }
auto seller = std::make_unique<Seller>(); if (isNumber(strs[1]))
seller->setSellerNo(row[0].get<int>()); seller->setNumArticlesOffered(std::stoi(strs[1]));
if (row[1].is_int()) { else
seller->setNumArticlesOffered(row[1].get<int>());
} else {
seller->setNumArticlesOffered(0); seller->setNumArticlesOffered(0);
}
// If both, first name and last name, are empty, use N. N. // If both, first name and last name, are empty, use N. N.
// Else, use the real values. // Else, use the real values.
if (row[2].get<std::string>().empty() && row[3].get<std::string>().empty()) { if (strs[2].empty() && strs[2].empty()) {
seller->setFirstName("N."); seller->setFirstName("N.");
seller->setLastName("N."); seller->setLastName("N.");
} else { } else {
std::string firstName = row[2].get<std::string>(); std::string firstName = strs[2];
seller->setFirstName(trim(firstName)); seller->setFirstName(trim(firstName));
std::string lastName = row[3].get<std::string>(); std::string lastName = strs[3];
seller->setLastName(trim(lastName)); seller->setLastName(trim(lastName));
} }

View File

@ -1,72 +0,0 @@
#include "excelreader.h"
#include "utils.h"
#include <fstream>
#include <xlnt/xlnt.hpp>
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;
}
auto seller = std::make_unique<Seller>();
seller->setSellerNo(row[0].value<int>());
seller->setNumArticlesOffered(row[1].value<int>());
// If both, first name and last name, are empty, use N. N.
// Else, use the real values.
if (row[2].value<std::string>().empty() && row[3].value<std::string>().empty()) {
seller->setFirstName("N.");
seller->setLastName("N.");
} else {
std::string firstName = row[2].value<std::string>();
seller->setFirstName(trim(firstName));
std::string lastName = row[3].value<std::string>();
seller->setLastName(trim(lastName));
}
market->getSellers().push_back(std::move(seller));
}
// Add one additional seller "RESERVE RESERVE"
auto seller = std::make_unique<Seller>();
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) {
auto seller = std::make_unique<Seller>();
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
}

View File

@ -1,19 +0,0 @@
#ifndef EXCEL_READER_H
#define EXCEL_READER_H
#include "marketplace.h"
#include "seller.h"
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
class ExcelReader
{
public:
static std::size_t readSellersFromFile(const std::filesystem::path &filePath,
Marketplace *market);
};
#endif

View File

@ -102,8 +102,10 @@ void JsonUtil::importSales(const std::filesystem::path &filePath, Marketplace *m
int source_no = jsonValues["source_no"]; int source_no = jsonValues["source_no"];
if (source_no == cashPointNo) { if (source_no == cashPointNo) {
throw std::runtime_error("Die Kassen-Nr. der zu imporierenden Daten wird von dieser Kasse " std::string ret = "Die Kassen-Nr. ";
"hier bereits verwendet."); 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->setSalesToDelete(jsonValues["source_no"]);

View File

@ -61,3 +61,10 @@ bool case_insensitive_match(std::string s1, std::string s2)
return true; // The strings are same return true; // The strings are same
return false; // not matched 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();
}

View File

@ -10,5 +10,6 @@ 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 &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 &trim(std::string &str, const std::string &chars = "\t\n\v\f\r ");
bool case_insensitive_match(std::string s1, std::string s2); bool case_insensitive_match(std::string s1, std::string s2);
bool isNumber(const std::string &str);
#endif #endif

View File

@ -42,7 +42,7 @@ add_executable(kima2 ${GUI_SOURCES} kima2.rc)
target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR}) target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR})
target_include_directories(kima2 PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git) 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 Qt5::Widgets Qt5::PrintSupport Qt5::Network stdc++fs)
target_link_libraries(kima2 core printer Qt::Core Qt::PrintSupport Qt::Network stdc++fs) target_link_libraries(kima2 core printer Qt::Core Qt::PrintSupport Qt::Network)
if(WIN32) if(WIN32)
set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows") set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows")

View File

@ -9,7 +9,6 @@
#include <config.h> #include <config.h>
#include <core/csvreader.h> #include <core/csvreader.h>
#include <core/excelreader.h>
#include <core/jsonutil.h> #include <core/jsonutil.h>
#include <core/utils.h> #include <core/utils.h>
#include <printer/posprinter.h> #include <printer/posprinter.h>
@ -100,14 +99,13 @@ MainWindow::MainWindow()
for (auto location : locations) { for (auto location : locations) {
if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) { if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) {
QDesktopServices::openUrl( QDesktopServices::openUrl(
QUrl(QString("file:///") + location + QString("/Benutzerhandbuch.pdf"), QUrl::fromLocalFile(location + QString("/Benutzerhandbuch.pdf")));
QUrl::TolerantMode));
} }
} }
}); });
connect(m_ui.licenseAction, &QAction::triggered, this, [this]() { connect(m_ui.licenseAction, &QAction::triggered, this, [this]() {
QString licenseText( QString licenseText(
"Copyright © 2018-2022 Martin Brodbeck\n\n" "Copyright © 2018-2024 Martin Brodbeck\n\n"
"Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der " "Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der "
"zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, " "zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, "
"sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, " "sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, "
@ -137,12 +135,8 @@ MainWindow::MainWindow()
this->setWindowTitle("KIMA2 - Kasse Nr. " + this->setWindowTitle("KIMA2 - Kasse Nr. " +
QSettings().value("global/cashPointNo").toString()); QSettings().value("global/cashPointNo").toString());
}); });
connect(m_ui.importSellerExcelAction, &QAction::triggered, this, connect(m_ui.importSellerAction, &QAction::triggered, this,
&MainWindow::onImportSellerExcelActionTriggered); &MainWindow::onImportSellerActionTriggered);
connect(m_ui.importSellerJsonAction, &QAction::triggered, this,
&MainWindow::onImportSellerJsonActionTriggered);
connect(m_ui.exportSellerJsonAction, &QAction::triggered, this,
&MainWindow::onExportSellerJsonActionTriggered);
connect(m_ui.exportSalesJsonAction, &QAction::triggered, this, connect(m_ui.exportSalesJsonAction, &QAction::triggered, this,
&MainWindow::onExportSalesJsonActionTriggered); &MainWindow::onExportSalesJsonActionTriggered);
connect(m_ui.importSalesJsonAction, &QAction::triggered, this, connect(m_ui.importSalesJsonAction, &QAction::triggered, this,
@ -345,7 +339,8 @@ void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked)
m_ui.basketView->model()->removeRow(iter->row()); m_ui.basketView->model()->removeRow(iter->row());
} }
m_ui.basketSumLabel->setText(m_marketplace->getBasketSumAsString().c_str()); // Update basket sum m_ui.basketSumLabel->setText(
m_marketplace->getBasketSumAsString().c_str()); // Update basket sum
m_ui.sellerNoEdit->setFocus(); m_ui.sellerNoEdit->setFocus();
} }
@ -428,7 +423,8 @@ void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked)
dynamic_cast<BasketModel *>(m_ui.basketView->model())->cancelSale(); dynamic_cast<BasketModel *>(m_ui.basketView->model())->cancelSale();
m_ui.basketSumLabel->setText(m_marketplace->getBasketSumAsString().c_str()); // Update basket sum m_ui.basketSumLabel->setText(
m_marketplace->getBasketSumAsString().c_str()); // Update basket sum
m_ui.sellerNoEdit->setFocus(); m_ui.sellerNoEdit->setFocus();
} }
@ -445,7 +441,7 @@ void MainWindow::onAbout()
">info@rustysoft.de</a>&gt;</p>"); ">info@rustysoft.de</a>&gt;</p>");
} }
void MainWindow::onImportSellerExcelActionTriggered() void MainWindow::onImportSellerActionTriggered()
{ {
if (!m_marketplace->getSales().empty()) { if (!m_marketplace->getSales().empty()) {
QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich",
@ -455,9 +451,9 @@ void MainWindow::onImportSellerExcelActionTriggered()
return; return;
} }
auto filename = QFileDialog::getOpenFileName( auto filename =
this, "Verkäufer importieren", QString(), QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(),
"Alle unterstützte Dateien (*.xlsx *.csv);;Excel Dateien (*.xlsx);;CSV Dateien (*.csv)"); "Alle unterstützte Dateien (*.csv);;CSV Dateien (*.csv)");
if (filename.isEmpty()) if (filename.isEmpty())
return; return;
@ -469,86 +465,19 @@ void MainWindow::onImportSellerExcelActionTriggered()
#endif #endif
std::size_t numImported{}; std::size_t numImported{};
if (case_insensitive_match(filePath.extension().string(), std::string(".xlsx"))) { numImported = CsvReader::readSellersFromFile(filePath, m_marketplace.get());
try {
numImported = ExcelReader::readSellersFromFile(filePath, m_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, m_marketplace.get());
}
updateStatLabel(); updateStatLabel();
using namespace std::string_literals; using namespace std::string_literals;
std::ostringstream msg; std::ostringstream msg;
msg << "Aus der Excel/CSV-Datei wurden <b>"s << std::to_string(numImported) msg << "Aus der CSV-Datei wurden <b>"s << std::to_string(numImported)
<< "</b> Verkäufer importiert."; << "</b> Verkäufer importiert.";
QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert", QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert",
msg.str().c_str(), QMessageBox::StandardButton::Ok, this) msg.str().c_str(), QMessageBox::StandardButton::Ok, this)
.exec(); .exec();
} }
void MainWindow::onImportSellerJsonActionTriggered()
{
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();
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, m_marketplace.get());
updateStatLabel();
using namespace std::string_literals;
std::ostringstream msg;
msg << "Aus der JSON-Datei wurden <b>"s << std::to_string(numImported)
<< "</b> 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, m_marketplace.get());
}
void MainWindow::onExportSalesJsonActionTriggered() void MainWindow::onExportSalesJsonActionTriggered()
{ {
QSettings settings; QSettings settings;
@ -575,27 +504,30 @@ void MainWindow::onImportSalesJsonActionTriggered()
{ {
QSettings settings; QSettings settings;
auto filename = QFileDialog::getOpenFileName(this, "Umsätze/Transaktionen importieren", auto filenames = QFileDialog::getOpenFileNames(this, "Umsätze/Transaktionen importieren",
QString(), "JSON Dateien (*.json)"); QString(), "JSON Dateien (*.json)");
if (filename.isEmpty()) if (filenames.isEmpty())
return; return;
for(auto filename: filenames) {
#if defined(_WIN64) || defined(_WIN32) #if defined(_WIN64) || defined(_WIN32)
fs::path filePath(filename.toStdWString()); fs::path filePath(filename.toStdWString());
#else #else
fs::path filePath(filename.toStdString()); fs::path filePath(filename.toStdString());
#endif #endif
delete m_ui.salesView->model(); delete m_ui.salesView->model();
try { try {
JsonUtil::importSales(filePath, m_marketplace.get(), JsonUtil::importSales(filePath, m_marketplace.get(),
settings.value("global/cashPointNo").toInt()); settings.value("global/cashPointNo").toInt());
} catch (std::runtime_error &err) { } catch (std::runtime_error &err) {
QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok,
this) this)
.exec(); .exec();
}
} }
setSaleModel(); setSaleModel();
updateStatLabel(); updateStatLabel();
} }

View File

@ -39,9 +39,7 @@ class MainWindow : public QMainWindow
void checkSellerNo(bool ctrlPressed = false); void checkSellerNo(bool ctrlPressed = false);
void onPaidButtonTriggered(); void onPaidButtonTriggered();
void onGivenSpinBoxValueChanged(double value); void onGivenSpinBoxValueChanged(double value);
void onImportSellerExcelActionTriggered(); void onImportSellerActionTriggered();
void onImportSellerJsonActionTriggered();
void onExportSellerJsonActionTriggered();
void onExportSalesJsonActionTriggered(); void onExportSalesJsonActionTriggered();
void onImportSalesJsonActionTriggered(); void onImportSalesJsonActionTriggered();
void setSaleModel(); void setSaleModel();

View File

@ -423,7 +423,7 @@ drucken</string>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>817</width> <width>817</width>
<height>30</height> <height>24</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_Datei"> <widget class="QMenu" name="menu_Datei">
@ -440,16 +440,8 @@ drucken</string>
<property name="title"> <property name="title">
<string>&amp;Verkäufer</string> <string>&amp;Verkäufer</string>
</property> </property>
<widget class="QMenu" name="importSellerMenu">
<property name="title">
<string>Importieren</string>
</property>
<addaction name="importSellerExcelAction"/>
<addaction name="importSellerJsonAction"/>
</widget>
<addaction name="actionEditSeller"/> <addaction name="actionEditSeller"/>
<addaction name="importSellerMenu"/> <addaction name="importSellerAction"/>
<addaction name="exportSellerJsonAction"/>
</widget> </widget>
<widget class="QMenu" name="menuHilfe"> <widget class="QMenu" name="menuHilfe">
<property name="title"> <property name="title">
@ -513,9 +505,9 @@ drucken</string>
<string>Exportieren für andere Kasse (JSON)</string> <string>Exportieren für andere Kasse (JSON)</string>
</property> </property>
</action> </action>
<action name="importSellerExcelAction"> <action name="importSellerActionX">
<property name="text"> <property name="text">
<string>Aus Excel/CSV-Datei (initial)</string> <string>Aus CSV-Datei (initial)</string>
</property> </property>
</action> </action>
<action name="importSellerJsonAction"> <action name="importSellerJsonAction">
@ -548,6 +540,11 @@ drucken</string>
<string>Lizenz</string> <string>Lizenz</string>
</property> </property>
</action> </action>
<action name="importSellerAction">
<property name="text">
<string>Importieren (aus CSV-Datei)</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1,6 +1,6 @@
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.62 REQUIRED) find_package(Boost 1.78 REQUIRED)
if(WIN32) if(WIN32)
find_package(LIBUSB REQUIRED) find_package(LIBUSB REQUIRED)
@ -20,4 +20,4 @@ if(WIN32)
else() else()
target_link_libraries(printer core ${LibUSB_LIBRARIES}) target_link_libraries(printer core ${LibUSB_LIBRARIES})
endif() endif()
target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ${Boost_INCLUDE_DIRS})

@ -1 +0,0 @@
Subproject commit ea547fdb16c7baf99bd9ced5febba52cc5da3ca3

@ -1 +1 @@
Subproject commit bc889afb4c5bf1c0d8ee29ef35eaaf4c8bef8a5d Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03

@ -1 +1 @@
Subproject commit a3ed916f591c300e97b873fde36863fa37b49fa9 Subproject commit 8c48163c4d3fbba603cfe8a5b94046c9dad71825