libQuotient
A Qt library for building matrix clients
roommember.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 
4 #pragma once
5 
6 #include "quotient_common.h"
7 #include "uri.h"
8 
9 #include <QtCore/QObject>
10 
11 namespace Quotient {
12 class Room;
13 class RoomMemberEvent;
14 
15 //! This class is for visualizing a user in a room context.
16 //!
17 //! The class is intentionally a read-only data object that is effectively a wrapper
18 //! around an m.room.member event for the desired user. This is designed provide the
19 //! data in a format ready for visualizing a user (avatar or name) in the context
20 //! of the room it was generated in. This means that if a user has set a unique
21 //! name or avatar for a particular room that is what will be returned.
22 //!
23 //! \note The RoomMember class is not intended for interacting with a User's profile.
24 //! For that a Quotient::User object should be obtained from a
25 //! Quotient::Connection as that has the support functions for modifying profile
26 //! information.
27 //!
28 //! \sa Quotient::User
29 class QUOTIENT_API RoomMember {
30  Q_GADGET
31  Q_PROPERTY(bool isEmpty READ isEmpty CONSTANT)
32  Q_PROPERTY(QString id READ id CONSTANT)
33  Q_PROPERTY(Uri uri READ uri CONSTANT)
34  Q_PROPERTY(bool isLocalMember READ isLocalMember CONSTANT)
35  Q_PROPERTY(QString displayName READ displayName CONSTANT)
36  Q_PROPERTY(QString htmlSafeDisplayName READ htmlSafeDisplayName CONSTANT)
37  Q_PROPERTY(QString fullName READ fullName CONSTANT)
38  Q_PROPERTY(QString htmlSafeFullName READ htmlSafeFullName CONSTANT)
39  Q_PROPERTY(QString disambiguatedName READ disambiguatedName CONSTANT)
40  Q_PROPERTY(QString htmlSafeDisambiguatedName READ htmlSafeDisambiguatedName CONSTANT)
41  Q_PROPERTY(int hue READ hue CONSTANT)
42  Q_PROPERTY(qreal hueF READ hueF CONSTANT)
43  Q_PROPERTY(QColor color READ color CONSTANT)
44  Q_PROPERTY(QUrl avatarUrl READ avatarUrl CONSTANT)
45 
46 public:
47  RoomMember() = default;
48 
49  explicit RoomMember(const Room* room, const RoomMemberEvent* member);
50 
51  bool isEmpty() const { return _member == nullptr; }
52 
53  bool operator==(const RoomMember& other) const;
54 
55  //! @brief Get unique stable user id
56  //!
57  //! The Matrix user ID is generated by the server and is never changed.
58  QString id() const;
59 
60  //! @brief The matrix.to URI for the user
61  //!
62  //! Typically used when you want to visit a user (see
63  //! Quotient::UriResolverBase::visitResource()).
64  //!
65  //! @sa Quotient::UriResolverBase::visitResource()
66  Uri uri() const;
67 
68  //! Whether this member is the local user
69  bool isLocalMember() const;
70 
71  //! The membership state of the member
72  Membership membershipState() const;
73 
74  //! \brief The raw unmodified display name for the user in the given room
75  //!
76  //! The value will be empty if no display name has been set.
77  //!
78  //! \warning This value is not sanitized or HTML escape so use appropriately.
79  //! For ready to display values use displayName() or fullName() for
80  //! plain text and htmlSafeDisplayName() or htmlSafeFullName() fo
81  //! rich text.
82  //!
83  //! \sa displayName(), htmlSafeDisplayName(), fullName(), htmlSafeFullName()
84  QString name() const;
85 
86  //! \brief Get the user display name ready for display
87  //!
88  //! This function always aims to return something that can be displayed in a
89  //! UI, so if no display name is set the user's Matrix ID will be returned.
90  //!
91  //! The output is sanitized and suitable for a plain text field. For a rich
92  //! field use htmlSafeDisplayName().
93  //!
94  //! \sa htmlSafeDisplayName()
95  QString displayName() const;
96 
97  //! \brief Get the user display name ready for display
98  //!
99  //! This function always aims to return something that can be displayed in a
100  //! UI, so if no display name is set the user's Matrix ID will be returned.
101  //!
102  //! The output is sanitized and html escaped ready for a rich text field. For
103  //! a plain field use displayName().
104  //!
105  //! \sa displayName()
106  QString htmlSafeDisplayName() const;
107 
108  //! \brief Get user name and id in a single string
109  //!
110  //! This function always aims to return something that can be displayed in a
111  //! UI, so if no display name is set the just user's Matrix ID will be returned.
112  //! The constructed string follows the format 'name (id)' which the spec
113  //! recommends for users disambiguation in a room context and in other places.
114  //!
115  //! The output is sanitized and suitable for a plain text field. For a rich
116  //! field use htmlSafeFullName().
117  //!
118  //! \sa htmlSafeFullName()
119  QString fullName() const;
120 
121  //! \brief Get user name and id in a single string
122  //!
123  //! This function always aims to return something that can be displayed in a
124  //! UI, so if no display name is set the just user's Matrix ID will be returned.
125  //! The constructed string follows the format 'name (id)' which the spec
126  //! recommends for users disambiguation in a room context and in other places.
127  //!
128  //! The output is sanitized and html escaped ready for a rich text field. For
129  //! a plain field use fullName().
130  //!
131  //! \sa fullName()
132  QString htmlSafeFullName() const;
133 
134  //! \brief Get the disambiguated user name
135  //!
136  //! This function always aims to return something that can be displayed in a
137  //! UI, so if no display name is set the just user's Matrix ID will be returned.
138  //! The output is equivalent to fullName() if there is another user in the room
139  //! with the same name. Otherwise it is equivalent to displayName().
140  //!
141  //! The output is sanitized and suitable for a plain text field. For a rich
142  //! field use htmlSafeDisambiguatedName().
143  //!
144  //! \sa htmlSafeDisambiguatedName(), fullName(), displayName()
145  QString disambiguatedName() const;
146 
147  //! \brief Get the disambiguated user name
148  //!
149  //! This function always aims to return something that can be displayed in a
150  //! UI, so if no display name is set the just user's Matrix ID will be returned.
151  //! The output is equivalent to htmlSafeFullName() if there is another user in the room
152  //! with the same name. Otherwise it is equivalent to htmlSafeDisplayName().
153  //!
154  //! The output is sanitized and html escaped ready for a rich text field. For
155  //! a plain field use disambiguatedName().
156  //!
157  //! \sa disambiguatedName(), htmlSafeFullName(), htmlSafeDisplayName()
158  QString htmlSafeDisambiguatedName() const;
159 
160  //! \brief Check whether the name or id of the member contains a substring
161  //!
162  //! This is useful for a predicate to filter room members.
163  //! \sa MemberMatcher
164  Q_INVOKABLE bool matches(QStringView substr, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
165 
166  //! \brief Hue color component of this user based on the user's Matrix ID
167  //!
168  //! The implementation is based on XEP-0392:
169  //! https://xmpp.org/extensions/xep-0392.html
170  //! Naming and ranges are the same as QColor's hue methods:
171  //! https://doc.qt.io/qt-5/qcolor.html#integer-vs-floating-point-precision
172  int hue() const;
173 
174  //! \brief HueF color component of this user based on the user's Matrix ID
175  //!
176  //! The implementation is based on XEP-0392:
177  //! https://xmpp.org/extensions/xep-0392.html
178  //! Naming and ranges are the same as QColor's hue methods:
179  //! https://doc.qt.io/qt-5/qcolor.html#integer-vs-floating-point-precision
180  qreal hueF() const;
181 
182  //! \brief Color based on the user's Matrix ID
183  //!
184  //! See https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal
185  //! for the methodology.
186  QColor color() const;
187 
188  //! \brief The mxc URL as a string for the user avatar in the room
189  //!
190  //! This can be empty if none set.
191  QString avatarMediaId() const;
192 
193  //! \brief The mxc URL for the user avatar in the room
194  //!
195  //!This can be empty if none set.
196  QUrl avatarUrl() const;
197 
198 private:
199  const Room* _room = nullptr;
200  const RoomMemberEvent* _member = nullptr;
201 
202  qreal _hueF = 0;
203 };
204 
205 //! \brief A factory to get a functional object matching room members against a substring
206 //!
207 //! This is a convenience wrapper to use RoomMember::matches() in standard algorithms.
208 inline auto memberMatcher(auto substr, Qt::CaseSensitivity cs = Qt::CaseSensitive)
209 {
210 #ifdef __cpp_lib_bind_back
211  return std::bind_back(&RoomMember::matches, substr, cs);
212 #else
213  return [substr, cs](const RoomMember& m) { return m.matches(substr, cs); };
214 #endif
215 }
216 
217 struct QUOTIENT_API MemberSorter {
218  bool operator()(const RoomMember& u1, const RoomMember& u2) const
219  {
220  return operator()(u1.displayName(), u2.displayName());
221  }
222  bool operator()(const RoomMember& u1, QStringView u2name) const
223  {
224  return operator()(u1.displayName(), u2name);
225  }
226  bool operator()(QStringView u1name, const RoomMember& u2) const
227  {
228  return operator()(u1name, u2.displayName());
229  }
230  bool operator()(QStringView u1name, QStringView u2name) const;
231 
232 #if Quotient_VERSION_MAJOR == 0 && Quotient_VERSION_MINOR < 10
233  template <template <class> class ContT>
234  [[deprecated("Use Quotient::lowerBoundIndex() or std::ranges::lower_bound() instead")]] //
235  typename ContT<RoomMember>::size_type
236  lowerBoundIndex(const ContT<RoomMember>& c, const auto& v) const
237  {
238  return std::ranges::lower_bound(c, v, *this) - c.begin();
239  }
240 #endif
241 };
242 
243 } // namespace Quotient