6 Commits

Author SHA1 Message Date
1a51eda00a Testing 123
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 5s
2025-04-07 21:16:47 +02:00
fa5f6b2588 Add weather routes project progress 2025-04-07 19:40:38 +02:00
8941d84bc8 updated dockerfile to reduce filesize to 2 Gb + updated pipeline to use local ip for runners to skip cloudflare limitations 2025-04-07 19:34:32 +02:00
39b594b0b2 Update .gitea/workflows/build-container.yaml
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
test local ip to push without uploading limits
2025-04-02 18:14:59 +00:00
e63985083c add automatic build of devcontainer if it changes
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 49m18s
2025-03-31 22:08:50 +02:00
bb0450ad69 Added devcontainer config and docker with development environment 2025-03-31 21:48:22 +02:00
57 changed files with 2187 additions and 1 deletions

81
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,81 @@
# Use the official Alpine Linux image
FROM alpine:3.21
# Install dependencies for Android SDK and Qt build tools
RUN apk update && \
apk add --no-cache \
bash \
build-base \
cmake \
git \
curl \
unzip \
openjdk17 \
libx11 \
libxcomposite \
libxrandr \
libxcursor \
libxi \
mesa-dev \
libusb
# Set environment variables for Qt and Android SDK
ENV QT_VERSION=6.8.0
ENV QT_INSTALL_PATH=/opt/qt-${QT_VERSION}
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk
ENV ANDROID_SDK_ROOT=/opt/android-sdk
ENV PATH="${QT_INSTALL_PATH}/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${ANDROID_SDK_ROOT}/emulator:${ANDROID_SDK_ROOT}/tools:${ANDROID_SDK_ROOT}/tools/bin:${JAVA_HOME}/bin:$PATH"
# Download and install Qt 6.8.0 from the official Qt website
RUN mkdir -p ${QT_INSTALL_PATH} && \
cd ${QT_INSTALL_PATH} && \
wget https://download.qt.io/archive/qt/6.8/6.8.0/single/qt-everywhere-src-${QT_VERSION}.tar.xz && \
tar -xf qt-everywhere-src-${QT_VERSION}.tar.xz && \
rm qt-everywhere-src-${QT_VERSION}.tar.xz && \
cd qt-everywhere-src-${QT_VERSION} && \
./configure -prefix ${QT_INSTALL_PATH} \
-nomake examples \
-nomake tests \
-nomake benchmarks \
-optimized-qmake \
-commercial -confirm-license \
-skip qt3d \
-skip qtdatavis3d \
-skip qtgamepad \
-skip qtlottie \
-skip qtnetworkauth \
-skip qtquicktimeline \
-skip qtsensors \
-skip qtspeech \
-skip qtwebchannel \
-skip qtwebengine \
-skip qtwebglplugin \
-release \
-optimize-size && \
make -j$(nproc) && \
make install && \
rm -rf ${QT_INSTALL_PATH}/qt-everywhere-src-${QT_VERSION}
# Install Android SDK Command Line Tools
RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \
curl -o sdk-tools-linux.zip https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip && \
unzip sdk-tools-linux.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools && \
rm sdk-tools-linux.zip && \
mv ${ANDROID_SDK_ROOT}/cmdline-tools/cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest
# Install required Android SDK components
RUN yes | sdkmanager --licenses && \
sdkmanager --update && \
sdkmanager "platform-tools" "platforms;android-33" "build-tools;33.0.2"
# Verify SDK installation
RUN sdkmanager --list
# Set working directory
WORKDIR /workspace
# Expose ADB debugging port
EXPOSE 5555
# Start bash as the default command
CMD ["/bin/bash"]

View File

@@ -0,0 +1,25 @@
{
"name": "Qt 6.8.0 Development Container",
"build": {
"dockerfile": "Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"extensions": [
"ms-vscode.cmake-tools",
"ms-vscode.cpptools",
"ms-vscode.makefile-tools",
"androidtool.android",
"ms-azuretools.vscode-docker"
]
}
},
"forwardPorts": [8080],
"mounts": [
"source=${localWorkspaceFolder},target=/workspace,type=bind"
]
}

View File

@@ -0,0 +1,28 @@
name: Build and Push Docker Image
on:
push:
branches:
- 'main'
paths:
- '**/Dockerfile'
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log into Gitea Container Registry
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ secrets.LOCAL_INSTANCE_IP }} -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Build Docker image
run: |
docker build -t ${{ secrets.LOCAL_INSTANCE_IP }}/${{ secrets.DOCKER_USERNAME }}/devcontainer:latest -f .devcontainer/Dockerfile .
- name: Push Docker image
run: |
docker push ${{ secrets.LOCAL_INSTANCE_IP }}/${{ secrets.DOCKER_USERNAME }}/devcontainer:latest

View File

