Added existing sources
92
.gitignore
vendored
@@ -1,39 +1,73 @@
|
||||
# C++ objects and libs
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.la
|
||||
*.lai
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.dll
|
||||
*.dylib
|
||||
|
||||
# Qt-es
|
||||
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
*.pro.user
|
||||
*.pro.user.*
|
||||
*.qbs.user
|
||||
*.qbs.user.*
|
||||
*.moc
|
||||
moc_*.cpp
|
||||
moc_*.h
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
Makefile*
|
||||
*build-*
|
||||
|
||||
# QtCreator
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
*.autosave
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# QtCtreator Qml
|
||||
*.qmlproject.user
|
||||
*.qmlproject.user.*
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# QtCtreator CMake
|
||||
CMakeLists.txt.user*
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
|
21
dialogs/aboutmedialog.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "aboutmedialog.h"
|
||||
#include "ui_aboutmedialog.h"
|
||||
|
||||
AboutMeDialog::AboutMeDialog(const Zeiterfassung::UserInfo &userInfo, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AboutMeDialog),
|
||||
m_userInfo(userInfo)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->spinBoxUserId->setValue(userInfo.userId);
|
||||
ui->lineEditEmail->setText(userInfo.email);
|
||||
ui->lineEditLongUsername->setText(userInfo.longUsername);
|
||||
ui->lineEditText->setText(userInfo.text);
|
||||
ui->lineEditUsername->setText(userInfo.username);
|
||||
}
|
||||
|
||||
AboutMeDialog::~AboutMeDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
23
dialogs/aboutmedialog.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef ABOUTMEDIALOG_H
|
||||
#define ABOUTMEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
namespace Ui { class AboutMeDialog; }
|
||||
|
||||
class AboutMeDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutMeDialog(const Zeiterfassung::UserInfo &userInfo, QWidget *parent = 0);
|
||||
~AboutMeDialog();
|
||||
|
||||
private:
|
||||
Ui::AboutMeDialog *ui;
|
||||
const Zeiterfassung::UserInfo &m_userInfo;
|
||||
};
|
||||
|
||||
#endif // ABOUTMEDIALOG_H
|
120
dialogs/aboutmedialog.ui
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutMeDialog</class>
|
||||
<widget class="QDialog" name="AboutMeDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTitle">
|
||||
<property name="text">
|
||||
<string><h1>About me</h1></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelUserId">
|
||||
<property name="text">
|
||||
<string>User-ID:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>spinBoxUserId</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelEmail">
|
||||
<property name="text">
|
||||
<string>E-Mail:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditEmail</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelLongUsername">
|
||||
<property name="text">
|
||||
<string>Long username:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditLongUsername</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelText">
|
||||
<property name="text">
|
||||
<string>Text:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditText</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelUsername">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditUsername</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxUserId">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>16777215</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditEmail">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditLongUsername">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEditText">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEditUsername">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
34
dialogs/authenticationdialog.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "authenticationdialog.h"
|
||||
#include "ui_authenticationdialog.h"
|
||||
|
||||
AuthenticationDialog::AuthenticationDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AuthenticationDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AuthenticationDialog::~AuthenticationDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString AuthenticationDialog::username() const
|
||||
{
|
||||
return ui->lineEditUsername->text();
|
||||
}
|
||||
|
||||
void AuthenticationDialog::setUsername(const QString &username)
|
||||
{
|
||||
ui->lineEditUsername->setText(username);
|
||||
}
|
||||
|
||||
QString AuthenticationDialog::password() const
|
||||
{
|
||||
return ui->lineEditPassword->text();
|
||||
}
|
||||
|
||||
void AuthenticationDialog::setPassword(const QString &password)
|
||||
{
|
||||
ui->lineEditPassword->setText(password);
|
||||
}
|
28
dialogs/authenticationdialog.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef AUTHENTICATIONDIALOG_H
|
||||
#define AUTHENTICATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class AuthenticationDialog;
|
||||
}
|
||||
|
||||
class AuthenticationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AuthenticationDialog(QWidget *parent = 0);
|
||||
~AuthenticationDialog();
|
||||
|
||||
QString username() const;
|
||||
void setUsername(const QString &username);
|
||||
|
||||
QString password() const;
|
||||
void setPassword(const QString &password);
|
||||
|
||||
private:
|
||||
Ui::AuthenticationDialog *ui;
|
||||
};
|
||||
|
||||
#endif // AUTHENTICATIONDIALOG_H
|
133
dialogs/authenticationdialog.ui
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AuthenticationDialog</class>
|
||||
<widget class="QDialog" name="AuthenticationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>394</width>
|
||||
<height>169</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLogo">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources.qrc">:/zeiterfassung/images/authentication.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTitle">
|
||||
<property name="text">
|
||||
<string><h1>Authentication</h1></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelUsername">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditUsername</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelPassword">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditPassword</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditUsername"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditPassword">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AuthenticationDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AuthenticationDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
55
dialogs/buchungdialog.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "buchungdialog.h"
|
||||
#include "ui_buchungdialog.h"
|
||||
|
||||
BuchungDialog::BuchungDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::BuchungDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->timeEditTime->setTime(QTime::currentTime());
|
||||
}
|
||||
|
||||
BuchungDialog::~BuchungDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QTime BuchungDialog::getTime() const
|
||||
{
|
||||
return ui->timeEditTime->time();
|
||||
}
|
||||
|
||||
void BuchungDialog::setTime(const QTime &time)
|
||||
{
|
||||
ui->timeEditTime->setTime(time);
|
||||
}
|
||||
|
||||
QTime BuchungDialog::getTimespan() const
|
||||
{
|
||||
return ui->timeEditTimespan->time();
|
||||
}
|
||||
|
||||
void BuchungDialog::setTimespan(const QTime ×pan)
|
||||
{
|
||||
ui->timeEditTimespan->setTime(timespan);
|
||||
}
|
||||
|
||||
QString BuchungDialog::getType() const
|
||||
{
|
||||
return ui->comboBoxType->currentText();
|
||||
}
|
||||
|
||||
void BuchungDialog::setType(const QString &type)
|
||||
{
|
||||
ui->comboBoxType->setCurrentText(type);
|
||||
}
|
||||
|
||||
QString BuchungDialog::getText() const
|
||||
{
|
||||
return ui->lineEditText->text();
|
||||
}
|
||||
|
||||
void BuchungDialog::setText(const QString &text)
|
||||
{
|
||||
ui->lineEditText->setText(text);
|
||||
}
|
34
dialogs/buchungdialog.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef BUCHUNGDIALOG_H
|
||||
#define BUCHUNGDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class BuchungDialog;
|
||||
}
|
||||
|
||||
class BuchungDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuchungDialog(QWidget *parent = 0);
|
||||
~BuchungDialog();
|
||||
|
||||
QTime getTime() const;
|
||||
void setTime(const QTime &time);
|
||||
|
||||
QTime getTimespan() const;
|
||||
void setTimespan(const QTime ×pan);
|
||||
|
||||
QString getType() const;
|
||||
void setType(const QString &type);
|
||||
|
||||
QString getText() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
private:
|
||||
Ui::BuchungDialog *ui;
|
||||
};
|
||||
|
||||
#endif // BUCHUNGDIALOG_H
|
139
dialogs/buchungdialog.ui
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuchungDialog</class>
|
||||
<widget class="QDialog" name="BuchungDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTitle">
|
||||
<property name="text">
|
||||
<string><h1>Buchung</h1></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTime">
|
||||
<property name="text">
|
||||
<string>Time:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>timeEditTime</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelTimespan">
|
||||
<property name="text">
|
||||
<string>Timespan:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>timeEditTimespan</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelType">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboBoxType</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelText">
|
||||
<property name="text">
|
||||
<string>Text:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditText</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QTimeEdit" name="timeEditTime">
|
||||
<property name="displayFormat">
|
||||
<string>HH:mm:ss</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTimeEdit" name="timeEditTimespan">
|
||||
<property name="displayFormat">
|
||||
<string>HH:mm:ss</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEditText"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxType">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BuchungDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BuchungDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
88
dialogs/kontierungdialog.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "kontierungdialog.h"
|
||||
#include "ui_kontierungdialog.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
#include <QDebug>
|
||||
|
||||
KontierungDialog::KontierungDialog(Zeiterfassung &erfassung, const Zeiterfassung::UserInfo &userInfo,
|
||||
const QVector<Zeiterfassung::Projekt> &projekte, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::KontierungDialog),
|
||||
m_erfassung(erfassung),
|
||||
m_userInfo(userInfo)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
for(const auto& projekt : projekte)
|
||||
ui->comboBoxProjekt->addItem(projekt.label % " (" % projekt.value % ')', projekt.value);
|
||||
}
|
||||
|
||||
KontierungDialog::~KontierungDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QTime KontierungDialog::getTime() const
|
||||
{
|
||||
return ui->timeEditTime->time();
|
||||
}
|
||||
|
||||
void KontierungDialog::setTime(const QTime &time)
|
||||
{
|
||||
ui->timeEditTime->setTime(time);
|
||||
}
|
||||
|
||||
QTime KontierungDialog::getTimespan() const
|
||||
{
|
||||
return ui->timeEditTimespan->time();
|
||||
}
|
||||
|
||||
void KontierungDialog::setTimespan(const QTime ×pan)
|
||||
{
|
||||
ui->timeEditTimespan->setTime(timespan);
|
||||
}
|
||||
|
||||
QString KontierungDialog::getProjekt() const
|
||||
{
|
||||
return ui->comboBoxProjekt->currentData().toString();
|
||||
}
|
||||
|
||||
void KontierungDialog::setProjekt(const QString &projekt)
|
||||
{
|
||||
auto index = ui->comboBoxProjekt->findData(projekt);
|
||||
if(index >= 0)
|
||||
ui->comboBoxProjekt->setCurrentIndex(index);
|
||||
else
|
||||
qWarning() << "could not find projekt" << projekt;
|
||||
}
|
||||
|
||||
QString KontierungDialog::getSubprojekt() const
|
||||
{
|
||||
return ui->lineEditSubprojekt->text();
|
||||
}
|
||||
|
||||
void KontierungDialog::setSubprojekt(const QString &subprojekt)
|
||||
{
|
||||
ui->lineEditSubprojekt->setText(subprojekt);
|
||||
}
|
||||
|
||||
QString KontierungDialog::getWorkpackage() const
|
||||
{
|
||||
return ui->lineEditWorkpackage->text();
|
||||
}
|
||||
|
||||
void KontierungDialog::setWorkpackage(const QString &workpackage)
|
||||
{
|
||||
ui->lineEditWorkpackage->setText(workpackage);
|
||||
}
|
||||
|
||||
QString KontierungDialog::getText() const
|
||||
{
|
||||
return ui->lineEditText->text();
|
||||
}
|
||||
|
||||
void KontierungDialog::setText(const QString &text)
|
||||
{
|
||||
ui->lineEditText->setText(text);
|
||||
}
|
43
dialogs/kontierungdialog.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef KONTIERUNGDIALOG_H
|
||||
#define KONTIERUNGDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
namespace Ui { class KontierungDialog; }
|
||||
|
||||
class KontierungDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit KontierungDialog(Zeiterfassung &erfassung, const Zeiterfassung::UserInfo &userInfo,
|
||||
const QVector<Zeiterfassung::Projekt> &projekte, QWidget *parent = 0);
|
||||
~KontierungDialog();
|
||||
|
||||
QTime getTime() const;
|
||||
void setTime(const QTime &time);
|
||||
|
||||
QTime getTimespan() const;
|
||||
void setTimespan(const QTime ×pan);
|
||||
|
||||
QString getProjekt() const;
|
||||
void setProjekt(const QString &projekt);
|
||||
|
||||
QString getSubprojekt() const;
|
||||
void setSubprojekt(const QString &subprojekt);
|
||||
|
||||
QString getWorkpackage() const;
|
||||
void setWorkpackage(const QString &workpackage);
|
||||
|
||||
QString getText() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
private:
|
||||
Ui::KontierungDialog *ui;
|
||||
Zeiterfassung &m_erfassung;
|
||||
const Zeiterfassung::UserInfo &m_userInfo;
|
||||
};
|
||||
|
||||
#endif // KONTIERUNGDIALOG_H
|
168
dialogs/kontierungdialog.ui
Normal file
@@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KontierungDialog</class>
|
||||
<widget class="QDialog" name="KontierungDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTitle">
|
||||
<property name="text">
|
||||
<string><h1>Kontierung</h1></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTime">
|
||||
<property name="text">
|
||||
<string>Time:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>timeEditTime</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelTimespan">
|
||||
<property name="text">
|
||||
<string>Timespan:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>timeEditTimespan</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelProjekt">
|
||||
<property name="text">
|
||||
<string>Projekt:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboBoxProjekt</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelSubprojekt">
|
||||
<property name="text">
|
||||
<string>Subprojekt:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditSubprojekt</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelWorkpackage">
|
||||
<property name="text">
|
||||
<string>Workpackage:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditWorkpackage</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelText">
|
||||
<property name="text">
|
||||
<string>Text:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditText</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QTimeEdit" name="timeEditTime">
|
||||
<property name="displayFormat">
|
||||
<string>HH:mm:ss</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTimeEdit" name="timeEditTimespan">
|
||||
<property name="displayFormat">
|
||||
<string>HH:mm:ss</string>
|
||||
</property>
|
||||
<property name="time">
|
||||
<time>
|
||||
<hour>1</hour>
|
||||
<minute>0</minute>
|
||||
<second>0</second>
|
||||
</time>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxProjekt"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEditSubprojekt"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEditWorkpackage"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEditText"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>KontierungDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>KontierungDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
24
eventloopwithstatus.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "eventloopwithstatus.h"
|
||||
|
||||
EventLoopWithStatus::EventLoopWithStatus(QObject *parent) :
|
||||
QEventLoop(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EventLoopWithStatus::success() const
|
||||
{
|
||||
return m_success;
|
||||
}
|
||||
|
||||
const QString &EventLoopWithStatus::message() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
void EventLoopWithStatus::quitWithStatus(bool success, const QString &message)
|
||||
{
|
||||
m_success = success;
|
||||
m_message = message;
|
||||
quit();
|
||||
}
|
24
eventloopwithstatus.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef EVENTLOOPWITHSTATUS_H
|
||||
#define EVENTLOOPWITHSTATUS_H
|
||||
|
||||
#include <QEventLoop>
|
||||
|
||||
class EventLoopWithStatus : public QEventLoop
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EventLoopWithStatus(QObject *parent = Q_NULLPTR);
|
||||
|
||||
bool success() const;
|
||||
const QString &message() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void quitWithStatus(bool success, const QString &message);
|
||||
|
||||
private:
|
||||
bool m_success;
|
||||
QString m_message;
|
||||
};
|
||||
|
||||
#endif // EVENTLOOPWITHSTATUS_H
|
BIN
images/authentication.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
images/next.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
images/previous.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
images/quit.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
images/refresh.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/splash.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
images/today.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
135
main.cpp
Executable file
@@ -0,0 +1,135 @@
|
||||
#include <QApplication>
|
||||
#include <QSplashScreen>
|
||||
#include <QPixmap>
|
||||
#include <QSettings>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
#include "eventloopwithstatus.h"
|
||||
#include "dialogs/authenticationdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QCoreApplication::setOrganizationDomain(QStringLiteral("brunner.ninja"));
|
||||
QCoreApplication::setOrganizationName(QStringLiteral("db-software"));
|
||||
QCoreApplication::setApplicationName(QStringLiteral("zeiterfassung"));
|
||||
QCoreApplication::setApplicationVersion(QStringLiteral("1.0"));
|
||||
|
||||
QSplashScreen splashScreen(QPixmap(":/zeiterfassung/images/splash.png"));
|
||||
splashScreen.showMessage(QObject::tr("Loading settings..."));
|
||||
splashScreen.show();
|
||||
|
||||
QSettings settings;
|
||||
|
||||
if(settings.value("url").isNull())
|
||||
{
|
||||
bool ok;
|
||||
auto url = QInputDialog::getText(&splashScreen, QObject::tr("Base url"),
|
||||
QObject::tr("Please enter the base url to the Zeiterfassung:"),
|
||||
QLineEdit::Normal, QString(), &ok);
|
||||
if(!ok)
|
||||
return -1;
|
||||
settings.setValue("url", url);
|
||||
}
|
||||
|
||||
splashScreen.showMessage(QObject::tr("Loading login page..."));
|
||||
|
||||
Zeiterfassung erfassung(settings.value("url").toString());
|
||||
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
QObject::connect(&erfassung, &Zeiterfassung::loginPageFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
again1:
|
||||
erfassung.doLoginPage();
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
bool ok;
|
||||
QMessageBox::warning(&splashScreen, QObject::tr("Could not access Zeiterfassung"),
|
||||
QObject::tr("The Zeiterfassung could not be accessed:\n\n%0").arg(eventLoop.message()));
|
||||
|
||||
auto url = QInputDialog::getText(&splashScreen, QObject::tr("Base url"),
|
||||
QObject::tr("Please enter the base url to the Zeiterfassung:"),
|
||||
QLineEdit::Normal, settings.value("url").toString(), &ok);
|
||||
if(!ok)
|
||||
return -1;
|
||||
settings.setValue("url", url);
|
||||
erfassung.setUrl(url);
|
||||
goto again1;
|
||||
}
|
||||
}
|
||||
|
||||
splashScreen.showMessage(QObject::tr("Authenticating..."));
|
||||
|
||||
if(settings.value("username").isNull() || settings.value("password").isNull())
|
||||
{
|
||||
AuthenticationDialog dialog(&splashScreen);
|
||||
if(dialog.exec() != QDialog::Accepted)
|
||||
return -1;
|
||||
settings.setValue("username", dialog.username());
|
||||
settings.setValue("password", dialog.password());
|
||||
}
|
||||
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
QObject::connect(&erfassung, &Zeiterfassung::loginFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
again2:
|
||||
erfassung.doLogin(settings.value("username").toString(), settings.value("password").toString());
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
QMessageBox::warning(&splashScreen, QObject::tr("Could not authenticate with Zeiterfassung"),
|
||||
QObject::tr("The Zeiterfassung authentication was not successful:\n\n%0").arg(eventLoop.message()));
|
||||
|
||||
AuthenticationDialog dialog(&splashScreen);
|
||||
dialog.setUsername(settings.value("username").toString());
|
||||
dialog.setPassword(settings.value("password").toString());
|
||||
if(dialog.exec() != QDialog::Accepted)
|
||||
return -1;
|
||||
settings.setValue("username", dialog.username());
|
||||
settings.setValue("password", dialog.password());
|
||||
|
||||
goto again2;
|
||||
}
|
||||
}
|
||||
|
||||
splashScreen.showMessage(QObject::tr("Getting user information..."));
|
||||
|
||||
Zeiterfassung::UserInfo userInfo;
|
||||
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
QObject::connect(&erfassung, &Zeiterfassung::userInfoFinished,
|
||||
[&](bool success, const QString &message, const Zeiterfassung::UserInfo &_userInfo) {
|
||||
Q_UNUSED(message)
|
||||
if(success)
|
||||
userInfo = _userInfo;
|
||||
});
|
||||
QObject::connect(&erfassung, &Zeiterfassung::userInfoFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
erfassung.doUserInfo();
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
QMessageBox::warning(&splashScreen, QObject::tr("Could not get user information!"),
|
||||
QObject::tr("Could not get user information:\n\n%0").arg(eventLoop.message()));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow mainWindow(settings, erfassung, userInfo);
|
||||
mainWindow.show();
|
||||
|
||||
splashScreen.finish(&mainWindow);
|
||||
|
||||
return app.exec();
|
||||
}
|
978
mainwindow.cpp
Normal file
@@ -0,0 +1,978 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStandardItem>
|
||||
#include <QStringBuilder>
|
||||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
|
||||
#include "eventloopwithstatus.h"
|
||||
#include "dialogs/aboutmedialog.h"
|
||||
#include "dialogs/buchungdialog.h"
|
||||
#include "dialogs/kontierungdialog.h"
|
||||
#include "models/buchungenmodel.h"
|
||||
#include "models/kontierungenmodel.h"
|
||||
|
||||
MainWindow::MainWindow(QSettings &settings, Zeiterfassung &erfassung, const Zeiterfassung::UserInfo &userInfo, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
m_settings(settings),
|
||||
m_erfassung(erfassung),
|
||||
m_userInfo(userInfo),
|
||||
m_buchungenModel(new BuchungenModel(erfassung, this)),
|
||||
m_kontierungenModel(new KontierungenModel(erfassung, this)),
|
||||
m_flag(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowTitle(tr("Zeiterfassung - %0").arg(m_userInfo.text));
|
||||
|
||||
ui->actionQuit->setShortcut(QKeySequence::Quit);
|
||||
|
||||
connect(ui->actionToday, &QAction::triggered, [=](){ ui->dateEditDate->setDate(QDate::currentDate()); });
|
||||
|
||||
ui->actionRefresh->setShortcut(QKeySequence::Refresh);
|
||||
connect(ui->actionRefresh, &QAction::triggered, this, &MainWindow::refresh);
|
||||
|
||||
connect(ui->actionAboutMe, &QAction::triggered, [=](){ AboutMeDialog(userInfo, this).exec(); });
|
||||
connect(ui->actionAboutQt, &QAction::triggered, [=](){ QMessageBox::aboutQt(this); });
|
||||
|
||||
ui->dateEditDate->setDate(QDate::currentDate());
|
||||
connect(ui->dateEditDate, &QDateTimeEdit::dateChanged, this, &MainWindow::refresh);
|
||||
refresh();
|
||||
|
||||
connect(ui->pushButtonPrev, &QAbstractButton::pressed, this, &MainWindow::pushButtonPrevPressed);
|
||||
connect(ui->pushButtonNext, &QAbstractButton::pressed, this, &MainWindow::pushButtonNextPressed);
|
||||
|
||||
ui->timeEditTime->setTime(timeNormalise(QTime::currentTime()));
|
||||
|
||||
connect(&m_erfassung, &Zeiterfassung::getProjekteFinished,
|
||||
this, &MainWindow::getProjekteFinished);
|
||||
erfassung.doGetProjekte(userInfo.userId);
|
||||
|
||||
ui->comboBoxProjekt->setMaxVisibleItems(10);
|
||||
|
||||
ui->comboBoxSubprojekt->lineEdit()->setPlaceholderText(tr("Subprojekt"));
|
||||
ui->comboBoxWorkpackage->lineEdit()->setPlaceholderText(tr("Workpackage"));
|
||||
ui->comboBoxText->lineEdit()->setPlaceholderText(tr("Text"));
|
||||
|
||||
updateComboboxes();
|
||||
|
||||
connect(ui->pushButtonStart, &QAbstractButton::pressed, this, &MainWindow::pushButtonStartPressed);
|
||||
connect(ui->pushButtonEnd, &QAbstractButton::pressed, this, &MainWindow::pushButtonEndPressed);
|
||||
|
||||
ui->treeViewBuchungen->setModel(m_buchungenModel);
|
||||
ui->treeViewKontierungen->setModel(m_kontierungenModel);
|
||||
|
||||
connect(ui->treeViewBuchungen, &QWidget::customContextMenuRequested,
|
||||
this, &MainWindow::contextMenuBuchung);
|
||||
connect(ui->treeViewKontierungen, &QWidget::customContextMenuRequested,
|
||||
this, &MainWindow::contextMenuKontierung);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::refresh()
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewBuchungen->setEnabled(false);
|
||||
ui->treeViewKontierungen->setEnabled(false);
|
||||
|
||||
auto waitForBuchugen = m_buchungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date());
|
||||
if(waitForBuchugen)
|
||||
{
|
||||
connect(m_buchungenModel, &BuchungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshBuchungenFinished);
|
||||
}
|
||||
|
||||
auto waitForKontierungen = m_kontierungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date());
|
||||
if(waitForKontierungen)
|
||||
{
|
||||
connect(m_kontierungenModel, &KontierungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshKontierungenFinished);
|
||||
}
|
||||
|
||||
if(!waitForBuchugen || !waitForKontierungen)
|
||||
QMessageBox::warning(this, tr("Unknown error occured."), tr("An unknown error occured."));
|
||||
|
||||
if(waitForBuchugen || waitForKontierungen)
|
||||
m_flag = waitForBuchugen == waitForKontierungen;
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::getProjekteFinished(bool success, const QString &message, const QVector<Zeiterfassung::Projekt> &projekte)
|
||||
{
|
||||
disconnect(&m_erfassung, &Zeiterfassung::getProjekteFinished,
|
||||
this, &MainWindow::getProjekteFinished);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not load Buchungen!"), tr("Could not load Buchungen:\n\n%0").arg(message));
|
||||
return;
|
||||
}
|
||||
|
||||
m_projekte = projekte;
|
||||
|
||||
updateComboboxes();
|
||||
}
|
||||
|
||||
void MainWindow::refreshBuchungenFinished(bool success, const QString &message)
|
||||
{
|
||||
disconnect(m_buchungenModel, &BuchungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshBuchungenFinished);
|
||||
|
||||
if(success)
|
||||
ui->treeViewBuchungen->setEnabled(true);
|
||||
|
||||
if(m_flag)
|
||||
m_flag = false;
|
||||
else
|
||||
validateEntries();
|
||||
|
||||
if(!success)
|
||||
QMessageBox::warning(Q_NULLPTR, tr("Could not refresh Buchungen!"), tr("Could not refresh Buchungen:\n\n%0").arg(message));
|
||||
}
|
||||
|
||||
void MainWindow::refreshKontierungenFinished(bool success, const QString &message)
|
||||
{
|
||||
disconnect(m_kontierungenModel, &KontierungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshKontierungenFinished);
|
||||
|
||||
if(success)
|
||||
ui->treeViewKontierungen->setEnabled(true);
|
||||
|
||||
if(m_flag)
|
||||
m_flag = false;
|
||||
else
|
||||
validateEntries();
|
||||
|
||||
if(!success)
|
||||
QMessageBox::warning(Q_NULLPTR, tr("Could not refresh Kontierungen!"), tr("Could not refresh Kontierungen:\n\n%0").arg(message));
|
||||
}
|
||||
|
||||
void MainWindow::contextMenuBuchung(const QPoint &pos)
|
||||
{
|
||||
auto index = ui->treeViewBuchungen->indexAt(pos);
|
||||
|
||||
if(index.isValid())
|
||||
{
|
||||
auto buchung = m_buchungenModel->getBuchung(index);
|
||||
|
||||
QMenu menu;
|
||||
auto editAction = menu.addAction(tr("Edit"));
|
||||
auto deleteAction = menu.addAction(tr("Delete"));
|
||||
auto selectedAction = menu.exec(ui->treeViewBuchungen->viewport()->mapToGlobal(pos));
|
||||
if(selectedAction == editAction)
|
||||
{
|
||||
BuchungDialog dialog(this);
|
||||
dialog.setTime(buchung.time);
|
||||
dialog.setTimespan(buchung.timespan);
|
||||
dialog.setType(buchung.type);
|
||||
dialog.setText(buchung.text);
|
||||
again1:
|
||||
if(dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::updateBuchungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doUpdateBuchung(buchung.id, m_userInfo.userId, ui->dateEditDate->date(),
|
||||
dialog.getTime(), dialog.getTimespan(),
|
||||
dialog.getType(), dialog.getText());
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewBuchungen->setEnabled(false);
|
||||
|
||||
if(m_buchungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_buchungenModel, &BuchungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshBuchungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not update Buchung!"), tr("Could not update Buchung:\n\n%0").arg(eventLoop.message()));
|
||||
goto again1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(selectedAction == deleteAction)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("Do you really want to delete the Buchung?");
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||
if(msgBox.exec() == QMessageBox::Yes)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::deleteBuchungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doDeleteBuchung(buchung.id);
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewBuchungen->setEnabled(false);
|
||||
|
||||
if(m_buchungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_buchungenModel, &BuchungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshBuchungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
QMessageBox::warning(this, tr("Could not delete Buchung!"), tr("Could not delete Buchung:\n\n%0").arg(eventLoop.message()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMenu menu;
|
||||
auto createAction = menu.addAction(tr("Create"));
|
||||
auto selectedAction = menu.exec(ui->treeViewBuchungen->viewport()->mapToGlobal(pos));
|
||||
if(selectedAction == createAction)
|
||||
{
|
||||
BuchungDialog dialog(this);
|
||||
dialog.setTime(QTime::currentTime());
|
||||
again2:
|
||||
if(dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::createBuchungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doCreateBuchung(m_userInfo.userId, ui->dateEditDate->date(),
|
||||
dialog.getTime(), dialog.getTimespan(),
|
||||
dialog.getType(), dialog.getText());
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewBuchungen->setEnabled(false);
|
||||
|
||||
if(m_buchungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_buchungenModel, &BuchungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshBuchungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not create Buchung!"), tr("Could not create Buchung:\n\n%0").arg(eventLoop.message()));
|
||||
goto again2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::contextMenuKontierung(const QPoint &pos)
|
||||
{
|
||||
auto index = ui->treeViewKontierungen->indexAt(pos);
|
||||
|
||||
if(index.isValid())
|
||||
{
|
||||
auto kontierung = m_kontierungenModel->getKontierung(index);
|
||||
|
||||
QMenu menu;
|
||||
auto editAction = menu.addAction(tr("Edit"));
|
||||
auto deleteAction = menu.addAction(tr("Delete"));
|
||||
auto selectedAction = menu.exec(ui->treeViewKontierungen->viewport()->mapToGlobal(pos));
|
||||
if(selectedAction == editAction)
|
||||
{
|
||||
KontierungDialog dialog(m_erfassung, m_userInfo, m_projekte, this);
|
||||
dialog.setTime(kontierung.time);
|
||||
dialog.setTimespan(kontierung.timespan);
|
||||
dialog.setProjekt(kontierung.projekt);
|
||||
dialog.setSubprojekt(kontierung.subprojekt);
|
||||
dialog.setWorkpackage(kontierung.workpackage);
|
||||
dialog.setText(kontierung.text);
|
||||
again1:
|
||||
if(dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::updateKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doUpdateKontierung(kontierung.id, m_userInfo.userId, ui->dateEditDate->date(),
|
||||
dialog.getTime(), dialog.getTimespan(),
|
||||
dialog.getProjekt(), dialog.getSubprojekt(),
|
||||
dialog.getWorkpackage(), dialog.getText());
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewKontierungen->setEnabled(false);
|
||||
|
||||
if(m_kontierungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_kontierungenModel, &KontierungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshKontierungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not update Kontierung!"), tr("Could not update Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
goto again1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(selectedAction == deleteAction)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("Do you really want to delete the Kontierung?");
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||
if(msgBox.exec() == QMessageBox::Yes)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::deleteKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doDeleteKontierung(kontierung.id);
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewKontierungen->setEnabled(false);
|
||||
|
||||
if(m_kontierungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_kontierungenModel, &KontierungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshKontierungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
QMessageBox::warning(this, tr("Could not delete Kontierung!"), tr("Could not delete Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMenu menu;
|
||||
auto createAction = menu.addAction(tr("Create"));
|
||||
auto selectedAction = menu.exec(ui->treeViewKontierungen->viewport()->mapToGlobal(pos));
|
||||
if(selectedAction == createAction)
|
||||
{
|
||||
KontierungDialog dialog(m_erfassung, m_userInfo, m_projekte, this);
|
||||
again2:
|
||||
if(dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::createKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doCreateKontierung(m_userInfo.userId, ui->dateEditDate->date(),
|
||||
dialog.getTime(), dialog.getTimespan(),
|
||||
dialog.getProjekt(), dialog.getSubprojekt(),
|
||||
dialog.getWorkpackage(), dialog.getText());
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
{
|
||||
ui->actionToday->setEnabled(false);
|
||||
ui->actionRefresh->setEnabled(false);
|
||||
ui->dateEditDate->setReadOnly(true);
|
||||
ui->timeEditTime->setEnabled(false);
|
||||
ui->comboBoxProjekt->setEnabled(false);
|
||||
ui->comboBoxSubprojekt->setEnabled(false);
|
||||
ui->comboBoxWorkpackage->setEnabled(false);
|
||||
ui->comboBoxText->setEnabled(false);
|
||||
ui->pushButtonStart->setEnabled(false);
|
||||
ui->pushButtonEnd->setEnabled(false);
|
||||
ui->treeViewKontierungen->setEnabled(false);
|
||||
|
||||
if(m_kontierungenModel->refresh(m_userInfo.userId, ui->dateEditDate->date(), ui->dateEditDate->date()))
|
||||
{
|
||||
connect(m_kontierungenModel, &KontierungenModel::refreshFinished,
|
||||
this, &MainWindow::refreshKontierungenFinished);
|
||||
m_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not create Kontierung!"), tr("Could not create Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
goto again2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::pushButtonPrevPressed()
|
||||
{
|
||||
ui->dateEditDate->setDate(ui->dateEditDate->date().addDays(-1));
|
||||
}
|
||||
|
||||
void MainWindow::pushButtonNextPressed()
|
||||
{
|
||||
ui->dateEditDate->setDate(ui->dateEditDate->date().addDays(1));
|
||||
}
|
||||
|
||||
void MainWindow::pushButtonStartPressed()
|
||||
{
|
||||
if(m_buchungenModel->rbegin() == m_buchungenModel->rend() ||
|
||||
m_buchungenModel->rbegin()->type == QStringLiteral("G"))
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::createBuchungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doCreateBuchung(m_userInfo.userId, ui->dateEditDate->date(),
|
||||
timeNormalise(ui->timeEditTime->time()), QTime(0, 0),
|
||||
QStringLiteral("K"), QStringLiteral(""));
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not create Buchung!"), tr("Could not create Buchung:\n\n%0").arg(eventLoop.message()));
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_kontierungenModel->rbegin() != m_kontierungenModel->rend())
|
||||
{
|
||||
auto kontierung = *m_kontierungenModel->rbegin();
|
||||
if(kontierung.timespan == QTime(0, 0))
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::updateKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
auto timespan = timeBetween(m_lastKontierungStart, ui->timeEditTime->time());
|
||||
qDebug() << "timespan" << timespan;
|
||||
|
||||
m_erfassung.doUpdateKontierung(kontierung.id, m_userInfo.userId, kontierung.date,
|
||||
kontierung.time, timespan,
|
||||
kontierung.projekt, kontierung.subprojekt,
|
||||
kontierung.workpackage, kontierung.text);
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
m_kontierungTime = timeAdd(m_kontierungTime, timespan);
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not update Kontierung!"), tr("Could not update Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::createKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doCreateKontierung(m_userInfo.userId, ui->dateEditDate->date(),
|
||||
m_kontierungTime, QTime(0, 0),
|
||||
ui->comboBoxProjekt->currentData().toString(), ui->comboBoxSubprojekt->currentText(),
|
||||
ui->comboBoxWorkpackage->currentText(), ui->comboBoxText->currentText());
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not create Kontierung!"), tr("Could not create Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QStringList projekte = m_settings.value("projekte", QStringList()).toStringList();
|
||||
projekte.removeAll(ui->comboBoxProjekt->currentData().toString());
|
||||
projekte.prepend(ui->comboBoxProjekt->currentData().toString());
|
||||
m_settings.setValue("projekte", projekte);
|
||||
}
|
||||
|
||||
if(!ui->comboBoxSubprojekt->currentText().trimmed().isEmpty())
|
||||
{
|
||||
QStringList subprojekte = m_settings.value("subprojekte", QStringList()).toStringList();
|
||||
subprojekte.removeAll(ui->comboBoxSubprojekt->currentText());
|
||||
subprojekte.prepend(ui->comboBoxSubprojekt->currentText());
|
||||
m_settings.setValue("subprojekte", subprojekte);
|
||||
}
|
||||
|
||||
if(!ui->comboBoxWorkpackage->currentText().trimmed().isEmpty())
|
||||
{
|
||||
QStringList workpackages = m_settings.value("workpackages", QStringList()).toStringList();
|
||||
workpackages.removeAll(ui->comboBoxWorkpackage->currentText());
|
||||
workpackages.prepend(ui->comboBoxWorkpackage->currentText());
|
||||
m_settings.setValue("workpackages", workpackages);
|
||||
}
|
||||
|
||||
if(!ui->comboBoxText->currentText().trimmed().isEmpty())
|
||||
{
|
||||
QStringList texte = m_settings.value("texte", QStringList()).toStringList();
|
||||
texte.removeAll(ui->comboBoxText->currentText());
|
||||
texte.prepend(ui->comboBoxText->currentText());
|
||||
m_settings.setValue("texte", texte);
|
||||
}
|
||||
|
||||
updateComboboxes();
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MainWindow::pushButtonEndPressed()
|
||||
{
|
||||
{
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::createBuchungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
m_erfassung.doCreateBuchung(m_userInfo.userId, ui->dateEditDate->date(),
|
||||
timeNormalise(ui->timeEditTime->time()), QTime(0, 0),
|
||||
QStringLiteral("G"), QStringLiteral(""));
|
||||
eventLoop.exec();
|
||||
|
||||
if(!eventLoop.success())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not create Buchung!"), tr("Could not create Buchung:\n\n%0").arg(eventLoop.message()));
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto kontierung = *m_kontierungenModel->rbegin();
|
||||
Q_ASSERT(kontierung.timespan == QTime(0, 0));
|
||||
|
||||
EventLoopWithStatus eventLoop;
|
||||
connect(&m_erfassung, &Zeiterfassung::updateKontierungFinished, &eventLoop, &EventLoopWithStatus::quitWithStatus);
|
||||
|
||||
auto timespan = timeBetween(m_lastKontierungStart, ui->timeEditTime->time());
|
||||
qDebug() << "timespan" << timespan;
|
||||
|
||||
m_erfassung.doUpdateKontierung(kontierung.id, m_userInfo.userId, kontierung.date,
|
||||
kontierung.time, timespan,
|
||||
kontierung.projekt, kontierung.subprojekt,
|
||||
kontierung.workpackage, kontierung.text);
|
||||
eventLoop.exec();
|
||||
|
||||
if(eventLoop.success())
|
||||
m_kontierungTime = timeAdd(m_kontierungTime, timespan);
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not update Kontierung!"), tr("Could not update Kontierung:\n\n%0").arg(eventLoop.message()));
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
void MainWindow::validateEntries()
|
||||
{
|
||||
ui->actionToday->setEnabled(true);
|
||||
ui->actionRefresh->setEnabled(true);
|
||||
ui->dateEditDate->setReadOnly(false);
|
||||
ui->pushButtonStart->setText(tr("Start"));
|
||||
|
||||
if(!ui->treeViewBuchungen->isEnabled())
|
||||
return;
|
||||
|
||||
if(!ui->treeViewKontierungen->isEnabled())
|
||||
return;
|
||||
|
||||
auto buchungenIter = m_buchungenModel->constBegin();
|
||||
auto kontierungenIter = m_kontierungenModel->constBegin();
|
||||
|
||||
m_kontierungTime = QTime(0, 0);
|
||||
auto buchungTimespan = QTime(0, 0);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(buchungenIter == m_buchungenModel->constEnd() &&
|
||||
kontierungenIter == m_kontierungenModel->constEnd())
|
||||
{
|
||||
ui->timeEditTime->setEnabled(true);
|
||||
ui->comboBoxProjekt->setEnabled(true);
|
||||
ui->comboBoxSubprojekt->setEnabled(true);
|
||||
ui->comboBoxWorkpackage->setEnabled(true);
|
||||
ui->comboBoxText->setEnabled(true);
|
||||
ui->pushButtonStart->setEnabled(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(buchungenIter == m_buchungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Missing Buchung.")));
|
||||
return;
|
||||
}
|
||||
|
||||
auto startBuchung = *buchungenIter++;
|
||||
qDebug() << "startBuchung" << startBuchung.time;
|
||||
if(startBuchung.type != QStringLiteral("K"))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Expected Buchung for Kommen, instead got type %0\nBuchung ID: %1").arg(startBuchung.type).arg(startBuchung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
m_lastKontierungStart = startBuchung.time;
|
||||
|
||||
if(kontierungenIter == m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Missing Kontierung.")));
|
||||
return;
|
||||
}
|
||||
|
||||
auto kontierung = *kontierungenIter++;
|
||||
if(kontierung.time != m_kontierungTime)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Expected time %0 but got %1 Kontierung.\nKontierung ID: %2")
|
||||
.arg(m_kontierungTime.toString("HH:mm:ss"))
|
||||
.arg(kontierung.time.toString("HH:mm:ss"))
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if(kontierung.timespan == QTime(0, 0))
|
||||
{
|
||||
if(buchungenIter != m_buchungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("There is another Buchung after an unfinished Kontierung.\nBuchung ID: %0\nKontierung ID: %1")
|
||||
.arg(buchungenIter->id)
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if(kontierungenIter != m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("There is another Kontierung after an unfinished Kontierung.\nKontierung ID: %0\nKontierung ID: %1")
|
||||
.arg(kontierungenIter->id)
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pushButtonStart->setText(tr("Switch"));
|
||||
ui->pushButtonEnd->setEnabled(true);
|
||||
goto after;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kontierungTime = timeAdd(m_kontierungTime, kontierung.timespan);
|
||||
m_lastKontierungStart = timeAdd(m_lastKontierungStart, kontierung.timespan);
|
||||
|
||||
if(buchungenIter == m_buchungenModel->constEnd())
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if(kontierungenIter == m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("The last Kontierung is finished without Gehen-Buchung\nKontierung ID: %0")
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
kontierung = *kontierungenIter++;
|
||||
if(kontierung.time != m_kontierungTime)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Expected time %0 but got %1 Kontierung.\nKontierung ID: %2")
|
||||
.arg(m_kontierungTime.toString("HH:mm:ss"))
|
||||
.arg(kontierung.time.toString("HH:mm:ss"))
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if(kontierung.timespan == QTime(0, 0))
|
||||
{
|
||||
if(kontierungenIter != m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("There is another Kontierung after an unfinished Kontierung.\nKontierung ID: %0\nKontierung ID: %1")
|
||||
.arg(kontierung.id)
|
||||
.arg(kontierungenIter->id)));
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pushButtonStart->setText(tr("Switch"));
|
||||
ui->pushButtonEnd->setEnabled(true);
|
||||
goto after;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kontierungTime = timeAdd(m_kontierungTime, kontierung.timespan);
|
||||
m_lastKontierungStart = timeAdd(m_lastKontierungStart, kontierung.timespan);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto endBuchung = *buchungenIter++;
|
||||
qDebug() << "endBuchung" << endBuchung.time;
|
||||
if(endBuchung.type != QStringLiteral("G"))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Expected Buchung for Gehen, instead got type %0\nBuchung ID: %1").arg(endBuchung.type).arg(endBuchung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
buchungTimespan = timeAdd(buchungTimespan, timeBetween(startBuchung.time, endBuchung.time));
|
||||
qDebug() << "buchungTimespan" << buchungTimespan;
|
||||
|
||||
while(m_kontierungTime < buchungTimespan)
|
||||
{
|
||||
if(kontierungenIter == m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Missing Kontierung! Time not filled: %0 - %1")
|
||||
.arg(m_kontierungTime.toString("HH:mm:ss"))
|
||||
.arg(buchungTimespan.toString("HH:mm:ss"))));
|
||||
return;
|
||||
}
|
||||
|
||||
kontierung = *kontierungenIter++;
|
||||
if(kontierung.time != m_kontierungTime)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("Expected time %0 but got %1 Kontierung.\nKontierung ID: %2")
|
||||
.arg(m_kontierungTime.toString("HH:mm:ss"))
|
||||
.arg(kontierung.time.toString("HH:mm:ss"))
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if(kontierung.timespan == QTime(0, 0))
|
||||
{
|
||||
if(buchungenIter != m_buchungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("There is another Buchung after an unfinished Kontierung.\nBuchung ID: %0\nKontierung ID: %1")
|
||||
.arg(buchungenIter->id)
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
if(kontierungenIter != m_kontierungenModel->constEnd())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Illegal state!"), tr("Your Buchungen and Kontierungen for this day are in an invalid state:\n\n%0")
|
||||
.arg(tr("There is another Kontierung after an unfinished Kontierung.\nKontierung ID: %0\nKontierung ID: %1")
|
||||
.arg(kontierungenIter->id)
|
||||
.arg(kontierung.id)));
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pushButtonStart->setText(tr("Switch"));
|
||||
ui->pushButtonEnd->setEnabled(true);
|
||||
goto after;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kontierungTime = timeAdd(m_kontierungTime, kontierung.timespan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
after:
|
||||
|
||||
qDebug() << "m_kontierTime" << m_kontierungTime;
|
||||
|
||||
ui->timeEditTime->setEnabled(true);
|
||||
ui->comboBoxProjekt->setEnabled(true);
|
||||
ui->comboBoxSubprojekt->setEnabled(true);
|
||||
ui->comboBoxWorkpackage->setEnabled(true);
|
||||
ui->comboBoxText->setEnabled(true);
|
||||
ui->pushButtonStart->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::updateComboboxes()
|
||||
{
|
||||
ui->comboBoxProjekt->clear();
|
||||
|
||||
{
|
||||
auto preferedProjekte = m_settings.value("projekte", QStringList()).toStringList();
|
||||
|
||||
for(const auto &preferedProjekt : preferedProjekte)
|
||||
{
|
||||
for(const auto &projekt : m_projekte)
|
||||
{
|
||||
if(preferedProjekt == projekt.value)
|
||||
ui->comboBoxProjekt->addItem(projekt.label % " (" % projekt.value % ')', projekt.value);
|
||||
}
|
||||
}
|
||||
|
||||
if(preferedProjekte.count())
|
||||
{
|
||||
ui->comboBoxProjekt->addItem(QStringLiteral("--------------"));
|
||||
|
||||
auto model = qobject_cast<const QStandardItemModel*>(ui->comboBoxProjekt->model());
|
||||
auto item = model->item(ui->comboBoxProjekt->count() - 1);
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
|
||||
}
|
||||
|
||||
for(const auto &projekt : m_projekte)
|
||||
{
|
||||
if(!preferedProjekte.contains(projekt.value))
|
||||
ui->comboBoxProjekt->addItem(projekt.label % " (" % projekt.value % ')', projekt.value);
|
||||
}
|
||||
}
|
||||
|
||||
ui->comboBoxSubprojekt->clear();
|
||||
|
||||
{
|
||||
auto subprojekte = m_settings.value("subprojekte", QStringList()).toStringList();
|
||||
for(const auto &subprojekt : subprojekte)
|
||||
ui->comboBoxSubprojekt->addItem(subprojekt);
|
||||
if(subprojekte.count())
|
||||
ui->comboBoxSubprojekt->setCurrentText(QString());
|
||||
}
|
||||
|
||||
ui->comboBoxWorkpackage->clear();
|
||||
|
||||
{
|
||||
auto workpackages = m_settings.value("workpackages", QStringList()).toStringList();
|
||||
for(const auto &workpackage : workpackages)
|
||||
ui->comboBoxWorkpackage->addItem(workpackage);
|
||||
if(workpackages.count())
|
||||
ui->comboBoxWorkpackage->setCurrentText(QString());
|
||||
}
|
||||
|
||||
ui->comboBoxText->clear();
|
||||
|
||||
{
|
||||
auto texte = m_settings.value("texte", QStringList()).toStringList();
|
||||
for(const auto &text : texte)
|
||||
ui->comboBoxText->addItem(text);
|
||||
if(texte.count())
|
||||
ui->comboBoxText->setCurrentText(QString());
|
||||
}
|
||||
}
|
||||
|
||||
int MainWindow::timeToSeconds(const QTime &time)
|
||||
{
|
||||
return QTime(0, 0).secsTo(time);
|
||||
}
|
||||
|
||||
QTime MainWindow::timeBetween(const QTime &l, const QTime &r)
|
||||
{
|
||||
Q_ASSERT(l <= r);
|
||||
return QTime(0, 0).addSecs(l.secsTo(r));
|
||||
}
|
||||
|
||||
QTime MainWindow::timeAdd(const QTime &l, const QTime &r)
|
||||
{
|
||||
Q_ASSERT(timeToSeconds(l) + timeToSeconds(r) < 86400);
|
||||
return l.addSecs(QTime(0, 0).secsTo(r));
|
||||
}
|
||||
|
||||
QTime MainWindow::timeNormalise(const QTime &time)
|
||||
{
|
||||
return time.addSecs(-time.second());
|
||||
}
|
57
mainwindow.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
namespace Ui { class MainWindow; }
|
||||
class BuchungenModel;
|
||||
class KontierungenModel;
|
||||
|
||||
class QSettings;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QSettings &settings, Zeiterfassung &erfassung, const Zeiterfassung::UserInfo &userInfo, QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private Q_SLOTS:
|
||||
void refresh();
|
||||
void getProjekteFinished(bool success, const QString &message, const QVector<Zeiterfassung::Projekt> &projekte);
|
||||
void refreshBuchungenFinished(bool success, const QString &message);
|
||||
void refreshKontierungenFinished(bool success, const QString &message);
|
||||
void contextMenuBuchung(const QPoint &pos);
|
||||
void contextMenuKontierung(const QPoint &pos);
|
||||
void pushButtonPrevPressed();
|
||||
void pushButtonNextPressed();
|
||||
void pushButtonStartPressed();
|
||||
void pushButtonEndPressed();
|
||||
|
||||
private:
|
||||
void validateEntries();
|
||||
void updateComboboxes();
|
||||
|
||||
static int timeToSeconds(const QTime &time);
|
||||
static QTime timeBetween(const QTime &l, const QTime &r);
|
||||
static QTime timeAdd(const QTime &l, const QTime &r);
|
||||
static QTime timeNormalise(const QTime &time);
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
QSettings &m_settings;
|
||||
Zeiterfassung &m_erfassung;
|
||||
const Zeiterfassung::UserInfo &m_userInfo;
|
||||
QVector<Zeiterfassung::Projekt> m_projekte;
|
||||
|
||||
BuchungenModel *m_buchungenModel;
|
||||
KontierungenModel *m_kontierungenModel;
|
||||
|
||||
bool m_flag;
|
||||
QTime m_kontierungTime;
|
||||
QTime m_lastKontierungStart;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
322
mainwindow.ui
Normal file
@@ -0,0 +1,322 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1242</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDateEdit" name="dateEditDate">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonPrev">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/zeiterfassung/images/previous.png</normaloff>:/zeiterfassung/images/previous.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonNext">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/zeiterfassung/images/next.png</normaloff>:/zeiterfassung/images/next.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTimeEdit" name="timeEditTime">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxProjekt">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxSubprojekt">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxWorkpackage">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxText">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonStart">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonEnd">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>End</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="groupBoxBuchungen">
|
||||
<property name="title">
|
||||
<string>Buchungen</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeViewBuchungen">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBoxKontierungen">
|
||||
<property name="title">
|
||||
<string>Kontierungen</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeViewKontierungen">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1242</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionQuit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_About">
|
||||
<property name="title">
|
||||
<string>&About</string>
|
||||
</property>
|
||||
<addaction name="actionAboutMe"/>
|
||||
<addaction name="actionAboutzeiterfassung"/>
|
||||
<addaction name="actionAboutQt"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_View">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="actionToday"/>
|
||||
<addaction name="actionRefresh"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menu_View"/>
|
||||
<addaction name="menu_About"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionQuit">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/zeiterfassung/images/quit.png</normaloff>:/zeiterfassung/images/quit.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Quit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAboutMe">
|
||||
<property name="text">
|
||||
<string>About &Me</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAboutzeiterfassung">
|
||||
<property name="text">
|
||||
<string>About &zeiterfassung</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAboutQt">
|
||||
<property name="text">
|
||||
<string>About &Qt</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToday">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/zeiterfassung/images/today.png</normaloff>:/zeiterfassung/images/today.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Today</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRefresh">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/zeiterfassung/images/refresh.png</normaloff>:/zeiterfassung/images/refresh.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Refresh</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionQuit</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>458</x>
|
||||
<y>296</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
106
models/buchungenmodel.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "buchungenmodel.h"
|
||||
|
||||
BuchungenModel::BuchungenModel(Zeiterfassung &erfassung, QObject *parent) :
|
||||
QAbstractListModel(parent),
|
||||
m_erfassung(erfassung)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int BuchungenModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return m_buchungen.count();
|
||||
}
|
||||
|
||||
int BuchungenModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
QVariant BuchungenModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Q_ASSERT(index.row() < m_buchungen.count());
|
||||
const auto &buchung = m_buchungen.at(index.row());
|
||||
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case 0: return buchung.id;
|
||||
case 1: return buchung.time;
|
||||
case 2: return buchung.timespan;
|
||||
case 3: return buchung.type;
|
||||
case 4: return buchung.text;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant BuchungenModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch(section)
|
||||
{
|
||||
case 0: return tr("ID");
|
||||
case 1: return tr("Time");
|
||||
case 2: return tr("Timespan");
|
||||
case 3: return tr("Type");
|
||||
case 4: return tr("Text");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Zeiterfassung::Buchung BuchungenModel::getBuchung(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return Zeiterfassung::Buchung();
|
||||
|
||||
Q_ASSERT(index.row() <= m_buchungen.count());
|
||||
return m_buchungen.at(index.row());
|
||||
}
|
||||
|
||||
bool BuchungenModel::refresh(int userId, const QDate &from, const QDate &to)
|
||||
{
|
||||
if(!m_erfassung.doGetBuchungen(userId, from, to))
|
||||
return false;
|
||||
|
||||
beginResetModel();
|
||||
m_buchungen.clear();
|
||||
endResetModel();
|
||||
|
||||
connect(&m_erfassung, &Zeiterfassung::getBuchungenFinished,
|
||||
this, &BuchungenModel::getBuchungenFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuchungenModel::getBuchungenFinished(bool success, const QString &message, const QVector<Zeiterfassung::Buchung> &buchungen)
|
||||
{
|
||||
disconnect(&m_erfassung, &Zeiterfassung::getBuchungenFinished,
|
||||
this, &BuchungenModel::getBuchungenFinished);
|
||||
|
||||
if(success)
|
||||
{
|
||||
beginResetModel();
|
||||
m_buchungen = buchungen;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
Q_EMIT refreshFinished(success, message);
|
||||
}
|
68
models/buchungenmodel.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef BUCHUNGENMODEL_H
|
||||
#define BUCHUNGENMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QVector>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
class BuchungenModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuchungenModel(Zeiterfassung &erfassung, QObject *parent = nullptr);
|
||||
|
||||
// QAbstractItemModel interface
|
||||
int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
|
||||
|
||||
Zeiterfassung::Buchung getBuchung(const QModelIndex &index) const;
|
||||
|
||||
bool refresh(int userId, const QDate &from, const QDate &to);
|
||||
|
||||
typedef QVector<Zeiterfassung::Buchung>::iterator iterator;
|
||||
typedef QVector<Zeiterfassung::Buchung>::const_iterator const_iterator;
|
||||
typedef QVector<Zeiterfassung::Buchung>::reverse_iterator reverse_iterator;
|
||||
typedef QVector<Zeiterfassung::Buchung>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
#if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC)
|
||||
//inline iterator begin() { return m_buchungen.begin(); }
|
||||
inline const_iterator begin() const Q_DECL_NOTHROW { return m_buchungen.begin(); }
|
||||
inline const_iterator cbegin() const Q_DECL_NOTHROW { return m_buchungen.cbegin(); }
|
||||
inline const_iterator constBegin() const Q_DECL_NOTHROW { return m_buchungen.constBegin(); }
|
||||
//inline iterator end() { return m_buchungen.end(); }
|
||||
inline const_iterator end() const Q_DECL_NOTHROW { return m_buchungen.end(); }
|
||||
inline const_iterator cend() const Q_DECL_NOTHROW { return m_buchungen.cend(); }
|
||||
inline const_iterator constEnd() const Q_DECL_NOTHROW { return m_buchungen.constEnd(); }
|
||||
#else
|
||||
//inline iterator begin(iterator = iterator()) { return m_buchungen.begin(); }
|
||||
inline const_iterator begin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_buchungen.begin(); }
|
||||
inline const_iterator cbegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
|
||||
inline const_iterator constBegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_buchungen.constBegin(); }
|
||||
//inline iterator end(iterator = iterator()) { return m_buchungen.end(); }
|
||||
inline const_iterator end(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_buchungen.end(); }
|
||||
inline const_iterator cend(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_buchungen.cend(); }
|
||||
inline const_iterator constEnd(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_buchungen.constEnd(); }
|
||||
#endif
|
||||
//reverse_iterator rbegin() { return m_buchungen.rbegin(); }
|
||||
//reverse_iterator rend() { return m_buchungen.rbegin(); }
|
||||
const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return m_buchungen.rbegin(); }
|
||||
const_reverse_iterator rend() const Q_DECL_NOTHROW { return m_buchungen.rend(); }
|
||||
const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return m_buchungen.crbegin(); }
|
||||
const_reverse_iterator crend() const Q_DECL_NOTHROW { return m_buchungen.crend(); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void refreshFinished(bool success, const QString &message);
|
||||
|
||||
private Q_SLOTS:
|
||||
void getBuchungenFinished(bool success, const QString &message, const QVector<Zeiterfassung::Buchung> &buchungen);
|
||||
|
||||
private:
|
||||
Zeiterfassung &m_erfassung;
|
||||
QVector<Zeiterfassung::Buchung> m_buchungen;
|
||||
};
|
||||
|
||||
#endif // BUCHUNGENMODEL_H
|
110
models/kontierungenmodel.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "kontierungenmodel.h"
|
||||
|
||||
KontierungenModel::KontierungenModel(Zeiterfassung &erfassung, QObject *parent) :
|
||||
QAbstractListModel(parent),
|
||||
m_erfassung(erfassung)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int KontierungenModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return m_kontierungen.count();
|
||||
}
|
||||
|
||||
int KontierungenModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return 7;
|
||||
}
|
||||
|
||||
QVariant KontierungenModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Q_ASSERT(index.row() < m_kontierungen.count());
|
||||
const auto &kontierung = m_kontierungen.at(index.row());
|
||||
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case 0: return kontierung.id;
|
||||
case 1: return kontierung.time;
|
||||
case 2: return kontierung.timespan;
|
||||
case 3: return kontierung.projekt;
|
||||
case 4: return kontierung.subprojekt;
|
||||
case 5: return kontierung.workpackage;
|
||||
case 6: return kontierung.text;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant KontierungenModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch(section)
|
||||
{
|
||||
case 0: return tr("ID");
|
||||
case 1: return tr("Time");
|
||||
case 2: return tr("Timespan");
|
||||
case 3: return tr("Projekt");
|
||||
case 4: return tr("Subprojekt");
|
||||
case 5: return tr("Workpackage");
|
||||
case 6: return tr("Text");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Zeiterfassung::Kontierung KontierungenModel::getKontierung(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return Zeiterfassung::Kontierung();
|
||||
|
||||
Q_ASSERT(index.row() <= m_kontierungen.count());
|
||||
return m_kontierungen.at(index.row());
|
||||
}
|
||||
|
||||
bool KontierungenModel::refresh(int userId, const QDate &from, const QDate &to)
|
||||
{
|
||||
if(!m_erfassung.doGetKontierungen(userId, from, to))
|
||||
return false;
|
||||
|
||||
beginResetModel();
|
||||
m_kontierungen.clear();
|
||||
endResetModel();
|
||||
|
||||
connect(&m_erfassung, &Zeiterfassung::getKontierungenFinished,
|
||||
this, &KontierungenModel::getKontierungenFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KontierungenModel::getKontierungenFinished(bool success, const QString &message, const QVector<Zeiterfassung::Kontierung> &kontierungen)
|
||||
{
|
||||
disconnect(&m_erfassung, &Zeiterfassung::getKontierungenFinished,
|
||||
this, &KontierungenModel::getKontierungenFinished);
|
||||
|
||||
if(success)
|
||||
{
|
||||
beginResetModel();
|
||||
m_kontierungen = kontierungen;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
Q_EMIT refreshFinished(success, message);
|
||||
}
|
68
models/kontierungenmodel.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef KONTIERUNGENMODEL_H
|
||||
#define KONTIERUNGENMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QVector>
|
||||
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
class KontierungenModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit KontierungenModel(Zeiterfassung &erfassung, QObject *parent = nullptr);
|
||||
|
||||
// QAbstractItemModel interface
|
||||
int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
|
||||
|
||||
Zeiterfassung::Kontierung getKontierung(const QModelIndex &index) const;
|
||||
|
||||
bool refresh(int userId, const QDate &from, const QDate &to);
|
||||
|
||||
typedef QVector<Zeiterfassung::Kontierung>::iterator iterator;
|
||||
typedef QVector<Zeiterfassung::Kontierung>::const_iterator const_iterator;
|
||||
typedef QVector<Zeiterfassung::Kontierung>::reverse_iterator reverse_iterator;
|
||||
typedef QVector<Zeiterfassung::Kontierung>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
#if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC)
|
||||
//inline iterator begin() { return m_kontierungen.begin(); }
|
||||
inline const_iterator begin() const Q_DECL_NOTHROW { return m_kontierungen.begin(); }
|
||||
inline const_iterator cbegin() const Q_DECL_NOTHROW { return m_kontierungen.cbegin(); }
|
||||
inline const_iterator constBegin() const Q_DECL_NOTHROW { return m_kontierungen.constBegin(); }
|
||||
//inline iterator end() { return m_kontierungen.end(); }
|
||||
inline const_iterator end() const Q_DECL_NOTHROW { return m_kontierungen.end(); }
|
||||
inline const_iterator cend() const Q_DECL_NOTHROW { return m_kontierungen.cend(); }
|
||||
inline const_iterator constEnd() const Q_DECL_NOTHROW { return m_kontierungen.constEnd(); }
|
||||
#else
|
||||
//inline iterator begin(iterator = iterator()) { return m_kontierungen.begin(); }
|
||||
inline const_iterator begin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_kontierungen.begin(); }
|
||||
inline const_iterator cbegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
|
||||
inline const_iterator constBegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_kontierungen.constBegin(); }
|
||||
//inline iterator end(iterator = iterator()) { return m_kontierungen.end(); }
|
||||
inline const_iterator end(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_kontierungen.end(); }
|
||||
inline const_iterator cend(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_kontierungen.cend(); }
|
||||
inline const_iterator constEnd(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return m_kontierungen.constEnd(); }
|
||||
#endif
|
||||
//reverse_iterator rbegin() { return m_kontierungen.rbegin(); }
|
||||
//reverse_iterator rend() { return m_kontierungen.rbegin(); }
|
||||
const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return m_kontierungen.rbegin(); }
|
||||
const_reverse_iterator rend() const Q_DECL_NOTHROW { return m_kontierungen.rend(); }
|
||||
const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return m_kontierungen.crbegin(); }
|
||||
const_reverse_iterator crend() const Q_DECL_NOTHROW { return m_kontierungen.crend(); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void refreshFinished(bool success, const QString &message);
|
||||
|
||||
private Q_SLOTS:
|
||||
void getKontierungenFinished(bool success, const QString &message, const QVector<Zeiterfassung::Kontierung> &kontierungen);
|
||||
|
||||
private:
|
||||
Zeiterfassung &m_erfassung;
|
||||
QVector<Zeiterfassung::Kontierung> m_kontierungen;
|
||||
};
|
||||
|
||||
#endif // KONTIERUNGENMODEL_H
|
11
resources.qrc
Normal file
@@ -0,0 +1,11 @@
|
||||
<RCC>
|
||||
<qresource prefix="/zeiterfassung">
|
||||
<file>images/splash.png</file>
|
||||
<file>images/authentication.png</file>
|
||||
<file>images/next.png</file>
|
||||
<file>images/previous.png</file>
|
||||
<file>images/quit.png</file>
|
||||
<file>images/refresh.png</file>
|
||||
<file>images/today.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
8
zeiterfassung.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
[General]
|
||||
password=HAHA
|
||||
projekte=0000001142, 0000010001, SONSTIGES
|
||||
subprojekte=
|
||||
texte=
|
||||
url=http://localhost:8080/evoApps/
|
||||
username=danielb
|
||||
workpackages=[D.1315], [M.0200]
|
817
zeiterfassung.cpp
Normal file
@@ -0,0 +1,817 @@
|
||||
#include "zeiterfassung.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonParseError>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonValue>
|
||||
#include <QStringBuilder>
|
||||
|
||||
QString QJsonValue::toString() const{ return toString(QString()); }
|
||||
|
||||
Zeiterfassung::Zeiterfassung(const QString &url, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_url(url),
|
||||
m_manager(new QNetworkAccessManager(this)),
|
||||
m_replies { Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR,
|
||||
Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR }
|
||||
{
|
||||
}
|
||||
|
||||
const QString &Zeiterfassung::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
void Zeiterfassung::setUrl(const QString &url)
|
||||
{
|
||||
if(m_url != url)
|
||||
Q_EMIT urlChanged(m_url = url);
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doLoginPage()
|
||||
{
|
||||
if(m_replies.login)
|
||||
{
|
||||
qWarning() << "another loginPage already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(m_url % "pages/login.jsp"));
|
||||
|
||||
m_replies.loginPage = m_manager->get(request);
|
||||
connect(m_replies.loginPage, &QNetworkReply::finished, this, &Zeiterfassung::loginPageRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doLogin(const QString &username, const QString &password)
|
||||
{
|
||||
if(m_replies.login)
|
||||
{
|
||||
qWarning() << "another login already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(m_url % "pages/j_spring_security_check"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/x-www-form-urlencoded"));
|
||||
request.setMaximumRedirectsAllowed(0);
|
||||
|
||||
m_replies.login = m_manager->post(request, QStringLiteral("j_username=%0&j_password=%1&login=Anmelden").arg(username).arg(password).toUtf8());
|
||||
connect(m_replies.login, &QNetworkReply::finished, this, &Zeiterfassung::loginRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doUserInfo()
|
||||
{
|
||||
if(m_replies.userInfo)
|
||||
{
|
||||
qWarning() << "another userInfo already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(m_url % "json/evoAppsUserInfoDialogController/load-EvoAppsUserInfoTO"));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("home"));
|
||||
|
||||
m_replies.userInfo = m_manager->get(request);
|
||||
connect(m_replies.userInfo, &QNetworkReply::finished, this, &Zeiterfassung::userInfoRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doGetBuchungen(int userId, const QDate &start, const QDate &end)
|
||||
{
|
||||
if(m_replies.getBuchungen)
|
||||
{
|
||||
qWarning() << "another getBuchungen already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/bookings?start=%1&end=%2&pnrLst=%3")
|
||||
.arg(m_url)
|
||||
.arg(start.toString(QStringLiteral("yyyyMMdd")))
|
||||
.arg(end.toString(QStringLiteral("yyyyMMdd")))
|
||||
.arg(userId)));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
m_replies.getBuchungen = m_manager->get(request);
|
||||
connect(m_replies.getBuchungen, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::getBuchungenRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doCreateBuchung(int userId, const QDate &date, const QTime &time, const QTime ×pan, const QString &type, const QString &text)
|
||||
{
|
||||
if(m_replies.createBuchung)
|
||||
{
|
||||
qWarning() << "another createBuchung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(m_url % "json/booking"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("persNr")] = userId;
|
||||
obj[QStringLiteral("bookingDate")] = date.toString("yyyyMMdd").toInt();
|
||||
obj[QStringLiteral("bookingTime")] = time.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingTimespan")] = timespan.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingType")] = type;
|
||||
obj[QStringLiteral("hourCategory")] = QStringLiteral("");
|
||||
obj[QStringLiteral("empfEinh")] = QStringLiteral("");
|
||||
obj[QStringLiteral("bewEinh")] = QStringLiteral("");
|
||||
obj[QStringLiteral("text")] = text;
|
||||
|
||||
m_replies.createBuchung = m_manager->post(request, QJsonDocument(obj).toJson());
|
||||
connect(m_replies.createBuchung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::createBuchungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doUpdateBuchung(int buchungId, int userId, const QDate &date, const QTime &time, const QTime ×pan, const QString &type, const QString &text)
|
||||
{
|
||||
if(m_replies.updateBuchung)
|
||||
{
|
||||
qWarning() << "another updateBuchung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/booking/%1").arg(m_url).arg(buchungId)));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("bookingNr")] = buchungId;
|
||||
obj[QStringLiteral("persNr")] = userId;
|
||||
obj[QStringLiteral("bookingDate")] = date.toString("yyyyMMdd").toInt();
|
||||
obj[QStringLiteral("bookingTime")] = time.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingTimespan")] = timespan.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingType")] = type;
|
||||
obj[QStringLiteral("hourCategory")] = QStringLiteral("");
|
||||
obj[QStringLiteral("empfEinh")] = QStringLiteral("");
|
||||
obj[QStringLiteral("bewEinh")] = QStringLiteral("");
|
||||
obj[QStringLiteral("text")] = text;
|
||||
|
||||
m_replies.updateBuchung = m_manager->put(request, QJsonDocument(obj).toJson());
|
||||
connect(m_replies.updateBuchung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::updateBuchungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doDeleteBuchung(int buchungId)
|
||||
{
|
||||
if(m_replies.deleteBuchung)
|
||||
{
|
||||
qWarning() << "another deleteBuchung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/booking/%1?text=")
|
||||
.arg(m_url)
|
||||
.arg(buchungId)));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
m_replies.deleteBuchung = m_manager->deleteResource(request);
|
||||
connect(m_replies.deleteBuchung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::deleteBuchungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doGetKontierungen(int userId, const QDate &start, const QDate &end)
|
||||
{
|
||||
if(m_replies.getKontierungen)
|
||||
{
|
||||
qWarning() << "another getKontierungen already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/azebooking?start=%1&end=%2&pnrLst=%3")
|
||||
.arg(m_url)
|
||||
.arg(start.toString(QStringLiteral("yyyyMMdd")))
|
||||
.arg(end.toString(QStringLiteral("yyyyMMdd")))
|
||||
.arg(userId)));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
m_replies.getKontierungen = m_manager->get(request);
|
||||
connect(m_replies.getKontierungen, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::getKontierungenRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doCreateKontierung(int userId, const QDate &date, const QTime &time, const QTime ×pan, const QString &projekt, const QString &subprojekt, const QString &workpackage, const QString &text)
|
||||
{
|
||||
if(m_replies.createKontierung)
|
||||
{
|
||||
qWarning() << "another createKontierung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(m_url % "json/azebooking"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("bookingNr")] = QJsonValue::Null;
|
||||
obj[QStringLiteral("persNr")] = userId;
|
||||
obj[QStringLiteral("bookingDate")] = date.toString("yyyyMMdd").toInt();
|
||||
obj[QStringLiteral("bookingTime")] = time.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingTimespan")] = timespan.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("text")] = text;
|
||||
{
|
||||
QJsonArray koWertList;
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = projekt;
|
||||
koWertList << obj;
|
||||
}
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = subprojekt;
|
||||
koWertList << obj;
|
||||
}
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = workpackage;
|
||||
koWertList << obj;
|
||||
}
|
||||
obj[QStringLiteral("koWertList")] = koWertList;
|
||||
}
|
||||
|
||||
m_replies.createKontierung = m_manager->post(request, QJsonDocument(obj).toJson());
|
||||
connect(m_replies.createKontierung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::createKontierungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doUpdateKontierung(int kontierungId, int userId, const QDate &date, const QTime &time, const QTime ×pan, const QString &projekt, const QString &subprojekt, const QString &workpackage, const QString &text)
|
||||
{
|
||||
if(m_replies.updateKontierung)
|
||||
{
|
||||
qWarning() << "another updateKontierung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/azebooking/%1").arg(m_url).arg(kontierungId)));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("bookingNr")] = kontierungId;
|
||||
obj[QStringLiteral("persNr")] = userId;
|
||||
obj[QStringLiteral("bookingDate")] = date.toString("yyyyMMdd").toInt();
|
||||
obj[QStringLiteral("bookingTime")] = time.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingTimespan")] = timespan.toString("Hmmss").toInt();
|
||||
obj[QStringLiteral("bookingType")] = QJsonValue::Null;
|
||||
obj[QStringLiteral("hourCategory")] = QJsonValue::Null;
|
||||
obj[QStringLiteral("bewEinh")] = QJsonValue::Null;
|
||||
obj[QStringLiteral("empfEinh")] = QJsonValue::Null;
|
||||
obj[QStringLiteral("einstuf")] = 0;
|
||||
obj[QStringLiteral("text")] = text;
|
||||
{
|
||||
QJsonArray koWertList;
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = projekt;
|
||||
koWertList << obj;
|
||||
}
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = subprojekt;
|
||||
koWertList << obj;
|
||||
}
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("value")] = workpackage;
|
||||
koWertList << obj;
|
||||
}
|
||||
obj[QStringLiteral("koWertList")] = koWertList;
|
||||
}
|
||||
|
||||
m_replies.updateKontierung = m_manager->put(request, QJsonDocument(obj).toJson());
|
||||
connect(m_replies.updateKontierung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::updateKontierungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doDeleteKontierung(int kontierungId)
|
||||
{
|
||||
if(m_replies.deleteKontierung)
|
||||
{
|
||||
qWarning() << "another deleteKontierung already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/azebooking/%1")
|
||||
.arg(m_url)
|
||||
.arg(kontierungId)));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
m_replies.deleteKontierung = m_manager->deleteResource(request);
|
||||
connect(m_replies.deleteKontierung, &QNetworkReply::finished,
|
||||
this, &Zeiterfassung::deleteKontierungRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Zeiterfassung::doGetProjekte(int userId, QDate date)
|
||||
{
|
||||
if(m_replies.getProjekte)
|
||||
{
|
||||
qWarning() << "another getProjekte already processing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QNetworkRequest request(QUrl(QStringLiteral("%0json/combobox?persnr=%1&date=%2&dqkey=KOST&kowert0=&kowert1=&kowert2=&term=")
|
||||
.arg(m_url)
|
||||
.arg(userId)
|
||||
.arg(date.toString(QStringLiteral("yyyyMMdd")))));
|
||||
request.setRawHeader(QByteArrayLiteral("sisAppName"), QByteArrayLiteral("bookingCalendar"));
|
||||
|
||||
m_replies.getProjekte = m_manager->get(request);
|
||||
connect(m_replies.getProjekte, &QNetworkReply::finished, this, &Zeiterfassung::getProjekteRequestFinished);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Zeiterfassung::loginPageRequestFinished()
|
||||
{
|
||||
if(m_replies.loginPage->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT loginPageFinished(false, tr("Request error occured: %0").arg(m_replies.loginPage->error()));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!m_replies.loginPage->readAll().contains(QByteArrayLiteral("evoApps Anmeldung")))
|
||||
{
|
||||
Q_EMIT loginPageFinished(false, tr("Could not find necessary keywords in login page!"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
Q_EMIT loginPageFinished(true, QString());
|
||||
|
||||
end:
|
||||
m_replies.loginPage->deleteLater();
|
||||
m_replies.loginPage = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::loginRequestFinished()
|
||||
{
|
||||
if(m_replies.login->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT loginFinished(false, tr("Request error occured: %0").arg(m_replies.login->error()));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!m_replies.login->hasRawHeader(QByteArrayLiteral("Location")))
|
||||
{
|
||||
Q_EMIT loginFinished(false, tr("Request did not contain a Location header."));
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
auto location = m_replies.login->rawHeader(QByteArrayLiteral("Location"));
|
||||
|
||||
if(location == QByteArrayLiteral("/evoApps/pages/home.jsp"))
|
||||
{
|
||||
Q_EMIT loginFinished(true, QString());
|
||||
goto end;
|
||||
}
|
||||
else if(location == QByteArrayLiteral("/evoApps/pages/login.jsp?error=user"))
|
||||
{
|
||||
Q_EMIT loginFinished(false, tr("Authentication failure. Please check username and password."));
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT loginFinished(false, tr("An unknown authentication failure occured. Redirected to: %0").arg(QString(location)));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.login->deleteLater();
|
||||
m_replies.login = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::userInfoRequestFinished()
|
||||
{
|
||||
if(m_replies.userInfo->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT userInfoFinished(false, tr("Request error occured: %0").arg(m_replies.userInfo->error()), UserInfo());
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
auto document = QJsonDocument::fromJson(m_replies.userInfo->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT userInfoFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), UserInfo());
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT userInfoFinished(false, tr("JSON document is not an object!"), UserInfo());
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto rootObj = document.object();
|
||||
|
||||
if(!rootObj.contains(QStringLiteral("evoAppsUser")))
|
||||
{
|
||||
Q_EMIT userInfoFinished(false, tr("JSON does not contain evoAppsUser!"), UserInfo());
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto evoAppsUser = rootObj.value(QStringLiteral("evoAppsUser"));
|
||||
|
||||
if(!evoAppsUser.isObject())
|
||||
{
|
||||
Q_EMIT userInfoFinished(false, tr("evoAppsUser is not an object!"), UserInfo());
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto evoAppsUserObj = evoAppsUser.toObject();
|
||||
|
||||
Q_EMIT userInfoFinished(true, QString(), {
|
||||
evoAppsUserObj.value(QStringLiteral("persNr")).toInt(),
|
||||
evoAppsUserObj.value(QStringLiteral("email")).toString(),
|
||||
evoAppsUserObj.value(QStringLiteral("longUsername")).toString(),
|
||||
evoAppsUserObj.value(QStringLiteral("text")).toString(),
|
||||
evoAppsUserObj.value(QStringLiteral("username")).toString()
|
||||
});
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.userInfo->deleteLater();
|
||||
m_replies.userInfo = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::getBuchungenRequestFinished()
|
||||
{
|
||||
if(m_replies.getBuchungen->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT getBuchungenFinished(false, tr("Request error occured: %0").arg(m_replies.getBuchungen->error()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.getBuchungen->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT getBuchungenFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isArray())
|
||||
{
|
||||
Q_EMIT getBuchungenFinished(false, tr("JSON document is not an array!"), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto arr = document.array();
|
||||
QVector<Buchung> buchungen;
|
||||
|
||||
for(const auto &val : arr)
|
||||
{
|
||||
auto obj = val.toObject();
|
||||
|
||||
buchungen.append({
|
||||
obj.value(QStringLiteral("bookingNr")).toInt(),
|
||||
QDate::fromString(QString::number(obj.value(QStringLiteral("bookingDate")).toInt()), QStringLiteral("yyyyMMdd")),
|
||||
QTime::fromString(QString("%0").arg(obj.value(QStringLiteral("bookingTime")).toInt(), 6, 10, QChar('0')), QStringLiteral("HHmmss")),
|
||||
QTime::fromString(QString("%0").arg(obj.value(QStringLiteral("bookingTimespan")).toInt(), 6, 10, QChar('0')), QStringLiteral("HHmmss")),
|
||||
obj.value(QStringLiteral("bookingType")).toString(),
|
||||
obj.value(QStringLiteral("text")).toString()
|
||||
});
|
||||
}
|
||||
|
||||
Q_EMIT getBuchungenFinished(true, QString(), buchungen);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.getBuchungen->deleteLater();
|
||||
m_replies.getBuchungen = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::createBuchungRequestFinished()
|
||||
{
|
||||
if(m_replies.createBuchung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT createBuchungFinished(false, tr("Request error occured: %0").arg(m_replies.createBuchung->error()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.createBuchung->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT createBuchungFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT createBuchungFinished(false, tr("JSON document is not an object!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto obj = document.object();
|
||||
|
||||
if(!obj.contains(QStringLiteral("bookingNr")))
|
||||
{
|
||||
Q_EMIT createBuchungFinished(false, tr("JSON does not contain bookingNr!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto buchungId = obj.value(QStringLiteral("bookingNr")).toInt();
|
||||
|
||||
Q_EMIT createBuchungFinished(true, QString(), buchungId);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.createBuchung->deleteLater();
|
||||
m_replies.createBuchung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::updateBuchungRequestFinished()
|
||||
{
|
||||
if(m_replies.updateBuchung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT updateBuchungFinished(false, tr("Request error occured: %0").arg(m_replies.updateBuchung->error()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.updateBuchung->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT updateBuchungFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT updateBuchungFinished(false, tr("JSON document is not an object!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto obj = document.object();
|
||||
|
||||
if(!obj.contains(QStringLiteral("bookingNr")))
|
||||
{
|
||||
Q_EMIT updateBuchungFinished(false, tr("JSON does not contain bookingNr!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto buchungId = obj.value(QStringLiteral("bookingNr")).toInt();
|
||||
|
||||
Q_EMIT updateBuchungFinished(true, QString(), buchungId);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.updateBuchung->deleteLater();
|
||||
m_replies.updateBuchung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::deleteBuchungRequestFinished()
|
||||
{
|
||||
if(m_replies.deleteBuchung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT deleteBuchungFinished(false, tr("Request error occured: %0").arg(m_replies.deleteBuchung->error()));
|
||||
goto end;
|
||||
}
|
||||
|
||||
//should be empty, so nothing to check...
|
||||
Q_EMIT deleteBuchungFinished(true, QString());
|
||||
|
||||
end:
|
||||
m_replies.deleteBuchung->deleteLater();
|
||||
m_replies.deleteBuchung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::getKontierungenRequestFinished()
|
||||
{
|
||||
if(m_replies.getKontierungen->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT getKontierungenFinished(false, tr("Request error occured: %0").arg(m_replies.getKontierungen->error()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.getKontierungen->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT getKontierungenFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isArray())
|
||||
{
|
||||
Q_EMIT getKontierungenFinished(false, tr("JSON document is not an array!"), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto arr = document.array();
|
||||
QVector<Kontierung> kontierungen;
|
||||
|
||||
for(const auto &val : arr)
|
||||
{
|
||||
auto obj = val.toObject();
|
||||
|
||||
auto koWertList = obj.value(QStringLiteral("koWertList")).toArray();
|
||||
|
||||
kontierungen.append({
|
||||
obj.value(QStringLiteral("bookingNr")).toInt(),
|
||||
QDate::fromString(QString::number(obj.value(QStringLiteral("bookingDate")).toInt()), QStringLiteral("yyyyMMdd")),
|
||||
QTime::fromString(QString("%0").arg(obj.value(QStringLiteral("bookingTime")).toInt(), 6, 10, QChar('0')), QStringLiteral("HHmmss")),
|
||||
QTime::fromString(QString("%0").arg(obj.value(QStringLiteral("bookingTimespan")).toInt(), 6, 10, QChar('0')), QStringLiteral("HHmmss")),
|
||||
obj.value(QStringLiteral("text")).toString(),
|
||||
koWertList.at(0).toObject().value(QStringLiteral("value")).toString(),
|
||||
koWertList.at(1).toObject().value(QStringLiteral("value")).toString(),
|
||||
koWertList.at(2).toObject().value(QStringLiteral("value")).toString()
|
||||
});
|
||||
}
|
||||
|
||||
Q_EMIT getKontierungenFinished(true, QString(), kontierungen);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.getKontierungen->deleteLater();
|
||||
m_replies.getKontierungen = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::createKontierungRequestFinished()
|
||||
{
|
||||
if(m_replies.createKontierung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT createKontierungFinished(false, tr("Request error occured: %0").arg(m_replies.createKontierung->error()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.createKontierung->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT createKontierungFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT createKontierungFinished(false, tr("JSON document is not an object!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto obj = document.object();
|
||||
|
||||
if(!obj.contains(QStringLiteral("bookingNr")))
|
||||
{
|
||||
Q_EMIT createKontierungFinished(false, tr("JSON does not contain bookingNr!"), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto kontierungId = obj.value(QStringLiteral("bookingNr")).toInt();
|
||||
|
||||
Q_EMIT createKontierungFinished(true, QString(), kontierungId);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.createKontierung->deleteLater();
|
||||
m_replies.createKontierung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::updateKontierungRequestFinished()
|
||||
{
|
||||
if(m_replies.updateKontierung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT updateKontierungFinished(false, tr("Request error occured: %0").arg(m_replies.updateKontierung->error()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.updateKontierung->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT updateKontierungFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), -1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT updateKontierungFinished(false, tr("JSON document is not an object!"), 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto obj = document.object();
|
||||
|
||||
if(!obj.contains(QStringLiteral("bookingNr")))
|
||||
{
|
||||
Q_EMIT updateKontierungFinished(false, tr("JSON does not contain bookingNr!"), 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto kontierungId = obj.value(QStringLiteral("bookingNr")).toInt();
|
||||
|
||||
Q_EMIT updateKontierungFinished(true, QString(), kontierungId);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.updateKontierung->deleteLater();
|
||||
m_replies.updateKontierung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::deleteKontierungRequestFinished()
|
||||
{
|
||||
if(m_replies.deleteKontierung->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT deleteKontierungFinished(false, tr("Request error occured: %0").arg(m_replies.deleteKontierung->error()));
|
||||
goto end;
|
||||
}
|
||||
|
||||
//only contains deleted id, so nothing to check here
|
||||
Q_EMIT deleteKontierungFinished(true, QString());
|
||||
|
||||
end:
|
||||
m_replies.deleteKontierung->deleteLater();
|
||||
m_replies.deleteKontierung = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void Zeiterfassung::getProjekteRequestFinished()
|
||||
{
|
||||
if(m_replies.getProjekte->error() != QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT getProjekteFinished(false, tr("Request error occured: %0").arg(m_replies.getProjekte->error()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
QJsonParseError error;
|
||||
QJsonDocument document = QJsonDocument::fromJson(m_replies.getProjekte->readAll(), &error);
|
||||
if(error.error != QJsonParseError::NoError)
|
||||
{
|
||||
Q_EMIT getProjekteFinished(false, tr("Parsing JSON failed: %0").arg(error.errorString()), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!document.isObject())
|
||||
{
|
||||
Q_EMIT getProjekteFinished(false, tr("JSON document is not an object!"), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto rootObj = document.object();
|
||||
|
||||
if(!rootObj.contains(QStringLiteral("elements")))
|
||||
{
|
||||
Q_EMIT getProjekteFinished(false, tr("JSON does not contain elements!"), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto elements = rootObj.value(QStringLiteral("elements"));
|
||||
|
||||
if(!elements.isArray())
|
||||
{
|
||||
Q_EMIT getProjekteFinished(false, tr("elements is not an array!"), {});
|
||||
goto end;
|
||||
}
|
||||
|
||||
auto elementsArr = elements.toArray();
|
||||
QVector<Projekt> projekte;
|
||||
|
||||
for(const auto &val : elementsArr)
|
||||
{
|
||||
auto obj = val.toObject();
|
||||
|
||||
projekte.append({
|
||||
obj.value(QStringLiteral("label")).toString(),
|
||||
obj.value(QStringLiteral("value")).toString()
|
||||
});
|
||||
}
|
||||
|
||||
Q_EMIT getProjekteFinished(true, QString(), projekte);
|
||||
}
|
||||
|
||||
end:
|
||||
m_replies.getProjekte->deleteLater();
|
||||
m_replies.getProjekte = Q_NULLPTR;
|
||||
}
|
142
zeiterfassung.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#ifndef ZEITERFASSUNG_H
|
||||
#define ZEITERFASSUNG_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDate>
|
||||
#include <QTime>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
class Zeiterfassung : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
|
||||
|
||||
public:
|
||||
explicit Zeiterfassung(const QString &url, QObject *parent = 0);
|
||||
|
||||
const QString &url() const;
|
||||
void setUrl(const QString &url);
|
||||
|
||||
struct UserInfo
|
||||
{
|
||||
int userId;
|
||||
QString email;
|
||||
QString longUsername;
|
||||
QString text;
|
||||
QString username;
|
||||
};
|
||||
|
||||
struct Buchung
|
||||
{
|
||||
int id;
|
||||
QDate date;
|
||||
QTime time;
|
||||
QTime timespan;
|
||||
QString type;
|
||||
QString text;
|
||||
};
|
||||
|
||||
struct Kontierung
|
||||
{
|
||||
int id;
|
||||
QDate date;
|
||||
QTime time;
|
||||
QTime timespan;
|
||||
QString text;
|
||||
QString projekt;
|
||||
QString subprojekt;
|
||||
QString workpackage;
|
||||
};
|
||||
|
||||
struct Projekt
|
||||
{
|
||||
QString label;
|
||||
QString value;
|
||||
};
|
||||
|
||||
public Q_SLOTS:
|
||||
bool doLoginPage();
|
||||
bool doLogin(const QString &username, const QString &password);
|
||||
bool doUserInfo();
|
||||
|
||||
bool doGetBuchungen(int userId, const QDate &start, const QDate &end);
|
||||
bool doCreateBuchung(int userId, const QDate &date, const QTime &time, const QTime ×pan,
|
||||
const QString &type, const QString &text);
|
||||
bool doUpdateBuchung(int buchungId, int userId, const QDate &date, const QTime &time,
|
||||
const QTime ×pan, const QString &type, const QString &text);
|
||||
bool doDeleteBuchung(int buchungId);
|
||||
|
||||
bool doGetKontierungen(int userId, const QDate &start, const QDate &end);
|
||||
bool doCreateKontierung(int userId, const QDate &date, const QTime &time, const QTime ×pan,
|
||||
const QString &projekt, const QString &subprojekt, const QString &workpackage,
|
||||
const QString &text);
|
||||
bool doUpdateKontierung(int kontierungId, int userId, const QDate &date, const QTime &time,
|
||||
const QTime ×pan, const QString &projekt, const QString &subprojekt,
|
||||
const QString &workpackage, const QString &text);
|
||||
bool doDeleteKontierung(int kontierungId);
|
||||
|
||||
bool doGetProjekte(int userId, QDate date = QDate::currentDate());
|
||||
|
||||
Q_SIGNALS:
|
||||
void urlChanged(const QString &url);
|
||||
|
||||
void loginPageFinished(bool success, const QString &message);
|
||||
void loginFinished(bool success, const QString &message);
|
||||
void userInfoFinished(bool success, const QString &message, const UserInfo &userInfo);
|
||||
|
||||
void getBuchungenFinished(bool success, const QString &message, const QVector<Buchung> &buchungen);
|
||||
void createBuchungFinished(bool success, const QString &message, int buchungId);
|
||||
void updateBuchungFinished(bool success, const QString &message, int buchungId);
|
||||
void deleteBuchungFinished(bool success, const QString &message);
|
||||
|
||||
void getKontierungenFinished(bool success, const QString &message, const QVector<Kontierung> &kontierungen);
|
||||
void createKontierungFinished(bool success, const QString &message, int buchungId);
|
||||
void updateKontierungFinished(bool success, const QString &message, int buchungId);
|
||||
void deleteKontierungFinished(bool success, const QString &message);
|
||||
|
||||
void getProjekteFinished(bool success, const QString &message, const QVector<Projekt> &projekte);
|
||||
|
||||
private Q_SLOTS:
|
||||
void loginPageRequestFinished();
|
||||
void loginRequestFinished();
|
||||
void userInfoRequestFinished();
|
||||
|
||||
void getBuchungenRequestFinished();
|
||||
void createBuchungRequestFinished();
|
||||
void updateBuchungRequestFinished();
|
||||
void deleteBuchungRequestFinished();
|
||||
|
||||
void getKontierungenRequestFinished();
|
||||
void createKontierungRequestFinished();
|
||||
void updateKontierungRequestFinished();
|
||||
void deleteKontierungRequestFinished();
|
||||
|
||||
void getProjekteRequestFinished();
|
||||
|
||||
private:
|
||||
QString m_url;
|
||||
QNetworkAccessManager *m_manager;
|
||||
|
||||
struct {
|
||||
QNetworkReply *loginPage;
|
||||
QNetworkReply *login;
|
||||
QNetworkReply *userInfo;
|
||||
|
||||
QNetworkReply *getBuchungen;
|
||||
QNetworkReply *createBuchung;
|
||||
QNetworkReply *updateBuchung;
|
||||
QNetworkReply *deleteBuchung;
|
||||
|
||||
QNetworkReply *getKontierungen;
|
||||
QNetworkReply *createKontierung;
|
||||
QNetworkReply *updateKontierung;
|
||||
QNetworkReply *deleteKontierung;
|
||||
|
||||
QNetworkReply *getProjekte;
|
||||
} m_replies;
|
||||
};
|
||||
|
||||
#endif // ZEITERFASSUNG_H
|
47
zeiterfassung.pro
Executable file
@@ -0,0 +1,47 @@
|
||||
QT += network gui widgets
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG -= app_bundle
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += main.cpp \
|
||||
zeiterfassung.cpp \
|
||||
mainwindow.cpp \
|
||||
dialogs/aboutmedialog.cpp \
|
||||
dialogs/authenticationdialog.cpp \
|
||||
dialogs/buchungdialog.cpp \
|
||||
models/buchungenmodel.cpp \
|
||||
dialogs/kontierungdialog.cpp \
|
||||
models/kontierungenmodel.cpp \
|
||||
eventloopwithstatus.cpp
|
||||
|
||||
HEADERS += \
|
||||
zeiterfassung.h \
|
||||
mainwindow.h \
|
||||
dialogs/aboutmedialog.h \
|
||||
dialogs/authenticationdialog.h \
|
||||
dialogs/buchungdialog.h \
|
||||
models/buchungenmodel.h \
|
||||
dialogs/kontierungdialog.h \
|
||||
models/kontierungenmodel.h \
|
||||
eventloopwithstatus.h
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
dialogs/aboutmedialog.ui \
|
||||
dialogs/authenticationdialog.ui \
|
||||
dialogs/buchungdialog.ui \
|
||||
dialogs/kontierungdialog.ui
|