Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • develop
  • master
  • release-0.1.0
  • release-0.2.0
  • release-0.2.1
  • release-0.3.0
  • release-0.3.1
  • release-0.3.2
  • release-0.4.0
  • release-0.4.1
  • release-0.4.2
  • release-0.4.3
  • release-0.4.4
  • release-0.5.0
  • release-0.5.1
  • release-0.5.2
  • release-0.5.3
  • release-0.5.4
  • release-0.5.5
  • release-0.6.0
  • release-0.6.1
  • release-0.6.2
  • release-0.6.3
  • release-0.6.4
  • release-0.6.5
  • release-0.7.0
  • release-0.7.1
  • release-0.7.2
  • release-0.8.0
  • release-0.8.1
30 results

Target

Select target project
  • akiraohgaki/ocs-manager
  • dfn2/ocs-manager
  • azubieta/ocs-manager
  • rws77/ocs-manager
4 results
Select Git revision
  • develop
  • fix_build
  • master
  • update_dialog
  • release-0.1.0
  • release-0.2.0
  • release-0.2.1
  • release-0.3.0
  • release-0.3.1
  • release-0.3.2
  • release-0.4.0
  • release-0.4.1
  • release-0.4.2
  • release-0.4.3
  • release-0.4.4
  • release-0.5.0
  • release-0.5.1
  • release-0.5.2
  • release-0.5.3
  • release-0.5.4
  • release-0.5.5
  • release-0.6.0
  • release-0.6.1
  • release-0.6.2
  • release-0.6.3
  • release-0.6.4
  • release-0.6.5
  • release-0.7.0
  • release-0.7.1
  • release-0.7.2
  • release-0.8.0
  • release-0.8.1