@@ -0,0 +1,25 @@
name: Build and Push Docker Image
on:
push:
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log into Gitea Container Registry
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ vars.LOCAL_INSTANCE_IP }} -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Build Docker image
run: |
docker pull hello-world
docker tag docker.io/library/hello-world:latest ${{ vars.LOCAL_INSTANCE_IP }}/${{ secrets.DOCKER_USERNAME }}/hello-world:latest
- name: Push Docker image
run: |
docker push ${{ vars.LOCAL_INSTANCE_IP }}/${{ secrets.DOCKER_USERNAME }}/hello-world:latest

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 silklaasboer
Copyright (c) 2025 silklaasboer & pavankumar bellary
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -0,0 +1,81 @@
cmake_minimum_required(VERSION 3.16)
project(WeatherRoutes VERSION 0.1 LANGUAGES CXX)
# Define versioning information
set(VERSION_CODE 1) # Change this to your desired version code
set(VERSION_NAME "0.1") # Your version name
# Include this in the Android section
set(ANDROID_PACKAGE_NAME "com.example.weatherroutes")
set(ANDROID_VERSION_CODE ${VERSION_CODE})
set(ANDROID_VERSION_NAME ${VERSION_NAME})
set(CMAKE_ANDROID_MANIFEST "${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml")
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(RESOURCE_FILES resources.qrc)
find_package(Qt6 REQUIRED COMPONENTS Quick)
find_package(Qt6 REQUIRED COMPONENTS Core)
find_package(Qt6 REQUIRED COMPONENTS Location)
find_package(Qt6 REQUIRED COMPONENTS Positioning)
find_package(Qt6 REQUIRED COMPONENTS Network)
qt_add_resources(RESOURCES_RCC "${RESOURCE_FILES}")
qt_add_executable(appWeatherRoutes
main.cpp
${RESOURCES_RCC}
)
qt_add_qml_module(appWeatherRoutes
URI WeatherRoutes
VERSION 1.0
QML_FILES
Main.qml
SOURCES
QML_FILES
QML_FILES qml/WaypointData.qml
QML_FILES qml/WeatherDetailsView.qml
QML_FILES qml/CustomInputField.qml
QML_FILES qml/MapView.qml
QML_FILES
QML_FILES qml/HomeScreen.qml
SOURCES mvc/data/waypoint.h mvc/data/waypoint.cpp
SOURCES mvc/data/mapdata.cpp mvc/data/mapdata.h
SOURCES mvc/model/mapdatamodel.h mvc/model/mapdatamodel.cpp
SOURCES mvc/data/weatherdetailsdata.h mvc/data/weatherdetailsdata.cpp
SOURCES mvc/enums/weatherstatus.h
SOURCES mvc/data/weatherdata.h mvc/data/weatherdata.cpp
SOURCES mvc/controller/weathercontroller.h mvc/controller/weathercontroller.cpp
SOURCES mvc/controller/networkmanager.h mvc/controller/networkmanager.cpp
SOURCES mvc/controller/stylecontroller.h mvc/controller/stylecontroller.cpp
)
target_include_directories(appWeatherRoutes
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/mvc
)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appWeatherRoutes PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appWeatherRoutes
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appWeatherRoutes PRIVATE Qt6::Quick Qt6::Location Qt6::Positioning)
set(CMAKE_AUTORCC ON)
include(GNUInstallDirs)
install(TARGETS appWeatherRoutes
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

17
WeatherRoutes/Main.qml Normal file
View File

@@ -0,0 +1,17 @@
import QtQuick
import QtQuick.Controls
import QtLocation
import QtPositioning
ApplicationWindow {
visible: true
width: Qt.platform.os == "android" ? Screen.width : 360
height: Qt.platform.os == "android" ? Screen.height : 640
title: "Weather Routes"
HomeScreen
{
id: homeScreen
anchors.fill: parent
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.weatherroutes" android:versionCode="" android:versionName="">
<application android:label="WeatherRoutes">
<activity
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:label="@string/appWeatherRoutes"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|direction|density|uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
</manifest>

14
WeatherRoutes/generate.py Normal file
View File

@@ -0,0 +1,14 @@
import os
resource_file = "resources.qrc"
image_folder = "images"
with open(resource_file, "w") as f:
f.write('<!DOCTYPE RCC><RCC version="1.0">\n<qresource prefix="">\n')
for root, _, files in os.walk(image_folder):
for file in files:
if file.endswith('.png'):
f.write(f' <file>{os.path.join(image_folder, file)}</file>\n')
f.write('</qresource>\n</RCC>\n')
print(f"{resource_file} has been generated.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

View File

@@ -0,0 +1,11 @@
<svg width="306" height="400" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" version="1.1">
<g>
<title>Layer 1</title>
<g id="_x31_57_x2C__Twitter_x2C__Location_x2C__Map">
<g id="svg_4">
<path id="svg_3" fill="#FF7979" d="m153.31529,-0.17747c84.87,0 153.81,68.94 153.81,153.96c0,77.059 -87.02,195.03 -153.2,246.04c-85.33,-69.24 -154.58,-167.75 -154.58,-246.04c0,-85.021 68.94,-153.96 153.97,-153.96zm74.79,150.799c0,-41.34 -33.521,-74.86 -74.87,-74.86c-41.35,0 -74.86,33.52 -74.86,74.86c0,41.35 33.51,74.87 74.86,74.87c41.35,0 74.87,-33.52 74.87,-74.87z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

65
WeatherRoutes/main.cpp Normal file
View File

@@ -0,0 +1,65 @@
#include "controller/networkmanager.h"
#include "controller/weathercontroller.h"
#include "data/mapdata.h"
#include "data/weatherdetailsdata.h"
#include "controller/weathercontroller.h"
#include "controller/networkmanager.h"
#include "enums/weatherstatus.h"
#include <QGuiApplication>
#include <QLocationPermission>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[]) {
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
#endif
QGuiApplication app(argc, argv);
QLocationPermission permission;
permission.setAccuracy(QLocationPermission::Precise);
permission.setAvailability(QLocationPermission::WhenInUse);
switch (qApp->checkPermission(permission)) {
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(permission, [](const QPermission &permission) {
if (permission.status() == Qt::PermissionStatus::Granted) {
qDebug() << "Permission granted !!";
}
});
case Qt::PermissionStatus::Granted:
case Qt::PermissionStatus::Denied:
break;
}
QQmlApplicationEngine engine;
MapData mapData;
mapData.setDefaultZoomLevel(15);
mapData.setZoomLevel(mapData.defaultZoomLevel());
mapData.setGpsUpdateInterval(1000);
engine.rootContext()->setContextProperty("mapData", &mapData);
WeatherController ctrl;
std::shared_ptr<WeatherController> weatherCntrl =
std::make_shared<WeatherController>();
ctrl.parseJSONData();
WeatherDetailsData weatherDetailsData(weatherCntrl);
engine.rootContext()->setContextProperty("weatherDetailsData",
&weatherDetailsData);
engine.rootContext()->setContextProperty("networkManager",
NetworkManager::Instance());
const QUrl url(QStringLiteral("qrc:/WeatherRoutes/Main.qml"));
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

View File

@@ -0,0 +1,42 @@
#include "networkmanager.h"
#include "QStandardPaths"
#include <QFile>
#include <QGuiApplication>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
NetworkManager *NetworkManager::m_instance;
NetworkManager::NetworkManager(QObject *parent) : QObject{parent} {}
NetworkManager *NetworkManager::Instance() {
if (m_instance != nullptr) {
return m_instance;
}
m_instance = new NetworkManager();
return m_instance;
}
void NetworkManager::fetchJSONfromAPI(QUrl url, QJsonDocument &doc)
{
qDebug() << "Fetch URL::" << url.toDisplayString();
QNetworkAccessManager m_manager;
QNetworkRequest request(url);
QNetworkReply *reply = m_manager.get(request);
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError)
{
QByteArray response = reply->readAll();
doc = QJsonDocument::fromJson(response);
}
else
{
qDebug() << "Invalid JSON response:: " << reply->errorString();
}
reply->deleteLater();
}

View File

@@ -0,0 +1,22 @@
#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H
#include <QObject>
class NetworkManager : public QObject {
Q_OBJECT
public:
void fetchJSONfromAPI(QUrl url, QJsonDocument &doc);
static NetworkManager *m_instance;
static NetworkManager *Instance();
NetworkManager(const NetworkManager&) = delete;
NetworkManager& operator=(const NetworkManager&) = delete;
signals:
private:
explicit NetworkManager(QObject *parent = nullptr);
};
#endif // NETWORKMANAGER_H

View File

@@ -0,0 +1,30 @@
#include "stylecontroller.h"
StyleController* StyleController::m_instance;
StyleController *StyleController::Instance()
{
if(m_instance != nullptr)
{
return m_instance;
}
m_instance = new StyleController();
return m_instance;
}
StyleController::StyleController(QObject *parent)
: QObject{parent}
{}
int StyleController::colorMode() const
{
return m_colorMode;
}
void StyleController::setColorMode(int newColorMode)
{
if (m_colorMode == newColorMode)
return;
m_colorMode = newColorMode;
emit colorModeChanged();
}

View File

@@ -0,0 +1,59 @@
#ifndef STYLECONTROLLER_H
#define STYLECONTROLLER_H
#include <QObject>
#include <QColor>
class StyleController : public QObject
{
Q_OBJECT
public:
static StyleController* m_instance;
StyleController(const StyleController&) = delete;
StyleController& operator=(const StyleController&) = delete;
StyleController* Instance();
enum COLOR_MODE
{
DARK = 0,
LIGHT,
SYSTEM
}
Q_ENUMS(COLOR_MODE);
Q_PROPERTY(int colorMode READ colorMode WRITE setColorMode NOTIFY colorModeChanged FINAL)
//Dark Mode
Q_PROPERTY(QColor textPrimary READ textPrimary NOTIFY colorChanged FINAL)
QColor textPrimary() const {return QColor(255,255,255);}
Q_PROPERTY(QColor textSecondary READ textSecondary NOTIFY colorChanged FINAL)
QColor textSecondary() const {return QColor(255,255,255,179);}
Q_PROPERTY(QColor textDisabled READ textDisabled NOTIFY colorChanged FINAL)
QColor textDisabled() const {return QColor(255,255,255,125);}
Q_PROPERTY(QColor buttonActive READ buttonActive NOTIFY colorChanged FINAL)
QColor buttonActive() const {return QColor(255,255,255);}
Q_PROPERTY(QColor buttonDisabled READ buttonDisabled NOTIFY colorChanged FINAL)
QColor buttonDisabled() const {return QColor(255,255,255, 77);}
Q_PROPERTY(QColor buttonSelected READ buttonSelected NOTIFY colorChanged FINAL)
QColor buttonSelected() const {return QColor(255,255,255, 40);}
int colorMode() const;
void setColorMode(int newColorMode);
signals:
void colorChanged();
void colorModeChanged();
private:
explicit StyleController(QObject *parent = nullptr);
int m_colorMode = COLOR_MODE::DARK;
};
#endif // STYLECONTROLLER_H

View File

@@ -0,0 +1,224 @@
#include "weathercontroller.h"
#include "QDir"
#include "QFile"
#include "QGuiApplication"
#include "QStandardPaths"
#include "networkmanager.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <qdebug.h>
const QString WeatherController::FILENAME = "static.json";
WeatherController::WeatherController(QObject *parent) : QObject{parent} {}
bool WeatherController::parseJSONData() {
QJsonDocument doc;
if (this->checkToDownload(doc)) {
QJsonObject jsonObject = doc.object();
QJsonArray dataArray = jsonObject["data"].toArray();
for (QJsonArray::const_iterator iter = dataArray.constBegin();
iter != dataArray.constEnd(); ++iter) {
QJsonObject weatherObject = (*iter).toObject();
// Extract values from the JSON object
long tijd = weatherObject["tijd"].toString().toLong();
QString tijd_nl = weatherObject["tijd_nl"].toString();
int offset = weatherObject["offset"].toInt();
float temp = weatherObject["temp"].toString().toFloat();
int wind_ms = weatherObject["windb"].toInt();
int wind_bf = weatherObject["winds"].toInt();
int wind_knp = weatherObject["windknp"].toInt();
int wind_kmh = weatherObject["windkmh"].toString().toFloat();
int wind_r = weatherObject["windr"].toInt();
QString wind_ltr = weatherObject["windrltr"].toString();
int visibility = weatherObject["vis"].toInt();
int neersl = weatherObject["neersl"].toString().toFloat() *
10; // Converted from 0.1 to 1 decimal scale
float luchtd_bar = weatherObject["luchtd"].toString().toFloat();
float luchtdmmhg = weatherObject["luchtdmmhg"].toString().toFloat();
float luchtdinHg = weatherObject["luchtdinhg"].toString().toFloat();
int hw = weatherObject["hw"].toInt();
int mw = weatherObject["mw"].toInt();
int lw = weatherObject["lw"].toInt();
int tw = weatherObject["tw"].toInt();
int rv = weatherObject["rv"].toInt();
int gr = weatherObject["gr"].toInt();
int gr_w = weatherObject["gr_w"].toInt();
QString cape = weatherObject["cape"].toString();
int snd = weatherObject["snd"].toInt();
int snv = weatherObject["snv"].toInt();
int cond = weatherObject["cond"].toInt();
int iconCode = weatherObject["ico"].toInt();
QString sameenv = weatherObject["samenv"].toString();
QString icoon = weatherObject["icoon"].toString();
// Create WeatherData object and add it to the list using initializer list
// constructor
mData.append(WeatherData(tijd, tijd_nl, offset, temp, wind_ms, wind_bf,
wind_knp, wind_kmh, wind_r, wind_ltr, visibility,
neersl, luchtd_bar, luchtdmmhg, luchtdinHg, hw,
mw, lw, tw, rv, gr, gr_w, cape, snd, snv, cond,
iconCode, sameenv, icoon));
}
}
else
return false;
return true;
}
QJsonObject WeatherController::fetchCurrentWeatherData(const QGeoCoordinate &coord)
{
QJsonDocument doc;
readWeatherData(doc, "liveweer");
QJsonArray liveweerArray = doc.array();
QJsonObject firstEntry = liveweerArray.at(0).toObject();
//Will fetch live data when the time difference is more than 10 mins from last fetch
if (qAbs(QDateTime::currentSecsSinceEpoch() - firstEntry["timestamp"].toString().toUInt()) > 600)
{
// NetworkManager::Instance()->fetchJSONfromAPI(prepareURL(coord), doc);
// if(!doc.isNull() && doc.isObject())
// {
// updateWeatherData(doc);
// }
}
return doc.object();
}
bool WeatherController::readWeatherData(QJsonDocument &doc, QString objName)
{
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
QString fileName = cacheDir + "/" + WeatherController::FILENAME;
QFile file(fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
QJsonParseError error;
doc = QJsonDocument::fromJson(in.readAll().toStdString().c_str(), &error);
file.close();
if(doc.isNull())
{
qWarning() << "Error:: " << error.errorString();
return false;
}
if (!doc.isObject()) {
qWarning() << "Invalid JSON format";
return false;
}
if(!objName.isNull())
{
QJsonArray ary = doc.object()[objName].toArray();
QJsonDocument temp_doc(ary);
doc = temp_doc;
}
}
return true;
}
bool WeatherController::saveWeatherData(QJsonDocument &doc)
{
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
// Ensure the directory exists
QDir dir(cacheDir);
if (!dir.exists()) {
dir.mkpath(cacheDir);
}
QString fileName = cacheDir + "/" + WeatherController::FILENAME;
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << doc.toJson();
file.close();
qDebug() << "Data saved to hidden cache file.";
return true;
} else {
qDebug() << "Failed to open file for writing";
return false;
}
}
bool WeatherController::fetchWeatherData(QUrl url, QJsonDocument &doc)
{
NetworkManager::Instance()->fetchJSONfromAPI(url, doc);
if (doc.isObject() && !doc.isNull()) {
QJsonObject jsonObject = doc.object();
QString todayDate = QDate::currentDate().toString("dd-MM-yyyy");
jsonObject["downloaddatum"] = todayDate;
QString timeOfDownload = QDateTime::currentDateTime().toString("hh:mm:ss");
jsonObject["downloadtime"] = timeOfDownload;
QJsonDocument updatedDoc(jsonObject);
saveWeatherData(updatedDoc);
}
return true;
}
void WeatherController::updateWeatherData(QJsonDocument &inputDoc)
{
QJsonDocument doc;
readWeatherData(doc);
QJsonObject rootObj = doc.object();
QJsonObject inputObj = inputDoc.object();
QJsonArray liveweerArray = inputObj["liveweer"].toArray();
rootObj["liveweer"] = liveweerArray;
QJsonDocument updatedDoc(rootObj);
saveWeatherData(updatedDoc);
}
QUrl WeatherController::prepareURL(const QString &plaats)
{
return QUrl(QString("http://data.meteoserver.nl/api/uurverwachting.php?locatie=%1&key=785f0630f0").arg(plaats));
}
QUrl WeatherController::prepareURL(const QGeoCoordinate &coord)
{
return QUrl(QString("http://data.meteoserver.nl/api/liveweer_synop.php?lat=%1&long=%2&key=785f0630f0&select=1").arg(coord.latitude()).arg(coord.longitude()));
}
bool WeatherController::checkToDownload(QJsonDocument &doc)
{
bool toDownloadData = false;
readWeatherData(doc);
if (doc.isObject() && !doc.isNull()) {
// Get the root object
QJsonObject jsonObject = doc.object();
// Extract the 'downloaddatum' value
QString downloaddatum = jsonObject.value("downloaddatum").toString();
if(downloaddatum != QDate::currentDate().toString("dd-MM-yyyy"))
toDownloadData = true;
QJsonArray plaatsnaamArray = jsonObject.value("plaatsnaam").toArray();
if (!plaatsnaamArray.isEmpty()) {
QJsonObject plaatsObject = plaatsnaamArray.at(0).toObject();
QString plaats = plaatsObject.value("plaats").toString();
if(plaats != "Raalte")
toDownloadData = true;
} else {
qWarning() << "plaatsnaam array is empty";
return false;
}
} else {
qWarning() << "Failed to open file for reading";
return false;
}
if(toDownloadData)
return fetchWeatherData(prepareURL("Raalte"), doc);
return false;
}

View File

@@ -0,0 +1,30 @@
#ifndef WEATHERCONTROLLER_H
#define WEATHERCONTROLLER_H
#include "../data/weatherdata.h"
#include <QGeoCoordinate>
#include <QObject>
class WeatherController : public QObject {
Q_OBJECT
public:
explicit WeatherController(QObject *parent = nullptr);
static const QString FILENAME;
bool parseJSONData();
QJsonObject fetchCurrentWeatherData(const QGeoCoordinate &coord);
signals:
private:
bool readWeatherData(QJsonDocument &doc, QString objName = NULL);
bool checkToDownload(QJsonDocument &doc);
bool saveWeatherData(QJsonDocument &doc);
bool fetchWeatherData(QUrl url, QJsonDocument &doc);
void updateWeatherData(QJsonDocument &inputDoc);
QUrl prepareURL(const QString &plaats);
QUrl prepareURL(const QGeoCoordinate &coord);
QList<WeatherData> mData;
};
#endif // WEATHERCONTROLLER_H

View File

@@ -0,0 +1,42 @@
#include "mapdata.h"
MapData::MapData(QObject *parent) : QObject{parent} {}
QList<std::unique_ptr<Waypoint>> MapData::waypoints() const {
return m_waypoints;
}
void MapData::setWaypoints(
const QList<std::unique_ptr<Waypoint>> &newWaypoints) {
if (m_waypoints == newWaypoints)
return;
m_waypoints = newWaypoints;
emit waypointsChanged();
}
int MapData::zoomLevel() const { return m_zoomLevel; }
void MapData::setZoomLevel(int newZoomLevel) {
if (m_zoomLevel == newZoomLevel)
return;
m_zoomLevel = newZoomLevel;
emit zoomLevelChanged();
}
int MapData::gpsUpdateInterval() const { return m_gpsUpdateInterval; }
void MapData::setGpsUpdateInterval(int newGpsUpdateInterval) {
if (m_gpsUpdateInterval == newGpsUpdateInterval)
return;
m_gpsUpdateInterval = newGpsUpdateInterval;
emit gpsUpdateIntervalChanged();
}
int MapData::defaultZoomLevel() const { return m_defaultZoomLevel; }
void MapData::setDefaultZoomLevel(int newDefaultZoomLevel) {
if (m_defaultZoomLevel == newDefaultZoomLevel)
return;
m_defaultZoomLevel = newDefaultZoomLevel;
emit defaultZoomLevelChanged();
}

View File

@@ -0,0 +1,46 @@
#ifndef MAPDATA_H
#define MAPDATA_H
#include "waypoint.h"
#include <QObject>
class MapData : public QObject {
Q_OBJECT
public:
explicit MapData(QObject *parent = nullptr);
Q_PROPERTY(QList<std::unique_ptr<Waypoint>> waypoints READ waypoints WRITE
setWaypoints NOTIFY waypointsChanged FINAL)
Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY
zoomLevelChanged FINAL)
Q_PROPERTY(int gpsUpdateInterval READ gpsUpdateInterval WRITE
setGpsUpdateInterval NOTIFY gpsUpdateIntervalChanged FINAL)
Q_PROPERTY(int defaultZoomLevel READ defaultZoomLevel NOTIFY
defaultZoomLevelChanged FINAL)
QList<std::unique_ptr<Waypoint>> waypoints() const;
void setWaypoints(const QList<std::unique_ptr<Waypoint>> &newWaypoints);
int zoomLevel() const;
void setZoomLevel(int newZoomLevel);
int gpsUpdateInterval() const;
void setGpsUpdateInterval(int newGpsUpdateInterval);
int defaultZoomLevel() const;
void setDefaultZoomLevel(int newDefaultZoomLevel);
signals:
void waypointsChanged();
void zoomLevelChanged();
void gpsUpdateIntervalChanged();
void defaultZoomLevelChanged();
private:
QList<std::unique_ptr<Waypoint>> m_waypoints;
int m_zoomLevel;
int m_gpsUpdateInterval;
int m_defaultZoomLevel;
};
#endif // MAPDATA_H

View File

@@ -0,0 +1,16 @@
#include "waypoint.h"
Waypoint::Waypoint(QObject *parent) : QObject{parent} {}
Waypoint::Waypoint(const double latitude, const double longitude)
: m_latitude(latitude), m_longitude(longitude), m_altitude(0) {}
Waypoint::Waypoint(const double latitude, const double longitude,
WeatherData &data)
: m_latitude(latitude), m_longitude(longitude), m_altitude(0),
m_data(data) {}
Waypoint::Waypoint(const double latitude, const double longitude,
const double altitude, WeatherData &data)
: m_latitude(latitude), m_longitude(longitude), m_altitude(altitude),
m_data(data) {}

View File

@@ -0,0 +1,23 @@
#ifndef WAYPOINT_H
#define WAYPOINT_H
#include "weatherdata.h"
#include <QObject>
class Waypoint : public QObject {
Q_OBJECT
public:
explicit Waypoint(QObject *parent = nullptr);
Waypoint(const double latitude, const double longitude);
Waypoint(const double latitude, const double longitude, WeatherData &data);
Waypoint(const double latitude, const double longitude, const double altitude,
WeatherData &data);
private:
double m_latitude;
double m_longitude;
double m_altitude;
WeatherData m_data;
};
#endif // WAYPOINT_H

View File

@@ -0,0 +1,331 @@
#include "weatherdata.h"
WeatherData::WeatherData(QObject *parent) : QObject{parent} {}
WeatherData::WeatherData(long tijd, const QString &tijd_nl, int offset,
float temp, int wind_ms, int wind_bf, int wind_knp,
int wind_kmh, int wind_r, const QString &wind_ltr,
int visibility, int neersl, float luchtd_bar,
float luchtdmmhg, float luchtdinHg, int hw, int mw,
int lw, int tw, int rv, int gr, int gr_w,
const QString &cape, int snd, int snv, int cond,
int iconCode, const QString &sameenv,
const QString &icoon)
: m_tijd(tijd), m_tijd_nl(tijd_nl), m_offset(offset), m_temp(temp),
m_wind_ms(wind_ms), m_wind_bf(wind_bf), m_wind_knp(wind_knp),
m_wind_kmh(wind_kmh), m_wind_r(wind_r), m_wind_ltr(wind_ltr),
m_visibility(visibility), m_neersl(neersl), m_luchtd_bar(luchtd_bar),
m_luchtdmmhg(luchtdmmhg), m_luchtdinHg(luchtdinHg), m_hw(hw), m_mw(mw),
m_lw(lw), m_tw(tw), m_rv(rv), m_gr(gr), m_gr_w(gr_w), m_cape(cape),
m_snd(snd), m_snv(snv), m_cond(cond), m_iconCode(iconCode),
m_sameenv(sameenv), m_icoon(icoon) {}
WeatherData::WeatherData(const WeatherData &other)
: m_tijd(other.m_tijd), m_tijd_nl(other.m_tijd_nl),
m_offset(other.m_offset), m_temp(other.m_temp),
m_wind_ms(other.m_wind_ms), m_wind_bf(other.m_wind_bf),
m_wind_knp(other.m_wind_knp), m_wind_kmh(other.m_wind_kmh),
m_wind_r(other.m_wind_r), m_wind_ltr(other.m_wind_ltr),
m_visibility(other.m_visibility), m_neersl(other.m_neersl),
m_luchtd_bar(other.m_luchtd_bar), m_luchtdmmhg(other.m_luchtdmmhg),
m_luchtdinHg(other.m_luchtdinHg), m_hw(other.m_hw), m_mw(other.m_mw),
m_lw(other.m_lw), m_tw(other.m_tw), m_rv(other.m_rv), m_gr(other.m_gr),
m_gr_w(other.m_gr_w), m_cape(other.m_cape), m_snd(other.m_snd),
m_snv(other.m_snv), m_cond(other.m_cond), m_iconCode(other.m_iconCode),
m_sameenv(other.m_sameenv), m_icoon(other.m_icoon) {}
WeatherData WeatherData::operator=(const WeatherData &other) {
m_tijd = (other.m_tijd);
m_tijd_nl = (other.m_tijd_nl);
m_offset = (other.m_offset);
m_temp = (other.m_temp);
m_wind_ms = (other.m_wind_ms);
m_wind_bf = (other.m_wind_bf);
m_wind_knp = (other.m_wind_knp);
m_wind_kmh = (other.m_wind_kmh);
m_wind_r = (other.m_wind_r);
m_wind_ltr = (other.m_wind_ltr);
m_visibility = (other.m_visibility);
m_neersl = (other.m_neersl);
m_luchtd_bar = (other.m_luchtd_bar);
m_luchtdmmhg = (other.m_luchtdmmhg);
m_luchtdinHg = (other.m_luchtdinHg);
m_hw = (other.m_hw);
m_mw = (other.m_mw);
m_lw = (other.m_lw);
m_tw = (other.m_tw);
m_rv = (other.m_rv);
m_gr = (other.m_gr);
m_gr_w = (other.m_gr_w);
m_cape = (other.m_cape);
m_snd = (other.m_snd);
m_snv = (other.m_snv);
m_cond = (other.m_cond);
m_iconCode = (other.m_iconCode);
m_sameenv = (other.m_sameenv);
m_icoon = (other.m_icoon);
return *this;
}
long WeatherData::tijd() const { return m_tijd; }
void WeatherData::setTijd(long newTijd) {
if (m_tijd == newTijd)
return;
m_tijd = newTijd;
emit tijdChanged();
}
QString WeatherData::tijd_nl() const { return m_tijd_nl; }
void WeatherData::setTijd_nl(const QString &newTijd_nl) {
if (m_tijd_nl == newTijd_nl)
return;
m_tijd_nl = newTijd_nl;
emit tijd_nlChanged();
}
int WeatherData::offset() const { return m_offset; }
void WeatherData::setOffset(int newOffset) {
if (m_offset == newOffset)
return;
m_offset = newOffset;
emit offsetChanged();
}
float WeatherData::temp() const { return m_temp; }
void WeatherData::setTemp(float newTemp) {
if (qFuzzyCompare(m_temp, newTemp))
return;
m_temp = newTemp;
emit tempChanged();
}
int WeatherData::wind_ms() const { return m_wind_ms; }
void WeatherData::setWind_ms(int newWind_ms) {
if (m_wind_ms == newWind_ms)
return;
m_wind_ms = newWind_ms;
emit wind_msChanged();
}
int WeatherData::wind_bf() const { return m_wind_bf; }
void WeatherData::setWind_bf(int newWind_bf) {
if (m_wind_bf == newWind_bf)
return;
m_wind_bf = newWind_bf;
emit wind_bfChanged();
}
int WeatherData::wind_knp() const { return m_wind_knp; }
void WeatherData::setWind_knp(int newWind_knp) {
if (m_wind_knp == newWind_knp)
return;
m_wind_knp = newWind_knp;
emit wind_knpChanged();
}
int WeatherData::wind_kmh() const { return m_wind_kmh; }
void WeatherData::setWind_kmh(int newWind_kmh) {
if (m_wind_kmh == newWind_kmh)
return;
m_wind_kmh = newWind_kmh;
emit wind_kmhChanged();
}
int WeatherData::wind_r() const { return m_wind_r; }
void WeatherData::setWind_r(int newWind_r) {
if (m_wind_r == newWind_r)
return;
m_wind_r = newWind_r;
emit wind_rChanged();
}
QString WeatherData::wind_ltr() const { return m_wind_ltr; }
void WeatherData::setWind_ltr(const QString &newWind_ltr) {
if (m_wind_ltr == newWind_ltr)
return;
m_wind_ltr = newWind_ltr;
emit wind_ltrChanged();
}
int WeatherData::visibility() const { return m_visibility; }
void WeatherData::setVisibility(int newVisibility) {
if (m_visibility == newVisibility)
return;
m_visibility = newVisibility;
emit visibilityChanged();
}
int WeatherData::neersl() const { return m_neersl; }
void WeatherData::setNeersl(int newNeersl) {
if (m_neersl == newNeersl)
return;
m_neersl = newNeersl;
emit neerslChanged();
}
float WeatherData::luchtd_bar() const { return m_luchtd_bar; }
void WeatherData::setLuchtd_bar(float newLuchtd_bar) {
if (qFuzzyCompare(m_luchtd_bar, newLuchtd_bar))
return;
m_luchtd_bar = newLuchtd_bar;
emit luchtd_barChanged();
}
float WeatherData::luchtdmmhg() const { return m_luchtdmmhg; }
void WeatherData::setLuchtdmmhg(float newLuchtdmmhg) {
if (qFuzzyCompare(m_luchtdmmhg, newLuchtdmmhg))
return;
m_luchtdmmhg = newLuchtdmmhg;
emit luchtdmmhgChanged();
}
float WeatherData::luchtdinHg() const { return m_luchtdinHg; }
void WeatherData::setLuchtdinHg(float newLuchtdinHg) {
if (qFuzzyCompare(m_luchtdinHg, newLuchtdinHg))
return;
m_luchtdinHg = newLuchtdinHg;
emit luchtdinHgChanged();
}
int WeatherData::hw() const { return m_hw; }
void WeatherData::setHw(int newHw) {
if (m_hw == newHw)
return;
m_hw = newHw;
emit hwChanged();
}
int WeatherData::mw() const { return m_mw; }
void WeatherData::setMw(int newMw) {
if (m_mw == newMw)
return;
m_mw = newMw;
emit mwChanged();
}
int WeatherData::lw() const { return m_lw; }
void WeatherData::setLw(int newLw) {
if (m_lw == newLw)
return;
m_lw = newLw;
emit lwChanged();
}
int WeatherData::tw() const { return m_tw; }
void WeatherData::setTw(int newTw) {
if (m_tw == newTw)
return;
m_tw = newTw;
emit twChanged();
}
int WeatherData::rv() const { return m_rv; }
void WeatherData::setRv(int newRv) {
if (m_rv == newRv)
return;
m_rv = newRv;
emit rvChanged();
}
int WeatherData::gr() const { return m_gr; }
void WeatherData::setGr(int newGr) {
if (m_gr == newGr)
return;
m_gr = newGr;
emit grChanged();
}
int WeatherData::gr_w() const { return m_gr_w; }
void WeatherData::setGr_w(int newGr_w) {
if (m_gr_w == newGr_w)
return;
m_gr_w = newGr_w;
emit gr_wChanged();
}
QString WeatherData::cape() const { return m_cape; }
void WeatherData::setCape(const QString &newCape) {
if (m_cape == newCape)
return;
m_cape = newCape;
emit capeChanged();
}
int WeatherData::snd() const { return m_snd; }
void WeatherData::setSnd(int newSnd) {
if (m_snd == newSnd)
return;
m_snd = newSnd;
emit sndChanged();
}
int WeatherData::snv() const { return m_snv; }
void WeatherData::setSnv(int newSnv) {
if (m_snv == newSnv)
return;
m_snv = newSnv;
emit snvChanged();
}
int WeatherData::cond() const { return m_cond; }
void WeatherData::setCond(int newCond) {
if (m_cond == newCond)
return;
m_cond = newCond;
emit condChanged();
}
int WeatherData::iconCode() const { return m_iconCode; }
void WeatherData::setIconCode(int newIconCode) {
if (m_iconCode == newIconCode)
return;
m_iconCode = newIconCode;
emit iconCodeChanged();
}
QString WeatherData::sameenv() const { return m_sameenv; }
void WeatherData::setSameenv(const QString &newSameenv) {
if (m_sameenv == newSameenv)
return;
m_sameenv = newSameenv;
emit sameenvChanged();
}
QString WeatherData::icoon() const { return m_icoon; }
void WeatherData::setIcoon(const QString &newIcoon) {
if (m_icoon == newIcoon)
return;
m_icoon = newIcoon;
emit icoonChanged();
}
void WeatherData::print() {}

View File

@@ -0,0 +1,306 @@
#ifndef WEATHERDATA_H
#define WEATHERDATA_H
#include <QObject>
class WeatherData : public QObject {
Q_OBJECT
public:
enum ICON_NAME {
regen,
bewolkt,
halfbewolkt,
lichtbewolkt,
nachtbewolkt,
wolkennacht,
zonnig,
helderenacht
};
Q_ENUM(ICON_NAME)
enum WEATHER_COND {
Regen,
Bewolkt,
Halfbewolkt,
Lichtbewolkt,
Zonnig,
Helder
};
Q_ENUM(WEATHER_COND)
enum WIND_DIR {
Noord,
NNO,
NO,
ONO,
Oost,
OZO,
ZO,
ZZO,
Zuid,
ZZW,
ZW,
WZW,
West,
WNW,
NW,
NNW
};
Q_ENUM(WIND_DIR)
explicit WeatherData(QObject *parent = nullptr);
WeatherData(long tijd, const QString &tijd_nl, int offset, float temp,
int wind_ms, int wind_bf, int wind_knp, int wind_kmh, int wind_r,
const QString &wind_ltr, int visibility, int neersl,
float luchtd_bar, float luchtdmmhg, float luchtdinHg, int hw,
int mw, int lw, int tw, int rv, int gr, int gr_w,
const QString &cape, int snd, int snv, int cond, int iconCode,
const QString &sameenv, const QString &icoon);
WeatherData(const WeatherData &other);
WeatherData operator=(WeatherData const &other);
Q_PROPERTY(long tijd READ tijd WRITE setTijd NOTIFY tijdChanged
FINAL) // DateTime in Timestamp
Q_PROPERTY(QString tijd_nl READ tijd_nl WRITE setTijd_nl NOTIFY tijd_nlChanged
FINAL) // DateTime is Human readable format
Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged
FINAL) // Offset is the last reference hour point of the
// model's predicted weather data
Q_PROPERTY(float temp READ temp WRITE setTemp NOTIFY tempChanged
FINAL) // temp in Celsius
Q_PROPERTY(int wind_ms READ wind_ms WRITE setWind_ms NOTIFY wind_msChanged
FINAL) // Wind avg speed in m/s
Q_PROPERTY(int wind_bf READ wind_bf WRITE setWind_bf NOTIFY wind_bfChanged
FINAL) // Wind avg speed in Beaufort
Q_PROPERTY(int wind_knp READ wind_knp WRITE setWind_knp NOTIFY wind_knpChanged
FINAL) // Wind avg speed in knots
Q_PROPERTY(int wind_kmh READ wind_kmh WRITE setWind_kmh NOTIFY wind_kmhChanged
FINAL) // Wind avg speed in k/h
Q_PROPERTY(int wind_r READ wind_r WRITE setWind_r NOTIFY wind_rChanged
FINAL) // Wind direction in degrees
Q_PROPERTY(
QString wind_ltr READ wind_ltr WRITE setWind_ltr NOTIFY wind_ltrChanged
FINAL) // Wind directions in Letters like N,S,E,W
Q_PROPERTY(int visibility READ visibility WRITE setVisibility NOTIFY
visibilityChanged FINAL) // Visibility in meters
Q_PROPERTY(int neersl READ neersl WRITE setNeersl NOTIFY neerslChanged
FINAL) // Precipitation in nml
Q_PROPERTY(float luchtd_bar READ luchtd_bar WRITE setLuchtd_bar NOTIFY
luchtd_barChanged FINAL) // Air pressure in mbar
Q_PROPERTY(float luchtdmmhg READ luchtdmmhg WRITE setLuchtdmmhg NOTIFY
luchtdmmhgChanged FINAL) // Air pressure in mmHg
Q_PROPERTY(float luchtdinHg READ luchtdinHg WRITE setLuchtdinHg NOTIFY
luchtdinHgChanged FINAL) // Air pressure in inHg
Q_PROPERTY(int hw READ hw WRITE setHw NOTIFY hwChanged
FINAL) //% of Higher Cloud desnsity
Q_PROPERTY(int mw READ mw WRITE setMw NOTIFY mwChanged
FINAL) // % of medium cloud density
Q_PROPERTY(int lw READ lw WRITE setLw NOTIFY lwChanged
FINAL) // % of low cloud density
Q_PROPERTY(int tw READ tw WRITE setTw NOTIFY twChanged
FINAL) // % avg of all cloud density
Q_PROPERTY(
int rv READ rv WRITE setRv NOTIFY rvChanged FINAL) // Reletive Humidity
Q_PROPERTY(int gr READ gr WRITE setGr NOTIFY grChanged
FINAL) // Expected Sun radiation J/cm2
Q_PROPERTY(int gr_w READ gr_w WRITE setGr_w NOTIFY gr_wChanged
FINAL) // Expected Sun radiation watts/m2
Q_PROPERTY(QString cape READ cape WRITE setCape NOTIFY capeChanged
FINAL) // Not gonna use it
Q_PROPERTY(int snd READ snd WRITE setSnd NOTIFY sndChanged
FINAL) // Available snow deck in mm
Q_PROPERTY(int snv READ snv WRITE setSnv NOTIFY snvChanged
FINAL) // Actual snowfall in mm
Q_PROPERTY(int cond READ cond WRITE setCond NOTIFY condChanged
FINAL) // Cond is condition code is weather type like sunny,
// rainy, etc
Q_PROPERTY(int iconCode READ iconCode WRITE setIconCode NOTIFY iconCodeChanged
FINAL) // Icon code of the weather
Q_PROPERTY(QString sameenv READ sameenv WRITE setSameenv NOTIFY sameenvChanged
FINAL) // Name of the current weather type
Q_PROPERTY(QString icoon READ icoon WRITE setIcoon NOTIFY icoonChanged
FINAL) // Icon name of the current weather
long tijd() const;
void setTijd(long newTijd);
QString tijd_nl() const;
void setTijd_nl(const QString &newTijd_nl);
int offset() const;
void setOffset(int newOffset);
float temp() const;
void setTemp(float newTemp);
int wind_ms() const;
void setWind_ms(int newWind_ms);
int wind_bf() const;
void setWind_bf(int newWind_bf);
int wind_knp() const;
void setWind_knp(int newWind_knp);
int wind_kmh() const;
void setWind_kmh(int newWind_kmh);
int wind_r() const;
void setWind_r(int newWind_r);
QString wind_ltr() const;
void setWind_ltr(const QString &newWind_ltr);
int visibility() const;
void setVisibility(int newVisibility);
int neersl() const;
void setNeersl(int newNeersl);
float luchtd_bar() const;
void setLuchtd_bar(float newLuchtd_bar);
float luchtdmmhg() const;
void setLuchtdmmhg(float newLuchtdmmhg);
float luchtdinHg() const;
void setLuchtdinHg(float newLuchtdinHg);
int hw() const;
void setHw(int newHw);
int mw() const;
void setMw(int newMw);
int lw() const;
void setLw(int newLw);
int tw() const;
void setTw(int newTw);
int rv() const;
void setRv(int newRv);
int gr() const;
void setGr(int newGr);
int gr_w() const;
void setGr_w(int newGr_w);
QString cape() const;
void setCape(const QString &newCape);
int snd() const;
void setSnd(int newSnd);
int snv() const;
void setSnv(int newSnv);
int cond() const;
void setCond(int newCond);
int iconCode() const;
void setIconCode(int newIconCode);
QString sameenv() const;
void setSameenv(const QString &newSameenv);
QString icoon() const;
void setIcoon(const QString &newIcoon);
void print();
signals:
void tijdChanged();
void tijd_nlChanged();
void offsetChanged();
void tempChanged();
void wind_msChanged();
void wind_bfChanged();
void wind_knpChanged();
void wind_kmhChanged();
void wind_rChanged();
void wind_ltrChanged();
void visibilityChanged();
void neerslChanged();
void luchtd_barChanged();
void luchtdmmhgChanged();
void luchtdinHgChanged();
void hwChanged();
void mwChanged();
void lwChanged();
void twChanged();
void rvChanged();
void grChanged();
void gr_wChanged();
void capeChanged();
void sndChanged();
void snvChanged();
void condChanged();
void iconCodeChanged();
void sameenvChanged();
void icoonChanged();
private:
long m_tijd;
QString m_tijd_nl;
int m_offset;
float m_temp;
int m_wind_ms;
int m_wind_bf;
int m_wind_knp;
int m_wind_kmh;
int m_wind_r;
QString m_wind_ltr;
int m_visibility;
int m_neersl;
float m_luchtd_bar;
float m_luchtdmmhg;
float m_luchtdinHg;
int m_hw;
int m_mw;
int m_lw;
int m_tw;
int m_rv;
int m_gr;
int m_gr_w;
QString m_cape;
int m_snd;
int m_snv;
int m_cond;
int m_iconCode;
QString m_sameenv;
QString m_icoon;
};
#endif // WEATHERDATA_H

