Fetch server Apps in AccountState (moved from ownCloudGui)
authorMichael Schuster <michael@schuster.ms>
Wed, 15 Jan 2020 15:23:46 +0000 (16:23 +0100)
committerMichael Schuster <michael@schuster.ms>
Wed, 15 Jan 2020 15:23:46 +0000 (16:23 +0100)
- Add a new class AccountApp to keep them in an AccountAppList
  and also save properties like ID and Icon URL.

- Clear the app list upon re-fetch to avoid endlessly growing lists
  like in the previous implementation in ownCloudGui.

Signed-off-by: Michael Schuster <michael@schuster.ms>
src/gui/accountstate.cpp
src/gui/accountstate.h
src/gui/owncloudgui.cpp
src/gui/owncloudgui.h

index 9d2fa1830f57a69c83ec41b35b44d9960f265199..b9b42eca548d11a15b4ead2ca7560614a5174224 100644 (file)
@@ -20,6 +20,7 @@
 #include "creds/httpcredentials.h"
 #include "logger.h"
 #include "configfile.h"
+#include "ocsnavigationappsjob.h"
 
 #include <QSettings>
 #include <QTimer>
@@ -27,6 +28,7 @@
 
 #include <QJsonDocument>
 #include <QJsonObject>
+#include <QJsonArray>
 #include <QNetworkRequest>
 #include <QBuffer>
 
@@ -259,6 +261,9 @@ void AccountState::checkConnectivity()
         // Use a small authed propfind as a minimal ping when we're
         // already connected.
         conValidator->checkAuthentication();
+
+        // Get the Apps available on the server.
+        fetchNavigationApps();
     } else {
         // Check the server and then the auth.
 
@@ -316,6 +321,9 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
         if (_state != Connected) {
             setState(Connected);
             setTalkCapability();
+
+            // Get the Apps available on the server.
+            fetchNavigationApps();
         }
         break;
     case ConnectionValidator::Undefined:
@@ -428,4 +436,96 @@ std::unique_ptr<QSettings> AccountState::settings()
     return s;
 }
 
+void AccountState::fetchNavigationApps(){
+    OcsNavigationAppsJob *job = new OcsNavigationAppsJob(_account);
+    job->addRawHeader("If-None-Match", navigationAppsEtagResponseHeader());
+    connect(job, &OcsNavigationAppsJob::appsJobFinished, this, &AccountState::slotNavigationAppsFetched);
+    connect(job, &OcsNavigationAppsJob::etagResponseHeaderReceived, this, &AccountState::slotEtagResponseHeaderReceived);
+    connect(job, &OcsNavigationAppsJob::ocsError, this, &AccountState::slotOcsError);
+    job->getNavigationApps();
+}
+
+void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
+    if(statusCode == 200){
+        qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
+        setNavigationAppsEtagResponseHeader(value);
+    }
+}
+
+void AccountState::slotOcsError(int statusCode, const QString &message)
+{
+    qCDebug(lcAccountState) << "Error " << statusCode << " while fetching new navigation apps: " << message;
+}
+
+void AccountState::slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode)
+{
+    if(_account){
+        if (statusCode == 304) {
+            qCWarning(lcAccountState) << "Status code " << statusCode << " Not Modified - No new navigation apps.";
+        } else {
+            _apps.clear();
+            _hasTalk = false;
+
+            if(!reply.isEmpty()){
+                printf("%s\n", reply.toJson().toStdString().c_str());
+                auto element = reply.object().value("ocs").toObject().value("data");
+                auto navLinks = element.toArray();
+
+                if(navLinks.size() > 0){
+                    foreach (const QJsonValue &value, navLinks) {
+                        auto navLink = value.toObject();
+
+                        AccountApp *app = new AccountApp(navLink.value("name").toString(), QUrl(navLink.value("href").toString()),
+                            navLink.value("id").toString(), QUrl(navLink.value("icon").toString()));
+
+                        _apps << app;
+                    }
+                }
+            }
+
+            emit hasFetchedNavigationApps();
+        }
+    }
+}
+
+AccountAppList AccountState::appList() const
+{
+    return _apps;
+}
+
+/*-------------------------------------------------------------------------------------*/
+
+AccountApp::AccountApp(const QString &name, const QUrl &url,
+    const QString &id, const QUrl &iconUrl,
+    QObject *parent)
+    : QObject(parent)
+    , _name(name)
+    , _url(url)
+    , _id(id)
+    , _iconUrl(iconUrl)
+{
+}
+
+QString AccountApp::name() const
+{
+    return _name;
+}
+
+QUrl AccountApp::url() const
+{
+    return _url;
+}
+
+QString AccountApp::id() const
+{
+    return _id;
+}
+
+QUrl AccountApp::iconUrl() const
+{
+    return _iconUrl;
+}
+
+/*-------------------------------------------------------------------------------------*/
+
 } // namespace OCC
