mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-22 04:55:48 +03:00
Use dynamic path for account online/offline state icon. Refresh GUI on connection state change.
Signed-off-by: Alex Zolotov <alex.zolotov.nextcloud.com> Signed-off-by: allexzander <blackslayer4@gmail.com>
This commit is contained in:
parent
10cb0a71eb
commit
665a8c4217
7 changed files with 106 additions and 9 deletions
|
@ -81,7 +81,9 @@ MenuItem {
|
||||||
}
|
}
|
||||||
Image {
|
Image {
|
||||||
id: accountStateIndicator
|
id: accountStateIndicator
|
||||||
source: isConnected ? "qrc:///client/theme/colored/state-ok.svg" : "qrc:///client/theme/colored/state-offline.svg"
|
source: model.isConnected
|
||||||
|
? Style.stateOnlineImageSource
|
||||||
|
: Style.stateOfflineImageSource
|
||||||
cache: false
|
cache: false
|
||||||
x: accountStateIndicatorBackground.x + 1
|
x: accountStateIndicatorBackground.x + 1
|
||||||
y: accountStateIndicatorBackground.y + 1
|
y: accountStateIndicatorBackground.y + 1
|
||||||
|
@ -89,7 +91,7 @@ MenuItem {
|
||||||
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
sourceSize.height: Style.accountAvatarStateIndicatorSize
|
||||||
|
|
||||||
Accessible.role: Accessible.Indicator
|
Accessible.role: Accessible.Indicator
|
||||||
Accessible.name: isConnected ? qsTr("Account connected") : qsTr("Account not connected")
|
Accessible.name: model.isConnected ? qsTr("Account connected") : qsTr("Account not connected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,11 +165,11 @@ MenuItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: isConnected ? qsTr("Log out") : qsTr("Log in")
|
text: model.isConnected ? qsTr("Log out") : qsTr("Log in")
|
||||||
font.pixelSize: Style.topLinePixelSize
|
font.pixelSize: Style.topLinePixelSize
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
isConnected ? UserModel.logout(index) : UserModel.login(index)
|
model.isConnected ? UserModel.logout(index) : UserModel.login(index)
|
||||||
accountMenu.close()
|
accountMenu.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,10 +184,10 @@ MenuItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
Accessible.role: Accessible.Button
|
Accessible.role: Accessible.Button
|
||||||
Accessible.name: isConnected ? qsTr("Log out") : qsTr("Log in")
|
Accessible.name: model.isConnected ? qsTr("Log out") : qsTr("Log in")
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (isConnected) {
|
if (model.isConnected) {
|
||||||
UserModel.logout(index)
|
UserModel.logout(index)
|
||||||
} else {
|
} else {
|
||||||
UserModel.login(index)
|
UserModel.login(index)
|
||||||
|
@ -221,4 +223,13 @@ MenuItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: UserModel
|
||||||
|
onRefreshCurrentUserGui: {
|
||||||
|
accountStateIndicator.source = model.isConnected
|
||||||
|
? Style.stateOnlineImageSource
|
||||||
|
: Style.stateOfflineImageSource
|
||||||
|
}
|
||||||
|
}
|
||||||
} // MenuItem userLine
|
} // MenuItem userLine
|
||||||
|
|
|
@ -41,6 +41,7 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
|
||||||
|
|
||||||
connect(_account.data(), &AccountState::stateChanged,
|
connect(_account.data(), &AccountState::stateChanged,
|
||||||
[=]() { if (isConnected()) {slotRefresh();} });
|
[=]() { if (isConnected()) {slotRefresh();} });
|
||||||
|
connect(_account.data(), &AccountState::stateChanged, this, &User::accountStateChanged);
|
||||||
connect(_account.data(), &AccountState::hasFetchedNavigationApps,
|
connect(_account.data(), &AccountState::hasFetchedNavigationApps,
|
||||||
this, &User::slotRebuildNavigationAppList);
|
this, &User::slotRebuildNavigationAppList);
|
||||||
connect(_account->account().data(), &Account::accountChangedDisplayName, this, &User::nameChanged);
|
connect(_account->account().data(), &Account::accountChangedDisplayName, this, &User::nameChanged);
|
||||||
|
@ -552,6 +553,7 @@ void UserModel::buildUserList()
|
||||||
}
|
}
|
||||||
if (_init) {
|
if (_init) {
|
||||||
_users.first()->setCurrentUser(true);
|
_users.first()->setCurrentUser(true);
|
||||||
|
connect(_users.first(), &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||||
_init = false;
|
_init = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,6 +615,7 @@ void UserModel::addUser(AccountStatePtr &user, const bool &isCurrent)
|
||||||
_users << u;
|
_users << u;
|
||||||
if (isCurrent) {
|
if (isCurrent) {
|
||||||
_currentUserId = _users.indexOf(_users.last());
|
_currentUserId = _users.indexOf(_users.last());
|
||||||
|
connect(u, &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||||
}
|
}
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
@ -665,8 +668,10 @@ Q_INVOKABLE void UserModel::switchCurrentUser(const int &id)
|
||||||
if (_users.isEmpty())
|
if (_users.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
disconnect(_users[_currentUserId], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||||
_users[_currentUserId]->setCurrentUser(false);
|
_users[_currentUserId]->setCurrentUser(false);
|
||||||
_users[id]->setCurrentUser(true);
|
_users[id]->setCurrentUser(true);
|
||||||
|
connect(_users[id], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||||
_currentUserId = id;
|
_currentUserId = id;
|
||||||
emit refreshCurrentUserGui();
|
emit refreshCurrentUserGui();
|
||||||
emit newUserSelected();
|
emit newUserSelected();
|
||||||
|
@ -710,6 +715,10 @@ Q_INVOKABLE void UserModel::removeAccount(const int &id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_users[id]->isCurrentUser()) {
|
||||||
|
disconnect(_users[id], &User::accountStateChanged, this, &UserModel::refreshCurrentUserGui);
|
||||||
|
}
|
||||||
|
|
||||||
if (_users[id]->isCurrentUser() && _users.count() > 1) {
|
if (_users[id]->isCurrentUser() && _users.count() > 1) {
|
||||||
id == 0 ? switchCurrentUser(1) : switchCurrentUser(0);
|
id == 0 ? switchCurrentUser(1) : switchCurrentUser(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ signals:
|
||||||
void hasLocalFolderChanged();
|
void hasLocalFolderChanged();
|
||||||
void serverHasTalkChanged();
|
void serverHasTalkChanged();
|
||||||
void avatarChanged();
|
void avatarChanged();
|
||||||
|
void accountStateChanged(int state);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
|
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
|
||||||
|
|
|
@ -36,7 +36,9 @@ Window {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
currentAccountStateIndicator.source = ""
|
currentAccountStateIndicator.source = ""
|
||||||
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId) ? "qrc:///client/theme/colored/state-ok.svg" : "qrc:///client/theme/colored/state-offline.svg"
|
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||||
|
? Style.stateOnlineImageSource
|
||||||
|
: Style.stateOfflineImageSource
|
||||||
|
|
||||||
// HACK: reload account Instantiator immediately by restting it - could be done better I guess
|
// HACK: reload account Instantiator immediately by restting it - could be done better I guess
|
||||||
// see also id:accountMenu below
|
// see also id:accountMenu below
|
||||||
|
@ -48,7 +50,9 @@ Window {
|
||||||
target: UserModel
|
target: UserModel
|
||||||
onRefreshCurrentUserGui: {
|
onRefreshCurrentUserGui: {
|
||||||
currentAccountStateIndicator.source = ""
|
currentAccountStateIndicator.source = ""
|
||||||
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId) ? "qrc:///client/theme/colored/state-ok.svg" : "qrc:///client/theme/colored/state-offline.svg"
|
currentAccountStateIndicator.source = UserModel.isUserConnected(UserModel.currentUserId)
|
||||||
|
? Style.stateOnlineImageSource
|
||||||
|
: Style.stateOfflineImageSource
|
||||||
}
|
}
|
||||||
onNewUserSelected: {
|
onNewUserSelected: {
|
||||||
accountMenu.close();
|
accountMenu.close();
|
||||||
|
@ -357,7 +361,9 @@ Window {
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: currentAccountStateIndicator
|
id: currentAccountStateIndicator
|
||||||
source: UserModel.isUserConnected(UserModel.currentUserId) ? "qrc:///client/theme/colored/state-ok.svg" : "qrc:///client/theme/colored/state-offline.svg"
|
source: UserModel.isUserConnected(UserModel.currentUserId)
|
||||||
|
? Style.stateOnlineImageSource
|
||||||
|
: Style.stateOfflineImageSource
|
||||||
cache: false
|
cache: false
|
||||||
x: currentAccountStateIndicatorBackground.x + 1
|
x: currentAccountStateIndicatorBackground.x + 1
|
||||||
y: currentAccountStateIndicatorBackground.y + 1
|
y: currentAccountStateIndicatorBackground.y + 1
|
||||||
|
|
|
@ -36,6 +36,22 @@
|
||||||
#undef Mirall
|
#undef Mirall
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QUrl imagePathToUrl(const QString &imagePath)
|
||||||
|
{
|
||||||
|
if (imagePath.startsWith(':')) {
|
||||||
|
auto url = QUrl();
|
||||||
|
url.setScheme(QStringLiteral("qrc"));
|
||||||
|
url.setPath(imagePath.mid(1));
|
||||||
|
return url;
|
||||||
|
} else {
|
||||||
|
return QUrl::fromLocalFile(imagePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
Theme *Theme::_instance = nullptr;
|
Theme *Theme::_instance = nullptr;
|
||||||
|
@ -106,6 +122,16 @@ QString Theme::appName() const
|
||||||
return APPLICATION_SHORTNAME;
|
return APPLICATION_SHORTNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl Theme::stateOnlineImageSource() const
|
||||||
|
{
|
||||||
|
return imagePathToUrl(themeImagePath("state-ok"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl Theme::stateOfflineImageSource() const
|
||||||
|
{
|
||||||
|
return imagePathToUrl(themeImagePath("state-offline", 16));
|
||||||
|
}
|
||||||
|
|
||||||
QString Theme::version() const
|
QString Theme::version() const
|
||||||
{
|
{
|
||||||
return MIRALL_VERSION_STRING;
|
return MIRALL_VERSION_STRING;
|
||||||
|
@ -188,6 +214,25 @@ QIcon Theme::themeIcon(const QString &name, bool sysTray) const
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Theme::themeImagePath(const QString &name, int size, bool sysTray) const
|
||||||
|
{
|
||||||
|
const auto flavor = (!isBranded() && sysTray) ? systrayIconFlavor(_mono) : QLatin1String("colored");
|
||||||
|
|
||||||
|
// branded client may have several sizes of the same icon
|
||||||
|
const QString filePath = (isBranded() && size > 0)
|
||||||
|
? QString::fromLatin1(":/client/theme/%1/%2-%3").arg(flavor).arg(name).arg(size)
|
||||||
|
: QString::fromLatin1(":/client/theme/%1/%2").arg(flavor).arg(name);
|
||||||
|
|
||||||
|
const QString brandedImagePath = filePath + ".png";
|
||||||
|
|
||||||
|
// only return branded .png image path if it exists, or fall-back to non-branded .svg otherwise
|
||||||
|
if (isBranded() && QFile::exists(brandedImagePath)) {
|
||||||
|
return brandedImagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath + ".svg";
|
||||||
|
}
|
||||||
|
|
||||||
QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
|
QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
|
||||||
{
|
{
|
||||||
QString themeResBasePath = ":/client/theme/";
|
QString themeResBasePath = ":/client/theme/";
|
||||||
|
|
|
@ -40,6 +40,8 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
|
||||||
Q_PROPERTY(bool branded READ isBranded CONSTANT)
|
Q_PROPERTY(bool branded READ isBranded CONSTANT)
|
||||||
Q_PROPERTY(QString appNameGUI READ appNameGUI CONSTANT)
|
Q_PROPERTY(QString appNameGUI READ appNameGUI CONSTANT)
|
||||||
Q_PROPERTY(QString appName READ appName CONSTANT)
|
Q_PROPERTY(QString appName READ appName CONSTANT)
|
||||||
|
Q_PROPERTY(QUrl stateOnlineImageSource READ stateOnlineImageSource CONSTANT)
|
||||||
|
Q_PROPERTY(QUrl stateOfflineImageSource READ stateOfflineImageSource CONSTANT)
|
||||||
#ifndef TOKEN_AUTH_ONLY
|
#ifndef TOKEN_AUTH_ONLY
|
||||||
Q_PROPERTY(QIcon folderDisabledIcon READ folderDisabledIcon CONSTANT)
|
Q_PROPERTY(QIcon folderDisabledIcon READ folderDisabledIcon CONSTANT)
|
||||||
Q_PROPERTY(QIcon folderOfflineIcon READ folderOfflineIcon CONSTANT)
|
Q_PROPERTY(QIcon folderOfflineIcon READ folderOfflineIcon CONSTANT)
|
||||||
|
@ -109,6 +111,18 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual QString appName() const;
|
virtual QString appName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns full path to an online state icon
|
||||||
|
* @return QUrl full path to an icon
|
||||||
|
*/
|
||||||
|
QUrl stateOnlineImageSource() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns full path to an offline state icon
|
||||||
|
* @return QUrl full path to an icon
|
||||||
|
*/
|
||||||
|
QUrl stateOfflineImageSource() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief configFileName
|
* @brief configFileName
|
||||||
* @return the name of the config file.
|
* @return the name of the config file.
|
||||||
|
@ -491,6 +505,14 @@ protected:
|
||||||
#ifndef TOKEN_AUTH_ONLY
|
#ifndef TOKEN_AUTH_ONLY
|
||||||
QIcon themeIcon(const QString &name, bool sysTray = false) const;
|
QIcon themeIcon(const QString &name, bool sysTray = false) const;
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Generates image path in the resources
|
||||||
|
* @param name Name of the image file
|
||||||
|
* @param size Size in the power of two (16, 32, 64, etc.)
|
||||||
|
* @param sysTray Whether the image requested is for Systray or not
|
||||||
|
* @return QString image path in the resources
|
||||||
|
**/
|
||||||
|
QString themeImagePath(const QString &name, int size = -1, bool sysTray = false) const;
|
||||||
Theme();
|
Theme();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -28,6 +28,9 @@ QtObject {
|
||||||
property int currentAccountButtonRadius: 2
|
property int currentAccountButtonRadius: 2
|
||||||
property int currentAccountLabelWidth: 128
|
property int currentAccountLabelWidth: 128
|
||||||
|
|
||||||
|
property url stateOnlineImageSource: Theme.stateOnlineImageSource
|
||||||
|
property url stateOfflineImageSource: Theme.stateOfflineImageSource
|
||||||
|
|
||||||
property int accountAvatarSize: (trayWindowHeaderHeight - 16)
|
property int accountAvatarSize: (trayWindowHeaderHeight - 16)
|
||||||
property int accountAvatarStateIndicatorSize: 16
|
property int accountAvatarStateIndicatorSize: 16
|
||||||
property int accountLabelWidth: 128
|
property int accountLabelWidth: 128
|
||||||
|
|
Loading…
Reference in a new issue