View File

@@ -0,0 +1,84 @@
#include "weatherdetailsdata.h"
#include <QJsonArray>
#include <qjsonobject.h>
WeatherDetailsData::WeatherDetailsData(QObject *parent) : QObject{parent} {}
WeatherDetailsData::WeatherDetailsData(std::shared_ptr<WeatherController> &ctrl)
: m_localWeatherCtrl(ctrl) {}
QString WeatherDetailsData::weatherStatus() const { return m_weatherStatus; }
void WeatherDetailsData::setWeatherStatus(QString newWeatherStatus) {
if (m_weatherStatus == newWeatherStatus)
return;
m_weatherStatus = newWeatherStatus;
emit weatherStatusChanged();
}
double WeatherDetailsData::temperature() const { return m_temperature; }
void WeatherDetailsData::setTemperature(double newTemperature) {
if (qFuzzyCompare(m_temperature, newTemperature))
return;
m_temperature = newTemperature;
emit temperatureChanged();
}
double WeatherDetailsData::humidity() const { return m_humidity; }
void WeatherDetailsData::setHumidity(double newHumidity) {
if (qFuzzyCompare(m_humidity, newHumidity))
return;
m_humidity = newHumidity;
emit humidityChanged();
}
double WeatherDetailsData::windSpeed() const { return m_windSpeed; }
void WeatherDetailsData::setWindSpeed(double newWindSpeed) {
if (qFuzzyCompare(m_windSpeed, newWindSpeed))
return;
m_windSpeed = newWindSpeed;
emit windSpeedChanged();
}
double WeatherDetailsData::precipitation() const { return m_precipitation; }
void WeatherDetailsData::setPrecipitation(double newPrecipitation) {
if (qFuzzyCompare(m_precipitation, newPrecipitation))
return;
m_precipitation = newPrecipitation;
emit precipitationChanged();
}
void WeatherDetailsData::populate(double temperature, double humidity,
double windSpeed, double precipitation,
QString weatherStatus) {
setTemperature(temperature);
setHumidity(humidity);
setWindSpeed(windSpeed);
setPrecipitation(precipitation);
setWeatherStatus(weatherStatus);
}
void WeatherDetailsData::populate(QGeoCoordinate coord) {
QJsonObject obj = m_localWeatherCtrl->fetchCurrentWeatherData(coord);
QJsonArray liveweerArray = obj["liveweer"].toArray();
QJsonObject firstEntry = liveweerArray.at(0).toObject();
QString temp = verifyForDash(firstEntry["temp"].toString());
QString humidity = verifyForDash(firstEntry["lv"].toString());
QString windSpeed = verifyForDash(firstEntry["windkmh"].toString());
QString precipitation = verifyForDash(firstEntry["neerslagints"].toString());
QString weatherStatus = verifyForDash(firstEntry["image"].toString());
populate(temp.toDouble(), humidity.toDouble(), windSpeed.toDouble(),
precipitation.toDouble(), weatherStatus);
}
QString WeatherDetailsData::getImgSrc(QString status) {
return QString("qrc:/images/live_icons/%1.png").arg(status);
}
QString WeatherDetailsData::verifyForDash(QString data) {
return data == "-" ? "0" : data;
}

