diff --git a/advancedviewdialog.cpp b/advancedviewdialog.cpp new file mode 100644 index 0000000..7eb5ef4 --- /dev/null +++ b/advancedviewdialog.cpp @@ -0,0 +1,268 @@ +#include "advancedviewdialog.h" +#include "ui_advancedviewdialog.h" + +#include +#include +#include +#include + +#include "replies/createbookingreply.h" +#include "replies/updatebookingreply.h" +#include "replies/deletebookingreply.h" +#include "replies/createtimeassignmentreply.h" +#include "replies/updatetimeassignmentreply.h" +#include "replies/deletetimeassignmentreply.h" + +#include "stripswidget.h" +#include "mainwindow.h" +#include "timeutils.h" +#include "dialogs/bookingdialog.h" +#include "dialogs/timeassignmentdialog.h" +#include "models/bookingsmodel.h" +#include "models/timeassignmentsmodel.h" + +AdvancedViewDialog::AdvancedViewDialog(StripsWidget &stripsWidget, QWidget *parent) : + ZeiterfassungDialog(parent), + ui(new Ui::AdvancedViewDialog), + m_stripsWidget(stripsWidget), + m_bookingsModel(new BookingsModel(stripsWidget, this)), + m_timeAssignmentsModel(new TimeAssignmentsModel(stripsWidget, this)) +{ + ui->setupUi(this); + + ui->bookingsView->setModel(m_bookingsModel); + ui->bookingsView->setEnabled(m_bookingsModel->enabled()); + connect(m_bookingsModel, &BookingsModel::enabledChanged, ui->bookingsView, &QWidget::setEnabled); + connect(ui->bookingsView, &QWidget::customContextMenuRequested, this, &AdvancedViewDialog::contextMenuBooking); + + ui->timeAssignmentsView->setModel(m_timeAssignmentsModel); + ui->timeAssignmentsView->setEnabled(m_timeAssignmentsModel->enabled()); + connect(m_timeAssignmentsModel, &TimeAssignmentsModel::enabledChanged, ui->timeAssignmentsView, &QWidget::setEnabled); + connect(ui->timeAssignmentsView, &QWidget::customContextMenuRequested, this, &AdvancedViewDialog::contextMenuTimeAssignment); +} + +AdvancedViewDialog::~AdvancedViewDialog() +{ + delete ui; +} + +void AdvancedViewDialog::contextMenuBooking(const QPoint &pos) +{ + auto index = ui->bookingsView->indexAt(pos); + + if(!index.isValid()) + { + QMenu menu; + auto createAction = menu.addAction(tr("Create booking")); + auto refreshAction = menu.addAction(QIcon(QPixmap(QStringLiteral(":/zeiterfassungguilib/images/refresh.png"))), tr("Refresh bookings")); + auto selectedAction = menu.exec(ui->bookingsView->viewport()->mapToGlobal(pos)); + if(selectedAction == createAction) + { + BookingDialog dialog(this); + dialog.setTime(timeNormalise(QTime::currentTime())); + again2: + if(dialog.exec() == QDialog::Accepted) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doCreateBooking( + m_stripsWidget.mainWindow().userInfo().userId, + m_stripsWidget.date(), + dialog.getTime(), + dialog.getTimespan(), + dialog.getType(), + dialog.getText() + ); + + reply->waitForFinished(); + + if(reply->success()) + { + m_stripsWidget.refreshBookings(); + } + else + { + QMessageBox::warning(this, tr("Could not create booking!"), tr("Could not create booking!") % "\n\n" % reply->message()); + goto again2; + } + } + } + else if(selectedAction == refreshAction) + { + m_stripsWidget.refreshBookings(); + } + } + else + { + auto booking = m_stripsWidget.bookings().at(index.row()); + + QMenu menu; + auto editAction = menu.addAction(tr("Edit booking")); + auto deleteAction = menu.addAction(tr("Delete booking")); + auto selectedAction = menu.exec(ui->bookingsView->viewport()->mapToGlobal(pos)); + if(selectedAction == editAction) + { + BookingDialog dialog(this); + dialog.setTime(booking.time); + dialog.setTimespan(booking.timespan); + dialog.setType(booking.type); + dialog.setText(booking.text); + again1: + if(dialog.exec() == QDialog::Accepted) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doUpdateBooking( + booking.id, + m_stripsWidget.mainWindow().userInfo().userId, + m_stripsWidget.date(), + dialog.getTime(), + dialog.getTimespan(), + dialog.getType(), + dialog.getText() + ); + + reply->waitForFinished(); + + if(reply->success()) + { + m_stripsWidget.refreshBookings(); + } + else + { + QMessageBox::warning(this, tr("Could not edit booking!"), tr("Could not edit booking!") % "\n\n" % reply->message()); + goto again1; + } + } + } + else if(selectedAction == deleteAction) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you really want to delete the booking?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Cancel); + if(msgBox.exec() == QMessageBox::Yes) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doDeleteBooking(booking.id); + + reply->waitForFinished(); + + if(reply->success()) + m_stripsWidget.refreshBookings(); + else + QMessageBox::warning(this, tr("Could not delete booking!"), tr("Could not delete booking!") % "\n\n" % reply->message()); + } + } + } +} + +void AdvancedViewDialog::contextMenuTimeAssignment(const QPoint &pos) +{ + auto index = ui->timeAssignmentsView->indexAt(pos); + + if(!index.isValid()) + { + QMenu menu; + auto createAction = menu.addAction(tr("Create time assignment")); + auto refreshAction = menu.addAction(QIcon(QPixmap(QStringLiteral(":/zeiterfassungguilib/images/refresh.png"))), tr("Refresh time assignments")); + auto selectedAction = menu.exec(ui->timeAssignmentsView->viewport()->mapToGlobal(pos)); + if(selectedAction == createAction) + { + TimeAssignmentDialog dialog(m_stripsWidget.mainWindow().projects(), + m_stripsWidget.mainWindow().settings(), this); + again2: + if(dialog.exec() == QDialog::Accepted) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doCreateTimeAssignment( + m_stripsWidget.mainWindow().userInfo().userId, + m_stripsWidget.date(), + dialog.getTime(), + dialog.getTimespan(), + dialog.getProject(), + dialog.getSubproject(), + dialog.getWorkpackage(), + dialog.getText() + ); + + reply->waitForFinished(); + + if(reply->success()) + { + m_stripsWidget.refreshTimeAssignments(); + } + else + { + QMessageBox::warning(this, tr("Could not create time assignment!"), tr("Could not create time assignment!") % "\n\n" % reply->message()); + goto again2; + } + } + } + else if(selectedAction == refreshAction) + { + m_stripsWidget.refreshTimeAssignments(); + } + } + else + { + auto timeAssignment = m_stripsWidget.timeAssignments().at(index.row()); + + QMenu menu; + auto editAction = menu.addAction(tr("Edit time assignment")); + auto deleteAction = menu.addAction(tr("Delete time assignment")); + auto selectedAction = menu.exec(ui->timeAssignmentsView->viewport()->mapToGlobal(pos)); + if(selectedAction == editAction) + { + TimeAssignmentDialog dialog(m_stripsWidget.mainWindow().projects(), + m_stripsWidget.mainWindow().settings(), this); + dialog.setTime(timeAssignment.time); + dialog.setTimespan(timeAssignment.timespan); + dialog.setProject(timeAssignment.project); + dialog.setSubproject(timeAssignment.subproject); + dialog.setWorkpackage(timeAssignment.workpackage); + dialog.setText(timeAssignment.text); + again1: + if(dialog.exec() == QDialog::Accepted) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doUpdateTimeAssignment( + timeAssignment.id, + m_stripsWidget.mainWindow().userInfo().userId, + m_stripsWidget.date(), + dialog.getTime(), + dialog.getTimespan(), + dialog.getProject(), + dialog.getSubproject(), + dialog.getWorkpackage(), + dialog.getText() + ); + + reply->waitForFinished(); + + if(reply->success()) + { + m_stripsWidget.refreshTimeAssignments(); + } + else + { + QMessageBox::warning(this, tr("Could not edit time assignment!"), tr("Could not edit time assignment!") % "\n\n" % reply->message()); + goto again1; + } + } + } + else if(selectedAction == deleteAction) + { + QMessageBox msgBox; + msgBox.setText(tr("Do you really want to delete the time assignment?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Cancel); + if(msgBox.exec() == QMessageBox::Yes) + { + auto reply = m_stripsWidget.mainWindow().erfassung().doDeleteTimeAssignment(timeAssignment.id); + + reply->waitForFinished(); + + if(reply->success()) + { + m_stripsWidget.refreshTimeAssignments(); + } + else + QMessageBox::warning(this, tr("Could not delete time assignment!"), tr("Could not delete time assignment!") % "\n\n" % reply->message()); + } + } + } +} diff --git a/advancedviewdialog.h b/advancedviewdialog.h new file mode 100644 index 0000000..9a0c223 --- /dev/null +++ b/advancedviewdialog.h @@ -0,0 +1,29 @@ +#pragma once + +#include "zeiterfassungdialog.h" + +namespace Ui { class AdvancedViewDialog; } +class StripsWidget; +class BookingsModel; +class TimeAssignmentsModel; + +class AdvancedViewDialog : public ZeiterfassungDialog +{ + Q_OBJECT + +public: + explicit AdvancedViewDialog(StripsWidget &stripsWidget, QWidget *parent = Q_NULLPTR); + ~AdvancedViewDialog(); + +private Q_SLOTS: + void contextMenuBooking(const QPoint &pos); + void contextMenuTimeAssignment(const QPoint &pos); + +private: + Ui::AdvancedViewDialog *ui; + + StripsWidget &m_stripsWidget; + + BookingsModel *m_bookingsModel; + TimeAssignmentsModel *m_timeAssignmentsModel; +}; diff --git a/advancedviewdialog.ui b/advancedviewdialog.ui new file mode 100644 index 0000000..0d87750 --- /dev/null +++ b/advancedviewdialog.ui @@ -0,0 +1,81 @@ + + + AdvancedViewDialog + + + + 0 + 0 + 1024 + 480 + + + + Advanced view + + + + + + Qt::Vertical + + + + Qt::CustomContextMenu + + + + + Qt::CustomContextMenu + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + AdvancedViewDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AdvancedViewDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/advancedviewplugin.cpp b/advancedviewplugin.cpp new file mode 100644 index 0000000..3b3f308 --- /dev/null +++ b/advancedviewplugin.cpp @@ -0,0 +1,38 @@ +#include "advancedviewplugin.h" + +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "stripswidget.h" + +#include "advancedviewwidget.h" + +AdvancedViewPlugin::AdvancedViewPlugin(QObject *parent) : + ZeiterfassungPlugin(parent) +{ + qDebug() << "called"; + + static auto dir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QStringLiteral("translations")); + + if(m_translator.load(QLocale(), QStringLiteral("advancedviewplugin"), QStringLiteral("_"), dir)) + { + if(!QCoreApplication::installTranslator(&m_translator)) + { + qWarning() << "could not install translation advancedviewplugin"; + } + } + else + { + qWarning() << "could not load translation advancedviewplugin"; + } +} + +void AdvancedViewPlugin::attachTo(MainWindow &mainWindow) +{ + for(auto stripsWidget : mainWindow.stripsWidgets()) + stripsWidget->headerLayout()->addWidget(new AdvancedViewWidget(*stripsWidget)); +} diff --git a/advancedviewplugin.h b/advancedviewplugin.h new file mode 100644 index 0000000..0e2c7ad --- /dev/null +++ b/advancedviewplugin.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include "zeiterfassungplugin.h" + +class MainWindow; + +class Q_DECL_EXPORT AdvancedViewPlugin : public ZeiterfassungPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "dbsoftware.zeiterfassung.plugin/1.0" FILE "advancedviewplugin.json") + Q_INTERFACES(ZeiterfassungPlugin) + +public: + explicit AdvancedViewPlugin(QObject *parent = Q_NULLPTR); + + // ZeiterfassungPlugin interface + void attachTo(MainWindow &mainWindow) Q_DECL_OVERRIDE; + +private: + QTranslator m_translator; +}; diff --git a/advancedviewplugin.json b/advancedviewplugin.json new file mode 100644 index 0000000..e69de29 diff --git a/advancedviewplugin.pro b/advancedviewplugin.pro new file mode 100644 index 0000000..00842f7 --- /dev/null +++ b/advancedviewplugin.pro @@ -0,0 +1,34 @@ +QT += core network gui widgets + +DBLIBS += zeiterfassungcore zeiterfassunggui + +TARGET = advancedviewplugin + +HEADERS += advancedviewdialog.h \ + advancedviewplugin.h \ + advancedviewwidget.h \ + dialogs/bookingdialog.h \ + dialogs/timeassignmentdialog.h \ + models/bookingsmodel.h \ + models/timeassignmentsmodel.h + +SOURCES += advancedviewdialog.cpp \ + advancedviewplugin.cpp \ + advancedviewwidget.cpp \ + dialogs/bookingdialog.cpp \ + dialogs/timeassignmentdialog.cpp \ + models/bookingsmodel.cpp \ + models/timeassignmentsmodel.cpp + +FORMS += advancedviewdialog.ui \ + dialogs/bookingdialog.ui \ + dialogs/timeassignmentdialog.ui + +RESOURCES += advancedviewplugin_resources.qrc + +TRANSLATIONS += translations/advancedviewplugin_en.ts \ + translations/advancedviewplugin_de.ts + +OTHER_FILES += advancedviewplugin.json + +include(../plugin.pri) diff --git a/advancedviewplugin_resources.qrc b/advancedviewplugin_resources.qrc new file mode 100644 index 0000000..6b72660 --- /dev/null +++ b/advancedviewplugin_resources.qrc @@ -0,0 +1,5 @@ + + + images/advanced-view.png + + diff --git a/advancedviewwidget.cpp b/advancedviewwidget.cpp new file mode 100644 index 0000000..be52d8d --- /dev/null +++ b/advancedviewwidget.cpp @@ -0,0 +1,30 @@ +#include "advancedviewwidget.h" + +#include + +#include "stripswidget.h" +#include "advancedviewdialog.h" + +AdvancedViewWidget::AdvancedViewWidget(StripsWidget &stripsWidget) : + QToolButton(&stripsWidget), + m_stripsWidget(stripsWidget) +{ + setIcon(QIcon(QStringLiteral(":/zeiterfassung/plugins/advancedviewplugin/images/advanced-view.png"))); + setText(tr("Advanced view")); + + connect(&stripsWidget, &StripsWidget::dateChanged, this, &AdvancedViewWidget::dateChanged); + dateChanged(stripsWidget.date()); + + connect(this, &QAbstractButton::pressed, this, &AdvancedViewWidget::pressedSlot); +} + +void AdvancedViewWidget::dateChanged(const QDate &date) +{ + setEnabled(date.isValid()); +} + +void AdvancedViewWidget::pressedSlot() +{ + AdvancedViewDialog dialog(m_stripsWidget, this); + dialog.exec(); +} diff --git a/advancedviewwidget.h b/advancedviewwidget.h new file mode 100644 index 0000000..d1004a8 --- /dev/null +++ b/advancedviewwidget.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +class StripsWidget; + +class AdvancedViewWidget : public QToolButton +{ + Q_OBJECT + +public: + explicit AdvancedViewWidget(StripsWidget &stripsWidget); + +private Q_SLOTS: + void dateChanged(const QDate &date); + void pressedSlot(); + +private: + StripsWidget &m_stripsWidget; +}; diff --git a/dialogs/bookingdialog.cpp b/dialogs/bookingdialog.cpp new file mode 100644 index 0000000..a2d42df --- /dev/null +++ b/dialogs/bookingdialog.cpp @@ -0,0 +1,54 @@ +#include "bookingdialog.h" +#include "ui_bookingdialog.h" + +BookingDialog::BookingDialog(QWidget *parent) : + ZeiterfassungDialog(parent), + ui(new Ui::BookingDialog) +{ + ui->setupUi(this); +} + +BookingDialog::~BookingDialog() +{ + delete ui; +} + +QTime BookingDialog::getTime() const +{ + return ui->timeEditTime->time(); +} + +void BookingDialog::setTime(const QTime &time) +{ + ui->timeEditTime->setTime(time); +} + +QTime BookingDialog::getTimespan() const +{ + return ui->timeEditTimespan->time(); +} + +void BookingDialog::setTimespan(const QTime ×pan) +{ + ui->timeEditTimespan->setTime(timespan); +} + +QString BookingDialog::getType() const +{ + return ui->comboBoxType->currentText(); +} + +void BookingDialog::setType(const QString &type) +{ + ui->comboBoxType->setCurrentText(type); +} + +QString BookingDialog::getText() const +{ + return ui->lineEditText->text(); +} + +void BookingDialog::setText(const QString &text) +{ + ui->lineEditText->setText(text); +} diff --git a/dialogs/bookingdialog.h b/dialogs/bookingdialog.h new file mode 100644 index 0000000..841a0db --- /dev/null +++ b/dialogs/bookingdialog.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "zeiterfassungdialog.h" + +namespace Ui { class BookingDialog; } + +class BookingDialog : public ZeiterfassungDialog +{ + Q_OBJECT + +public: + explicit BookingDialog(QWidget *parent = Q_NULLPTR); + ~BookingDialog(); + + 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::BookingDialog *ui; +}; diff --git a/dialogs/bookingdialog.ui b/dialogs/bookingdialog.ui new file mode 100644 index 0000000..6e79a85 --- /dev/null +++ b/dialogs/bookingdialog.ui @@ -0,0 +1,163 @@ + + + BookingDialog + + + + 0 + 0 + 400 + 237 + + + + + 16777215 + 0 + + + + Booking + + + + + + + 20 + + + + Booking + + + + + + + + + Time: + + + timeEditTime + + + + + + + Timespan: + + + timeEditTimespan + + + + + + + Type: + + + comboBoxType + + + + + + + Text: + + + lineEditText + + + + + + + HH:mm:ss + + + + + + + HH:mm:ss + + + + + + + + + + true + + + QComboBox::NoInsert + + + + K + + + + + G + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + BookingDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + BookingDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/dialogs/timeassignmentdialog.cpp b/dialogs/timeassignmentdialog.cpp new file mode 100644 index 0000000..13abd07 --- /dev/null +++ b/dialogs/timeassignmentdialog.cpp @@ -0,0 +1,119 @@ +#include "timeassignmentdialog.h" +#include "ui_timeassignmentdialog.h" + +#include +#include +#include + +#include "zeiterfassungsettings.h" + +TimeAssignmentDialog::TimeAssignmentDialog(const QMap &projects, const ZeiterfassungSettings &settings, + QWidget *parent) : + ZeiterfassungDialog(parent), + ui(new Ui::TimeAssignmentDialog) +{ + ui->setupUi(this); + + { + for(const auto &preferedProject : settings.projects()) + { + if(!projects.contains(preferedProject)) + { + qWarning() << "cannot find project" << preferedProject; + continue; + } + + ui->comboBoxProject->addItem(tr("%0 (%1)").arg(projects.value(preferedProject)).arg(preferedProject), preferedProject); + } + + if(settings.projects().count()) + ui->comboBoxProject->insertSeparator(ui->comboBoxProject->count()); + + for(auto iter = projects.constBegin(); iter != projects.constEnd(); iter++) + { + if(!settings.projects().contains(iter.key())) + ui->comboBoxProject->addItem(tr("%0 (%1)").arg(iter.value()).arg(iter.key()), iter.key()); + } + } + + for(const auto &subproject : settings.subprojects()) + ui->comboBoxSubproject->addItem(subproject); + ui->comboBoxSubproject->clearEditText(); + + for(const auto &workpackage : settings.workpackages()) + ui->comboBoxWorkpackage->addItem(workpackage); + ui->comboBoxWorkpackage->clearEditText(); + + for(const auto &text : settings.texts()) + ui->comboBoxText->addItem(text); + ui->comboBoxText->clearEditText(); +} + +TimeAssignmentDialog::~TimeAssignmentDialog() +{ + delete ui; +} + +QTime TimeAssignmentDialog::getTime() const +{ + return ui->timeEditTime->time(); +} + +void TimeAssignmentDialog::setTime(const QTime &time) +{ + ui->timeEditTime->setTime(time); +} + +QTime TimeAssignmentDialog::getTimespan() const +{ + return ui->timeEditTimespan->time(); +} + +void TimeAssignmentDialog::setTimespan(const QTime ×pan) +{ + ui->timeEditTimespan->setTime(timespan); +} + +QString TimeAssignmentDialog::getProject() const +{ + return ui->comboBoxProject->currentData().toString(); +} + +void TimeAssignmentDialog::setProject(const QString &project) +{ + auto index = ui->comboBoxProject->findData(project); + if(index >= 0) + ui->comboBoxProject->setCurrentIndex(index); + else + qWarning() << "could not find project" << project; +} + +QString TimeAssignmentDialog::getSubproject() const +{ + return ui->comboBoxSubproject->currentText(); +} + +void TimeAssignmentDialog::setSubproject(const QString &subproject) +{ + ui->comboBoxSubproject->setCurrentText(subproject); +} + +QString TimeAssignmentDialog::getWorkpackage() const +{ + return ui->comboBoxWorkpackage->currentText(); +} + +void TimeAssignmentDialog::setWorkpackage(const QString &workpackage) +{ + ui->comboBoxWorkpackage->setCurrentText(workpackage); +} + +QString TimeAssignmentDialog::getText() const +{ + return ui->comboBoxText->currentText(); +} + +void TimeAssignmentDialog::setText(const QString &text) +{ + ui->comboBoxText->setCurrentText(text); +} diff --git a/dialogs/timeassignmentdialog.h b/dialogs/timeassignmentdialog.h new file mode 100644 index 0000000..916fd09 --- /dev/null +++ b/dialogs/timeassignmentdialog.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include "zeiterfassungdialog.h" + +template class QMap; + +class ZeiterfassungSettings; + +namespace Ui { class TimeAssignmentDialog; } + +class TimeAssignmentDialog : public ZeiterfassungDialog +{ + Q_OBJECT + +public: + explicit TimeAssignmentDialog(const QMap &projects, const ZeiterfassungSettings &settings, + QWidget *parent = Q_NULLPTR); + ~TimeAssignmentDialog(); + + QTime getTime() const; + void setTime(const QTime &time); + + QTime getTimespan() const; + void setTimespan(const QTime ×pan); + + QString getProject() const; + void setProject(const QString &project); + + QString getSubproject() const; + void setSubproject(const QString &subproject); + + QString getWorkpackage() const; + void setWorkpackage(const QString &workpackage); + + QString getText() const; + void setText(const QString &text); + +private: + Ui::TimeAssignmentDialog *ui; +}; diff --git a/dialogs/timeassignmentdialog.ui b/dialogs/timeassignmentdialog.ui new file mode 100644 index 0000000..3587f7c --- /dev/null +++ b/dialogs/timeassignmentdialog.ui @@ -0,0 +1,184 @@ + + + TimeAssignmentDialog + + + + 0 + 0 + 400 + 307 + + + + + 16777215 + 0 + + + + Time assignment + + + + + + + 20 + + + + Time assignment + + + + + + + + + Time: + + + timeEditTime + + + + + + + Timespan: + + + timeEditTimespan + + + + + + + Project: + + + comboBoxProject + + + + + + + Subproject: + + + + + + + Workpackage: + + + + + + + Text: + + + + + + + HH:mm:ss + + + + + + + HH:mm:ss + + + + + + + + + + true + + + QComboBox::NoInsert + + + + + + + true + + + QComboBox::NoInsert + + + + + + + true + + + QComboBox::NoInsert + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + TimeAssignmentDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TimeAssignmentDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/images/advanced-view.png b/images/advanced-view.png new file mode 100644 index 0000000..7a6c875 Binary files /dev/null and b/images/advanced-view.png differ diff --git a/models/bookingsmodel.cpp b/models/bookingsmodel.cpp new file mode 100644 index 0000000..4c59657 --- /dev/null +++ b/models/bookingsmodel.cpp @@ -0,0 +1,93 @@ +#include "bookingsmodel.h" + +#include "stripswidget.h" + +BookingsModel::BookingsModel(StripsWidget &stripsWidget, QObject *parent) : + QAbstractListModel(parent), + m_stripsWidget(stripsWidget) +{ + connect(&stripsWidget, &StripsWidget::bookingsChanged, this, &BookingsModel::bookingsChanged); + connect(&stripsWidget, &StripsWidget::refreshingBookingsChanged, this, &BookingsModel::refreshingChanged); +} + +StripsWidget &BookingsModel::stripsWidget() const +{ + return m_stripsWidget; +} + +bool BookingsModel::enabled() const +{ + return !m_stripsWidget.refreshingBookings(); +} + +int BookingsModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return m_stripsWidget.bookings().count(); +} + +int BookingsModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 5; +} + +QVariant BookingsModel::data(const QModelIndex &index, int role) const +{ + Q_ASSERT(index.row() < m_stripsWidget.bookings().count()); + const auto &booking = m_stripsWidget.bookings().at(index.row()); + + switch(role) + { + case Qt::DisplayRole: + case Qt::EditRole: + switch(index.column()) + { + case 0: return booking.id; + case 1: return booking.time; + case 2: return booking.timespan; + case 3: return booking.type; + case 4: return booking.text; + } + } + + return QVariant(); +} + +QVariant BookingsModel::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"); + } + } + default: + qt_noop(); + } + + return QVariant(); +} + +void BookingsModel::bookingsChanged() +{ + beginResetModel(); + endResetModel(); +} + +void BookingsModel::refreshingChanged(bool refreshing) +{ + Q_EMIT enabledChanged(!refreshing); +} diff --git a/models/bookingsmodel.h b/models/bookingsmodel.h new file mode 100644 index 0000000..fd8b654 --- /dev/null +++ b/models/bookingsmodel.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include "zeiterfassungapi.h" + +class StripsWidget; + +class BookingsModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged) + +public: + explicit BookingsModel(StripsWidget &stripsWidget, QObject *parent = Q_NULLPTR); + + StripsWidget &stripsWidget() const; + + bool enabled() const; + + // 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; + +Q_SIGNALS: + void enabledChanged(bool enabled); + +private Q_SLOTS: + void bookingsChanged(); + void refreshingChanged(bool refreshing); + +private: + StripsWidget &m_stripsWidget; +}; diff --git a/models/timeassignmentsmodel.cpp b/models/timeassignmentsmodel.cpp new file mode 100644 index 0000000..73a1a70 --- /dev/null +++ b/models/timeassignmentsmodel.cpp @@ -0,0 +1,97 @@ +#include "timeassignmentsmodel.h" + +#include "stripswidget.h" + +TimeAssignmentsModel::TimeAssignmentsModel(StripsWidget &stripsWidget, QObject *parent) : + QAbstractListModel(parent), + m_stripsWidget(stripsWidget) +{ + connect(&stripsWidget, &StripsWidget::timeAssignmentsChanged, this, &TimeAssignmentsModel::timeAssignmentsChanged); + connect(&stripsWidget, &StripsWidget::refreshingTimeAssignmentsChanged, this, &TimeAssignmentsModel::refreshingChanged); +} + +StripsWidget &TimeAssignmentsModel::stripsWidget() const +{ + return m_stripsWidget; +} + +bool TimeAssignmentsModel::enabled() const +{ + return !m_stripsWidget.refreshingTimeAssignments(); +} + +int TimeAssignmentsModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return m_stripsWidget.timeAssignments().count(); +} + +int TimeAssignmentsModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 7; +} + +QVariant TimeAssignmentsModel::data(const QModelIndex &index, int role) const +{ + Q_ASSERT(index.row() < m_stripsWidget.timeAssignments().count()); + const auto &timeAssignment = m_stripsWidget.timeAssignments().at(index.row()); + + switch(role) + { + case Qt::DisplayRole: + case Qt::EditRole: + switch(index.column()) + { + case 0: return timeAssignment.id; + case 1: return timeAssignment.time; + case 2: return timeAssignment.timespan; + case 3: return timeAssignment.project; + case 4: return timeAssignment.subproject; + case 5: return timeAssignment.workpackage; + case 6: return timeAssignment.text; + } + } + + return QVariant(); +} + +QVariant TimeAssignmentsModel::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("Project"); + case 4: return tr("Subproject"); + case 5: return tr("Workpackage"); + case 6: return tr("Text"); + } + } + default: + qt_noop(); + } + + return QVariant(); +} + +void TimeAssignmentsModel::timeAssignmentsChanged() +{ + beginResetModel(); + endResetModel(); +} + +void TimeAssignmentsModel::refreshingChanged(bool refreshing) +{ + Q_EMIT enabledChanged(!refreshing); +} diff --git a/models/timeassignmentsmodel.h b/models/timeassignmentsmodel.h new file mode 100644 index 0000000..cedbcd9 --- /dev/null +++ b/models/timeassignmentsmodel.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include "zeiterfassungapi.h" + +class StripsWidget; + +class TimeAssignmentsModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged) + +public: + explicit TimeAssignmentsModel(StripsWidget &stripsWidget, QObject *parent = Q_NULLPTR); + + StripsWidget &stripsWidget() const; + + bool enabled() const; + + // 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; + +Q_SIGNALS: + void stripsWidgetChanged(StripsWidget *stripsWidget); + void enabledChanged(bool enabled); + +private Q_SLOTS: + void timeAssignmentsChanged(); + void refreshingChanged(bool refreshing); + +private: + StripsWidget &m_stripsWidget; +}; diff --git a/translations/advancedviewplugin_de.ts b/translations/advancedviewplugin_de.ts new file mode 100644 index 0000000..b68cae8 --- /dev/null +++ b/translations/advancedviewplugin_de.ts @@ -0,0 +1,240 @@ + + + + + AdvancedViewDialog + + + Advanced view + Erweiterte Anzeige + + + + Create booking + Buchung erstellen + + + + Refresh bookings + Buchungen aktualisieren + + + + Could not create booking! + Konnte Buchung nicht erstellen! + + + + Edit booking + Buchung bearbeiten + + + + Delete booking + Buchung löschen + + + + Could not edit booking! + Konnte Buchung nicht bearbeiten! + + + + Do you really want to delete the booking? + Möchten Sie die Buchung wirklich löschen? + + + + Could not delete booking! + Konnte Buchung nicht löschen! + + + + Create time assignment + Kontierung erstellen + + + + Refresh time assignments + Kontierungen aktualisieren + + + + Could not create time assignment! + Konnte Kontierung nicht erstellen! + + + + Edit time assignment + Kontierung bearbeiten + + + + Delete time assignment + Kontierung löschen + + + + Could not edit time assignment! + Konnte Kontierung nicht bearbeiten! + + + + Do you really want to delete the time assignment? + Möchten Sie die Kontierung wirklich löschen? + + + + Could not delete time assignment! + Konnte Kontierung nicht löschen! + + + + AdvancedViewWidget + + + Advanced view + Erweiterte Anzeige + + + + BookingDialog + + + + Booking + Buchung + + + + Time: + Zeit: + + + + Timespan: + Zeitspanne: + + + + Type: + Typ: + + + + Text: + Text: + + + + BookingsModel + + + ID + ID + + + + Time + Zeit + + + + Timespan + Zeitspanne + + + + Type + Typ + + + + Text + Text + + + + TimeAssignmentDialog + + + + Time assignment + Kontierung + + + + Time: + Zeit: + + + + Timespan: + Zeitspanne: + + + + Project: + Projekt: + + + + Subproject: + Subprojekt: + + + + Workpackage: + Arbeitspaket: + + + + Text: + Text: + + + + + %0 (%1) + %0 (%1) + + + + TimeAssignmentsModel + + + ID + ID + + + + Time + Zeit + + + + Timespan + Zeitspanne + + + + Project + Projekt + + + + Subproject + Subprojekt + + + + Workpackage + Arbeitspaket + + + + Text + Text + + + diff --git a/translations/advancedviewplugin_en.ts b/translations/advancedviewplugin_en.ts new file mode 100644 index 0000000..80acdaf --- /dev/null +++ b/translations/advancedviewplugin_en.ts @@ -0,0 +1,240 @@ + + + + + AdvancedViewDialog + + + Advanced view + + + + + Create booking + + + + + Refresh bookings + + + + + Could not create booking! + + + + + Edit booking + + + + + Delete booking + + + + + Could not edit booking! + + + + + Do you really want to delete the booking? + + + + + Could not delete booking! + + + + + Create time assignment + + + + + Refresh time assignments + + + + + Could not create time assignment! + + + + + Edit time assignment + + + + + Delete time assignment + + + + + Could not edit time assignment! + + + + + Do you really want to delete the time assignment? + + + + + Could not delete time assignment! + + + + + AdvancedViewWidget + + + Advanced view + + + + + BookingDialog + + + + Booking + + + + + Time: + + + + + Timespan: + + + + + Type: + + + + + Text: + + + + + BookingsModel + + + ID + + + + + Time + + + + + Timespan + + + + + Type + + + + + Text + + + + + TimeAssignmentDialog + + + + Time assignment + + + + + Time: + + + + + Timespan: + + + + + Project: + + + + + Subproject: + + + + + Workpackage: + + + + + Text: + + + + + + %0 (%1) + + + + + TimeAssignmentsModel + + + ID + + + + + Time + + + + + Timespan + + + + + Project + + + + + Subproject + + + + + Workpackage + + + + + Text + + + +