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
  • master
  • update_dialog
  • fix_build
  • develop
  • 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

Commits on Source 177

77 additional commits have been omitted to prevent performance issues.
38 files
+ 880
499
Compare changes
  • Side-by-side
  • Inline

Files

+1 −1
Original line number Diff line number Diff line
*.pro.user
build_*/
lib/qtlib/
lib/qtil/
lib/AppImageUpdate/
lib/AppImageUpdate-prebuilt/

.gitlab-ci.yml

0 → 100644
+15 −0
Original line number Diff line number Diff line
stages:
  - build

appimage:
  stage: build
  image: ubuntu:14.04
  only:
    - master
    - /^release\-.+/
  script:
    - ./scripts/package appimage
  artifacts:
    paths:
    - build_*/ocs-manager*.AppImage
    expire_in: 2 days

.travis.yml

deleted100644 → 0
+0 −15
Original line number Diff line number Diff line
dist: trusty
sudo: required
services:
  - docker

branches:
  only:
    - master

script:
  - mntdir='/mnt/ocs-manager'
  #- docker run --rm -v $(pwd):${mntdir} ubuntu:16.04 /bin/bash -c "sh ${mntdir}/scripts/build-docker.sh snap"
  #- docker run --rm -v $(pwd):${mntdir} ubuntu:16.04 /bin/bash -c "sh ${mntdir}/scripts/build-docker.sh flatpak"
  - docker run --rm -v $(pwd):${mntdir} ubuntu:17.10 /bin/bash -c "sh ${mntdir}/scripts/build-docker.sh appimage"
  - cat transfer.log
+1 −2
Original line number Diff line number Diff line
# ocs-manager

