- Modify Window.qml and Systray to show the App menu upon clicking the App button
on the top-right. Fall back to opening the general URL in case no apps are found.
- Introduce a new UserAppsModel in UserModel.cpp to access the fetched server Apps
from AccountState (propagated down from the User class).
Signed-off-by: Michael Schuster <michael@schuster.ms>
_trayEngine = new QQmlEngine;
_trayEngine->addImageProvider("avatars", new ImageProvider);
_trayEngine->rootContext()->setContextProperty("userModelBackend", UserModel::instance());
+ _trayEngine->rootContext()->setContextProperty("appsMenuModelBackend", UserAppsModel::instance());
_trayEngine->rootContext()->setContextProperty("systrayBackend", this);
_trayComponent = new QQmlComponent(_trayEngine, QUrl(QStringLiteral("qrc:/qml/src/gui/tray/Window.qml")));
connect(UserModel::instance(), &UserModel::newUserSelected,
- this, &Systray::slotChangeActivityModel);
+ this, &Systray::slotNewUserSelected);
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &Systray::showWindow);
}
}
-void Systray::slotChangeActivityModel()
+void Systray::slotNewUserSelected()
{
+ // Change ActivityModel
_trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
+
+ // Rebuild App list
+ UserAppsModel::instance()->buildAppList();
}
bool Systray::isOpen()
Q_INVOKABLE void showWindow();
public slots:
- void slotChangeActivityModel();
+ void slotNewUserSelected();
private:
static Systray *_instance;
connect(_account.data(), &AccountState::stateChanged,
[=]() { if (isConnected()) {slotRefresh();} });
+ connect(_account.data(), &AccountState::hasFetchedNavigationApps,
+ this, &User::slotRebuildNavigationAppList);
}
void User::slotBuildNotificationDisplay(const ActivityList &list)
}
}
+void User::slotRebuildNavigationAppList()
+{
+ // Rebuild App list
+ UserAppsModel::instance()->buildAppList();
+}
+
void User::slotNotificationRequestFinished(int statusCode)
{
int row = sender()->property("activityRow").toInt();
return _account->account()->capabilities().hasActivities();
}
+AccountAppList User::appList() const
+{
+ return _account->appList();
+}
+
bool User::isCurrentUser() const
{
return _isCurrentUser;
Q_INVOKABLE void UserModel::openCurrentAccountServer()
{
+ // Don't open this URL when the QML appMenu pops up on click (see Window.qml)
+ if(appList().count() > 0)
+ return;
+
QString url = _users[_currentUserId]->server(false);
if (!(url.contains("http://") || url.contains("https://"))) {
url = "https://" + _users[_currentUserId]->server(false);
_users[currentUserId()]->slotRefresh();
}
+AccountAppList UserModel::appList() const
+{
+ if (_users.count() >= 1) {
+ return _users[_currentUserId]->appList();
+ } else {
+ return AccountAppList();
+ }
+}
+
/*-------------------------------------------------------------------------------------*/
ImageProvider::ImageProvider()
}
}
+/*-------------------------------------------------------------------------------------*/
+
+UserAppsModel *UserAppsModel::_instance = nullptr;
+
+UserAppsModel *UserAppsModel::instance()
+{
+ if (_instance == nullptr) {
+ _instance = new UserAppsModel();
+ }
+ return _instance;
+}
+
+UserAppsModel::UserAppsModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+void UserAppsModel::buildAppList()
+{
+ beginRemoveRows(QModelIndex(), 0, rowCount());
+ _apps.clear();
+ endRemoveRows();
+
+ if(UserModel::instance()->appList().count() > 0) {
+ foreach(AccountApp *app, UserModel::instance()->appList()) {
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ _apps << app;
+ endInsertRows();
+ }
+ }
+}
+
+void UserAppsModel::openAppUrl(const QUrl &url)
+{
+ QDesktopServices::openUrl(url);
+}
+
+int UserAppsModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return _apps.count();
+}
+
+QVariant UserAppsModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= _apps.count()) {
+ return QVariant();
+ }
+
+ if (role == NameRole) {
+ return _apps[index.row()]->name();
+ } else if (role == UrlRole) {
+ return _apps[index.row()]->url();
+ }
+ return QVariant();
+}
+
+QHash<int, QByteArray> UserAppsModel::roleNames() const
+{
+ QHash<int, QByteArray> roles;
+ roles[NameRole] = "appName";
+ roles[UrlRole] = "appUrl";
+ return roles;
+}
+
}
QString server(bool shortened = true) const;
bool serverHasTalk() const;
bool hasActivities() const;
+ AccountAppList appList() const;
QImage avatar(bool whiteBg = false) const;
QString id() const;
void login() const;
void slotRefreshActivities();
void slotRefresh();
void setNotificationRefreshInterval(std::chrono::milliseconds interval);
+ void slotRebuildNavigationAppList();
private:
AccountStatePtr _account;
IdRole
};
+ AccountAppList appList() const;
+
signals:
Q_INVOKABLE void addAccount();
Q_INVOKABLE void refreshCurrentUserGui();
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
};
+class UserAppsModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ static UserAppsModel *instance();
+ virtual ~UserAppsModel() {};
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ enum UserAppsRoles {
+ NameRole = Qt::UserRole + 1,
+ UrlRole
+ };
+
+ void buildAppList();
+
+public slots:
+ void openAppUrl(const QUrl &url);
+
+protected:
+ QHash<int, QByteArray> roleNames() const;
+
+private:
+ static UserAppsModel *_instance;
+ UserAppsModel(QObject *parent = 0);
+
+ AccountAppList _apps;
+};
+
}
#endif // USERMODEL_H
hoverEnabled: true\r
onClicked:\r
{\r
+ /*\r
+ // The count() property was introduced in QtQuick.Controls 2.3 (Qt 5.10)\r
+ // so we handle this with userModelBackend.openCurrentAccountServer()\r
+ //\r
+ // See UserModel::openCurrentAccountServer() to disable this workaround\r
+ // in the future for Qt >= 5.10\r
+\r
+ if(appsMenu.count() > 0) {\r
+ appsMenu.popup();\r
+ } else {\r
+ userModelBackend.openCurrentAccountServer();\r
+ }\r
+ */\r
+\r
+ appsMenu.open();\r
userModelBackend.openCurrentAccountServer();\r
}\r
+\r
+ Menu {\r
+ id: appsMenu\r
+ x: (trayWindowAppsButton.x + 2)\r
+ y: (trayWindowAppsButton.y + trayWindowAppsButton.height + 2)\r
+ width: (trayWindowAppsButton.width - 2)\r
+ closePolicy: "CloseOnPressOutside"\r
+\r
+ background: Rectangle {\r
+ border.color: "#0082c9"\r
+ radius: 2\r
+ }\r
+\r
+ Instantiator {\r
+ id: appsMenuInstantiator\r
+ model: appsMenuModelBackend\r
+ onObjectAdded: appsMenu.insertItem(index, object)\r
+ onObjectRemoved: appsMenu.removeItem(object)\r
+ delegate: MenuItem {\r
+ text: appName\r
+ onTriggered: appsMenuModelBackend.openAppUrl(appUrl)\r
+ }\r
+ }\r
+ }\r
}\r
\r
background:\r