Imported existing sources

This commit is contained in:
0xFEEDC0DE64
2018-09-17 19:42:01 +02:00
parent 730828eb94
commit 6c48560724
17 changed files with 579 additions and 0 deletions

BIN
images/lunch-meal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

20
lunchmealdialog.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include "lunchmealdialog.h"
#include "ui_lunchmealdialog.h"
#include <QDate>
#include <QLocale>
LunchMealDialog::LunchMealDialog(const QDate &date, const QString &content, QWidget *parent) :
ZeiterfassungDialog(parent),
ui(new Ui::LunchMealDialog)
{
ui->setupUi(this);
ui->labelTitle->setText(tr("Lunch meal for %0").arg(QLocale().toString(date)));
ui->labelLunchMeal->setText(content);
}
LunchMealDialog::~LunchMealDialog()
{
delete ui;
}

21
lunchmealdialog.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "zeiterfassungdialog.h"
class QDate;
class StripsWidget;
namespace Ui { class LunchMealDialog; }
class LunchMealDialog : public ZeiterfassungDialog
{
Q_OBJECT
public:
explicit LunchMealDialog(const QDate &date, const QString &content, QWidget *parent = Q_NULLPTR);
~LunchMealDialog();
private:
Ui::LunchMealDialog *ui;
};

88
lunchmealdialog.ui Normal file
View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LunchMealDialog</class>
<widget class="QDialog" name="LunchMealDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Lunch meal</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
<item>
<widget class="QLabel" name="labelTitle">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">Lunch meal for</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelLunchMeal">
<property name="text">
<string>Loading...</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>LunchMealDialog</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>LunchMealDialog</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>

44
lunchmealplugin.cpp Normal file
View File

@@ -0,0 +1,44 @@
#include "lunchmealplugin.h"
#include <QDebug>
#include <QDir>
#include <QCoreApplication>
#include <QLocale>
#include <QBoxLayout>
#include "mainwindow.h"
#include "stripswidget.h"
#include "lunchmealwidget.h"
#include "lunchmealsettingswidget.h"
LunchMealPlugin::LunchMealPlugin(QObject *parent) :
ZeiterfassungPlugin(parent)
{
qDebug() << "called";
static auto dir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QStringLiteral("translations"));
if(m_translator.load(QLocale(), QStringLiteral("lunchmealplugin"), QStringLiteral("_"), dir))
{
if(!QCoreApplication::installTranslator(&m_translator))
{
qWarning() << "could not install translation lunchmealplugin";
}
}
else
{
qWarning() << "could not load translation lunchmealplugin";
}
}
void LunchMealPlugin::attachTo(MainWindow &mainWindow)
{
for(auto stripsWidget : mainWindow.stripsWidgets())
stripsWidget->headerLayout()->addWidget(new LunchMealWidget(*stripsWidget));
}
SettingsWidget *LunchMealPlugin::settingsWidget(ZeiterfassungSettings &settings, QWidget *parent) const
{
return new LunchMealSettingsWidget(settings, parent);
}

26
lunchmealplugin.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <QObject>
#include <QTranslator>
#include "zeiterfassungplugin.h"
class MainWindow;
class Q_DECL_EXPORT LunchMealPlugin : public ZeiterfassungPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "dbsoftware.zeiterfassung.plugin/1.0" FILE "lunchmealplugin.json")
Q_INTERFACES(ZeiterfassungPlugin)
public:
explicit LunchMealPlugin(QObject *parent = Q_NULLPTR);
// ZeiterfassungPlugin interface
void attachTo(MainWindow &mainWindow) Q_DECL_OVERRIDE;
virtual SettingsWidget *settingsWidget(ZeiterfassungSettings &settings, QWidget *parent = Q_NULLPTR) const Q_DECL_OVERRIDE;
private:
QTranslator m_translator;
};

0
lunchmealplugin.json Normal file
View File

28
lunchmealplugin.pro Normal file
View File

@@ -0,0 +1,28 @@
QT += core network gui widgets
DBLIBS += zeiterfassungcore zeiterfassunggui
TARGET = lunchmealplugin
HEADERS += lunchmealdialog.h \
lunchmealsettings.h \
lunchmealsettingswidget.h \
lunchmealplugin.h \
lunchmealwidget.h
SOURCES += lunchmealdialog.cpp \
lunchmealsettings.cpp \
lunchmealsettingswidget.cpp \
lunchmealplugin.cpp \
lunchmealwidget.cpp
FORMS += lunchmealdialog.ui
RESOURCES += lunchmealplugin_resources.qrc
TRANSLATIONS += translations/lunchmealplugin_en.ts \
translations/lunchmealplugin_de.ts
OTHER_FILES += lunchmealplugin.json
include(../plugin.pri)

