Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ set(client_SRCS
activity/activitylistmodel.cpp
tray/asyncimageresponse.cpp
tray/trayimageprovider.cpp
tray/trayaccountmenupolicy.h
tray/trayaccountappsmodel.h
tray/trayaccountappsmodel.cpp
tray/usermodel.h
Expand Down
9 changes: 5 additions & 4 deletions src/gui/macOS/trayaccountpopup/ncaccountactionspopup.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#pragma once

#import <Cocoa/Cocoa.h>

Check failure on line 8 in src/gui/macOS/trayaccountpopup/ncaccountactionspopup.h

View workflow job for this annotation

GitHub Actions / build

src/gui/macOS/trayaccountpopup/ncaccountactionspopup.h:8:9 [clang-diagnostic-error]

'Cocoa/Cocoa.h' file not found

#include <QVariantList>

Expand All @@ -14,9 +14,10 @@
/**
* @brief The submenu shown for a single account.
*
* Lists the user status, "Reveal in Finder", the Assistant, Search and Apps
* shortcuts, pending notifications and recent activity. Owns the apps and
* notification-actions sub-popups.
* Lists only "Reveal in Finder" and, where supported, the sign-in action while
* disconnected. Connected accounts also show user status, Assistant, Search
* and Apps shortcuts, pending notifications and recent activity. Owns the apps
* and notification-actions sub-popups.
*/
@interface NCAccountActionsPopup : NSPanel
/** @brief Rebuilds the popup for the given account and refreshes its activity preview. */
Expand All @@ -28,7 +29,7 @@
*/
- (void)populateForUserIndex:(int)userIndex owner:(NCTrayPopup *)owner refreshActivities:(BOOL)refreshActivities;
/** @brief Whether the popup is currently visible and showing the given account. */
- (BOOL)isShowingActivitiesForUserIndex:(int)userIndex;
- (BOOL)isShowingUserIndex:(int)userIndex;

Check warning on line 32 in src/gui/macOS/trayaccountpopup/ncaccountactionspopup.h

View workflow job for this annotation

GitHub Actions / build

src/gui/macOS/trayaccountpopup/ncaccountactionspopup.h:32:4 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'BOOL' is non-const and globally accessible, consider making it const
/** @brief Removes the persistent highlight from the row whose submenu is currently open. */
- (void)clearActiveSubmenuRow;
/** @brief Hides the apps and notification-actions sub-popups and clears the active submenu row. */
Expand Down
119 changes: 83 additions & 36 deletions src/gui/macOS/trayaccountpopup/ncaccountactionspopup.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "systray.h"
#include "tray/trayaccountappsmodel.h"
#include "tray/trayaccountmenupolicy.h"
#include "tray/usermodel.h"

#include <QCoreApplication>
Expand Down Expand Up @@ -89,7 +90,7 @@ @implementation NCAccountActionsPopup {
NCNotificationActionsPopup *_notificationActionsPopup;
NCActionRow *_activeSubmenuRow; //!< The row whose sub-popup is currently shown, kept persistently highlighted.
__unsafe_unretained NCTrayPopup *_owner;
QMetaObject::Connection _recentActivitiesConnection; //!< Rebuilds the popup in place when the model reports new activity or notifications.
QMetaObject::Connection _accountMenuDataConnection; //!< Rebuilds the popup when visible menu data or connectivity changes.
int _userIndex;
}

Expand All @@ -112,13 +113,13 @@ - (void)dealloc
{
[_appsPopup release];
[_notificationActionsPopup release];
if (_recentActivitiesConnection) {
QObject::disconnect(_recentActivitiesConnection);
if (_accountMenuDataConnection) {
QObject::disconnect(_accountMenuDataConnection);
}
[super dealloc];
}

- (BOOL)isShowingActivitiesForUserIndex:(int)userIndex
- (BOOL)isShowingUserIndex:(int)userIndex
{
return [self isVisible] && _userIndex == userIndex;
}
Expand All @@ -128,9 +129,9 @@ - (void)orderOut:(id)sender
[_appsPopup orderOut:nil];
[_notificationActionsPopup orderOut:nil];
[self clearActiveSubmenuRow];
if (_recentActivitiesConnection) {
QObject::disconnect(_recentActivitiesConnection);
_recentActivitiesConnection = {};
if (_accountMenuDataConnection) {
QObject::disconnect(_accountMenuDataConnection);
_accountMenuDataConnection = {};
}
_userIndex = -1;
[super orderOut:sender];
Expand Down Expand Up @@ -190,56 +191,117 @@ - (void)populateForUserIndex:(int)userIndex owner:(NCTrayPopup *)owner
[self populateForUserIndex:userIndex owner:owner refreshActivities:YES];
}

/**
* @brief Resizes the popup to its current rows while optionally retaining its top edge.
* @param preserveTopEdge Whether a visible popup should grow downwards.
* @param topEdge The previous top edge to retain when @p preserveTopEdge is YES.
*/
- (void)resizeToFitPreservingTopEdge:(BOOL)preserveTopEdge topEdge:(CGFloat)topEdge
{
[self.contentView layoutSubtreeIfNeeded];
NSRect frame = self.frame;
frame.size.width = kAccountActionsPopupWidth;
frame.size.height = _stack.fittingSize.height;
if (preserveTopEdge) {
frame.origin.y = topEdge - frame.size.height;
}
auto screen = self.screen;
if (!screen) {
screen = NSScreen.mainScreen ?: NSScreen.screens.firstObject;
}
if (screen) {
frame.origin = clampedPopupOrigin(frame.origin, frame.size, screen.visibleFrame);
}
[self setFrame:frame display:NO];
[self invalidateShadow];
}

- (void)populateForUserIndex:(int)userIndex owner:(NCTrayPopup *)owner refreshActivities:(BOOL)refreshActivities
{
const auto preserveTopEdge = [self isVisible];
const auto topEdge = NSMaxY(self.frame);

_owner = owner;
_userIndex = userIndex;
[_appsPopup orderOut:nil];
[self clearActiveSubmenuRow];
[self hideAppsPopup];

clearStack(_stack);

auto model = OCC::UserModel::instance();
if (_recentActivitiesConnection) {
QObject::disconnect(_recentActivitiesConnection);
_recentActivitiesConnection = {};
if (_accountMenuDataConnection) {
QObject::disconnect(_accountMenuDataConnection);
_accountMenuDataConnection = {};
}
if (!model || userIndex < 0 || userIndex >= model->rowCount()) {
return;
}

__unsafe_unretained NCTrayPopup *weakOwner = owner;
__unsafe_unretained NCAccountActionsPopup *weakSelf = self;
_recentActivitiesConnection = QObject::connect(model, &QAbstractItemModel::dataChanged, model,
_accountMenuDataConnection = QObject::connect(model, &QAbstractItemModel::dataChanged, model,
[weakSelf, weakOwner, userIndex](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
if (!weakSelf || ![weakSelf isShowingActivitiesForUserIndex:userIndex]) {
if (!weakSelf || ![weakSelf isShowingUserIndex:userIndex]) {
return;
}
if (userIndex < topLeft.row() || userIndex > bottomRight.row()) {
return;
}
if (!roles.isEmpty()
&& !roles.contains(OCC::UserModel::RecentActivitiesRole)
&& !roles.contains(OCC::UserModel::TrayNotificationsRole)) {
&& !roles.contains(OCC::UserModel::TrayNotificationsRole)
&& !roles.contains(OCC::UserModel::IsConnectedRole)) {
return;
}

[weakSelf populateForUserIndex:userIndex owner:weakOwner refreshActivities:NO];
});

const auto userModelIndex = model->index(userIndex);
const auto policy = OCC::TrayAccountMenuPolicy{
model->data(userModelIndex, OCC::UserModel::IsConnectedRole).toBool(),
model->data(userModelIndex, OCC::UserModel::CanLogoutRole).toBool(),
};
if (!policy.showConnectedSections()) {
addOwnedArrangedSubview(_stack, [[NCSpacerView alloc] initWithHeight:kActionVerticalPadding width:kAccountActionsPopupWidth]);
for (const auto entry : policy.disconnectedEntries()) {
switch (entry) {
case OCC::TrayAccountMenuPolicy::Entry::LocalFolder:
addOwnedArrangedSubview(_stack, [[NCActionRow alloc] initWithTitle:QCoreApplication::translate("TrayFoldersMenuButton", "Reveal in Finder").toNSString()
width:kAccountActionsPopupWidth
enabled:YES
action:^{
[weakOwner openLocalFolderForIndex:userIndex];
} hoverAction:^(NSView *) {
[weakSelf hideAppsPopup];
}]);
break;
case OCC::TrayAccountMenuPolicy::Entry::Separator:
[_stack addArrangedSubview:accountActionsSeparator()];
break;
case OCC::TrayAccountMenuPolicy::Entry::Reconnect:
addOwnedArrangedSubview(_stack, [[NCActionRow alloc] initWithTitle:QCoreApplication::translate("OCC::AccountSettings", "Log in").toNSString()
width:kAccountActionsPopupWidth
enabled:YES
action:^{
[weakOwner reconnectForIndex:userIndex];
} hoverAction:^(NSView *) {
[weakSelf hideAppsPopup];
}]);
break;
}
}
addOwnedArrangedSubview(_stack, [[NCSpacerView alloc] initWithHeight:kActionVerticalPadding width:kAccountActionsPopupWidth]);
[self resizeToFitPreservingTopEdge:preserveTopEdge topEdge:topEdge];
return;
}
Comment thread
claucambra marked this conversation as resolved.

const auto serverHasUserStatus = model->data(userModelIndex, OCC::UserModel::ServerHasUserStatusRole).toBool();
const auto onlineStatusEnabled = model->data(userModelIndex, OCC::UserModel::IsConnectedRole).toBool()
&& serverHasUserStatus;
const auto onlineStatusEnabled = policy.showConnectedSections() && serverHasUserStatus;

auto appsModel = OCC::TrayAccountAppsModel::instance();
appsModel->setUserId(userIndex);
const auto appsEnabled = appsModel->rowCount() > 0;
const auto assistantEnabled = model->data(userModelIndex, OCC::UserModel::AssistantEnabledRole).toBool();
const auto searchEnabled = model->data(userModelIndex, OCC::UserModel::IsConnectedRole).toBool();
addOwnedArrangedSubview(_stack, [[NCSpacerView alloc] initWithHeight:kActionVerticalPadding width:kAccountActionsPopupWidth]);
if (serverHasUserStatus) {
const auto status = model->data(userModelIndex, OCC::UserModel::StatusRole).value<OCC::UserStatus::OnlineStatus>();
Expand Down Expand Up @@ -278,7 +340,7 @@ - (void)populateForUserIndex:(int)userIndex owner:(NCTrayPopup *)owner refreshAc
}
addOwnedArrangedSubview(_stack, [[NCActionRow alloc] initWithTitle:QCoreApplication::translate("TrayAccountPopup", "Search").toNSString()
width:kAccountActionsPopupWidth
enabled:searchEnabled
enabled:YES
action:^{
[weakOwner openSearchForIndex:userIndex];
} hoverAction:^(NSView *) {
Expand Down Expand Up @@ -370,24 +432,9 @@ - (void)populateForUserIndex:(int)userIndex owner:(NCTrayPopup *)owner refreshAc

addOwnedArrangedSubview(_stack, [[NCSpacerView alloc] initWithHeight:kActionVerticalPadding width:kAccountActionsPopupWidth]);

[self.contentView layoutSubtreeIfNeeded];
NSRect frame = self.frame;
frame.size.width = kAccountActionsPopupWidth;
frame.size.height = _stack.fittingSize.height;
if (preserveTopEdge) {
frame.origin.y = topEdge - frame.size.height;
}
auto screen = self.screen;
if (!screen) {
screen = NSScreen.mainScreen ?: NSScreen.screens.firstObject;
}
if (screen) {
frame.origin = clampedPopupOrigin(frame.origin, frame.size, screen.visibleFrame);
}
[self setFrame:frame display:NO];
[self invalidateShadow];
[self resizeToFitPreservingTopEdge:preserveTopEdge topEdge:topEdge];

if (refreshActivities) {
if (refreshActivities && policy.fetchActivityPreview()) {
model->fetchActivityPreview(userIndex);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/gui/macOS/trayaccountpopup/nctraypopup.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#pragma once

#import <Cocoa/Cocoa.h>

Check failure on line 8 in src/gui/macOS/trayaccountpopup/nctraypopup.h

View workflow job for this annotation

GitHub Actions / build

src/gui/macOS/trayaccountpopup/nctraypopup.h:8:9 [clang-diagnostic-error]

'Cocoa/Cocoa.h' file not found

#import "ncaccountrow.h"

Expand All @@ -29,6 +29,8 @@
- (void)openActivitiesForIndex:(int)index;
/** @brief Closes the popups and reveals the given account's local folder (or file provider domain) in Finder. */
- (void)openLocalFolderForIndex:(int)index;
/** @brief Closes the popups and starts the sign-in flow for the given account. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Document both reconnect paths

For disconnected but not signed-out accounts, such as network, maintenance, or configuration failures, reconnectForIndex: ultimately calls User::login(), which selects RetryConnection and invokes freshConnectionAttempt() rather than starting a sign-in flow. Update this declaration and the matching NCAccountActionsPopup type comment to describe both possible outcomes; the current API documentation contradicts the implementation.

AGENTS.md reference: AGENTS.md:L83-L87

Useful? React with 👍 / 👎.

- (void)reconnectForIndex:(int)index;
/** @brief Closes the popups and opens the Assistant window for the given account. */
- (void)openAssistantForIndex:(int)index;
/** @brief Closes the popups and opens the Search window for the given account. */
Expand Down
9 changes: 9 additions & 0 deletions src/gui/macOS/trayaccountpopup/nctraypopup.mm
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ - (void)openLocalFolderForIndex:(int)index
#endif
}

- (void)reconnectForIndex:(int)index
{
[self closeAllPopups];

if (auto userModel = OCC::UserModel::instance()) {
userModel->login(index);
}
}

- (void)openAssistantForIndex:(int)index
{
[_accountActionsPopup orderOut:nil];
Expand Down
95 changes: 95 additions & 0 deletions src/gui/tray/trayaccountmenupolicy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#pragma once

#include <array>

Check failure on line 8 in src/gui/tray/trayaccountmenupolicy.h

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/trayaccountmenupolicy.h:8:10 [clang-diagnostic-error]

'array' file not found
#include <span>

namespace OCC {

Check warning on line 11 in src/gui/tray/trayaccountmenupolicy.h

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/trayaccountmenupolicy.h:11:11 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'OCC' is non-const and globally accessible, consider making it const

/**
* @brief Defines which account-menu content is relevant for the connection state.
*/
class TrayAccountMenuPolicy
{
public:
/** @brief Semantic entries used by the disconnected account menu. */
enum class Entry {
LocalFolder,
Separator,
Reconnect,
};

/** @brief Account operation selected for the reconnect action. */
enum class ReconnectMode {
None,
SignIn,
RetryConnection,
};

/**
* @brief Creates the menu policy for an account.
* @param canReconnect Whether the account supports signing in, which excludes public shares.
*/
explicit constexpr TrayAccountMenuPolicy(const bool isConnected, const bool canReconnect)
: _isConnected(isConnected)
, _canReconnect(canReconnect)
{
}

/** @brief Whether server-backed account sections should be shown. */

Check warning on line 43 in src/gui/tray/trayaccountmenupolicy.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Edit this comment to use the C++ format, i.e. "//".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6VswtrUo18Gaw3Wi&open=AZ-o6VswtrUo18Gaw3Wi&pullRequest=10461
[[nodiscard]] constexpr bool showConnectedSections() const
{
return _isConnected;
}

/** @brief Ordered entries to show instead of server-backed sections. */

Check warning on line 49 in src/gui/tray/trayaccountmenupolicy.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Edit this comment to use the C++ format, i.e. "//".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6VswtrUo18Gaw3Wj&open=AZ-o6VswtrUo18Gaw3Wj&pullRequest=10461
[[nodiscard]] constexpr std::span<const Entry> disconnectedEntries() const
{
if (_isConnected) {
return {};
}
if (_canReconnect) {
return disconnectedReconnectEntries;
}
return disconnectedEntriesWithoutReconnect;
}

/** @brief Whether opening the menu should request fresh server-backed previews. */
[[nodiscard]] constexpr bool fetchActivityPreview() const
{
return _isConnected;
}

/** @brief Selects the account operation behind the reconnect menu action. */
[[nodiscard]] static constexpr ReconnectMode reconnectMode(
const bool isConnected,
const bool isSignedOut,
const bool canReconnect)
{
if (isConnected || !canReconnect) {
return ReconnectMode::None;
}
return isSignedOut
? ReconnectMode::SignIn
: ReconnectMode::RetryConnection;
}

private:
static constexpr std::array disconnectedReconnectEntries{
Entry::LocalFolder,
Entry::Separator,
Entry::Reconnect,
};
static constexpr std::array disconnectedEntriesWithoutReconnect{
Entry::LocalFolder,
};

bool _isConnected;
bool _canReconnect;
};

}
18 changes: 16 additions & 2 deletions src/gui/tray/usermodel.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/*
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/

Check warning on line 4 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Edit this comment to use the C++ format, i.e. "//".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Ww&open=AZ-o6V63trUo18Gaw3Ww&pullRequest=10461

#include "activity/notificationhandler.h"

Check failure on line 6 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:6:10 [clang-diagnostic-error]

'activity/notificationhandler.h' file not found
#include "trayaccountmenupolicy.h"
#include "usermodel.h"
#include "common/filesystembase.h"

Expand Down Expand Up @@ -118,7 +119,7 @@
if (nestedOutput.isObject()) {
const auto nestedObject = nestedOutput.toObject();
const auto textValue = nestedObject.value("text"_L1);
if (textValue.isString()) {

Check warning on line 122 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the init-statement to declare "textValue" inside the if statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3W6&open=AZ-o6V63trUo18Gaw3W6&pullRequest=10461
return textValue.toString();
}
const auto answerValue = nestedObject.value("answer"_L1);
Expand All @@ -128,7 +129,7 @@
}

const auto textValue = outputObject.value("text"_L1);
if (textValue.isString()) {

Check warning on line 132 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the init-statement to declare "textValue" inside the if statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3W5&open=AZ-o6V63trUo18Gaw3W5&pullRequest=10461
return textValue.toString();
}
const auto answerValue = outputObject.value("answer"_L1);
Expand Down Expand Up @@ -309,7 +310,7 @@
{
auto result = SyncIssueKind::None;

switch (status) {

Check failure on line 313 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a "default" case to this switch statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3W-&open=AZ-o6V63trUo18Gaw3W-&pullRequest=10461
case OCC::SyncFileItem::NormalError:
case OCC::SyncFileItem::FatalError:
case OCC::SyncFileItem::DetailError:
Expand Down Expand Up @@ -390,7 +391,7 @@
}

const auto &allFolders = OCC::FolderMan::instance()->map().values();
for (const auto folder : allFolders) {

Check warning on line 394 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this range for-loop by "std::ranges::any_of".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XA&open=AZ-o6V63trUo18Gaw3XA&pullRequest=10461
if (folder->accountState() != accountState.data()) {
continue;
}
Expand Down Expand Up @@ -477,7 +478,7 @@
activity._talkNotificationData.conversationToken = QStringLiteral("debug-call");

const auto avatarUrl = qEnvironmentVariable(debugCallNotificationAvatarEnvVar);
if (!avatarUrl.isEmpty()) {

Check warning on line 481 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the init-statement to declare "avatarUrl" inside the if statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XB&open=AZ-o6V63trUo18Gaw3XB&pullRequest=10461
activity._talkNotificationData.userAvatar = avatarUrl;
} else if (!account->account()->url().isEmpty() && !account->account()->davUser().isEmpty()) {
activity._talkNotificationData.userAvatar = account->account()->url().toString()
Expand Down Expand Up @@ -727,7 +728,7 @@

_activityModel->removeOutdatedNotifications(list);

std::copy_if(list.constBegin(), list.constEnd(), std::back_inserter(toNotifyList), [&](const Activity &activity) -> bool {

Check warning on line 731 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the redundant return type of this lambda.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XE&open=AZ-o6V63trUo18Gaw3XE&pullRequest=10461
if (!activity._shouldNotify) {
qCDebug(lcActivity).nospace() << "No notification should be sent for activity with id=" << activity._id << " objectType=" << activity._objectType;
return false;
Expand Down Expand Up @@ -825,7 +826,7 @@
setNotificationRefreshInterval(ConfigFile().notificationRefreshInterval());
}

void User::slotReceivedPushFilesChanges(Account *account)

Check warning on line 829 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the type of this parameter a pointer-to-const. The current type of "account" is "class OCC::Account *".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XF&open=AZ-o6V63trUo18Gaw3XF&pullRequest=10461
{
if (account->id() != _account->account()->id()) {
return;
Expand All @@ -843,7 +844,7 @@
#endif
}

void User::slotReceivedPushFileIdsChanges(Account *account, const QList<qint64> &fileIds)

Check warning on line 847 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the type of this parameter a pointer-to-const. The current type of "account" is "class OCC::Account *".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XH&open=AZ-o6V63trUo18Gaw3XH&pullRequest=10461
{
if (account->id() != _account->account()->id()) {
return;
Expand Down Expand Up @@ -1805,8 +1806,21 @@

void User::login() const
{
_account->account()->resetRejectedCertificates();
_account->signIn();
switch (TrayAccountMenuPolicy::reconnectMode(

Check failure on line 1809 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a "default" case to this switch statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XM&open=AZ-o6V63trUo18Gaw3XM&pullRequest=10461
_account->isConnected(),
_account->isSignedOut(),
!isPublicShareLink())) {
case TrayAccountMenuPolicy::ReconnectMode::None:
return;
case TrayAccountMenuPolicy::ReconnectMode::SignIn:
_account->account()->resetRejectedCertificates();
_account->signIn();
break;
case TrayAccountMenuPolicy::ReconnectMode::RetryConnection:
_account->account()->resetRejectedCertificates();
_account->freshConnectionAttempt();
break;
}
}

void User::logout() const
Expand Down Expand Up @@ -2153,7 +2167,7 @@
_assistantConnector->fetchTasks(_assistantTaskType);
}

void User::slotAssistantTaskTypesFetched(const QJsonDocument &json, int statusCode)

Check warning on line 2170 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "statusCode" of type "int" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XO&open=AZ-o6V63trUo18Gaw3XO&pullRequest=10461
{
if (statusCode < assistantSuccessMinStatusCode || statusCode >= assistantSuccessMaxStatusCode) {
slotAssistantRequestError(QStringLiteral("taskTypes"), statusCode);
Expand Down Expand Up @@ -2188,7 +2202,7 @@
_assistantConnector->scheduleTask(_assistantQuestion, _assistantTaskType, history);
}

void User::slotAssistantTasksFetched(const QJsonDocument &json, int statusCode)

Check warning on line 2205 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "statusCode" of type "int" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XP&open=AZ-o6V63trUo18Gaw3XP&pullRequest=10461
{
if (statusCode < assistantSuccessMinStatusCode || statusCode >= assistantSuccessMaxStatusCode) {
slotAssistantRequestError(QStringLiteral("tasks"), statusCode);
Expand Down Expand Up @@ -2236,7 +2250,7 @@
}
}

void User::slotAssistantTaskScheduled(const QJsonDocument &json, int statusCode)

Check warning on line 2253 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "statusCode" of type "int" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XQ&open=AZ-o6V63trUo18Gaw3XQ&pullRequest=10461
{
if (statusCode < assistantSuccessMinStatusCode || statusCode >= assistantSuccessMaxStatusCode) {
slotAssistantRequestError(QStringLiteral("schedule"), statusCode);
Expand All @@ -2261,7 +2275,7 @@
slotAssistantRequestError(QStringLiteral("deleteTask"), statusCode);
}

void User::slotAssistantRequestError(const QString &context, int statusCode)

Check warning on line 2278 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "statusCode" of type "int" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XS&open=AZ-o6V63trUo18Gaw3XS&pullRequest=10461
{
_assistantPollTimer.stop();
_assistantRequestInProgress = false;
Expand Down Expand Up @@ -2334,7 +2348,7 @@
return;
}

int64_t total = usedBytes + availableBytes;

Check warning on line 2351 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "total" of type "long" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XT&open=AZ-o6V63trUo18Gaw3XT&pullRequest=10461
if (total <= 0 || !ConfigFile().showQuotaWarningNotifications()) {
return;
}
Expand Down Expand Up @@ -2494,7 +2508,7 @@
buildUserList();

if(!_users.isEmpty()) {
ConfigFile cfg;

Check warning on line 2511 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "cfg" of type "class OCC::ConfigFile" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XW&open=AZ-o6V63trUo18Gaw3XW&pullRequest=10461
const uint lastSelectedAccountId = cfg.lastSelectedAccount();

for (int i = 0; i < _users.size(); i++) {
Expand All @@ -2513,7 +2527,7 @@

int UserModel::numUsers()
{
return _users.size();

Check warning on line 2530 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Wy&open=AZ-o6V63trUo18Gaw3Wy&pullRequest=10461
}

int UserModel::count() const
Expand Down Expand Up @@ -2561,9 +2575,9 @@

QImage UserModel::avatarById(const int id) const
{
const auto foundUserByIdIter = std::find_if(std::cbegin(_users), std::cend(_users), [&id](const OCC::User* const user) {
return user->account()->id() == QString::number(id);
});

Check warning on line 2580 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace with the version of "std::ranges::find_if" that takes a range.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XX&open=AZ-o6V63trUo18Gaw3XX&pullRequest=10461

if (foundUserByIdIter == std::cend(_users)) {
return {};
Expand Down Expand Up @@ -2666,7 +2680,7 @@
emit countChanged();

if (selectAddedUser) {
setCurrentUserId(_users.size() - 1);

Check warning on line 2683 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3W0&open=AZ-o6V63trUo18Gaw3W0&pullRequest=10461
} else {
emit currentUserChanged();
}
Expand Down Expand Up @@ -2718,7 +2732,7 @@
_users[_currentUserId]->openFolderLocallyOrInBrowser(fullRemotePath);
}

void UserModel::openCurrentAccountFeaturedApp()

Check warning on line 2735 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function should be declared "const".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3XY&open=AZ-o6V63trUo18Gaw3XY&pullRequest=10461
{
if (!currentUser()) {
return;
Expand Down Expand Up @@ -2814,7 +2828,7 @@
emit countChanged();

if (_users.size() <= 1) {
setCurrentUserId(_users.size() - 1);

Check warning on line 2831 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3W1&open=AZ-o6V63trUo18Gaw3W1&pullRequest=10461
} else if (currentUserId() > id) {
// an account was removed from the in-between 0 and the current one, the index of the current one needs a decrement
setCurrentUserId(currentUserId() - 1);
Expand Down Expand Up @@ -3008,9 +3022,9 @@
{
Q_ASSERT(account);

const auto it = std::find_if(_users.cbegin(), _users.cend(), [account](const User *user) {
return user->account()->id() == account->account()->id();
});

Check warning on line 3027 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace with the version of "std::ranges::find_if" that takes a range.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xa&open=AZ-o6V63trUo18Gaw3Xa&pullRequest=10461

if (it == _users.cend()) {
return nullptr;
Expand All @@ -3021,9 +3035,9 @@

int UserModel::findUserIdForAccount(AccountState *account) const
{
const auto it = std::find_if(std::cbegin(_users), std::cend(_users), [=](const User *user) {
return user->account()->id() == account->account()->id();
});

Check warning on line 3040 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace with the version of "std::ranges::find_if" that takes a range.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xb&open=AZ-o6V63trUo18Gaw3Xb&pullRequest=10461

if (it == std::cend(_users)) {
return -1;
Expand Down Expand Up @@ -3064,7 +3078,7 @@
class ImageResponse : public QQuickImageResponse
{
public:
ImageResponse(const QString &id, const QSize &requestedSize, QThreadPool *pool)

Check warning on line 3081 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the type of this parameter a pointer-to-const. The current type of "pool" is "class QThreadPool *".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xd&open=AZ-o6V63trUo18Gaw3Xd&pullRequest=10461

Check warning on line 3081 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "pool" of type "class QThreadPool *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xe&open=AZ-o6V63trUo18Gaw3Xe&pullRequest=10461
{
Q_UNUSED(pool)

Expand All @@ -3089,8 +3103,8 @@
// Format is "image://avatars/user-id=avatar-requested-user/local-user-id:0"
const auto userIdsString = id.split('=');
const auto userIds = userIdsString.last().split("/local-account:");
const auto avatarUserId = userIds.first();

Check warning on line 3106 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Avoid this unnecessary copy by using a "const" reference.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xf&open=AZ-o6V63trUo18Gaw3Xf&pullRequest=10461
const auto accountString = userIds.last();

Check warning on line 3107 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Avoid this unnecessary copy by using a "const" reference.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xg&open=AZ-o6V63trUo18Gaw3Xg&pullRequest=10461
const auto accountState = AccountManager::instance()->account(accountString);
Q_ASSERT(accountState);
Q_ASSERT(accountState->account());
Expand All @@ -3104,8 +3118,8 @@

QMetaObject::invokeMethod(qnam, [this, requestedSize, avatarUserId, account]() {
const auto avatarSize = requestedSize.width() > 0 ? requestedSize.width() : 64;
const auto avatarJob = new AvatarJob(account, avatarUserId, avatarSize);

Check failure on line 3121 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the use of "new" with an operation that automatically manages the memory.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xh&open=AZ-o6V63trUo18Gaw3Xh&pullRequest=10461
connect(avatarJob, &AvatarJob::avatarPixmap, this, [&](const QImage &avatarImg) {

Check failure on line 3122 in src/gui/tray/usermodel.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Explicitly capture the required scope variables.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ-o6V63trUo18Gaw3Xi&open=AZ-o6V63trUo18Gaw3Xi&pullRequest=10461
QMetaObject::invokeMethod(this, [this, avatarImg] {
handleDone(AvatarJob::makeCircularAvatar(avatarImg));
});
Expand Down
Loading
Loading