View File

@@ -0,0 +1,81 @@
#ifndef WEATHERDETAILSDATA_H
#define WEATHERDETAILSDATA_H
#include <QObject>
#include "../controller/weathercontroller.h"
#include "enums/weatherstatus.h"
#include <QObject>
class WeatherDetailsData : public QObject {
Q_OBJECT
public:
enum LIVE_ICON_NAME {
zonnig,
bliksem,
regen,
buien,
hagel,
mist,
sneeuw,
bewolkt,
halfbewolkt,
zwaarbewolkt,
lichtbewolkt,
nachtmist,
helderenacht,
wolkennacht
};
Q_ENUM(LIVE_ICON_NAME)
explicit WeatherDetailsData(QObject *parent = nullptr);
WeatherDetailsData(std::shared_ptr<WeatherController> &ctrl);
Q_PROPERTY(double temperature READ temperature WRITE setTemperature NOTIFY
temperatureChanged FINAL)
Q_PROPERTY(double humidity READ humidity WRITE setHumidity NOTIFY
humidityChanged FINAL)
Q_PROPERTY(double windSpeed READ windSpeed WRITE setWindSpeed NOTIFY
windSpeedChanged FINAL)
Q_PROPERTY(double precipitation READ precipitation WRITE setPrecipitation
NOTIFY precipitationChanged FINAL)
Q_PROPERTY(QString weatherStatus READ weatherStatus WRITE setWeatherStatus
NOTIFY weatherStatusChanged FINAL)
QString weatherStatus() const;
void setWeatherStatus(QString newWeatherStatus);
double temperature() const;
void setTemperature(double newTemperature);
double humidity() const;
void setHumidity(double newHumidity);
double windSpeed() const;
void setWindSpeed(double newWindSpeed);
double precipitation() const;
void setPrecipitation(double newPrecipitation);
void populate(double temperature, double humidity, double windSpeed,
double precipitation, QString weatherStatus);
Q_INVOKABLE void populate(QGeoCoordinate coord);
Q_INVOKABLE QString getImgSrc(QString status);
signals:
void weatherStatusChanged();
void temperatureChanged();
void humidityChanged();
void windSpeedChanged();
void precipitationChanged();
private:
QString m_weatherStatus = "regen";
double m_temperature = 0.0;
double m_humidity = 0.0;
double m_windSpeed = 0.0;
double m_precipitation = 0.0;
std::shared_ptr<WeatherController> m_localWeatherCtrl;
QString verifyForDash(QString data);
};
#endif // WEATHERDETAILSDATA_H

