diff --git a/README.md b/README.md
index f771513..fc95ffe 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,73 @@
-# Arbeitszeitrechner
+
->**Du hast Gleitzeit und möchtest wissen, wann du ohne Minusstunden nach Hause kannst? Dann bist du hier genau richtig!**
-***
->
+# 🕐 Arbeitszeitrechner
+**Du hast Gleitzeit und möchtest wissen, wann du ohne Minusstunden nach Hause kannst?**
+Dann bist du hier genau richtig.
+
+
+
+---
+
+## ✨ Features
+
+- **Netto-Arbeitszeit berechnen** — Einstempelzeit + beliebig viele Pausen → exakte Netto-Zeit
+- **Zeitkonto** — positiver oder negativer Saldo gegenüber der Regelarbeitszeit auf einen Blick
+- **Ausstempelzeit vorschlagen** — kein Endzeitpunkt? Die App berechnet ihn automatisch
+- **Mitternachts-Überlauf** — Schichten die über 00:00 gehen werden korrekt behandelt
+- **ArbZG-Hinweise** — Erinnerung an gesetzliche Mindestpausen (§ 4 ArbZG) bei langen Arbeitstagen
+- **Einstellungen werden gespeichert** — Regelarbeitszeit bleibt nach dem Neustart erhalten
+- **Dark Mode** — Fusion-Palette, augenschonend auch spät abends
+
+---
+
+## 🔧 Voraussetzungen
+
+| Abhängigkeit | Mindestversion |
+|---|---|
+| Qt | 6.x (`Qt6::Widgets`) |
+| CMake | 3.16 |
+| C++-Compiler | C++17 (GCC, Clang, MSVC) |
+
+**Arch Linux:**
+```bash
+sudo pacman -S --needed qt6-base cmake gcc make
+```
+
+**Ubuntu / Debian:**
+```bash
+sudo apt install qt6-base-dev cmake g++
+```
+
+---
+
+## 🚀 Build & Start
+
+```bash
+# Konfigurieren
+cmake -B build -DCMAKE_BUILD_TYPE=Release
+
+# Kompilieren
+cmake --build build -j$(nproc)
+
+# Starten
+./build/ArbeitszeitRechner
+```
+
+---
+
+## 📖 Benutzung
+
+1. **Einstempelzeit** eintragen
+2. **Pausen** einzeln in Minuten hinzufügen (Entf-Taste entfernt markierte Einträge)
+3. Optional: **Ausstempelzeit** aktivieren, um die tatsächlich geleistete Zeit zu berechnen
+4. **Regelarbeitszeit** (Std : Min) einstellen — wird beim nächsten Start gespeichert
+5. **„Berechnung starten"** → Netto-Zeit, Zeitkonto und ggf. Ausstempel-Vorschlag erscheinen
+
+---
+
+## 📄 Lizenz
+
+MIT — mach damit was du willst.
diff --git a/WorkTimeCalculator.cpp b/WorkTimeCalculator.cpp
index eead62a..c568ffc 100644
--- a/WorkTimeCalculator.cpp
+++ b/WorkTimeCalculator.cpp
@@ -6,16 +6,25 @@
#include
#include
#include
+#include
+#include
+#include
+
+WorkTimeCalculator::WorkTimeCalculator(QWidget *parent)
+: QMainWindow(parent) {
+ // QSettings braucht Organisation + Anwendung. Einmal global setzen,
+ // dann reicht QSettings() ohne Argumente überall in der App.
+ QCoreApplication::setOrganizationName("DietzLabs");
+ QCoreApplication::setApplicationName("ArbeitszeitRechner");
-WorkTimeCalculator::WorkTimeCalculator() {
// Hauptlayout
QWidget *mainWidget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout(mainWidget);
- mainWidget->setLayout(layout); // Setze das Layout für das Widget
// Einstempelzeit
QLabel *startTimeLabel = new QLabel("Einstempelzeit:");
startTimeEdit = new QTimeEdit;
+ startTimeEdit->setDisplayFormat("hh:mm");
startTimeEdit->setTime(QTime::currentTime());
layout->addWidget(startTimeLabel);
layout->addWidget(startTimeEdit);
@@ -24,17 +33,26 @@ WorkTimeCalculator::WorkTimeCalculator() {
QLabel *breaksLabel = new QLabel("Pausenzeiten (Minuten):");
layout->addWidget(breaksLabel);
- addBreakButton = new QPushButton("Pause hinzufügen");
- layout->addWidget(addBreakButton);
+ QHBoxLayout *breakButtonLayout = new QHBoxLayout();
+ addBreakButton = new QPushButton("Pause hinzufügen");
+ removeBreakButton = new QPushButton("Pause entfernen");
+ breakButtonLayout->addWidget(addBreakButton);
+ breakButtonLayout->addWidget(removeBreakButton);
+ layout->addLayout(breakButtonLayout);
breakList = new QListWidget;
layout->addWidget(breakList);
- connect(addBreakButton, &QPushButton::clicked, this, &WorkTimeCalculator::addBreak);
+ connect(addBreakButton, &QPushButton::clicked, this, &WorkTimeCalculator::addBreak);
+ connect(removeBreakButton, &QPushButton::clicked, this, &WorkTimeCalculator::removeSelectedBreak);
+ // Komfort: Entf-Taste löscht die markierte Pause.
+ QShortcut *del = new QShortcut(QKeySequence(Qt::Key_Delete), breakList);
+ connect(del, &QShortcut::activated, this, &WorkTimeCalculator::removeSelectedBreak);
// Ausstempelzeit (optional)
includeEndTimeCheckbox = new QCheckBox("Ausstempelzeit angeben");
endTimeEdit = new QTimeEdit;
+ endTimeEdit->setDisplayFormat("hh:mm");
endTimeEdit->setTime(QTime::currentTime());
endTimeEdit->setVisible(false);
layout->addWidget(includeEndTimeCheckbox);
@@ -61,6 +79,7 @@ WorkTimeCalculator::WorkTimeCalculator() {
layout->addWidget(calculateButton);
resultLabel = new QLabel;
+ resultLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
layout->addWidget(resultLabel);
connect(calculateButton, &QPushButton::clicked, this, &WorkTimeCalculator::calculateWorkTime);
@@ -75,7 +94,6 @@ WorkTimeCalculator::WorkTimeCalculator() {
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, Qt::white);
-
qApp->setPalette(darkPalette);
setCentralWidget(mainWidget);
@@ -88,60 +106,127 @@ WorkTimeCalculator::~WorkTimeCalculator() {
saveSettings();
}
-void WorkTimeCalculator::addBreak() {
- bool ok;
- int breakTime = QInputDialog::getInt(this, "Pause hinzufügen", "Pause (Minuten):", 0, 0, 1440, 1, &ok);
- if (ok && breakTime > 0) {
- breakList->addItem(QString::number(breakTime) + " Minuten");
- }
+// --- Pausen -----------------------------------------------------------------
+
+void WorkTimeCalculator::addBreakItem(int minutes) {
+ auto *item = new QListWidgetItem(QString("%1 Minuten").arg(minutes));
+ item->setData(BreakRole, minutes); // echte Daten getrennt vom Anzeigetext
+ breakList->addItem(item);
}
-void WorkTimeCalculator::calculateWorkTime() {
- QTime startTime = startTimeEdit->time();
- int totalBreakMinutes = 0;
+void WorkTimeCalculator::addBreak() {
+ bool ok = false;
+ int breakTime = QInputDialog::getInt(
+ this, "Pause hinzufügen", "Pause (Minuten):",
+ /*value*/ 30, /*min*/ 1, /*max*/ 1440, /*step*/ 1, &ok);
+ if (ok)
+ addBreakItem(breakTime);
+}
- for (int i = 0; i < breakList->count(); ++i) {
- totalBreakMinutes += breakList->item(i)->text().split(" ")[0].toInt();
+void WorkTimeCalculator::removeSelectedBreak() {
+ qDeleteAll(breakList->selectedItems()); // entfernt + löscht die markierten Items
+}
+
+int WorkTimeCalculator::totalBreakMinutes() const {
+ int total = 0;
+ for (int i = 0; i < breakList->count(); ++i)
+ total += breakList->item(i)->data(BreakRole).toInt();
+ return total;
+}
+
+// --- Hilfsfunktionen --------------------------------------------------------
+
+int WorkTimeCalculator::minutesBetween(const QTime &start, const QTime &end, bool *crossesMidnight) {
+ int secs = start.secsTo(end);
+ bool wrapped = false;
+ if (secs < 0) { // Ende liegt am Folgetag (z. B. Spät-/Nachtschicht)
+ secs += 24 * 3600;
+ wrapped = true;
}
+ if (crossesMidnight)
+ *crossesMidnight = wrapped;
+ return secs / 60;
+}
- // Gesamte Pausenzeit anzeigen
- QString breakTimeMessage = QString("Gesamte Pausenzeit: %1 Minuten").arg(totalBreakMinutes);
+QString WorkTimeCalculator::formatDuration(int minutes) {
+ int a = qAbs(minutes);
+ return QString("%1:%2").arg(a / 60).arg(a % 60, 2, 10, QChar('0'));
+}
+
+QString WorkTimeCalculator::formatSignedDuration(int minutes) {
+ const QString sign = minutes < 0 ? "-" : "+";
+ return sign + formatDuration(minutes);
+}
+
+// --- Berechnung -------------------------------------------------------------
+
+void WorkTimeCalculator::calculateWorkTime() {
+ const QTime startTime = startTimeEdit->time();
+ const int breaks = totalBreakMinutes();
+ const int dailyMinutes = dailyHoursSpin->value() * 60 + dailyMinutesSpin->value();
QTime endTime;
+ bool endIsNextDay = false;
+
if (includeEndTimeCheckbox->isChecked()) {
endTime = endTimeEdit->time();
} else {
- // Ausstempelzeit berechnen, wenn nicht angegeben
- int dailyMinutes = dailyHoursSpin->value() * 60 + dailyMinutesSpin->value();
- endTime = startTime.addSecs((dailyMinutes + totalBreakMinutes) * 60);
+ // Vorschlag: Anwesenheit = Soll-Netto + Pausen.
+ const int presenceMinutes = dailyMinutes + breaks;
+ endTime = startTime.addSecs(presenceMinutes * 60);
+ endIsNextDay = (startTime.secsTo(endTime) < 0) || (presenceMinutes >= 24 * 60);
}
- int workedMinutes = startTime.secsTo(endTime) / 60 - totalBreakMinutes;
+ // Vergangene Anwesenheit inkl. korrekter Mitternachts-Behandlung.
+ bool crossesMidnight = false;
+ const int presenceMinutes = minutesBetween(startTime, endTime, &crossesMidnight);
+ if (includeEndTimeCheckbox->isChecked())
+ endIsNextDay = crossesMidnight;
- int dailyMinutes = dailyHoursSpin->value() * 60 + dailyMinutesSpin->value();
- int balanceMinutes = workedMinutes - dailyMinutes;
+ const int workedMinutes = presenceMinutes - breaks;
- QString result = QString("Netto-Arbeitszeit: %1 Stunden %2 Minuten\n")
- .arg(workedMinutes / 60)
- .arg(workedMinutes % 60);
- result += QString("Zeitkonto: %1 Minuten\n").arg(balanceMinutes);
- result += breakTimeMessage; // Gesamte Pausenzeit hinzufügen
+ // Plausibilitätsprüfung im manuellen Modus.
+ if (includeEndTimeCheckbox->isChecked() && workedMinutes < 0) {
+ QMessageBox::warning(this, "Ungültige Eingabe",
+ "Die Pausenzeit ist länger als die Anwesenheit. "
+ "Bitte Ein-/Ausstempelzeit und Pausen prüfen.");
+ return;
+ }
+
+ const int balanceMinutes = workedMinutes - dailyMinutes;
+
+ QString result;
+ result += QString("Netto-Arbeitszeit: %1 Std\n").arg(formatDuration(workedMinutes));
+ result += QString("Zeitkonto: %1 Std\n").arg(formatSignedDuration(balanceMinutes));
+ result += QString("Gesamte Pausenzeit: %1 Minuten").arg(breaks);
if (!includeEndTimeCheckbox->isChecked()) {
- result += QString("\nVorgeschlagene Ausstempelzeit: %1").arg(endTime.toString("hh:mm"));
+ result += QString("\nVorgeschlagene Ausstempelzeit: %1%2")
+ .arg(endTime.toString("hh:mm"),
+ endIsNextDay ? " (Folgetag)" : "");
+ } else if (endIsNextDay) {
+ result += "\nHinweis: Ausstempelzeit liegt am Folgetag (über Mitternacht).";
}
+ // Hinweis auf gesetzliche Mindestpausen nach ArbZG §4 (kein Rechtsrat).
+ if (workedMinutes > 9 * 60 && breaks < 45)
+ result += "\n\n⚠ Ab 9 Std Arbeitszeit sind mind. 45 Minuten Pause vorgesehen (ArbZG §4).";
+ else if (workedMinutes > 6 * 60 && breaks < 30)
+ result += "\n\n⚠ Ab 6 Std Arbeitszeit sind mind. 30 Minuten Pause vorgesehen (ArbZG §4).";
+
resultLabel->setText(result);
}
+// --- Persistenz -------------------------------------------------------------
+
void WorkTimeCalculator::loadSettings() {
- QSettings settings("ArbeitszeitRechner", "Settings");
+ QSettings settings; // nutzt Organisation/Anwendung aus dem Konstruktor
dailyHoursSpin->setValue(settings.value("dailyHours", 8).toInt());
dailyMinutesSpin->setValue(settings.value("dailyMinutes", 0).toInt());
}
void WorkTimeCalculator::saveSettings() {
- QSettings settings("ArbeitszeitRechner", "Settings");
+ QSettings settings;
settings.setValue("dailyHours", dailyHoursSpin->value());
settings.setValue("dailyMinutes", dailyMinutesSpin->value());
}
diff --git a/WorkTimeCalculator.h b/WorkTimeCalculator.h
index 8e5366f..9f41a0d 100644
--- a/WorkTimeCalculator.h
+++ b/WorkTimeCalculator.h
@@ -8,35 +8,48 @@
#include // Widget zur Anzeige der Pausenzeiten
#include // Eingabe für numerische Werte (z. B. Stunden/Minuten)
#include // Widget zur Anzeige von Text
+#include
class WorkTimeCalculator : public QMainWindow {
Q_OBJECT // Erforderlich für Qt-Signal- und Slot-Mechanismus
public:
// Konstruktor und Destruktor
- WorkTimeCalculator(); // Initialisiert das GUI und die Logik
- ~WorkTimeCalculator(); // Speichert Einstellungen beim Schließen
+ explicit WorkTimeCalculator(QWidget *parent = nullptr); // Initialisiert GUI und Logik
+ ~WorkTimeCalculator() override; // Speichert Einstellungen beim Schließen
private slots:
// Slots für Benutzeraktionen
- void addBreak(); // Hinzufügen einer neuen Pause
+ void addBreak(); // Hinzufügen einer neuen Pause
+ void removeSelectedBreak(); // Entfernt die markierte Pause
void calculateWorkTime(); // Berechnet die Netto-Arbeitszeit
private:
// Hilfsfunktionen
void loadSettings(); // Lädt gespeicherte Einstellungen
void saveSettings(); // Speichert aktuelle Einstellungen
+ int totalBreakMinutes() const; // Summe aller Pausen (aus den Item-Daten)
+ void addBreakItem(int minutes); // Fügt eine Pause als Item mit Datenrolle ein
+
+ // Liefert vergangene Minuten zwischen zwei Zeiten und behandelt
+ // den Überlauf über Mitternacht korrekt (Ende < Start -> +24h).
+ static int minutesBetween(const QTime &start, const QTime &end, bool *crossesMidnight = nullptr);
+ static QString formatDuration(int minutes); // "8:05" (Betrag, ohne Vorzeichen)
+ static QString formatSignedDuration(int minutes); // "+1:15" / "-0:45"
// GUI-Komponenten
- QTimeEdit *startTimeEdit; // Widget für die Einstempelzeit
- QTimeEdit *endTimeEdit; // Widget für die Ausstempelzeit (optional)
- QPushButton *addBreakButton; // Button, um eine Pause hinzuzufügen
- QPushButton *calculateButton; // Button, um die Arbeitszeit zu berechnen
- QCheckBox *includeEndTimeCheckbox; // Checkbox zur Aktivierung der Ausstempelzeit
- QListWidget *breakList; // Liste der eingegebenen Pausenzeiten
- QSpinBox *dailyHoursSpin; // Eingabe für tägliche Sollarbeitszeit (Stunden)
- QSpinBox *dailyMinutesSpin; // Eingabe für tägliche Sollarbeitszeit (Minuten)
- QLabel *resultLabel; // Anzeige für das Ergebnis der Berechnung
+ QTimeEdit *startTimeEdit; // Widget für die Einstempelzeit
+ QTimeEdit *endTimeEdit; // Widget für die Ausstempelzeit (optional)
+ QPushButton *addBreakButton; // Button, um eine Pause hinzuzufügen
+ QPushButton *removeBreakButton; // Button, um eine Pause zu entfernen
+ QPushButton *calculateButton; // Button, um die Arbeitszeit zu berechnen
+ QCheckBox *includeEndTimeCheckbox; // Checkbox zur Aktivierung der Ausstempelzeit
+ QListWidget *breakList; // Liste der eingegebenen Pausenzeiten
+ QSpinBox *dailyHoursSpin; // Eingabe für tägliche Sollarbeitszeit (Stunden)
+ QSpinBox *dailyMinutesSpin; // Eingabe für tägliche Sollarbeitszeit (Minuten)
+ QLabel *resultLabel; // Anzeige für das Ergebnis der Berechnung
+
+ static constexpr int BreakRole = Qt::UserRole; // Datenrolle für die Pausenminuten
};
#endif // WORKTIMECALCULATOR_H