mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-28 03:49:20 +03:00
First real activity connection
Signed-off-by: Dominique Fuchs <32204802+DominiqueFuchs@users.noreply.github.com>
This commit is contained in:
parent
f01c47e0ec
commit
e0641df727
6 changed files with 71 additions and 32 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "tray/UserModel.h"
|
#include "tray/UserModel.h"
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
@ -36,8 +37,7 @@
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
Systray::Systray() // TODO: make singleton, provide ::instance()
|
Systray::Systray() // TODO: make singleton, provide ::instance()
|
||||||
: _currentAccount(nullptr)
|
: _trayComponent(nullptr)
|
||||||
, _trayComponent(nullptr)
|
|
||||||
, _trayContext(nullptr)
|
, _trayContext(nullptr)
|
||||||
{
|
{
|
||||||
// Create QML tray engine, build component, set C++ backend context used in window.qml
|
// Create QML tray engine, build component, set C++ backend context used in window.qml
|
||||||
|
@ -46,17 +46,17 @@ Systray::Systray() // TODO: make singleton, provide ::instance()
|
||||||
_trayEngine->addImageProvider("avatars", new ImageProvider);
|
_trayEngine->addImageProvider("avatars", new ImageProvider);
|
||||||
_trayEngine->rootContext()->setContextProperty("userModelBackend", UserModel::instance());
|
_trayEngine->rootContext()->setContextProperty("userModelBackend", UserModel::instance());
|
||||||
_trayEngine->rootContext()->setContextProperty("systrayBackend", this);
|
_trayEngine->rootContext()->setContextProperty("systrayBackend", this);
|
||||||
|
|
||||||
_trayComponent = new QQmlComponent(_trayEngine, QUrl(QStringLiteral("qrc:/qml/src/gui/tray/Window.qml")));
|
_trayComponent = new QQmlComponent(_trayEngine, QUrl(QStringLiteral("qrc:/qml/src/gui/tray/Window.qml")));
|
||||||
_trayContext = _trayEngine->contextForObject(_trayComponent->create());
|
_trayContext = _trayEngine->contextForObject(_trayComponent->create());
|
||||||
|
|
||||||
// TODO: hack to pass the icon to QML
|
|
||||||
//ctxt->setContextProperty("theme", QLatin1String("colored"));
|
|
||||||
//ctxt->setContextProperty("filename", "state-offline");
|
|
||||||
|
|
||||||
if (!AccountManager::instance()->accounts().isEmpty()) {
|
if (!AccountManager::instance()->accounts().isEmpty()) {
|
||||||
slotChangeActivityModel(AccountManager::instance()->accounts().first());
|
slotChangeActivityModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(UserModel::instance(), &UserModel::newUserSelected,
|
||||||
|
this, &Systray::slotChangeActivityModel);
|
||||||
|
|
||||||
hideWindow();
|
hideWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +64,10 @@ Systray::~Systray()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Systray::slotChangeActivityModel(const AccountStatePtr account)
|
void Systray::slotChangeActivityModel()
|
||||||
{
|
{
|
||||||
_currentAccount = account;
|
|
||||||
emit currentUserChanged();
|
|
||||||
_trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
|
_trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
|
||||||
|
emit currentUserChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Systray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint)
|
void Systray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint)
|
||||||
|
@ -109,10 +108,10 @@ int Systray::calcTrayWindowX()
|
||||||
int trayIconTopCenterX = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).x();
|
int trayIconTopCenterX = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).x();
|
||||||
int trayIconTopCenterY = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).y();
|
int trayIconTopCenterY = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).y();
|
||||||
|
|
||||||
if ( (trayScreen->geometry().width() - trayIconTopCenterX) < (trayScreen->geometry().width() * 0.5) ) {
|
if ((trayScreen->geometry().width() - trayIconTopCenterX) < (trayScreen->geometry().width() * 0.5)) {
|
||||||
// tray icon is on right side of the screen
|
// tray icon is on right side of the screen
|
||||||
if ( ((trayScreen->geometry().width() - trayIconTopCenterX) < trayScreen->geometry().height() - trayIconTopCenterY)
|
if (((trayScreen->geometry().width() - trayIconTopCenterX) < trayScreen->geometry().height() - trayIconTopCenterY)
|
||||||
&& ((trayScreen->geometry().width() - trayIconTopCenterX) < trayIconTopCenterY) ) {
|
&& ((trayScreen->geometry().width() - trayIconTopCenterX) < trayIconTopCenterY)) {
|
||||||
// taskbar is on the right
|
// taskbar is on the right
|
||||||
return trayScreen->availableSize().width() - 400 - 6;
|
return trayScreen->availableSize().width() - 400 - 6;
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,20 +131,20 @@ int Systray::calcTrayWindowX()
|
||||||
}
|
}
|
||||||
int Systray::calcTrayWindowY()
|
int Systray::calcTrayWindowY()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||||
QScreen *trayScreen = QGuiApplication::screenAt(this->geometry().topRight());
|
QScreen *trayScreen = QGuiApplication::screenAt(this->geometry().topRight());
|
||||||
#else
|
#else
|
||||||
QScreen *trayScreen = QGuiApplication::primaryScreen();
|
QScreen *trayScreen = QGuiApplication::primaryScreen();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// get coordinates from top center point of tray icon
|
// get coordinates from top center point of tray icon
|
||||||
int trayIconTopCenterX = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).x();
|
int trayIconTopCenterX = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).x();
|
||||||
int trayIconTopCenterY = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).y();
|
int trayIconTopCenterY = (this->geometry().topRight() - ((this->geometry().topRight() - this->geometry().topLeft()) * 0.5)).y();
|
||||||
|
|
||||||
if ( (trayScreen->geometry().height() - trayIconTopCenterY) < (trayScreen->geometry().height() * 0.5) ) {
|
if ((trayScreen->geometry().height() - trayIconTopCenterY) < (trayScreen->geometry().height() * 0.5)) {
|
||||||
// tray icon is on bottom side of the screen
|
// tray icon is on bottom side of the screen
|
||||||
if ( ((trayScreen->geometry().height() - trayIconTopCenterY) < trayScreen->geometry().width() - trayIconTopCenterX )
|
if (((trayScreen->geometry().height() - trayIconTopCenterY) < trayScreen->geometry().width() - trayIconTopCenterX)
|
||||||
&& ((trayScreen->geometry().height() - trayIconTopCenterY) < trayIconTopCenterX) ) {
|
&& ((trayScreen->geometry().height() - trayIconTopCenterY) < trayIconTopCenterX)) {
|
||||||
// taskbar is on the bottom
|
// taskbar is on the bottom
|
||||||
return trayScreen->availableSize().height() - 500 - 6;
|
return trayScreen->availableSize().height() - 500 - 6;
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,6 +160,4 @@ int Systray::calcTrayWindowY()
|
||||||
return (trayScreen->geometry().height() - trayScreen->availableGeometry().height()) + 6;
|
return (trayScreen->geometry().height() - trayScreen->availableGeometry().height()) + 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
|
@ -58,10 +58,9 @@ signals:
|
||||||
Q_INVOKABLE void showWindow();
|
Q_INVOKABLE void showWindow();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotChangeActivityModel(const AccountStatePtr account);
|
void slotChangeActivityModel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AccountStatePtr _currentAccount;
|
|
||||||
QQmlEngine *_trayEngine;
|
QQmlEngine *_trayEngine;
|
||||||
QQmlComponent *_trayComponent;
|
QQmlComponent *_trayComponent;
|
||||||
QQmlContext *_trayContext;
|
QQmlContext *_trayContext;
|
||||||
|
|
|
@ -45,6 +45,10 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
roles[PathRole] = "path";
|
roles[PathRole] = "path";
|
||||||
roles[MessageRole] = "message";
|
roles[MessageRole] = "message";
|
||||||
|
roles[ActionRole] = "type";
|
||||||
|
roles[ActionIconRole] = "icon";
|
||||||
|
roles[ActionTextRole] = "subject";
|
||||||
|
roles[ObjectTypeRole] = "objectType";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +77,8 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||||
if(folder) relPath.prepend(folder->remotePath());
|
if(folder) relPath.prepend(folder->remotePath());
|
||||||
list = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());
|
list = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());
|
||||||
if (list.count() > 0) {
|
if (list.count() > 0) {
|
||||||
return QVariant(list.at(0));
|
QString path = "file:///" + QString(list.at(0));
|
||||||
|
return QUrl(path);
|
||||||
}
|
}
|
||||||
// File does not exist anymore? Let's try to open its path
|
// File does not exist anymore? Let's try to open its path
|
||||||
if(QFileInfo(relPath).exists()) {
|
if(QFileInfo(relPath).exists()) {
|
||||||
|
@ -83,7 +88,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QString();
|
||||||
case ActionsLinksRole:{
|
case ActionsLinksRole:{
|
||||||
QList<QVariant> customList;
|
QList<QVariant> customList;
|
||||||
foreach (ActivityLink customItem, a._links) {
|
foreach (ActivityLink customItem, a._links) {
|
||||||
|
@ -96,13 +101,13 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||||
case ActionIconRole:{
|
case ActionIconRole:{
|
||||||
ActionIcon actionIcon;
|
ActionIcon actionIcon;
|
||||||
if(a._type == Activity::NotificationType){
|
if(a._type == Activity::NotificationType){
|
||||||
/*QIcon cachedIcon = ServerNotificationHandler::iconCache.value(a._id);
|
QIcon cachedIcon;
|
||||||
if(!cachedIcon.isNull()) {
|
if(!cachedIcon.isNull()) {
|
||||||
actionIcon.iconType = ActivityIconType::iconUseCached;
|
actionIcon.iconType = ActivityIconType::iconUseCached;
|
||||||
actionIcon.cachedIcon = cachedIcon;
|
actionIcon.cachedIcon = cachedIcon;
|
||||||
} else {
|
} else {
|
||||||
actionIcon.iconType = ActivityIconType::iconBell;
|
actionIcon.iconType = ActivityIconType::iconBell;
|
||||||
}*/
|
}
|
||||||
} else if(a._type == Activity::SyncResultType){
|
} else if(a._type == Activity::SyncResultType){
|
||||||
actionIcon.iconType = ActivityIconType::iconStateError;
|
actionIcon.iconType = ActivityIconType::iconStateError;
|
||||||
} else if(a._type == Activity::SyncFileItemType){
|
} else if(a._type == Activity::SyncFileItemType){
|
||||||
|
@ -131,13 +136,25 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||||
case ObjectTypeRole:
|
case ObjectTypeRole:
|
||||||
return a._objectType;
|
return a._objectType;
|
||||||
case ActionRole:{
|
case ActionRole:{
|
||||||
QVariant type;
|
switch (a._type) {
|
||||||
type.setValue(a._type);
|
case Activity::ActivityType:
|
||||||
return type;
|
return "Activity";
|
||||||
|
case Activity::NotificationType:
|
||||||
|
return "Notification";
|
||||||
|
case Activity::SyncFileItemType:
|
||||||
|
return "File";
|
||||||
|
case Activity::SyncResultType:
|
||||||
|
return "Sync";
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case ActionTextRole:
|
case ActionTextRole:
|
||||||
return a._subject;
|
return a._subject;
|
||||||
case MessageRole:
|
case MessageRole:
|
||||||
|
if (a._message.isEmpty()) {
|
||||||
|
return QString("No description available.");
|
||||||
|
}
|
||||||
return a._message;
|
return a._message;
|
||||||
case LinkRole:
|
case LinkRole:
|
||||||
return a._link;
|
return a._link;
|
||||||
|
|
|
@ -86,6 +86,11 @@ bool User::serverHasTalk() const
|
||||||
return _account->hasTalk();
|
return _account->hasTalk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool User::hasActivities() const
|
||||||
|
{
|
||||||
|
return _account->account()->capabilities().hasActivities();
|
||||||
|
}
|
||||||
|
|
||||||
bool User::isCurrentUser() const
|
bool User::isCurrentUser() const
|
||||||
{
|
{
|
||||||
return _isCurrentUser;
|
return _isCurrentUser;
|
||||||
|
@ -195,7 +200,7 @@ Q_INVOKABLE void UserModel::openCurrentAccountTalk()
|
||||||
Q_INVOKABLE void UserModel::openCurrentAccountServer()
|
Q_INVOKABLE void UserModel::openCurrentAccountServer()
|
||||||
{
|
{
|
||||||
QString url = _users[_currentUserId].server(false);
|
QString url = _users[_currentUserId].server(false);
|
||||||
if (! (url.contains("http://") || url.contains("https://")) ) {
|
if (!(url.contains("http://") || url.contains("https://"))) {
|
||||||
url = "https://" + _users[_currentUserId].server(false);
|
url = "https://" + _users[_currentUserId].server(false);
|
||||||
}
|
}
|
||||||
QDesktopServices::openUrl(QUrl(url));
|
QDesktopServices::openUrl(QUrl(url));
|
||||||
|
@ -251,6 +256,11 @@ ActivityListModel *UserModel::currentActivityModel()
|
||||||
return _users[currentUserIndex()].getActivityModel();
|
return _users[currentUserIndex()].getActivityModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UserModel::currentUserHasActivities()
|
||||||
|
{
|
||||||
|
return _users[currentUserIndex()].hasActivities();
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
ImageProvider::ImageProvider()
|
ImageProvider::ImageProvider()
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QString server(bool shortened = true) const;
|
QString server(bool shortened = true) const;
|
||||||
bool serverHasTalk() const;
|
bool serverHasTalk() const;
|
||||||
|
bool hasActivities() const;
|
||||||
QImage avatar() const;
|
QImage avatar() const;
|
||||||
QString id() const;
|
QString id() const;
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ public:
|
||||||
Q_INVOKABLE bool isCurrentUserConnected();
|
Q_INVOKABLE bool isCurrentUserConnected();
|
||||||
Q_INVOKABLE QString currentUserName();
|
Q_INVOKABLE QString currentUserName();
|
||||||
Q_INVOKABLE QString currentUserServer();
|
Q_INVOKABLE QString currentUserServer();
|
||||||
|
Q_INVOKABLE bool currentUserHasActivities();
|
||||||
Q_INVOKABLE bool currentServerHasTalk();
|
Q_INVOKABLE bool currentServerHasTalk();
|
||||||
Q_INVOKABLE void switchCurrentUser(const int &id);
|
Q_INVOKABLE void switchCurrentUser(const int &id);
|
||||||
|
|
||||||
|
|
|
@ -393,17 +393,22 @@ Window {
|
||||||
sourceSize.width: 48
|
sourceSize.width: 48
|
||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
|
id: activityTextColumn
|
||||||
Layout.leftMargin: 6
|
Layout.leftMargin: 6
|
||||||
spacing: 4
|
spacing: 4
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
Text {
|
Text {
|
||||||
id: activityTextTitle
|
id: activityTextTitle
|
||||||
text: path
|
text: subject
|
||||||
|
width: 220
|
||||||
|
elide: Text.ElideRight
|
||||||
font.pointSize: 9
|
font.pointSize: 9
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
id: activityTextInfo
|
id: activityTextInfo
|
||||||
text: message
|
text: path
|
||||||
|
width: 220
|
||||||
|
elide: Text.ElideRight
|
||||||
font.pointSize: 8
|
font.pointSize: 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,19 +417,28 @@ Window {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
|
id: activityButton1
|
||||||
Layout.preferredWidth: activityItem.height
|
Layout.preferredWidth: activityItem.height
|
||||||
Layout.preferredHeight: activityItem.height
|
Layout.preferredHeight: activityItem.height
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
flat: true
|
flat: true
|
||||||
|
hoverEnabled: false
|
||||||
|
visible: (path === "") ? false : true
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
icon.source: "qrc:///client/resources/files.svg"
|
icon.source: "qrc:///client/resources/files.svg"
|
||||||
icon.color: "transparent"
|
icon.color: "transparent"
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
Qt.openUrlExternally(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
Layout.preferredWidth: activityItem.height
|
Layout.preferredWidth: activityItem.height
|
||||||
Layout.preferredHeight: activityItem.height
|
Layout.preferredHeight: activityItem.height
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
flat: true
|
flat: true
|
||||||
|
hoverEnabled: false
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
icon.source: "qrc:///client/resources/public.svg"
|
icon.source: "qrc:///client/resources/public.svg"
|
||||||
icon.color: "transparent"
|
icon.color: "transparent"
|
||||||
|
|
Loading…
Reference in a new issue