index 7633bd78dfa2c0d5e734f56302c73e00850ba012..8bacdcd9c7db318f3288058e5b4b6b534e62e2f2 100644 (file)
@@ -29,9 +29,11 @@ namespace OCC {
 
 class AccountState;
 class Account;
+class AccountApp;
 class RemoteWipe;
 
 typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
+typedef QList<AccountApp*> AccountAppList;
 
 /**
  * @brief Extra info about an ownCloud server account.
@@ -103,6 +105,8 @@ public:
 
     bool hasTalk() const;
 
+    AccountAppList appList() const;
+
     /** A user-triggered sign out which disconnects, stops syncs
      * for the account and forgets the password. */
     void signOutByUi();
@@ -164,10 +168,12 @@ public slots:
 private:
     void setState(State state);
     void setTalkCapability();
+    void fetchNavigationApps();
 
 signals:
     void stateChanged(int state);
     void isConnectedChanged();
+    void hasFetchedNavigationApps();
 
 protected Q_SLOTS:
     void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
@@ -179,6 +185,10 @@ protected Q_SLOTS:
     void slotCredentialsFetched(AbstractCredentials *creds);
     void slotCredentialsAsked(AbstractCredentials *creds);
 
+    void slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode);
+    void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
+    void slotOcsError(int statusCode, const QString &message);
+
 private:
     AccountPtr _account;
     State _state;
@@ -209,7 +219,34 @@ private:
      */
     RemoteWipe *_remoteWipe;
 
+    /**
+     * Holds the App names and URLs available on the server
+     */
+    AccountAppList _apps;
+
 };
+
+class AccountApp : public QObject
+{
+    Q_OBJECT
+public:
+    AccountApp(const QString &name, const QUrl &url,
+        const QString &id, const QUrl &iconUrl,
+        QObject* parent = 0);
+
+    QString name() const;
+    QUrl url() const;
+    QString id() const;
+    QUrl iconUrl() const;
+
+private:
+    QString _name;
+    QUrl _url;
+
+    QString _id;
+    QUrl _iconUrl;
+};
+
 }
 
 Q_DECLARE_METATYPE(OCC::AccountState *)
index b62122395b8968789da3931d31e45cb91b4cfb12..f4f37ba1ae7479de7196a2f9c886f88a9253ecf1 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "application.h"
 #include "owncloudgui.h"
-#include "ocsnavigationappsjob.h"
 #include "theme.h"
 #include "folderman.h"
 #include "progressdispatcher.h"
 #include <QX11Info>
 #endif
 
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonArray>
-
 #include <QQmlEngine>
 #include <QQmlComponent>
 #include <QQmlApplicationEngine>
@@ -68,7 +63,6 @@ ownCloudGui::ownCloudGui(Application *parent)
 #ifdef WITH_LIBCLOUDPROVIDERS
     , _bus(QDBusConnection::sessionBus())
 #endif
-    , _recentActionsMenu(nullptr)
     , _app(parent)
 {
     _tray = Systray::instance();
@@ -369,7 +363,6 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin
     slotShowTrayMessage(title, msg);
 }
 
-
 /*
  * open the folder with the given Alias
  */
@@ -393,93 +386,6 @@ void ownCloudGui::slotFolderOpenAction(const QString &alias)
     }
 }
 