View File

@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/zeiterfassung/plugins/lunchmealplugin">
<file>images/lunch-meal.png</file>
</qresource>
</RCC>

73
lunchmealsettings.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include "lunchmealsettings.h"
#include "zeiterfassungsettings.h"
const QString LunchMealSettings::m_url("LunchMealPlugin/url");
const QString LunchMealSettings::m_dateFormat("LunchMealPlugin/dateFormat");
const QString LunchMealSettings::m_defaultUrl("https://brunner.ninja/lunch/%0.txt");
const QString LunchMealSettings::m_defaultDateFormat("yyyy-MM-dd");
LunchMealSettings::LunchMealSettings(ZeiterfassungSettings &settings, QObject *parent) :
QObject(parent),
m_settings(settings)
{
}
QString LunchMealSettings::url() const
{
return m_settings.value(m_url, m_defaultUrl).toString();
}
bool LunchMealSettings::setUrl(const QString &url)
{
if(this->url() == url)
return true;
if(url == m_defaultUrl)
m_settings.remove(m_url);
else
m_settings.setValue(m_url, url);
m_settings.sync();
const auto success = m_settings.status() == QSettings::NoError;
if(success)
Q_EMIT urlChanged(url);
else
{
Q_EMIT m_settings.saveErrorOccured();
Q_EMIT saveErrorOccured();
}
return success;
}
QString LunchMealSettings::dateFormat() const
{
return m_settings.value(m_dateFormat, m_defaultDateFormat).toString();
}
bool LunchMealSettings::setDateFormat(const QString &dateFormat)
{
if(this->dateFormat() == dateFormat)
return true;
if(dateFormat == m_defaultDateFormat)
m_settings.remove(m_dateFormat);
else
m_settings.setValue(m_dateFormat, dateFormat);
m_settings.sync();
const auto success = m_settings.status() == QSettings::NoError;
if(success)
Q_EMIT dateFormatChanged(dateFormat);
else
{
Q_EMIT m_settings.saveErrorOccured();
Q_EMIT saveErrorOccured();
}
return success;
}

37
lunchmealsettings.h Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <QObject>
#include <QUrl>
class ZeiterfassungSettings;
class LunchMealSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat NOTIFY dateFormatChanged)
public:
LunchMealSettings(ZeiterfassungSettings &settings, QObject *parent = Q_NULLPTR);
// no QString becuase placeholder %0 encodes wrong in urls!
QString url() const;
bool setUrl(const QString &url);
QString dateFormat() const;
bool setDateFormat(const QString &dateFormat);
Q_SIGNALS:
void saveErrorOccured();
void urlChanged(const QString &url);
void dateFormatChanged(const QString &dateFormat);
private:
ZeiterfassungSettings &m_settings;
static const QString m_url;
static const QString m_dateFormat;
static const QString m_defaultUrl;
static const QString m_defaultDateFormat;
};

View File

@@ -0,0 +1,36 @@
#include "lunchmealsettingswidget.h"
#include <QFormLayout>
#include <QLineEdit>
LunchMealSettingsWidget::LunchMealSettingsWidget(ZeiterfassungSettings &settings, QWidget *parent) :
SettingsWidget(parent),
m_settings(settings)
{
auto layout = new QFormLayout(this);
layout->setMargin(0);
m_lineEditUrl = new QLineEdit(m_settings.url(), this);
layout->addRow(tr("Lunch meal API:"), m_lineEditUrl);
m_lineEditDateFormat = new QLineEdit(m_settings.dateFormat(), this);
layout->addRow(tr("Lunch meal date format:"), m_lineEditDateFormat);
setLayout(layout);
}
bool LunchMealSettingsWidget::isValid(QString &message) const
{
auto valid = QUrl::fromUserInput(m_lineEditUrl->text()).isValid();
if(!valid)
message = tr("The lunch meal api url is invalid!");
return valid;
}
bool LunchMealSettingsWidget::apply()
{
return m_settings.setUrl(m_lineEditUrl->text()) &&
m_settings.setDateFormat(m_lineEditDateFormat->text());
}

26
lunchmealsettingswidget.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include "settingswidget.h"
#include "lunchmealsettings.h"
class QLineEdit;
class LunchMealSettingsWidget : public SettingsWidget
{
Q_OBJECT
public:
explicit LunchMealSettingsWidget(ZeiterfassungSettings &settings, QWidget *parent = Q_NULLPTR);
virtual bool isValid(QString &message) const Q_DECL_OVERRIDE;
public Q_SLOTS:
virtual bool apply() Q_DECL_OVERRIDE;
private:
LunchMealSettings m_settings;
QLineEdit *m_lineEditUrl;
QLineEdit *m_lineEditDateFormat;
};