[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Build Status](https://travis-ci.org/opendesktop/ocs-manager.svg?branch=master)](https://travis-ci.org/opendesktop/ocs-manager)

A tool to handle item installation from OCS provider, file management, and apply themes.

Copyright: 2017, Opendesktop.org
Copyright: 2017-2019, Opendesktop.org

License: GPL-3+
+3 −1
Original line number Diff line number Diff line
@@ -29,10 +29,11 @@ RESOURCES += $${PWD}/configs/configs.qrc

INCLUDEPATH += $${PWD}/src

unix:!ios:!android {
contains(DEFINES, APP_DESKTOP) {
    QT += dbus

    HEADERS += \
        $${PWD}/src/updaters/appimageupdater.h \
        $${PWD}/src/desktopthemes/kdetheme.h \
        $${PWD}/src/desktopthemes/gnometheme.h \
        $${PWD}/src/desktopthemes/xfcetheme.h \
@@ -40,6 +41,7 @@ unix:!ios:!android {
        $${PWD}/src/desktopthemes/matetheme.h

    SOURCES += \
        $${PWD}/src/updaters/appimageupdater.cpp \
        $${PWD}/src/desktopthemes/kdetheme.cpp \
        $${PWD}/src/desktopthemes/gnometheme.cpp \
        $${PWD}/src/desktopthemes/xfcetheme.cpp \
Original line number Diff line number Diff line
{
    "id": "ocs-manager",
    "name": "ocs-manager",
    "version": "0.4.4",
    "version": "0.8.1",
    "organization": "Opendesktop.org",
    "domain": "org.opendesktop.ocs-manager",
    "icon": ":/desktop/ocs-manager.svg",
@@ -9,5 +9,5 @@
    "license": "GPL-3+",
    "author": "Opendesktop.org",
    "contact": "contact@opendesktop.org",
    "homepage": "https://github.com/opendesktop/ocs-manager"
    "homepage": "https://git.opendesktop.org/akiraohgaki/ocs-manager"
}
Original line number Diff line number Diff line
{
    "bin": {
        "name": "Softwares",
        "destination": "$HOME/.local/bin",
        "name": "Software",
        "destination": "",
        "xdg_destination": "$HOME/.local/bin",
        "generic_destination": "$APP_DATA/bin"
    },
    "downloads": {
        "name": "Downloads",
        "destination": "$XDG_DOWNLOAD_DIR",
        "destination": "",
        "xdg_destination": "$XDG_DOWNLOAD_DIR",
        "generic_destination": "$APP_DATA/downloads"
    },
    "documents": {
        "name": "Documents",
        "destination": "$XDG_DOCUMENTS_DIR",
        "destination": "",
        "xdg_destination": "$XDG_DOCUMENTS_DIR",
        "generic_destination": "$APP_DATA/documents"
    },
    "pictures": {
        "name": "Pictures",
        "destination": "$XDG_PICTURES_DIR",
        "destination": "",
        "xdg_destination": "$XDG_PICTURES_DIR",
        "generic_destination": "$APP_DATA/pictures"
    },
    "music": {
        "name": "Music",
        "destination": "$XDG_MUSIC_DIR",
        "destination": "",
        "xdg_destination": "$XDG_MUSIC_DIR",
        "generic_destination": "$APP_DATA/music"
    },
    "videos": {
        "name": "Videos",
        "destination": "$XDG_VIDEOS_DIR",
        "destination": "",
        "xdg_destination": "$XDG_VIDEOS_DIR",
        "generic_destination": "$APP_DATA/videos"
    },
    "wallpapers": {
        "name": "Wallpapers",
        "destination": "$XDG_DATA_HOME/wallpapers",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/wallpapers",
        "generic_destination": "$APP_DATA/wallpapers"
    },
    "fonts": {
        "name": "Fonts",
        "destination": "$HOME/.fonts",
        "destination": "",
        "xdg_destination": "$HOME/.fonts",
        "generic_destination": "$APP_DATA/fonts"
    },
    "cursors": {
        "name": "Cursors",
        "destination": "$HOME/.icons",
        "destination": "",
        "xdg_destination": "$HOME/.icons",
        "generic_destination": "$APP_DATA/cursors"
    },
    "icons": {
        "name": "Icons",
        "destination": "$XDG_DATA_HOME/icons",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/icons",
        "generic_destination": "$APP_DATA/icons"
    },
    "emoticons": {
        "name": "Emoticons",
        "destination": "$XDG_DATA_HOME/emoticons",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/emoticons",
        "generic_destination": "$APP_DATA/emoticons"
    },
    "themes": {
        "name": "Desktop Themes",
        "destination": "$HOME/.themes",
        "destination": "",
        "xdg_destination": "$HOME/.themes",
        "generic_destination": "$APP_DATA/themes"
    },
    "emerald_themes": {
        "name": "Emerald Themes",
        "destination": "$HOME/.emerald/themes",
        "destination": "",
        "xdg_destination": "$HOME/.emerald/themes",
        "generic_destination": "$APP_DATA/emerald_themes"
    },
    "enlightenment_themes": {
        "name": "Enlightenment Themes",
        "destination": "$HOME/.e/e/themes",
        "destination": "",
        "xdg_destination": "$HOME/.e/e/themes",
        "generic_destination": "$APP_DATA/enlightenment_themes"
    },
    "enlightenment_backgrounds": {
        "name": "Enlightenment Backgrounds",
        "destination": "$HOME/.e/e/backgrounds",
        "destination": "",
        "xdg_destination": "$HOME/.e/e/backgrounds",
        "generic_destination": "$APP_DATA/enlightenment_backgrounds"
    },
    "fluxbox_styles": {
        "name": "Fluxbox Styles",
        "destination": "$HOME/.fluxbox/styles",
        "destination": "",
        "xdg_destination": "$HOME/.fluxbox/styles",
        "generic_destination": "$APP_DATA/fluxbox_styles"
    },
    "pekwm_themes": {
        "name": "PekWM Themes",
        "destination": "$HOME/.pekwm/themes",
        "destination": "",
        "xdg_destination": "$HOME/.pekwm/themes",
        "generic_destination": "$APP_DATA/pekwm_themes"
    },
    "icewm_themes": {
        "name": "IceWM Themes",
        "destination": "$HOME/.icewm/themes",
        "destination": "",
        "xdg_destination": "$HOME/.icewm/themes",
        "generic_destination": "$APP_DATA/icewm_themes"
    },
    "plasma_plasmoids": {
        "name": "Plasma Plasmoids",
        "destination": "$XDG_DATA_HOME/plasma/plasmoids",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/plasma/plasmoids",
        "generic_destination": "$APP_DATA/plasma_plasmoids"
    },
    "plasma_look_and_feel": {
        "name": "Plasma Look and Feel",
        "destination": "$XDG_DATA_HOME/plasma/look-and-feel",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/plasma/look-and-feel",
        "generic_destination": "$APP_DATA/plasma_look_and_feel"
    },
    "plasma_desktopthemes": {
        "name": "Plasma Desktop Themes",
        "destination": "$XDG_DATA_HOME/plasma/desktoptheme",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/plasma/desktoptheme",
        "generic_destination": "$APP_DATA/plasma_desktopthemes"
    },
    "kwin_effects": {
        "name": "KWin Effects",
        "destination": "$XDG_DATA_HOME/kwin/effects",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/kwin/effects",
        "generic_destination": "$APP_DATA/kwin_effects"
    },
    "kwin_scripts": {
        "name": "KWin Scripts",
        "destination": "$XDG_DATA_HOME/kwin/scripts",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/kwin/scripts",
        "generic_destination": "$APP_DATA/kwin_scripts"
    },
    "kwin_tabbox": {
        "name": "KWin Window Switcher",
        "destination": "$XDG_DATA_HOME/kwin/tabbox",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/kwin/tabbox",
        "generic_destination": "$APP_DATA/kwin_tabbox"
    },
    "aurorae_themes": {
        "name": "Aurorae Themes",
        "destination": "$XDG_DATA_HOME/aurorae/themes",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/aurorae/themes",
        "generic_destination": "$APP_DATA/aurorae_themes"
    },
    "dekorator_themes": {
        "name": "deKorator Themes",
        "destination": "$XDG_DATA_HOME/deKorator/themes",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/deKorator/themes",
        "generic_destination": "$APP_DATA/dekorator_themes"
    },
    "qtcurve": {
        "name": "QtCurve Themes",
        "destination": "$XDG_DATA_HOME/QtCurve",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/QtCurve",
        "generic_destination": "$APP_DATA/qtcurve"
    },
    "color_schemes": {
        "name": "KDE Color Schemes",
        "destination": "$XDG_DATA_HOME/color-schemes",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/color-schemes",
        "generic_destination": "$APP_DATA/color_schemes"
    },
    "gnome_shell_extensions": {
        "name": "Gnome Shell Extensions",
        "destination": "$XDG_DATA_HOME/gnome-shell/extensions",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/gnome-shell/extensions",
        "generic_destination": "$APP_DATA/gnome_shell_extensions"
    },
    "cinnamon_applets": {
        "name": "Cinnamon Applets",
        "destination": "$XDG_DATA_HOME/cinnamon/applets",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/cinnamon/applets",
        "generic_destination": "$APP_DATA/cinnamon_applets"
    },
    "cinnamon_desklets": {
        "name": "Cinnamon Desklets",
        "destination": "$XDG_DATA_HOME/cinnamon/desklets",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/cinnamon/desklets",
        "generic_destination": "$APP_DATA/cinnamon_desklets"
    },
    "cinnamon_extensions": {
        "name": "Cinnamon Extensions",
        "destination": "$XDG_DATA_HOME/cinnamon/extensions",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/cinnamon/extensions",
        "generic_destination": "$APP_DATA/cinnamon_extensions"
    },
    "nautilus_scripts": {
        "name": "Nautilus Scripts",
        "destination": "$XDG_DATA_HOME/nautilus/scripts",
        "destination": "",
        "xdg_destination": "$XDG_DATA_HOME/nautilus/scripts",
        "generic_destination": "$APP_DATA/nautilus_scripts"
    },
    "amarok_scripts": {
        "name": "Amarok Scripts",
        "destination": "$KDEHOME/share/apps/amarok/scripts",
        "destination": "",
        "xdg_destination": "$KDEHOME/share/apps/amarok/scripts",
        "generic_destination": "$APP_DATA/amarok_scripts"
    },
    "yakuake_skins": {
        "name": "Yakuake Skins",
        "destination": "$KDEHOME/share/apps/yakuake/skins",
        "destination": "",
        "xdg_destination": "$KDEHOME/share/apps/yakuake/skins",
        "generic_destination": "$APP_DATA/yakuake_skins"
    },
    "cairo_clock_themes": {
        "name": "Cairo-Clock Themes",
        "destination": "$HOME/.cairo-clock/themes",
        "destination": "",
        "xdg_destination": "$HOME/.cairo-clock/themes",
        "generic_destination": "$APP_DATA/cairo_clock_themes"
    },
    "books": {
        "name": "Books",
        "destination": "$APP_DATA/books",
        "destination": "",
        "xdg_destination": "$APP_DATA/books",
        "generic_destination": "$APP_DATA/books"
    },
    "comics": {
        "name": "Comics",
        "destination": "$APP_DATA/comics",
        "destination": "",
        "xdg_destination": "$APP_DATA/comics",
        "generic_destination": "$APP_DATA/comics"
    }
}
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ bool KdeTheme::applyAsCursor() const
        << "c.writeEntry('cursorTheme', '" + themeName_ + "');";

    if (evaluateScript(script)) {
        QProcess::startDetached("sh -c \"echo 'Xcursor.theme: " + themeName_ + "' | xrdb -merge\"");

        auto setLaunchEnv = QDBusMessage::createMethodCall("org.kde.klauncher5", "/KLauncher", "org.kde.KLauncher", "setLaunchEnv");
        setLaunchEnv.setArguments(QVariantList() << QVariant(QString("XCURSOR_THEME")) << QVariant(themeName_));
        QDBusConnection::sessionBus().call(setLaunchEnv);
@@ -67,6 +69,10 @@ bool KdeTheme::applyAsCursor() const
        notifyChange.setArguments(QVariantList() << QVariant(qint32(5)) << QVariant(qint32(0)));
        QDBusConnection::sessionBus().send(notifyChange);

        QProcess::startDetached("kwin --replace");
        QProcess::startDetached("kquitapp5 plasmashell");
        QProcess::startDetached("sh -c \"XCURSOR_THEME='" + themeName_ + "' kstart5 plasmashell\"");

        return true;
    }
    return false;
Original line number Diff line number Diff line
@@ -3,15 +3,15 @@
#include <QStringList>
#include <QStandardPaths>

#include "qtlib_dir.h"
#include "qtil_dir.h"

ConfigHandler::ConfigHandler(QObject *parent)
    : QObject(parent)
{
    appConfig_ = qtlib::Config(":/configs");
    appConfig_ = Qtil::Config(":/configs");
    importAppConfigApplication();
    importAppConfigInstallTypes();
    usrConfig_ = qtlib::Config(qtlib::Dir::genericConfigPath() + "/" + getAppConfigApplication()["id"].toString());
    usrConfig_ = Qtil::Config(Qtil::Dir::genericConfigPath() + "/" + getAppConfigApplication()["id"].toString());
}

QJsonObject ConfigHandler::getAppConfigApplication() const
@@ -69,14 +69,14 @@ bool ConfigHandler::setUsrConfigInstalledItems(const QJsonObject &object) const
    return usrConfig_.set("installed_items", object);
}

QJsonObject ConfigHandler::getUsrConfigUpdateAvailable() const
QJsonObject ConfigHandler::getUsrConfigUpdateAvailableItems() const
{
    return usrConfig_.get("update_available");
    return usrConfig_.get("update_available_items");
}

bool ConfigHandler::setUsrConfigUpdateAvailable(const QJsonObject &object) const
bool ConfigHandler::setUsrConfigUpdateAvailableItems(const QJsonObject &object) const
{
    return usrConfig_.set("update_available", object);
    return usrConfig_.set("update_available_items", object);
}

bool ConfigHandler::setUsrConfigProvidersProvider(const QString &providerKey, const QJsonObject &object) const
@@ -177,26 +177,24 @@ bool ConfigHandler::removeUsrConfigInstalledItemsItem(const QString &itemKey) co
    return setUsrConfigInstalledItems(installedItems);
}

bool ConfigHandler::setUsrConfigUpdateAvailableFile(const QString &fileKey, const QJsonObject &object) const
bool ConfigHandler::setUsrConfigUpdateAvailableItemsItem(const QString &itemKey, const QJsonObject &object) const
{
    /* object format
    {
        "path": "/home/user/.local/bin/example.AppImage",
        "filename": "example.AppImage",
        "installed_item": "http://example.com/downloads/example.AppImage",
        "update_method": "appimageupdate"
    }
    */
    auto updateAvailable = getUsrConfigUpdateAvailable();
    updateAvailable[fileKey] = object;
    return setUsrConfigUpdateAvailable(updateAvailable);
    auto updateAvailableItems = getUsrConfigUpdateAvailableItems();
    updateAvailableItems[itemKey] = object;
    return setUsrConfigUpdateAvailableItems(updateAvailableItems);
}

bool ConfigHandler::removeUsrConfigUpdateAvailableFile(const QString &fileKey) const
bool ConfigHandler::removeUsrConfigUpdateAvailableItemsItem(const QString &itemKey) const
{
    auto updateAvailable = getUsrConfigUpdateAvailable();
    updateAvailable.remove(fileKey);
    return setUsrConfigUpdateAvailable(updateAvailable);
    auto updateAvailableItems = getUsrConfigUpdateAvailableItems();
    updateAvailableItems.remove(itemKey);
    return setUsrConfigUpdateAvailableItems(updateAvailableItems);
}

void ConfigHandler::importAppConfigApplication()
@@ -209,8 +207,15 @@ void ConfigHandler::importAppConfigInstallTypes()
    auto installTypes = appConfig_.get("install_types");
    for (const auto &key : installTypes.keys()) {
        auto installtype = installTypes[key].toObject();
        installtype["destination"] = convertPathString(installtype["destination"].toString());
        installtype["generic_destination"] = convertPathString(installtype["generic_destination"].toString());
        auto xdgDestination = convertPathString(installtype["xdg_destination"].toString());
        auto genericDestination = convertPathString(installtype["generic_destination"].toString());
        installtype["xdg_destination"] = xdgDestination;
        installtype["generic_destination"] = genericDestination;
#ifdef APP_DESKTOP
        installtype["destination"] = xdgDestination;
#else
        installtype["destination"] = genericDestination;
#endif
        installTypes[key] = installtype;
    }
    auto installTypesAlias = appConfig_.get("install_types_alias");
@@ -231,7 +236,7 @@ QString ConfigHandler::convertPathString(const QString &path) const
{
    auto newPath = path;
    if (newPath.contains("$HOME")) {
        newPath.replace("$HOME", qtlib::Dir::homePath());
        newPath.replace("$HOME", Qtil::Dir::homePath());
    }
    else if (newPath.contains("$XDG_DOCUMENTS_DIR")) {
        newPath.replace("$XDG_DOCUMENTS_DIR", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
@@ -249,13 +254,13 @@ QString ConfigHandler::convertPathString(const QString &path) const
        newPath.replace("$XDG_VIDEOS_DIR", QStandardPaths::writableLocation(QStandardPaths::MoviesLocation));
    }
    else if (newPath.contains("$XDG_DATA_HOME")) {
        newPath.replace("$XDG_DATA_HOME", qtlib::Dir::genericDataPath());
        newPath.replace("$XDG_DATA_HOME", Qtil::Dir::genericDataPath());
    }
    else if (newPath.contains("$KDEHOME")) {
        newPath.replace("$KDEHOME", qtlib::Dir::kdehomePath());
        newPath.replace("$KDEHOME", Qtil::Dir::kdehomePath());
    }
    else if (newPath.contains("$APP_DATA")) {
        newPath.replace("$APP_DATA", qtlib::Dir::genericDataPath() + "/" + getAppConfigApplication()["id"].toString());
        newPath.replace("$APP_DATA", Qtil::Dir::genericDataPath() + "/" + getAppConfigApplication()["id"].toString());
    }
    return newPath;
}
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
#include <QObject>
#include <QJsonObject>

#include "qtlib_config.h"
#include "qtil_config.h"

class ConfigHandler : public QObject
{
@@ -24,8 +24,8 @@ public slots:
    bool setUsrConfigCategories(const QJsonObject &object) const;
    QJsonObject getUsrConfigInstalledItems() const;
    bool setUsrConfigInstalledItems(const QJsonObject &object) const;
    QJsonObject getUsrConfigUpdateAvailable() const;
    bool setUsrConfigUpdateAvailable(const QJsonObject &object) const;
    QJsonObject getUsrConfigUpdateAvailableItems() const;
    bool setUsrConfigUpdateAvailableItems(const QJsonObject &object) const;

    bool setUsrConfigProvidersProvider(const QString &providerKey, const QJsonObject &object) const;
    bool removeUsrConfigProvidersProvider(const QString &providerKey) const;
@@ -34,16 +34,16 @@ public slots:
    bool setUsrConfigCategoriesInstallType(const QString &providerKey, const QString &categoryKey, const QString &installType) const;
    bool setUsrConfigInstalledItemsItem(const QString &itemKey, const QJsonObject &object) const;
    bool removeUsrConfigInstalledItemsItem(const QString &itemKey) const;
    bool setUsrConfigUpdateAvailableFile(const QString &fileKey, const QJsonObject &object) const;
    bool removeUsrConfigUpdateAvailableFile(const QString &fileKey) const;
    bool setUsrConfigUpdateAvailableItemsItem(const QString &itemKey, const QJsonObject &object) const;
    bool removeUsrConfigUpdateAvailableItemsItem(const QString &itemKey) const;

private:
    void importAppConfigApplication();
    void importAppConfigInstallTypes();
    QString convertPathString(const QString &path) const;

    qtlib::Config appConfig_;
    qtlib::Config usrConfig_;
    Qtil::Config appConfig_;
    Qtil::Config usrConfig_;
    QJsonObject appConfigApplication_;
    QJsonObject appConfigInstallTypes_;
};
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

#include <QStringList>

#ifdef QTLIB_UNIX
#ifdef APP_DESKTOP
#include <QFileInfo>

#include "desktopthemes/kdetheme.h"
@@ -96,9 +96,9 @@ bool DesktopThemeHandler::isApplicableType(const QString &installType) const
    return applicableTypes.contains(installType);
}

#ifdef QTLIB_UNIX
bool DesktopThemeHandler::applyTheme(const QString &path, const QString &installType) const
{
#ifdef APP_DESKTOP
    if (QFileInfo::exists(path) && isApplicableType(installType)) {
        auto desktop = desktopEnvironment();

@@ -196,7 +196,7 @@ bool DesktopThemeHandler::applyTheme(const QString &path, const QString &install
            }
        }
    }
#endif

    return false;
}
#endif
Original line number Diff line number Diff line
@@ -12,8 +12,5 @@ public:
public slots:
    QString desktopEnvironment() const;
    bool isApplicableType(const QString &installType) const;

#ifdef QTLIB_UNIX
    bool applyTheme(const QString &path, const QString &installType) const;
#endif
};
Original line number Diff line number Diff line
@@ -6,14 +6,16 @@
#include <QFileInfo>
#include <QDateTime>