View File

@@ -0,0 +1,20 @@
#ifndef WEATHERSTATUS_H
#define WEATHERSTATUS_H
#include <stdint.h>
enum WeatherStatus : uint8_t {
UNKNOWN = 0,
SUNNY,
PARTLY_CLOUDY,
CLOUDY,
RAINY,
SNOWING,
HAILSTORM,
FROZED_TO_DEAD,
THUNDERSTORM,
TSUNAMI
};
#endif // WEATHERSTATUS_H

View File

@@ -0,0 +1,34 @@
// #include "mapdatamodel.h"
// MapDataModel::MapDataModel(QObject *parent) {}
// int MapDataModel::rowCount(const QModelIndex &parent) const
// {
// return mDatas.size();
// }
// int MapDataModel::columnCount(const QModelIndex &parent) const
// {
// }
// QVariant MapDataModel::data(const QModelIndex &index, int role) const
// {
// if (!index.isValid())
// return QVariant();
// if ( role == Qt::DisplayRole)
// {
// if ( index.column() == 0)
// return mDatas[index.row()].waypoints();
// if ( index.column() == 1)
// return mDatas[index.row()].longitude();
// if ( index.column() == 2)
// return mDatas[index.row()].altitude();
// }
// return QVariant();
// }
// void MapDataModel::populate()
// {
// }

