diff --git a/README.md b/README.md
index cd6db47e89b0743635f5fb1051c6459dba0894d9..53a3b3fdf16f384b4cf45a20574b386d456a6b5f 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 [![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 filemanagement and "apply".
+A tool to handle item installation from OCS provider, file management, and apply themes.
 
 Copyright: 2017, Opendesktop.org
 
diff --git a/app/configs/application.json b/app/configs/application.json
index e08a138128479bd5bfc0d7fc1394364977cd77ae..32460d9f8ea58b929c98b3e3e1ea0330690b8c85 100644
--- a/app/configs/application.json
+++ b/app/configs/application.json
@@ -1,11 +1,11 @@
 {
     "id": "ocs-manager",
     "name": "ocs-manager",
-    "version": "0.2.1",
+    "version": "0.3.0",
     "organization": "Opendesktop.org",
     "domain": "org.opendesktop.ocs-manager",
     "icon": "",
-    "description": "A tool to handle filemanagement and apply.",
+    "description": "A tool to handle item installation from OCS provider, file management, and apply themes.",
     "license": "GPL-3+",
     "author": "Opendesktop.org",
     "contact": "contact@opendesktop.org",
diff --git a/app/src/handlers/itemhandler.cpp b/app/src/handlers/itemhandler.cpp
index d7e46bcebabdd8a0c34c442af5fb333eeb0e92df..39aa42b04bacd60e41cdbd906aa119ab6f5a6bdd 100644
--- a/app/src/handlers/itemhandler.cpp
+++ b/app/src/handlers/itemhandler.cpp
@@ -48,6 +48,13 @@ void ItemHandler::getItem(const QString &command, const QString &url, const QStr
     QJsonObject result;
     result["metadata"] = metadata;
 
+    if (command == "install" && configHandler_->getUsrConfigInstalledItems().contains(itemKey)) {
+        result["status"] = QString("error_downloadstart");
+        result["message"] = tr("The item already installed");
+        emit downloadStarted(result);
+        return;
+    }
+
     auto itemMetadataSet = metadataSet();
 
     if (itemMetadataSet.contains(itemKey)) {
@@ -124,6 +131,14 @@ void ItemHandler::getItemByOcsUrl(const QString &ocsUrl, const QString &provider
 void ItemHandler::uninstall(const QString &itemKey)
 {
     QJsonObject result;
+
+    if (!configHandler_->getUsrConfigInstalledItems().contains(itemKey)) {
+        result["status"] = QString("error_uninstallstart");
+        result["message"] = tr("The item not installed");
+        emit uninstallStarted(result);
+        return;
+    }
+
     result["status"] = QString("success_uninstallstart");
     result["message"] = tr("Uninstalling");
     emit uninstallStarted(result);
@@ -259,6 +274,11 @@ void ItemHandler::saveDownloadedFile(qtlib::NetworkResource *resource)
     destDir.make();
     qtlib::File destFile(destDir.path() + "/" + filename);
 
+    if (destFile.exists()) {
+        auto filenamePrefix = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_";
+        destFile.setPath(destDir.path() + "/" + filenamePrefix + filename);
+    }
+
     if (!resource->saveData(destFile.path())) {
         result["status"] = QString("error_save");
         result["message"] = tr("Failed to save data");
@@ -294,8 +314,8 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
     auto filename = metadata["filename"].toString();
     auto installType = metadata["install_type"].toString();
 
-    auto prefix = configHandler_->getAppConfigApplication()["id"].toString() + "_" + filename;
-    qtlib::Dir tempDir(qtlib::Dir::tempPath() + "/" + prefix);
+    auto tempDirPrefix = configHandler_->getAppConfigApplication()["id"].toString() + "_" + filename;
+    qtlib::Dir tempDir(qtlib::Dir::tempPath() + "/" + tempDirPrefix);
     tempDir.make();
     qtlib::Dir tempDestDir(tempDir.path() + "/dest");
     tempDestDir.make();
@@ -392,14 +412,22 @@ void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource)
     destDir.make();
 
     QJsonArray installedFiles;
+    auto filenamePrefix = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_";
+
     for (const auto &fileInfo : tempDestDir.list()) {
-        installedFiles.append(QJsonValue(fileInfo.fileName()));
+        auto destFilename = fileInfo.fileName();
+        if (QFileInfo::exists(destDir.path() + "/" + destFilename)) {
+            destFilename = filenamePrefix + destFilename;
+        }
+
         if (fileInfo.isDir()) {
-            qtlib::Dir(fileInfo.filePath()).move(destDir.path() + "/" + fileInfo.fileName());
+            qtlib::Dir(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
         }
         else {
-            qtlib::File(fileInfo.filePath()).move(destDir.path() + "/" + fileInfo.fileName());
+            qtlib::File(fileInfo.filePath()).move(destDir.path() + "/" + destFilename);
         }
+
+        installedFiles.append(QJsonValue(destFilename));
     }
 
     // Installation post-process
diff --git a/app/src/handlers/systemhandler.cpp b/app/src/handlers/systemhandler.cpp
index 13ff4a61984b4d915f347993c12d5fd55811492e..461cbce430c7a462b49dc837e9c42ea1c327eef7 100644
--- a/app/src/handlers/systemhandler.cpp
+++ b/app/src/handlers/systemhandler.cpp
@@ -64,7 +64,7 @@ bool SystemHandler::openUrl(const QString &url) const
 
 QString SystemHandler::desktopEnvironment() const
 {
-    QString desktop = "unknown";
+    QString desktop = "";
     QString currentDesktop = "";
 
     if (!qgetenv("XDG_CURRENT_DESKTOP").isEmpty()) {
@@ -93,152 +93,146 @@ bool SystemHandler::isApplicableType(const QString &installType) const
 {
     auto desktop = desktopEnvironment();
 
-    if (installType == "wallpapers"
-            && (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
-        return true;
+    QStringList applicableTypes;
+
+    if (desktop == "kde") {
+        applicableTypes << "wallpapers";
     }
-    /*else if (installType == "icons"
-             && (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
-        return true;
+    else if (desktop == "gnome") {
+        applicableTypes << "wallpapers"
+                        << "icons"
+                        << "cursors"
+                        << "gtk3_themes"
+                        << "gnome_shell_themes";
     }
-    else if (installType == "cursors"
-             && (desktop == "kde" || desktop == "gnome" || desktop == "xfce")) {
-        return true;
+    else if (desktop == "xfce") {
+        applicableTypes << "wallpapers";
     }
-    else if ((installType == "aurorae_themes" && desktop == "kde")
-             || (installType == "metacity_themes" && desktop == "gnome")
-             || (installType == "xfwm4_themes" && desktop == "xfce")) {
-        return true;
-    }*/
-    return false;
+
+    return applicableTypes.contains(installType);
 }
 
 #ifdef QTLIB_UNIX
 bool SystemHandler::applyFile(const QString &path, const QString &installType) const
 {
     if (QFileInfo::exists(path) && isApplicableType(installType)) {
-        if (installType == "wallpapers") {
-            return applyWallpaper(path);
+        auto desktop = desktopEnvironment();
+
+        if (desktop == "kde") {
+            if (installType == "wallpapers") {
+                return applyKdeWallpaper(path);
+            }
         }
-        /*else if (installType == "icons") {
-            return applyIcon(path);
+        else if (desktop == "gnome") {
+            if (installType == "wallpapers") {
+                return applyGnomeWallpaper(path);
+            }
+            else if (installType == "icons") {
+                return applyGnomeIcon(path);
+            }
+            else if (installType == "cursors") {
+                return applyGnomeCursor(path);
+            }
+            else if (installType == "gtk3_themes") {
+                return applyGnomeGtk3Theme(path);
+            }
+            else if (installType == "gnome_shell_themes") {
+                return applyGnomeGnomeShellTheme(path);
+            }
         }
-        else if (installType == "cursors") {
-            return applyCursor(path);
+        else if (desktop == "xfce") {
+            if (installType == "wallpapers") {
+                return applyXfceWallpaper(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) const
+bool SystemHandler::applyKdeWallpaper(const QString &path) const
 {
-    auto desktop = desktopEnvironment();
+    auto message = QDBusMessage::createMethodCall("org.kde.plasmashell", "/PlasmaShell", "org.kde.PlasmaShell", "evaluateScript");
 
-    if (desktop == "kde") {
-        // plasma5.6+
-        auto 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);
-
-        auto reply = QDBusConnection::sessionBus().call(message);
-
-        if (reply.type() == QDBusMessage::ErrorMessage) {
-            qWarning() << reply.errorMessage();
-            return false;
-        }
-        return true;
-    }
-    else if (desktop == "gnome") {
-        // gnome3
-        QStringList arguments{"set", "org.gnome.desktop.background", "picture-uri", "file://" + path};
-        return QProcess::startDetached("gsettings", arguments);
-        // gnome2
-        //QStringList arguments{"--type=string", "--set", "/desktop/gnome/background/picture_filename", path};
-        //return QProcess::startDetached("gconftool-2", arguments);
-    }
-    else if (desktop == "xfce") {
-        auto 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);
+    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(channelValue) << QVariant(propertyValue) << QVariant::fromValue(valueValue);
-        message.setArguments(arguments);
+    QVariantList arguments;
+    arguments << QVariant(script);
+    message.setArguments(arguments);
 
-        auto reply = QDBusConnection::sessionBus().call(message);
+    auto reply = QDBusConnection::sessionBus().call(message);
 
-        if (reply.type() == QDBusMessage::ErrorMessage) {
-            qWarning() << reply.errorMessage();
-            return false;
-        }
-        return true;
+    if (reply.type() == QDBusMessage::ErrorMessage) {
+        qWarning() << reply.errorMessage();
+        return false;
     }
-    return false;
+
+    return true;
 }
 
-bool SystemHandler::applyIcon(const QString &path) const
+bool SystemHandler::applyGnomeWallpaper(const QString &path) const
 {
-    qDebug() << path;
-
-    auto desktop = desktopEnvironment();
+    QStringList arguments{"set", "org.gnome.desktop.background", "picture-uri", "file://" + path};
+    return QProcess::startDetached("gsettings", arguments);
+}
 
-    if (desktop == "kde") {
-    }
-    else if (desktop == "gnome") {
-    }
-    else if (desktop == "xfce") {
-    }
-    return false;
+bool SystemHandler::applyGnomeIcon(const QString &path) const
+{
+    auto themeName = QFileInfo(path).fileName();
+    QStringList arguments{"set", "org.gnome.desktop.interface", "icon-theme", themeName};
+    return QProcess::startDetached("gsettings", arguments);
 }
 
-bool SystemHandler::applyCursor(const QString &path) const
+bool SystemHandler::applyGnomeCursor(const QString &path) const
 {
-    qDebug() << path;
+    auto themeName = QFileInfo(path).fileName();
+    QStringList arguments{"set", "org.gnome.desktop.interface", "cursor-theme", themeName};
+    return QProcess::startDetached("gsettings", arguments);
+}
 
-    auto desktop = desktopEnvironment();
+bool SystemHandler::applyGnomeGtk3Theme(const QString &path) const
+{
+    auto themeName = QFileInfo(path).fileName();
+    QStringList arguments{"set", "org.gnome.desktop.interface", "gtk-theme", themeName};
+    return QProcess::startDetached("gsettings", arguments);
+}
 
-    if (desktop == "kde") {
-    }
-    else if (desktop == "gnome") {
-    }
-    else if (desktop == "xfce") {
-    }
-    return false;
+bool SystemHandler::applyGnomeGnomeShellTheme(const QString &path) const
+{
+    auto themeName = QFileInfo(path).fileName();
+    QStringList arguments{"set", "org.gnome.shell.extensions.user-theme", "name", themeName};
+    return QProcess::startDetached("gsettings", arguments);
 }
 
-bool SystemHandler::applyWindowTheme(const QString &path) const
+bool SystemHandler::applyXfceWallpaper(const QString &path) const
 {
-    qDebug() << path;
+    auto message = QDBusMessage::createMethodCall("org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", "SetProperty");
 
-    auto desktop = desktopEnvironment();
+    QString channelValue = "xfce4-desktop";
+    //QString propertyValue = "/backdrop/screen0/monitor0/image-path";
+    QString propertyValue = "/backdrop/screen0/monitor0/workspace0/last-image";
+    QDBusVariant valueValue(path);
 
-    if (desktop == "kde") {
-    }
-    else if (desktop == "gnome") {
-    }
-    else if (desktop == "xfce") {
+    QVariantList arguments;
+    arguments << QVariant(channelValue) << QVariant(propertyValue) << QVariant::fromValue(valueValue);
+    message.setArguments(arguments);
+
+    auto reply = QDBusConnection::sessionBus().call(message);
+
+    if (reply.type() == QDBusMessage::ErrorMessage) {
+        qWarning() << reply.errorMessage();
+        return false;
     }
-    return false;
+
+    return true;
 }
 #endif
diff --git a/app/src/handlers/systemhandler.h b/app/src/handlers/systemhandler.h
index b4697833b8a86be062fa31a0dbfe1e7132818153..3ea555e5983718de0a9fae0b17ddc8983d7e39c8 100644
--- a/app/src/handlers/systemhandler.h
+++ b/app/src/handlers/systemhandler.h
@@ -23,9 +23,14 @@ public slots:
 
 private:
 #ifdef QTLIB_UNIX
-    bool applyWallpaper(const QString &path) const;
-    bool applyIcon(const QString &path) const;
-    bool applyCursor(const QString &path) const;
-    bool applyWindowTheme(const QString &path) const;
+    bool applyKdeWallpaper(const QString &path) const;
+
+    bool applyGnomeWallpaper(const QString &path) const;
+    bool applyGnomeIcon(const QString &path) const;
+    bool applyGnomeCursor(const QString &path) const;
+    bool applyGnomeGtk3Theme(const QString &path) const;
+    bool applyGnomeGnomeShellTheme(const QString &path) const;
+
+    bool applyXfceWallpaper(const QString &path) const;
 #endif
 };
diff --git a/app/src/main.cpp b/app/src/main.cpp
index f1df5336d391c7b127974af9c0117fd10a7559d9..36827d1bdac104a676a7fbe926e4387c01158fc2 100644
--- a/app/src/main.cpp
+++ b/app/src/main.cpp
@@ -15,7 +15,7 @@ int main(int argc, char *argv[])
     // Init
     QGuiApplication app(argc, argv); // This is backend program, but need GUI module
 
-    auto *configHandler = new ConfigHandler();
+    auto *configHandler = new ConfigHandler(&app);
     auto appConfigApplication = configHandler->getAppConfigApplication();
 
     app.setApplicationName(appConfigApplication["name"].toString());