#include "creds/httpcredentials.h"
#include "logger.h"
#include "configfile.h"
+#include "ocsnavigationappsjob.h"
#include <QSettings>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
+#include <QJsonArray>
#include <QNetworkRequest>
#include <QBuffer>
// 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.
if (_state != Connected) {
setState(Connected);
setTalkCapability();
+
+ // Get the Apps available on the server.
+ fetchNavigationApps();
}
break;
case ConnectionValidator::Undefined:
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
class AccountState;
class Account;
+class AccountApp;
class RemoteWipe;
typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
+typedef QList<AccountApp*> AccountAppList;
/**
* @brief Extra info about an ownCloud server account.
bool hasTalk() const;
+ AccountAppList appList() const;
+
/** A user-triggered sign out which disconnects, stops syncs
* for the account and forgets the password. */
void signOutByUi();
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);
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;
*/
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 *)
#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>
#ifdef WITH_LIBCLOUDPROVIDERS
, _bus(QDBusConnection::sessionBus())
#endif
- , _recentActionsMenu(nullptr)
, _app(parent)
{
_tray = Systray::instance();
slotShowTrayMessage(title, msg);
}
-
/*
* open the folder with the given 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);
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);
/**
void slotRemoveDestroyedShareDialogs();
-protected slots:
- void slotOcsError(int statusCode, const QString &message);
-
private slots:
void slotLogin();
void slotLogout();
private:
void setPauseOnAllFoldersHelper(bool pause);
- void fetchNavigationApps(AccountStatePtr account);
- void buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu);
QPointer<Systray> _tray;
QPointer<SettingsDialog> _settingsDialog;
QDBusConnection _bus;
#endif
- QMenu *_recentActionsMenu;
- QVector<QMenu *> _accountMenus;
QMap<QString, QPointer<ShareDialog>> _shareDialogs;
QAction *_actionNewAccountWizard;
QAction *_actionEstimate;
- QMenu *_navLinksMenu;
- QMap<AccountStatePtr, QJsonArray> _navApps;
-
QList<QAction *> _recentItemsActions;
Application *_app;
};