32 results
Show changes
Showing
with 1212 additions and 471 deletions
This diff is collapsed.
......@@ -3,7 +3,7 @@
#include <QObject>
#include <QJsonObject>
namespace qtlib {
namespace Qtil {
class NetworkResource;
}
......@@ -14,13 +14,15 @@ class ItemHandler : public QObject
Q_OBJECT
public:
explicit ItemHandler(ConfigHandler *configHandler, QObject *parent = 0);
explicit ItemHandler(ConfigHandler *configHandler, QObject *parent = nullptr);
signals:
void metadataSetChanged();
void downloadStarted(QJsonObject result);
void downloadFinished(QJsonObject result);
void downloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal);
void saveStarted(QJsonObject result);
void saveFinished(QJsonObject result);
void installStarted(QJsonObject result);
void installFinished(QJsonObject result);
void uninstallStarted(QJsonObject result);
......@@ -29,16 +31,23 @@ signals:
public slots:
QJsonObject metadataSet() const;
void download(const QString &url, const QString &installType, const QString &providerKey = "", const QString &contentId = "");
void getItem(const QString &command, const QString &url, const QString &installType, const QString &filename = QString(),
const QString &providerKey = QString(), const QString &contentId = QString());
void getItemByOcsUrl(const QString &ocsUrl, const QString &providerKey = QString(), const QString &contentId = QString());
void uninstall(const QString &itemKey);
private slots:
void networkResourceFinished(qtlib::NetworkResource *resource);
void networkResourceFinished(Qtil::NetworkResource *resource);
private:
void setMetadataSet(const QJsonObject &metadataSet);
void install(qtlib::NetworkResource *resource);
void saveDownloadedFile(Qtil::NetworkResource *resource);
void installDownloadedFile(Qtil::NetworkResource *resource);
#ifdef APP_DESKTOP
bool installThemes(const QString &installType, const QString &name, const QString &srcDir, const QString &destDir);
#endif
ConfigHandler *configHandler_;
QJsonObject metadataSet_;
......
#include "ocshandler.h"
#include "ocsapihandler.h"
#include <QStringList>
#include <QJsonValue>
#include "qtlib_ocsapi.h"
#include "qtil_ocsapi.h"
#include "handlers/confighandler.h"
OcsHandler::OcsHandler(ConfigHandler *configHandler, QObject *parent)
OcsApiHandler::OcsApiHandler(ConfigHandler *configHandler, QObject *parent)
: QObject(parent), configHandler_(configHandler)
{}
bool OcsHandler::addProviders(const QString &providerFileUrl)
bool OcsApiHandler::addProviders(const QString &providerFileUrl) const
{
QJsonArray providers = qtlib::OcsApi::getProviderFile(QUrl(providerFileUrl));
auto providers = Qtil::OcsApi::getProviderFile(QUrl(providerFileUrl));
if (!providers.isEmpty()) {
foreach (const QJsonValue &providerValue, providers) {
QJsonObject provider = providerValue.toObject();
for (const auto providerValue : providers) {
auto provider = providerValue.toObject();
if (provider.contains("location")) {
// Use location (API base URL) as unique key
QString providerKey = provider["location"].toString();
auto providerKey = provider["location"].toString();
if (configHandler_->setUsrConfigProvidersProvider(providerKey, provider)) {
updateCategories(providerKey, true);
}
......@@ -29,7 +30,7 @@ bool OcsHandler::addProviders(const QString &providerFileUrl)
return false;
}
bool OcsHandler::removeProvider(const QString &providerKey)
bool OcsApiHandler::removeProvider(const QString &providerKey) const
{
if (configHandler_->removeUsrConfigProvidersProvider(providerKey)) {
configHandler_->removeUsrConfigCategoriesProvider(providerKey);
......@@ -38,11 +39,11 @@ bool OcsHandler::removeProvider(const QString &providerKey)
return false;
}
bool OcsHandler::updateAllCategories(bool force)
bool OcsApiHandler::updateAllCategories(bool force) const
{
QJsonObject providers = configHandler_->getUsrConfigProviders();
auto providers = configHandler_->getUsrConfigProviders();
if (!providers.isEmpty()) {
foreach (const QString &providerKey, providers.keys()) {
for (const auto &providerKey : providers.keys()) {
updateCategories(providerKey, force);
}
return true;
......@@ -50,16 +51,16 @@ bool OcsHandler::updateAllCategories(bool force)
return false;
}
bool OcsHandler::updateCategories(const QString &providerKey, bool force)
bool OcsApiHandler::updateCategories(const QString &providerKey, bool force) const
{
QJsonObject providers = configHandler_->getUsrConfigProviders();
auto providers = configHandler_->getUsrConfigProviders();
if (!providers.contains(providerKey)) {
return false;
}
QString baseUrl = providers[providerKey].toObject()["location"].toString();
QJsonObject response = qtlib::OcsApi(baseUrl, QUrl(baseUrl)).getContentCategories();
auto baseUrl = providers[providerKey].toObject()["location"].toString();
auto response = Qtil::OcsApi(baseUrl, QUrl(baseUrl)).getContentCategories();
if (!response.contains("data")) {
return false;
......@@ -68,7 +69,7 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force)
// Data type variation workaround, convert object to array
QJsonArray responseData;
if (response["data"].isObject()) {
foreach (const QJsonValue &dataValue, response["data"].toObject()) {
for (const auto dataValue : response["data"].toObject()) {
responseData.append(dataValue);
}
}
......@@ -76,17 +77,17 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force)
responseData = response["data"].toArray();
}
QJsonObject installTypes = configHandler_->getAppConfigInstallTypes();
auto installTypes = configHandler_->getAppConfigInstallTypes();
QJsonObject categories = configHandler_->getUsrConfigCategories();
auto categories = configHandler_->getUsrConfigCategories();
QJsonObject providerCategories;
if (!force && categories.contains(providerKey)) {
providerCategories = categories[providerKey].toObject();
}
QJsonObject newProviderCategories;
foreach (const QJsonValue &dataValue, responseData) {
QJsonObject data = dataValue.toObject();
for (const auto dataValue : responseData) {
auto data = dataValue.toObject();
// Data type variation workaround, convert int to string
QString id;
......@@ -98,9 +99,9 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force)
}
// Use category id as unique key
QString categoryKey = id;
auto categoryKey = id;
QString name = data["name"].toString();
auto name = data["name"].toString();
// display_name: Not compatible to legacy OCS-API
if (data.contains("display_name") && data["display_name"].toString() != "") {
name = data["display_name"].toString();
......@@ -112,7 +113,7 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force)
parentId = data["parent_id"].toString();
}
QString installType = configHandler_->getAppConfigApplication()["options"].toObject()["default_install_type"].toString();
auto installType = configHandler_->getAppConfigApplication()["options"].toObject()["default_install_type"].toString();
if (!force && providerCategories.contains(categoryKey)) {
installType = providerCategories[categoryKey].toObject()["install_type"].toString();
}
......@@ -133,9 +134,9 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force)
return configHandler_->setUsrConfigCategoriesProvider(providerKey, newProviderCategories);
}
QJsonObject OcsHandler::getContents(const QString &providerKeys, const QString &categoryKeys,
QJsonObject OcsApiHandler::getContents(const QString &providerKeys, const QString &categoryKeys,
const QString &xdgTypes, const QString &packageTypes,
const QString &search, const QString &sortmode, int pagesize, int page)
const QString &search, const QString &sortmode, int pagesize, int page) const
{
QJsonObject responseSet;
......@@ -149,23 +150,23 @@ QJsonObject OcsHandler::getContents(const QString &providerKeys, const QString &
categoryKeyList = categoryKeys.split(",");
}
QJsonObject providers = configHandler_->getUsrConfigProviders();
QJsonObject categories = configHandler_->getUsrConfigCategories();
auto providers = configHandler_->getUsrConfigProviders();
auto categories = configHandler_->getUsrConfigCategories();
foreach (const QString &providerKey, providers.keys()) {
for (const auto &providerKey : providers.keys()) {
if (!providerKeyList.isEmpty() && !providerKeyList.contains(providerKey)) {
continue;
}
QStringList categoryIdList;
QJsonObject providerCategories = categories[providerKey].toObject();
foreach (const QString &categoryKey, providerCategories.keys()) {
auto providerCategories = categories[providerKey].toObject();
for (const auto &categoryKey : providerCategories.keys()) {
if (!categoryKeyList.isEmpty() && !categoryKeyList.contains(categoryKey)) {
continue;
}
categoryIdList.append(providerCategories[categoryKey].toObject()["id"].toString());
}
if (!categoryIdList.isEmpty()) {
QString baseUrl = providers[providerKey].toObject()["location"].toString();
auto baseUrl = providers[providerKey].toObject()["location"].toString();
QUrlQuery query;
// categories: Comma-separated list is not compatible to legacy OCS-API
//query.addQueryItem("categories", categoryIdList.join(","));
......@@ -184,20 +185,20 @@ QJsonObject OcsHandler::getContents(const QString &providerKeys, const QString &
query.addQueryItem("sortmode", sortmode);
query.addQueryItem("pagesize", QString::number(pagesize));
query.addQueryItem("page", QString::number(page));
responseSet[providerKey] = qtlib::OcsApi(baseUrl, QUrl(baseUrl)).getContentDataSet(query);
responseSet[providerKey] = Qtil::OcsApi(baseUrl, QUrl(baseUrl)).getContentDataSet(query);
}
}
return responseSet;
}
QJsonObject OcsHandler::getContent(const QString &providerKey, const QString &contentId)
QJsonObject OcsApiHandler::getContent(const QString &providerKey, const QString &contentId) const
{
QJsonObject response;
QJsonObject providers = configHandler_->getUsrConfigProviders();
auto providers = configHandler_->getUsrConfigProviders();
if (providers.contains(providerKey)) {
QString baseUrl = providers[providerKey].toObject()["location"].toString();
response = qtlib::OcsApi(baseUrl, QUrl(baseUrl)).getContentData(contentId);
auto baseUrl = providers[providerKey].toObject()["location"].toString();
response = Qtil::OcsApi(baseUrl, QUrl(baseUrl)).getContentData(contentId);
}
return response;
}
#pragma once
#include <QObject>
#include <QJsonObject>
class ConfigHandler;
class OcsApiHandler : public QObject
{
Q_OBJECT
public:
explicit OcsApiHandler(ConfigHandler *configHandler, QObject *parent = nullptr);
public slots:
bool addProviders(const QString &providerFileUrl) const;
bool removeProvider(const QString &providerKey) const;
bool updateAllCategories(bool force = false) const;
bool updateCategories(const QString &providerKey, bool force = false) const;
QJsonObject getContents(const QString &providerKeys = QString(), const QString &categoryKeys = QString(),
const QString &xdgTypes = QString(), const QString &packageTypes = QString(),
const QString &search = QString(), const QString &sortmode = QString("new"), int pagesize = 25, int page = 0) const;
QJsonObject getContent(const QString &providerKey, const QString &contentId) const;
private:
ConfigHandler *configHandler_;
};
#pragma once
#include <QObject>
#include <QJsonObject>
class ConfigHandler;
class OcsHandler : public QObject
{
Q_OBJECT
public:
explicit OcsHandler(ConfigHandler *configHandler, QObject *parent = 0);
public slots:
bool addProviders(const QString &providerFileUrl);
bool removeProvider(const QString &providerKey);
bool updateAllCategories(bool force = false);
bool updateCategories(const QString &providerKey, bool force = false);
QJsonObject getContents(const QString &providerKeys = "", const QString &categoryKeys = "",
const QString &xdgTypes = "", const QString &packageTypes = "",
const QString &search = "", const QString &sortmode = "new", int pagesize = 25, int page = 0);
QJsonObject getContent(const QString &providerKey, const QString &contentId);
private:
ConfigHandler *configHandler_;
};
#include "systemhandler.h"
#ifdef QTLIB_UNIX
#include <QUrl>
#include <QDesktopServices>
#ifdef APP_DESKTOP
#include <QFileInfo>
#include <QProcess>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDBusVariant>
#include <QDebug>
#endif
#ifdef Q_OS_ANDROID
#include "qtil_package.h"
#endif
SystemHandler::SystemHandler(QObject *parent)
: QObject(parent)
{}
bool SystemHandler::isUnix()
bool SystemHandler::isMobileDevice() const
{
#ifdef QTLIB_UNIX
#if defined(APP_MOBILE)
return true;
#endif
return false;
}
QString SystemHandler::desktopEnvironment()
{
QString desktop = "unknown";
QString currentDesktop = "";
if (!qgetenv("XDG_CURRENT_DESKTOP").isEmpty()) {
currentDesktop = QString::fromLocal8Bit(qgetenv("XDG_CURRENT_DESKTOP").constData()).toLower();
}
else if (!qgetenv("XDG_SESSION_DESKTOP").isEmpty()) {
currentDesktop = QString::fromLocal8Bit(qgetenv("XDG_SESSION_DESKTOP").constData()).toLower();
}
else if (!qgetenv("DESKTOP_SESSION").isEmpty()) {
currentDesktop = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION").constData()).toLower();
}
if (currentDesktop.contains("kde") || currentDesktop.contains("plasma")) {
desktop = "kde";
}
else if (currentDesktop.contains("gnome") || currentDesktop.contains("unity")) {
desktop = "gnome";
}
else if (currentDesktop.contains("xfce")) {
desktop = "xfce";
}
return desktop;
}
bool SystemHandler::isApplicableType(const QString &installType)
{
QString desktop = desktopEnvironment();
if (installType == "wallpapers"
&& (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
#elif defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || defined(Q_OS_WINPHONE)
return true;
}
/*else if (installType == "icons"
&& (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
return true;
}
else if (installType == "cursors"
&& (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
return true;
}
else if ((installType == "aurorae_themes" && desktop == "kde")
|| (installType == "metacity_themes" && desktop == "gnome")
|| (installType == "xfwm4_themes" && desktop == "xfce")) {
#elif defined(Q_OS_LINUX) && defined(Q_PROCESSOR_ARM) // Ubuntu Phone, Plasma Phone
return true;
}*/
return false;
}
#ifdef QTLIB_UNIX
bool SystemHandler::applyFile(const QString &path, const QString &installType)
{
if (QFileInfo::exists(path) && isApplicableType(installType)) {
if (installType == "wallpapers") {
return applyWallpaper(path);
}
/*else if (installType == "icons") {
return applyIcon(path);
}
else if (installType == "cursors") {
return applyCursor(path);
}
else if (installType == "aurorae_themes"
|| installType == "metacity_themes"
|| installType == "xfwm4_themes") {
return applyWindowTheme(path);
}*/
}
return false;
}
#endif
#ifdef QTLIB_UNIX
bool SystemHandler::applyWallpaper(const QString &path)
{
QString desktop = desktopEnvironment();
if (desktop == "kde") {
// plasma5.6+
QDBusMessage message = QDBusMessage::createMethodCall("org.kde.plasmashell", "/PlasmaShell", "org.kde.PlasmaShell", "evaluateScript");
QVariantList arguments;
QString script;
QTextStream out(&script);
out << "for (var key in desktops()) {"
<< "var d = desktops()[key];"
<< "d.wallpaperPlugin = 'org.kde.image';"
<< "d.currentConfigGroup = ['Wallpaper', 'org.kde.image', 'General'];"
<< "d.writeConfig('Image', 'file://" + path + "');"
<< "}";
arguments << QVariant(script);
message.setArguments(arguments);
QDBusMessage reply = QDBusConnection::sessionBus().call(message);
if (reply.type() == QDBusMessage::ErrorMessage) {
qWarning() << reply.errorMessage();
return false;
}
return true;
}
else if (desktop == "gnome") {
QStringList arguments;
// gnome3
arguments << "set" << "org.gnome.desktop.background" << "picture-uri" << "file://" + path;
return QProcess::startDetached("gsettings", arguments);
// gnome2
//arguments << "--type=string" << "--set" << "/desktop/gnome/background/picture_filename" << path;
//return QProcess::startDetached("gconftool-2", arguments);
}
else if (desktop == "xfce") {
QDBusMessage message = QDBusMessage::createMethodCall("org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", "SetProperty");
QVariantList arguments;
QString channelValue = "xfce4-desktop";
//QString propertyValue = "/backdrop/screen0/monitor0/image-path";
QString propertyValue = "/backdrop/screen0/monitor0/workspace0/last-image";
QDBusVariant valueValue(path);
arguments << QVariant(channelValue) << QVariant(propertyValue) << QVariant::fromValue(valueValue);
message.setArguments(arguments);
QDBusMessage reply = QDBusConnection::sessionBus().call(message);
if (reply.type() == QDBusMessage::ErrorMessage) {
qWarning() << reply.errorMessage();
return false;
}
return true;
}
return false;
}
bool SystemHandler::applyIcon(const QString &path)
bool SystemHandler::openUrl(const QString &url) const
{
qDebug() << path;
QString desktop = desktopEnvironment();
auto path = url;
path.replace("file://localhost", "", Qt::CaseInsensitive);
path.replace("file://", "", Qt::CaseInsensitive);
if (desktop == "kde") {
}
else if (desktop == "gnome") {
}
else if (desktop == "xfce") {
#ifdef APP_DESKTOP
if ((path.endsWith(".appimage", Qt::CaseInsensitive) || path.endsWith(".exe", Qt::CaseInsensitive))
&& QFileInfo(path).isExecutable()) {
return QProcess::startDetached(path);
}
return false;
}
bool SystemHandler::applyCursor(const QString &path)
{
qDebug() << path;
QString desktop = desktopEnvironment();
#endif
if (desktop == "kde") {
}
else if (desktop == "gnome") {
}
else if (desktop == "xfce") {
}
return false;
#ifdef Q_OS_ANDROID
if (path.endsWith(".apk", Qt::CaseInsensitive)) {
return Qtil::Package(path).installAsApk();
}
#endif
bool SystemHandler::applyWindowTheme(const QString &path)
{
qDebug() << path;
QString desktop = desktopEnvironment();
if (desktop == "kde") {
}
else if (desktop == "gnome") {
return QDesktopServices::openUrl(QUrl(url));
}
else if (desktop == "xfce") {
}
return false;
}
#endif
......@@ -7,23 +7,9 @@ class SystemHandler : public QObject
Q_OBJECT
public:
explicit SystemHandler(QObject *parent = 0);
explicit SystemHandler(QObject *parent = nullptr);
public slots:
bool isUnix();
QString desktopEnvironment();
bool isApplicableType(const QString &installType);
#ifdef QTLIB_UNIX
bool applyFile(const QString &path, const QString &installType);
#endif
private:
#ifdef QTLIB_UNIX
bool applyWallpaper(const QString &path);
bool applyIcon(const QString &path);
bool applyCursor(const QString &path);
bool applyWindowTheme(const QString &path);
#endif
bool isMobileDevice() const;
bool openUrl(const QString &url) const;
};
#include "updatehandler.h"
#include <QStringList>
#include <QJsonValue>
#include <QJsonArray>
#include <QDateTime>
#include "qtil_file.h"
#include "handlers/confighandler.h"
#ifdef APP_DESKTOP
#include "updaters/appimageupdater.h"
#endif
UpdateHandler::UpdateHandler(ConfigHandler *configHandler, QObject *parent)
: QObject(parent), configHandler_(configHandler)
{}
void UpdateHandler::checkAll()
{
// Resets data
QJsonObject updateAvailableItems;
configHandler_->setUsrConfigUpdateAvailableItems(updateAvailableItems);
auto installedItems = configHandler_->getUsrConfigInstalledItems();
if (installedItems.isEmpty()) {
emit checkAllStarted(false);
return;
}
emit checkAllStarted(true);
for (const auto &itemKey : installedItems.keys()) {
auto installedItem = installedItems[itemKey].toObject();
auto filename = installedItem["filename"].toString();
auto installType = installedItem["install_type"].toString();
auto filePath = configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString() + "/" + filename;
QString updateMethod = "";
if (installType == "bin") {
#ifdef APP_DESKTOP
if (filePath.endsWith(".appimage", Qt::CaseInsensitive)) {
if (AppImageUpdater(itemKey, filePath).checkForChanges()) {
updateMethod = "appimageupdate";
}
//else if (OcsFileUpdater(url).checkFile()) {
// updateMethod = "appimageupdate_ocs";
//}
}
#endif
}
if (!updateMethod.isEmpty()) {
QJsonObject updateAvailableItem;
updateAvailableItem["installed_item"] = itemKey;
updateAvailableItem["update_method"] = updateMethod;
// Use installed item's key as unique key to the update available item
configHandler_->setUsrConfigUpdateAvailableItemsItem(itemKey, updateAvailableItem);
}
}
auto application = configHandler_->getUsrConfigApplication();
application["update_checked_at"] = QDateTime::currentMSecsSinceEpoch();
configHandler_->setUsrConfigApplication(application);
emit checkAllFinished(true);
}
void UpdateHandler::update(const QString &itemKey)
{
auto updateAvailableItems = configHandler_->getUsrConfigUpdateAvailableItems();
if (!updateAvailableItems.contains(itemKey)) {
emit updateStarted(itemKey, false);
return;
}
auto updateMethod = updateAvailableItems[itemKey].toObject()["update_method"].toString();
#ifdef APP_DESKTOP
if (updateMethod == "appimageupdate") {
updateAppImage(itemKey);
}
//else if (updateMethod == "appimageupdate_ocs") {
// updateAppImageOcs(itemKey);
//}
#endif
}
#ifdef APP_DESKTOP
void UpdateHandler::appImageUpdaterFinished(AppImageUpdater *updater)
{
auto itemKey = updater->id();
auto metadata = metadataSet_[itemKey].toObject();
metadataSet_.remove(itemKey);
if (!updater->isFinishedWithNoError()) {
emit updateFinished(itemKey, false);
updater->deleteLater();
return;
}
auto installedItemKey = metadata["installed_item_key"].toString();
auto installedItem = metadata["installed_item_obj"].toObject();
auto newFilename = metadata["new_filename"].toString();
auto filename = installedItem["filename"].toString();
installedItem["filename"] = newFilename;
QJsonArray files;
files.append(QJsonValue(newFilename));
installedItem["files"] = files;
installedItem["installed_at"] = QDateTime::currentMSecsSinceEpoch();
configHandler_->setUsrConfigInstalledItemsItem(installedItemKey, installedItem);
if (newFilename != filename) {
Qtil::File(updater->path()).remove();
}
configHandler_->removeUsrConfigUpdateAvailableItemsItem(itemKey);
emit updateFinished(itemKey, true);
updater->deleteLater();
}
#endif
#ifdef APP_DESKTOP
void UpdateHandler::updateAppImage(const QString &itemKey)
{
auto updateAvailableItem = configHandler_->getUsrConfigUpdateAvailableItems()[itemKey].toObject();
auto installedItemKey = updateAvailableItem["installed_item"].toString();
auto installedItems = configHandler_->getUsrConfigInstalledItems();
if (!installedItems.contains(installedItemKey)) {
emit updateStarted(itemKey, false);
return;
}
auto installedItem = installedItems[installedItemKey].toObject();
auto filename = installedItem["filename"].toString();
auto installType = installedItem["install_type"].toString();
auto filePath = configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString() + "/" + filename;
auto *updater = new AppImageUpdater(itemKey, filePath, this);
connect(updater, &AppImageUpdater::updateProgress, this, &UpdateHandler::updateProgress);
connect(updater, &AppImageUpdater::finished, this, &UpdateHandler::appImageUpdaterFinished);
QJsonObject metadata;
metadata["installed_item_key"] = installedItemKey;
metadata["installed_item_obj"] = installedItem;
metadata["new_filename"] = filename;
QString assembledNewFilename = "";
QString rawNewFilename = "";
auto updateInformation = updater->describeAppImage();
for (const auto &info : updateInformation.split("\n")) {
if (info.endsWith(".zsync", Qt::CaseInsensitive)) {
if (info.startsWith("Assembled ZSync URL:", Qt::CaseInsensitive)) {
assembledNewFilename = info.split("/").last().replace(".zsync", "", Qt::CaseInsensitive);
}
else if (info.startsWith("Raw update information:", Qt::CaseInsensitive)) {
rawNewFilename = info.split("|").last().split("/").last().replace(".zsync", "", Qt::CaseInsensitive);
}
}
}
if (!assembledNewFilename.isEmpty()) {
metadata["new_filename"] = assembledNewFilename;
}
else if (!rawNewFilename.isEmpty() && !rawNewFilename.contains("*")) {
metadata["new_filename"] = rawNewFilename;
}
metadataSet_[itemKey] = metadata;
emit updateStarted(itemKey, true);
updater->start();
}
#endif
#pragma once
#include <QObject>
#include <QJsonObject>
class ConfigHandler;
#ifdef APP_DESKTOP
class AppImageUpdater;
#endif
class UpdateHandler : public QObject
{
Q_OBJECT
public:
explicit UpdateHandler(ConfigHandler *configHandler, QObject *parent = nullptr);
signals:
void checkAllStarted(bool status);
void checkAllFinished(bool status);
void updateStarted(QString itemKey, bool status);
void updateFinished(QString itemKey, bool status);
void updateProgress(QString itemKey, double progress);
public slots:
void checkAll();
void update(const QString &itemKey);
private slots:
#ifdef APP_DESKTOP
void appImageUpdaterFinished(AppImageUpdater *updater);
#endif
private:
#ifdef APP_DESKTOP
void updateAppImage(const QString &itemKey);
#endif
ConfigHandler *configHandler_;
QJsonObject metadataSet_;
};
#include <QStringList>
#include <QJsonObject>
//#include <QTranslator>
//#include <QLocale>
#include <QTranslator>
#include <QLocale>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QIcon>
#include <QDebug>
#include "handlers/confighandler.h"
......@@ -13,21 +14,25 @@
int main(int argc, char *argv[])
{
// Init
QCoreApplication app(argc, argv);
QGuiApplication app(argc, argv); // This is backend program, but need GUI module
ConfigHandler *configHandler = new ConfigHandler();
QJsonObject appConfigApplication = configHandler->getAppConfigApplication();
auto envPath = QString::fromLocal8Bit(qgetenv("PATH").constData()) + ":" + app.applicationDirPath();
qputenv("PATH", envPath.toUtf8().constData());
auto *configHandler = new ConfigHandler(&app);
auto appConfigApplication = configHandler->getAppConfigApplication();
app.setApplicationName(appConfigApplication["name"].toString());
app.setApplicationVersion(appConfigApplication["version"].toString());
app.setOrganizationName(appConfigApplication["organization"].toString());
app.setOrganizationDomain(appConfigApplication["domain"].toString());
app.setWindowIcon(QIcon::fromTheme(appConfigApplication["id"].toString(), QIcon(appConfigApplication["icon"].toString())));
// Setup translator
//QTranslator translator;
//if (translator.load(QLocale(), "messages", ".", ":/i18n")) {
// app.installTranslator(&translator);
//}
QTranslator translator;
if (translator.load(QLocale(), "messages", ".", ":/i18n")) {
app.installTranslator(&translator);
}
// Setup CLI
QCommandLineParser clParser;
......@@ -42,14 +47,14 @@ int main(int argc, char *argv[])
clParser.process(app);
int port = clParser.value(clOptionPort).toInt();
auto port = clParser.value(clOptionPort).toUShort();
// Setup websocket server
WebSocketServer *wsServer = new WebSocketServer(configHandler, appConfigApplication["id"].toString(), port, &app);
QObject::connect(wsServer, &WebSocketServer::stopped, &app, &QCoreApplication::quit);
auto *wsServer = new WebSocketServer(configHandler, appConfigApplication["id"].toString(), port, &app);
QObject::connect(wsServer, &WebSocketServer::stopped, &app, &QGuiApplication::quit);
if (wsServer->start()) {
qDebug() << "Websocket server started at:" << wsServer->serverUrl().toString();
qInfo() << "Websocket server started at:" << wsServer->serverUrl().toString();
}
else {
qCritical() << "Failed to start websocket server:" << wsServer->errorString();
......
#include "appimageupdater.h"
#include <QTimer>
#include "appimage/update.h"
AppImageUpdater::AppImageUpdater(const QString &id, const QString &path, QObject *parent)
: QObject(parent), id_(id), path_(path)
{
isFinishedWithNoError_ = false;
errorString_ = "";
updater_ = new appimage::update::Updater(path_.toStdString(), false);
}
AppImageUpdater::~AppImageUpdater()
{
delete updater_;
}
QString AppImageUpdater::id() const
{
return id_;
}
QString AppImageUpdater::path() const
{
return path_;
}
bool AppImageUpdater::isFinishedWithNoError() const
{
return isFinishedWithNoError_;
}
QString AppImageUpdater::errorString() const
{
return errorString_;
}
QString AppImageUpdater::describeAppImage() const
{
std::string description;
if (updater_->describeAppImage(description)) {
return QString::fromStdString(description);
}
return QString();
}
bool AppImageUpdater::checkForChanges() const
{
bool updateAvailable;
if (updater_->checkForChanges(updateAvailable)) {
return updateAvailable;
}
return false;
}
void AppImageUpdater::start()
{
isFinishedWithNoError_ = false;
errorString_ = "";
if (!updater_->start()) {
emit finished(this);
return;
}
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &AppImageUpdater::checkProgress);
connect(this, &AppImageUpdater::finished, timer, &QTimer::stop);
timer->start(100);
}
void AppImageUpdater::checkProgress()
{
if (!updater_->isDone()) {
double progress;
if (updater_->progress(progress)) {
emit updateProgress(id_, progress);
}
return;
}
if (updater_->hasError()) {
std::string message;
while (updater_->nextStatusMessage(message)) {
errorString_ += QString::fromStdString(message) + "\n";
}
emit finished(this);
return;
}
isFinishedWithNoError_ = true;
emit finished(this);
}
#pragma once
#include <QObject>
namespace appimage {
namespace update {
class Updater;
}
}
class AppImageUpdater : public QObject
{
Q_OBJECT
public:
explicit AppImageUpdater(const QString &id, const QString &path, QObject *parent = nullptr);
~AppImageUpdater();
QString id() const;
QString path() const;
bool isFinishedWithNoError() const;
QString errorString() const;
QString describeAppImage() const;
bool checkForChanges() const;
void start();
signals:
void finished(AppImageUpdater *updater);
void updateProgress(QString id, double progress);
private slots:
void checkProgress();
private:
QString id_;
QString path_;
bool isFinishedWithNoError_;
QString errorString_;
appimage::update::Updater *updater_;
};
This diff is collapsed.
......@@ -2,22 +2,25 @@
#include <QObject>
#include <QUrl>
//#include <QJsonObject>
#include <QJsonObject>
#include <QJsonArray>
class QWebSocketServer;
class QWebSocket;
class ConfigHandler;
class SystemHandler;
class OcsHandler;
class OcsApiHandler;
class ItemHandler;
class UpdateHandler;
class DesktopThemeHandler;
class WebSocketServer : public QObject
{
Q_OBJECT
public:
explicit WebSocketServer(ConfigHandler *configHandler, const QString &serverName = "WebSocketServer", quint16 serverPort = 0, QObject *parent = 0);
explicit WebSocketServer(ConfigHandler *configHandler, const QString &serverName = QString("WebSocketServer"), quint16 serverPort = 0, QObject *parent = nullptr);
~WebSocketServer();
signals:
......@@ -27,9 +30,9 @@ signals:
public slots:
bool start();
void stop();
bool isError();
QString errorString();
QUrl serverUrl();
bool isError() const;
QString errorString() const;
QUrl serverUrl() const;
private slots:
void wsNewConnection();
......@@ -37,16 +40,36 @@ private slots:
void wsTextMessageReceived(const QString &message);
void wsBinaryMessageReceived(const QByteArray &message);
void itemHandlerMetadataSetChanged();
void itemHandlerDownloadStarted(QJsonObject result);
void itemHandlerDownloadFinished(QJsonObject result);
void itemHandlerDownloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal);
void itemHandlerSaveStarted(QJsonObject result);
void itemHandlerSaveFinished(QJsonObject result);
void itemHandlerInstallStarted(QJsonObject result);
void itemHandlerInstallFinished(QJsonObject result);
void itemHandlerUninstallStarted(QJsonObject result);
void itemHandlerUninstallFinished(QJsonObject result);
void updateHandlerCheckAllStarted(bool status);
void updateHandlerCheckAllFinished(bool status);
void updateHandlerUpdateStarted(QString itemKey, bool status);
void updateHandlerUpdateFinished(QString itemKey, bool status);
void updateHandlerUpdateProgress(QString itemKey, double progress);
private:
void callFunction(const QJsonObject &request, QWebSocket *wsClient);
void receiveMessage(const QString &id, const QString &func, const QJsonArray &data);
void sendMessage(const QString &id, const QString &func, const QJsonArray &data);
ConfigHandler *configHandler_;
SystemHandler *systemHandler_;
OcsApiHandler *ocsApiHandler_;
ItemHandler *itemHandler_;
UpdateHandler *updateHandler_;
DesktopThemeHandler *desktopThemeHandler_;
QString serverName_;
quint16 serverPort_;
QWebSocketServer *wsServer_;
QList<QWebSocket *> wsClients_;
ConfigHandler *configHandler_;
SystemHandler *systemHandler_;
OcsHandler *ocsHandler_;
ItemHandler *itemHandler_;
};
contains(DEFINES, APP_DESKTOP) {
isEmpty(PREFIX) {
PREFIX = /usr/local
}
SRCDIR = $${PWD}
BINDIR = $${PREFIX}/bin
DATADIR = $${PREFIX}/share
target.path = $${BINDIR}
desktop.files = $${SRCDIR}/desktop/$${TARGET}.desktop
desktop.path = $${DATADIR}/applications
icon.files = $${SRCDIR}/desktop/$${TARGET}.svg
icon.path = $${DATADIR}/icons/hicolor/scalable/apps
INSTALLS += target desktop icon
}
export(INSTALLS)
RESOURCES += $${PWD}/desktop.qrc
DISTFILES += $${PWD}/ocs-manager.desktop
<RCC>
<qresource prefix="/desktop">
<file>ocs-manager.svg</file>
</qresource>
</RCC>
[Desktop Entry]
Name=ocs-manager
Exec=ocs-manager
Icon=ocs-manager
Type=Application
Terminal=true
NoDisplay=true
Categories=Network;Utility;
X-AppImage-Integrate=false
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="130" height="130" viewBox="0, 0, 130, 130">
<g id="Background">
<rect x="0" y="0" width="130" height="130" fill="#000000" fill-opacity="0"/>
</g>
<defs>
<linearGradient id="Gradient_1" gradientUnits="userSpaceOnUse" x1="-0" y1="0" x2="1" y2="0" gradientTransform="matrix(-10.879, 51.573, -55.925, -10.033, 115.314, 55.906)">
<stop offset="0" stop-color="#FF2F00"/>
<stop offset="0.07" stop-color="#FF2F00"/>
<stop offset="1" stop-color="#FF8400"/>
</linearGradient>
<linearGradient id="Gradient_2" gradientUnits="userSpaceOnUse" x1="-0" y1="0" x2="1" y2="0" gradientTransform="matrix(24.87, 0, 0, 24.689, 97.286, 52.662)">
<stop offset="0" stop-color="#FF2F00"/>
<stop offset="1" stop-color="#FF8900"/>
</linearGradient>
<linearGradient id="Gradient_3" gradientUnits="userSpaceOnUse" x1="0" y1="-0" x2="1" y2="-0" gradientTransform="matrix(68.978, 0, 0, 70.77, 37.204, 17.652)">
<stop offset="0" stop-color="#2147A0"/>
<stop offset="1" stop-color="#00F2A1"/>
</linearGradient>
<linearGradient id="Gradient_4" gradientUnits="userSpaceOnUse" x1="-0" y1="0" x2="1" y2="0" gradientTransform="matrix(45.982, 0, 0, 51.587, 23.818, 17.568)">
<stop offset="0" stop-color="#204EA0"/>
<stop offset="1" stop-color="#01F0A1"/>
</linearGradient>
<linearGradient id="Gradient_5" gradientUnits="userSpaceOnUse" x1="-0" y1="-0" x2="1" y2="-0" gradientTransform="matrix(20.249, 34.848, -33.693, 20.943, 78.418, 93.962)">
<stop offset="0" stop-color="#F0C209"/>
<stop offset="0.14" stop-color="#F0C209"/>
<stop offset="0.63" stop-color="#DE920A"/>
<stop offset="1" stop-color="#D67C0B"/>
</linearGradient>
<linearGradient id="Gradient_6" gradientUnits="userSpaceOnUse" x1="-0" y1="-0" x2="1" y2="-0" gradientTransform="matrix(26.051, 45.434, -43.36, 27.297, 40.828, 90.812)">
<stop offset="0" stop-color="#F0C209"/>
<stop offset="0.14" stop-color="#F0C209"/>
<stop offset="1" stop-color="#D4760B"/>
</linearGradient>
<linearGradient id="Gradient_7" gradientUnits="userSpaceOnUse" x1="0" y1="-0" x2="1" y2="-0" gradientTransform="matrix(-35.942, 54.407, -51.313, -38.109, 41.57, 45.214)">
<stop offset="0" stop-color="#B1115D"/>
<stop offset="0.14" stop-color="#B1115D"/>
<stop offset="1" stop-color="#D72881"/>
</linearGradient>
<linearGradient id="Gradient_8" gradientUnits="userSpaceOnUse" x1="-0" y1="-0" x2="1" y2="-0" gradientTransform="matrix(25.635, 0, 0, 22.663, 7.08, 62.99)">
<stop offset="0" stop-color="#B1115D"/>
<stop offset="1" stop-color="#D62881"/>
</linearGradient>
</defs>
<g id="Layer_1">
<path d="M93.26,97.462 L93.648,97.732 L107.152,111.236 L107.452,111.694 L107.546,112.234 L107.416,112.766 L107.086,113.202 C106.47,113.736 105.848,114.262 105.216,114.774 C104.052,115.716 102.856,116.616 101.63,117.474 C98.04,119.986 94.194,122.128 90.17,123.852 C88.9,124.398 87.612,124.9 86.308,125.36 C85.85,125.522 85.39,125.68 84.93,125.83 C84.732,125.896 84.534,125.96 84.336,126.022 C84.336,126.022 84.336,126.02 84.336,126.02 C84.334,126.022 84.334,126.022 84.332,126.024 C84.316,126.028 84.298,126.034 84.282,126.04 C84.28,126.04 84.278,126.04 84.276,126.04 C84.276,126.04 84.278,126.04 84.278,126.04 C83.992,126.132 83.706,126.218 83.42,126.304 C82.798,126.492 82.172,126.67 81.544,126.838 C79.692,127.332 77.818,127.744 75.928,128.068 C72.476,128.664 68.976,128.972 65.472,128.998 C63.058,129.016 60.642,128.9 58.24,128.646 C55.688,128.378 53.154,127.956 50.652,127.382 C46.892,126.52 43.21,125.312 39.666,123.782 C38.172,123.136 36.702,122.434 35.26,121.676 C34.542,121.298 33.832,120.906 33.13,120.502 L33.018,120.438 L32.91,120.374 L32.44,120.082 L31.972,119.81 C31.766,119.696 31.656,119.618 31.482,119.52 C31.478,119.518 31.202,119.346 31.2,119.344 C30.964,119.198 30.728,119.048 30.494,118.898 C29.934,118.538 29.378,118.17 28.83,117.792 C27.504,116.882 26.214,115.922 24.96,114.916 C24.312,114.396 23.676,113.862 23.048,113.318 L22.924,113.21 L22.594,112.774 L22.464,112.244 L22.556,111.704 L22.856,111.246 L31.236,102.848 L31.672,102.556 L32.188,102.452 L32.702,102.554 L33.14,102.846 L33.432,103.282 L33.534,103.798 L33.534,117.322 L49.63,100.588 L50.07,100.284 L50.596,100.176 L70.856,100.142 L82.906,100.142 L84.608,100.08 C85.12,100.018 85.634,99.972 86.146,99.896 C86.39,99.858 86.632,99.794 86.874,99.744 C87.578,99.594 87.58,99.6 88.264,99.382 C88.42,99.332 89.108,99.104 89.336,99.014 C89.494,98.952 89.956,98.748 90.116,98.668 C90.386,98.532 90.606,98.398 90.864,98.248 C90.996,98.17 91.128,98.094 91.26,98.016 C91.374,97.95 91.49,97.89 91.598,97.82 C91.704,97.75 91.804,97.67 91.906,97.596 L92.332,97.388 L92.802,97.342 C92.956,97.382 93.108,97.422 93.26,97.462 z M112.788,22.61 C112.934,22.72 113.084,22.824 113.224,22.94 C113.26,22.97 113.286,23.012 113.318,23.048 C113.414,23.158 113.51,23.268 113.604,23.38 C113.856,23.674 114.108,23.972 114.354,24.272 C115.128,25.208 115.876,26.166 116.596,27.146 C119.434,31.008 121.84,35.186 123.746,39.582 C125.368,43.322 126.63,47.218 127.506,51.2 C127.788,52.482 128.03,53.774 128.232,55.072 C128.304,55.524 128.37,55.976 128.43,56.43 C128.45,56.582 128.47,56.734 128.49,56.886 C128.496,56.936 128.504,56.988 128.508,57.04 C128.508,57.04 128.508,57.038 128.508,57.038 C128.54,57.282 128.568,57.528 128.596,57.772 C128.656,58.306 128.708,58.84 128.756,59.374 C128.904,61.076 128.984,62.786 128.998,64.496 C129.028,68.37 128.712,72.246 128.046,76.062 C127.374,79.908 126.348,83.692 124.982,87.35 C123.272,91.932 121.032,96.314 118.322,100.386 C117.318,101.896 116.252,103.362 115.124,104.78 C114.578,105.466 114.02,106.138 113.448,106.802 L113.332,106.934 L113.22,107.064 L112.784,107.396 L112.252,107.526 L111.712,107.432 L111.254,107.132 L96.332,92.212 C96.248,92.096 96.146,91.992 96.082,91.864 C96.018,91.736 95.974,91.596 95.952,91.454 C95.894,91.056 96.114,90.152 96.15,89.944 L96.274,88.852 C96.37,87.674 96.37,87.674 96.4,86.492 L96.4,43.438 C96.38,42.654 96.37,41.84 96.306,41.056 C96.274,40.686 96.23,40.318 96.182,39.95 C96.164,39.814 96.018,39.048 95.994,38.918 L95.984,38.484 C96.112,38.072 96.114,38.068 96.366,37.718 L111.26,22.87 L111.718,22.572 L112.256,22.48 C112.434,22.522 112.61,22.566 112.788,22.61 z M18.282,22.572 L18.74,22.87 L33.634,37.718 C33.718,37.836 33.824,37.942 33.89,38.074 C33.954,38.206 33.998,38.35 34.018,38.494 C34.06,38.822 33.936,39.262 33.878,39.562 L33.784,40.184 C33.692,40.82 33.692,40.82 33.63,41.46 L33.566,43.442 L33.566,91.722 L33.464,92.236 L33.172,92.672 L18.73,107.116 L18.272,107.416 L17.734,107.508 L17.202,107.378 L16.766,107.048 C16.266,106.474 15.776,105.894 15.298,105.304 C14.886,104.798 14.482,104.286 14.088,103.766 C13.956,103.594 13.824,103.42 13.694,103.246 C13.662,103.202 13.63,103.158 13.596,103.114 C13.564,103.072 13.532,103.028 13.5,102.986 C13.5,102.986 13.502,102.986 13.502,102.986 C13.47,102.944 13.438,102.902 13.408,102.86 C13.378,102.818 13.346,102.776 13.316,102.734 C13.224,102.61 13.134,102.484 13.044,102.358 C12.742,101.94 12.444,101.516 12.152,101.09 C9.51,97.23 7.292,93.082 5.554,88.738 C3.88,84.556 2.654,80.196 1.902,75.754 C1.308,72.258 1.01,68.712 1,65.166 C0.992,62.138 1.196,59.108 1.614,56.108 C1.974,53.528 2.49,50.97 3.164,48.454 C3.856,45.862 4.714,43.314 5.73,40.83 C7.442,36.636 9.606,32.628 12.166,28.89 C13.09,27.542 14.066,26.226 15.092,24.952 C15.602,24.314 16.128,23.688 16.662,23.07 L16.776,22.94 L17.212,22.61 L17.744,22.48 C17.922,22.51 18.102,22.54 18.282,22.572 z M47.054,29.854 C46.318,29.872 45.516,29.882 44.78,29.948 C44.03,30.014 43.524,30.102 42.788,30.254 C42.47,30.32 42.154,30.384 41.84,30.468 C41.546,30.546 41.258,30.64 40.97,30.738 C40.698,30.83 40.426,30.928 40.162,31.038 C39.736,31.214 39.402,31.378 39.016,31.596 C38.902,31.66 38.786,31.724 38.676,31.794 C38.404,31.962 38.254,32.08 37.994,32.268 L37.57,32.474 C37.16,32.516 37.032,32.582 36.64,32.402 C36.498,32.336 36.382,32.222 36.252,32.132 L22.868,18.746 L22.566,18.288 L22.474,17.748 L22.604,17.216 L22.934,16.78 C23.242,16.512 23.552,16.248 23.864,15.984 C24.49,15.458 25.126,14.944 25.77,14.444 C27.712,12.936 29.738,11.538 31.838,10.262 C34.456,8.672 37.188,7.27 40.006,6.072 C42.638,4.954 45.344,4.012 48.104,3.258 C51.562,2.312 55.098,1.662 58.666,1.31 C59.96,1.182 61.26,1.094 62.56,1.046 C63.248,1.02 63.936,1.006 64.624,1.002 C64.8,1 64.978,1 65.154,1 C65.822,1.002 66.49,1.014 67.156,1.036 C67.768,1.056 68.38,1.084 68.99,1.122 C69.192,1.136 69.396,1.148 69.598,1.162 C69.652,1.166 69.846,1.18 69.9,1.186 C69.902,1.186 69.904,1.186 69.904,1.186 C69.904,1.186 69.904,1.186 69.904,1.186 C69.978,1.192 70.052,1.196 70.126,1.202 C70.35,1.22 70.574,1.24 70.798,1.26 C74.334,1.578 77.842,2.19 81.274,3.092 C84.1,3.834 86.874,4.77 89.572,5.894 C92.238,7.004 94.826,8.298 97.318,9.758 C99.626,11.112 101.85,12.612 103.97,14.244 C104.99,15.028 105.986,15.844 106.958,16.688 L107.066,16.78 L107.396,17.218 L107.526,17.748 L107.434,18.288 L107.132,18.746 L93.748,32.132 L93.354,32.404 C93.2,32.444 93.05,32.51 92.892,32.522 C92.456,32.554 92.36,32.442 91.99,32.256 L91.954,32.23 L91.996,32.252 L91.89,32.192 L90.97,31.62 L90.086,31.15 C89.21,30.804 88.97,30.68 88.036,30.438 C87.292,30.244 86.432,30.102 85.672,30.008 C85.238,29.956 84.806,29.91 84.37,29.884 C83.898,29.858 83.424,29.864 82.95,29.854 L47.054,29.854 z" fill="#CCCCCC" id="logo-outline2-0"/>
<g id="logo-rounded2-0">
<path d="M127.17,57.172 C127.49,59.736 127.656,62.348 127.656,65 C127.656,80.758 121.824,95.166 112.204,106.182 L97.284,91.26 L97.482,90.138 L97.614,88.984 L97.712,87.762 L97.746,86.51 L97.746,81.534 C107.508,73.364 117.322,65.248 127.17,57.172 z" fill="url(#Gradient_1)" id="path45-6"/>
<path d="M112.21,23.824 C120.216,32.992 125.596,44.512 127.174,57.204 L97.746,81.566 L97.746,43.42 L97.712,42.168 L97.646,40.946 L97.514,39.758 L97.416,39.198 L97.316,38.67 L112.21,23.824 z" fill="url(#Gradient_2)" id="path47-1"/>
<path d="M69.772,2.524 C71.034,2.62 72.284,2.752 73.524,2.922 L92.598,31.048 L91.642,30.454 L90.652,29.926 L89.564,29.498 L88.376,29.134 L87.154,28.87 L85.834,28.674 L84.45,28.542 L82.964,28.508 L47.036,28.508 L45.814,28.542 L44.66,28.608 L43.572,28.74 L42.516,28.936 L41.492,29.168 L40.536,29.464 L39.646,29.794 L38.788,30.19 L38.358,30.422 L37.962,30.652 L37.566,30.916 L37.204,31.18 C47.286,21.554 57.968,11.986 69.772,2.524 z M73.524,2.922 C85.93,4.612 97.188,9.94 106.182,17.796 L92.796,31.18 L92.664,31.082 L92.598,31.048 L73.524,2.922 z" fill="url(#Gradient_3)" id="path49-3"/>
<path d="M23.818,17.796 C34.834,8.176 49.242,2.344 65,2.344 C66.614,2.344 68.216,2.406 69.8,2.526 L37.204,31.18 L23.818,17.796 z" fill="url(#Gradient_4)" id="path51-8"/>
<path d="M106.202,112.188 C99.778,117.802 92.2,122.126 83.874,124.758 L70.856,101.488 L82.932,101.488 L84.714,101.422 L86.362,101.224 L87.154,101.058 L87.914,100.894 L88.672,100.662 L89.366,100.432 L89.826,100.266 L90.288,100.07 L90.718,99.872 L91.146,99.64 L91.542,99.41 L91.938,99.178 L92.334,98.948 L92.698,98.684 L106.202,112.188 z" fill="url(#Gradient_5)" id="path53-9"/>
<path d="M83.928,124.74 C77.954,126.634 71.596,127.654 65,127.654 C53.554,127.654 42.822,124.58 33.584,119.21 L50.598,101.52 L70.902,101.488 L83.928,124.74 z M32.188,118.376 C29.222,116.546 26.42,114.478 23.808,112.196 L32.188,103.798 L32.188,118.376 z" fill="url(#Gradient_6)" id="path55-3"/>
<path d="M14.536,102.124 C19.474,80.59 24.722,59.004 32.684,38.67 L32.552,39.33 L32.452,39.99 L32.354,40.682 L32.288,41.376 L32.222,43.42 L32.222,91.722 L17.78,106.164 C16.644,104.864 15.562,103.516 14.536,102.124 z" fill="url(#Gradient_7)" id="path57-4"/>
<path d="M32.684,38.67 L14.582,102.184 C6.892,91.78 2.346,78.918 2.346,65 C2.346,49.244 8.174,34.838 17.79,23.824 L32.684,38.67 z" fill="url(#Gradient_8)" id="path59-4"/>
</g>
</g>
</svg>
RESOURCES += $${PWD}/i18n.qrc