Коммит cb72f8cf создал по автору OMP Education's avatar OMP Education
Просмотр файлов

[Project] Implement generator for WebView-based applications.

владелец 8a912bbb
**/__pycache__/*
build-*
\ No newline at end of file
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import re
class ConfigurationError(Exception):
def __init__(self, *args: object) -> None:
super().__init__(*args)
class Configuration:
PERMISSIONS = frozenset(['AccessSecurityLog', 'LogSecurityEvents', 'Sensors', 'SecureStorage', 'PushNotifications',
'DeviceInfo', 'Audio', 'Bluetooth', 'Camera', 'Internet', 'Location', 'MediaIndexing',
'Microphone', 'NFC', 'RemovableMedia', 'UserDirs', 'WebView', 'Documents', 'Downloads',
'Music', 'Pictures', 'PublicDir', 'Videos'])
WEB_PERMISSIONS = frozenset(['geolocation', 'microphone', 'camera', 'cookie', 'popup'])
REQUIRED_KEYS = frozenset(['application_name', 'organization_name', 'summary', 'version',
'application_permission', 'background_activity', 'url'])
OPTIONAL_KEYS = frozenset(['desktop_name', 'description', 'icon', 'external_urls', 'frame_urls', 'web_permissions',
'user_agent', 'push_app_id', 'push_handler_name', 'push_id_injector'])
KEYS = REQUIRED_KEYS.union(OPTIONAL_KEYS)
def __init__(self, json: dict) -> None:
for key, value in json.items():
if key not in self.KEYS:
raise ConfigurationError(f"Unknown key {key}")
if key == 'application_permission' or key == 'external_urls' or key == 'frame_urls' or key == 'web_permissions' or key == 'push_id_injector':
if type(value) != list:
raise ConfigurationError(f"{key} must be a list")
if key == 'application_permission':
unknown_permissions = set(value).difference(self.PERMISSIONS)
if unknown_permissions:
raise ConfigurationError(f"Unknown application permission {', '.join(unknown_permissions)}")
elif key == "web_permissions":
unknown_permissions = set([permission.lower() for permission in value]).difference(self.WEB_PERMISSIONS)
if unknown_permissions:
raise ConfigurationError(f"Unknown Web permission {', '.join(unknown_permissions)}")
elif key == 'organization_name':
value = '.'.join(value.split('.')[::-1])
setattr(self, key, value)
missing_keys = self.REQUIRED_KEYS.difference(set(json.keys()))
if missing_keys:
raise ConfigurationError(f"{', '.join(missing_keys)} must be set")
if not locals().get('icon', None):
locals()['icon'] = './default_icons'
self.full_name = self.organization_name + '.' + self.application_name
if not hasattr(self, 'desktop_name'):
setattr(self, 'desktop_name', self.application_name)
for key in self.OPTIONAL_KEYS:
if not hasattr(self, key):
setattr(self, key, None)
<svg width="1024" height="1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path id="Background" d="m0 357.5c0-180.46 0-245.38 56.06-301.44s120.99-56.06 326.74-56.06h258.39c205.76 0 270.68 0 326.74 56.06s56.06 120.99 56.06 326.74v258.39c0 205.76 0 270.68-56.06 326.74-56.06 56.059-120.99 56.059-326.74 56.059h-258.39c-205.76 0-270.68 0-326.74-56.059-56.06-56.06-56.06-120.99-56.06-326.74z" fill="#003e88"/>
<mask id="Frame_Mask" maskUnits="userSpaceOnUse">
<use xlink:href="#Background"/>
</mask>
<g fill="none" mask="url(#Frame_Mask)" stroke="#4169e1" stroke-width="1024">
<path d="m-2e-5 512h1024" stroke-dasharray="1.024, 49.152, 1.024, 0"/>
<path d="m512-2.41e-5v1024" stroke-dasharray="1.024, 49.152, 1.024, 0"/>
<path d="m-2e-5 512h1024" stroke-dasharray="2.56, 506.88, 2.56, 0"/>
<path d="m512-2.41e-5v1024" stroke-dasharray="2.56, 506.88, 2.56, 0"/>
</g>
<radialGradient id="Aurora_Gradient" cx="253.16" cy="572.03" r="346.86" gradientTransform="matrix(1.7323 .99965 -1 1.7329 540.61 -618.36)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" offset="0"/>
<stop stop-color="#fff" stop-opacity="0" offset="1"/>
</radialGradient>
<path d="m820.13 625.96h-23.404a3.7229 3.7229 0 0 1-3.2222-5.5952l8.1207-14.064a12.388 12.388 0 0 0 0-12.41l-35.161-60.959-53.775 93.007h-17.831a3.7229 3.7229 0 0 1-3.2222-5.5952l59.109-102.32a12.388 12.388 0 0 0 0-12.41l-35.161-60.959-204.15 353.24-9.2745-16.045a9.8624 9.8624 0 0 1 0-9.9277l197.7-341.96a12.388 12.388 0 0 0 0-12.41l-35.161-60.959-204.21 353.19-9.2528-16.045a9.8624 9.8624 0 0 1 0-9.9277l197.75-342.05a12.388 12.388 0 0 0 0-12.41l-35.182-61.003-206.7 357.61h-17.722a3.7229 3.7229 0 0 1-3.2221-5.5952l211.92-366.76a12.453 12.453 0 0 0 0-12.41l-35.182-60.959-257.66 445.72h-17.831a3.7229 3.7229 0 0 1-3.2221-5.5952l263.02-455.02a12.388 12.388 0 0 0 0-12.41l-35.204-60.938-346.86 601.06h208.15l138.16 238.94 138.18-238.94h209.22z" fill="url(#Aurora_Gradient)"/>
</svg>
#!/usr/bin/env python3
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import argparse
from ast import arg
import json
import os
import pathlib
import shutil
from configuration import Configuration
from generators import desktop, spec, pro, main, cover, applicationwindow, connectionchecker, connectionheader, connmanmanager, applicationcontroller, applicationservice, webview
def generate(file: str, project_dir: str) -> int:
if not os.path.exists(file):
raise FileNotFoundError(f"{file} does not exist")
with open(file, encoding="utf-8") as f:
config = Configuration(json.load(f))
desktop.DesktopFileGenerator(config=config, project_dir=project_dir).save()
spec.SpecFileGenerator(config=config, project_dir=project_dir).save()
pro.ProFileGenerator(config=config, project_dir=project_dir).save()
main.MainFileGenerator(config=config, project_dir=project_dir).save()
connectionchecker.ConnectionCheckerFileGenerator(config=config, project_dir=project_dir).save()
connectionheader.ConnectionHeaderFileGenerator(config=config, project_dir=project_dir).save()
connmanmanager.ConnmanManagerFileGenerator(config=config, project_dir=project_dir).save()
webview.WebViewFileGenerator(config=config, project_dir=project_dir).save()
if config.push_app_id:
applicationcontroller.ApplicationControllerFileGenerator(config=config, project_dir=project_dir).save()
applicationservice.ApplicationServiceFileGenerator(config=config, project_dir=project_dir).save()
if not config.background_activity:
cover.CoverFileGenerator(config=config, project_dir=project_dir).save()
shutil.copy('./default_icons/defaultcovericon.svg',
f"{config.application_name}/qml/icons/{config.application_name}.svg")
applicationwindow.ApplicationWindowFileGenerator(config=config, project_dir=project_dir).save()
if config.icon:
if not list(pathlib.Path(config.icon).glob('**/*.png')):
raise FileNotFoundError(f"Directory {config.icon} does not contains icons")
for icon in pathlib.Path(config.icon).glob('**/*.png'):
dest_dir = f"{project_dir}/{config.application_name}/icons/{icon.parent.name}/"
os.makedirs(os.path.dirname(dest_dir), exist_ok=True)
shutil.copy(icon, f"{dest_dir}{config.full_name}.png")
else:
for resolution in [86, 108, 128, 172]:
os.makedirs(f"{project_dir}/{config.application_name}/icons/{resolution}x{resolution}", exist_ok=True)
shutil.copy(f"./default_icons/{resolution}x{resolution}/defaulticon.png",
f"{project_dir}/{config.application_name}/icons/{resolution}x{resolution}/{config.full_name}.png")
def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description='Generate WebView-based Aurora OS application from JSON configuration.'
)
parser.add_argument(
dest='file',
type=str,
help='Path to the JSON configuration file.'
)
parser.add_argument(
'-p', '--project-dir',
help='Path to the generated project location.',
type=str,
default="./"
)
return parser.parse_args()
if __name__ == '__main__':
args = parse_arguments()
generate(args.file, args.project_dir)
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ApplicationControllerFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = 'src/applicationcontroller'
def generate_header(self) -> str:
content =\
"""\
#ifndef APPLICATIONCONTROLLER_H
#define APPLICATIONCONTROLLER_H
#include <QtCore/QObject>
#include <QtCore/QVariantMap>
class QQuickView;
namespace Aurora {
namespace PushNotifications {
class Client;
}
}
class ApplicationController : public QObject
{
Q_OBJECT
Q_PROPERTY(QString applicationId READ applicationId NOTIFY applicationIdChanged)
Q_PROPERTY(QString registrationId READ registrationId NOTIFY registrationIdChanged)
public:
explicit ApplicationController(QObject *parent = nullptr);
ApplicationController(const QStringList &arguments, QObject *parent = nullptr);
QString applicationId() const;
QString registrationId() const;
signals:
void applicationIdChanged(const QString &applicationId);
void registrationIdChanged(const QString &registrationId);
void dataReceived(const QVariantMap &data);
public slots:
void showGui(const QVariantMap &data = QVariantMap());
private:
QString getApplicationId() const;
void setApplicationId(const QString &applicationId);
void setRegistrationId(const QString &registrationId);
private:
Aurora::PushNotifications::Client *m_notificationsClient;
QQuickView *m_view;
QString m_registrationId;
};
#endif // APPLICATIONCONTROLLER_H
"""
return content
def generate_source(self) -> str:
content =\
"""\
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlContext>
#include <QtQuick/QQuickView>
#include <auroraapp.h>
#include <push_client.h>
#include <nemonotifications-qt5/notification.h>
#include "applicationcontroller.h"
#include "applicationservice.h"
namespace {
const QString applicationIdFilePath = QStringLiteral(APP_ID_FILE_PATH);
}
using namespace Aurora::PushNotifications;
ApplicationController::ApplicationController(QObject *parent)
: ApplicationController({ }, parent) {
}
ApplicationController::ApplicationController(const QStringList &arguments, QObject *parent)
: QObject(parent)
, m_notificationsClient(new Client(this))
, m_view(nullptr) {
setApplicationId(getApplicationId());
if (arguments.indexOf(QStringLiteral("/no-gui")) == -1)
showGui();
connect(m_notificationsClient, &Client::clientInactive, [this]() {
if (m_view == nullptr)
qApp->quit();
});
connect(m_notificationsClient, &Client::pushSystemReadinessChanged, [](bool status) {
qWarning() << "Push system is" << (status ? "available" : "not available");
});
connect(m_notificationsClient, &Client::registrationId, [this](const QString &registrationId) {
setRegistrationId(registrationId);
});
connect(m_notificationsClient, &Client::registrationError, []() {
qWarning() << "Push system have problems with registrationId";
});
connect(m_notificationsClient, &Client::notifications, [this](const PushList &pushList) {
for (const auto &push : pushList) {
auto jsonDcoument = QJsonDocument::fromJson(push.data.toUtf8());
QVariant defaultAction = Notification::remoteAction(QStringLiteral("default"), tr("Open app"),
ApplicationService::notifyDBusService(),
ApplicationService::notifyDBusPath(),
ApplicationService::notifyDBusIface(),
ApplicationService::notifyDBusMethod(),
QVariantList() << jsonDcoument.object().toVariantMap());
Notification notification;
notification.setAppName(tr("Web Messenger"));
notification.setSummary(push.title);
notification.setBody(push.message);
notification.setIsTransient(false);
notification.setItemCount(1);
notification.setRemoteAction(defaultAction);
notification.publish();
}
});
}
QString ApplicationController::applicationId() const
{
return m_notificationsClient->applicationId();
}
QString ApplicationController::registrationId() const
{
return m_registrationId;
}
void ApplicationController::showGui(const QVariantMap &data) {
if (m_view != nullptr) {
m_view->raise();
m_view->showFullScreen();
} else {
m_view = Aurora::Application::createView();
m_view->rootContext()->setContextProperty("AppCtrl", this);
m_view->rootContext()->setContextProperty("targetUrl", TARGET_URL);
m_view->setSource(Aurora::Application::pathToMainQml());
m_view->show();
}
emit dataReceived(data);
}
QString ApplicationController::getApplicationId() const {
QFile applicationIdFile(applicationIdFilePath);
if (applicationIdFile.exists() && applicationIdFile.open(QIODevice::ReadOnly)) {
auto data = applicationIdFile.readAll().trimmed();
applicationIdFile.close();
return data;
} else {
return QStringLiteral("applicationId not set");
}
}
void ApplicationController::setApplicationId(const QString &applicationId) {
if (m_notificationsClient->applicationId() == applicationId)
return;
m_notificationsClient->setApplicationId(applicationId);
m_notificationsClient->registrate();
emit applicationIdChanged(applicationId);
}
void ApplicationController::setRegistrationId(const QString &registrationId) {
if (registrationId == m_registrationId)
return;
m_registrationId = registrationId;
emit registrationIdChanged(registrationId);
}
"""
return content
def save(self) -> None:
filename = self.project_dir + self.path
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename + '.h', mode='w', encoding='utf-8') as f:
f.write(self.generate_header())
with open(filename + '.cpp', mode='w', encoding='utf-8') as f:
f.write(self.generate_source())
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ApplicationServiceFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = 'src/applicationservice'
def generate_header(self) -> str:
content =\
"""\
#ifndef APPLICATIONSERVICE_H
#define APPLICATIONSERVICE_H
#include <QtDBus/QDBusAbstractAdaptor>
class ApplicationService : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_INTERFACE)
public:
explicit ApplicationService(QObject *parent = nullptr);
~ApplicationService() override;
static bool isRegistered();
static QString notifyDBusService();
static QString notifyDBusPath();
static QString notifyDBusIface();
static QString notifyDBusMethod();
static qint32 updateApplicationArgs(const QStringList &arguments);
signals:
void showGui(const QVariantMap &data = QVariantMap());
public slots:
void handleApplicationArgs(const QStringList &arguments);
void handleApplicationWakeUp(const QVariantMap &data);
};
#endif // APPLICATIONSERVICE_H
"""
return content
def generate_source(self) -> str:
content =\
"""\
#include <QtGui/QGuiApplication>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusMessage>
#include "applicationservice.h"
namespace {
const QString dbusServiceStr = QStringLiteral(DBUS_SERVICE);
const QString dbusPathStr = QStringLiteral(DBUS_PATH);
const QString dbusIfaceStr = QStringLiteral(DBUS_INTERFACE);
const QString dbusMethodAppArgs = QStringLiteral("handleApplicationArgs");
const QString dbusMethodAppWakeUp = QStringLiteral("handleApplicationWakeUp");
}
ApplicationService::ApplicationService(QObject *parent)
: QDBusAbstractAdaptor(parent) {
setAutoRelaySignals(true);
auto dbus = QDBusConnection::sessionBus();
dbus.registerObject(dbusPathStr, this, QDBusConnection::ExportAllSlots);
if (!isRegistered()) {
bool success = dbus.registerService(dbusServiceStr);
if (!success)
qApp->quit();
}
}
ApplicationService::~ApplicationService() {
auto dbus = QDBusConnection::sessionBus();
dbus.unregisterObject(dbusPathStr);
dbus.unregisterService(dbusServiceStr);
}
bool ApplicationService::isRegistered() {
return QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusServiceStr);
}
QString ApplicationService::notifyDBusService()
{
return dbusServiceStr;
}
QString ApplicationService::notifyDBusPath()
{
return dbusPathStr;
}
QString ApplicationService::notifyDBusIface()
{
return dbusIfaceStr;
}
QString ApplicationService::notifyDBusMethod()
{
return dbusMethodAppWakeUp;
}
qint32 ApplicationService::updateApplicationArgs(const QStringList &arguments) {
auto message = QDBusMessage::createMethodCall(dbusServiceStr, dbusPathStr, dbusIfaceStr, dbusMethodAppArgs);
message.setArguments(QList<QVariant>() << arguments);
auto reply = QDBusConnection::sessionBus().call(message);
return 0;
}
void ApplicationService::handleApplicationArgs(const QStringList &arguments) {
if (arguments.indexOf(QStringLiteral("/no-gui")) != -1)
return;
emit showGui();
}
void ApplicationService::handleApplicationWakeUp(const QVariantMap &data) {
emit showGui(data);
}
"""
return content
def save(self) -> None:
filename = self.project_dir + self.path
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename + '.h', mode='w', encoding='utf-8') as f:
f.write(self.generate_header())
with open(filename + '.cpp', mode='w', encoding='utf-8') as f:
f.write(self.generate_source())
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ApplicationWindowFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = f"qml/{self.config.full_name}.qml"
def generate(self) -> str:
content =\
f"""\
import QtQuick 2.0
import Sailfish.Silica 1.0
ApplicationWindow {{
objectName: "applicationWindow"
initialPage: Qt.resolvedUrl("pages/WebViewPage.qml")
"""
if self.config.background_activity:
content += ' cover: null'
else:
content += ' cover: Qt.resolvedUrl("cover/CoverPage.qml")'
content +=\
"""
allowedOrientations: defaultAllowedOrientations
}
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ConnectionCheckerFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = 'src/connectionchecker.h'
def generate(self) -> str:
content =\
r"""#ifndef CONNECTIONCHECKER_H
#define CONNECTIONCHECKER_H
#include <QNetworkAccessManager>
#include <QNetworkConfigurationManager>
#include <QNetworkReply>
#include <QUrl>
#include <QObject>
class ConnectionChecker : public QObject
{
Q_OBJECT
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
Q_PROPERTY(bool running READ running NOTIFY runningChanged)
public:
/*!
* \brief Add handler for network manager's replies.
* Send initial request to verify connection to the host.
*/
ConnectionChecker(QObject *parent = nullptr)
: QObject(parent)
, _connected(true)
, _running(false) {
QObject::connect(&nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(handleReply(QNetworkReply*)));
ping();
}
/*!
* \brief Whether the last HTTP request to the host was successful.
*/
bool connected() { return _connected; }
/*!
* \brief Whether there is a running HTTP request.
*/
bool running() { return _running; }
/*!
* \brief Send a GET request with the 'Host' header set to target URL
* so that we can verify the connection between client and the host.
*/
Q_INVOKABLE void ping() {
if (ncm.isOnline()) {
setRunning(true);
QNetworkRequest req(QUrl(TARGET_URL));
req.setRawHeader(QByteArray("Host"), TARGET_URL);
nam.get(req);
} else {
setConnected(false);
}
}
signals:
void connectedChanged(bool connected);
void runningChanged(bool running);
private slots:
/*!
* \brief Handle network manager's reply to a previously sent request.
* The lack of reply's content means the host is unreachable.
* \param reply HTTP reply to a request.
*/
void handleReply(QNetworkReply* reply) {
quint64 size = reply->bytesAvailable();
reply->deleteLater();
setRunning(false);
setConnected(size > 0);
}
private:
void setConnected(bool connected) {
if (connected != _connected) {
_connected = connected;
emit connectedChanged(connected);
}
}
void setRunning(bool running) {
if (running != _running) {
_running = running;
emit runningChanged(running);
}
}
QNetworkConfigurationManager ncm;
QNetworkAccessManager nam;
bool _connected;
bool _running;
};
#endif // CONNECTIONCHECKER_H
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ConnectionHeaderFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = 'qml/components/ConnectionHeader.qml'
def generate(self) -> str:
content =\
"""\
import QtQuick 2.0
import Sailfish.Silica 1.0
SilicaItem {
id: connectionHeader
property bool connected: true
width: parent.width
height: 0
Row {
anchors.verticalCenter: parent.verticalCenter
Icon {
source: "image://theme/icon-m-website?" + Theme.errorColor
}
Label {
text: qsTr("Отсутствует соединение")
anchors.verticalCenter: parent.verticalCenter
}
}
states: State {
name: "show"
when: !connected
PropertyChanges {
target: connectionHeader
height: Theme.iconSizeMedium
}
}
transitions: Transition {
reversible: true
NumberAnimation {
properties: "height"
easing.type: Easing.InOutQuad
duration: 200
}
}
}
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ConnmanManagerFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = 'qml/components/ConnmanManager.qml'
def generate(self) -> str:
content =\
"""\
import QtQuick 2.0
import Nemo.DBus 2.0
DBusInterface {
property bool online: true
function propertyChanged(name, value) {
if (name === "State")
online = value === "online";
}
bus: DBus.SystemBus
service: "net.connman"
path: "/"
iface: "net.connman.Manager"
signalsEnabled: true
Component.onCompleted: {
call("GetProperties", undefined,
function(result) {
online = result["State"] === "online" || result["State"] == "ready";
},
function(error, message) {
// Ignore connman manager state in case it's not available
})
}
}
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class CoverFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = f"qml/cover/CoverPage.qml"
def generate(self) -> str:
content =\
f"""\
import QtQuick 2.0
import Sailfish.Silica 1.0
CoverBackground {{
CoverPlaceholder {{
text: qsTr("{self.config.application_name}")
icon {{
source: Qt.resolvedUrl("../icons/{self.config.application_name}.svg")
sourceSize {{ width: icon.width; height: icon.height }}
}}
forceFit: true
}}
}}
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class DesktopFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = f"{self.config.full_name}.desktop"
def generate(self) -> str:
content =\
f"""\
[Desktop Entry]
Type=Application
X-Nemo-Application-Type=silica-qt5
X-Nemo-Single-Instance=no
X-Aurora-Single-Cover=yes
Icon={self.config.full_name}
Exec=/usr/bin/{self.config.full_name} %u
Name={self.config.application_name}
Name[ru]={self.config.desktop_name}
[X-Application]
Permissions={';'.join(self.config.application_permission)}
OrganizationName={self.config.organization_name}
ApplicationName={self.config.application_name}
ExecDBus=/usr/bin/{self.config.full_name} %u
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
from configuration import Configuration
class FileGenerator:
def __init__(self, config: Configuration, project_dir: str = './') -> None:
self.config = config
self.project_dir = f"{project_dir}/{self.config.application_name}/"
self.path = None
def generate(self) -> str:
raise NotImplementedError
def save(self) -> None:
filename = self.project_dir + self.path
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename, mode='w', encoding='utf-8') as f:
f.write(self.generate())
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class MainFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = f"src/{self.config.application_name.lower()}.cpp"
def generate(self) -> str:
content =\
"""\
#include <QGuiApplication>
#include <QQmlContext>
#include <QQuickView>
#include <QScopedPointer>
#include <auroraapp.h>
#include "connectionchecker.h"
"""
if self.config.push_app_id:
content +=\
"""
#include "applicationcontroller.h"
#include "applicationservice.h"
"""
content +=\
f"""
int main(int argc, char *argv[])
{{
QScopedPointer<QGuiApplication> application(Aurora::Application::application(argc, argv));
application->setOrganizationName(QStringLiteral("{self.config.organization_name}"));
application->setApplicationName(QStringLiteral("{self.config.application_name}"));
qmlRegisterType<ConnectionChecker>("{self.config.organization_name}", 1, 0, "ConnectionChecker");
"""
if self.config.push_app_id:
content +=\
"""
auto applicationArgs = application->arguments();
applicationArgs.removeFirst();
if (ApplicationService::isRegistered()) {
return ApplicationService::updateApplicationArgs(applicationArgs);
} else {
auto applicationService = new ApplicationService(application.data());
auto applicationController = new ApplicationController(applicationArgs, application.data());
QObject::connect(applicationService, &ApplicationService::showGui,
applicationController, &ApplicationController::showGui);
return application->exec();
}
}
"""
else:
content +=\
f"""
QScopedPointer<QQuickView> view(Aurora::Application::createView());
view->rootContext()->setContextProperty("targetUrl", TARGET_URL);
view->setSource(Aurora::Application::pathTo(QStringLiteral("qml/{self.config.full_name}.qml")));
view->show();
return application->exec();
}}
"""
return content
# Copyright (C) 2023 Open Mobile Platform LLC.
# Contact: https://community.omprussia.ru/open-source
#
# This file is part of the Aurora OS WebApp Generator project.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from configuration import Configuration
from generators.filegenerator import FileGenerator
class ProFileGenerator(FileGenerator):
def __init__(self, config: Configuration, project_dir: str = './') -> None:
super().__init__(config, project_dir)
self.path = f"{self.config.full_name}.pro"
def generate(self) -> str:
configs = ['c++14', 'auroraapp', 'auroraapp_i18n']
defines = [fr"TARGET_URL=\\\"{self.config.url}\\\""]
distfiles = [
f"$$PWD/rpm/{self.config.full_name}.spec",
f"$$PWD/qml/{self.config.full_name}.qml",
'$$PWD/qml/components/ConnectionHeader.qml',
'$$PWD/qml/components/ConnmanManager.qml',
'$$PWD/qml/pages/WebViewPage.qml',
]
sources = [f"$$PWD/src/{self.config.application_name.lower()}.cpp"]
headers = ['$$PWD/src/connectionchecker.h']
if self.config.push_app_id:
configs.insert(0, 'link_pkgconfig')
defines.extend([
fr"DBUS_SERVICE=\\\"{self.config.full_name}\\\"",
fr"DBUS_PATH=\\\"/{self.config.full_name.replace('.', '/')}\\\"",
fr"DBUS_INTERFACE=\\\"{self.config.full_name}\\\"",
fr"APP_ID_FILE_PATH=\\\"$$APP_ID_PATH/$$APP_ID_FILE\\\"",
])
for classname in ['applicationservice', 'applicationcontroller']:
sources.append(f"$$PWD/src/{classname}.cpp")
headers.append(f"$$PWD/src/{classname}.h")
if not self.config.background_activity:
distfiles.append('$$PWD/qml/cover/CoverPage.qml')
content =\
fr"""TARGET = {self.config.full_name}
CONFIG += \
{self.__multiline(configs)}
"""
if self.config.push_app_id:
content +=\
fr"""
QT += dbus
PKGCONFIG += \
pushclient \
nemonotifications-qt5
APP_ID = {self.config.push_app_id}
APP_ID_PATH = /usr/share/$$TARGET
APP_ID_FILE = applicationid
applicationid_install.extra = echo $$APP_ID > $$OUT_PWD/$$APP_ID_FILE
applicationid_install.files = $$OUT_PWD/$$APP_ID_FILE
applicationid_install.path = $$APP_ID_PATH
applicationid_install.CONFIG = no_check_exist
QMAKE_CLEAN += \
$${{applicationid_install.files}}
QMAKE_EXTRA_TARGETS += \
applicationid_install
INSTALLS += \
applicationid_install
"""
content +=\
fr"""
DEFINES += \
{self.__multiline(defines)}
SOURCES += \
{self.__multiline(sources)}
HEADERS += \
{self.__multiline(headers)}
DISTFILES += \
{self.__multiline(distfiles)}
AURORAAPP_ICONS = 86x86 108x108 128x128 172x172
CONFIG += auroraapp_i18n
"""
return content
def __multiline(self, list):
return ' \\\n '.join(list)
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать