diff --git a/translations/weatherplugin_de.ts b/translations/weatherplugin_de.ts new file mode 100644 index 0000000..18961a2 --- /dev/null +++ b/translations/weatherplugin_de.ts @@ -0,0 +1,42 @@ + + + + + WeatherWidget + + + Loading... + Lade... + + + + Request failed + Anfrage fehlgeschlagen + + + + Parsing failed + Parsen fehlgeschlagen + + + + Not an json obj + Kein json obj + + + + No weather found + Kein weather gefunden + + + + No main found + Kein main gefunden + + + + %0 (%1°C) + %0 (%1°C) + + + diff --git a/translations/weatherplugin_en.ts b/translations/weatherplugin_en.ts new file mode 100644 index 0000000..1c9d0aa --- /dev/null +++ b/translations/weatherplugin_en.ts @@ -0,0 +1,42 @@ + + + + + WeatherWidget + + + Loading... + + + + + Request failed + + + + + Parsing failed + + + + + Not an json obj + + + + + No weather found + + + + + No main found + + + + + %0 (%1°C) + + + + diff --git a/weatherplugin.cpp b/weatherplugin.cpp new file mode 100644 index 0000000..a09feee --- /dev/null +++ b/weatherplugin.cpp @@ -0,0 +1,42 @@ +#include "weatherplugin.h" + +#include +#include +#include +#include +#include + +#include "mainwindow.h" + +#include "weatherwidget.h" +#include "weathersettingswidget.h" + +WeatherPlugin::WeatherPlugin(QObject *parent) : + ZeiterfassungPlugin(parent) +{ + qDebug() << "called"; + + static auto dir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QStringLiteral("translations")); + + if(m_translator.load(QLocale(), QStringLiteral("weatherplugin"), QStringLiteral("_"), dir)) + { + if(!QCoreApplication::installTranslator(&m_translator)) + { + qWarning() << "could not install translation weatherplugin"; + } + } + else + { + qWarning() << "could not load translation weatherplugin"; + } +} + +void WeatherPlugin::attachTo(MainWindow &mainWindow) +{ + mainWindow.statusBar()->addWidget(new WeatherWidget(mainWindow)); +} + +SettingsWidget *WeatherPlugin::settingsWidget(ZeiterfassungSettings &settings, QWidget *parent) const +{ + return new WeatherSettingsWidget(settings, parent); +} diff --git a/weatherplugin.h b/weatherplugin.h new file mode 100644 index 0000000..f4fd64c --- /dev/null +++ b/weatherplugin.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include "zeiterfassungplugin.h" + +class SettingsWidget; +class ZeiterfassungSettings; + +class Q_DECL_EXPORT WeatherPlugin : public ZeiterfassungPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "dbsoftware.zeiterfassung.plugin/1.0" FILE "weatherplugin.json") + Q_INTERFACES(ZeiterfassungPlugin) + +public: + explicit WeatherPlugin(QObject *parent = Q_NULLPTR); + + // ZeiterfassungPlugin interface + void attachTo(MainWindow &mainWindow) Q_DECL_OVERRIDE; + + SettingsWidget *settingsWidget(ZeiterfassungSettings &settings, QWidget *parent = Q_NULLPTR) const Q_DECL_OVERRIDE; + +private: + QTranslator m_translator; +}; diff --git a/weatherplugin.json b/weatherplugin.json new file mode 100644 index 0000000..e69de29 diff --git a/weatherplugin.pro b/weatherplugin.pro new file mode 100644 index 0000000..4ef451c --- /dev/null +++ b/weatherplugin.pro @@ -0,0 +1,26 @@ +QT += core network gui widgets + +DBLIBS += zeiterfassungcore zeiterfassunggui + +TARGET = weatherplugin + +HEADERS += weatherplugin.h \ + weathersettings.h \ + weathersettingswidget.h \ + weatherwidget.h + +SOURCES += weatherplugin.cpp \ + weathersettings.cpp \ + weathersettingswidget.cpp \ + weatherwidget.cpp + +FORMS += + +RESOURCES += + +TRANSLATIONS += translations/weatherplugin_en.ts \ + translations/weatherplugin_de.ts + +OTHER_FILES += weatherplugin.json + +include(../plugin.pri) diff --git a/weathersettings.cpp b/weathersettings.cpp new file mode 100644 index 0000000..71332df --- /dev/null +++ b/weathersettings.cpp @@ -0,0 +1,42 @@ +#include "weathersettings.h" + +#include "zeiterfassungsettings.h" + +const QString WeatherSettings::m_url("WeatherPlugin/url"); +const QUrl WeatherSettings::m_defaultUrl(QStringLiteral("http://api.openweathermap.org/data/2.5/weather?q=Graz,AT&units=metric&APPID=40f6c892c6162680c6c9235169dc9f83")); + +WeatherSettings::WeatherSettings(ZeiterfassungSettings &settings, QObject *parent) : + QObject(parent), + m_settings(settings) +{ + +} + +QUrl WeatherSettings::url() const +{ + return m_settings.value(m_url, m_defaultUrl).toUrl(); +} + +bool WeatherSettings::setUrl(const QUrl &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; +} diff --git a/weathersettings.h b/weathersettings.h new file mode 100644 index 0000000..aa9fb2f --- /dev/null +++ b/weathersettings.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +class ZeiterfassungSettings; + +class WeatherSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) + +public: + WeatherSettings(ZeiterfassungSettings &settings, QObject *parent = Q_NULLPTR); + + QUrl url() const; + bool setUrl(const QUrl &url); + +Q_SIGNALS: + void saveErrorOccured(); + + void urlChanged(const QUrl &url); + +private: + ZeiterfassungSettings &m_settings; + + static const QString m_url; + static const QUrl m_defaultUrl; +}; diff --git a/weathersettingswidget.cpp b/weathersettingswidget.cpp new file mode 100644 index 0000000..35f3cb5 --- /dev/null +++ b/weathersettingswidget.cpp @@ -0,0 +1,32 @@ +#include "weathersettingswidget.h" + +#include +#include + +WeatherSettingsWidget::WeatherSettingsWidget(ZeiterfassungSettings &settings, QWidget *parent) : + SettingsWidget(parent), + m_settings(settings) +{ + auto layout = new QFormLayout(this); + layout->setMargin(0); + + m_lineEdit = new QLineEdit(m_settings.url().toString(), this); + layout->addRow(tr("Weather API:"), m_lineEdit); + + setLayout(layout); +} + +bool WeatherSettingsWidget::isValid(QString &message) const +{ + auto valid = QUrl::fromUserInput(m_lineEdit->text()).isValid(); + + if(!valid) + message = tr("The weather api url is invalid!"); + + return valid; +} + +bool WeatherSettingsWidget::apply() +{ + return m_settings.setUrl(QUrl::fromUserInput(m_lineEdit->text())); +} diff --git a/weathersettingswidget.h b/weathersettingswidget.h new file mode 100644 index 0000000..7936f48 --- /dev/null +++ b/weathersettingswidget.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "settingswidget.h" + +#include "weathersettings.h" + +class QLineEdit; + +class ZeiterfassungSettings; + +class WeatherSettingsWidget : public SettingsWidget +{ + Q_OBJECT + +public: + explicit WeatherSettingsWidget(ZeiterfassungSettings &settings, QWidget *parent = Q_NULLPTR); + + bool isValid(QString &message) const Q_DECL_OVERRIDE; + +public Q_SLOTS: + virtual bool apply() Q_DECL_OVERRIDE; + +private: + WeatherSettings m_settings; + + QLineEdit *m_lineEdit; +}; diff --git a/weatherwidget.cpp b/weatherwidget.cpp new file mode 100644 index 0000000..9d62b09 --- /dev/null +++ b/weatherwidget.cpp @@ -0,0 +1,92 @@ +#include "weatherwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "zeiterfassungsettings.h" +#include "zeiterfassungapi.h" + +#include "weathersettings.h" + +WeatherWidget::WeatherWidget(MainWindow &mainWindow) : + QLabel(&mainWindow), + m_mainWindow(mainWindow) +{ + setFrameShape(QFrame::Panel); + setFrameShadow(QFrame::Sunken); + + connect(&m_mainWindow, &MainWindow::refreshEverything, this, &WeatherWidget::refresh); + + refresh(); +} + +void WeatherWidget::refresh() +{ + setText(tr("Loading...")); + + auto url = WeatherSettings(m_mainWindow.settings()).url(); + + m_reply = std::unique_ptr(m_mainWindow.erfassung().manager()->get(QNetworkRequest(url))); + connect(m_reply.get(), &QNetworkReply::finished, this, &WeatherWidget::finished); +} + +void WeatherWidget::finished() +{ + if(m_reply->error() != QNetworkReply::NoError) + { + qWarning() << m_reply->errorString(); + setText(tr("Request failed")); + goto after; + } + + { + QJsonParseError error; + + auto document = QJsonDocument::fromJson(m_reply->readAll(), &error); + if(error.error != QJsonParseError::NoError) + { + qWarning() << error.errorString(); + setText(tr("Parsing failed")); + goto after; + } + + if(!document.isObject()) + { + setText(tr("Not an json obj")); + goto after; + } + + auto obj = document.object(); + + if(!obj.contains(QStringLiteral("weather"))) + { + qWarning() << "no weather" << obj; + setText(tr("No weather found")); + goto after; + } + + if(!obj.contains(QStringLiteral("main"))) + { + qWarning() << "no main" << obj; + setText(tr("No main found")); + goto after; + } + + auto weaterObj = obj.value(QStringLiteral("weather")).toArray(); + auto mainObj = obj.value(QStringLiteral("main")).toObject(); + + setText(tr("%0 (%1°C)").arg(weaterObj.first().toObject().value(QStringLiteral("main")).toString()) + .arg(mainObj.value(QStringLiteral("temp")).toDouble())); + } + + after: + m_reply = Q_NULLPTR; +} diff --git a/weatherwidget.h b/weatherwidget.h new file mode 100644 index 0000000..8a3a2f7 --- /dev/null +++ b/weatherwidget.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include +#include + +class MainWindow; + +class WeatherWidget : public QLabel +{ + Q_OBJECT + +public: + explicit WeatherWidget(MainWindow &mainWindow); + +private Q_SLOTS: + void refresh(); + void finished(); + +private: + MainWindow &m_mainWindow; + + std::unique_ptr m_reply; +};