View File

@@ -0,0 +1,22 @@
// #ifndef MAPDATAMODEL_H
// #define MAPDATAMODEL_H
// #include <QAbstractItemModel >
// #include <QObject>
// #include "../data/mapdata.h"
// class MapDataModel : public QAbstractItemModel
// {
// Q_OBJECT
// public:
// MapDataModel(QObject * parent = 0);
// int rowCount(const QModelIndex& parent = QModelIndex()) const;
// int columnCount(const QModelIndex& parent = QModelIndex()) const;
// QVariant data(const QModelIndex &index, int role) const;
// void populate();
// private:
// QList<MapData> mDatas;
// };
// #endif // MAPDATAMODEL_H

View File

@@ -0,0 +1,50 @@
import QtQuick
import QtQuick.Controls
Rectangle {
property alias logoSrc: logoImage.source
property alias placeHolderText: textInput.placeholderText
property alias text: textInput.text
Rectangle
{
id: logoRect
width: parent.width * 0.1
height: parent.height
anchors.left: parent.left
anchors.top: parent.top
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
Image
{
id: logoImage
anchors.fill: parent
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
z: parent.z + 1
}
}
Rectangle
{
id: inputRect
width: parent.width * 0.9
height: parent.height
anchors.left: logoRect.right
anchors.top: parent.top
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
radius: parent.radius
TextField
{
id: textInput
anchors.fill: parent
onPressed: textInput.forceActiveFocus()
background: Rectangle{
width: inputRect.width
height:inputRect.height
radius: inputRect.radius
}
}
}
}

