commit 5295a82aa377ce4e972513ead563053527f0ebe9 Author: PANIK\chris Date: Tue Aug 5 22:37:51 2025 +0200 first re-commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da1d64b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.user +build/ diff --git a/libMiniCash/README.md b/libMiniCash/README.md new file mode 100644 index 0000000..bbd771f --- /dev/null +++ b/libMiniCash/README.md @@ -0,0 +1,11 @@ +# libMiniCash README.md + +## about +`libMiniCash` enthält die von den Kassensystemen 'miniCash' und 'miniCash.connect' gemeinsam verwendete Funktionalität als Dll. + +## Funktionsbereiche +- Datenmodelle und Datentypen +- Eingabe der Verkäufe +- Setup-Dialoge +- Erzeugung der Abrechnungen +- Druckersteuerung diff --git a/libMiniCash/libMiniCash.h b/libMiniCash/libMiniCash.h new file mode 100644 index 0000000..b4d8c0f --- /dev/null +++ b/libMiniCash/libMiniCash.h @@ -0,0 +1,185 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef LIBMINICASH_H +#define LIBMINICASH_H + +#include "libMiniCash_global.h" + + +/** + +@mainpage libMiniCash + +@section xxx Die libMiniCash Dll + +libMiniCash enthält die von den Kassensystemen 'miniCash' und 'miniCash.connect' +gemeinsam verwendete Funktionalität als Dll. + +@subsection xxz Funktionsbereiche + - Datenmodelle und Datentypen + - Eingabe der Verkäufe + - Setup-Dialoge + - Erzeugung der Abrechnungen + - Druckersteuerung + +@section sec3 Ideen & TODO: + +@subsection sec3_1 Ideen: + + - oberfläche erneuern? + - beim server hochfahren: daten abholen, puffern, wahlweise via usb + - adressverwaltung einbeziehen, für personalisierte Abrechnungen + +@subsection sec3_2 TODO für 1.0: + + - wlan first, disk backup + - netzprotocol, erfinden oder json/xml + - splash screen? + - fehler dulden wg. kassenschlange, hinterher kennzeichnen + - server security: only allowed hosts + - auto feeder zum testen + - data: kasse|count|cust|pos|price|timestamp + - protocol: [...]: transaction, -: storno; + - kasse: semi blocking (soll genau was heissen, chris?) + - Beim einlesen mitzählen, Ergebnis in den statusbar. + - suche bei Storno mit mehreren Feldern zulassen + - setup.exe bauen + + +@subsection sec3_3 TODO für 0.9: + + - backup über WLAN -> Adhoc Netzwerk einrichten + - layouts verwenden + - handbuch schreiben + - vernünftiger setup-dialog mit abbruch möglichkeit + + +@subsection sec3_4 TODO für 0.8: + + - Auswertung: laden und speichern : + - Printbuttons ab/an schalten : + - Kurzanleitung : + - programm muss immer starten, fehlerloop verwirrt nur + QUARK: Programm _kann_ ohne Laufwerk nicht starten! + - help about : mit hinweis auf sourceworx & logo + - fonts vereinheitlichen + - statusbar einbinden ?!? + - Caps lock abschalten, wie ? + +*/ + +/** + * @brief der namespace miniCash enthält Definitionen und Konstanten. + * + * Hier stehen die Konstanten für + * - die HTML-Templates zur Erzeugung der Print-Files + * - Die Dateipfade + * - die RegEx zur Eingabekontrolle + * - Copyright-Hinweise + * Der Namespace gilt Anwendungsübergreifend sowohl für die Library als + * auch die damit implementierten Anwendungen. + */ + + +namespace miniCash +{ +/// networkstate +typedef enum +{ + Disabled = 0, + UnConnected, + Error, + Connected, + IsServer, + ServerReady, + CStateSize +} CState; + +[[maybe_unused]] constexpr static const char* cstDisabled = " "; +[[maybe_unused]] constexpr static const char* cstUnConnected = "--Ready"; +[[maybe_unused]] constexpr static const char* cstError = "Error"; +[[maybe_unused]] constexpr static const char* cstConnected = "Connected"; +[[maybe_unused]] constexpr static const char* cstIsServer = "Ready"; +[[maybe_unused]] constexpr static const char* cstServerReady = "Connected"; + +[[maybe_unused]] static const char* const icnConnected = ":images/connect.png"; +[[maybe_unused]] static const char* const icnUnConnected = ":images/disconnect.png"; +[[maybe_unused]] static const char* const icnServer = ":images/_server.png"; + +/// basics +[[maybe_unused]] static const char* const orgName = "source::worx"; +[[maybe_unused]] static const char* const domainName = "sourceworx.org"; + +/// eigene KassenID +[[maybe_unused]] static const char* const keySelfID = "selfID"; +[[maybe_unused]] static const char* const selfID = "1"; + +/// transaktionszähler, vormals die hässliche Zähldatei +[[maybe_unused]] static const char* const keyTransCount = "TransCount"; +[[maybe_unused]] static const char* const transCount = "1"; + +/// file handling +[[maybe_unused]] static const char* const keyMobileDrive = "MobileDrive"; +[[maybe_unused]] static const char* const mobileDrive = "E:/"; +[[maybe_unused]] static const char* const dataDir = "/miniCash.data/"; +[[maybe_unused]] static const char* const filetype = ".mcd"; + +/// address handling +[[maybe_unused]] static const char* const keyAddressFile = "AddressFile"; + +/// defaults +[[maybe_unused]] static const char* const keyProfit = "Profit"; +[[maybe_unused]] static const char* const profit = "15"; + +[[maybe_unused]] static const char* const keyFooterText = "FooterText"; + +/// networking +[[maybe_unused]] static const char* const keyIsTcpReceiver = "isTcpReceiver"; +[[maybe_unused]] static const bool isTcpReceiver = false; + +[[maybe_unused]] static const char* const keyIsTcpSender = "isTcpSender"; +[[maybe_unused]] static const bool isTcpSender = true; +[[maybe_unused]] static const int senderTimeout = 60000; + +[[maybe_unused]] static const char* const keyReceiverPort = "receiverPort"; +[[maybe_unused]] static const int receiverPort = 7077; + +[[maybe_unused]] static const char* const keyReceiverHost = "receiverHost"; + + +/// resource handling +[[maybe_unused]] static const char* const tplFinal = ":templates/tplFinal.html"; +[[maybe_unused]] static const char* const tplPayoff = ":templates/tplPayoff.html"; +[[maybe_unused]] static const char* const tplReceipt = ":templates/tplReceipt.html"; + +/// input filter +[[maybe_unused]] static const char* const fCustID = "^[0-9]{4}$"; +[[maybe_unused]] static const char* const fItemNo = "^[0-9]{1,3}$"; +[[maybe_unused]] static const char* const fPrice = "^[0-9]{1,3}(,[0-9]{1,2})?$"; + +[[maybe_unused]] static const char* const fSrcDrive = "^[e-zE-Z]$"; +[[maybe_unused]] static const char* const fProfit = "^[0-9]{2}$"; +[[maybe_unused]] static const char* const fFromID = "^1[1-3][0-9]{2}$"; +[[maybe_unused]] static const char* const fToID = "^1[1-3][0-9]{2}$"; + +/// misc +[[maybe_unused]] static const char* const versionLib = "Version 0.8.42, 14.07.2022"; +[[maybe_unused]] static const char* const copyright = "miniCash, © 2013-2022 Christoph Holzheuer c.holzheuer@sourceworx.org "; +[[maybe_unused]] static const char* const copyShort = "miniCash, © 2013-2022\nc.holzheuer@sourceworx.org "; + +} + + +#endif // LIBMINICASH_H diff --git a/libMiniCash/libMiniCash.pro b/libMiniCash/libMiniCash.pro new file mode 100644 index 0000000..b264eba --- /dev/null +++ b/libMiniCash/libMiniCash.pro @@ -0,0 +1,75 @@ +QT += printsupport core gui network widgets + +TEMPLATE = lib +TARGET = libMiniCash +DEFINES += LIBMINICASH_LIBRARY + +DESTDIR = $$OUT_PWD/../common + +CONFIG += c++17 + +SOURCES += \ + libminicash.cpp \ + mcbillingview.cpp \ + mcformwidget.cpp \ + mcinputview.cpp \ + mcloaddialog.cpp \ + mcmainwindowbase.cpp \ + mcnetworkdialog.cpp \ + mcnetworkwidget.cpp \ + mcprinter.cpp \ + mcreceiver.cpp \ + mcsalesitemmap.cpp \ + mcsalesmodel.cpp \ + mcsalessummary.cpp \ + mcsender.cpp \ + mcsetupdialog.cpp \ + mctransactionview.cpp \ + mctreeview.cpp \ + mcvendorsdialog.cpp \ + swdriveselector.cpp \ + swsidebar.cpp + +HEADERS += \ + libMiniCash_global.h \ + libminicash.h \ + mcbillingview.h \ + mcformwidget.h \ + mcinputview.h \ + mcloaddialog.h \ + mcmainwindowbase.h \ + mcnetworkdialog.h \ + mcnetworkwidget.h \ + mcprinter.h \ + mcreceiver.h \ + mcsalesitem.h \ + mcsalesitemmap.h \ + mcsalesmodel.h \ + mcsalessummary.h \ + mcsender.h \ + mcsetupdialog.h \ + mctransactionview.h \ + mctreeview.h \ + mcvendorsdialog.h \ + swdriveselector.h \ + swsidebar.h + +# Default rules for deployment. +unix { + target.path = /usr/lib +} +!isEmpty(target.path): INSTALLS += target + +FORMS += \ + mcbillingview.ui \ + mcformwidget.ui \ + mcinputview.ui \ + mcloaddialog.ui \ + mcnetworkdialog.ui \ + mcnetworkwidget.ui \ + mcsetupdialog.ui \ + mctransactionview.ui \ + mcvendorsdialog.ui + +DISTFILES += \ + README.md diff --git a/libMiniCash/libMiniCash_global.h b/libMiniCash/libMiniCash_global.h new file mode 100644 index 0000000..ea202dc --- /dev/null +++ b/libMiniCash/libMiniCash_global.h @@ -0,0 +1,12 @@ +#ifndef LIBMINICASH_GLOBAL_H +#define LIBMINICASH_GLOBAL_H + +#include + +#if defined(LIBMINICASH_LIBRARY) +#define LIBMINICASH_EXPORT Q_DECL_EXPORT +#else +#define LIBMINICASH_EXPORT Q_DECL_IMPORT +#endif + +#endif // LIBMINICASH_GLOBAL_H diff --git a/libMiniCash/libminicash.cpp b/libMiniCash/libminicash.cpp new file mode 100644 index 0000000..138181f --- /dev/null +++ b/libMiniCash/libminicash.cpp @@ -0,0 +1,2 @@ +#include "libminicash.h" + diff --git a/libMiniCash/mcbillingview.cpp b/libMiniCash/mcbillingview.cpp new file mode 100644 index 0000000..8a3ce3a --- /dev/null +++ b/libMiniCash/mcbillingview.cpp @@ -0,0 +1,634 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/** + * @brief Konstruktor des Abrechnungsdialogs + * + * @param parent Das Elternfenster + * @param datafilename Der Filename der Kassendatei + * @param settings die globalen Systemeinstellungen + * + */ + +MCBillingView::MCBillingView( QWidget *parent ) + : QFrame( parent ), _ui{new Ui::MCBillingView}, _allCustomers( 0 ) +{ + + _ui->setupUi( this ); + + /// model setzen + _salesModel.setParent( this ); + _ui->_trList->setModel( &_salesModel ); + + QRegularExpressionValidator* srcDrive = new QRegularExpressionValidator( QRegularExpression( miniCash::fSrcDrive ) ); + QRegularExpressionValidator* profit = new QRegularExpressionValidator( QRegularExpression( miniCash::fProfit ) ); + QRegularExpressionValidator* fromID = new QRegularExpressionValidator( QRegularExpression( miniCash::fFromID ) ); + QRegularExpressionValidator* toID = new QRegularExpressionValidator( QRegularExpression( miniCash::fToID ) ); + + _ui->_srcDrive->setValidator( srcDrive ); + _ui->_trProfit->setValidator( profit ); + _ui->_trFrom->setValidator( fromID ); + _ui->_trTo->setValidator( toID ); + +} + + +/** + * @brief Destruktor + * + * Destruktor + * + */ + +MCBillingView::~MCBillingView() +{ + +} + + +/** + * @brief MCBillingView::setupDefaults: Werte von ausserhalb, weil durch die + * Qt-setpUi()-Autotmatik nichts mehr über den Konstruktor übergeben werden + * kann. + * + * @param datafilename + * @param settings + */ + +void MCBillingView::setupDefaults( const QString& datafilename, QSettings* settings ) +{ + + /// dateifilter für die Kassenfiles + _fileFilter = "*_" + datafilename; + _settings = settings; + /// Wertvorgaben laden + _ui->_srcDrive->addItem( _settings->value( miniCash::keyMobileDrive ).toString() ); + _ui->_trFooterText->setText( _settings->value( miniCash::keyFooterText ).toString() ); + + connect( _ui->_trButtonRead, SIGNAL(clicked()), this, SLOT( onReadTransactions()) ); + connect( _ui->_trButtonPrintBills, SIGNAL(clicked()), this, SLOT( onPrintBills()) ); + connect( _ui->_trButtonPrintReceipts,SIGNAL(clicked()), this, SLOT( onPrintReceipts()) ); + + /// erst lesen dann drucken + _ui->_trButtonPrintBills->setEnabled( false ); + _ui->_trButtonPrintReceipts->setEnabled( false ); + _ui->_trProfit->setText( _settings->value( miniCash::keyProfit ).toString() ); + +} + + +/** + * @brief testet die Formulareingaben! + * + * Testet die Eingaben des Abrechnungsformulars auf Gültigkeit: + * + * - Anteil des Kindergartens + * - Kundennummer 'von' + * - Kundennummer 'bis' + * + */ + +bool MCBillingView::testFormData() +{ + const QString& profit = _ui->_trProfit->text(); + const QString& trFrom = _ui->_trFrom->text(); + const QString& trTo = _ui->_trTo->text(); + + if( profit.isEmpty() || trFrom.isEmpty() || trTo.isEmpty() ) + { + QMessageBox::warning + ( + this, + "Eingabefehler", + QString( + "Die Felder 'Anteil Kindergarten' und\n " + "'Abrechung Kundenummer von...bis'\nmüssen belegt sein." + ) + ); + return false; + } + + // alles ok, also Felder sichern + _settings->setValue( miniCash::keyMobileDrive, _ui->_srcDrive->currentText() ); + _settings->setValue( miniCash::keyProfit, profit ); + _settings->setValue( miniCash::keyFooterText, _ui->_trFooterText->document()->toPlainText() ); + + return true; +} + + +/** + * @brief Kassendateien einlesen + * + * Liest die (nunmehr zusammenkopierten) Kassendateien zur weiteren Bearbeitung ein. + * Die Dateinamen sind aus der jeweiligen Kassennummer (1..x) und dem Basisnahmen + * zusammengesetzt: + * _.klm, also etwa: 1_03-13-2022.klm + * + */ + +void MCBillingView::onReadTransactions() +{ + + /// erst lesen dann drucken + _ui->_trButtonPrintBills->setEnabled( false ); + _ui->_trButtonPrintReceipts->setEnabled( false ); + + + /// + /// erstmal die Felder prüfen und erst bei korrekten Daten weitermachen. + /// + + if( !testFormData() ) + return; + + /// saubermachen + _salesSummary.clear(); + + QDir datadir( _ui->_srcDrive->currentText() ); + + datadir.setFilter( QDir::Files | QDir::NoSymLinks ); + datadir.setSorting( QDir::Name ); + + + /// Dateien holen und zeigen + QStringList filter( _fileFilter ); + QStringList list = datadir.entryList( filter ); + + /// was gefunden? + if( list.isEmpty() ) + { + QString msg( "Im Pfad '%0' \nkonnten keine Kassendateien gefunden werden." ); + QMessageBox::warning(this, "Keine Kassendateien gefunden", msg.arg( datadir.absolutePath() + _fileFilter ) ); + return; + } + + /// listview befüllen + MCLoadDialog dlg( this ); + for( const QString& entry : list ) + dlg.appendEntry( entry ); + + if( dlg.exec() != QDialog::Accepted ) + return; + + /// alle Kassenfiles einlesen + _salesSummary.clear(); + ///_salesModel.clear(); <-- löscht den Header mit + _salesModel.removeRows( 0, _salesModel.rowCount() ); + + dlg.show(); + + _allCustomers = 0; + int salescount=0, customercount=0; + QString dlgitem( ": Kunden: %0 Artikel: %1" ); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + for( int i = 0; i < list.size(); ++i ) + { + QString filename = _ui->_srcDrive->currentText() + list.at( i ); + salescount = _salesSummary.appendFromFile( filename, customercount, _salesModel ); + _allCustomers += customercount; + dlg.updateEntry( i, dlgitem.arg( customercount ).arg( salescount ) ); + } + QApplication::restoreOverrideCursor(); + + if( dlg.exec() != QDialog::Accepted ) + return; + + /// es kann gedruckt werden + _ui->_trButtonPrintBills->setEnabled( true ); + _ui->_trButtonPrintReceipts->setEnabled( true ); + +} + + +/** + * @brief Abrechungen drucken + * + * Erzeugt aus den eingelesenen Kassendaten mit Hilfe + * der vorgegebenen HTML-Templates die Druckdateien der + * Abrechung als .pdf-Files. + * + * Auf den Abrechnungen sind pro Kunden(=Verkäufer)-Nummer die Laufnummern der + * jeweils verkauften Artikel, der Umsatz und der Auszahlungsbetrag nach Abzug der + * Provision für den Kindergarten aufgelistet. + * + * @bug die untere ('1100') und obere ('1399') Grenze des Kundennummernintervalls + * sind nicht mehr unbedingt gültig und sollten hier nicht hardkodiert sein. + * @bug der progressbar wir nicht benutzt. + */ + +void MCBillingView::onPrintBills() +{ + + + /// + /// nochmal die Felder prüfen und erst bei korrekten Daten weitermachen. + /// + + if( !testFormData() ) + return; + + /// + /// Step 1: HTML-Template laden und Wiederholungsblock + /// (= Zeile auf der Abrechnung) erzeugen + /// + + + QFile file( miniCash::tplPayoff ); + if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QMessageBox::critical( + this, + tr( "Dateifehler" ), + QString( tr( "Datei nicht gefunden: %1" ) ).arg( file.errorString() ), + QMessageBox::Ok ); + return; + } + + /// HTML-template für die Abrechnung + QString invoice( file.readAll() ); + /// speichert alles Abrechnungen + /// Zeilentemplate der Abrechung + QString block( + "" + "%0" + "%1" + "%2 " + "%3 " + "" + ); + + /// Die Abrechnung + QTextDocument document; + /// der Anteil für den Kindergarten in % + double fee = _settings->value( miniCash::keyProfit ).toDouble(); + /// in Datei Drucken ? + bool printToFile = _ui->_trSaveBills->isChecked(); + + QString drive = _ui->_srcDrive->currentText(); + QPrinter printer; + if( printToFile ) + printer.setOutputFormat( QPrinter::PdfFormat ); + + + /// + /// Step 2: Iterieren über alle Verkäufer ... + /// + + const QString& strFrom = _ui->_trFrom->text(); + const QString& strTo = _ui->_trTo->text(); + + /// wenn ein intervall angegeben ist, muss zuerst der exakte Schlüssel + /// gesucht werden, denn upperbound liefert die position _nach_ dem + /// angegebenen Schlüssel. + + MCSalesSummary::const_iterator posSeller = _salesSummary.cbegin(); + + if( strFrom != "1100" ) + { + posSeller = _salesSummary.constFind( strFrom ); + if( posSeller == _salesSummary.cend() ) + posSeller = _salesSummary.lowerBound( strFrom ); + } + + /// dito das 'obere' Ende des Intervalls + + MCSalesSummary::const_iterator posEnd = _salesSummary.cend(); + /// + if( strTo != "1399" ) + { + posEnd = _salesSummary.constFind( strTo ); + if( posEnd == _salesSummary.cend() ) + posEnd = _salesSummary.upperBound( strTo ); + } + + /// Progressbar vorbereiten + + /* + int sellerCount = 0; + QStatusBar* statusBar = ( (MCMainWindow*) parent() )->statusBar(); + QProgressBar* progress = new QProgressBar( bar ); + progress->setRange( 0, _salesSummary.size() ); + bar->addWidget( progress ); + */ + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + /// Über alle Verkäufernummern ... + for( ; posSeller != posEnd; ++posSeller ) + { + + /// + /// Step 2B: Iterieren über alle verkauften Artikel des Verkäufers ... + /// + + //// FIX! + //// progress->setValue( sellerCount++ ); + /// Der Zeilenblock, also die Einzelauflistung der verkauften Artikel + QString result; + /// Der Umsatz der Verkäufers + double revenueOverall = 0; + /// Der Auszahlungsbetrag (Umsatz abzgl. Kindergartenanteil) + double gainOverall = 0; + + int soldItems = 0; + MCSalesItemMap::const_iterator posSales = posSeller.value().begin(); + for( ; posSales != posSeller.value().end(); ++posSales ) + { + + qDebug() << "Kunde: " << posSeller.key(); + /// Ein Eintrag + const MCSalesItem& itm = posSales.value(); + revenueOverall += itm.trPrice; + double gain = itm.trPrice / 100.0 * (100.0 - fee ); + gainOverall += gain; + ++soldItems; + + QString entry = block.arg + ( + itm.trSellerID, + itm.trItemNo, + MCSalesModel::toCurrency( itm.trPrice ), + MCSalesModel::toCurrency( gain ) + ); + result += entry + '\n'; + + + } /// Über alle Artikel € <-- Euro + + /// Seite fertig: Header Parameter in die Abrechnung schreiben + QDate date = QDate::currentDate(); + /// header + QString soldStr = QString("%1").arg( soldItems ); + QString tmpInvoice = invoice.arg + ( + date.toString( "dd.MM.yyyy" ), + posSeller.key(), + soldStr, + MCSalesModel::toCurrency( revenueOverall ), + MCSalesModel::toCurrency( gainOverall ) + ); + + /// body & footer + + QString footer = _settings->value( miniCash::keyFooterText ).toString(); + if( !footer.isEmpty() ) + { + footer.replace( "\n", "
" ); + footer = "-------------------------------------------------------------------------------------------------------------------------------------------------------\n" + footer; + } + + tmpInvoice = tmpInvoice.arg( result, footer ); + if( printToFile ) + printer.setOutputFileName( drive + QString("abrechung_%1.pdf").arg( posSeller.key() ) ); + document.setHtml( tmpInvoice ); + document.print( &printer ); + + } /// über alle Verkäufer + + ///statusBar->removeWidget( progress ); + QApplication::restoreOverrideCursor(); + QMessageBox::information( this, "Abrechungen drucken", "Alle Druckaufträge wurden erfolgreich erzeugt." ); + + +} + + +/** + * @brief Quittierlisten drucken + * + * Erzeugt aus den eingelesenen Kassendaten mit Hilfe + * der vorgegebenen HTML-Templates die Druckdateien der + * Quittierlisten als .pdf-Files. + * + * Auf den Quittierlisten steht die Kunden(=Verkäufer)-Nummer, der + * Auszahlungsbetrag und das Unterschriftsfeld zur Bestätigung der Auszahlung. + * + * @bug die untere ('1100') und obere ('1399') Grenze des Kundennummernintervalls + * sind nicht mehr unbedingt gültig und sollten hier nicht hardkodiert sein. + * @bug der progressbar wir nicht benutzt. + */ + +void MCBillingView::onPrintReceipts() +{ + + static const int MAXLINES = 23; + + + /// + /// nochmal die Felder prüfen und erst bei korrekten Daten weitermachen. + /// + + if( !testFormData() ) + return; + + /// + /// Step 1: HTML-Template laden und Wiederholungsblock + /// (= Zeile auf der Abrechnung) erzeugen + /// + + QString fileKey = miniCash::tplReceipt; + QFile file( fileKey ); + if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QMessageBox::critical( this, "Dateifehler", QString( "Datei nicht gefunden: %1" ).arg( file.errorString() ), QMessageBox::Ok ); + return; + } + + /// HTML-template für die Quittungsliste + QString receipt( file.readAll() ); + + + /// Zeilentemplate der Abrechung + QString block( + "" + "%0" + "%1 " + "%2 " + " " + " " + "" + "-------------------------------------------------------------------------------------------------------------------------------------------------------" + ); + + + /// Die Abrechnung + QTextDocument document; + /// der Anteil für den Kindergarten in % + double fee = _settings->value( miniCash::keyProfit ).toDouble(); + + MCPrinter printer; + + QString drive = _ui->_srcDrive->currentText(); + bool printToFile = _ui->_trSaveReceipts->isChecked(); + + if( printToFile ) + printer.setOutputFormat( QPrinter::PdfFormat ); + + /// Der Zeilenblock, also die Einzelauflistung der verkauften Artikel + QString result, fromKey, toKey; + bool setKey = true; + int pageCount=1; + int lineCount=0; + + double revenueFinal = 0; + double gainFinal = 0; + int piecesFinal = 0; + + /* + QStatusBar* statusBar = ( (MCMainWindow*) parent() )->statusBar(); + QProgressBar* progress = new QProgressBar( statusBar ); + progress->setRange( 0, _salesSummary.size() ); + statusBar->addWidget( progress ); + */ + + /// + /// Step 2: Iterieren über alle Verkäufer ... + /// + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + MCSalesSummary::const_iterator posSeller = _salesSummary.cbegin(); + for( ; posSeller != _salesSummary.cend(); ++posSeller ) + { + /// Schlüssel merken für die Anzeige "Verkäufer von .. bis" + if( setKey ) + { + fromKey = posSeller.key(); + setKey = false; + } + toKey = posSeller.key(); + + /// + /// Step 2B: Iterieren über alle verkauften Artikel des Verkäufers ... + /// + + /// Der Umsatz der Verkäufers + double revenueOverall = 0; + /// Der Auszahlungsbetrag (Umsatz abzgl. Kindergartenanteil) + double gainOverall = 0; + + ////progress->setValue( pageCount ); + + MCSalesItemMap::const_iterator posSales = posSeller.value().cbegin(); + piecesFinal += posSeller.value().size(); + for( ; posSales != posSeller.value().cend(); ++posSales ) + { + + /// Ein Eintrag + const MCSalesItem& itm = posSales.value(); + + revenueOverall += itm.trPrice; + double gain = itm.trPrice / 100.0 * (100.0 - fee ); + gainOverall += gain; + + + } /// über alle Artikel € <-- Euro + + revenueFinal += revenueOverall; + gainFinal += gainOverall; + QString entry = block.arg + ( + posSeller.key(), + MCSalesModel::toCurrency( revenueOverall ), + MCSalesModel::toCurrency( gainOverall ) + ); + result += entry + '\n'; + + /// Seite fertig: drucken, zurücksetzen & neu starten + if( ++lineCount >= MAXLINES ) + { + lineCount = 0; + if( printToFile ) + printer.setOutputFileName( drive + QString("quittungen_%1.pdf").arg( pageCount ) ); + pageCount++; + /// Seite fertig: Header Parameter in die Abrechnung schreiben + setKey = true; + QDate date = QDate::currentDate(); + /// header + QString tmpReceipt = receipt.arg( date.toString( "dd.MM.yyyy" ), fromKey, toKey, result ); + + document.setHtml( tmpReceipt ); + document.print( &printer ); + document.clear(); + result = ""; + } + + ///if(pageCount >= 3 ) + /// break; + + } /// über alle Verkäufer + + /// Reste Drucken: + QDate date = QDate::currentDate(); + if( lineCount && lineCount < MAXLINES ) + { + + /// header + QString tmpReceipt = receipt.arg( date.toString( "dd.MM.yyyy" ), fromKey, toKey, result ); + if( printToFile ) + printer.setOutputFileName( drive + QString( "receipts_%1.pdf" ).arg( pageCount ) ); + document.setHtml( tmpReceipt ); + document.print( &printer ); + } + + /// und das Finale Abschlussdokument: die Endabrechnung + QFile lastpage( miniCash::tplFinal ); + if( !lastpage.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QMessageBox::critical( this, tr("Dateifehler"), QString( tr("Datei nicht gefunden: %1") ).arg( lastpage.errorString() ), QMessageBox::Ok ); + return; + } + + QString final( lastpage.readAll() ); + final = final.arg( date.toString( "dd.MM.yyyy" ), MCSalesModel::toCurrency( revenueFinal ), MCSalesModel::toCurrency( gainFinal ) ); + final = final.arg( MCSalesModel::toCurrency( revenueFinal - gainFinal ) ); + final = final.arg( fee ); + final = final.arg( piecesFinal ); + final = final.arg( _allCustomers ); + final = final.arg( _salesSummary.size() ); + + if( printToFile ) + printer.setOutputFileName( drive + "FinalInvoice.pdf" ); + document.setHtml( final ); + document.print( &printer ); + + QApplication::restoreOverrideCursor(); + ///statusBar->removeWidget( progress ); + QMessageBox::information( this, tr("Quittungen drucken"), tr("Alle Druckaufträge wurden erfolgreich erzeugt.") ); + +} + + + + + + + + diff --git a/libMiniCash/mcbillingview.h b/libMiniCash/mcbillingview.h new file mode 100644 index 0000000..a928e59 --- /dev/null +++ b/libMiniCash/mcbillingview.h @@ -0,0 +1,72 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCBILLINGVIEW_H +#define MCBILLINGVIEW_H + +#include + +#include +#include +#include + + + +class MCMainWindow; + +namespace Ui +{ + class MCBillingView; +} + +/** + * @brief Das Hauptfenster der Anwendung im Abrechnungsmodus. + * + * Beim Umschalten in den Abrechnungsmodus wir ein neues Hauptfenster + * angezeigt. Hier lassen sich die zur Abrechnung notwendigen Daten noch + * einmal überprüfen und gegebenenfalls ändern. + */ + +class LIBMINICASH_EXPORT MCBillingView : public QFrame +{ + Q_OBJECT + +public: + + explicit MCBillingView( QWidget *parent = nullptr ); + virtual ~MCBillingView(); + + void setupDefaults( const QString& datafilename, QSettings* settings ); + +protected slots: + + void onReadTransactions(); // Kassendateien einlesen + void onPrintBills(); // Abrechnungen drucken + void onPrintReceipts(); // Quittungen drucken + +protected: + + bool testFormData(); + + Ui::MCBillingView* _ui{}; + int _allCustomers; + QSettings* _settings = nullptr; + MCSalesModel _salesModel; // StandardItemModel, speichert Verkaufsdaten und zeigt sie an. + MCSalesSummary _salesSummary; // _alle_ transaktionen, für die Auswertung + QString _fileFilter; + +}; + + +#endif // MCBILLINGVIEW_H diff --git a/libMiniCash/mcbillingview.ui b/libMiniCash/mcbillingview.ui new file mode 100644 index 0000000..518ecbe --- /dev/null +++ b/libMiniCash/mcbillingview.ui @@ -0,0 +1,369 @@ + + + MCBillingView + + + + 0 + 0 + 793 + 726 + + + + Frame + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 9 + true + + + + Druck in Datei + + + + + + + + 0 + 0 + + + + + 9 + true + + + + Quittungsliste drucken + + + Quittungsliste drucken + + + + :/myresource/images/printer2.png:/myresource/images/printer2.png + + + + 16 + 16 + + + + + + + + + 9 + true + + + + Druck in Datei + + + + + + + + 0 + 0 + + + + + 9 + true + + + + Alle Abrechungen Drucken + + + Abrechnungen drucken + + + + :/myresource/images/printer2.png:/myresource/images/printer2.png + + + + 16 + 16 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 240 + + + + + 9 + true + + + + Qt::NoFocus + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + false + + + false + + + + + + + + 9 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 9 + true + + + + Fußzeilentext (optional) + + + Qt::AutoText + + + + + + + + 0 + 0 + + + + + 9 + true + + + + <html><head/><body><p>Einlesen der Kassendateien vom Memorystick starten</p></body></html> + + + Kassendateien einlesen + + + + :/myresource/images/fileexport.png:/myresource/images/fileexport.png + + + + 16 + 16 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 9 + true + + + + + + + + + 9 + true + + + + Quelllaufwerk (z.B. 'E:\') + + + Qt::AutoText + + + + + + + + 9 + true + + + + + + + + + 9 + true + + + + Abrechnung Kundennumer von ... bis + + + Qt::AutoText + + + + + + + + 9 + true + + + + Anteil Kindergarten (%) + + + + + + + + 9 + true + + + + 1100 + + + + + + + + 9 + true + + + + 1399 + + + + + + + + MCTreeView + QTreeView +
mctreeview.h
+
+ + SWDriveSelector + QComboBox +
swdriveselector.h
+
+
+ + +
diff --git a/libMiniCash/mcformwidget.cpp b/libMiniCash/mcformwidget.cpp new file mode 100644 index 0000000..32056ea --- /dev/null +++ b/libMiniCash/mcformwidget.cpp @@ -0,0 +1,14 @@ +#include "mcformwidget.h" +#include "ui_mcformwidget.h" + +MCFormWidget::MCFormWidget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::MCFormWidget) +{ + ui->setupUi(this); +} + +MCFormWidget::~MCFormWidget() +{ + delete ui; +} diff --git a/libMiniCash/mcformwidget.h b/libMiniCash/mcformwidget.h new file mode 100644 index 0000000..5c8218c --- /dev/null +++ b/libMiniCash/mcformwidget.h @@ -0,0 +1,27 @@ +#ifndef MCFORMWIDGET_H +#define MCFORMWIDGET_H + +#include + +#include "libMiniCash_global.h" + +namespace Ui +{ + class MCFormWidget; +} + +class LIBMINICASH_EXPORT MCFormWidget : public QWidget +{ + Q_OBJECT + +public: + + explicit MCFormWidget(QWidget *parent = nullptr); + ~MCFormWidget(); + +private: + + Ui::MCFormWidget *ui; +}; + +#endif // MCFORMWIDGET_H diff --git a/libMiniCash/mcformwidget.ui b/libMiniCash/mcformwidget.ui new file mode 100644 index 0000000..6fe8740 --- /dev/null +++ b/libMiniCash/mcformwidget.ui @@ -0,0 +1,31 @@ + + + MCFormWidget + + + + 0 + 0 + 540 + 300 + + + + Form + + + + + + FITZ! + + + + + + + + + + + diff --git a/libMiniCash/mcinputview.cpp b/libMiniCash/mcinputview.cpp new file mode 100644 index 0000000..5dd1f8f --- /dev/null +++ b/libMiniCash/mcinputview.cpp @@ -0,0 +1,274 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include + +#include +#include +#include + +#include +/** + * Standardkonstruktor. + * @param parent + */ + +MCInputView::MCInputView( QWidget* parent ) + : QWidget( parent ), _ui{new Ui::MCInputView} +{ + _ui->setupUi( this ); + _ui->_trSellerID->setFocus(); +} + + +/** + * @brief Destruktor + */ + +MCInputView::~MCInputView() +{ + delete _ui; +} + + +/** + * @brief Vorgabewerete der Eingabemaske setzen + * @param parent + * @param salesModel + */ + +void MCInputView::setupDefaults( MCMainWindowBase* parent, MCSalesModel* salesModel ) +{ + + _parent = parent; + Q_ASSERT( _parent != nullptr ); + + // model setzen + _salesModel = salesModel; + _ui->_trList->setModel( _salesModel ); + + _valCustId.setRegularExpression( QRegularExpression( miniCash::fCustID ) ); // Validator für die Kundennnummer + _valItemNo.setRegularExpression( QRegularExpression( miniCash::fItemNo ) ); // Validator für die Kundennnummer; // Validator für die laufende Nummer des Artikels + _valPrice.setRegularExpression( QRegularExpression( miniCash::fPrice ) ); // Validator für die Kundennnummer; // Validator für die Preisangabe + + _ui->_trSellerID->setValidator( &_valCustId ); + _ui->_trItemNo->setValidator( &_valItemNo ); + _ui->_trPrice->setValidator( &_valPrice ); + + // Doppelklick auf einen Eintrag in der View soll diesen löschen + connect( _ui->_trList, SIGNAL( doubleClicked(QModelIndex) ), this, SLOT( onRemoveEntry(QModelIndex)) ); + + // hosianna : key event handling ist gar nicht nötig + QShortcut* shortcutPayback = new QShortcut( QKeySequence( Qt::Key_F1 ), this ); + QShortcut* shortcutSave = new QShortcut( QKeySequence( Qt::Key_F12 ), this ); + + connect( shortcutPayback, SIGNAL(activated()), this, SLOT( onCalculatePayback()) ); + connect( shortcutSave, SIGNAL(activated()), _parent, SLOT( onSaveTransaction()) ); + + // Alle Transaktionen sichern + connect( _ui->_trOK, SIGNAL(clicked()), _parent, SLOT( onSaveTransaction()) ); + + // Felder auch mit Enter weiterschalten + connect( _ui->_trSellerID, SIGNAL(returnPressed()), this, SLOT( onMoveInputFocus()) ); + connect( _ui->_trItemNo, SIGNAL(returnPressed()), this, SLOT( onMoveInputFocus()) ); + + // Transaktion fertig eingegeben? Dann prüfen + connect( _ui->_trPrice, SIGNAL(editingFinished()),this, SLOT( onAddSalesItem()) ); + + _ui->_trPos->setText( "1" ); + _ui->_trCount->setText( _parent->transCount() ); + +} + + + /** + * @brief Eingabefelder per Enter weiterschalten + * + * Die Eingabefelder (Kundennummer, laufende Nummer etc. ) sollen nicht nur per TAB + * sondern auch per ENTER weitergeschaltet werden, also wird das Signal "returnPressed" + * eingefangen und der Focus an das jeweils nächste Eingabeelement weitergereicht. + */ + + void MCInputView::onMoveInputFocus() + { + QWidget* sigsender = dynamic_cast( sender() ); + if( sigsender ) + sigsender->nextInFocusChain()->setFocus(); + } + + + /** + * @brief einen verkauften Artikel speichern + * + * Wird aufgerufen wenn ein verkaufter Artikel fertig eingegeben ist + * (sprich: wenn das Preisfeld den Fokus verliert oder Enter gedrückt wird). + * Nach erfolgreicher Überprüfung der Eingaben wird ein neuer Eintrag in die + * Transaktionliste geschrieben. + */ + + void MCInputView::onAddSalesItem() + { + + /// murx, präventiv + _ui->_trList->clearSelection(); + + QString custID = _ui->_trSellerID->text(); + QString itemNo = _ui->_trItemNo->text(); + QString price = _ui->_trPrice->text(); + + /// TODO: + /// Bei Fehlern: + /// - message im statusbar + /// - feld dg rot, focus + /// - tönchen + /// _kein_ popup + + int pos = 0; + if + ( + custID.isEmpty() || + itemNo.isEmpty() || + price.isEmpty() || + _valCustId.validate( custID, pos ) != QValidator::Acceptable || + _valItemNo.validate( itemNo, pos ) != QValidator::Acceptable || + _valPrice.validate( price, pos ) != QValidator::Acceptable + ) + { + QApplication::beep(); + return; + } + + /// den neuen Eintrag in der schicken liste speichern & anzeigen ... + _salesModel->appendEntry( _parent->transCount(), custID, itemNo, price ); + + /// Die Liste Runterscrollen damit der Beitrag auch sichtbar wird + _ui->_trList->scrollToBottom(); + + /// ... und die Lineedits wieder löschen ... + _ui->_trSellerID->clear(); + _ui->_trItemNo->clear(); + _ui->_trPrice->clear(); + + /// positionscount hochzählen + _ui->_trPos->setText( QString( "%0" ).arg( ++_poscount ) ); + /// und die gesamtsumme sichern + _overallSum += MCSalesModel::fromCurrency( price ); + _ui->_trOverall->setText( MCSalesModel::toCurrency( _overallSum ) ); + + _ui->_trSellerID->setFocus(); + + } + + + /** + * @brief Das Rückgeld berechnen + * + * Zeigt einen einfachen Dialog, um das Rückgeld zu berechnen. + */ + + void MCInputView::onCalculatePayback() + { + bool ok; + double amount = QInputDialog::getDouble + ( + this, + "Rückgeld berechnen", + "Welchen Betrag haben Sie erhalten?", + 0, 0, 1000, 2, &ok + ); + if( ok ) + { + QString ret( "Das Rückgeld beträgt: %0"); + QMessageBox::information( this, "Rückgeld", ret.arg( MCSalesModel::toCurrency( amount - _overallSum ) ) ); + } + + } + + + /** + * @brief einen Artikel per Doppelklick aus der + * Verkaufsliste entfernen + * @param idx + * + * Einen Verkaufseintrag per Doppelklick auf die entsprechende Zeile + * in der View löschen. Die Gesamtsumme und die Positionszähler müssen + * entsprechend angepasst werden. + * + */ + + void MCInputView::onRemoveEntry( QModelIndex idx ) + { + + // murx, translate + QMessageBox msg; + msg.setWindowTitle( "Eintrag löschen" ); + msg.setText( "Soll dieser Eintrag wirklich gelöscht werden?" ); + msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msg.addButton( "Ja", QMessageBox::YesRole); + msg.addButton("Nein", QMessageBox::NoRole ); + msg.setDefaultButton(QMessageBox::Yes); + msg.setIcon ( QMessageBox::Question ); + + _ui->_trList->clearSelection(); + + if( msg.exec() == QMessageBox::No ) + return; + + // die gesamtsumme anpassen + QVariant var = _salesModel->item( idx.row(), 3 )->data( Qt::DisplayRole ); + + double price = MCSalesModel::fromCurrency( var.toString() ); + double newprice = _overallSum - price; + + // oops we did it again ... + _salesModel->removeRow( idx.row() ); + + // recalc maxpos + _ui->_trPos->setText( QString( "%0" ).arg( --_poscount ) ); + + // neue summe + _ui->_trOverall->setText( MCSalesModel::toCurrency( newprice ) ); + _overallSum = newprice; + _ui->_trList->clearSelection(); + + } + + + /** + * @brief Die Eingabemaske zurücksetzen + * + * Setzt die Eingabemaske nach einer Kundentransaktion zurück, + * erhöht die internen Zähler und zeigt diese an. + */ + + void MCInputView::onResetView() + { + _ui->_trSellerID->clear(); + _ui->_trItemNo->clear(); + _ui->_trPrice->clear(); + + // Gesamtsumme nicht vergessen + _ui->_trOverall->setText( MCSalesModel::toCurrency( 0 ) ); + + // Zähler anzeigen + _ui->_trCount->setText( _parent->transCount() ); + _ui->_trPos->setText( "1" ); + + _overallSum = 0.0; + _salesModel->removeRows( 0, _salesModel->rowCount() ); + + + } diff --git a/libMiniCash/mcinputview.h b/libMiniCash/mcinputview.h new file mode 100644 index 0000000..f1b73d1 --- /dev/null +++ b/libMiniCash/mcinputview.h @@ -0,0 +1,73 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCINPUTVIEW_H +#define MCCINPUTVIEW_H + +#include +#include +#include + +#include + + + +class MCMainWindowBase; +class MCSalesModel; + +namespace Ui +{ + class MCInputView; +} + +/** + * @brief The MCInputView class + */ + +class LIBMINICASH_EXPORT MCInputView : public QWidget +{ + Q_OBJECT + +public: + + explicit MCInputView( QWidget* parent = nullptr ); + virtual ~MCInputView(); + + void setupDefaults( MCMainWindowBase* parent, MCSalesModel* salesModel ); + +public slots: + + void onCalculatePayback(); + void onResetView(); + void onRemoveEntry( QModelIndex idx ); + void onMoveInputFocus(); /// Eingabefelder sollen auch per Enter weitergeschaltet werden + void onAddSalesItem(); + +private: + + Ui::MCInputView* _ui{}; + + QRegularExpressionValidator _valCustId; /// Validator für die Kundennnummer + QRegularExpressionValidator _valItemNo; /// Validator für die laufende Nummer des Artikels + QRegularExpressionValidator _valPrice; /// Validator für die Preisangabe + + int _poscount = 1; /// Verkaufsposition innerhalb des aktuellen Vorgangs + double _overallSum = 0.0; /// Gesamtpreis der aktuellen Verkaufstransaktion + + MCSalesModel* _salesModel = nullptr; + MCMainWindowBase* _parent = nullptr; + +}; + +#endif /// MCCINPUTVIEW_H diff --git a/libMiniCash/mcinputview.ui b/libMiniCash/mcinputview.ui new file mode 100644 index 0000000..3f33731 --- /dev/null +++ b/libMiniCash/mcinputview.ui @@ -0,0 +1,380 @@ + + + MCInputView + + + + 0 + 0 + 950 + 770 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Lucida Sans Typewriter + 9 + true + + + + Qt::NoFocus + + + false + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + false + + + false + + + + + + + + + + 0 + 0 + + + + + 240 + 10 + + + + + 14 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:400;">Hier klicken (oder F12 drücken) um einen neuen Verkaufsvorgang zu starten.</span></p></body></html> + + + QWidget{ background: rgb(210, 210, 200) } + + + Neuer Kunde (F12) + + + F12 + + + false + + + + + + + true + + + + 20 + 0 + + + + + 40 + 16777215 + + + + + 14 + + + + Qt::NoFocus + + + QWidget{ background: rgb(232, 232, 232) } + + + 99 + + + + + + + + 14 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Geben sie hier die zweistellige laufende Nummer des Artikels ein.</span></p></body></html> + + + + + + + + + + + 14 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Geben sie hier den Preis des Artikels ein.</span></p></body></html> + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 9 + true + + + + Preis + + + + + + + true + + + + 80 + 0 + + + + + 80 + 16777215 + + + + + 14 + + + + Qt::NoFocus + + + + + + + + + + + + QWidget{ background: rgb(232, 232, 232) } + + + Qt::ImhDigitsOnly + + + 9999 + + + + + + + + 9 + true + + + + Pos. + + + + + + + + 9 + true + + + + Verkäufernummer + + + + + + + + 9 + true + + + + laufende Nummer + + + + + + + + 14 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Geben sie hier die Kundennummer (1100 bis 1999) ein.</span></p></body></html> + + + + + + + + + + + 9 + true + + + + Kunde + + + + + + + + 40 + false + + + + Gesamtpreis + + + QLabel { background-color: white } + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 0,00 € + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 9 + false + + + + Hinweise: + - <tab> wechselt die Eingabefelder + - <enter> bzw. <tab> schließt die Eingabe ab + - Doppelklick in der Übersicht löscht den Eintrag + - F1 zur Rückgeldberechnung drücken + + + + + + + + + + MCTreeView + QTreeView +
mctreeview.h
+
+
+ + _trSellerID + _trItemNo + _trPrice + + + +
diff --git a/libMiniCash/mcloaddialog.cpp b/libMiniCash/mcloaddialog.cpp new file mode 100644 index 0000000..4d2c2ed --- /dev/null +++ b/libMiniCash/mcloaddialog.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + +#include +#include + +/** + * @brief Dialogfenster das das Laden der Kassendateien anzeigt. + * + * @param parent Elternfenster + * Die Namen der Kassendateien werden aufgelistet und nach erfolgreichem + * Ladevorgang abgehakt. + */ + +MCLoadDialog::MCLoadDialog( QWidget* parent ) + : QDialog(parent), _ui{new Ui::MCLoadDialog}, _firstTime( true ) +{ + _ui->setupUi( this ); + + connect( _ui->_OkButton, SIGNAL(clicked()), this, SLOT( accept() ) ); + +} + +MCLoadDialog::~MCLoadDialog() +{ + delete _ui; +} + + +/** + * @brief Einen Dateinamen in die Liste schreiben + * @param entry der Dateiname + */ + +void MCLoadDialog::appendEntry( const QString& entry ) +{ + _ui->_listWidget->addItem( entry ); +} + + +/** + * @brief Statusmeldung an einen Dateinamen der Liste anhängen. + * + * @param idx der Index des Dateinnamens + * @param text der Zusatztext: 'OK' oder 'Fehler'. + */ + +void MCLoadDialog::updateEntry( int idx, const QString& text ) +{ + const QString& txt = _ui->_listWidget->item( idx )->text(); + QIcon icon( ":/images/button_ok.png" ); + // text ändern + QListWidgetItem& itm = *_ui->_listWidget->item( idx ); + itm.setIcon( icon ); + itm.setText( txt + text ); +} + + +/** + * @brief Startet das einlesen der Kassendateien. + * + * Beim ersten Klick auf 'OK' (Anzeige 'Einlesen') werden die Ergebnisse + * angezeigt und der Text geändert. Beim zweiten 'OK' (Anzeige: 'Weiter' ) + * werden die Texte zurückgesetzt und es geht tatsächlich weiter. + */ + +void MCLoadDialog::accept() +{ + + if( _firstTime ) + { + _firstTime = false; + // Murx, FIX! das sollte über den Translator gehen + //buttonBox->button( QDialogButtonBox::Ok )->setText( "Weiter" ); + _ui->_label1->setText( "verkaufte Artikel:" ); + + } + + return QDialog::accept(); +} diff --git a/libMiniCash/mcloaddialog.h b/libMiniCash/mcloaddialog.h new file mode 100644 index 0000000..a9e9fd4 --- /dev/null +++ b/libMiniCash/mcloaddialog.h @@ -0,0 +1,58 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCLOADDIALOG_H +#define MCLOADDIALOG_H + +#include + +#include +#include + +namespace Ui +{ + class MCLoadDialog; +} + +/** + * @brief Infodialog, der bei der Abrechnung die vorhandenen Kassendateien anzeigt. + */ + +class LIBMINICASH_EXPORT MCLoadDialog : public QDialog +{ + Q_OBJECT + +public: + + explicit MCLoadDialog( QWidget* parent ); + ~MCLoadDialog(); + + void appendEntry( const QString& entry ); + void updateEntry( int idx, const QString& text ); + +protected: + + void accept(); + +private: + + Ui::MCLoadDialog* _ui{}; + bool _firstTime; + +}; + +#endif // MCLOADDIALOG_H + + + diff --git a/libMiniCash/mcloaddialog.ui b/libMiniCash/mcloaddialog.ui new file mode 100644 index 0000000..0472b19 --- /dev/null +++ b/libMiniCash/mcloaddialog.ui @@ -0,0 +1,89 @@ + + + MCLoadDialog + + + + 0 + 0 + 450 + 250 + + + + Dialog + + + + + + + 10 + true + + + + + + + Folgende Kassendateien werden jetzt eingelesen: + + + + + + + false + + + + 10 + + + + QWidget{ background: rgb(232, 232, 232) } + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 325 + 20 + + + + + + + + + 0 + 0 + + + + + true + + + + OK + + + + + + + + diff --git a/libMiniCash/mcmainwindowbase.cpp b/libMiniCash/mcmainwindowbase.cpp new file mode 100644 index 0000000..8395e09 --- /dev/null +++ b/libMiniCash/mcmainwindowbase.cpp @@ -0,0 +1,468 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2018 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +/// Für den Test auf CapsLock +///#include "Windows.h" +/* + * bool QMyClass::checkCapsLock() +{ +// platform dependent method of determining if CAPS LOCK is on +#ifdef Q_OS_WIN32 // MS Windows version +return GetKeyState(VK_CAPITAL) == 1; +#else // X11 version (Linux/Unix/Mac OS X/etc...) +Display * d = XOpenDisplay((char*)0); +bool caps_state = false; +if (d) +{ +unsigned n; +XkbGetIndicatorState(d, XkbUseCoreKbd, &n); +caps_state = (n & 0x01) == 1; +} +return caps_state; +#endif +} +*/ + + +/** + * @brief Der Konstruktor, die Initialisierungen des GUI + * und der Netzverbindung werden in den Unterklassen vorgenommen. + */ + +MCMainWindowBase::MCMainWindowBase( QWidget* parent ) + : QMainWindow( parent ) +{ + + /// model setzen + _salesModel.setParent( this ); + +} + + +/** + * @brief MCMainWindowBase::~MCMainWindowBase ! + */ + +MCMainWindowBase::~MCMainWindowBase() +{ + +} + + +/** + * @brief MCMainWindowBase::transCount ! + * @return + */ + +QString MCMainWindowBase::transCount() +{ + return MCSalesModel::formatInt( _transCount ); +} + + +/** + * @brief Dateipfad anhand der Vorgaben aus dem Setup-Dialog erzeugen. + * @param key settingskey + * + * Dateipfad anhand der Vorgaben aus den settings zusammenbasteln, Hilfsfunktion + * + * @return pfad + */ + +QString MCMainWindowBase::fetchSetting( const QString& key ) +{ + return _mainSettings.value( key ).toString(); +} + + +/** + * @brief Datei-Fehlermeldung anzeigen: Meistens sind einfach die Pfadeinstellungen falsch. + * @param filename + * @param errormsg + * + * Conveniencefunction zur vereinfachten Handhabung von Dateifehlern, + * errortxt holen, Messagebox erzeugen etc. + * @return immer false + */ + +bool MCMainWindowBase::showFileError( const QString& filename, const QString& errormsg ) +{ + + QString msg( "Datei '%0' konnte nicht geöffnet werden.\nFehlercode: %1" ); + /// je schlimmer je geiler + QMessageBox::critical( this, "Fehler", msg.arg( filename, errormsg ) ); + return false; +} + + +/** + * @brief Dateien & Settings initialisieren + * + * Wird direkt beim Programmstart aufgerufen, setzt die Vorgabewerte + * und erzeugt die Arbeitsdateien. + * + * @see setupDataFile + * + */ + +void MCMainWindowBase::setupDefaults() +{ + + /// leer? dann defaults reinschreiben + if( !_mainSettings.contains( miniCash::keyMobileDrive) ) + { + _mainSettings.setValue( miniCash::keyMobileDrive, miniCash::mobileDrive ); + _mainSettings.setValue( miniCash::keyProfit, miniCash::profit ); + _mainSettings.setValue( miniCash::keySelfID, miniCash::selfID ); + _mainSettings.setValue( miniCash::keyFooterText, "" ); + } + + /// solange Setup-Dialog zeigen bis die Arbeitsfiles + /// nutzbar sind + + bool allfine = false; + while( !allfine ) + { + allfine = setupDataFile(); + if( !allfine ) + { + QString msg( "Die lokale Arbeitsdatei konnte nicht angelegt werden.\nBitte die Programmeinstellungen überprüfen." ); + QMessageBox::critical( this, "Dateifehler", msg ); + setupDataFile(); + } + } + +} + + +/** + * @brief Kassendateien öffnen oder erzeugen + * + * Hier werden die beiden Arbeitsdateien geöffnet bzw. erzeugt: es + * wird entschieden, ob ein zum heutigen Datum (also Freitag oder Samstag) + * ein passender Kleidermarkt vorhanden ist. + * Falls nicht, wird eine Kassendatei fürs heutige Datum angelegt. + */ + +bool MCMainWindowBase::setupDataFile() +{ + + /// step 1: Filenamen aus Datum bauen, hack: wir nehmen immer den Freitag + QDate date = QDate::currentDate(); + /// Hack: Am Samstag schalten wir auf Freitag + if( date.dayOfWeek() == 6 ) + date = date.addDays( -1 ); + + /// Filenames aus Datum + _dataFileName = date.toString( "MM-dd-yyyy" ) + miniCash::filetype; + QString dirName = QDir::homePath() + miniCash::dataDir; + QDir dir( dirName ); + if( !dir.exists() ) + dir.mkpath( dirName ); + + _dataFilePath = dirName + _dataFileName; + + /// erstmal alles auf Anfang + _transCount = 1; + + /// Ist das File schon vorhanden ? Sonst anlegen + QFile datafile( _dataFilePath ); + + if( !datafile.exists() ) + { + /// hats auch wirklich geklappt? + if( !datafile.open( QIODevice::WriteOnly ) ) + /// wenn schon der start misslingt, hat + /// nichts mehr einen sinn + return showFileError( _dataFilePath, datafile.errorString() ); + _mainSettings.setValue( miniCash::keyTransCount, "1" ); + } + + /// Zählerstand lesen. + _transCount = _mainSettings.value( miniCash::keyTransCount ).toInt(); + + return true; + +} + + + +/** + * @brief Speichert die Transaktionsdaten in eine Datei, hier Stick und Festplatte + * @param filename Zieldatei + * @param result die Verkaufstransaktion + * + * Verkaufte Artikel auf Platte oder Stick sichern. Ds ist eine Hilfsfunktion für + * @see onSaveTransaction, wir zweimal aufgerufen: einmal auf Stick und einmal + * als Geheim-Backup auf Platte. + * + */ + +bool MCMainWindowBase::saveTransactionToFile( const QString& filename, const QString& transaction ) +{ + QFile datafile( filename ); + if (!datafile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append )) + return showFileError( filename, datafile.errorString() ); + + /// file nicht direkt beschreiben + QTextStream output( &datafile ); + /// Stream füllen + output << transaction; + + return true; + +} + + +/** + * @brief Schreibt die Einkäufe eines Kunden (==Transaktion) + * via QTextStream formatiert in einen String. + * + * Alle bisherigen Verkäufe, also der Inhalt des @see MCSalesModel, werden + * mit Hilfe eines QTextStreams als Tab-Separated-Values in einen QString + * geschrieben + * + * @return Die Verkaufstransaktion als String + * + */ + +QString MCMainWindowBase::saveTransactionToString() +{ + + QString result; + QTextStream output( &result ); + + /// Stream füllen + for( int row = 0; row < _salesModel.rowCount(); ++row ) + { + + /// TransactionNo + QModelIndex idx = _salesModel.index( row, MCSalesItemMap::Count ); + QString content = _salesModel.data( idx ).toString(); + output << content << " "; + + /// SellerID + idx = _salesModel.index( row, MCSalesItemMap::SellerID ); + content = _salesModel.data( idx ).toString(); + output << content << " "; + + /// Laufende ArtikelNo + idx = _salesModel.index( row, MCSalesItemMap::ItemNo ); + + /// passiert jetzt schon im model + ///output << formatInt( _salesModel.data( idx ).toInt(), 3 ); + output << _salesModel.data( idx ).toString(); + + idx = _salesModel.index( row, MCSalesItemMap::Price ); + content = _salesModel.data( idx ).toString(); + + /// Eurozeichen absäbeln, komma statt punkt wg. kompatibilität + /// mit PCK + + if( content.isEmpty() || content.isNull() ) + { + /// FIX, murx: log error + content = "0,0"; + } + else + { + content = content.split( ' ' ).at(0); + } + + /// so sollte man es eigentlich machen + output << Qt::right << qSetFieldWidth(15) << content << Qt::reset; + /// datum/zeit dranhängen & zeile fertig + QString dtstr = QDateTime::currentDateTime().toString( "MM-dd-yyyy hh:mm:ss" ); + output << ' ' << dtstr << Qt::endl; + + } + + return result; + +} + + +/** + * @brief Vom aktuellen Kunden gekaufte Artikel auf Platte sichern. + * + * Speichert die vom aktuellen Kunden gekauften Artikel auf Platte. + * @see saveTransactionToString() + * + */ + +bool MCMainWindowBase::onSaveTransaction() +{ + + // View auslesen + /// an datei anhängen + /// zähler zurücksetzen + /// die Lineedits wieder löschen + + /// + /// Step 0: gibbet überhaupt View-Daten? + /// + + if( _salesModel.rowCount() == 0 ) + { + QApplication::beep(); + return false; + } + + /// + /// Step 1: View-Daten via Textstream in einen String schreiben + /// + + QString transaction = saveTransactionToString(); + + /// + /// Step 2a: Die (nunmehr formatierte) Transaktion speichern und sichern + /// + + /// Offizieller Speicherort auf dem Stick bzw. nunmehr auf SSD + if( !saveTransactionToFile( _dataFilePath, transaction ) ) + return false; + + /// Dummy für Speichern im Netz + emit transactionCreated( transaction ); + + /// + /// Step 4: das Zählerfeld neu setzen + /// + _newTransCount++; + _transCount++; + _mainSettings.setValue( miniCash::keyTransCount, _transCount ); + + /// + /// Step 4: Die Lineedits & view wieder löschen + /// + + _inputViewProxy->onResetView(); + + return true; + +} + + +/** + * @brief Verkaufstransaktionen kopieren + * + * Alle Verkaufstransaktionen zur Auswertung auf einen Memorystick + * kopieren + * + */ + +void MCMainWindowBase::onCopyTransactions() +{ + + /// FIX murx + QMessageBox msg; + msg.setWindowTitle( "Auswertungsdatei erzeugen" ); + QString txt( "Wenn der Memorystick in Laufwerk '%0' \neingesteckt ist bitte auf 'Speichern' klicken" ); + msg.setText( txt.arg( fetchSetting( miniCash::keyMobileDrive ) ) ); + msg.setStandardButtons( QMessageBox::Save | QMessageBox::Cancel ); + msg.addButton("Speichern",QMessageBox::AcceptRole); + msg.addButton("Abbrechen",QMessageBox::RejectRole); + msg.setDefaultButton(QMessageBox::Save); + msg.setIcon ( QMessageBox::Information ); + + if( msg.exec() == QMessageBox::Cancel ) + return; + + QString target = fetchSetting( miniCash::keyMobileDrive ) + fetchSetting( miniCash::keySelfID ); + target += "_" + _dataFileName; + + /// falls vorhanden löschen weil copy nicht überschreibt + QFileInfo fitarget( target ); + + if( fitarget.exists() ) + QFile::remove( target ); + + if( !QFile::copy( _dataFilePath, target ) ) + { + QString msg( "Dateifehler: Kopieren von %0\nnach %1 fehlgeschlagen."); + QMessageBox::warning(this, "Dateifehler", msg.arg( _dataFilePath, target ) ); + + return onSetup(); + } + + QMessageBox::information( this, "Auswertungsdatei erzeugen", "Auswertungsdatei wurde erfolgreich erzeugt." ); + +} + + + + +/** + * @brief Handbuch anzeigen + * + * @bug Handbuch ist noch nicht fertig. + */ + +void MCMainWindowBase::onHelpManual() +{ + //QMessageBox::StandardButton reply = QMessageBox::information(this, "onHelpContents()", "onHelpContents()" ); + //_helpViewer->show(); + onHelpAbout(); +} + + + +/** + * @brief Speichern und Beenden, die Toolbarversion: Es wird nachgefragt. + */ + +void MCMainWindowBase::onExitConfirmed() +{ + /// murx + QMessageBox msg; + msg.setWindowTitle("Programm beenden"); + msg.setText("Programm wirklich beenden?"); + msg.setStandardButtons( QMessageBox::Save | QMessageBox::Cancel ); + msg.addButton("OK", QMessageBox::AcceptRole ); + msg.addButton("Abbrechen",QMessageBox::RejectRole); + msg.setDefaultButton(QMessageBox::Save); + msg.setIcon ( QMessageBox::Information ); + + if( msg.exec() == QMessageBox::Cancel ) + return; + + onExit(); + +} + + +/** + * @brief Speichern und Beenden, die Menuversion: Es wird nicht nachgefragt. + */ + +void MCMainWindowBase::onExit() +{ + + /// Falls noch Transaktion vorhanden, + /// diese sichern + if( _salesModel.rowCount() != 0 ) + onSaveTransaction(); + qApp->exit(); +} diff --git a/libMiniCash/mcmainwindowbase.h b/libMiniCash/mcmainwindowbase.h new file mode 100644 index 0000000..50d0ae0 --- /dev/null +++ b/libMiniCash/mcmainwindowbase.h @@ -0,0 +1,120 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCMAINWINDOWBASE_H +#define MCMAINWINDOWBASE_H + +#include +#include + +#include +#include +#include + + +/** + * @brief Dient als abstrakte MainWindow-Basisklasse für Projekte, + * die auf libMiniCash aufbauen. + * + * Die MCMainWindowBase-Klasse ist die Hauptklasse der libMiniCash-Library und dient als + * abstrakte Basisklasse der jeweiligen MainWindows in den Projekten, die auf libMiniCash aufbauen. + * + * Die Benutzeroberlfläche wird hier _nicht_ implementiert, sondern nur die Infrastruktur zum + * + * - Eingeben + * - Bearbeiten + * - sowie Speichern + * + * von Verkaufsdaten. Funktionen, die direkt mit der Nutzeroberfläche interagieren, werden + * daher in den Subklassen implemntiert. + +* Die dazu verwendeten Klassen werden auch in dieser Bibliothek definiert: +* + * - @see mcsalesitem + * - @see mcsalesitemmap + * - @see mcsalesmodel + * - @see mcsalessummary + * + * Weiterhing enthält MCMainWindowBase die Implementierung der SLOTS für Servicefunktionalität der + * Benutzeroberfläche. + * + */ + +class LIBMINICASH_EXPORT MCMainWindowBase : public QMainWindow +{ + Q_OBJECT + +public: + + explicit MCMainWindowBase( QWidget* parent = nullptr ); + virtual ~MCMainWindowBase(); + + QString transCount(); + +signals: + + void fileError(); + void transactionCreated( const QString& transaction ); /// Einkaufstransaktion beenden, senden + +protected: + + QString fetchSetting( const QString& key ); /// Hilfsfunktion: Dateipfad erzeugen + bool showFileError( const QString& filename, const QString& errormsg ); /// Hilfsfunktion: Fehlermeldung anzeigen + + void setupDefaults(); /// Init-Funktion, wird beim Programmstart aufgerufen + bool setupDataFile(); /// Arbeitsdateien erzeugen bzw. öffnen + + QString saveTransactionToString(); + bool saveTransactionToFile( const QString& filename, const QString& transaction ); /// Einkaufstransaktion beenden, auf platte oder ins netz schreiben schreiben + +protected slots: + + virtual void onSetup() = 0; + virtual void onEditTransactions() = 0; /// Kassendatei durchsuchen und editieren + virtual bool onSaveTransaction(); /// Kundentransaktion beenden, auf platte schreiben + virtual void onCopyTransactions(); /// Alle Transaktionen zur Auswertung von Disk auf Stick kopieren + virtual void onStartBilling() = 0; /// Kassieren beenden und Abrechnungsmodus starten + virtual void onExit(); /// Programm beenden + virtual void onExitConfirmed(); /// Programm beenden, mit Bestätigung + virtual void onHelpAbout() = 0; /// rumbalotte + virtual void onHelpManual(); /// Hilfe anzeigen + +protected: + + int _transCount = -10; /// Anzahl der Transaktionen (== Verkäufe) ingesamt bisher + int _newTransCount = 0; /// Anzahl der Transaktionen (== Verkäufe) seit dem Programmstart + + MCSalesModel _salesModel; /// StandardItemModel, speichert Verkaufsdaten und zeigt sie an. + QString _dataFileName; /// Name der Transaktionsdatei _ohne_ Laufwerk: 02-15-2013.klm + QString _dataFilePath; /// Pfad der Transaktionsdatei _ohne_ Laufwerk: 02-15-2013.klm + MCInputView* _inputViewProxy = nullptr; /// Platzhalter für die InputView, die in den subclasses implementiert wird. + QSettings _mainSettings; /// Persistente Einstellungen + +}; + +#endif // MCMAINWINDOWBASE_H + + + + + + + + + + + + + + diff --git a/libMiniCash/mcnetworkdialog.cpp b/libMiniCash/mcnetworkdialog.cpp new file mode 100644 index 0000000..a4f7806 --- /dev/null +++ b/libMiniCash/mcnetworkdialog.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + + miniCash + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + +#include +#include + +#include + + +MCNetworkDialog::MCNetworkDialog( QWidget* parent, QSettings* settings ) + : QDialog( parent ), _ui{new Ui::MCNetworkDialog}, _settings( settings ) +{ + + Q_ASSERT( nullptr != _settings ); + + _ui->setupUi( this ); + + // Murx, FIX! das sollte über den Translator gehen + _ui->_buttonBox->button( QDialogButtonBox::Ok )->setText( "Speichern" ); + _ui->_buttonBox->button( QDialogButtonBox::Cancel )->setText( "Abbrechen" ); + + /// Vorgabewerte setzen + _ui->_receiverHost->setText( _settings->value( miniCash::keyReceiverHost ).toString() ); + _ui->_receiverPort->setText( _settings->value( miniCash::keyReceiverPort, miniCash::receiverPort ).toString() ); + _ui->_senderHost->setText( QHostInfo::localHostName() ); + + bool isReceiver = _settings->value( miniCash::keyIsTcpReceiver, miniCash::isTcpReceiver ).toBool(); + bool isSender = _settings->value( miniCash::keyIsTcpSender, miniCash::isTcpSender ).toBool(); + _ui->_isSender->setChecked ( isSender ); + _ui->_isReceiver->setChecked( isReceiver ); + + onSetNetworkEnabled( true ); + onTestHostEntry(); + + connect( _ui->_buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) ); + connect( _ui->_buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) ); + + connect( _ui->_receiverHost, SIGNAL( textChanged(QString) ), this, SLOT( onTestHostEntry(QString) ) ); + connect( _ui->_receiverPort, SIGNAL( textChanged(QString) ), this, SLOT( onTestHostEntry(QString) ) ); + connect( _ui->_isSender, SIGNAL( toggled(bool) ), this, SLOT( onSetNetworkEnabled(bool) ) ); + connect( _ui->_isReceiver, SIGNAL( toggled(bool) ), this, SLOT( onSetNetworkEnabled(bool) ) ); + + /// @see https://www.kdab.com/nailing-13-signal-slot-mistakes-clazy-1-3/: + /// warning pass a context object as 3rd connect parameter + connect( _ui->_buttonUseNetwork, &QAbstractButton::toggled, _ui->_receiverHost, + [=]( bool isOn ) + { + _ui->_groupBox->setEnabled( isOn ); + _useNetwork = isOn; + if( !isOn ) + { + _ui->_isSender->setChecked( false ); + _ui->_isReceiver->setChecked( false ); + } + } ); + + connect( _ui->_buttonTest, &QPushButton::clicked, _ui->_receiverHost, + [=]() + { + QHostInfo::lookupHost( _ui->_receiverHost->text(), this, SLOT( onLookupHost(QHostInfo) ) ); + } ); + +} + +/** + * @brief Destruktor + */ + +MCNetworkDialog::~MCNetworkDialog() +{ + delete _ui; +} + + +void MCNetworkDialog::onTestHostEntry( const QString& ) +{ + bool enable = !_ui->_receiverHost->text().isEmpty() && !_ui->_receiverPort->text().isEmpty(); + _ui->_buttonTest->setEnabled( enable ); +} + + +void MCNetworkDialog::onSetNetworkEnabled( bool ) +{ + + bool isSender = _ui->_isSender->isChecked(); + bool isReceiver = _ui->_isReceiver->isChecked(); + + _ui->_buttonTest->setEnabled( isSender ); + _ui->_receiverHost->setEnabled( isSender ); + _ui->_receiverPort->setEnabled( isSender ); + + _useNetwork = isSender || isReceiver; + /// klappt nicht! Bedenke die Logik! + ///_buttonUseNetwork->setChecked( _useNetwork ); + _ui->_buttonUseUSB->setChecked( !_useNetwork ); + _ui->_buttonUseNetwork->setChecked( _useNetwork ); + _ui->_groupBox->setEnabled( _useNetwork ); + +} + + +bool MCNetworkDialog::onLookupHost( const QHostInfo& hostInfo ) +{ + + if( hostInfo.error() != QHostInfo::NoError ) + { + _ui->_labelTest->setStyleSheet( "font-weight: bold; color: red" ); + _ui->_labelTest->setText( "Host nicht gefunden" ); + return false; + } + + _ui->_labelTest->setStyleSheet( "font-weight: normal; color: green" ); + _ui->_labelTest->setText( "Verbindung möglich" ); + + return true; + +} + + +/** + * @brief ok gedrückt: geänderte Daten prüfen und übernehmen + */ + +void MCNetworkDialog::accept() +{ + + qDebug() << "MCNetworkDialog::accept()"; + + const QString& host = _ui->_receiverHost->text(); + const QString& port = _ui->_receiverPort->text(); + QHostInfo hostInfo; + + /// wollen wir ins netz? + onSetNetworkEnabled( true ); + + /// wir wollen gar kein netz? + if( !_useNetwork || _ui->_buttonUseUSB->isChecked() ) + //return QDialog::reject(); + goto xx; + + /// wollen wir server sein? + if( !_ui->_isSender->isChecked() ) + goto xx; + + /// wir wollen senden, also Receiver prüfen + if( host.isEmpty() || port.isEmpty() ) + { + QMessageBox::warning + ( + this, + "Eingabefehler", + "Die Felder 'Servername' und 'Port'\n " + "müssen belegt sein." + ); + return; + } + + /* + Nein, das haut so nicht hin + // alles da, klappts dann auch mit dem Nachbarn? + int res = QHostInfo::lookupHost( host, this, SLOT( onLookupHost(QHostInfo) ) ); + /// hier warten, bis 'onLookupHost' zurückkommt und '_hostValid' gesetzt ist + _lookupLock.lock(); + */ + + hostInfo = QHostInfo::fromName( host ); + if( onLookupHost( hostInfo ) ) + goto xx; + + QMessageBox::warning + ( + this, + "Netzwerkfehler", + "Der Server '" + host + "' ist \n" + "nicht erreichbar." + ); + return; + + +xx: _settings->setValue( miniCash::keyIsTcpSender, _ui->_isSender->isChecked() ); + _settings->setValue( miniCash::keyIsTcpReceiver, _ui->_isReceiver->isChecked() ); + _settings->setValue( miniCash::keyReceiverHost, host ); + _settings->setValue( miniCash::keyReceiverPort, port ); + + qDebug() << "-- isSender: " << _ui->_isSender->isChecked(); + qDebug() << "-- isReceiver: " << _ui->_isReceiver->isChecked(); + qDebug() << "-- host: " << host; + qDebug() << "-- port: " << port; + + return QDialog::accept(); + +} diff --git a/libMiniCash/mcnetworkdialog.h b/libMiniCash/mcnetworkdialog.h new file mode 100644 index 0000000..7575ce9 --- /dev/null +++ b/libMiniCash/mcnetworkdialog.h @@ -0,0 +1,62 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCNETWORKDIALOG_H +#define MCCNETWORKDIALOG_H + +#include +#include +#include +#include + +#include + +namespace Ui +{ + class MCNetworkDialog; +} + +/** + * @brief Hilfsdialog, setzt und überprüft die Netzwerkeinstellungen, + * zusätzlich zum normalen 'Setup'-Dialog. + */ + +class LIBMINICASH_EXPORT MCNetworkDialog : public QDialog +{ + + Q_OBJECT + +public: + + explicit MCNetworkDialog( QWidget* parent, QSettings* settings ); + virtual ~MCNetworkDialog(); + +public slots: + + void accept() override; + void onSetNetworkEnabled(bool); + void onTestHostEntry( const QString& entry = "" ); + bool onLookupHost( const QHostInfo& hostInfo ); + +protected: + + Ui::MCNetworkDialog* _ui{}; + + QSettings* _settings = nullptr; + bool _useNetwork = false; + +}; + + +#endif // MCCNETWORKDIALOG_H diff --git a/libMiniCash/mcnetworkdialog.ui b/libMiniCash/mcnetworkdialog.ui new file mode 100644 index 0000000..bb2bdce --- /dev/null +++ b/libMiniCash/mcnetworkdialog.ui @@ -0,0 +1,261 @@ + + + MCNetworkDialog + + + + 0 + 0 + 592 + 405 + + + + Netzwerkeinstellungen + + + + + + + + 11 + 11 + 471 + 36 + + + + + 16 + true + + + + Netzwerkeinstellungen + + + Qt::AutoText + + + + + + 10 + 50 + 632 + 3 + + + + Qt::Horizontal + + + + + + 10 + 345 + 571 + 16 + + + + Qt::Horizontal + + + + + + 20 + 70 + 401 + 24 + + + + Daten nur auf USB-Stick speichern + + + + + + 20 + 100 + 411 + 24 + + + + Daten über Netzwerk senden + + + + + + 10 + 130 + 571 + 211 + + + + Setup + + + + + 30 + 102 + 141 + 20 + + + + Servername, Port: + + + + + + 180 + 100 + 113 + 26 + + + + + + + 300 + 100 + 16 + 18 + + + + + 12 + true + + + + : + + + + + + 310 + 100 + 81 + 26 + + + + + + + 10 + 150 + 521 + 24 + + + + Dieser PC ist die Abrechnungskasse ('Server') + + + + + + 10 + 70 + 221 + 24 + + + + diese Kasse ist Sender + + + + + + 30 + 32 + 141 + 20 + + + + Eigener Name: + + + + + false + + + + 180 + 30 + 113 + 26 + + + + + + + + + + 402 + 100 + 151 + 28 + + + + Verbindung Testen + + + + + + 402 + 69 + 151 + 25 + + + + + + + + + + + 130 + 365 + 449 + 29 + + + + + 9 + true + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + diff --git a/libMiniCash/mcnetworkwidget.cpp b/libMiniCash/mcnetworkwidget.cpp new file mode 100644 index 0000000..818df8b --- /dev/null +++ b/libMiniCash/mcnetworkwidget.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + + miniCash + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + +#include +#include + +#include + +MCNetworkWidget::MCNetworkWidget( QWidget* parent ) + : QLabel{ parent }, _ui{ new Ui::MCNetworkWidget} +{ + + _ui->setupUi( this ); + _ui->_labelState->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter ); + + /// wir haben vier mögliche Zustände + /// - das Netz wird gar nicht verwendet + /// - noch nicht verbunden + /// - Verbindungsfehler + /// - Wir haben die gewünschte Verbindung + + QIcon iconOff ( miniCash::icnUnConnected ); + QIcon iconOn ( miniCash::icnConnected ); + QIcon iconServer( miniCash::icnServer ); + + _networkStates[miniCash::Disabled] = MCNetworkState( miniCash::cstDisabled, QIcon( iconOff.pixmap( QSize(64,64), QIcon::Disabled, QIcon::On ) ) ); + _networkStates[miniCash::UnConnected] = MCNetworkState( miniCash::cstUnConnected, QIcon( iconOff.pixmap( QSize(64,64), QIcon::Disabled, QIcon::On ) ) ); + _networkStates[miniCash::Error] = MCNetworkState( miniCash::cstError, iconOff ); + _networkStates[miniCash::Connected] = MCNetworkState( miniCash::cstConnected, iconOn ); + _networkStates[miniCash::IsServer] = MCNetworkState( miniCash::cstIsServer, QIcon( iconServer.pixmap( QSize(64,64), QIcon::Disabled, QIcon::On ) ) ); + _networkStates[miniCash::ServerReady] = MCNetworkState( miniCash::cstServerReady, iconServer ); + + /// erstmal sind wir neutral + setConnectionState( miniCash::Disabled ); + + /// hack: Netzwerksachen sollen erst ausgeführt werden, + /// wenn das Mainwindow zu sehen ist + ///QTimer::singleShot( 500, this, &MCConnectMainWindow::onStartNetworking ); + + /// Button nach aussen weiterleiten + connect( _ui->_buttonState, &QPushButton::clicked, this, + [=]() + { + emit showNetworkDialog(); + } ); + +} + + + +MCNetworkWidget::~MCNetworkWidget() +{ + delete _ui; +} + + +miniCash::CState MCNetworkWidget::connectionState() +{ + return _senderState; +} + + +void MCNetworkWidget::setConnectionState( miniCash::CState state ) +{ + qDebug() << "SET STATE:" << state; + _senderState = state; + _ui->_labelState->setText( _networkStates[_senderState].label ); + _ui->_buttonState->setIcon( _networkStates[_senderState].icon ); +} + +/* + QPixmap pixmap = icon.pixmap(QSize(22, 22), + isEnabled() ? QIcon::Normal + : QIcon::Disabled, + isChecked() ? QIcon::On + : QIcon::Off); + + +myPushButton = new QPushButton(); +myMovie = new QMovie("someAnimation.gif"); + +connect(myMovie,SIGNAL(frameChanged(int)),this,SLOT(setButtonIcon(int))); + +// if movie doesn't loop forever, force it to. +if (myMovie->loopCount() != -1) + connect(myMovie,SIGNAL(finished()),myMovie,SLOT(start())); + +myMovie->start(); +*/ + + + + + + + + + diff --git a/libMiniCash/mcnetworkwidget.h b/libMiniCash/mcnetworkwidget.h new file mode 100644 index 0000000..2185e26 --- /dev/null +++ b/libMiniCash/mcnetworkwidget.h @@ -0,0 +1,74 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCNETWORKWIDGET_H +#define MCCNETWORKWIDGET_H + +#include +#include +#include +#include + +#include + +namespace Ui +{ + class MCNetworkWidget; +} + +class LIBMINICASH_EXPORT MCNetworkWidget : public QLabel +{ + Q_OBJECT + +public: + + explicit MCNetworkWidget( QWidget* parent = nullptr ); + virtual ~MCNetworkWidget(); + + miniCash::CState connectionState(); + void setConnectionState( miniCash::CState state ); + +signals: + + void showNetworkDialog(); + +protected: + + struct MCNetworkState + { + MCNetworkState() + { + } + + MCNetworkState( const QString alabel, QIcon aicon ) + : label{ alabel }, icon{ aicon } + { + } + + QString label; + QIcon icon; + + }; + + Ui::MCNetworkWidget* _ui{}; + + miniCash::CState _senderState = miniCash::Disabled; + MCNetworkState _networkStates[miniCash::CStateSize]; + +}; + +#endif /// MCCNETWORKWIDGET_H + + + diff --git a/libMiniCash/mcnetworkwidget.ui b/libMiniCash/mcnetworkwidget.ui new file mode 100644 index 0000000..49bb5d8 --- /dev/null +++ b/libMiniCash/mcnetworkwidget.ui @@ -0,0 +1,69 @@ + + + MCNetworkWidget + + + + 0 + 0 + 140 + 90 + + + + ConnectionState + + + background: groove gray; + + + + true + + + + 40 + 2 + 64 + 64 + + + + + + + + + + + 64 + 64 + + + + false + + + true + + + + + + 5 + 62 + 130 + 20 + + + + color:white; + + + + + + + + + diff --git a/libMiniCash/mcprinter.cpp b/libMiniCash/mcprinter.cpp new file mode 100644 index 0000000..6c109eb --- /dev/null +++ b/libMiniCash/mcprinter.cpp @@ -0,0 +1,28 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include + +/** + * @brief Erzeugt einen QPrinter mit den gewünschten Voreinstellungen. + */ + +MCPrinter::MCPrinter() +{ + // Seite einrichten + setPageOrientation( QPageLayout::Portrait ); + setPageSize( QPageSize( QPageSize::A4 ) ); + setFullPage( false ); + setPrintRange( QPrinter::AllPages ); +} diff --git a/libMiniCash/mcprinter.h b/libMiniCash/mcprinter.h new file mode 100644 index 0000000..12a9521 --- /dev/null +++ b/libMiniCash/mcprinter.h @@ -0,0 +1,37 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCPRINTER_H +#define MCPRINTER_H + +#include + +#include + + +/** + * @brief Convenience-Klasse um einen vorkonfigurierten + * Printer zu erzeugen. + */ + +class LIBMINICASH_EXPORT MCPrinter : public QPrinter +{ + +public: + + MCPrinter(); + +}; + +#endif // MCPRINTER_H diff --git a/libMiniCash/mcreceiver.cpp b/libMiniCash/mcreceiver.cpp new file mode 100644 index 0000000..55bc6a8 --- /dev/null +++ b/libMiniCash/mcreceiver.cpp @@ -0,0 +1,173 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +/** + * @brief Destructor, alles schließen + */ + +MCReceiver::~MCReceiver() +{ + onDiscardConnection(); + deleteLater(); +} + + +/** + * @brief Empfangsbereit machen: hier passiert weiter nichts, + * erst wir nur der parameter 'port' neu gesetzt, die + * entsprechende Aktion wird über ein SIGNAL getriggert. + */ + +void MCReceiver::setupConnection( int port ) +{ + qDebug() << "MCReceiver::setupConnection: " << port; + _port = port; +} + + +/** + * @brief Slot, + */ + +void MCReceiver::onCreateConnection() +{ + if( isListening() ) + onDiscardConnection(); + + //qDebug( "MCReceiver::onCreateConnection() 1: listen...." ); + + if( listen( QHostAddress::Any, _port ) ) + { + //qDebug( "MCReceiver::onCreateConnection() 2: Server is listening..."); + connect( this, &QTcpServer::newConnection, this, &MCReceiver::onNewConnection ); + //qDebug( "MCReceiver::onCreateConnection() 3: Server is listening..."); + + emit connectionChanged( miniCash::IsServer ); + + return; + } + + emit connectionChanged( miniCash::Error ); + + //QMessageBox::critical(this,"QTCPServer",QString("Unable to start the server: %1.").arg(errorString())); + //exit(EXIT_FAILURE); + +} + + +void MCReceiver::onDiscardConnection() +{ + + //qDebug( "MCReceiver::onDiscardConnection()"); + + foreach( QTcpSocket* socket, _connections ) + { + socket->close(); + socket->deleteLater(); + } + close(); + + emit connectionChanged( miniCash::UnConnected ); + +} + + + +/** + * @brief Nimmt neue Connections an und schreibt sie + * in die Connectionliste. + */ + +void MCReceiver::onNewConnection() +{ + + while( hasPendingConnections() ) + appendToSocketList( nextPendingConnection() ); + + emit connectionChanged( miniCash::ServerReady ); +} + + +void MCReceiver::appendToSocketList( QTcpSocket* socket ) +{ + _connections.insert(socket); + connect( socket, &QTcpSocket::readyRead, this, &MCReceiver::onReadReady ); + connect( socket, &QTcpSocket::disconnected, this, &MCReceiver::onSocketDisconnected ); + + //qDebug() << QString("INFO :: Client with sockd:%1 has just entered the room").arg(socket->socketDescriptor() ); + +} + + +void MCReceiver::onReadReady() +{ + + QTcpSocket* socket = reinterpret_cast( sender() ); + QByteArray buffer; + + QDataStream socketStream( socket ); + socketStream.setVersion( QDataStream::Qt_5_15 ); + + socketStream.startTransaction(); + socketStream >> buffer; + + if( !socketStream.commitTransaction() ) + return; + /* + { + QString message = QString("%1 :: Waiting for more data to come..").arg(socket->socketDescriptor()); + emit newData(message); + return; + } + */ + + // warum?? + //QString message = QString::fromStdString( buffer.toStdString() ); + + emit newTransaction( QString( buffer ) ); + +} + + + +void MCReceiver::onSocketDisconnected() +{ + QTcpSocket* socket = reinterpret_cast(sender()); + + QSet::iterator it = _connections.find(socket); + if (it != _connections.end()) + { + //displayMessage( QString("INFO :: A client has just left the room").arg(socket->socketDescriptor()) ); + _connections.remove( *it ); + } + + socket->deleteLater(); +} + + + + diff --git a/libMiniCash/mcreceiver.h b/libMiniCash/mcreceiver.h new file mode 100644 index 0000000..52a101e --- /dev/null +++ b/libMiniCash/mcreceiver.h @@ -0,0 +1,66 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCRECEIVER_H +#define MCRECEIVER_H + +#include +#include + +#include + + +/** + * @brief Ein angespasster QTcpServer + */ + +class LIBMINICASH_EXPORT MCReceiver : public QTcpServer +{ + + Q_OBJECT + +public: + + explicit MCReceiver() = default; + virtual ~MCReceiver(); + + void setupConnection( int port ); + +public slots: + + void onCreateConnection(); + void onDiscardConnection(); + +signals: + + void connectionChanged( miniCash::CState newState ); + void newTransaction( QString data ); + +protected slots: + + void onNewConnection(); + void onReadReady(); + void onSocketDisconnected(); + +protected: + + void appendToSocketList(QTcpSocket* socket); + + int _port = -1; + QSet _connections; + +}; + + +#endif // MCRECEIVER_H diff --git a/libMiniCash/mcsalesitem.h b/libMiniCash/mcsalesitem.h new file mode 100644 index 0000000..44cf1c6 --- /dev/null +++ b/libMiniCash/mcsalesitem.h @@ -0,0 +1,67 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCSALESITEM_H +#define MCSALESITEM_H + + +#include + +#include + + +//class MCSalesModel; + + +/** + * @brief Ein verkaufter Artikel + * + * Ein verkaufter Artikel : Verkäufenummrer, Listennummer und Preis + */ + + +struct LIBMINICASH_EXPORT MCSalesItem +{ + + QString trSellerID; + QString trItemNo; + double trPrice; + + MCSalesItem() + { + + } + + MCSalesItem( const QString& id, const QString& no, double price ) + : trSellerID( id ) , trItemNo( no ), trPrice( price ) + { + + } + + QString toString() const + { + QString result( "id: %1 itemno: %2 price: %3" ); + result = result.arg( trSellerID, trItemNo ).arg( trPrice ); + return result; + } + + bool operator==(const MCSalesItem& other) const + { + return (trSellerID == other.trSellerID && trItemNo == other.trItemNo && trPrice == other.trPrice); + } + +}; + + +#endif // MCSALESITEM_H diff --git a/libMiniCash/mcsalesitemmap.cpp b/libMiniCash/mcsalesitemmap.cpp new file mode 100644 index 0000000..f15f182 --- /dev/null +++ b/libMiniCash/mcsalesitemmap.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + +#include +#include +#include + + +/** + * @brief speichert verkaufte Artikel. + * + * Speichert verkaufte Artikel pro Kunde nach der laufenden Nummer des Artikels + */ + +MCSalesItemMap::MCSalesItemMap() +: QMap() + +{ + +} + + +/** + * @brief einen neuen Eintrag erzeugen + * + * @param id Die Kunden- bzw. Verkäufernummer + * @param num Die laufende Nummer des verkauften Artikels + * @param strprice der Preis des Artikels + */ + +void MCSalesItemMap::appendItem( const QString& id, const QString& num, const QString& strprice ) +{ + + // doppelt vergebene laufende nummern werden + // gekennzeichnet: '025' -> '#025' + QString key = num; + if( contains( num ) ) + { + key = '#' + num; + } + + // Wir wollen beim Dateiformat kompatibel bleiben: + // 0003 1211 012 2,00 02-13-2013 10:39:55 + // also: float mit komma, ohne Euro-Zeichen + + insert( key, MCSalesItem( id, key, MCSalesModel::toDoubleLocale( strprice ) ) ); + +} + + +/** + * @brief Dump nach cout zu debugging-zwecken + */ + +void MCSalesItemMap::dump() const +{ + MCSalesItemMap::const_iterator pos = begin(); + for( ; pos != end(); ++pos ) + { + qDebug() << "key:" << pos.key() << " value: " << pos.value().toString(); + } + qDebug() << Qt::endl; +} + + + + diff --git a/libMiniCash/mcsalesitemmap.h b/libMiniCash/mcsalesitemmap.h new file mode 100644 index 0000000..a450d94 --- /dev/null +++ b/libMiniCash/mcsalesitemmap.h @@ -0,0 +1,55 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCSALESITEMMAP_H +#define MCSALESITEMMAP_H + +#include +#include + +#include +#include + + + +/** + * @brief Speichert verkaufte Artikel. + * + * Speichert verkaufte Artikel pro Kunde nach der laufenden Nummer des Artikels. + */ + +class MCSalesItemMap : public QMap +{ + +public: + + enum Index + { + Count = 0, + SellerID, + ItemNo, + Price, + MaxSize + }; + + MCSalesItemMap(); + + void appendItem( const QString& id, const QString& no, const QString& price ); + + void dump() const; + + +}; + +#endif // MCSALESITEMMAP_H diff --git a/libMiniCash/mcsalesmodel.cpp b/libMiniCash/mcsalesmodel.cpp new file mode 100644 index 0000000..8908964 --- /dev/null +++ b/libMiniCash/mcsalesmodel.cpp @@ -0,0 +1,181 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + +#include +#include + +using namespace std; + + +/** + * @brief Macht aus int x den String 000x zum schönaussehen. + * @param count der Wert + * @param len die voranzustellenden Nullen + * + * Macht aus int x den String 000x zum schönaussehen. + * + */ + +QString MCSalesModel::formatInt(int count, int len ) +{ + QString result( "%0" ); + result = result.arg( count, len, 10, QChar( '0' ) ); + return result; +} + + +/** + * @brief Formatiert einen double als String im Währungsformat: 2.3 -> 2,30 € + * + * Formatiert einen double als String im Währungsformat: 2.3 -> 2,30 € + * + */ + +QString MCSalesModel::toCurrency( double amount ) +{ + QLocale loc; + return loc.toCurrencyString( amount ); +} + + +/** + * @brief Konvertiert einen String-Zahlenwert in + * deutscher Schreibweise zum double. + * + * Macht aus einem Zahlen-String in deutscher Schreibweise: + * 1,50 (statt 1.5) einen double. + * + */ + +double MCSalesModel::toDoubleLocale( QString amount ) +{ + QLocale converter( QLocale::German ); + bool ok; + return converter.toDouble( amount, &ok ) ; +} + + +/** + * @brief Konvertiert einen Währungs-String zurück ins Gleitkommaformat. + * @param Eingabewert als String + * @return 0.0 im Fehlerfall, sonst: Der Zahlenwert des String + * + * Das €-Zeichen wird abgeschitten: "23,20 €" wird zu 23.2 + * + */ + +double MCSalesModel::fromCurrency( QString amount ) +{ + + if( amount.isEmpty() || amount.isNull() ) + return 0.0; + + QString raw = amount.split( ' ' ).at(0); + return toDoubleLocale( raw ); +} + + +/** + * @brief Defaultkonstruktor. + */ + +MCSalesModel::MCSalesModel( QObject *parent ) : + QStandardItemModel( parent ) +{ + + QStringList header; + header << "Kunde" << "Verkäufernummer" << "lfd. Nummer" << "Verkaufspreis"; + setHorizontalHeaderLabels( header ); + +} + + +/** + * @brief Speichert einen Verkaufseintrag. + * + * @param trCount laufende Transaktionsnummer + * @param trSellerID die Kundennummer + * @param trItemNo die Artikelnummer + * @param trPrice der Preis + * + */ + +void MCSalesModel::appendEntry( const QString& trCount, const QString& trSellerID, const QString& trItemNo, const QString& trPrice ) +{ + + QStandardItem* item1 = new QStandardItem( trCount ); + QStandardItem* item2 = new QStandardItem( trSellerID ); + // wir formatieren gleich auf 3 Stellen: 12 -> 012 + QStandardItem* item3 = new QStandardItem( formatInt( trItemNo.toInt(), 3 ) ); + // wild: price ist ein string mit komma: "2,6" + QStandardItem* item4 = new QStandardItem( toCurrency( toDoubleLocale( trPrice ) ) ); + //QStandardItem* item4 = new QStandardItem( "77,77 €" ); + item1->setTextAlignment ( Qt::AlignCenter ); + item2->setTextAlignment ( Qt::AlignCenter ); + item3->setTextAlignment ( Qt::AlignCenter ); + item4->setTextAlignment ( Qt::AlignRight ); + + QList items; + items.append( item1 ); + items.append( item2 ); + items.append( item3 ); + items.append( item4 ); + + appendRow( items ); + +} + + +/** + * @brief Transaktionen aus einem TextStream einlesen + * @param input TextStream zeigt auf eine Datei mit Transaktionen (==Verkäufen) + */ + +void MCSalesModel::appendTransactions( QTextStream& input ) +{ + + + while( !input.atEnd() ) + { + + QString line = input.readLine(); + QStringList entries = line.simplified().split( QRegularExpression("\\s+") ); + + if( entries.size() < MCSalesItemMap::MaxSize ) + continue; + + const QString& tcount = entries[ MCSalesItemMap::Count ]; + const QString& sellerID = entries[ MCSalesItemMap::SellerID ]; + const QString& itemNo = entries[ MCSalesItemMap::ItemNo ]; + const QString& price = entries[ MCSalesItemMap::Price ]; + + /// die Transaktionsnummer entspricht der Anzahl der Kunden + /// und auch anzeigen + appendEntry + ( + tcount, + sellerID, + itemNo, + price + ); + + + } /// while + + +} + diff --git a/libMiniCash/mcsalesmodel.h b/libMiniCash/mcsalesmodel.h new file mode 100644 index 0000000..1bb6423 --- /dev/null +++ b/libMiniCash/mcsalesmodel.h @@ -0,0 +1,55 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCSALESMODEL_H +#define MCSALESMODEL_H + +#include +#include + +#include + + +/** + * @brief Das Itemmodel zur Anzeige der verkauften Artikel + * + * @see QStandardItemModel + * @see QTreeView + * + * MCSalesModel ist ein QStandardItemModel zur Anzeige der verkauften Artikel an einer Kasse. + * Mit @see appendEntry wurde eine neue Methode hinzugefügt: Hier werden die Werte der + * Eingabefelder formatiert und per ("flacher") TreeView angezeigt. + * + */ + +class LIBMINICASH_EXPORT MCSalesModel : public QStandardItemModel +{ + Q_OBJECT + +public: + + static QString formatInt( int count, int len=4 ); /// Macht aus int x den String 000x zum schönaussehen. + static QString toCurrency( double amount ); /// Formatiert einen double als String im Währungsformat: 2.3 -> 2,30 EUR + static double toDoubleLocale( QString amount ); /// Macht aus einem Zahlen-String in deutscher Schreibweise: 1,50 (statt 1.5) einen double. + static double fromCurrency( QString amount ); /// Versucht, das EUR-Zeichen abzusäbeln: "23,20 EUR" wird zu 23.2 + + explicit MCSalesModel( QObject* parent = nullptr ); + + void appendEntry( const QString& trCount, const QString &trSellerID, const QString &trItemNo, const QString &trPrice ); + void appendTransactions( QTextStream& input ); + +}; + + +#endif // MCSALESMODEL_H diff --git a/libMiniCash/mcsalessummary.cpp b/libMiniCash/mcsalessummary.cpp new file mode 100644 index 0000000..6bcf246 --- /dev/null +++ b/libMiniCash/mcsalessummary.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include + +#include +#include +#include + +/** + * @brief MCSalesSummary::MCSalesSummary: speichert die Verkaufsliste einzelner Kunden nach Kundennummer. + */ + +MCSalesSummary::MCSalesSummary() +: QMap() +{ + +} + + +/** + * @brief Liest jeweils eine Transaktionsdatei ein. + * + * @param filename der Dateiname + * @param salescount die Gesamtanzahl der Verkäufe, wird hier hochgezählt + * @param model das Datenmodel + * @return die Anzahl der Verkäufe in dieser Datei + */ + +int MCSalesSummary::appendFromFile( const QString& filename, int& customercount, MCSalesModel& model ) +{ + QFile file( filename ); + if ( !file.open(QIODevice::ReadOnly | QIODevice::Text ) ) + return -1; // throw... + + int salescount = 0; + + QSet customerSet; + QTextStream input(&file); + while( !input.atEnd() ) + { + + QString line = input.readLine(); + QStringList entries = line.simplified().split( QRegularExpression("\\s+") ); + + if( entries.size() < MCSalesItemMap::MaxSize ) + continue; + + const QString& tcount = entries[ MCSalesItemMap::Count ]; + const QString& sellerID = entries[ MCSalesItemMap::SellerID ]; + const QString& itemNo = entries[ MCSalesItemMap::ItemNo ]; + const QString& price = entries[ MCSalesItemMap::Price ]; + + /// Transaktionen des Kunden holen, eventuell erzeugen + MCSalesItemMap& result = operator[]( sellerID ); + customerSet.insert( tcount ); + + /// speichern ... + result.appendItem + ( + sellerID, + itemNo, + price + ); + + /// die Transaktionsnummer entspricht der Anzahl der Kunden + /// und auch anzeigen + model.appendEntry + ( + tcount, + sellerID, + itemNo, + price + ); + + salescount++; + + } + customercount = customerSet.count(); + return salescount; + +} + + +/** + * @brief Dump nach cout zu debugging-zwecken + */ + +void MCSalesSummary::dump() +{ + // for( const QString& key : *this->keys() ) haut so nicht hin, lernen + foreach (const QString &str, keys()) + { + qDebug() << str << ':' << ": "; + value( str ).dump(); + } + +} + + + + + diff --git a/libMiniCash/mcsalessummary.h b/libMiniCash/mcsalessummary.h new file mode 100644 index 0000000..1e5aa4a --- /dev/null +++ b/libMiniCash/mcsalessummary.h @@ -0,0 +1,54 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + +#ifndef MCSALESSUMMARY_H +#define MCSALESSUMMARY_H + +#include +#include + +#include +#include + +class MCSalesModel; + +/** + * @brief Speichert die Verkaufsliste einzelner Kunden nach Kundennummer. + * + * Verwaltet _alle_ Verkaufstransaktionen, wird benötigt für die Endabrechnung. + * Die einzelen Verkäufe an der Kasse werden von @see MCSalesItemMap abgedeckt. + * + * Die einzelen Kassendateien werden nacheinander eingelesen und dann für die + * Endabrechnung ausgewertet. Für jede Kundennummer wird eine Map mit verkauften Artikeln + * angelegt, der Schlüssel ist die laufende Nummer des Artikels, die Verwendung einer Map + * sichert die automatische Sortierung der Einträge. Die Artikelmaps landen wiederum in der + * "Hauptmap", mit der CustomerId als Schlüssel. Ergebnis ist eine sortierte Struktur mit allen + * Kunden und den jeweils verkauften Artikeln. QMultiMap taugt hierfür leider nicht, + * es wird also eine "Map of Maps" implementiert. + * + */ + +class LIBMINICASH_EXPORT MCSalesSummary : public QMap +{ + +public: + + explicit MCSalesSummary(); + + int appendFromFile( const QString& filename, int& customercount, MCSalesModel& model ); + + void dump(); + +}; + +#endif // MCSALESSUMMARY_H diff --git a/libMiniCash/mcsender.cpp b/libMiniCash/mcsender.cpp new file mode 100644 index 0000000..3b49c1f --- /dev/null +++ b/libMiniCash/mcsender.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + + +/** + * @brief MCSender::MCSender + */ + +MCSender::MCSender() +{ + +} + + +/** + * @brief MCSender::~MCSender + */ + +MCSender::~MCSender() +{ + if( isOpen() ) + close(); +} + + +void MCSender::setupConnection( const QString& host, int port ) +{ + //qDebug() << "\n\nMCSender::setupConnection(): " << host << " : " << port; + _port = port; + _host = host; +} + + +/** + * @brief MCSender::initConnection + * @param parent + * @param host + * @param port + * @return + */ + +void MCSender::onCreateConnection() +{ + if( isOpen() ) + onDiscardConnection(); + + //qDebug() << "MCSender::onCreateConnection()"; + + connectToHost( _host, _port, QIODevice::WriteOnly ); + if( waitForConnected( miniCash::senderTimeout ) ) + { + emit connectionChanged( miniCash::Connected ); + return; // allet jut + } + + emit errorOccurred( error() ); + +} + + +/** + * @brief MCSender::onDiscardConnection + */ + +void MCSender::onDiscardConnection() +{ + // qDebug() << "MCSender::onDiscardConnection()"; + flush(); + if( isOpen() ) + close(); + + emit connectionChanged( miniCash::UnConnected ); + +} + + +/** + * @brief MCSender::writeTransaction + * @param transaction + */ + +void MCSender::onSendTransaction( const QString& transaction ) +{ + + if( !isOpen() ) + { + emit connectionChanged( miniCash::UnConnected ); + //qDebug( "---QTCPClient: Not connected"); + return; + } + + QDataStream socketStream( this ); + socketStream.setVersion(QDataStream::Qt_5_15); + QByteArray byteArray = transaction.toUtf8(); + + socketStream << byteArray; + +} + + + diff --git a/libMiniCash/mcsender.h b/libMiniCash/mcsender.h new file mode 100644 index 0000000..bd02495 --- /dev/null +++ b/libMiniCash/mcsender.h @@ -0,0 +1,58 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCSENDER_H +#define MCSENDER_H + +#include +#include + +#include + + + +/** + * @brief Ein angepasstes QTcpSocket zur Datenübertragung + */ + +class LIBMINICASH_EXPORT MCSender : public QTcpSocket +{ + Q_OBJECT + +public: + + MCSender(); + virtual ~MCSender(); + + void setupConnection( const QString& host, int port ); + +signals: + + void connectionChanged( miniCash::CState newState ); + +public slots: + + void onCreateConnection(); + void onDiscardConnection(); + + void onSendTransaction( const QString& transaction ); + +protected: + + int _port = -1; + QString _host; + +}; + +#endif // MCSENDER_H diff --git a/libMiniCash/mcsetupdialog.cpp b/libMiniCash/mcsetupdialog.cpp new file mode 100644 index 0000000..f24153b --- /dev/null +++ b/libMiniCash/mcsetupdialog.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/** + * @brief Der Setup-Dialog: Hier werden die Vorgabewerte gesetzt. + */ + +MCSetupDialog::MCSetupDialog( QWidget* parent, QSettings* settings ) + : QDialog{ parent }, _ui{new Ui::MCSetupDialog}, _settings{ settings } + +{ + + _ui->setupUi( this ); + setupDefaults(); + + // Murx, FIX! das sollte über den Translator gehen + _ui->_buttonBox->button( QDialogButtonBox::Ok )->setText( "Speichern" ); + _ui->_buttonBox->button( QDialogButtonBox::Cancel )->setText( "Abbrechen" ); + + connect( _ui->_buttonReset, SIGNAL( clicked() ), this, SLOT( onReset() ) ); + connect( _ui->_buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) ); + connect( _ui->_buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) ); + connect( _ui->_buttonFile, SIGNAL( clicked() ), this, SLOT( onChooseVendorsFile() ) ); + connect( _ui->_buttonViewFile, SIGNAL( clicked() ), this, SLOT( onViewVendorsFile() ) ); + + _ui->_tabWidget->setCurrentIndex( 0 ); + +} + + +/** + * @brief Destruktor. + */ + +MCSetupDialog::~MCSetupDialog() +{ + delete _ui; +} + + +/** + * @brief Vorgabewerte ins Form laden + */ + +void MCSetupDialog::setupDefaults() +{ + // Vorgabewerte setzen + QString driveLetter = _settings->value( miniCash::keyMobileDrive, miniCash::mobileDrive ).toString(); + _ui->_driveMobile->addItem( driveLetter ); + _ui->_driveMobile->setCurrentText( driveLetter ); + _ui->_trProfit->setValue( _settings->value( miniCash::keyProfit, miniCash::profit ).toInt() ); + _ui->_selfID->setValue( _settings->value( miniCash::keySelfID, miniCash::selfID ).toInt() ); + _ui->_trFooterText->setText( _settings->value( miniCash::keyFooterText ).toString() ); + + _ui->_buttonViewFile->setEnabled( false ); + QString filePath = _settings->value( miniCash::keyAddressFile ).toString(); + if( !filePath.isEmpty() ) + { + QFileInfo addressFile( filePath ); + if( addressFile.exists() ) + { + _ui->_addressFile->setText( addressFile.fileName() ); + _ui->_buttonViewFile->setEnabled( true ); + } + } + + +} + + +/** + * @brief Setzt alle voreinstellungen zurück auf den jeweiligen Default-Wert. + */ + +void MCSetupDialog::onReset() +{ + int ret = QMessageBox::warning(this, "miniCash Setup", + tr("Sollen die Voreinstellugen\n" + "neu geladen werden?"), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + + if( ret == QMessageBox::Cancel ) + return; + + _settings->clear(); + setupDefaults(); + + /// neu: wir setzen hier auch schon die network-defaults, weil der dialog + /// jetzt auch von minicash.connect verwendet wird. + + _settings->setValue( miniCash::keyIsTcpSender, miniCash::isTcpSender ); + _settings->setValue( miniCash::keyReceiverHost, "" ); + _settings->setValue( miniCash::keyReceiverPort, miniCash::receiverPort ); + _settings->setValue( miniCash::keyIsTcpReceiver, miniCash::isTcpReceiver ); + _settings->setValue( miniCash::keyAddressFile, "" ); + /// gefährlich + _settings->setValue( miniCash::keyTransCount, "1" ); + +} + + +void MCSetupDialog::onChooseVendorsFile() +{ + + _ui->_buttonViewFile->setEnabled( false ); + QString docDir = QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ); + QString filePath = QFileDialog::getOpenFileName( this, tr("Adressdatei"), docDir, tr("CSV Datei (*.csv *.txt)") ); + + if( !filePath.isEmpty() ) + { + _ui->_buttonViewFile->setEnabled( true ); + QFileInfo addressFile( filePath ); + _settings->setValue( miniCash::keyAddressFile, addressFile.absoluteFilePath() ); + _ui->_addressFile->setText( addressFile.fileName() ); + } +} + + +void MCSetupDialog::onViewVendorsFile() +{ + QString filePath = _settings->value( miniCash::keyAddressFile ).toString(); + if( filePath.isEmpty() || !QFileInfo::exists( filePath ) ) + return; + + MCVendorsDialog( this, filePath ).exec(); + +} + + +/** + * @brief ok gedrückt: geänderte Daten übernehmen + */ + +void MCSetupDialog::accept() +{ + + const QString& mDrive = _ui->_driveMobile->currentText(); + const QString& profit = _ui->_trProfit->cleanText(); + const QString& prefix = _ui->_selfID->cleanText(); + + // Murx, FIX! das sollte über den Translator gehen + if( profit.isEmpty() || prefix.isEmpty() ) + { + QMessageBox::warning + ( + this, + "Eingabefehler", + "Die Felder\n - lokales Laufwerk', 'KassenNr.'\n " + "sowie 'Anteil Kindergarten' müssen belegt sein." + ); + return; + } + + _settings->setValue( miniCash::keyMobileDrive, mDrive ); + _settings->setValue( miniCash::keyProfit, profit ); + _settings->setValue( miniCash::keySelfID, prefix ); + _settings->setValue( miniCash::keyFooterText, _ui->_trFooterText->document()->toPlainText() ); + + return QDialog::accept(); + +} diff --git a/libMiniCash/mcsetupdialog.h b/libMiniCash/mcsetupdialog.h new file mode 100644 index 0000000..bf31b51 --- /dev/null +++ b/libMiniCash/mcsetupdialog.h @@ -0,0 +1,69 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCSETUPDIALOG_H +#define MCSETUPDIALOG_H + +#include +#include + +#include + +namespace Ui +{ + class MCSetupDialog; +} + +/** + * @brief Der Setup-Dialog: Hier werden die Grundeinstellungen vorgenommen. + * + * Im Setup-Dialog werden folgende Grundeinstellungen vorgenommen: + * für den Kassenmodus: + * - die Kassennummer + * - das lokale Datenlaufwerk, Vorgabe: E:\ + * - das "Transport"-Laufwerk, auf das die Kassendaten zur Abrechnung kopiert werden + * für den Abrechnungsmodus: + * - Das Laufwerk, vom dem die zusammengeführten Kassendaten geladen werden, Vorgabe: E:\ + * - Der Gewinnanteil des Kindergartens in Prozent, Vorgabe: 15% + * - Ein optionaler Fußzeilentext, wird mit auf die Abrechnungen gedruckt. + */ + +class LIBMINICASH_EXPORT MCSetupDialog : public QDialog +{ + Q_OBJECT + +public: + + explicit MCSetupDialog( QWidget* parent, QSettings* settings ); + virtual ~MCSetupDialog(); + + void accept(); + void setupDefaults(); + +public slots: + + void onReset(); + void onChooseVendorsFile(); + void onViewVendorsFile(); + +protected: + + Ui::MCSetupDialog* _ui{}; + + QSettings* _settings = nullptr; + +}; + + +#endif // MCSETUPDIALOG_H diff --git a/libMiniCash/mcsetupdialog.ui b/libMiniCash/mcsetupdialog.ui new file mode 100644 index 0000000..bb849e7 --- /dev/null +++ b/libMiniCash/mcsetupdialog.ui @@ -0,0 +1,364 @@ + + + MCSetupDialog + + + + 0 + 0 + 650 + 400 + + + + miniCash Setup + + + + + + + 9 + true + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + + + + + 16 + true + + + + Einstellungen + + + Qt::AutoText + + + + + + + Qt::Horizontal + + + + + + + + 9 + true + + + + 0 + + + + diese Kasse + + + + + 340 + 20 + 51 + 24 + + + + + + + 11 + 21 + 77 + 18 + + + + + 9 + true + + + + KassenNr. + + + + + + 340 + 60 + 51 + 24 + + + + + 0 + 0 + + + + + + + 10 + 60 + 321 + 18 + + + + + 9 + true + + + + Laufwerk zum Datentransport (z.B. 'F:\') + + + + + + 340 + 145 + 93 + 29 + + + + Reset + + + + + + 10 + 150 + 321 + 18 + + + + + 9 + true + + + + Alle Programm-Einstellungen zurücksetzen + + + + + + 10 + 105 + 321 + 18 + + + + + 9 + true + + + + Adressdatei im CSV-Format (optional) + + + + + + 372 + 100 + 141 + 29 + + + + + + + 340 + 100 + 29 + 29 + + + + + + + + :/images/open.png:/images/open.png + + + + + + 520 + 100 + 81 + 29 + + + + Anzeigen + + + + + + Abrechnung + + + + + 10 + 90 + 601 + 151 + + + + + 9 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:700; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-weight:400;"><br /></p></body></html> + + + + + + 10 + 70 + 182 + 18 + + + + + 9 + true + + + + Fußzeilentext (optional) + + + Qt::AutoText + + + + + + 210 + 21 + 46 + 24 + + + + + 0 + 0 + + + + + + + 12 + 21 + 186 + 18 + + + + + 9 + true + + + + Anteil Kindergarten in % + + + + + + + + + + SWDriveSelector + QComboBox +
swdriveselector.h
+
+
+ + + + + + _buttonBox + accepted() + MCSetupDialog + accept() + + + 257 + 451 + + + 295 + 241 + + + + + _buttonBox + rejected() + MCSetupDialog + reject() + + + 257 + 451 + + + 295 + 241 + + + + +
diff --git a/libMiniCash/mctransactionview.cpp b/libMiniCash/mctransactionview.cpp new file mode 100644 index 0000000..5068381 --- /dev/null +++ b/libMiniCash/mctransactionview.cpp @@ -0,0 +1,33 @@ +/*************************************************************************** + + miniCash + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + + +MCTransactionView::MCTransactionView( QWidget* parent ) + : QFrame( parent ), _ui{new Ui::MCTransactionView} +{ + _ui->setupUi( this ); +} + +MCTransactionView::~MCTransactionView() +{ + +} + +void MCTransactionView::onTransactionReceived( const QString& transaction ) +{ + _ui->_textView->appendPlainText( transaction ); +} diff --git a/libMiniCash/mctransactionview.h b/libMiniCash/mctransactionview.h new file mode 100644 index 0000000..1a9dacf --- /dev/null +++ b/libMiniCash/mctransactionview.h @@ -0,0 +1,46 @@ +/*************************************************************************** + + miniCash + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCTRANSACTIONVIEW_H +#define MCCTRANSACTIONVIEW_H + +#include + +#include + +namespace Ui +{ + class MCTransactionView; +} + +class LIBMINICASH_EXPORT MCTransactionView : public QFrame +{ + Q_OBJECT + +public: + + explicit MCTransactionView( QWidget* parent = nullptr ); + virtual ~MCTransactionView(); + +public slots: + + void onTransactionReceived( const QString& transaction ); + +protected: + + Ui::MCTransactionView* _ui{}; + +}; + +#endif // MCCTRANSACTIONVIEW_H diff --git a/libMiniCash/mctransactionview.ui b/libMiniCash/mctransactionview.ui new file mode 100644 index 0000000..f649286 --- /dev/null +++ b/libMiniCash/mctransactionview.ui @@ -0,0 +1,46 @@ + + + MCTransactionView + + + + 0 + 0 + 793 + 624 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Roboto Mono + 9 + + + + true + + + + + + + + diff --git a/libMiniCash/mctreeview.cpp b/libMiniCash/mctreeview.cpp new file mode 100644 index 0000000..abfd9c4 --- /dev/null +++ b/libMiniCash/mctreeview.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + + +/** + * @brief Konstruktor, setzt die Default-Styles. + * @param parent + */ + +MCTreeView::MCTreeView( QWidget* parent ) + : QTreeView( parent ) +{ + header()->setDefaultAlignment ( Qt::AlignHCenter ); + header()->setMinimumSectionSize( 150 ); + header()->setDefaultSectionSize( 185 ); + setStyleSheet("QHeaderView::section { background-color:#eeeeee }"); +} + + +MCTreeView::~MCTreeView() +{ + +} diff --git a/libMiniCash/mctreeview.h b/libMiniCash/mctreeview.h new file mode 100644 index 0000000..ff2294c --- /dev/null +++ b/libMiniCash/mctreeview.h @@ -0,0 +1,45 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCTREEVIEW_H +#define MCTREEVIEW_H + +#include +#include +#include + +#include + + +/** + * @brief The MCTreeView class: Eine angepasste QTreeView + * + * Convenience-Klasse: Konfiguriert dei QTreeView als Listenansicht + * mit verschiebbaren Header-Spalten + */ + +class LIBMINICASH_EXPORT MCTreeView : public QTreeView +{ + + Q_OBJECT + +public: + + MCTreeView( QWidget* parent = nullptr ); + virtual ~MCTreeView(); + +}; + + +#endif // MCTREEVIEW_H diff --git a/libMiniCash/mcvendorsdialog.cpp b/libMiniCash/mcvendorsdialog.cpp new file mode 100644 index 0000000..9c66cfe --- /dev/null +++ b/libMiniCash/mcvendorsdialog.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + +#include +#include + +MCVendorsDialog::MCVendorsDialog( QWidget* parent, const QString& filePath ) + : QDialog( parent ), _ui{new Ui::MCVendorsDialog} + +{ + _ui->setupUi( this ); + loadVendorsFile( filePath ); + + connect( _ui->_buttonOk, &QPushButton::clicked, this, + [=] + { + accept(); + } ); +} + + +MCVendorsDialog::~MCVendorsDialog() +{ + delete _ui; +} + + +void MCVendorsDialog::loadVendorsFile( const QString& filePath ) +{ + + QFile file( filePath ); + + if( !file.open(QFile::ReadOnly | QFile::Text) ) + return; + + /// Create a data model for the mapping table from a CSV file + int cols[]{ 0, 3, 4, 5 }; + _csvModel.setColumnCount( 4 ); + _csvModel.setHorizontalHeaderLabels( QStringList( {"Nummer", "Name", "Anschrift", "Telephon"} ) ); + _ui->_vendorsView->setModel( &_csvModel ); + _ui->_vendorsView->setStyleSheet("QHeaderView::section { background-color:#eeeeee }"); + _ui->_vendorsView->setCornerButtonEnabled( false ); + // Open the file from the resources. Instead of the file + // Need to specify the path to your desired file + + // Create a thread to retrieve data from a file + QTextStream in( &file ); + in.readLine(); + //Reads the data up to the end of file + while( !in.atEnd() ) + { + QStringList entries = in.readLine().split( "\t" ); + // Adding to the model in line with the elements + QList standardItemsList; + + for( int idx : cols ) + { + if( entries.size() > idx ) + standardItemsList.append( new QStandardItem( entries[idx] ) ); + } + + _csvModel.insertRow( _csvModel.rowCount(), standardItemsList ); + } + + file.close(); + +} diff --git a/libMiniCash/mcvendorsdialog.h b/libMiniCash/mcvendorsdialog.h new file mode 100644 index 0000000..c1b0755 --- /dev/null +++ b/libMiniCash/mcvendorsdialog.h @@ -0,0 +1,47 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCVENDORSDIALOG_H +#define MCVENDORSDIALOG_H + +#include +#include + +#include +#include + +namespace Ui +{ + class MCVendorsDialog; +} + +class LIBMINICASH_EXPORT MCVendorsDialog : public QDialog +{ + + Q_OBJECT + +public: + + explicit MCVendorsDialog( QWidget* parent, const QString& filePath ); + virtual ~MCVendorsDialog(); + +protected: + + void loadVendorsFile( const QString& filePath ); + + Ui::MCVendorsDialog* _ui{}; + QStandardItemModel _csvModel; +}; + +#endif // MCVENDORSDIALOG_H diff --git a/libMiniCash/mcvendorsdialog.ui b/libMiniCash/mcvendorsdialog.ui new file mode 100644 index 0000000..da20efb --- /dev/null +++ b/libMiniCash/mcvendorsdialog.ui @@ -0,0 +1,95 @@ + + + MCVendorsDialog + + + + 0 + 0 + 727 + 572 + + + + Verkäuferliste + + + + + + + 16777215 + 36 + + + + + 16 + true + + + + Verkäuferliste + + + Qt::AutoText + + + + + + + Qt::Horizontal + + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 90 + 16777215 + + + + + true + + + + Schliessen + + + + + + + + + + diff --git a/libMiniCash/swdriveselector.cpp b/libMiniCash/swdriveselector.cpp new file mode 100644 index 0000000..b92e717 --- /dev/null +++ b/libMiniCash/swdriveselector.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include + + +SWDriveSelector::SWDriveSelector( QWidget* parent ) + : QComboBox( parent ) +{ + +} + +SWDriveSelector::~SWDriveSelector() +{ + +} + +bool SWDriveSelector::event( QEvent* event ) +{ + if( event->type() == QEvent::MouseButtonPress ) + { + clear(); + for( auto& storage : QStorageInfo::mountedVolumes() ) + { + if( storage.isValid() && storage.isReady() ) + addItem( storage.rootPath() ); + } + } + return QComboBox::event( event ); +} + + diff --git a/libMiniCash/swdriveselector.h b/libMiniCash/swdriveselector.h new file mode 100644 index 0000000..f8b812e --- /dev/null +++ b/libMiniCash/swdriveselector.h @@ -0,0 +1,47 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef QDRIVESELECTOR_H +#define QDRIVESELECTOR_H + +#include +#include +#include +#include + +#include + +/** + * @brief Eine QComboBox zur Auswahl von Laufwerken. + * + * Mit dem QDriveSelektor wird ein Laufwerk(sbuchstabe) + * ausgewählt. Besonderheit: Beim Aktivieren werden ad hoc alle + * verfügbaren Laufwerke in die ComboBox geladen, um Fehleingaben + * zu reduzieren. + */ + +class LIBMINICASH_EXPORT SWDriveSelector : public QComboBox +{ + Q_OBJECT + +public: + + explicit SWDriveSelector( QWidget* parent = nullptr ); + virtual ~SWDriveSelector(); + + virtual bool event(QEvent* ev); + +}; + +#endif // QDRIVESELECTOR_H diff --git a/libMiniCash/swsidebar.cpp b/libMiniCash/swsidebar.cpp new file mode 100644 index 0000000..aa77db9 --- /dev/null +++ b/libMiniCash/swsidebar.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + + source::worx libWidgets + Copyright © 2021-2022 c.holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +***************************************************************************/ + + + + +#include +#include +#include +#include +#include + +#include + + + + + +SWSideBar::SWSideBar( QWidget *parent ) + : QFrame( parent ) +{ + setMouseTracking( true ); +} + + +SWSideBar::~SWSideBar() +{ + +} + + +void SWSideBar::appendAction( QAction* action ) +{ + Q_ASSERT( action != nullptr ); + action->setCheckable( true ); + //action->setEnabled( false ); + QFrame::addAction( action ); + +} + + +void SWSideBar::appendAction( const QIcon& icon, const QString& text ) +{ + return appendAction( new QAction( icon, text ) ); +} + +void SWSideBar::setCheckedAction( QAction* action ) +{ + /// PFUSCH! Prüfen! + _checkedAction = action; + update(); +} + +void SWSideBar::paintEvent( QPaintEvent* event ) +{ + + + QPainter painter( this ); + + int actionY = 0; + for( auto& action : actions() ) + { + + QRect actionRect( 0, actionY, event->rect().width(), SWACTIONHEIGHT ); + if( action->isEnabled() ) + { + if( action == _hoveredAction ) + painter.fillRect( actionRect, _hoveredColor ); + + if( action == _pressedAction ) + painter.fillRect( actionRect, Qt::lightGray ); + + if( action == _checkedAction ) + painter.fillRect( actionRect, _checkedColor ); + + } + + QSize size = painter.fontMetrics().size( Qt::TextSingleLine, action->text() ); + QRect textRect( QPoint( actionRect.width()/2 - size.width()/2, actionRect.bottom()-size.height() - 10 ), size ); + painter.setPen( action->isEnabled() ? Qt::white : Qt::gray ); + painter.drawText( textRect, Qt::AlignCenter, action->text() ); + + QRect pixmapRect( actionRect.width()/2 - 32, actionY+15 , 64, 64 ); + QPixmap pixmap = action->icon().pixmap( QSize( 64, 64 ), action->isEnabled() ? QIcon::Normal : QIcon::Disabled, QIcon::On ); + painter.drawPixmap( pixmapRect, pixmap ); + + actionY += actionRect.height(); + + } + +} + + + +void SWSideBar::mousePressEvent( QMouseEvent* event ) +{ + + QAction* tempAction = actionAt( event->pos() ); + if( tempAction == nullptr ) + return; + + if( _hoveredAction == tempAction ) + _hoveredAction = nullptr; + + _pressedAction = tempAction; + + update(); + QFrame::mousePressEvent (event ); + +} + + +void SWSideBar::mouseReleaseEvent( QMouseEvent *event ) +{ + + QAction* tempAction = actionAt( event->pos() ); + if( tempAction == nullptr ) + return; + + if( tempAction == _pressedAction ) + { + _hoveredAction = _pressedAction; + _checkedAction = _pressedAction; + _pressedAction = nullptr; + update(); + if( _checkedAction->isEnabled() ) + _checkedAction->trigger(); + + } + + + //update();QGuiApplication::palette()) an QPalette::Highlight + QFrame::mouseReleaseEvent( event ); + +} + + +void SWSideBar::mouseMoveEvent(QMouseEvent *event) +{ + QAction* tempAction = actionAt( event->pos() ); + /// nix gefunden + if( tempAction == nullptr) + { + /// dann ist auch nix gehovered + _hoveredAction = nullptr; + update(); + return; + } + /// ist schon gehovered? auch weg + if( _hoveredAction == tempAction ) + return; + + _hoveredAction = tempAction; + update(); + QFrame::mouseMoveEvent(event); +} + + +void SWSideBar::leaveEvent(QEvent * event) +{ + _hoveredAction = _pressedAction = nullptr; + update(); + QFrame::leaveEvent(event); +} + + +QSize SWSideBar::minimumSizeHint() const +{ + return SWACTIONHEIGHT * QSize( 1, actions().size() ); +} + + +QAction* SWSideBar::actionAt(const QPoint &at) +{ + int actionY = 0; + + for( QAction* action : actions() ) + { + QRect actionRect( 0, actionY, rect().width(), SWACTIONHEIGHT ); + if(actionRect.contains(at)) + return action; + actionY += actionRect.height(); + } + return nullptr; +} + + diff --git a/libMiniCash/swsidebar.h b/libMiniCash/swsidebar.h new file mode 100644 index 0000000..6801d37 --- /dev/null +++ b/libMiniCash/swsidebar.h @@ -0,0 +1,69 @@ +/*************************************************************************** + + source::worx libWidgets + Copyright © 2021-2022 c.holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef SWSIDEBAR_H +#define SWSIDEBAR_H + +#include +#include +#include + +#include + + +class LIBMINICASH_EXPORT SWSideBar : public QFrame +{ + Q_OBJECT + +public: + + explicit SWSideBar( QWidget *parent = nullptr ); + virtual ~SWSideBar(); + + void appendAction( QAction* action ); + void appendAction( const QIcon &icon, const QString &text = "" ); + void setCheckedAction( QAction* action ); + + QSize minimumSizeHint() const; + +signals: + +public slots: + + //void koo(); + +protected: + + void paintEvent( QPaintEvent *event ); + void mousePressEvent( QMouseEvent *event ); + void mouseReleaseEvent( QMouseEvent *event ); + void mouseMoveEvent( QMouseEvent *event ); + void leaveEvent( QEvent * event ); + + QAction* actionAt( const QPoint &at ); + + + static const int SWACTIONHEIGHT = 108; + + const QColor _hoveredColor = QColor( 150, 150, 150 ); + const QColor _checkedColor = QColor( 55, 55, 55 ); + + QAction* _hoveredAction = nullptr; + QAction* _pressedAction = nullptr; + QAction* _checkedAction = nullptr; + + +}; + +#endif // SWSIDEBAR_H diff --git a/miniCash/main.cpp b/miniCash/main.cpp new file mode 100644 index 0000000..123c36f --- /dev/null +++ b/miniCash/main.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + + +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName ( miniCash::orgName ); + QCoreApplication::setOrganizationDomain( miniCash::domainName ); + QCoreApplication::setApplicationName ( miniCash::appName ); + + QApplication application(argc, argv); + + MCMainWindowLocal window; + window.show(); + + return application.exec(); +} diff --git a/miniCash/mcaboutme.cpp b/miniCash/mcaboutme.cpp new file mode 100644 index 0000000..731aabb --- /dev/null +++ b/miniCash/mcaboutme.cpp @@ -0,0 +1,32 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include + +MCAboutMe::MCAboutMe(QWidget *parent) : + QDialog( parent ) +{ + + setupUi( this ); + label2->setText( QString( miniCash::copyShort ) + '\n' + miniCash::version ); +} + + +MCAboutMe::~MCAboutMe() +{ + +} diff --git a/miniCash/mcaboutme.h b/miniCash/mcaboutme.h new file mode 100644 index 0000000..5d7ef33 --- /dev/null +++ b/miniCash/mcaboutme.h @@ -0,0 +1,37 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCABOUTME_H +#define MCABOUTME_H + +#include +#include + +/** + * @brief + */ + +class MCAboutMe : public QDialog, private Ui_MCAboutMe +{ + Q_OBJECT + +public: + + explicit MCAboutMe( QWidget* parent = nullptr ); + virtual ~MCAboutMe(); + +}; + + +#endif // MCABOUTME_H diff --git a/miniCash/mcaboutme.ui b/miniCash/mcaboutme.ui new file mode 100644 index 0000000..80e4b91 --- /dev/null +++ b/miniCash/mcaboutme.ui @@ -0,0 +1,126 @@ + + + MCAboutMe + + + + 0 + 0 + 612 + 393 + + + + über minCash + + + + + 230 + 320 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 40 + 30 + 351 + 81 + + + + + + + :/miniCash/images/miniCash.png + + + + + + 60 + 200 + 441 + 101 + + + + Based on Qt 5.15.2(64 bit) + +The program is provided AS IS with NO WARRANTY OF ANY KIND, +INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + 60 + 120 + 461 + 71 + + + + + 10 + true + + + + <html><head/><body><p>...</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + buttonBox + rejected() + MCAboutMe + reject() + + + 316 + 260 + + + 286 + 274 + + + + + buttonBox + accepted() + MCAboutMe + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/miniCash/mceditdialog.cpp b/miniCash/mceditdialog.cpp new file mode 100644 index 0000000..4aa7f66 --- /dev/null +++ b/miniCash/mceditdialog.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + + +/** + * @brief Erzeugt das Dialogfenster, im dem die Kassendatei editiert + * werden kann. + * @param parent das Elternfenster + * @param filename der Name der Kassendatei + */ + +MCEditDialog::MCEditDialog( QWidget* parent, const QString& filename ) : + QDialog( parent ), + _filename( filename ) +{ + + setupUi(this); + + // Murx, FIX! das sollte über den Translator gehen + buttonBox->button( QDialogButtonBox::Ok )->setText( "Kassendatei Speichern" ); + buttonBox->button( QDialogButtonBox::Cancel )->setText( "Abbrechen" ); + + connect( buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect( buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + connect( _startSearch, SIGNAL(clicked()), this, SLOT( onSearch() ) ); + + onLoadFile(); + +} + + +MCEditDialog::~MCEditDialog() +{ + +} + + +/** + * @brief lädt die Kassendatei + */ + +void MCEditDialog::onLoadFile() +{ + QFile file( _filename ); + if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QString msg( "Datei '%0' konnte nicht geöffnet werden.\nFehlercode: %1" ); + QMessageBox::warning( this, "Dateifehler", msg.arg( _filename, file.errorString() ) ); + return; + } + + _trSalesText->setPlainText( file.readAll() ); + +} + + +/** + * @brief Durchsucht die Kassendatei nach einen Schlüsselbegriff + */ + +void MCEditDialog::onSearch() +{ + QString src =_searchString->text(); + _trSalesText->find( src ); +} + + +/** + * @brief sichert die ggf. geänderte Kassendatei + */ + +void MCEditDialog::accept() +{ + // sichern + + QFile file( _filename ); + if( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + QString msg( "Datei '%0' konnte nicht geschrieben werden.\nFehlercode: %1" ); + QMessageBox::warning( this, "Dateifehler", msg.arg( _filename, file.errorString() ) ); + return; + } + + file.write(_trSalesText->toPlainText().toLatin1() ); + + return QDialog::accept(); + +} diff --git a/miniCash/mceditdialog.h b/miniCash/mceditdialog.h new file mode 100644 index 0000000..1afa3f9 --- /dev/null +++ b/miniCash/mceditdialog.h @@ -0,0 +1,56 @@ +/*************************************************************************** + + libMiniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCEDITDIALOG_H +#define MCEDITDIALOG_H + +#include +#include +#include + +/** + * @brief Editiert eine Kassendatei + * + * Hier kann die Verkaufsdatei einer Kassen direkt editiert + * werden, um Zahlendrehen oder Tippfehler zu korrigieren oder + * Einträge zu löschen (Storno des kleinen Mannes) + * + */ + +class MCEditDialog : public QDialog, private Ui_MCEditDialog +{ + Q_OBJECT + +public: + + explicit MCEditDialog(QWidget *parent = nullptr, const QString& filename="" ); + ~MCEditDialog(); + +public slots: + + void onSearch(); + +protected: + + void onLoadFile(); + void accept(); + +protected: + + QString _filename; + +}; + + +#endif // MCEditDialog_H diff --git a/miniCash/mceditdialog.ui b/miniCash/mceditdialog.ui new file mode 100644 index 0000000..d3095c3 --- /dev/null +++ b/miniCash/mceditdialog.ui @@ -0,0 +1,150 @@ + + + MCEditDialog + + + + 0 + 0 + 694 + 588 + + + + Dialog + + + + + + + 9 + true + + + + <html><head/><body><p>Suchbegriff:</p></body></html> + + + Qt::AutoText + + + + + + + + 9 + true + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + + + + + 16 + true + + + + Kassendatei editieren + + + Qt::AutoText + + + + + + + + 9 + + + + + + + + + 9 + true + + + + Verkaufte Artikel + + + + + + + + Lucida Sans Typewriter + 10 + + + + false + + + + + + + + 0 + 0 + + + + + 9 + true + + + + Kassendatei durchsuchen + + + Suchen + + + + :/myresource/images/package_editors.png:/myresource/images/package_editors.png + + + + 16 + 16 + + + + + + + + Qt::Horizontal + + + + + + + + diff --git a/miniCash/mcmainwindowlocal.cpp b/miniCash/mcmainwindowlocal.cpp new file mode 100644 index 0000000..513a976 --- /dev/null +++ b/miniCash/mcmainwindowlocal.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "ui_mcmainwindowlocal.h" + + +MCMainWindowLocal::MCMainWindowLocal( QWidget* parent ) : + MCMainWindowBase( parent ), _ui{new Ui::MCMainWindowLocal} + +{ + + _ui->setupUi( this ); + setupDefaults(); + + _inputViewProxy = _ui->_inputView; + _ui->_inputView->setupDefaults( this, &_salesModel ); + _ui->_billingView->setupDefaults( _dataFileName, &_mainSettings ); + _ui->_contentWidget->setCurrentWidget( _ui->_inputView ); + + statusBar()->setFont( QFont( "Arial", 8 ) ); + statusBar()->showMessage( QString( miniCash::copyright ) + miniCash::version ); + + //_helpViewer = new MCHelpViewer(); + //_helpViewer->load( "file:///C:/HandbuchMiniCash.html" ); + + // Menü Leiste + connect( _ui->_actionHelpAbout, SIGNAL(triggered()), this, SLOT( onHelpAbout() ) ); + connect( _ui->_actionHelpContents, SIGNAL(triggered()), this, SLOT( onHelpManual() ) ); + connect( _ui->_actionStartBilling, SIGNAL(triggered()), this, SLOT( onStartBilling() ) ); + connect( _ui->_actionEditSalesFile, SIGNAL(triggered()), this, SLOT( onEditTransactions() ) ); + connect( _ui->_actionCopySaleData, SIGNAL(triggered()), this, SLOT( onCopyTransactions() ) ); + connect( _ui->_actionSetup, SIGNAL(triggered()), this, SLOT( onSetup() ) ); + connect( _ui->_actionExit, SIGNAL(triggered()), this, SLOT( onExit()) ); + connect( _ui->_actionExitConfirmed, SIGNAL(triggered()), this, SLOT( onExitConfirmed()) ); + +} + + +/** + * @brief Tod und Verderben + */ + +MCMainWindowLocal::~MCMainWindowLocal() +{ + +} + + + + +/** + * @brief In den Abrechungsmodus schalten + * + * Abrechnung starten: Dazu wird das Hauptfenster auf die Abrechungsmaske + * umgeschaltet (irreversibel) + */ + +void MCMainWindowLocal::onStartBilling() +{ + _ui->_contentWidget->setCurrentWidget( _ui->_billingView ); +} + + +/** + * @brief Die Kassendatei editieren + */ + +void MCMainWindowLocal::onEditTransactions() +{ + MCEditDialog dlg( this, _dataFilePath ); + dlg.exec(); + +} + + +/** + * @brief setup dialog anzeigen + * + * Maske mit den Programmeinstellungen anzeigen: Ziellaufwerk etc. + * + */ + +void MCMainWindowLocal::onSetup() +{ + MCSetupDialog dlg( this, &_mainSettings ); + dlg.exec(); +} + + +/** + * @brief Kurzinfo anzeigen + * + */ + +void MCMainWindowLocal::onHelpAbout() +{ + MCAboutMe aboutMe; + aboutMe.exec(); + +} diff --git a/miniCash/mcmainwindowlocal.h b/miniCash/mcmainwindowlocal.h new file mode 100644 index 0000000..5ee9b21 --- /dev/null +++ b/miniCash/mcmainwindowlocal.h @@ -0,0 +1,42 @@ +#ifndef MCMAINWINDOWLOCAL_H +#define MCMAINWINDOWLOCAL_H + +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui +{ + class MCMainWindowLocal; +} +QT_END_NAMESPACE + +/** + * @brief MainWindow der miniCash-Anwendung. + * + * Erbt von MCMainWindowBase und stellt die Implementierung der Nutzeroberfläche + * zur Verfügung. + */ + +class MCMainWindowLocal : public MCMainWindowBase +{ + Q_OBJECT + +public: + + explicit MCMainWindowLocal( QWidget* parent = 0 ); + virtual ~MCMainWindowLocal(); + +protected slots: + + void onSetup() override; // Programmeinstellungen vornehmen + void onEditTransactions() override; // Kassendatei durchsuchen und editieren + void onStartBilling() override; // Kassieren beenden, Abrechnungsmodus starten + void onHelpAbout() override; // Kurzinfo anzeigen + +private: + + Ui::MCMainWindowLocal* _ui{}; +}; + +#endif // MCMAINWINDOWLOCAL diff --git a/miniCash/mcmainwindowlocal.ui b/miniCash/mcmainwindowlocal.ui new file mode 100644 index 0000000..597ad25 --- /dev/null +++ b/miniCash/mcmainwindowlocal.ui @@ -0,0 +1,266 @@ + + + MCMainWindowLocal + + + + 0 + 0 + 1000 + 700 + + + + miniCash.local + + + + + + + + + + + + + + + 0 + 0 + 1000 + 26 + + + + + 9 + true + + + + + + 9 + false + + + + &Datei + + + + + + + + + + 9 + false + + + + &Abrechnung + + + + + + + + 9 + false + + + + &Hilfe + + + + + + + + + + + + 9 + true + + + + TopToolBarArea + + + false + + + + + + + + + + 10 + + + + + + + :/images/exit.png:/images/exit.png + + + &Speichern und Beenden + + + Speichern und Programm beenden + + + + 9 + true + + + + + + + :/images/contexthelp.png:/images/contexthelp.png + + + Handbuch anzeigen + + + + 9 + true + + + + + + + :/images/help.png:/images/help.png + + + Über miniCash + + + + 9 + true + + + + + + + :/images/buisness.png:/images/buisness.png + + + &Abrechung starten + + + Abrechnung starten + + + Eingabe verlassen und Abrechnung starten + + + + 9 + true + + + + + + + :/images/agt_Utilities.png:/images/agt_Utilities.png + + + Kassendatei editieren + + + Verkauften Artikel suchen und ggf. stornieren + + + + 9 + true + + + + + + + :/images/stick.png:/images/stick.png + + + Daten &kopieren + + + Kopiert die Verkaufsdaten auf den Memorystick + + + Kopiert die Verkaufsdaten auf den Memorystick + + + + 9 + true + + + + + + + :/images/exit.png:/images/exit.png + + + ExitConfirmed + + + Speichern und Programm beenden + + + + + + :/images/agt_utilities_copy.png:/images/agt_utilities_copy.png + + + Programmeinstellungen + + + + 9 + true + + + + + + + + MCInputView + QWidget +
mcinputview.h
+ 1 +
+ + MCBillingView + QWidget +
mcbillingview.h
+ 1 +
+
+ + + + +
diff --git a/miniCash/miniCash.h b/miniCash/miniCash.h new file mode 100644 index 0000000..a37c37d --- /dev/null +++ b/miniCash/miniCash.h @@ -0,0 +1,112 @@ +/*************************************************************************** + + miniCash + Copyright © 2013-2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MINICASH_H +#define MINICASH_H + +#include + +/** + +@mainpage miniCash + +@section xxx das Kassensystem 'miniCash' + +'miniCash' ist ein semi-verteiltes Kassen- und Abrechnungssystem für den KinderKleiderMarkt +in Kist. Beim Kister Kleidermarkt können Kindersachen günstig verkauft und erworben, sozusagen +weitergereicht werden. +so + +... + +@warning ein zwei warning + +@note ein zwei note + +@bug ein zwei bug + +@deprecated ein zwei deprecated + +@todo eins zwei todo + +@remark eins zwei remark + +@subsection xxz Funktionsbereiche + - Datenmodelle und Datentypen + - Eingabe der Verkäufe + - Setup-Dialoge + - Erzeugung der Abrechnungen + - Druckersteuerung + +@section sec3 Ideen & TODO: + +@warning das handling von 'enter' und 'tab' überprüfen +@bug die filterung von falschen kundennummern geht nicht. + +@subsection sec3_1 Ideen: + + - oberfläche erneuern? + - beim server hochfahren: daten abholen, puffern, wahlweise via usb + - adressverwaltung einbeziehen, für personalisierte Abrechnungen + +@subsection sec3_2 TODO für 1.0: + + - wlan first, disk backup + - netzprotocol, erfinden oder json/xml + - splash screen? + - fehler dulden wg. Kassenschlange, hinterher kennzeichnen + - server security: only allowed hosts + - auto feeder zum testen + - data: kasse|count|cust|pos|price|timestamp + - protocol: [...]: transaction, -: storno; + - kasse: semi blocking (soll genau was heissen, chris?) + - Beim einlesen mitzählen, Ergebnis in den statusbar. + - suche bei Storno mit mehreren Feldern zulassen + - setup.exe bauen + + +@subsection sec3_3 TODO für 0.9: + + - backup über WLAN -> Adhoc Netzwerk einrichten + - DONE: layouts verwenden + - Handbuch schreiben + - DONE: vernünftiger Setup-dialog mit Abbruchmöglichkeit + - Auswertung: laden und speichern ? + - Printbuttons ab/an schalten ? + - Kurzanleitung ? + - QUARK: programm muss immer starten, fehlerloop verwirrt nur + QUARK: Programm _kann_ ohne Laufwerk nicht starten! + - help about : mit hinweis auf sourceworx & logo + - Fonts vereinheitlichen + - Statusbar einbinden ?!? + - Caps lock abschalten, wie ? + +*/ + + +/** + * @brief der namespace miniCash enthält Definitionen und Konstanten. + */ + +namespace miniCash +{ +/// basics +[[maybe_unused]] static const char* const appName = "miniCash.local"; + +/// misc +[[maybe_unused]] static const char* const version = "Version 0.8.21. 14.07.2022"; + +} + +#endif // MINICASH_H diff --git a/miniCash/miniCash.pro b/miniCash/miniCash.pro new file mode 100644 index 0000000..67eb561 --- /dev/null +++ b/miniCash/miniCash.pro @@ -0,0 +1,49 @@ +QT += core gui widgets + +CONFIG += c++17 + +TEMPLATE = app +TARGET = miniCash + + +DESTDIR = $$OUT_PWD/../common + + +INCLUDEPATH += $$PWD/../libMiniCash + +SOURCES += \ + main.cpp \ + mcaboutme.cpp \ + mceditdialog.cpp \ + mcmainwindowlocal.cpp + +HEADERS += \ + mcaboutme.h \ + mceditdialog.h \ + mcmainwindowlocal.h \ + miniCash.h + +FORMS += \ + mcaboutme.ui \ + mceditdialog.ui \ + mcmainwindowlocal.ui + +DEPENDPATH += $$PWD/../libMiniCash + +LIBS += -L$$OUT_PWD/../common -llibMiniCash + + +#PRE_TARGETDEPS += $$OUT_PWD/../build/lib/$$qtLibraryTarget(libMiniCash) + +#SRC_DIR = $$OUT_PWD/../libMiniCash/debug +#DEST_DIR = $$OUT_PWD/debug + +#QMAKE_PRE_LINK += $$QMAKE_COPY_FILE $$shell_path($$SRC_DIR/libMiniCash.dll) $$shell_path($$DEST_DIR) +#QMAKE_POST_LINK += $$QMAKE_COPY_FILE $$shell_path($$SRC_DIR/libMiniCash.dll) $$shell_path($$DEST_DIR) + + +message("OUT_PWD = $$OUT_PWD") +message("shellpath = $$shell_path($$SRC_DIR/libMiniCash.dll)") +message("dest = $$shell_path($$DEST_DIR)") +message("copy file = $$QMAKE_COPY_FILE") + diff --git a/miniCash/miniCash.qrc b/miniCash/miniCash.qrc new file mode 100644 index 0000000..9554690 --- /dev/null +++ b/miniCash/miniCash.qrc @@ -0,0 +1,32 @@ + + + + images/agt_utilities_copy.png + images/agt_Utilities.png + images/buisness.png + images/help.png + images/contexthelp.png + images/copy.png + images/cut.png + images/exit.png + images/filenew.png + images/fileopen.png + images/filesave.png + images/filesaveas.png + images/findf.png + images/folder_new.png + images/new.png + images/open.png + images/paste.png + images/save.png + images/stick.png + images/printer2.png + images/fileexport.png + images/button_ok.png + images/search.png + templates/tplFinal.html + templates/tplPayoff.html + templates/tplReceipt.html + + + diff --git a/miniCashAll.pro b/miniCashAll.pro new file mode 100644 index 0000000..7c35617 --- /dev/null +++ b/miniCashAll.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + libMiniCash \ + miniCashConnect \ + miniCash + +miniCash.depends = libMiniCash +miniCashConnect.depends = libMiniCash diff --git a/miniCashConnect/.gitignore b/miniCashConnect/.gitignore new file mode 100644 index 0000000..5e57128 --- /dev/null +++ b/miniCashConnect/.gitignore @@ -0,0 +1,8 @@ +*.o +build +*.autosave +*.pro.user +*.pro.user.* +miniCashConnect.pro.user + + diff --git a/miniCashConnect/.gitmodules b/miniCashConnect/.gitmodules new file mode 100644 index 0000000..9fb4212 --- /dev/null +++ b/miniCashConnect/.gitmodules @@ -0,0 +1,3 @@ +[submodule "doc/doxygen-awesome-css"] + path = doc/doxygen-awesome-css + url = https://github.com/jothepro/doxygen-awesome-css.git diff --git a/miniCashConnect/LICENSE b/miniCashConnect/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/miniCashConnect/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/miniCashConnect/README.md b/miniCashConnect/README.md new file mode 100644 index 0000000..dcf3151 --- /dev/null +++ b/miniCashConnect/README.md @@ -0,0 +1,2 @@ +# README.md miniCashConnect +## miniCashConnect zweite diff --git a/miniCashConnect/images/_billing2.png b/miniCashConnect/images/_billing2.png new file mode 100644 index 0000000..e6b4ebc Binary files /dev/null and b/miniCashConnect/images/_billing2.png differ diff --git a/miniCashConnect/images/_edit2.png b/miniCashConnect/images/_edit2.png new file mode 100644 index 0000000..fab5d32 Binary files /dev/null and b/miniCashConnect/images/_edit2.png differ diff --git a/miniCashConnect/images/_input2.png b/miniCashConnect/images/_input2.png new file mode 100644 index 0000000..e8138ff Binary files /dev/null and b/miniCashConnect/images/_input2.png differ diff --git a/miniCashConnect/images/_network2.png b/miniCashConnect/images/_network2.png new file mode 100644 index 0000000..e0c1571 Binary files /dev/null and b/miniCashConnect/images/_network2.png differ diff --git a/miniCashConnect/images/_server.png b/miniCashConnect/images/_server.png new file mode 100644 index 0000000..a45e518 Binary files /dev/null and b/miniCashConnect/images/_server.png differ diff --git a/miniCashConnect/images/_setup2.png b/miniCashConnect/images/_setup2.png new file mode 100644 index 0000000..769baf2 Binary files /dev/null and b/miniCashConnect/images/_setup2.png differ diff --git a/miniCashConnect/images/_transactions2.png b/miniCashConnect/images/_transactions2.png new file mode 100644 index 0000000..1ee0824 Binary files /dev/null and b/miniCashConnect/images/_transactions2.png differ diff --git a/miniCashConnect/images/button_ok.png b/miniCashConnect/images/button_ok.png new file mode 100644 index 0000000..27019ed Binary files /dev/null and b/miniCashConnect/images/button_ok.png differ diff --git a/miniCashConnect/images/connect.png b/miniCashConnect/images/connect.png new file mode 100644 index 0000000..43d40b9 Binary files /dev/null and b/miniCashConnect/images/connect.png differ diff --git a/miniCashConnect/images/contexthelp.png b/miniCashConnect/images/contexthelp.png new file mode 100644 index 0000000..197708e Binary files /dev/null and b/miniCashConnect/images/contexthelp.png differ diff --git a/miniCashConnect/images/disconnect.png b/miniCashConnect/images/disconnect.png new file mode 100644 index 0000000..6a7e035 Binary files /dev/null and b/miniCashConnect/images/disconnect.png differ diff --git a/miniCashConnect/images/exit.png b/miniCashConnect/images/exit.png new file mode 100644 index 0000000..1c7d8fb Binary files /dev/null and b/miniCashConnect/images/exit.png differ diff --git a/miniCashConnect/images/filesave.png b/miniCashConnect/images/filesave.png new file mode 100644 index 0000000..82db505 Binary files /dev/null and b/miniCashConnect/images/filesave.png differ diff --git a/miniCashConnect/images/filesaveas.png b/miniCashConnect/images/filesaveas.png new file mode 100644 index 0000000..59ecc9f Binary files /dev/null and b/miniCashConnect/images/filesaveas.png differ diff --git a/miniCashConnect/images/findf.png b/miniCashConnect/images/findf.png new file mode 100644 index 0000000..3946c5f Binary files /dev/null and b/miniCashConnect/images/findf.png differ diff --git a/miniCashConnect/images/folder_new.png b/miniCashConnect/images/folder_new.png new file mode 100644 index 0000000..cf189f4 Binary files /dev/null and b/miniCashConnect/images/folder_new.png differ diff --git a/miniCashConnect/images/help.png b/miniCashConnect/images/help.png new file mode 100644 index 0000000..6bd0281 Binary files /dev/null and b/miniCashConnect/images/help.png differ diff --git a/miniCashConnect/images/miniCashConnect.png b/miniCashConnect/images/miniCashConnect.png new file mode 100644 index 0000000..b74d156 Binary files /dev/null and b/miniCashConnect/images/miniCashConnect.png differ diff --git a/miniCashConnect/images/nfs_mount.png b/miniCashConnect/images/nfs_mount.png new file mode 100644 index 0000000..40ae998 Binary files /dev/null and b/miniCashConnect/images/nfs_mount.png differ diff --git a/miniCashConnect/images/stick.png b/miniCashConnect/images/stick.png new file mode 100644 index 0000000..ef8e5a7 Binary files /dev/null and b/miniCashConnect/images/stick.png differ diff --git a/miniCashConnect/main.cpp b/miniCashConnect/main.cpp new file mode 100644 index 0000000..cc3e59d --- /dev/null +++ b/miniCashConnect/main.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + + QCoreApplication::setOrganizationName ( miniCash::orgName ); + QCoreApplication::setOrganizationDomain( miniCash::domainName ); + QCoreApplication::setApplicationName ( miniCash::appName ); + + QApplication application(argc, argv); + + /* + qDebug() << " -- first"; + myMutex.lock(); + qDebug() << " -- second"; + myfunc(); + myMutex.lock(); + qDebug() << " -- third"; + */ + + QTranslator translator; + QLocale locale; + + QStringList list = locale.uiLanguages(); + for( const QString& lang : list ) + qDebug() << "lang: " << lang; + qDebug() << "name:" << locale.name(); + + //translator.load( QLocale(), QLatin1String("miniCash"), QLatin1String("_"), QLatin1String(":/i18n")); + //translator.load( "miniCash_en" ); + //application.installTranslator( &translator ); + + MCConnectMainWindow window; + window.show(); + + return application.exec(); +} diff --git a/miniCashConnect/mccaboutme.cpp b/miniCashConnect/mccaboutme.cpp new file mode 100644 index 0000000..0789d94 --- /dev/null +++ b/miniCashConnect/mccaboutme.cpp @@ -0,0 +1,31 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include + +MCCAboutMe::MCCAboutMe(QWidget *parent) : + QDialog( parent ) + +{ + setupUi( this ); + label2->setText( QString( miniCash::copyConnect ) + '\n' + miniCash::versionConnect ); +} + + +MCCAboutMe::~MCCAboutMe() +{ + +} diff --git a/miniCashConnect/mccaboutme.h b/miniCashConnect/mccaboutme.h new file mode 100644 index 0000000..78ba5c2 --- /dev/null +++ b/miniCashConnect/mccaboutme.h @@ -0,0 +1,38 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCABOUTME_H +#define MCCABOUTME_H + +#include +#include + + +/** + * @brief The MCCAboutMe class ! + */ + +class MCCAboutMe : public QDialog, private Ui_MCCAboutMe +{ + Q_OBJECT + +public: + + explicit MCCAboutMe( QWidget* parent = nullptr ); + virtual ~MCCAboutMe(); + +}; + + +#endif // MCCABOUTME_H diff --git a/miniCashConnect/mccaboutme.ui b/miniCashConnect/mccaboutme.ui new file mode 100644 index 0000000..22cad89 --- /dev/null +++ b/miniCashConnect/mccaboutme.ui @@ -0,0 +1,126 @@ + + + MCCAboutMe + + + + 0 + 0 + 580 + 434 + + + + über minCash + + + + + 190 + 370 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 40 + 50 + 351 + 111 + + + + + + + :/images/miniCashConnect.png + + + + + + 60 + 240 + 441 + 101 + + + + Based on Qt 5.15.2(64 bit) + +The program is provided AS IS with NO WARRANTY OF ANY KIND, +INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + 60 + 160 + 461 + 71 + + + + + 10 + true + + + + <html><head/><body><p>...</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + buttonBox + rejected() + MCCAboutMe + reject() + + + 316 + 260 + + + 286 + 274 + + + + + buttonBox + accepted() + MCCAboutMe + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/miniCashConnect/mcceditview.cpp b/miniCashConnect/mcceditview.cpp new file mode 100644 index 0000000..1032679 --- /dev/null +++ b/miniCashConnect/mcceditview.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include + +#include +#include +#include +#include + + +/** + * @brief Default Konstruktor + * @param parent + */ + +MCCEditView::MCCEditView( QWidget* parent ) + : QWidget( parent ) + +{ + setupUi( this ); +} + + +/** + * @brief Default Destruktor + */ + +MCCEditView::~MCCEditView() +{ + +} + + +void MCCEditView::setupDefaults( MCMainWindowBase* parent ) +{ + _parent = parent; + Q_ASSERT( _parent != nullptr ); + + /// model setzen: + _trList->setModel( &_salesModel ); + + _valCustId.setRegularExpression( QRegularExpression( miniCash::fCustID ) ); // Validator für die Kundennnummer + _valItemNo.setRegularExpression( QRegularExpression( miniCash::fItemNo ) ); // Validator für die Kundennnummer; // Validator für die laufende Nummer des Artikels + _valPrice.setRegularExpression( QRegularExpression( miniCash::fPrice ) ); // Validator für die Kundennnummer; // Validator für die Preisangabe + + /* + _trSellerID->setValidator( &_valCustId ); + _trItemNo->setValidator( &_valItemNo ); + _trPrice->setValidator( &_valPrice ); + */ + + /* + // Doppelklick auf einen Eintrag in der View soll diesen löschen + connect( _trList, SIGNAL( doubleClicked(QModelIndex) ), this, SLOT( onRemoveEntry(QModelIndex)) ); + + // hosianna : key event handling ist gar nicht nötig + QShortcut* shortcutPayback = new QShortcut( QKeySequence( Qt::Key_F1 ), this ); + QShortcut* shortcutSave = new QShortcut( QKeySequence( Qt::Key_F12 ), this ); + + connect( shortcutPayback, SIGNAL(activated()), this, SLOT( onCalculatePayback()) ); + connect( shortcutSave, SIGNAL(activated()), _parent, SLOT( onSaveTransaction()) ); + + // Alle Transaktionen sichern + connect( _trOK, SIGNAL(clicked()), _parent, SLOT( onSaveTransaction()) ); + + // Felder auch mit Enter weiterschalten + connect( _trSellerID, SIGNAL(returnPressed()), this, SLOT( onMoveInputFocus()) ); + connect( _trItemNo, SIGNAL(returnPressed()), this, SLOT( onMoveInputFocus()) ); + + // Transaktion fertig eingegeben? Dann prüfen + connect( _trPrice, SIGNAL(editingFinished()),this, SLOT( onAddSalesItem()) ); + + _trPos->setText( "1" ); + _trCount->setText( _parent->transCount() ); + */ +} + + +/** + * @brief lädt die Kassendatei + */ + +void MCCEditView::loadTransactions( const QString& fileName ) +{ + + QFile file( fileName ); + if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QString msg( "Datei '%0' konnte nicht geöffnet werden.\nFehlercode: %1" ); + QMessageBox::warning( this, "Dateifehler", msg.arg( fileName, file.errorString() ) ); + return; + } + + QTextStream inputStream(&file); + /// nicht aggregieren + + ///_salesModel.clear(); <-- löscht den Header mit + ///_salesModel.removeRows( 0, _salesModel.rowCount() ); + /// anhängen + _salesModel.appendTransactions( inputStream ); + +} + + + +/** + * @brief Durchsucht die Kassendatei nach einen Schlüsselbegriff + */ + +void MCCEditView::onSearch() +{ + /* + QString src =_searchString->text(); + _trSalesText->find( src ); + */ +} + + +/** + * @brief sichert die ggf. geänderte Kassendatei + */ + +void MCCEditView::accept() +{ + // sichern +/* + QFile file( _filename ); + if( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + QString msg( "Datei '%0' konnte nicht geschrieben werden.\nFehlercode: %1" ); + QMessageBox::warning( this, "Dateifehler", msg.arg( _filename, file.errorString() ) ); + return; + } + + file.write(_trSalesText->toPlainText().toLatin1() ); + + return QDialog::accept(); +*/ +} diff --git a/miniCashConnect/mcceditview.h b/miniCashConnect/mcceditview.h new file mode 100644 index 0000000..2f14f8f --- /dev/null +++ b/miniCashConnect/mcceditview.h @@ -0,0 +1,67 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCEDITVIEW_H +#define MCCEDITVIEW_H + +#include +#include + +#include +#include +#include + + +class MCMainWindowBase; + + +/** + * @brief Dieses Widget zeigt die aktuelle Transaktionsdatei an und ermöglicht Änderungen + * und Stornos. + */ + +class MCCEditView : public QWidget, private Ui_MCCEditView +{ + + Q_OBJECT + +public: + + explicit MCCEditView( QWidget* parent = nullptr ); + virtual ~MCCEditView(); + + void setupDefaults( MCMainWindowBase* parent ); + void loadTransactions( const QString& fileName ); + +public slots: + + void onSearch(); + +protected: + + + void accept(); + + MCMainWindowBase* _parent = nullptr; + MCSalesModel _salesModel; + int _poscount = 1; /// Verkaufsposition innerhanlb des aktuellen Vorgangs + double _overallSum = 0.0; /// Gesamtpreis der aktuellen Verkaufstransaktion + + QRegularExpressionValidator _valCustId; /// Validator für die Kundennnummer + QRegularExpressionValidator _valItemNo; /// Validator für die laufende Nummer des Artikels + QRegularExpressionValidator _valPrice; /// Validator für die Preisangabe + +}; + +#endif // MCCEDITVIEW_H diff --git a/miniCashConnect/mcceditview.ui b/miniCashConnect/mcceditview.ui new file mode 100644 index 0000000..64b433a --- /dev/null +++ b/miniCashConnect/mcceditview.ui @@ -0,0 +1,147 @@ + + + MCCEditView + + + + 0 + 0 + 1054 + 605 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Lucida Sans Typewriter + true + + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + background: lightGray + + + + + 625 + 2 + 86 + 29 + + + + + 9 + true + + + + <html><head/><body><p>Suchbegriff:</p></body></html> + + + Qt::AutoText + + + + + + 920 + 2 + 93 + 29 + + + + + 0 + 0 + + + + + 9 + true + + + + Kassendatei durchsuchen + + + Suchen + + + + :/myresource/images/package_editors.png:/myresource/images/package_editors.png + + + + 16 + 16 + + + + + + + 718 + 4 + 195 + 26 + + + + + 9 + + + + background: white + + + + + + + + + MCTreeView + QTreeView +
mctreeview.h
+
+
+ + +
diff --git a/miniCashConnect/mcconnectmainwindow.cpp b/miniCashConnect/mcconnectmainwindow.cpp new file mode 100644 index 0000000..5b09e59 --- /dev/null +++ b/miniCashConnect/mcconnectmainwindow.cpp @@ -0,0 +1,384 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief MCConnectMainWindow::MCConnectMainWindow + * @param parent + */ + +MCConnectMainWindow::MCConnectMainWindow( QWidget* parent ) + : MCMainWindowBase{ parent } + +{ + + setupUi( this ); + + /// kommt aus der miniCash library + setupDefaults(); + + _billingView->setupDefaults( _dataFileName, &_mainSettings ); + /// das ist ein hack, der der Oberklasse 'MCMainwindowbase' den Zugriff ermöglicht. + _inputViewProxy = _inputView; + _inputView->setupDefaults( this, &_salesModel ); + _editView->setupDefaults( this ); + + statusBar()->setFont( QFont( "Arial", 8 ) ); + statusBar()->showMessage( QString( miniCash::copyConnect ) + miniCash::versionConnect ); + + //_helpViewer = new MCHelpViewer(); + //_helpViewer->load( "file:///C:/HandbuchMiniCash.html" ); + + /// actions + connect( _actionSetup, SIGNAL( triggered() ), this, SLOT( onSetup() ) ); + connect( _actionSetupNetwork, SIGNAL( triggered() ), this, SLOT( onShowNetworkDialog() ) ); + connect( _actionInputTransactions, SIGNAL( triggered() ), this, SLOT( onInputTransactions() ) ); + connect( _actionViewTransactions, SIGNAL( triggered() ), this, SLOT( onViewTransactions() ) ); + connect( _actionEditTransactions, SIGNAL( triggered() ), this, SLOT( onEditTransactions() ) ); + connect( _actionCopySaleData, SIGNAL( triggered() ), this, SLOT( onCopyTransactions() ) ); + connect( _actionStartBilling, SIGNAL( triggered() ), this, SLOT( onStartBilling() ) ); + connect( _actionExit, SIGNAL( triggered() ), this, SLOT( onExit() ) ); + connect( _actionExitConfirmed, SIGNAL( triggered() ), this, SLOT( onExitConfirmed() ) ); + connect( _actionHelpAbout, SIGNAL( triggered() ), this, SLOT( onHelpAbout() ) ); + connect( _actionHelpContents, SIGNAL( triggered() ), this, SLOT( onHelpManual() ) ); + + + /// senden & empfangen sind asynchron, also schieben wir die in + /// eigenen Threads + _tcpSender.moveToThread( &_senderThread ); + _tcpReceiver.moveToThread( &_receiverThread ); + + //connect( this, SIGNAL( stopNetwork() ), &_tcpSender, SLOT( onDiscardConnection() ) ); + //connect( this, SIGNAL( stopNetwork() ), &_tcpReceiver, SLOT( onDiscardConnection() ) ); + + connect( this, SIGNAL( startNetwork() ), &_tcpSender, SLOT( onCreateConnection() ) ); + connect( this, SIGNAL( startNetwork() ), &_tcpReceiver, SLOT( onCreateConnection() ) ); + + qRegisterMetaType("miniCash::CState"); + qRegisterMetaType("QAbstractSocket::SocketError"); + + connect( &_tcpSender, SIGNAL( connectionChanged(miniCash::CState) ), this, SLOT( onStateChanged(miniCash::CState) ) ); + connect( &_tcpReceiver, SIGNAL( connectionChanged(miniCash::CState) ), this, SLOT( onStateChanged(miniCash::CState) ) ); + + /// das SIG transactionCreated() stammt aus der Basisklass MCMainWindowBase, nette Möglichkleit, eine + /// abstrakte Methode 'sendTransaction() = 0' zu ersetzen. + connect( this, SIGNAL( transactionCreated(QString) ), &_tcpSender, SLOT( onSendTransaction(QString) ) ); + connect( &_tcpReceiver, SIGNAL( newTransaction(QString) ), this, SLOT( onTransactionReceived(QString) ) ); + + + /// catch network errors + connect( &_tcpSender, SIGNAL( errorOccurred(QAbstractSocket::SocketError) ), this, SLOT( onConnectionError(QAbstractSocket::SocketError) ) ); + connect( &_tcpReceiver, SIGNAL( acceptError(QAbstractSocket::SocketError) ), this, SLOT( onConnectionError(QAbstractSocket::SocketError) ) ); + + /// erstmal die Basis ... + /// wenn wir das erste mal hier sind, defaults laden. + if( !_mainSettings.contains( miniCash::keyReceiverHost ) ) + { + _mainSettings.setValue( miniCash::keyIsTcpReceiver, miniCash::isTcpReceiver ); + _mainSettings.setValue( miniCash::keyIsTcpSender, miniCash::isTcpSender ); + _mainSettings.setValue( miniCash::keyReceiverHost, "" ); + _mainSettings.setValue( miniCash::keyReceiverPort, miniCash::receiverPort ); + } + + connect( _netWidget, SIGNAL( showNetworkDialog() ), this, SLOT( onShowNetworkDialog() ) ); + + /// gleich beim Start NetDlg zeigen? + //_isSender = _mainSettings.value( miniCash::keyIsTcpSender ).toBool(); + //_host = _mainSettings.value( miniCash::keyReceiverHost ).toString(); + //if( _isSender && _host.isEmpty() ) + + /// Ist schon Ok, den DLG immer anzuzeigen + _showDlg = true; + + _isReceiver = _mainSettings.value( miniCash::keyIsTcpReceiver ).toBool(); + + _sideBar->appendAction( _actionInputTransactions ); + if( _isReceiver ) + _sideBar->appendAction( _actionViewTransactions ); + _sideBar->appendAction( _actionEditTransactions ); + _sideBar->appendAction( _actionStartBilling ); + _sideBar->setCheckedAction( _actionInputTransactions ); + +} + + +/** + * @brief Destruktor + */ + +MCConnectMainWindow::~MCConnectMainWindow() +{ + _senderThread.exit(); + _receiverThread.exit(); + + if( !_senderThread.wait( 3000 ) ) //Wait until it actually has terminated (max. 3 sec) + { + _senderThread.terminate(); //Thread didn't exit in time, probably deadlocked, terminate it! + _senderThread.wait(); //We have to wait again here! + } + if( !_receiverThread.wait( 3000 ) ) //Wait until it actually has terminated (max. 3 sec) + { + _receiverThread.terminate(); //Thread didn't exit in time, probably deadlocked, terminate it! + _receiverThread.wait(); //We have to wait again here! + } + + +} + + +/** + * @brief Überschreibt 'QMainWindow::showEvent', um ggf. einen NetworkSetup Dialog + * einzuschmuggleln. + * @param event + */ + +void MCConnectMainWindow::showEvent( QShowEvent* event ) +{ + + /// 'onShowNetworkDialog' gehört eigentlich in den Konstruktor (falls der Hostname nicht gesetzt ist, + /// wenn aber dort der NetworkSetup-Dialog aufgerufen wird, dann erscheint dieser _vor_ dem + /// Hauptfenster. Um das zu vermeiden, schmuggeln wir das per 'showEvent' ein. + + QMainWindow::showEvent( event ); + + /// guard: der DLG soll nur einmal beim Start erscheinen + if( !_showDlg ) + return; + + /// Call slot via queued connection so it's called from the UI thread after this method has returned and the window has been shown + QMetaObject::invokeMethod( this, &MCConnectMainWindow::onShowNetworkDialog, Qt::ConnectionType::QueuedConnection ); + _showDlg = false; + +} + + + + +void MCConnectMainWindow::onStateChanged( miniCash::CState state ) +{ + /// Serverstate schlägt Clientstate, ist deswege numerisch höher, + /// Errorstates werden woanders gesetzt + if( state > _netWidget->connectionState() ) + _netWidget->setConnectionState( state ); +} + + +/** + * @brief setup dialog anzeigen + * + * Maske mit den Programmeinstellungen anzeigen: Ziellaufwerk etc. + * + */ + +void MCConnectMainWindow::onSetup() +{ + MCSetupDialog( this, &_mainSettings ).exec(); + /// alles kann geändert worden sein -> also nochmal los + setupDefaults(); +} + + +void MCConnectMainWindow::onShowNetworkDialog() +{ + + int result = MCNetworkDialog( this, &_mainSettings ).exec(); + if( QDialog::Rejected == result ) + return; + + setupNetwork(); + +} + + +/** + * @brief Netzwerksettings initialisieren + * + * Wird direkt beim Programmstart aufgerufen, setzt die Vorgabewerte + * fürs Networking. Das ist eine Ergänzung zu @see setupDefaults in der Basisklasse. + */ + +void MCConnectMainWindow::setupNetwork() +{ + + //emit stopNetwork(); + + _isSender = _mainSettings.value( miniCash::keyIsTcpSender ).toBool(); + _isReceiver = _mainSettings.value( miniCash::keyIsTcpReceiver ).toBool(); + _host = _mainSettings.value( miniCash::keyReceiverHost ).toString(); + _port = _mainSettings.value( miniCash::keyReceiverPort ).toInt(); + + bool useNetwork = _isSender || _isReceiver; + + /// gar kein Netz? + if( !useNetwork ) + return _netWidget->setConnectionState( miniCash::Disabled ); + + /* + /// ... und nochmal Prüfen: Host, default ist ja leer + if( _host.isEmpty() ) + { + int result = MCNetworkDialog( this, &_mainSettings ).exec(); + if( QDialog::Rejected == result ) + return; + } + */ + + /// Netz wird verwendet, verrbinden ... + _netWidget->setConnectionState( miniCash::UnConnected ); + + /// bin ich Server, also Empfänger + if( _isReceiver ) + { + /// (Re-)init server + _tcpReceiver.setupConnection( _port ); + if( !_receiverThread.isRunning() ) + _receiverThread.start(); + } + + /// bin ich Client, also Sender? + if( _isSender ) + { + _tcpSender.setupConnection( _host, _port ); + if( !_senderThread.isRunning() ) + _senderThread.start(); + } + + emit startNetwork(); + +} + + + +void MCConnectMainWindow::onConnectionError( QAbstractSocket::SocketError socketError ) +{ + + qDebug() << "socketError:" << socketError; + + switch( socketError ) + { + case QAbstractSocket::RemoteHostClosedError: + QMessageBox::information(this, "QTCPServer", "RemoteHostClosedError:"); + break; + + case QAbstractSocket::HostNotFoundError: + QMessageBox::information(this, "QTCPServer", "The host was not found. Please check the host name and port settings."); + + break; + + case QAbstractSocket::ConnectionRefusedError: + QMessageBox::information(this, "QTCPServer", "The connection was refused by the peer. Make sure QTCPServer is running, and check that the host name and port settings are correct."); + break; + + default: + QTcpSocket* socket = qobject_cast(sender()); + QMessageBox::information(this, "QTCPServer", QString("The following error occurred: %1.").arg(socket->errorString())); + break; + } + + +} + + + +/** + * @brief Eingabemaske (wieder) einblenden, in den + * Eingabemodus schalten + */ + +void MCConnectMainWindow::onInputTransactions() +{ + _contentWidget->setCurrentWidget( _inputView ); +} + + +/** + * @brief TransactionView einblenden: Eingehende Transaktionen werden angezeigt + */ + +void MCConnectMainWindow::onViewTransactions() +{ + // Anim?? + _contentWidget->setCurrentWidget( _transactionView ); +} + + +/** + * @brief Transaktionsdaten korrigieren, z.B. Zahlendreher beheben oder Stornos + * einbuchen. + */ + +void MCConnectMainWindow::onEditTransactions() +{ + + qDebug() << " -- Edit Transactions: " << _dataFilePath; + + _editView->loadTransactions( _dataFilePath ); + _contentWidget->setCurrentWidget( _editView ); + +} + + + +/** + * @brief MCConnectMainWindow::onTransactionReceived + * @param transaction: Transaktionen als String + */ + +void MCConnectMainWindow::onTransactionReceived( const QString& transaction ) +{ + _transactionView->onTransactionReceived( transaction ); +} + + +/** + * @brief In den Abrechungsmodus schalten + * + * Abrechnung starten: Dazu wird das Hauptfenster auf die Abrechungsmaske + * umgeschaltet + */ + +void MCConnectMainWindow::onStartBilling() +{ + _contentWidget->setCurrentWidget( _billingView ); +} + + +/** + * @brief Kurzinfo anzeigen + * + */ + +void MCConnectMainWindow::onHelpAbout() +{ + MCCAboutMe().exec(); +} diff --git a/miniCashConnect/mcconnectmainwindow.h b/miniCashConnect/mcconnectmainwindow.h new file mode 100644 index 0000000..e0ec6c6 --- /dev/null +++ b/miniCashConnect/mcconnectmainwindow.h @@ -0,0 +1,89 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MCCONNECTMAINWINDOW_H +#define MCCONNECTMAINWINDOW_H + + +#include +#include +#include +#include + +#include + + +/** + * @brief MainWindow der miniCashConnect-Anwendung. + * + * Erbt von MCMainWindowBase und stellt die Implementierung der Nutzeroberfläche + * zur Verfügung. + */ + +class MCConnectMainWindow : public MCMainWindowBase, private Ui_MCConnectMainWindow +{ + + Q_OBJECT + +public: + + explicit MCConnectMainWindow( QWidget* parent = nullptr ); + virtual ~MCConnectMainWindow(); + +signals: + + //void stopNetwork(); + void startNetwork(); + +public slots: + + void onShowNetworkDialog(); + void onStateChanged( miniCash::CState state ); + void onConnectionError( QAbstractSocket::SocketError socketError ); + /// ref?? + void onTransactionReceived( const QString& transaction ); + +protected slots: + + void onSetup() override; /// Programmeinstellungen vornehmen + + void onInputTransactions(); /// Eingabemaske, hier als StackedWidget + void onViewTransactions(); /// im Server(==Receiver) Modus: ankommende Transaktionen anzeigen + void onEditTransactions() override; /// Alle Transaktionen durchsuchen und editieren + void onStartBilling() override; /// Kassieren beenden, Abrechnungsmodus starten + void onHelpAbout() override; /// Kurzinfo anzeigen + +protected: + + void showEvent( QShowEvent* event ) override; + void setupNetwork(); + + int _sentTransCount = 0; /// Anzahl der Transaktionen (== Verkäufe) die übers Netz gesendet wurden + + QString _host; + int _port; + + bool _isSender = false; + bool _isReceiver = false; + bool _showDlg = false; + + MCSender _tcpSender; + MCReceiver _tcpReceiver; + + QThread _senderThread; + QThread _receiverThread; + +}; + +#endif /// MCLOCALMAINWINDOW_H diff --git a/miniCashConnect/mcconnectmainwindow.ui b/miniCashConnect/mcconnectmainwindow.ui new file mode 100644 index 0000000..e558586 --- /dev/null +++ b/miniCashConnect/mcconnectmainwindow.ui @@ -0,0 +1,425 @@ + + + MCConnectMainWindow + + + + 0 + 0 + 1186 + 916 + + + + miniCash.connect + + + + + + + + + + 140 + 0 + + + + + 140 + 16777215 + + + + background: groove gray; + + + QFrame::WinPanel + + + QFrame::Sunken + + + + + + + + 140 + 90 + + + + + 140 + 90 + + + + background: groove gray; + + + + + + + + + + + + + + + + 7 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + 0 + 0 + 1186 + 26 + + + + + 9 + true + + + + + + 9 + false + + + + &Datei + + + + + + + + + + 9 + false + + + + &Abrechnung + + + + + + + + 9 + false + + + + &Hilfe + + + + + + + + + + + + 9 + true + + + + TopToolBarArea + + + false + + + + + + + + + + 10 + + + + + + + :/images/exit.png:/images/exit.png + + + &Speichern und Beenden + + + Speichern und Programm beenden + + + + 9 + true + + + + + + + :/images/contexthelp.png:/images/contexthelp.png + + + Handbuch anzeigen + + + + 9 + true + + + + + + + :/images/help.png:/images/help.png + + + Über miniCash + + + + 9 + true + + + + + + + :/images/_billing2.png:/images/_billing2.png + + + Abrechung + + + Abrechnung starten + + + Eingabe verlassen und Abrechnung starten + + + + 9 + true + + + + + + + :/images/_edit2.png:/images/_edit2.png + + + Kassendatei editieren + + + Verkauften Artikel suchen und ggf. stornieren + + + + 9 + true + + + + + + + :/images/stick.png:/images/stick.png + + + Daten &kopieren + + + Kopiert die Verkaufsdaten auf den Memorystick + + + Kopiert die Verkaufsdaten auf den Memorystick + + + + 9 + true + + + + + + + :/images/exit.png:/images/exit.png + + + ExitConfirmed + + + Speichern und Programm beenden + + + + + + :/images/_setup2.png:/images/_setup2.png + + + Programmeinstellungen + + + + 9 + true + + + + + + + :/images/_transactions2.png:/images/_transactions2.png + + + Verkäufe + + + Transaktionen anzeigen + + + + + + :/images/_input2.png:/images/_input2.png + + + Kasse + + + Eingabemaske der Kasse öffnen + + + + 9 + true + + + + + + + :/images/_edit2.png:/images/_edit2.png + + + Storno + + + Verkauften Artikel suchen und ggf. stornieren + + + + 9 + true + + + + + + + :/images/connect.png:/images/connect.png + + + Netzwerkeinstellungen + + + + true + + + + + + + + SWSideBar + QFrame +
swsidebar.h
+ 1 +
+ + MCInputView + QWidget +
mcinputview.h
+ 1 +
+ + MCBillingView + QWidget +
mcbillingview.h
+ 1 +
+ + MCCEditView + QWidget +
mcceditview.h
+ 1 +
+ + MCTransactionView + QWidget +
mctransactionview.h
+ 1 +
+ + MCNetworkWidget + QFrame +
mcnetworkwidget.h
+ 1 +
+
+ + + + +
diff --git a/miniCashConnect/miniCashConnect.h b/miniCashConnect/miniCashConnect.h new file mode 100644 index 0000000..da4544f --- /dev/null +++ b/miniCashConnect/miniCashConnect.h @@ -0,0 +1,67 @@ +/*************************************************************************** + + miniCashConnect + Copyright © 2022 christoph holzheuer + c.holzheuer@sourceworx.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + +***************************************************************************/ + + +#ifndef MINICASHCONNECT_H +#define MINICASHCONNECT_H + + +#include + +/** + +@mainpage miniCashConnect + +@section xxx das Kassensystem 'miniCashConnect' + +'miniCashConnect' ist ein semi-verteiltes Kassen- und Abrechnungssystem für den KinderKleiderMarkt +in Kist. Beim Kister Kleidermarkt können Kindersachen günstig verkauft und erworben, sozusagen +weitergereicht werden. +so + +... + +@warning ein zwei warning + +@note ein zwei note + +@bug ein zwei bug + +@deprecated ein zwei deprecated + +@todo eins zwei todo + +@remark eins zwei remark + +*/ + + + +/** + * @brief der namespace miniCash enthält Definitionen und Konstanten. + */ + +namespace miniCash +{ + + /// basics + [[maybe_unused]] constexpr static const char* appName = "miniCash.connect"; + + + /// misc + [[maybe_unused]] constexpr static const char* versionConnect = "Version 0.0.40, 14.07.2022"; + [[maybe_unused]] constexpr static const char* copyConnect = "miniCashConnect, © 2022\nc.holzheuer@sourceworx.org "; + +} + +#endif // MINICASHCONNECT_H diff --git a/miniCashConnect/miniCashConnect.pro b/miniCashConnect/miniCashConnect.pro new file mode 100644 index 0000000..626cec3 --- /dev/null +++ b/miniCashConnect/miniCashConnect.pro @@ -0,0 +1,60 @@ +QT += printsupport core gui network widgets + +CONFIG += c++17 + +TEMPLATE = app +TARGET = miniCashConnect + +DESTDIR = $$OUT_PWD/../common + +INCLUDEPATH += $$PWD/../libMiniCash + +DEFINES += QT_DEPRECATED_WARNINGS + +SOURCES += \ + main.cpp \ + mccaboutme.cpp \ + mcceditview.cpp \ + mcconnectmainwindow.cpp \ + + +HEADERS += \ + miniCashConnect.h \ + mccaboutme.h \ + mcceditview.h \ + mcconnectmainwindow.h \ + +FORMS += \ + mccaboutme.ui \ + mcceditview.ui \ + mcconnectmainwindow.ui + +RESOURCES += \ + miniCashConnect.qrc + + +DEPENDPATH += $$PWD/../libMiniCash + +LIBS += -L$$OUT_PWD/../common -llibMiniCash + +#SRC_DIR = $$OUT_PWD/../libMiniCash/debug +#DEST_DIR = $$OUT_PWD/debug + +#QMAKE_PRE_LINK += $$QMAKE_COPY_FILE $$shell_path($$SRC_DIR/libMiniCash.dll) $$shell_path($$DEST_DIR) +#QMAKE_POST_LINK += $$QMAKE_COPY_FILE $$shell_path($$SRC_DIR/libMiniCash.dll) $$shell_path($$DEST_DIR) + + +#DEPENDPATH += . ../libMiniCash + +#linux { +# TARGET = miniCash +# INCLUDEPATH += ../libMiniCash +# LIBS += -L../libMiniCash /usr/lib -lMiniCash +# TARGET = miniCashConnect +#} + +#windows { +# INCLUDEPATH += ../libMiniCash +# LIBS += -L../../../libMiniCash/build/Desktop_Qt_6_9_0_MinGW_64_bit-Debug/debug -lMiniCash +#} + diff --git a/miniCashConnect/miniCashConnect.qrc b/miniCashConnect/miniCashConnect.qrc new file mode 100644 index 0000000..d47ebff --- /dev/null +++ b/miniCashConnect/miniCashConnect.qrc @@ -0,0 +1,26 @@ + + + images/help.png + images/contexthelp.png + images/exit.png + images/filesave.png + images/filesaveas.png + images/findf.png + images/folder_new.png + images/stick.png + images/button_ok.png + templates/tplFinal.html + templates/tplPayoff.html + templates/tplReceipt.html + images/miniCashConnect.png + images/_billing2.png + images/_edit2.png + images/_input2.png + images/_transactions2.png + images/_setup2.png + images/_network2.png + images/connect.png + images/disconnect.png + images/_server.png + + diff --git a/miniCashConnect/miniCashConnect_en_DE.ts b/miniCashConnect/miniCashConnect_en_DE.ts new file mode 100644 index 0000000..1e97bc2 --- /dev/null +++ b/miniCashConnect/miniCashConnect_en_DE.ts @@ -0,0 +1,3 @@ + + + diff --git a/miniCashConnect/templates/tplFinal.html b/miniCashConnect/templates/tplFinal.html new file mode 100644 index 0000000..b9ae970 --- /dev/null +++ b/miniCashConnect/templates/tplFinal.html @@ -0,0 +1,52 @@ + + + + + Quittungsdruck + + + +
+
+

Kleidermarkt Kindergarten Kist

+

Datum: %0

+
+

Endabrechnung

+ +------------------------------------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Gesamtumsatz:%1
Gesamtauszahlungssumme:%2
Gewinn:%3
Anteil Kindergarten:%4 %
verkaufte Teile:%5
Anzahl Kunden:%6
Anzahl Verkäufer:%7
+------------------------------------------------------------------------------------------------------------------------------------------------------- +
+
+ diff --git a/miniCashConnect/templates/tplPayoff.html b/miniCashConnect/templates/tplPayoff.html new file mode 100644 index 0000000..7788ee3 --- /dev/null +++ b/miniCashConnect/templates/tplPayoff.html @@ -0,0 +1,39 @@ + + +template.html + + + +
+
+

Kleidermarkt Kindergarten Kist

+

Datum: %0

+

Abrechung für Verkäufernummer: %1

+

Verkaufte Teile: %2   Gesamtbetrag: %3    Auszahlungsbetrag: %4

+
+
+ + + + + + + + + + + + + +
Verkäufernummerlaufende NummerUmsatzAuszahlungssumme
-------------------------------------------------------------------------------------------------------------------------------------------------------
+ + +%5 + +
+
+%6 +
+
+
+ diff --git a/miniCashConnect/templates/tplReceipt.html b/miniCashConnect/templates/tplReceipt.html new file mode 100644 index 0000000..7e8c11f --- /dev/null +++ b/miniCashConnect/templates/tplReceipt.html @@ -0,0 +1,39 @@ + + +Quittungsdruck + + + +
+ +
+

Kleidermarkt Kindergarten Kist

+

Datum: %0

+
+

Quittungsliste für Kennziffer %1 bis %2:

+
+
+ + + + + + + + + + + + + + +%3 + +
Verk.Nr.VerkaufspreisAuszahlungspreisDatumUnterschrift
+ ------------------------------------------------------------------------------------------------------------------------------------------------------- +
+ +
+
+ +