mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-22 21:15:55 +03:00
Merge pull request #3935 from nextcloud/feature/profile-page
Add profile page
This commit is contained in:
commit
48a8085453
12 changed files with 885 additions and 32 deletions
|
@ -98,6 +98,7 @@ set(client_SRCS
|
|||
sharelinkwidget.cpp
|
||||
sharemanager.cpp
|
||||
shareusergroupwidget.cpp
|
||||
profilepagewidget.cpp
|
||||
sharee.cpp
|
||||
sslbutton.cpp
|
||||
sslerrordialog.cpp
|
||||
|
@ -115,7 +116,6 @@ set(client_SRCS
|
|||
guiutility.cpp
|
||||
elidedlabel.cpp
|
||||
headerbanner.cpp
|
||||
iconjob.cpp
|
||||
iconutils.cpp
|
||||
remotewipe.cpp
|
||||
userstatusselectormodel.cpp
|
||||
|
|
46
src/gui/profilepagewidget.cpp
Normal file
46
src/gui/profilepagewidget.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "profilepagewidget.h"
|
||||
#include "guiutility.h"
|
||||
#include "ocsprofileconnector.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
ProfilePageMenu::ProfilePageMenu(AccountPtr account, const QString &shareWithUserId, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, _profileConnector(account)
|
||||
{
|
||||
connect(&_profileConnector, &OcsProfileConnector::hovercardFetched, this, &ProfilePageMenu::onHovercardFetched);
|
||||
connect(&_profileConnector, &OcsProfileConnector::iconLoaded, this, &ProfilePageMenu::onIconLoaded);
|
||||
_profileConnector.fetchHovercard(shareWithUserId);
|
||||
}
|
||||
|
||||
ProfilePageMenu::~ProfilePageMenu() = default;
|
||||
|
||||
void ProfilePageMenu::exec(const QPoint &globalPosition)
|
||||
{
|
||||
_menu.exec(globalPosition);
|
||||
}
|
||||
|
||||
void ProfilePageMenu::onHovercardFetched()
|
||||
{
|
||||
_menu.clear();
|
||||
|
||||
const auto hovercardActions = _profileConnector.hovercard()._actions;
|
||||
for (const auto &hovercardAction : hovercardActions) {
|
||||
const auto action = _menu.addAction(hovercardAction._icon, hovercardAction._title);
|
||||
const auto link = hovercardAction._link;
|
||||
connect(action, &QAction::triggered, action, [link](bool) { Utility::openBrowser(link); });
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilePageMenu::onIconLoaded(const std::size_t &hovercardActionIndex)
|
||||
{
|
||||
const auto hovercardActions = _profileConnector.hovercard()._actions;
|
||||
const auto menuActions = _menu.actions();
|
||||
if (hovercardActionIndex >= hovercardActions.size()
|
||||
|| hovercardActionIndex >= static_cast<std::size_t>(menuActions.size())) {
|
||||
return;
|
||||
}
|
||||
const auto menuAction = menuActions[static_cast<int>(hovercardActionIndex)];
|
||||
menuAction->setIcon(hovercardActions[hovercardActionIndex]._icon);
|
||||
}
|
||||
}
|
30
src/gui/profilepagewidget.h
Normal file
30
src/gui/profilepagewidget.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "ocsprofileconnector.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <account.h>
|
||||
#include <QMenu>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class ProfilePageMenu : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProfilePageMenu(AccountPtr account, const QString &shareWithUserId, QWidget *parent = nullptr);
|
||||
~ProfilePageMenu() override;
|
||||
|
||||
void exec(const QPoint &globalPosition);
|
||||
|
||||
private:
|
||||
void onHovercardFetched();
|
||||
void onIconLoaded(const std::size_t &hovercardActionIndex);
|
||||
|
||||
OcsProfileConnector _profileConnector;
|
||||
QMenu _menu;
|
||||
};
|
||||
}
|
|
@ -12,7 +12,9 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
#include "ocsprofileconnector.h"
|
||||
#include "sharee.h"
|
||||
#include "tray/usermodel.h"
|
||||
#include "ui_shareusergroupwidget.h"
|
||||
#include "ui_shareuserline.h"
|
||||
#include "shareusergroupwidget.h"
|
||||
|
@ -36,7 +38,9 @@
|
|||
#include <QFileInfo>
|
||||
#include <QAbstractProxyModel>
|
||||
#include <QCompleter>
|
||||
#include <qlayout.h>
|
||||
#include <QBoxLayout>
|
||||
#include <QIcon>
|
||||
#include <QLayout>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
@ -48,15 +52,37 @@
|
|||
#include <QPainter>
|
||||
#include <QListWidget>
|
||||
#include <QSvgRenderer>
|
||||
#include <QPushButton>
|
||||
#include <QContextMenuEvent>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
const char *passwordIsSetPlaceholder = "●●●●●●●●";
|
||||
const char *passwordIsSetPlaceholder = "●●●●●●●●";
|
||||
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
|
||||
AvatarEventFilter::AvatarEventFilter(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool AvatarEventFilter::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ContextMenu) {
|
||||
const auto contextMenuEvent = dynamic_cast<QContextMenuEvent *>(event);
|
||||
if (!contextMenuEvent) {
|
||||
return false;
|
||||
}
|
||||
emit contextMenu(contextMenuEvent->globalPos());
|
||||
return true;
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
|
||||
const QString &sharePath,
|
||||
const QString &localPath,
|
||||
|
@ -465,16 +491,14 @@ void ShareUserGroupWidget::activateShareeLineEdit()
|
|||
_ui->shareeLineEdit->setFocus();
|
||||
}
|
||||
|
||||
ShareUserLine::ShareUserLine(AccountPtr account,
|
||||
QSharedPointer<UserGroupShare> share,
|
||||
SharePermissions maxSharingPermissions,
|
||||
bool isFile,
|
||||
QWidget *parent)
|
||||
ShareUserLine::ShareUserLine(AccountPtr account, QSharedPointer<UserGroupShare> share,
|
||||
SharePermissions maxSharingPermissions, bool isFile, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, _ui(new Ui::ShareUserLine)
|
||||
, _account(account)
|
||||
, _share(share)
|
||||
, _isFile(isFile)
|
||||
, _profilePageMenu(account, share->getShareWith()->shareWith())
|
||||
{
|
||||
Q_ASSERT(_share);
|
||||
_ui->setupUi(this);
|
||||
|
@ -618,11 +642,22 @@ ShareUserLine::ShareUserLine(AccountPtr account,
|
|||
_permissionReshare->setVisible(false);
|
||||
}
|
||||
|
||||
const auto avatarEventFilter = new AvatarEventFilter(_ui->avatar);
|
||||
connect(avatarEventFilter, &AvatarEventFilter::contextMenu, this, &ShareUserLine::onAvatarContextMenu);
|
||||
_ui->avatar->installEventFilter(avatarEventFilter);
|
||||
|
||||
loadAvatar();
|
||||
|
||||
customizeStyle();
|
||||
}
|
||||
|
||||
void ShareUserLine::onAvatarContextMenu(const QPoint &globalPosition)
|
||||
{
|
||||
if (_share->getShareType() == Share::TypeUser) {
|
||||
_profilePageMenu.exec(globalPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void ShareUserLine::loadAvatar()
|
||||
{
|
||||
const int avatarSize = 36;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "sharemanager.h"
|
||||
#include "sharepermissions.h"
|
||||
#include "sharee.h"
|
||||
#include "profilepagewidget.h"
|
||||
#include "QProgressIndicator.h"
|
||||
#include <QDialog>
|
||||
#include <QWidget>
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <QTimer>
|
||||
#include <qpushbutton.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
class QAction;
|
||||
|
@ -44,6 +46,21 @@ class SyncResult;
|
|||
class Share;
|
||||
class ShareManager;
|
||||
|
||||
class AvatarEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AvatarEventFilter(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
void contextMenu(const QPoint &globalPosition);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ShareDialog (user/group) class
|
||||
* @ingroup gui
|
||||
|
@ -166,6 +183,8 @@ private slots:
|
|||
|
||||
void slotConfirmPasswordClicked();
|
||||
|
||||
void onAvatarContextMenu(const QPoint &globalPosition);
|
||||
|
||||
private:
|
||||
void displayPermissions();
|
||||
void loadAvatar();
|
||||
|
@ -197,6 +216,8 @@ private:
|
|||
QSharedPointer<UserGroupShare> _share;
|
||||
bool _isFile;
|
||||
|
||||
ProfilePageMenu _profilePageMenu;
|
||||
|
||||
// _permissionEdit is a checkbox
|
||||
QAction *_permissionReshare;
|
||||
QAction *_deleteShareButton;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>980</width>
|
||||
<height>239</height>
|
||||
<width>899</width>
|
||||
<height>310</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -302,32 +302,518 @@
|
|||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>65</red>
|
||||
<green>70</green>
|
||||
<blue>84</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Light">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>95</red>
|
||||
<green>103</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>49</red>
|
||||
<green>49</green>
|
||||
<blue>49</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Mid">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>25</red>
|
||||
<green>25</green>
|
||||
<blue>25</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>64</red>
|
||||
<green>69</green>
|
||||
<blue>82</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>56</red>
|
||||
<green>60</green>
|
||||
<blue>74</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Shadow">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>82</red>
|
||||
<green>148</green>
|
||||
<blue>226</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="HighlightedText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Link">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>157</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="LinkVisited">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>158</red>
|
||||
<green>79</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="AlternateBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>60</red>
|
||||
<green>67</green>
|
||||
<blue>79</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>238</red>
|
||||
<green>252</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>65</red>
|
||||
<green>70</green>
|
||||
<blue>84</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Light">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>95</red>
|
||||
<green>103</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>49</red>
|
||||
<green>49</green>
|
||||
<blue>49</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Mid">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>25</red>
|
||||
<green>25</green>
|
||||
<blue>25</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="200">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>64</red>
|
||||
<green>69</green>
|
||||
<blue>82</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>56</red>
|
||||
<green>60</green>
|
||||
<blue>74</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Shadow">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>82</red>
|
||||
<green>149</green>
|
||||
<blue>225</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="HighlightedText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Link">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>157</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="LinkVisited">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>158</red>
|
||||
<green>79</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="AlternateBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>60</red>
|
||||
<green>67</green>
|
||||
<blue>79</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>238</red>
|
||||
<green>252</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="115">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>123</red>
|
||||
<green>121</green>
|
||||
<blue>134</blue>
|
||||
<red>65</red>
|
||||
<green>70</green>
|
||||
<blue>84</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Light">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>95</red>
|
||||
<green>103</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Midlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>49</red>
|
||||
<green>49</green>
|
||||
<blue>49</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Dark">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Mid">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>25</red>
|
||||
<green>25</green>
|
||||
<blue>25</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="115">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ButtonText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="115">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>64</red>
|
||||
<green>69</green>
|
||||
<blue>82</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>56</red>
|
||||
<green>60</green>
|
||||
<blue>74</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Shadow">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Highlight">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>82</red>
|
||||
<green>148</green>
|
||||
<blue>226</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="HighlightedText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Link">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>157</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="LinkVisited">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>158</red>
|
||||
<green>79</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="AlternateBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>60</red>
|
||||
<green>67</green>
|
||||
<blue>79</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipBase">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="ToolTipText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>238</red>
|
||||
<green>252</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
|
|
|
@ -113,7 +113,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
|
|||
a._icon = json.value("icon").toString();
|
||||
|
||||
if (!a._icon.isEmpty()) {
|
||||
auto *iconJob = new IconJob(QUrl(a._icon));
|
||||
auto *iconJob = new IconJob(_accountState->account(), QUrl(a._icon));
|
||||
iconJob->setProperty("activityId", a._id);
|
||||
connect(iconJob, &IconJob::jobFinished, this, &ServerNotificationHandler::slotIconDownloaded);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ set(libsync_SRCS
|
|||
configfile.cpp
|
||||
abstractnetworkjob.cpp
|
||||
networkjobs.cpp
|
||||
iconjob.cpp
|
||||
owncloudpropagator.cpp
|
||||
nextcloudtheme.cpp
|
||||
abstractpropagateremotedeleteencrypted.cpp
|
||||
|
@ -58,6 +59,7 @@ set(libsync_SRCS
|
|||
datetimeprovider.cpp
|
||||
ocsuserstatusconnector.cpp
|
||||
userstatusconnector.cpp
|
||||
ocsprofileconnector.cpp
|
||||
creds/dummycredentials.cpp
|
||||
creds/abstractcredentials.cpp
|
||||
creds/credentialscommon.cpp
|
||||
|
|
|
@ -16,26 +16,31 @@
|
|||
|
||||
namespace OCC {
|
||||
|
||||
IconJob::IconJob(const QUrl &url, QObject *parent) :
|
||||
QObject(parent)
|
||||
IconJob::IconJob(AccountPtr account, const QUrl &url, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&_accessManager, &QNetworkAccessManager::finished,
|
||||
this, &IconJob::finished);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
#if (QT_VERSION >= 0x050600)
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
#endif
|
||||
_accessManager.get(request);
|
||||
const auto reply = account->sendRawRequest(QByteArrayLiteral("GET"), url, request);
|
||||
connect(reply, &QNetworkReply::finished, this, &IconJob::finished);
|
||||
}
|
||||
|
||||
void IconJob::finished(QNetworkReply *reply)
|
||||
void IconJob::finished()
|
||||
{
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
const auto reply = qobject_cast<QNetworkReply *>(sender());
|
||||
if (!reply) {
|
||||
return;
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
deleteLater();
|
||||
|
||||
const auto networkError = reply->error();
|
||||
if (networkError != QNetworkReply::NoError) {
|
||||
emit error(networkError);
|
||||
return;
|
||||
}
|
||||
|
||||
emit jobFinished(reply->readAll());
|
||||
}
|
||||
}
|
|
@ -15,6 +15,10 @@
|
|||
#ifndef ICONJOB_H
|
||||
#define ICONJOB_H
|
||||
|
||||
#include "account.h"
|
||||
#include "accountfwd.h"
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <QNetworkAccessManager>
|
||||
|
@ -27,20 +31,18 @@ namespace OCC {
|
|||
* @brief Job to fetch a icon
|
||||
* @ingroup gui
|
||||
*/
|
||||
class IconJob : public QObject
|
||||
class OWNCLOUDSYNC_EXPORT IconJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit IconJob(const QUrl &url, QObject *parent = nullptr);
|
||||
explicit IconJob(AccountPtr account, const QUrl &url, QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void jobFinished(QByteArray iconData);
|
||||
void error(QNetworkReply::NetworkError errorType);
|
||||
|
||||
private slots:
|
||||
void finished(QNetworkReply *reply);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager _accessManager;
|
||||
void finished();
|
||||
};
|
||||
}
|
||||
|
168
src/libsync/ocsprofileconnector.cpp
Normal file
168
src/libsync/ocsprofileconnector.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
#include "ocsprofileconnector.h"
|
||||
#include "accountfwd.h"
|
||||
#include "common/result.h"
|
||||
#include "networkjobs.h"
|
||||
#include "iconjob.h"
|
||||
#include "theme.h"
|
||||
#include "account.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QLoggingCategory>
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <QSvgRenderer>
|
||||
#include <QNetworkReply>
|
||||
#include <QPixmap>
|
||||
#include <QPixmapCache>
|
||||
|
||||
namespace {
|
||||
Q_LOGGING_CATEGORY(lcOcsProfileConnector, "nextcloud.gui.ocsprofileconnector", QtInfoMsg)
|
||||
|
||||
OCC::HovercardAction jsonToAction(const QJsonObject &jsonActionObject)
|
||||
{
|
||||
const auto iconUrl = jsonActionObject.value(QStringLiteral("icon")).toString(QStringLiteral("no-icon"));
|
||||
QPixmap iconPixmap;
|
||||
OCC::HovercardAction hovercardAction{
|
||||
jsonActionObject.value(QStringLiteral("title")).toString(QStringLiteral("No title")), iconUrl,
|
||||
jsonActionObject.value(QStringLiteral("hyperlink")).toString(QStringLiteral("no-link"))};
|
||||
if (QPixmapCache::find(iconUrl, &iconPixmap)) {
|
||||
hovercardAction._icon = iconPixmap;
|
||||
}
|
||||
return hovercardAction;
|
||||
}
|
||||
|
||||
OCC::Hovercard jsonToHovercard(const QJsonArray &jsonDataArray)
|
||||
{
|
||||
OCC::Hovercard hovercard;
|
||||
hovercard._actions.reserve(jsonDataArray.size());
|
||||
for (const auto &jsonEntry : jsonDataArray) {
|
||||
Q_ASSERT(jsonEntry.isObject());
|
||||
if (!jsonEntry.isObject()) {
|
||||
continue;
|
||||
}
|
||||
hovercard._actions.push_back(jsonToAction(jsonEntry.toObject()));
|
||||
}
|
||||
return hovercard;
|
||||
}
|
||||
|
||||
OCC::Optional<QPixmap> createPixmapFromSvgData(const QByteArray &iconData)
|
||||
{
|
||||
QSvgRenderer svgRenderer;
|
||||
if (!svgRenderer.load(iconData)) {
|
||||
return {};
|
||||
}
|
||||
QSize imageSize{16, 16};
|
||||
if (OCC::Theme::isHidpi()) {
|
||||
imageSize = QSize{32, 32};
|
||||
}
|
||||
QImage scaledSvg(imageSize, QImage::Format_ARGB32);
|
||||
scaledSvg.fill("transparent");
|
||||
QPainter svgPainter{&scaledSvg};
|
||||
svgRenderer.render(&svgPainter);
|
||||
return QPixmap::fromImage(scaledSvg);
|
||||
}
|
||||
|
||||
OCC::Optional<QPixmap> iconDataToPixmap(const QByteArray iconData)
|
||||
{
|
||||
if (!iconData.startsWith("<svg")) {
|
||||
return {};
|
||||
}
|
||||
return createPixmapFromSvgData(iconData);
|
||||
}
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
|
||||
HovercardAction::HovercardAction() = default;
|
||||
|
||||
HovercardAction::HovercardAction(QString title, QUrl iconUrl, QUrl link)
|
||||
: _title(std::move(title))
|
||||
, _iconUrl(std::move(iconUrl))
|
||||
, _link(std::move(link))
|
||||
{
|
||||
}
|
||||
|
||||
OcsProfileConnector::OcsProfileConnector(AccountPtr account, QObject *parent)
|
||||
: QObject(parent)
|
||||
, _account(account)
|
||||
{
|
||||
}
|
||||
|
||||
void OcsProfileConnector::fetchHovercard(const QString &userId)
|
||||
{
|
||||
if (_account->serverVersionInt() < Account::makeServerVersion(23, 0, 0)) {
|
||||
qInfo(lcOcsProfileConnector) << "Server version" << _account->serverVersion()
|
||||
<< "does not support profile page";
|
||||
emit error();
|
||||
return;
|
||||
}
|
||||
const QString url = QStringLiteral("/ocs/v2.php/hovercard/v1/%1").arg(userId);
|
||||
const auto job = new JsonApiJob(_account, url, this);
|
||||
connect(job, &JsonApiJob::jsonReceived, this, &OcsProfileConnector::onHovercardFetched);
|
||||
job->start();
|
||||
}
|
||||
|
||||
void OcsProfileConnector::onHovercardFetched(const QJsonDocument &json, int statusCode)
|
||||
{
|
||||
qCDebug(lcOcsProfileConnector) << "Hovercard fetched:" << json;
|
||||
|
||||
if (statusCode != 200) {
|
||||
qCInfo(lcOcsProfileConnector) << "Fetching of hovercard finished with status code" << statusCode;
|
||||
return;
|
||||
}
|
||||
const auto jsonData = json.object().value("ocs").toObject().value("data").toObject().value("actions");
|
||||
Q_ASSERT(jsonData.isArray());
|
||||
_currentHovercard = jsonToHovercard(jsonData.toArray());
|
||||
fetchIcons();
|
||||
emit hovercardFetched();
|
||||
}
|
||||
|
||||
void OcsProfileConnector::setHovercardActionIcon(const std::size_t index, const QPixmap &pixmap)
|
||||
{
|
||||
auto &hovercardAction = _currentHovercard._actions[index];
|
||||
QPixmapCache::insert(hovercardAction._iconUrl.toString(), pixmap);
|
||||
hovercardAction._icon = pixmap;
|
||||
emit iconLoaded(index);
|
||||
}
|
||||
|
||||
void OcsProfileConnector::loadHovercardActionIcon(const std::size_t hovercardActionIndex, const QByteArray &iconData)
|
||||
{
|
||||
if (hovercardActionIndex >= _currentHovercard._actions.size()) {
|
||||
// Note: Probably could do more checking, like checking if the url is still the same.
|
||||
return;
|
||||
}
|
||||
const auto icon = iconDataToPixmap(iconData);
|
||||
if (icon.isValid()) {
|
||||
setHovercardActionIcon(hovercardActionIndex, icon.get());
|
||||
return;
|
||||
}
|
||||
qCWarning(lcOcsProfileConnector) << "Could not load Svg icon from data" << iconData;
|
||||
}
|
||||
|
||||
void OcsProfileConnector::startFetchIconJob(const std::size_t hovercardActionIndex)
|
||||
{
|
||||
const auto hovercardAction = _currentHovercard._actions[hovercardActionIndex];
|
||||
const auto iconJob = new IconJob{_account, hovercardAction._iconUrl, this};
|
||||
connect(iconJob, &IconJob::jobFinished,
|
||||
[this, hovercardActionIndex](QByteArray iconData) { loadHovercardActionIcon(hovercardActionIndex, iconData); });
|
||||
connect(iconJob, &IconJob::error, this, [](QNetworkReply::NetworkError errorType) {
|
||||
qCWarning(lcOcsProfileConnector) << "Could not fetch icon:" << errorType;
|
||||
});
|
||||
}
|
||||
|
||||
void OcsProfileConnector::fetchIcons()
|
||||
{
|
||||
for (auto hovercardActionIndex = 0u; hovercardActionIndex < _currentHovercard._actions.size();
|
||||
++hovercardActionIndex) {
|
||||
startFetchIconJob(hovercardActionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
const Hovercard &OcsProfileConnector::hovercard() const
|
||||
{
|
||||
return _currentHovercard;
|
||||
}
|
||||
}
|
58
src/libsync/ocsprofileconnector.h
Normal file
58
src/libsync/ocsprofileconnector.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include "accountfwd.h"
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
#include <QUrl>
|
||||
#include <QString>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
struct OWNCLOUDSYNC_EXPORT HovercardAction
|
||||
{
|
||||
public:
|
||||
HovercardAction();
|
||||
HovercardAction(QString title, QUrl iconUrl, QUrl link);
|
||||
|
||||
QString _title;
|
||||
QUrl _iconUrl;
|
||||
QPixmap _icon;
|
||||
QUrl _link;
|
||||
};
|
||||
|
||||
struct OWNCLOUDSYNC_EXPORT Hovercard
|
||||
{
|
||||
std::vector<HovercardAction> _actions;
|
||||
};
|
||||
|
||||
class OWNCLOUDSYNC_EXPORT OcsProfileConnector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OcsProfileConnector(AccountPtr account, QObject *parent = nullptr);
|
||||
|
||||
void fetchHovercard(const QString &userId);
|
||||
const Hovercard &hovercard() const;
|
||||
|
||||
signals:
|
||||
void error();
|
||||
void hovercardFetched();
|
||||
void iconLoaded(const std::size_t hovercardActionIndex);
|
||||
|
||||
private:
|
||||
void onHovercardFetched(const QJsonDocument &json, int statusCode);
|
||||
|
||||
void fetchIcons();
|
||||
void startFetchIconJob(const std::size_t hovercardActionIndex);
|
||||
void setHovercardActionIcon(const std::size_t index, const QPixmap &pixmap);
|
||||
void loadHovercardActionIcon(const std::size_t hovercardActionIndex, const QByteArray &iconData);
|
||||
|
||||
AccountPtr _account;
|
||||
Hovercard _currentHovercard;
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(OCC::HovercardAction)
|
||||
Q_DECLARE_METATYPE(OCC::Hovercard)
|
Loading…
Reference in a new issue