-void ownCloudGui::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
-    if(statusCode == 200){
-        qCDebug(lcApplication) << "New navigation apps ETag Response Header received " << value;
-        auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC));
-        account->setNavigationAppsEtagResponseHeader(value);
-    }
-}
-
-void ownCloudGui::fetchNavigationApps(AccountStatePtr account){
-    OcsNavigationAppsJob *job = new OcsNavigationAppsJob(account->account());
-    job->setProperty(propertyAccountC, QVariant::fromValue(account));
-    job->addRawHeader("If-None-Match", account->navigationAppsEtagResponseHeader());
-    connect(job, &OcsNavigationAppsJob::appsJobFinished, this, &ownCloudGui::slotNavigationAppsFetched);
-    connect(job, &OcsNavigationAppsJob::etagResponseHeaderReceived, this, &ownCloudGui::slotEtagResponseHeaderReceived);
-    connect(job, &OcsNavigationAppsJob::ocsError, this, &ownCloudGui::slotOcsError);
-    job->getNavigationApps();
-}
-
-void ownCloudGui::buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu){
-    auto navLinks = _navApps.value(account);
-
-    _navLinksMenu->clear();
-    _navLinksMenu->setEnabled(navLinks.size() > 0);
-
-    if(navLinks.size() > 0){
-        // when there is only one account add the nav links above the settings
-        QAction *actionBefore = _actionSettings;
-
-        // when there is more than one account add the nav links above pause/unpause folder or logout action
-        if(AccountManager::instance()->accounts().size() > 1){
-            foreach(QAction *action, accountMenu->actions()){
-
-                // pause/unpause folder and logout actions have propertyAccountC
-                if(auto actionAccount = qvariant_cast<AccountStatePtr>(action->property(propertyAccountC))){
-                    if(actionAccount == account){
-                        actionBefore = action;
-                        break;
-                    }
-                }
-            }
-        }
-
-        // Create submenu with links
-        foreach (const QJsonValue &value, navLinks) {
-            auto navLink = value.toObject();
-            QAction *action = new QAction(navLink.value("name").toString(), this);
-            QUrl href(navLink.value("href").toString());
-            connect(action, &QAction::triggered, this, [href] { QDesktopServices::openUrl(href); });
-            _navLinksMenu->addAction(action);
-        }
-    }
-}
-
-void ownCloudGui::slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode)
-{
-    if(auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC))){
-        if (statusCode == 304) {
-            qCWarning(lcApplication) << "Status code " << statusCode << " Not Modified - No new navigation apps.";
-        } else {
-            if(!reply.isEmpty()){
-                auto element = reply.object().value("ocs").toObject().value("data");
-                auto navLinks = element.toArray();
-                _navApps.insert(account, navLinks);
-            }
-        }
-
-        // TODO see pull #523
-        auto accountList = AccountManager::instance()->accounts();
-        if(accountList.size() > 1){
-            // the list of apps will be displayed under the account that it belongs to
-            foreach (QMenu *accountMenu, _accountMenus) {
-                if(accountMenu->title() == account->account()->displayName()){
-                    buildNavigationAppsMenu(account, accountMenu);
-                    break;
-                }
-            }
-        } else if(accountList.size() == 1){
-            //buildNavigationAppsMenu(account, _contextMenu.data());
-        }
-    }
-}
-
-void ownCloudGui::slotOcsError(int statusCode, const QString &message)
-{
-    emit serverError(statusCode, message);
-}
-
 void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &progress)
 {
     Q_UNUSED(folder);
index 9efd34e8b9bee5d61065660ee41bd0f50128acf0..928a0fbd0b97fc44c95c3e7d95316efc9b62004c 100644 (file)
@@ -91,8 +91,6 @@ public slots:
     void slotOpenPath(const QString &path);
     void slotAccountStateChanged();
     void slotTrayMessageIfServerUnsupported(Account *account);
-    void slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode);
-    void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
 
 
     /**
@@ -106,9 +104,6 @@ public slots:
 
     void slotRemoveDestroyedShareDialogs();
 
-protected slots:
-    void slotOcsError(int statusCode, const QString &message);
-
 private slots:
     void slotLogin();
     void slotLogout();
@@ -118,8 +113,6 @@ private slots:
 
 private:
     void setPauseOnAllFoldersHelper(bool pause);
-    void fetchNavigationApps(AccountStatePtr account);
-    void buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu);
 
     QPointer<Systray> _tray;
     QPointer<SettingsDialog> _settingsDialog;
@@ -129,8 +122,6 @@ private:
     QDBusConnection _bus;
 #endif
 
-    QMenu *_recentActionsMenu;
-    QVector<QMenu *> _accountMenus;
     QMap<QString, QPointer<ShareDialog>> _shareDialogs;
 
     QAction *_actionNewAccountWizard;
@@ -138,9 +129,6 @@ private:
     QAction *_actionEstimate;
 
 
-    QMenu *_navLinksMenu;
-    QMap<AccountStatePtr, QJsonArray> _navApps;
-
     QList<QAction *> _recentItemsActions;
     Application *_app;
 };