#ifdef QTLIB_UNIX
#include <QProcess>
#ifdef APP_DESKTOP
#include <QStringList>
#include <QDir>
#include <QDirIterator>
#endif

#include "qtlib_dir.h"
#include "qtlib_file.h"
#include "qtlib_networkresource.h"
#include "qtlib_package.h"
#include "qtil_dir.h"
#include "qtil_file.h"
#include "qtil_networkresource.h"
#include "qtil_package.h"

#include "handlers/confighandler.h"

@@ -67,9 +69,9 @@ void ItemHandler::getItem(const QString &command, const QString &url, const QStr
    itemMetadataSet[itemKey] = metadata;
    setMetadataSet(itemMetadataSet);

    auto *resource = new qtlib::NetworkResource(itemKey, QUrl(url), true, this);
    connect(resource, &qtlib::NetworkResource::downloadProgress, this, &ItemHandler::downloadProgress);
    connect(resource, &qtlib::NetworkResource::finished, this, &ItemHandler::networkResourceFinished);
    auto *resource = new Qtil::NetworkResource(itemKey, QUrl(url), true, this);
    connect(resource, &Qtil::NetworkResource::downloadProgress, this, &ItemHandler::downloadProgress);
    connect(resource, &Qtil::NetworkResource::finished, this, &ItemHandler::networkResourceFinished);
    resource->get();

    result["status"] = QString("success_downloadstart");
@@ -112,8 +114,7 @@ void ItemHandler::getItemByOcsUrl(const QString &ocsUrl, const QString &provider
        filename = QUrl(url).fileName();
    }

    // Still support xdg and xdgs schemes for backward compatibility
    if ((scheme == "ocs" || scheme == "ocss" || scheme == "xdg" || scheme == "xdgs")
    if ((scheme == "ocs" || scheme == "ocss")
            && (command == "download" || command == "install")
            && QUrl(url).isValid()
            && configHandler_->getAppConfigInstallTypes().contains(type)
@@ -146,26 +147,18 @@ void ItemHandler::uninstall(const QString &itemKey)
    auto installedItem = configHandler_->getUsrConfigInstalledItems()[itemKey].toObject();
    auto installType = installedItem["install_type"].toString();

    qtlib::Dir destDir;
#ifdef QTLIB_UNIX
    destDir.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());
    Qtil::Dir destDir(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());

    for (const auto &filename : installedItem["files"].toArray()) {
#ifdef APP_DESKTOP
    for (const auto filename : installedItem["files"].toArray()) {
        QFileInfo fileInfo(destDir.path() + "/" + filename.toString());

        // plasmapkg: Installation process has should be saved plasmapkg into destination directory
        // plasmapkg: Installation process will saved plasmapkg into destination directory

        qtlib::Package package(fileInfo.filePath());
        Qtil::Package package(fileInfo.filePath());

        // Uninstall
        if (installType == "bin") {
            if (fileInfo.filePath().endsWith(".appimage", Qt::CaseInsensitive)) {
                QProcess process;
                process.start(fileInfo.filePath() + " --remove-appimage-desktop-integration");
                process.waitForFinished();
            }
        }
        else if (installType == "plasma_plasmoids" || installType == "plasma4_plasmoids" || installType == "plasma5_plasmoids") {
        if (installType == "plasma_plasmoids" || installType == "plasma4_plasmoids" || installType == "plasma5_plasmoids") {
            package.uninstallAsPlasmapkg("plasmoid");
        }
        else if (installType == "plasma_look_and_feel" || installType == "plasma5_look_and_feel") {
@@ -186,34 +179,33 @@ void ItemHandler::uninstall(const QString &itemKey)

        // Remove file
        if (fileInfo.isDir()) {
            qtlib::Dir(fileInfo.filePath()).remove();
            Qtil::Dir(fileInfo.filePath()).remove();
        }
        else {
            qtlib::File(fileInfo.filePath()).remove();
            Qtil::File(fileInfo.filePath()).remove();
        }
    }
#else
    destDir.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["generic_destination"].toString());

    for (const auto &filename : installedItem["files"].toArray()) {
    for (const auto filename : installedItem["files"].toArray()) {
        QFileInfo fileInfo(destDir.path() + "/" + filename.toString());
        if (fileInfo.isDir()) {
            qtlib::Dir(fileInfo.filePath()).remove();
            Qtil::Dir(fileInfo.filePath()).remove();
        }
        else {
            qtlib::File(fileInfo.filePath()).remove();
            Qtil::File(fileInfo.filePath()).remove();
        }
    }
#endif

    configHandler_->removeUsrConfigInstalledItemsItem(itemKey);
    configHandler_->removeUsrConfigUpdateAvailableItemsItem(itemKey);

    result["status"] = QString("success_uninstall");
    result["message"] = tr("Uninstalled");
    emit uninstallFinished(result);
}

void ItemHandler::networkResourceFinished(qtlib::NetworkResource *resource)
void ItemHandler::networkResourceFinished(Qtil::NetworkResource *resource)
{
    auto itemKey = resource->id();

@@ -251,7 +243,7 @@ void ItemHandler::setMetadataSet(const QJsonObject &metadataSet)
    emit metadataSetChanged();
}

void ItemHandler::saveDownloadedFile(qtlib::NetworkResource *resource)
void ItemHandler::saveDownloadedFile(Qtil::NetworkResource *resource)
{
    auto itemKey = resource->id();

@@ -270,9 +262,9 @@ void ItemHandler::saveDownloadedFile(qtlib::NetworkResource *resource)
    auto filename = metadata["filename"].toString();
    auto installType = metadata["install_type"].toString();

    qtlib::Dir destDir(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());
    Qtil::Dir destDir(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());
    destDir.make();
    qtlib::File destFile(destDir.path() + "/" + filename);
    Qtil::File destFile(destDir.path() + "/" + filename);

    if (destFile.exists()) {
        auto filenamePrefix = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_";
@@ -294,7 +286,7 @@ void ItemHandler::saveDownloadedFile(qtlib::NetworkResource *resource)
    resource->deleteLater();
}

void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
void ItemHandler::installDownloadedFile(Qtil::NetworkResource *resource)
{
    // Installation pre-process
    auto itemKey = resource->id();
@@ -315,13 +307,15 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
    auto installType = metadata["install_type"].toString();

    QString tempDirPrefix = "temp_" + filename;
    qtlib::Dir tempDir(qtlib::Dir::genericCachePath() + "/"
    Qtil::Dir tempDir(Qtil::Dir::genericCachePath() + "/"
                       + configHandler_->getAppConfigApplication()["id"].toString() + "/"
                       + tempDirPrefix);
    tempDir.make();
    qtlib::Dir tempDestDir(tempDir.path() + "/dest");
    Qtil::Dir tempDestDir(tempDir.path() + "/dest");
    tempDestDir.make();
    qtlib::Package package(tempDir.path() + "/" + filename);
    Qtil::Dir tempSrcDir(tempDir.path() + "/src");
    tempSrcDir.make();
    Qtil::Package package(tempDir.path() + "/" + filename);

    if (!resource->saveData(package.path())) {
        result["status"] = QString("error_save");
@@ -341,11 +335,10 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
    result["message"] = tr("Installing");
    emit installStarted(result);

    qtlib::Dir destDir;
#ifdef QTLIB_UNIX
    destDir.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());
    Qtil::Dir destDir(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString());

    // plasmapkg: Need to save package to remove installed files later
#ifdef APP_DESKTOP
    // plasmapkg: Should save a package to remove installed files in uninstall process

    if (installType == "bin"
            && package.installAsProgram(tempDestDir.path() + "/" + filename)) {
@@ -381,6 +374,32 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
        package.installAsFile(tempDestDir.path() + "/" + filename);
        result["message"] = tr("The KWin window switcher has been installed");
    }
    else if (installType == "cursors"
             && package.installAsArchive(tempSrcDir.path())
             && installThemes("cursors", filename.section(".", 0, 0), tempSrcDir.path(), tempDestDir.path())) {
        result["message"] = tr("The cursor theme has been installed");
    }
    else if (installType == "icons"
             && package.installAsArchive(tempSrcDir.path())
             && installThemes("icons", filename.section(".", 0, 0), tempSrcDir.path(), tempDestDir.path())) {
        result["message"] = tr("The icon theme has been installed");
    }
    else if (installType == "emoticons"
             && package.installAsArchive(tempSrcDir.path())
             && installThemes("emoticons", filename.section(".", 0, 0), tempSrcDir.path(), tempDestDir.path())) {
        result["message"] = tr("The emoticon theme has been installed");
    }
    else if ((installType == "themes"
              || installType == "gnome_shell_themes"
              || installType == "cinnamon_themes"
              || installType == "gtk2_themes"
              || installType == "gtk3_themes"
              || installType == "metacity_themes"
              || installType == "xfwm4_themes")
             && package.installAsArchive(tempSrcDir.path())
             && installThemes("themes", filename.section(".", 0, 0), tempSrcDir.path(), tempDestDir.path())) {
        result["message"] = tr("The desktop theme has been installed");
    }
    else if (package.installAsArchive(tempDestDir.path())) {
        result["message"] = tr("The archive file has been extracted");
    }
@@ -396,9 +415,7 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
        return;
    }
#else
    destDir.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["generic_destination"].toString());

    if (qtlib::File(package.path()).copy(tempDestDir.path() + "/" + filename)) {
    if (Qtil::File(package.path()).copy(tempDestDir.path() + "/" + filename)) {
        result["message"] = tr("The file has been installed");
    }
    else {
@@ -423,15 +440,24 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
        }

        if (fileInfo.isDir()) {
            qtlib::Dir(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
            Qtil::Dir(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
        }
        else {
            qtlib::File(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
            Qtil::File(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
        }

        installedFiles.append(QJsonValue(destFilename));
    }

    if (installedFiles.isEmpty()) {
        result["status"] = QString("error_install");
        result["message"] = tr("Failed to installation");
        emit installFinished(result);
        tempDir.remove();
        resource->deleteLater();
        return;
    }

    // Installation post-process
    metadata.remove("command");
    metadata["files"] = installedFiles;
@@ -445,3 +471,66 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
    tempDir.remove();
    resource->deleteLater();
}

#ifdef APP_DESKTOP
bool ItemHandler::installThemes(const QString &installType, const QString &name, const QString &srcDir, const QString &destDir)
{
    QStringList themeDirs;

    if (installType == "cursors") {
        //QDirIterator iterator(srcDir, QStringList() << "index.theme", QDir::Files, QDirIterator::Subdirectories);
        QDirIterator iterator(srcDir, QStringList() << "cursors", QDir::Dirs, QDirIterator::Subdirectories);
        while (iterator.hasNext()) {
            auto path = iterator.next();
            path.truncate(path.lastIndexOf("/"));
            themeDirs << path;
        }
    }
    else if (installType == "icons") {
        QDirIterator iterator(srcDir, QStringList() << "index.theme", QDir::Files, QDirIterator::Subdirectories);
        while (iterator.hasNext()) {
            auto path = iterator.next();
            path.truncate(path.lastIndexOf("/"));
            themeDirs << path;
        }
    }
    else if (installType == "emoticons") {
        QDirIterator iterator(srcDir, QStringList() << "emoticons.xml", QDir::Files, QDirIterator::Subdirectories);
        while (iterator.hasNext()) {
            auto path = iterator.next();
            path.truncate(path.lastIndexOf("/"));
            themeDirs << path;
        }
    }
    else if (installType == "themes") {
        /*QDirIterator iterator(srcDir,
                              QStringList() << "cinnamon"
                                            << "gnome-shell"
                                            << "gtk-2.0"
                                            << "gtk-3.0"
                                            << "metacity-1"
                                            << "plank"
                                            << "unity"
                                            << "xfwm4",
                              QDir::Dirs, QDirIterator::Subdirectories);*/
        QDirIterator iterator(srcDir, QStringList() << "index.theme", QDir::Files, QDirIterator::Subdirectories);
        while (iterator.hasNext()) {
            auto path = iterator.next();
            path.truncate(path.lastIndexOf("/"));
            themeDirs << path;
        }
    }

    if (!themeDirs.isEmpty()) {
        for (const auto &themeDir : themeDirs) {
            auto themeName = name;
            if (themeDir != srcDir) {
                themeName = themeDir.split("/").last();
            }
            Qtil::Dir(themeDir).move(destDir + "/" + themeName);
        }
        return true;
    }
    return false;
}
#endif
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
#include <QObject>
#include <QJsonObject>

namespace qtlib {
namespace Qtil {
class NetworkResource;
}

@@ -37,13 +37,17 @@ public slots:
    void uninstall(const QString &itemKey);

private slots:
    void networkResourceFinished(qtlib::NetworkResource *resource);
    void networkResourceFinished(Qtil::NetworkResource *resource);

private:
    void setMetadataSet(const QJsonObject &metadataSet);

    void saveDownloadedFile(qtlib::NetworkResource *resource);
    void installDownloadedFile(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_;
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
#include <QStringList>
#include <QJsonValue>

#include "qtlib_ocsapi.h"
#include "qtil_ocsapi.h"

#include "handlers/confighandler.h"

@@ -13,9 +13,9 @@ OcsApiHandler::OcsApiHandler(ConfigHandler *configHandler, QObject *parent)

bool OcsApiHandler::addProviders(const QString &providerFileUrl) const
{
    auto providers = qtlib::OcsApi::getProviderFile(QUrl(providerFileUrl));
    auto providers = Qtil::OcsApi::getProviderFile(QUrl(providerFileUrl));
    if (!providers.isEmpty()) {
        for (const auto &providerValue : providers) {
        for (const auto providerValue : providers) {
            auto provider = providerValue.toObject();
            if (provider.contains("location")) {
                // Use location (API base URL) as unique key
@@ -60,7 +60,7 @@ bool OcsApiHandler::updateCategories(const QString &providerKey, bool force) con
    }

    auto baseUrl = providers[providerKey].toObject()["location"].toString();
    auto response = qtlib::OcsApi(baseUrl, QUrl(baseUrl)).getContentCategories();
    auto response = Qtil::OcsApi(baseUrl, QUrl(baseUrl)).getContentCategories();

    if (!response.contains("data")) {
        return false;
@@ -69,7 +69,7 @@ bool OcsApiHandler::updateCategories(const QString &providerKey, bool force) con
    // Data type variation workaround, convert object to array
    QJsonArray responseData;
    if (response["data"].isObject()) {
        for (const auto &dataValue : response["data"].toObject()) {
        for (const auto dataValue : response["data"].toObject()) {
            responseData.append(dataValue);
        }
    }
@@ -86,7 +86,7 @@ bool OcsApiHandler::updateCategories(const QString &providerKey, bool force) con
    }

    QJsonObject newProviderCategories;
    for (const auto &dataValue : responseData) {
    for (const auto dataValue : responseData) {
        auto data = dataValue.toObject();

        // Data type variation workaround, convert int to string
@@ -185,7 +185,7 @@ QJsonObject OcsApiHandler::getContents(const QString &providerKeys, const QStrin
            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);
        }
    }

@@ -198,7 +198,7 @@ QJsonObject OcsApiHandler::getContent(const QString &providerKey, const QString
    auto providers = configHandler_->getUsrConfigProviders();
    if (providers.contains(providerKey)) {
        auto baseUrl = providers[providerKey].toObject()["location"].toString();
        response = qtlib::OcsApi(baseUrl, QUrl(baseUrl)).getContentData(contentId);
        response = Qtil::OcsApi(baseUrl, QUrl(baseUrl)).getContentData(contentId);
    }
    return response;
}
Original line number Diff line number Diff line
@@ -3,27 +3,19 @@
#include <QUrl>
#include <QDesktopServices>

#ifdef QTLIB_UNIX
#ifdef APP_DESKTOP
#include <QFileInfo>
#include <QProcess>
#endif

#ifdef Q_OS_ANDROID
#include "qtlib_package.h"
#include "qtil_package.h"
#endif

SystemHandler::SystemHandler(QObject *parent)
    : QObject(parent)
{}

bool SystemHandler::isUnix() const
{
#ifdef QTLIB_UNIX
    return true;
#endif
    return false;
}

bool SystemHandler::isMobileDevice() const
{
#if defined(APP_MOBILE)
@@ -42,7 +34,7 @@ bool SystemHandler::openUrl(const QString &url) const
    path.replace("file://localhost", "", Qt::CaseInsensitive);
    path.replace("file://", "", Qt::CaseInsensitive);

#ifdef QTLIB_UNIX
#ifdef APP_DESKTOP
    if ((path.endsWith(".appimage", Qt::CaseInsensitive) || path.endsWith(".exe", Qt::CaseInsensitive))
            && QFileInfo(path).isExecutable()) {
        return QProcess::startDetached(path);
@@ -51,7 +43,7 @@ bool SystemHandler::openUrl(const QString &url) const

#ifdef Q_OS_ANDROID
    if (path.endsWith(".apk", Qt::CaseInsensitive)) {
        return qtlib::Package(path).installAsApk();
        return Qtil::Package(path).installAsApk();
    }
#endif

Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ public:
    explicit SystemHandler(QObject *parent = nullptr);

public slots:
    bool isUnix() const;
    bool isMobileDevice() const;
    bool openUrl(const QString &url) const;
};
Original line number Diff line number Diff line
#include "updatehandler.h"

#ifdef QTLIB_UNIX
#include <thread>
#include <chrono>
#include <QStringList>
#include <QJsonValue>
#include <QJsonArray>
#include <QDateTime>

#include "appimage/update.h"
#endif
#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)
{}

QString UpdateHandler::checkAll() const
void UpdateHandler::checkAll()
{
    // Resets data
    QJsonObject updateAvailableItems;
    configHandler_->setUsrConfigUpdateAvailableItems(updateAvailableItems);

    auto installedItems = configHandler_->getUsrConfigInstalledItems();

    if (installedItems.isEmpty()) {
        emit checkAllStarted(false);
        return;
    }

QString UpdateHandler::update(const QString &path) const
{
    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);

#ifdef QTLIB_UNIX
QString UpdateHandler::describeAppImage(const QString &path) const
    emit checkAllFinished(true);
}

void UpdateHandler::update(const QString &itemKey)
{
    appimage::update::Updater appImageUpdater(path.toStdString());
    QString updateInformation;
    std::string description;
    if (appImageUpdater.describeAppImage(description)) {
        updateInformation = QString::fromStdString(description);
    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);
    }
    return updateInformation;
    //else if (updateMethod == "appimageupdate_ocs") {
    //    updateAppImageOcs(itemKey);
    //}
#endif
}

bool UpdateHandler::checkAppImage(const QString &path) const
#ifdef APP_DESKTOP
void UpdateHandler::appImageUpdaterFinished(AppImageUpdater *updater)
{
    appimage::update::Updater appImageUpdater(path.toStdString());
    bool updateAvailable;
    if (appImageUpdater.checkForChanges(updateAvailable)) {
        return updateAvailable;
    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();
    }
    return false;

    configHandler_->removeUsrConfigUpdateAvailableItemsItem(itemKey);

    emit updateFinished(itemKey, true);
    updater->deleteLater();
}
#endif

bool UpdateHandler::updateAppImage(const QString &path)
#ifdef APP_DESKTOP
void UpdateHandler::updateAppImage(const QString &itemKey)
{
    appimage::update::Updater appImageUpdater(path.toStdString(), false);
    if (appImageUpdater.start()) {
        emit updateStarted(path);
        while (!appImageUpdater.isDone()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            double progress;
            if (appImageUpdater.progress(progress)) {
                emit updateProgress(path, progress * 100);
    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);
            }
        auto newPath = path; // dummy
        emit updateFinished(path, newPath);
        if (!appImageUpdater.hasError()) {
            return true;
        }
    }
    return false;

    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
Original line number Diff line number Diff line
#pragma once

#include <QObject>
#include <QJsonObject>

class ConfigHandler;

#ifdef APP_DESKTOP
class AppImageUpdater;
#endif

class UpdateHandler : public QObject
{
    Q_OBJECT
@@ -12,22 +17,26 @@ public:
    explicit UpdateHandler(ConfigHandler *configHandler, QObject *parent = nullptr);

signals:
    void checkAllStarted();
    void checkAllFinished();
    void updateStarted(QString path);
    void updateFinished(QString path, QString newPath);
    void updateProgress(QString path, int progress);
    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:
    bool checkAll() const;
    bool update(const QString &path) const;
    void checkAll();
    void update(const QString &itemKey);

private slots:
#ifdef APP_DESKTOP
    void appImageUpdaterFinished(AppImageUpdater *updater);
#endif

private:
#ifdef QTLIB_UNIX
    QString describeAppImage(const QString &path) const;
    bool checkAppImage(const QString &path) const;
    bool updateAppImage(const QString &path);
#ifdef APP_DESKTOP
    void updateAppImage(const QString &itemKey);
#endif

    ConfigHandler *configHandler_;
    QJsonObject metadataSet_;
};
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@ int main(int argc, char *argv[])
    // Init
    QGuiApplication app(argc, argv); // This is backend program, but need GUI module

    auto envPath = QString::fromLocal8Bit(qgetenv("PATH").constData()) + ":" + app.applicationDirPath();
    qputenv("PATH", envPath.toUtf8().constData());

    auto *configHandler = new ConfigHandler(&app);
    auto appConfigApplication = configHandler->getAppConfigApplication();

@@ -44,14 +47,14 @@ int main(int argc, char *argv[])

    clParser.process(app);

    auto port = clParser.value(clOptionPort).toInt();
    auto port = clParser.value(clOptionPort).toUShort();

    // Setup websocket server
    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();
+95 −0
Original line number Diff line number Diff line
#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);
}
+41 −0
Original line number Diff line number Diff line
#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_;
};
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
#include <QWebSocketServer>
#include <QWebSocket>

#include "qtlib_json.h"
#include "qtil_json.h"

#include "handlers/confighandler.h"
#include "handlers/systemhandler.h"
@@ -28,22 +28,22 @@ WebSocketServer::WebSocketServer(ConfigHandler *configHandler, const QString &se
    updateHandler_ = new UpdateHandler(configHandler_, this);
    desktopThemeHandler_ = new DesktopThemeHandler(this);

    connect(itemHandler_, &ItemHandler::metadataSetChanged, this, &WebSocketServer::itemMetadataSetChanged);
    connect(itemHandler_, &ItemHandler::downloadStarted, this, &WebSocketServer::itemDownloadStarted);
    connect(itemHandler_, &ItemHandler::downloadFinished, this, &WebSocketServer::itemDownloadFinished);
    connect(itemHandler_, &ItemHandler::downloadProgress, this, &WebSocketServer::itemDownloadProgress);
    connect(itemHandler_, &ItemHandler::saveStarted, this, &WebSocketServer::itemSaveStarted);
    connect(itemHandler_, &ItemHandler::saveFinished, this, &WebSocketServer::itemSaveFinished);
    connect(itemHandler_, &ItemHandler::installStarted, this, &WebSocketServer::itemInstallStarted);
    connect(itemHandler_, &ItemHandler::installFinished, this, &WebSocketServer::itemInstallFinished);
    connect(itemHandler_, &ItemHandler::uninstallStarted, this, &WebSocketServer::itemUninstallStarted);
    connect(itemHandler_, &ItemHandler::uninstallFinished, this, &WebSocketServer::itemUninstallFinished);
    connect(itemHandler_, &ItemHandler::metadataSetChanged, this, &WebSocketServer::itemHandlerMetadataSetChanged);
    connect(itemHandler_, &ItemHandler::downloadStarted, this, &WebSocketServer::itemHandlerDownloadStarted);
    connect(itemHandler_, &ItemHandler::downloadFinished, this, &WebSocketServer::itemHandlerDownloadFinished);
    connect(itemHandler_, &ItemHandler::downloadProgress, this, &WebSocketServer::itemHandlerDownloadProgress);
    connect(itemHandler_, &ItemHandler::saveStarted, this, &WebSocketServer::itemHandlerSaveStarted);
    connect(itemHandler_, &ItemHandler::saveFinished, this, &WebSocketServer::itemHandlerSaveFinished);
    connect(itemHandler_, &ItemHandler::installStarted, this, &WebSocketServer::itemHandlerInstallStarted);
    connect(itemHandler_, &ItemHandler::installFinished, this, &WebSocketServer::itemHandlerInstallFinished);
    connect(itemHandler_, &ItemHandler::uninstallStarted, this, &WebSocketServer::itemHandlerUninstallStarted);
    connect(itemHandler_, &ItemHandler::uninstallFinished, this, &WebSocketServer::itemHandlerUninstallFinished);

    connect(updateHandler_, &UpdateHandler::checkAllStarted, this, &WebSocketServer::updateCheckAllStarted);
    connect(updateHandler_, &UpdateHandler::checkAllFinished, this, &WebSocketServer::updateCheckAllFinished);
    connect(updateHandler_, &UpdateHandler::updateStarted, this, &WebSocketServer::updateUpdateStarted);
    connect(updateHandler_, &UpdateHandler::updateFinished, this, &WebSocketServer::updateUpdateFinished);
    connect(updateHandler_, &UpdateHandler::updateProgress, this, &WebSocketServer::updateUpdateProgress);
    connect(updateHandler_, &UpdateHandler::checkAllStarted, this, &WebSocketServer::updateHandlerCheckAllStarted);
    connect(updateHandler_, &UpdateHandler::checkAllFinished, this, &WebSocketServer::updateHandlerCheckAllFinished);
    connect(updateHandler_, &UpdateHandler::updateStarted, this, &WebSocketServer::updateHandlerUpdateStarted);
    connect(updateHandler_, &UpdateHandler::updateFinished, this, &WebSocketServer::updateHandlerUpdateFinished);
    connect(updateHandler_, &UpdateHandler::updateProgress, this, &WebSocketServer::updateHandlerUpdateProgress);
}

WebSocketServer::~WebSocketServer()
@@ -55,6 +55,10 @@ WebSocketServer::~WebSocketServer()
bool WebSocketServer::start()
{
    if (wsServer_->listen(QHostAddress::Any, serverPort_)) {
        auto application = configHandler_->getUsrConfigApplication();
        application["websocket_url"] = serverUrl().toString();
        configHandler_->setUsrConfigApplication(application);

        emit started();
        return true;
    }
@@ -63,6 +67,10 @@ bool WebSocketServer::start()

void WebSocketServer::stop()
{
    auto application = configHandler_->getUsrConfigApplication();
    application["websocket_url"] = QString("");
    configHandler_->setUsrConfigApplication(application);

    wsServer_->close();
}

@@ -108,7 +116,7 @@ void WebSocketServer::wsTextMessageReceived(const QString &message)
{
    auto *wsClient = qobject_cast<QWebSocket *>(sender());
    if (wsClient) {
        qtlib::Json json(message.toUtf8());
        Qtil::Json json(message.toUtf8());
        if (json.isObject()) {
            auto object = json.toObject();
            receiveMessage(object["id"].toString(), object["func"].toString(), object["data"].toArray());
@@ -120,7 +128,7 @@ void WebSocketServer::wsBinaryMessageReceived(const QByteArray &message)
{
    auto *wsClient = qobject_cast<QWebSocket *>(sender());
    if (wsClient) {
        qtlib::Json json(message);
        Qtil::Json json(message);
        if (json.isObject()) {
            auto object = json.toObject();
            receiveMessage(object["id"].toString(), object["func"].toString(), object["data"].toArray());
@@ -128,27 +136,27 @@ void WebSocketServer::wsBinaryMessageReceived(const QByteArray &message)
    }
}

void WebSocketServer::itemMetadataSetChanged()
void WebSocketServer::itemHandlerMetadataSetChanged()
{
    QJsonArray data;
    sendMessage("", "ItemHandler::metadataSetChanged", data);
}

void WebSocketServer::itemDownloadStarted(QJsonObject result)
void WebSocketServer::itemHandlerDownloadStarted(QJsonObject result)
{
    QJsonArray data;
    data.append(result);
    sendMessage("", "ItemHandler::downloadStarted", data);
}

void WebSocketServer::itemDownloadFinished(QJsonObject result)
void WebSocketServer::itemHandlerDownloadFinished(QJsonObject result)
{
    QJsonArray data;
    data.append(result);
    sendMessage("", "ItemHandler::downloadFinished", data);
}

void WebSocketServer::itemDownloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal)
void WebSocketServer::itemHandlerDownloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal)
{
    QJsonArray data;
    data.append(id);
@@ -157,79 +165,82 @@ void WebSocketServer::itemDownloadProgress(QString id, qint64 bytesReceived, qin
    sendMessage("", "ItemHandler::downloadProgress", data);
}

void WebSocketServer::itemSaveStarted(QJsonObject result)
void WebSocketServer::itemHandlerSaveStarted(QJsonObject result)
{
    QJsonArray data;
    data.append(result);
    sendMessage("", "ItemHandler::saveStarted", data);
}

void WebSocketServer::itemSaveFinished(QJsonObject result)
void WebSocketServer::itemHandlerSaveFinished(QJsonObject result)
{
    QJsonArray data;
    data.append(result);
    sendMessage("", "ItemHandler::saveFinished", data);
}

void WebSocketServer::itemInstallStarted(QJsonObject result)
void WebSocketServer::itemHandlerInstallStarted(QJsonObject result)
{
    QJsonArray data;
    data.append(result);
    sendMessage("", "ItemHandler::installStarted", data);