View File

@@ -0,0 +1,97 @@
import QtQuick
import QtQuick.Controls
Rectangle {
id: root
anchors.fill: parent
border.color: "black"
border.width: 2
color: "transparent"
readonly property int radius: width * 0.025
Component.onCompleted:
{
mapView.positionSource.start()
weatherDetailsData.populate(mapView.positionSource.position.coordinate)
}
CustomInputField
{
id: inputFrom
width: parent.width - (2 * anchors.margins)
height: parent.height * 0.05
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.margins: parent.width * 0.01
anchors.topMargin: parent.width * 0.02
logoSrc: "qrc:/images/start_location.svg"
placeHolderText: "Start"
z: mapView.z + 1
radius: root.radius
}
CustomInputField
{
id: inputTo
width: parent.width - (2 * anchors.margins)
height: parent.height * 0.05
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: inputFrom.bottom
anchors.margins: parent.width * 0.01
logoSrc: "qrc:/images/Destination_location.png"
placeHolderText: "Destination"
z: mapView.z + 1
radius: root.radius
}
MapView
{
id: mapView
anchors.fill: parent
radius: root.radius
}
Button
{
id: myLocationButton
width: parent.width * 0.1
height: width
anchors.right: parent.right
anchors.bottom: weatherDetails.top
anchors.margins: parent.width * 0.01
background: Rectangle
{
anchors.fill: parent
color:"darkgray"
radius: width/2
Image
{
source: "qrc:/images/centerToGPS.png"
fillMode: Image.PreserveAspectFit
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
onClicked:
{
mapView.resetZoomLevel()
}
z: mapView.z + 1
}
WeatherDetailsView
{
id: weatherDetails
width: parent.width
height: parent.height * 0.1
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
z: mapView.z + 1
radius: root.radius
imgSrc: weatherDetailsData.getImgSrc(weatherDetailsData.weatherStatus)
temperature: weatherDetailsData.temperature
precipitation: weatherDetailsData.precipitation
windSpeed: weatherDetailsData.windSpeed
humidity: weatherDetailsData.humidity
}
}

View File

@@ -0,0 +1,107 @@
import QtQuick
import QtLocation
import QtPositioning
Rectangle {
property alias positionSource: positionSource
property variant waypoints: mapData.waypoints
function resetZoomLevel()
{
map.zoomLevel = mapData.defaultZoomLevel
map.bearing = 0;
positionSource.start()
}
Plugin {
id: mapPlugin
name: "osm"
PluginParameter {
name: "osm.mapping.providersrepository.disabled"
value: "true"
}
PluginParameter {
name: "osm.mapping.providersrepository.address"
value: "http://maps-redirect.qt.io/osm/5.6/"
}
}
PositionSource
{
id: positionSource
updateInterval: mapData.gpsUpdateInterval
active: true
onPositionChanged: {
var coord = positionSource.position.coordinate;
map.visible = true;
map.center = positionSource.position.coordinate;
}
}
MapQuickItem {
id: marker
zoomLevel: map.zoomLevel
anchorPoint.x: image.width/2
anchorPoint.y: image.height
coordinate: positionSource.position.coordinate
sourceItem: Image {
id: image
height: 40
width: height*2/3
source: "qrc:/images/currentLocationOfWaypoint.svg"
transform: Rotation { origin.x: marker.anchorPoint.x; origin.y: marker.anchorPoint.y; angle: map.bearing}
}
Component.onCompleted: map.addMapItem(marker)
}
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(59.91, 10.75) // Oslo
zoomLevel: mapData.zoomLevel
property geoCoordinate startCentroid
PinchHandler {
id: pinch
target: null
onActiveChanged: if (active) {
map.startCentroid = map.toCoordinate(pinch.centroid.position, false)
}
onScaleChanged: (delta) => {
map.zoomLevel += Math.log2(delta)
map.alignCoordinateToPoint(map.startCentroid, pinch.centroid.position)
}
onRotationChanged: (delta) => {
map.bearing -= delta
map.alignCoordinateToPoint(map.startCentroid, pinch.centroid.position)
}
grabPermissions: PointerHandler.TakeOverForbidden
}
WheelHandler {
id: wheel
acceptedDevices: Qt.platform.pluginName === "cocoa" || Qt.platform.pluginName === "wayland"
? PointerDevice.Mouse | PointerDevice.TouchPad
: PointerDevice.Mouse
rotationScale: 1/120
property: "zoomLevel"
}
DragHandler {
id: drag
target: null
onTranslationChanged: (delta) => map.pan(-delta.x, -delta.y)
// onGrabChanged: positionSource.active = false
}
Shortcut {
enabled: map.zoomLevel < map.maximumZoomLevel
sequence: StandardKey.ZoomIn
onActivated: map.zoomLevel = Math.round(map.zoomLevel + 1)
}
Shortcut {
enabled: map.zoomLevel > map.minimumZoomLevel
sequence: StandardKey.ZoomOut
onActivated: map.zoomLevel = Math.round(map.zoomLevel - 1)
}
}
}

View File

@@ -0,0 +1,5 @@
import QtQuick 2.15
Item {
}

View File

@@ -0,0 +1,119 @@
import QtQuick
Rectangle {
id: root
property alias imgSrc: image.source
property alias temperature: tempValue.text
property alias humidity: humidityValue.text
property alias precipitation: precipValue.text
property alias windSpeed: windValue.text
property double rightMargin: root.width * 0.05
Rectangle
{
id: imageRect
width: parent.width * 0.2
height: parent.height
anchors.left: parent.left
anchors.top: parent.top
radius: 15
color: "black"
Image
{
id: image
fillMode: Image.PreserveAspectFit
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle
{
id: tempRect
width: parent.width * 0.4
height: parent.height * 0.5
anchors.left: imageRect.right
anchors.top: parent.top
Text
{
id: tempLabel
text: "Temp (C):"
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
Text
{
id: tempValue
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: root.rightMargin
}
}
Rectangle
{
id: humidityRect
width: parent.width * 0.4
height: parent.height * 0.5
anchors.left: tempRect.right
anchors.top: parent.top
Text
{
id: humidityLabel
text: "Humidity (%):"
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
Text
{
id: humidityValue
anchors.right: parent.right
anchors.rightMargin: root.rightMargin
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle
{
id: precipRect
width: parent.width * 0.4
height: parent.height * 0.5
anchors.left: imageRect.right
anchors.top: tempRect.bottom
Text
{
id: precipLabel
text: "Precipitation (mm)"
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
Text
{
id: precipValue
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: root.rightMargin
}
}
Rectangle
{
id: windRect
width: parent.width * 0.4
height: parent.height * 0.5
anchors.left: tempRect.right
anchors.top: humidityRect.bottom
Text
{
id: windLabel
text: "Wind (km/h):"
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
Text
{
id: windValue
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: root.rightMargin
}
}
}

View File

@@ -0,0 +1,28 @@
<RCC>
<qresource prefix="/">
<file>images/Destination_location.png</file>
<file>images/start_location.png</file>
<file>images/weather_partly_cloudy_day.png</file>
<file>images/weather_rainy.png</file>
<file>images/weather_sunny.png</file>
<file>images/weather_thunderstorm.png</file>
<file>images/weather_tsunami.png</file>
<file>images/start_location.svg</file>
<file>images/centerToGPS.png</file>
<file>images/currentLocationOfWaypoint.svg</file>
<file>images/live_icons/bewolkt.png</file>
<file>images/live_icons/bliksem.png</file>
<file>images/live_icons/buien.png</file>
<file>images/live_icons/hagel.png</file>
<file>images/live_icons/halfbewolkt.png</file>
<file>images/live_icons/helderenacht.png</file>
<file>images/live_icons/lichtbewolkt.png</file>
<file>images/live_icons/mist.png</file>
<file>images/live_icons/nachtmist.png</file>
<file>images/live_icons/regen.png</file>
<file>images/live_icons/sneeuw.png</file>
<file>images/live_icons/wolkennacht.png</file>
<file>images/live_icons/zonnig.png</file>
<file>images/live_icons/zwaarbewolkt.png</file>
</qresource>
</RCC>