67
lunchmealwidget.cpp Normal file
View File

@@ -0,0 +1,67 @@
#include "lunchmealwidget.h"
#include <QIcon>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QUrl>
#include <QMessageBox>
#include <QStringBuilder>
#include "stripswidget.h"
#include "mainwindow.h"
#include "zeiterfassungapi.h"
#include "lunchmealdialog.h"
#include "lunchmealsettings.h"
LunchMealWidget::LunchMealWidget(StripsWidget &stripsWidget) :
QToolButton(&stripsWidget),
m_stripsWidget(stripsWidget)
{
setIcon(QIcon(QStringLiteral(":/zeiterfassung/plugins/lunchmealplugin/images/lunch-meal.png")));
setText(tr("Lunch meal"));
connect(this, &QAbstractButton::pressed, this, &LunchMealWidget::pressedSlot);
connect(&m_stripsWidget, &StripsWidget::dateChanged, this, &LunchMealWidget::dateChanged);
dateChanged(m_stripsWidget.date());
}
void LunchMealWidget::pressedSlot()
{
LunchMealDialog dialog(m_stripsWidget.date(), m_content, this);
dialog.exec();
}
void LunchMealWidget::dateChanged(const QDate &date)
{
setEnabled(false);
setVisible(false);
LunchMealSettings settings(m_stripsWidget.mainWindow().settings());
auto url = QUrl(settings.url().arg(date.toString(settings.dateFormat())));
m_reply = std::unique_ptr<QNetworkReply>(m_stripsWidget.mainWindow().erfassung().manager()->get(QNetworkRequest(url)));
connect(m_reply.get(), &QNetworkReply::finished, this, &LunchMealWidget::finished);
}
void LunchMealWidget::finished()
{
if(m_reply->error() != QNetworkReply::NoError &&
m_reply->error() != QNetworkReply::ContentNotFoundError)
{
QMessageBox::warning(&m_stripsWidget.mainWindow(), tr("Could not load lunch meal!"),
tr("Could not load lunch meal!") % "\n\n" % m_reply->errorString());
goto after;
}
if(m_reply->error() == QNetworkReply::NoError)
{
setEnabled(true);
setVisible(true);
m_content = m_reply->readAll();
}
after:
m_reply = Q_NULLPTR;
}

26
lunchmealwidget.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <QToolButton>
#include <QNetworkReply>
class StripsWidget;
class LunchMealWidget : public QToolButton
{
Q_OBJECT
public:
explicit LunchMealWidget(StripsWidget &stripsWidget);
private Q_SLOTS:
void pressedSlot();
void dateChanged(const QDate &date);
void finished();
private:
StripsWidget &m_stripsWidget;
std::unique_ptr<QNetworkReply> m_reply;
QString m_content;
};

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>LunchMealDialog</name>
<message>
<location filename="../lunchmealdialog.ui" line="14"/>
<source>Lunch meal</source>
<translation>Mittagsmenü</translation>
</message>
<message>
<location filename="../lunchmealdialog.ui" line="34"/>
<source>Loading...</source>
<translation>Lade...</translation>
</message>
<message>
<location filename="../lunchmealdialog.cpp" line="12"/>
<source>Lunch meal for %0</source>
<translation>Mittagsmenü vom %0</translation>
</message>
<message>
<location filename="../lunchmealdialog.cpp" line="12"/>
<source>dd.MM.yyyy</source>
<translation>dd.MM.yyyy</translation>
</message>
</context>
<context>
<name>LunchMealWidget</name>
<message>
<location filename="../lunchmealwidget.cpp" line="22"/>
<source>Lunch meal</source>
<translation>Mittagsmenü</translation>
</message>
<message>
<location filename="../lunchmealwidget.cpp" line="55"/>
<location filename="../lunchmealwidget.cpp" line="56"/>
<source>Could not load lunch meal!</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>LunchMealDialog</name>
<message>
<location filename="../lunchmealdialog.ui" line="14"/>
<source>Lunch meal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../lunchmealdialog.ui" line="34"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../lunchmealdialog.cpp" line="12"/>
<source>Lunch meal for %0</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../lunchmealdialog.cpp" line="12"/>
<source>dd.MM.yyyy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>LunchMealWidget</name>
<message>
<location filename="../lunchmealwidget.cpp" line="22"/>
<source>Lunch meal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../lunchmealwidget.cpp" line="55"/>
<location filename="../lunchmealwidget.cpp" line="56"/>
<source>Could not load lunch meal!</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>