libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
room.h
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2016 Kitsune Ral <Kitsune-Ral@users.sf.net>
2
// SPDX-FileCopyrightText: 2017 Roman Plášil <me@rplasil.name>
3
// SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com>
4
// SPDX-FileCopyrightText: 2018 Josip Delic <delijati@googlemail.com>
5
// SPDX-FileCopyrightText: 2018 Black Hat <bhat@encom.eu.org>
6
// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru>
7
// SPDX-FileCopyrightText: 2020 Ram Nad <ramnad1999@gmail.com>
8
// SPDX-License-Identifier: LGPL-2.1-or-later
9
10
#
pragma
once
11
12
#
include
"connection.h"
13
#
include
"roommember.h"
14
#
include
"roomstateview.h"
15
#
include
"eventitem.h"
16
#
include
"quotient_common.h"
17
18
#
include
"csapi/message_pagination.h"
19
20
#
include
"events/accountdataevents.h"
21
#
include
"events/encryptedevent.h"
22
#
include
"events/eventrelation.h"
23
#
include
"events/roomcreateevent.h"
24
#
include
"events/roomkeyevent.h"
25
#
include
"events/roommessageevent.h"
26
#
include
"events/roompowerlevelsevent.h"
27
#
include
"events/roomtombstoneevent.h"
28
29
#
include
<
QtCore
/
QJsonObject
>
30
#
include
<
QtGui
/
QImage
>
31
32
#
include
<
deque
>
33
#
include
<
utility
>
34
35
namespace
Quotient
{
36
class
Event;
37
class
Avatar;
38
class
SyncRoomData;
39
class
RoomMemberEvent;
40
class
User;
41
class
RoomMember;
42
struct
MemberSorter;
43
class
LeaveRoomJob;
44
class
SetRoomStateWithKeyJob;
45
class
RedactEventJob;
46
class
Thread;
47
48
/** The data structure used to expose file transfer information to views
49
*
50
* This is specifically tuned to work with QML exposing all traits as
51
* Q_PROPERTY values.
52
*/
53
class
QUOTIENT_API
FileTransferInfo
{
54
Q_GADGET
55
Q_PROPERTY
(
bool
isUpload
MEMBER
isUpload
CONSTANT
)
56
Q_PROPERTY
(
bool
active
READ
active
CONSTANT
)
57
Q_PROPERTY
(
bool
started
READ
started
CONSTANT
)
58
Q_PROPERTY
(
bool
completed
READ
completed
CONSTANT
)
59
Q_PROPERTY
(
bool
failed
READ
failed
CONSTANT
)
60
Q_PROPERTY
(
int
progress
MEMBER
progress
CONSTANT
)
61
Q_PROPERTY
(
int
total
MEMBER
total
CONSTANT
)
62
Q_PROPERTY
(
QUrl
localDir
MEMBER
localDir
CONSTANT
)
63
Q_PROPERTY
(
QUrl
localPath
MEMBER
localPath
CONSTANT
)
64
public
:
65
enum
Status
{
None
,
Started
,
Completed
,
Failed
,
Cancelled
};
66
Status
status
=
None
;
67
bool
isUpload
=
false
;
68
int
progress
= 0;
69
int
total
= -1;
70
QUrl
localDir
{};
71
QUrl
localPath
{};
72
73
bool
started
()
const
{
return
status
==
Started
; }
74
bool
completed
()
const
{
return
status
==
Completed
; }
75
bool
active
()
const
{
return
started
() ||
completed
(); }
76
bool
failed
()
const
{
return
status
==
Failed
; }
77
};
78
79
//! \brief Data structure for a room member's read receipt
80
//! \sa Room::lastReadReceipt
81
class
QUOTIENT_API
ReadReceipt
{
82
Q_GADGET
83
Q_PROPERTY
(
QString
eventId
MEMBER
eventId
CONSTANT
)
84
Q_PROPERTY
(
QDateTime
timestamp
MEMBER
timestamp
CONSTANT
)
85
public
:
86
QString
eventId
;
87
QDateTime
timestamp
= {};
88
89
bool
operator
==(
const
ReadReceipt
&
other
)
const
90
{
91
return
eventId
==
other
.
eventId
&&
timestamp
==
other
.
timestamp
;
92
}
93
bool
operator
!=(
const
ReadReceipt
&
other
)
const
94
{
95
return
!
operator
==(
other
);
96
}
97
};
98
inline
void
swap
(
ReadReceipt
&
lhs
,
ReadReceipt
&
rhs
)
99
{
100
swap
(
lhs
.
eventId
,
rhs
.
eventId
);
101
swap
(
lhs
.
timestamp
,
rhs
.
timestamp
);
102
}
103
104
struct
EventStats;
105
106
struct
Notification
107
{
108
enum
Type
{
None
= 0,
Basic
,
Highlight
};
109
Q_ENUM
(
Type
)
110
111
Type
type
=
None
;
112
113
private
:
114
Q_GADGET
115
Q_PROPERTY(
Type
type MEMBER type CONSTANT)
116
};
117
118
class
QUOTIENT_API
Room
:
public
QObject
{
119
Q_OBJECT
120
Q_PROPERTY
(
Connection
*
connection
READ
connection
CONSTANT
)
121
Q_PROPERTY
(
RoomMember
localMember
READ
localMember
CONSTANT
)
122
Q_PROPERTY
(
QString
id
READ
id
CONSTANT
)
123
Q_PROPERTY
(
QString
version
READ
version
NOTIFY
baseStateLoaded
)
124
Q_PROPERTY
(
bool
isUnstable
READ
isUnstable
NOTIFY
stabilityUpdated
)
125
Q_PROPERTY
(
QString
predecessorId
READ
predecessorId
NOTIFY
baseStateLoaded
)
126
Q_PROPERTY
(
QString
successorId
READ
successorId
NOTIFY
upgraded
)
127
Q_PROPERTY
(
QString
name
READ
name
NOTIFY
namesChanged
)
128
Q_PROPERTY
(
QStringList
aliases
READ
aliases
NOTIFY
namesChanged
)
129
Q_PROPERTY
(
QStringList
altAliases
READ
altAliases
NOTIFY
namesChanged
)
130
Q_PROPERTY
(
QString
canonicalAlias
READ
canonicalAlias
NOTIFY
namesChanged
)
131
Q_PROPERTY
(
QString
displayName
READ
displayName
NOTIFY
displaynameChanged
)
132
Q_PROPERTY
(
QStringList
pinnedEventIds
READ
pinnedEventIds
WRITE
setPinnedEvents
133
NOTIFY
pinnedEventsChanged
)
134
Q_PROPERTY
(
QString
displayNameForHtml
READ
displayNameForHtml
NOTIFY
displaynameChanged
)
135
Q_PROPERTY
(
QString
topic
READ
topic
NOTIFY
topicChanged
)
136
Q_PROPERTY
(
QString
avatarMediaId
READ
avatarMediaId
NOTIFY
avatarChanged
137
STORED
false
)
138
Q_PROPERTY
(
QUrl
avatarUrl
READ
avatarUrl
NOTIFY
avatarChanged
)
139
Q_PROPERTY
(
bool
usesEncryption
READ
usesEncryption
NOTIFY
encryption
)
140
141
Q_PROPERTY
(
int
timelineSize
READ
timelineSize
NOTIFY
addedMessages
)
142
Q_PROPERTY
(
int
joinedCount
READ
joinedCount
NOTIFY
memberListChanged
)
143
Q_PROPERTY
(
int
invitedCount
READ
invitedCount
NOTIFY
memberListChanged
)
144
Q_PROPERTY
(
int
totalMemberCount
READ
totalMemberCount
NOTIFY
memberListChanged
)
145
Q_PROPERTY
(
QList
<
RoomMember
>
membersTyping
READ
membersTyping
NOTIFY
typingChanged
)
146
Q_PROPERTY
(
QList
<
RoomMember
>
otherMembersTyping
READ
otherMembersTyping
NOTIFY
typingChanged
)
147
Q_PROPERTY
(
int
localMemberEffectivePowerLevel
READ
memberEffectivePowerLevel
NOTIFY
changed
)
148
149
Q_PROPERTY
(
bool
displayed
READ
displayed
WRITE
setDisplayed
NOTIFY
150
displayedChanged
)
151
Q_PROPERTY
(
QString
firstDisplayedEventId
READ
firstDisplayedEventId
WRITE
152
setFirstDisplayedEventId
NOTIFY
firstDisplayedEventChanged
)
153
Q_PROPERTY
(
QString
lastDisplayedEventId
READ
lastDisplayedEventId
WRITE
154
setLastDisplayedEventId
NOTIFY
lastDisplayedEventChanged
)
155
Q_PROPERTY
(
QString
lastFullyReadEventId
READ
lastFullyReadEventId
WRITE
156
markMessagesAsRead
NOTIFY
fullyReadMarkerMoved
)
157
Q_PROPERTY
(
qsizetype
highlightCount
READ
highlightCount
158
NOTIFY
highlightCountChanged
)
159
Q_PROPERTY
(
qsizetype
notificationCount
READ
notificationCount
160
NOTIFY
notificationCountChanged
)
161
Q_PROPERTY
(
EventStats
partiallyReadStats
READ
partiallyReadStats
NOTIFY
partiallyReadStatsChanged
)
162
Q_PROPERTY
(
EventStats
unreadStats
READ
unreadStats
NOTIFY
unreadStatsChanged
)
163
Q_PROPERTY
(
bool
allHistoryLoaded
READ
allHistoryLoaded
NOTIFY
allHistoryLoadedChanged
164
STORED
false
)
165
Q_PROPERTY
(
QStringList
tagNames
READ
tagNames
NOTIFY
tagsChanged
)
166
Q_PROPERTY
(
bool
isFavourite
READ
isFavourite
NOTIFY
tagsChanged
STORED
false
)
167
Q_PROPERTY
(
bool
isLowPriority
READ
isLowPriority
NOTIFY
tagsChanged
STORED
false
)
168
169
Q_PROPERTY
(
GetRoomEventsJob
*
eventsHistoryJob
READ
eventsHistoryJob
NOTIFY
eventsHistoryJobChanged
)
170
Q_PROPERTY
(
int
requestedHistorySize
READ
requestedHistorySize
NOTIFY
eventsHistoryJobChanged
)
171
172
Q_PROPERTY
(
QStringList
accountDataEventTypes
READ
accountDataEventTypes
NOTIFY
accountDataChanged
)
173
174
public
:
175
using
Timeline
=
std
::
deque
<
TimelineItem
>;
176
using
PendingEvents
=
std
::
vector
<
PendingEventItem
>;
177
using
RelatedEvents
=
QVector
<
const
RoomEvent
*>;
178
using
rev_iter_t
=
Timeline
::
const_reverse_iterator
;
179
using
timeline_iter_t
=
Timeline
::
const_iterator
;
180
using
ThreadView
=
QHash
<
QString
,
Thread
>;
181
182
//! \brief Room changes that can be tracked using Room::changed() signal
183
//!
184
//! This enumeration lists kinds of changes that can be tracked with
185
//! a "cumulative" changed() signal instead of using individual signals for
186
//! each change. Specific enumerators mention these individual signals.
187
//! \sa changed
188
enum
class
Change
:
quint32
{
// QFlags can't go more than 32-bit
189
None
= 0x0,
//!< No changes occurred in the room
190
RoomNames
= 0x1,
//!< \sa namesChanged, displaynameChanged
191
// NotInUse = 0x2,
192
Topic
= 0x4,
//!< \sa topicChanged
193
PartiallyReadStats
= 0x8,
//!< \sa partiallyReadStatsChanged
194
Avatar
= 0x10,
//!< \sa avatarChanged
195
JoinState
= 0x20,
//!< \sa joinStateChanged
196
Tags
= 0x40,
//!< \sa tagsChanged
197
//! \sa userAdded, userRemoved, memberRenamed, memberListChanged,
198
//! displaynameChanged
199
Members
= 0x80,
200
UnreadStats
= 0x100,
//!< \sa unreadStatsChanged
201
// AccountData pre-0.9 = 0x200,
202
Summary
= 0x400,
//!< \sa summaryChanged, displaynameChanged
203
// ReadMarker pre-0.9 = 0x800,
204
Highlights
= 0x1000,
//!< \sa highlightCountChanged
205
//! A catch-all value that covers changes not listed above (such as
206
//! encryption turned on or the room having been upgraded), as well as
207
//! changes in the room state that the library is not aware of (e.g.,
208
//! custom state events) and m.read/m.fully_read position changes.
209
//! \sa encryptionChanged, upgraded, accountDataChanged
210
Other
= 0x8000,
211
//! This is intended to test a Change/Changes value for non-emptiness;
212
//! adding <tt>& Change::Any</tt> has the same meaning as
213
//! !testFlag(Change::None) or adding <tt>!= Change::None</tt>
214
//! \note testFlag(Change::Any) tests that _all_ bits are on and
215
//! will always return false.
216
Any
= 0xFFFF
217
};
218
QUO_DECLARE_FLAGS
(
Changes
,
Change
)
219
220
Room
(
Connection
*
connection
,
QString
id
,
JoinState
initialJoinState
);
221
Q_DISABLE_COPY_MOVE
(
Room
)
222
~
Room
()
override
;
223
224
// Property accessors
225
226
Connection
*
connection
()
const
;
227
228
//! Get a RoomMember object for the local user.
229
RoomMember
localMember
()
const
;
230
const
QString
&
id
()
const
;
231
QString
version
()
const
;
232
bool
isUnstable
()
const
;
233
QString
predecessorId
()
const
;
234
/// Room predecessor
235
/** This function validates that the predecessor has a tombstone and
236
* the tombstone refers to the current room. If that's not the case,
237
* or if the predecessor is in a join state not matching \p stateFilter,
238
* the function returns nullptr.
239
*/
240
Room
*
predecessor
(
JoinStates
statesFilter
=
JoinState
::
Invite
241
|
JoinState
::
Join
)
const
;
242
QString
successorId
()
const
;
243
/// Room successor
244
/** This function validates that the successor room's creation event
245
* refers to the current room. If that's not the case, or if the successor
246
* is in a join state not matching \p stateFilter, it returns nullptr.
247
*/
248
Room
*
successor
(
JoinStates
statesFilter
=
JoinState
::
Invite
249
|
JoinState
::
Join
)
const
;
250
QString
name
()
const
;
251
QString
canonicalAlias
()
const
;
252
QStringList
altAliases
()
const
;
253
//! Get a list of both canonical and alternative aliases
254
QStringList
aliases
()
const
;
255
QString
displayName
()
const
;
256
QStringList
pinnedEventIds
()
const
;
257
// Returns events available locally, use pinnedEventIds() for full list
258
QVector
<
const
RoomEvent
*>
pinnedEvents
()
const
;
259
QString
displayNameForHtml
()
const
;
260
QString
topic
()
const
;
261
QString
avatarMediaId
()
const
;
262
QUrl
avatarUrl
()
const
;
263
const
Avatar
&
avatarObject
()
const
;
264
Q_INVOKABLE
JoinState
joinState
()
const
;
265
266
int
timelineSize
()
const
;
267
bool
usesEncryption
()
const
;
268
RoomEventPtr
decryptMessage
(
const
EncryptedEvent
&
encryptedEvent
);
269
void
handleRoomKeyEvent
(
const
RoomKeyEvent
&
roomKeyEvent
,
270
const
QString
&
senderId
,
271
const
QByteArray
&
olmSessionId
,
272
const
QByteArray
&
senderKey
,
273
const
QByteArray
&
senderEdKey
);
274
int
joinedCount
()
const
;
275
int
invitedCount
()
const
;
276
int
totalMemberCount
()
const
;
277
278
GetRoomEventsJob
*
eventsHistoryJob
()
const
;
279
280
/**
281
* Returns a square room avatar with the given size and requests it
282
* from the network if needed
283
* \return a pixmap with the avatar or a placeholder if there's none
284
* available yet
285
*/
286
Q_INVOKABLE
QImage
avatar
(
int
dimension
);
287
/**
288
* Returns a room avatar with the given dimensions and requests it
289
* from the network if needed
290
* \return a pixmap with the avatar or a placeholder if there's none
291
* available yet
292
*/
293
Q_INVOKABLE
QImage
avatar
(
int
width
,
int
height
);
294
295
//! \brief Get a RoomMember object for the given user Matrix ID
296
//!
297
//! Will return a nullptr if there is no m.room.member event for the user in
298
//! the room so needs to be null checked.
299
//!
300
//! \note This can return a member in any state that is known to the room so
301
//! check the state (using RoomMember::membershipState()) before use.
302
Q_INVOKABLE
RoomMember
member
(
const
QString
&
userId
)
const
;
303
304
//! Get a list of room members who have joined the room.
305
QList
<
RoomMember
>
joinedMembers
()
const
;
306
307
//! Get a list of all members known to the room.
308
QList
<
RoomMember
>
members
()
const
;
309
310
//! Get a list of all members known to have left the room.
311
QList
<
RoomMember
>
membersLeft
()
const
;
312
313
//! Get a list of room members who are currently sending a typing indicator.
314
QList
<
RoomMember
>
membersTyping
()
const
;
315
316
//! \brief Get a list of room members who are currently sending a typing indicator.
317
//!
318
//! The local member is excluded from this list.
319
QList
<
RoomMember
>
otherMembersTyping
()
const
;
320
321
//! Get a list of room member Matrix IDs who have joined the room.
322
QStringList
joinedMemberIds
()
const
;
323
324
//! Get a list of all member Matrix IDs known to the room.
325
QStringList
memberIds
()
const
;
326
327
//! Whether the name for the given member should be disambiguated
328
bool
needsDisambiguation
(
const
QString
&
userId
)
const
;
329
330
//! \brief Check the join state of a given user in this room
331
//!
332
//! \return the given user's state with respect to the room
333
Q_INVOKABLE
Quotient
::
Membership
memberState
(
const
QString
&
userId
)
const
;
334
335
//! Check whether a user with the given id is a member of the room
336
Q_INVOKABLE
bool
isMember
(
const
QString
&
userId
)
const
;
337
338
const
Avatar
&
memberAvatarObject
(
const
QString
&
memberId
)
const
;
339
340
//! \brief Get a avatar of the specified dimensions
341
//!
342
//! This always returns immediately; if there's no avatar cached yet, the call triggers
343
//! a network request, that will emit Room::memberAvatarUpdated() once completed.
344
//! \return a pixmap with the avatar or a placeholder if there's none available yet
345
Q_INVOKABLE
QImage
memberAvatar
(
const
QString
&
memberId
,
int
width
,
int
height
);
346
347
//! \brief Get a square avatar of the specified size
348
//!
349
//! This is an overload for the case when the needed width and height are equal.
350
Q_INVOKABLE
QImage
memberAvatar
(
const
QString
&
memberId
,
int
dimension
);
351
352
const
Timeline
&
messageEvents
()
const
;
353
const
PendingEvents
&
pendingEvents
()
const
;
354
355
//! \brief Get the number of requested historical events
356
//! \return The number of requested events if there's a pending request; 0 otherwise
357
int
requestedHistorySize
()
const
;
358
359
//! Check whether all historical messages are already loaded
360
//! \return true if the "oldest" event in the timeline is a room creation event and there's
361
//! no further history to load; false otherwise
362
bool
allHistoryLoaded
()
const
;
363
364
//! \brief Get a reverse iterator at the position before the "oldest" event
365
//!
366
//! Same as messageEvents().crend()
367
rev_iter_t
historyEdge
()
const
;
368
369
const
ThreadView
&
threads
()
const
;
370
371
//! \brief Get an iterator for the position beyond the latest arrived event
372
//!
373
//! Same as messageEvents().cend()
374
Timeline
::
const_iterator
syncEdge
()
const
;
375
Q_INVOKABLE
Quotient
::
TimelineItem
::
index_t
minTimelineIndex
()
const
;
376
Q_INVOKABLE
Quotient
::
TimelineItem
::
index_t
maxTimelineIndex
()
const
;
377
Q_INVOKABLE
bool
isValidIndex
(
Quotient
::
TimelineItem
::
index_t
timelineIndex
)
const
;
378
379
rev_iter_t
findInTimeline
(
TimelineItem
::
index_t
index
)
const
;
380
rev_iter_t
findInTimeline
(
const
QString
&
evtId
)
const
;
381
PendingEvents
::
iterator
findPendingEvent
(
const
QString
&
txnId
);
382
PendingEvents
::
const_iterator
findPendingEvent
(
const
QString
&
txnId
)
const
;
383
384
const
RelatedEvents
relatedEvents
(
const
QString
&
evtId
,
385
EventRelation
::
reltypeid_t
relType
)
const
;
386
const
RelatedEvents
relatedEvents
(
const
RoomEvent
&
evt
,
387
EventRelation
::
reltypeid_t
relType
)
const
;
388
389
const
RoomCreateEvent
*
creation
()
const
;
390
const
RoomTombstoneEvent
*
tombstone
()
const
;
391
392
bool
displayed
()
const
;
393
/// Mark the room as currently displayed to the user
394
/**
395
* Marking the room displayed causes the room to obtain the full
396
* list of members if it's been lazy-loaded before; in the future
397
* it may do more things bound to "screen time" of the room, e.g.
398
* measure that "screen time".
399
*/
400
void
setDisplayed
(
bool
displayed
=
true
);
401
QString
firstDisplayedEventId
()
const
;
402
rev_iter_t
firstDisplayedMarker
()
const
;
403
void
setFirstDisplayedEventId
(
const
QString
&
eventId
);
404
void
setFirstDisplayedEvent
(
TimelineItem
::
index_t
index
);
405
QString
lastDisplayedEventId
()
const
;
406
rev_iter_t
lastDisplayedMarker
()
const
;
407
void
setLastDisplayedEventId
(
const
QString
&
eventId
);
408
void
setLastDisplayedEvent
(
TimelineItem
::
index_t
index
);
409
410
//! \brief Get the latest read receipt from a user
411
//!
412
//! The user id must be valid. A read receipt with an empty event id
413
//! is returned if the user id is valid but there was no read receipt
414
//! from them.
415
//! \sa usersAtEventId
416
ReadReceipt
lastReadReceipt
(
const
QString
&
userId
)
const
;
417
418
//! \brief Get the latest read receipt from the local user
419
//!
420
//! This is a shortcut for <tt>lastReadReceipt(localUserId)</tt>.
421
//! \sa lastReadReceipt
422
ReadReceipt
lastLocalReadReceipt
()
const
;
423
424
//! \brief Find the timeline item the local read receipt is at
425
//!
426
//! This is a shortcut for \code
427
//! room->findInTimeline(room->lastLocalReadReceipt().eventId);
428
//! \endcode
429
rev_iter_t
localReadReceiptMarker
()
const
;
430
431
//! \brief Get the latest event id marked as fully read
432
//!
433
//! This can be either the event id pointed to by the actual latest
434
//! m.fully_read event, or the latest event id marked locally as fully read
435
//! if markMessagesAsRead or markAllMessagesAsRead has been called and
436
//! the homeserver didn't return an updated m.fully_read event yet.
437
//! \sa markMessagesAsRead, markAllMessagesAsRead, fullyReadMarker
438
QString
lastFullyReadEventId
()
const
;
439
440
//! \brief Get the iterator to the latest timeline item marked as fully read
441
//!
442
//! This method calls findInTimeline on the result of lastFullyReadEventId.
443
//! If the fully read marker turns out to be outside the timeline (because
444
//! the event marked as fully read is too far back in the history) the
445
//! returned value will be equal to historyEdge.
446
//!
447
//! Be sure to read the caveats on iterators returned by findInTimeline.
448
//! \sa lastFullyReadEventId, findInTimeline
449
rev_iter_t
fullyReadMarker
()
const
;
450
451
//! \brief Get users whose latest read receipts point to the event
452
//!
453
//! This method is for cases when you need to show users who have read
454
//! an event. Calling it on inexistent or empty event id will return
455
//! an empty set.
456
//! \note The returned list may contain ids resolving to users that are
457
//! not loaded as room members yet (in particular, if members are not
458
//! yet lazy-loaded). For now this merely means that the user's
459
//! room-specific name and avatar will not be there; but generally
460
//! it's recommended to ensure that all room members are loaded
461
//! before operating on the result of this function.
462
//! \sa lastReadReceipt, allMembersLoaded
463
QSet
<
QString
>
userIdsAtEvent
(
const
QString
&
eventId
)
const
;
464
465
//! \brief Mark the event with uptoEventId as fully read
466
//!
467
//! Marks the event with the specified id as fully read locally and also
468
//! sends an update to m.fully_read account data to the server either
469
//! for this message or, if it's from the local user, for
470
//! the nearest non-local message before. uptoEventId must point to a known
471
//! event in the timeline; the method will do nothing if the event is behind
472
//! the current m.fully_read marker or is not loaded, to prevent
473
//! accidentally trying to move the marker back in the timeline.
474
//! \sa markAllMessagesAsRead, fullyReadMarker
475
Q_INVOKABLE
void
markMessagesAsRead
(
const
QString
&
uptoEventId
);
476
477
//! \brief Determine whether an event should be counted as unread
478
//!
479
//! The criteria of including an event in unread counters are described in
480
//! [MSC2654](https://github.com/matrix-org/matrix-doc/pull/2654); according
481
//! to these, the event should be counted as unread (or, in libQuotient
482
//! parlance, is "notable") if it is:
483
//! - either
484
//! - a message event that is not m.notice, or
485
//! - a state event with type being one of:
486
//! `m.room.topic`, `m.room.name`, `m.room.avatar`, `m.room.tombstone`;
487
//! - neither redacted, nor an edit (redactions cause the redacted event
488
//! to stop being notable, while edits are not notable themselves while
489
//! the original event usually is);
490
//! - from a non-local user (events from other devices of the local
491
//! user are not notable).
492
//! \sa partiallyReadStats, unreadStats
493
virtual
bool
isEventNotable
(
const
TimelineItem
&
ti
)
const
;
494
495
//! \brief Get notification details for an event
496
//!
497
//! This allows to get details on the kind of notification that should
498
//! generated for \p evt.
499
Notification
notificationFor
(
const
TimelineItem
&
ti
)
const
;
500
501
//! \brief Get event statistics since the fully read marker
502
//!
503
//! This call returns a structure containing:
504
//! - the number of notable unread events since the fully read marker;
505
//! depending on the fully read marker state with respect to the local
506
//! timeline, this number may be either exact or estimated
507
//! (see EventStats::isEstimate);
508
//! - the number of highlights (TODO).
509
//!
510
//! Note that this is different from the unread count defined by MSC2654
511
//! and from the notification/highlight numbers defined by the spec in that
512
//! it counts events since the fully read marker, not since the last
513
//! read receipt position.
514
//!
515
//! As E2EE is not supported in the library, the returned result will always
516
//! be an estimate (<tt>isEstimate == true</tt>) for encrypted rooms;
517
//! moreover, since the library doesn't know how to tackle push rules yet
518
//! the number of highlights returned here will always be zero (there's no
519
//! good substitute for that now).
520
//!
521
//! \sa isEventNotable, fullyReadMarker, unreadStats, EventStats
522
EventStats
partiallyReadStats
()
const
;
523
524
//! \brief Get event statistics since the last read receipt
525
//!
526
//! This call returns a structure that contains the following three numbers,
527
//! all counted on the timeline segment between the event pointed to by
528
//! the m.fully_read marker and the sync edge:
529
//! - the number of unread events - depending on the read receipt state
530
//! with respect to the local timeline, this number may be either precise
531
//! or estimated (see EventStats::isEstimate);
532
//! - the number of highlights (TODO).
533
//!
534
//! As E2EE is not supported in the library, the returned result will always
535
//! be an estimate (<tt>isEstimate == true</tt>) for encrypted rooms;
536
//! moreover, since the library doesn't know how to tackle push rules yet
537
//! the number of highlights returned here will always be zero - use
538
//! highlightCount() for now.
539
//!
540
//! \sa isEventNotable, lastLocalReadReceipt, partiallyReadStats,
541
//! highlightCount
542
EventStats
unreadStats
()
const
;
543
544
//! \brief Get the number of notifications since the last read receipt
545
//!
546
//! This is the same as <tt>unreadStats().notableCount</tt>.
547
//!
548
//! \sa unreadStats, lastLocalReadReceipt
549
qsizetype
notificationCount
()
const
;
550
551
//! \brief Get the number of highlights since the last read receipt
552
//!
553
//! As of 0.7, this is defined by the homeserver as Quotient doesn't process
554
//! push rules.
555
//!
556
//! \sa unreadStats, lastLocalReadReceipt
557
qsizetype
highlightCount
()
const
;
558
559
/** Check whether the room has account data of the given type
560
* Tags and read markers are not supported by this method _yet_.
561
*/
562
bool
hasAccountData
(
const
QString
&
type
)
const
;
563
564
/** Get a generic account data event of the given type
565
* This returns a generic hash map for any room account data event
566
* stored on the server. Tags and read markers cannot be retrieved
567
* using this method _yet_.
568
*/
569
const
EventPtr
&
accountData
(
const
QString
&
type
)
const
;
570
571
//! Get a list of all room account data events
572
//! \return A list of event types that exist in the room
573
QStringList
accountDataEventTypes
()
const
;
574
575
QStringList
tagNames
()
const
;
576
TagsMap
tags
()
const
;
577
Tag
tag
(
const
QString
&
name
)
const
;
578
579
/** Add a new tag to this room
580
* If this room already has this tag, nothing happens. If it's a new
581
* tag for the room, the respective tag record is added to the set
582
* of tags and the new set is sent to the server to update other
583
* clients.
584
*/
585
void
addTag
(
const
QString
&
name
,
const
Tag
&
tagData
= {});
586
Q_INVOKABLE
void
addTag
(
const
QString
&
name
,
float
order
);
587
588
/// Remove a tag from the room
589
Q_INVOKABLE
void
removeTag
(
const
QString
&
name
);
590
591
/// The scope to apply an action on
592
/*! This enumeration is used to pick a strategy to propagate certain
593
* actions on the room to its predecessors and successors.
594
*/
595
enum
ActionScope
{
596
ThisRoomOnly
,
///< Do not apply to predecessors and successors
597
WithinSameState
,
///< Apply to predecessors and successors in the same
598
///< state as the current one
599
OmitLeftState
,
///< Apply to all reachable predecessors and successors
600
///< except those in Leave state
601
WholeSequence
///< Apply to all reachable predecessors and successors
602
};
603
604
/** Overwrite the room's tags
605
* This completely replaces the existing room's tags with a set
606
* of new ones and updates the new set on the server. Unlike
607
* most other methods in Room, this one sends a signal about changes
608
* immediately, not waiting for confirmation from the server
609
* (because tags are saved in account data rather than in shared
610
* room state).
611
* \param applyOn setting this to Room::OnAllConversations will set tags
612
* on this and all _known_ predecessors and successors;
613
* by default only the current room is changed
614
*/
615
void
setTags
(
TagsMap
newTags
,
ActionScope
applyOn
=
ThisRoomOnly
);
616
617
/// Check whether the list of tags has m.favourite
618
bool
isFavourite
()
const
;
619
/// Check whether the list of tags has m.lowpriority
620
bool
isLowPriority
()
const
;
621
/// Check whether this room is for server notices (MSC1452)
622
bool
isServerNoticeRoom
()
const
;
623
624
/// Check whether this room is a direct chat
625
Q_INVOKABLE
bool
isDirectChat
()
const
;
626
627
/// Get the list of members this room is a direct chat with
628
QList
<
RoomMember
>
directChatMembers
()
const
;
629
630
Q_INVOKABLE
QUrl
makeMediaUrl
(
const
QString
&
eventId
,
631
const
QUrl
&
mxcUrl
)
const
;
632
633
Q_INVOKABLE
QUrl
urlToThumbnail
(
const
QString
&
eventId
)
const
;
634
Q_INVOKABLE
QUrl
urlToDownload
(
const
QString
&
eventId
)
const
;
635
636
/// Get a file name for downloading for a given event id
637
/*!
638
* The event MUST be RoomMessageEvent and have content
639
* for downloading. \sa RoomMessageEvent::hasContent
640
*/
641
Q_INVOKABLE
QString
fileNameToDownload
(
const
QString
&
eventId
)
const
;
642
643
/// Get information on file upload/download
644
/*!
645
* \param id uploads are identified by the corresponding event's
646
* transactionId (because uploads are done before
647
* the event is even sent), while downloads are using
648
* the normal event id for identifier.
649
*/
650
Q_INVOKABLE
Quotient
::
FileTransferInfo
651
fileTransferInfo
(
const
QString
&
id
)
const
;
652
653
/// Get the URL to the actual file source in a unified way
654
/*!
655
* For uploads it will return a URL to a local file; for downloads
656
* the URL will be taken from the corresponding room event.
657
*/
658
Q_INVOKABLE
QUrl
fileSource
(
const
QString
&
id
)
const
;
659
660
/** Pretty-prints plain text into HTML
661
* As of now, it's exactly the same as Quotient::prettyPrint();
662
* in the future, it will also linkify room aliases, mxids etc.
663
* using the room context.
664
*/
665
Q_INVOKABLE
QString
prettyPrint
(
const
QString
&
plainText
)
const
;
666
667
#
if
Quotient_VERSION_MAJOR
==
0
&&
Quotient_VERSION_MINOR
<
10
668
[[
deprecated
(
"Create MemberSorter objects directly instead"
)]]
669
MemberSorter
memberSorter
()
const
;
670
#
endif
671
672
Q_INVOKABLE
bool
supportsCalls
()
const
;
673
674
/// Whether the current user is allowed to upgrade the room
675
Q_INVOKABLE
bool
canSwitchVersions
()
const
;
676
677
/// \brief Get the current room state
678
RoomStateView
currentState
()
const
;
679
680
//! \brief The effective power level of the given member in the room
681
//!
682
//! This is normally the same as calling `RoomPowerLevelEvent::powerLevelForUser(userId)` but
683
//! takes into account the room context and works even if the room state has no power levels
684
//! event. It is THE recommended way to get a room member's power level to display in the UI.
685
//! \param memberId The room member ID to check; if empty, the local user will be checked
686
//! \sa RoomPowerLevelsEvent, https://spec.matrix.org/v1.11/client-server-api/#mroompower_levels
687
Q_INVOKABLE
int
memberEffectivePowerLevel
(
const
QString
&
memberId
= {})
const
;
688
689
//! \brief Get the power level required to send events of the given type
690
//!
691
//! \note This is a generic method that only gets the power level to send events with a given
692
//! type. Some operations have additional restrictions or enablers though: e.g.,
693
//! room member changes (kicks, invites) have special power levels; on the other hand,
694
//! redactions of one's own messages are allowed regardless of the power level. To check
695
//! effective ability to perform an operation, use Room's can*() methods instead of
696
//! comparing the power levels (those are also slightly more efficient).
697
//! \note Unlike the template version below, this method determines at runtime whether an event
698
//! type is that of a state event, assuming unknown event types to be non-state; pass
699
//! `true` as the second parameter to override that.
700
//! \sa canSend, canRedact, canSwitchVersions
701
Q_INVOKABLE
int
powerLevelFor
(
const
QString
&
eventTypeId
,
bool
forceStateEvent
=
false
)
const
;
702
703
//! \brief Get the power level required to send events of the given type
704
//!
705
//! This is an optimised version of non-template powerLevelFor() (with the same caveat about
706
//! operations based on some event types) for cases when the event type is known at build time.
707
//! \tparam EvT the event type to get the power level for
708
template
<
EventClass
EvT
>
709
int
powerLevelFor
()
const
710
{
711
return
currentState
().
get
<
RoomPowerLevelsEvent
>()->
powerLevelForEventType
<
EvT
>();
712
}
713
714
//! \brief Post a pre-created room message event
715
//!
716
//! Takes ownership of the event, deleting it once the matching one arrives with the sync.
717
//! \note Do not assume that the event is already on the road to the homeserver when this (or
718
//! any other `post*`) method returns; it can be queued internally.
719
//! \sa PendingEventItem::deliveryStatus()
720
//! \return a reference to the pending event item
721
const
PendingEventItem
&
post
(
RoomEventPtr
event
);
722
723
template
<
typename
EvT
,
typename
...
ArgTs
>
724
const
PendingEventItem
&
post
(
ArgTs
&&...
args
)
725
{
726
return
post
(
makeEvent
<
EvT
>(
std
::
forward
<
ArgTs
>(
args
)...));
727
}
728
729
QString
postFile
(
const
QString
&
plainText
,
730
std
::
unique_ptr
<
EventContent
::
FileContentBase
>
fileContent
);
731
732
PendingEventItem
::
future_type
whenMessageMerged
(
QString
txnId
)
const
;
733
734
//! Send a request to update the room state with the given event
735
SetRoomStateWithKeyJob
*
setState
(
const
StateEvent
&
evt
);
736
737
//! \brief Set a state event of the given type with the given arguments
738
//!
739
//! This type-safe overload attempts to send a state event of the type \p EvT constructed from
740
//! \p args.
741
template
<
typename
EvT
,
typename
...
ArgTs
>
742
auto
setState
(
ArgTs
&&...
args
)
743
{
744
return
setState
(
EvT
(
std
::
forward
<
ArgTs
>(
args
)...));
745
}
746
747
void
addMegolmSessionFromBackup
(
const
QByteArray
&
sessionId
,
const
QByteArray
&
sessionKey
,
uint32_t
index
,
const
QByteArray
&
senderKey
,
const
QByteArray
&
senderEdKey
);
748
749
Q_INVOKABLE
void
startVerification
();
750
751
QJsonArray
exportMegolmSessions
();
752
753
public
Q_SLOTS
:
754
/** Check whether the room should be upgraded */
755
void
checkVersion
();
756
757
QString
postMessage
(
const
QString
&
plainText
,
MessageEventType
type
);
758
QString
postPlainText
(
const
QString
&
plainText
);
759
QString
postHtmlMessage
(
const
QString
&
plainText
,
const
QString
&
html
,
760
MessageEventType
type
=
MessageEventType
::
Text
);
761
QString
postHtmlText
(
const
QString
&
plainText
,
const
QString
&
html
);
762
/// Send a reaction on a given event with a given key
763
QString
postReaction
(
const
QString
&
eventId
,
const
QString
&
key
);
764
765
/** Post a pre-created room message event
766
*
767
* Takes ownership of the event, deleting it once the matching one
768
* arrives with the sync
769
* \return transaction id associated with the event.
770
*/
771
[[
deprecated
(
"Use post() instead"
)]]
772
QString
postEvent
(
RoomEvent
*
event
);
773
QString
postJson
(
const
QString
&
matrixType
,
const
QJsonObject
&
eventContent
);
774
QString
retryMessage
(
const
QString
&
txnId
);
775
void
discardMessage
(
const
QString
&
txnId
);
776
777
//! Send a request to update the room state based on freeform inputs
778
SetRoomStateWithKeyJob
*
setState
(
const
QString
&
evtType
,
779
const
QString
&
stateKey
,
780
const
QJsonObject
&
contentJson
);
781
void
setName
(
const
QString
&
newName
);
782
void
setCanonicalAlias
(
const
QString
&
newAlias
);
783
void
setPinnedEvents
(
const
QStringList
&
events
);
784
/// Set room aliases on the user's current server
785
void
setLocalAliases
(
const
QStringList
&
aliases
);
786
void
setTopic
(
const
QString
&
newTopic
);
787
788
/// You shouldn't normally call this method; it's here for debugging
789
void
refreshDisplayName
();
790
791
JobHandle
<
GetRoomEventsJob
>
getPreviousContent
(
int
limit
= 10,
const
QString
&
filter
= {});
792
793
void
inviteToRoom
(
const
QString
&
memberId
);
794
JobHandle
<
LeaveRoomJob
>
leaveRoom
();
795
void
kickMember
(
const
QString
&
memberId
,
const
QString
&
reason
= {});
796
void
ban
(
const
QString
&
userId
,
const
QString
&
reason
= {});
797
void
unban
(
const
QString
&
userId
);
798
void
redactEvent
(
const
QString
&
eventId
,
const
QString
&
reason
= {});
799
800
void
uploadFile
(
const
QString
&
id
,
const
QUrl
&
localFilename
,
801
const
QString
&
overrideContentType
= {});
802
// If localFilename is empty a temporary file is created
803
void
downloadFile
(
const
QString
&
eventId
,
const
QUrl
&
localFilename
= {});
804
void
cancelFileTransfer
(
const
QString
&
id
);
805
806
//! \brief Set a given event as last read and post a read receipt on it
807
//!
808
//! Does nothing if the event is behind the current read receipt.
809
//! \sa lastReadReceipt, markMessagesAsRead, markAllMessagesAsRead
810
void
setReadReceipt
(
const
QString
&
atEventId
);
811
//! Put the fully-read marker at the latest message in the room
812
void
markAllMessagesAsRead
();
813
814
/// Switch the room's version (aka upgrade)
815
void
switchVersion
(
QString
newVersion
);
816
817
void
inviteCall
(
const
QString
&
callId
,
const
int
lifetime
,
818
const
QString
&
sdp
);
819
void
sendCallCandidates
(
const
QString
&
callId
,
const
QJsonArray
&
candidates
);
820
void
answerCall
(
const
QString
&
callId
,
const
QString
&
sdp
);
821
void
hangupCall
(
const
QString
&
callId
);
822
823
/**
824
* Activates encryption for this room.
825
* Warning: Cannot be undone
826
*/
827
void
activateEncryption
();
828
829
Q_SIGNALS
:
830
/// Initial set of state events has been loaded
831
/**
832
* The initial set is what comes from the initial sync for the room.
833
* This includes all basic things like RoomCreateEvent,
834
* RoomNameEvent, a (lazy-loaded, not full) set of RoomMemberEvents
835
* etc. This is a per-room reflection of Connection::loadedRoomState
836
* \sa Connection::loadedRoomState
837
*/
838
void
baseStateLoaded
();
839
void
eventsHistoryJobChanged
();
840
void
aboutToAddHistoricalMessages
(
Quotient
::
RoomEventsRange
events
);
841
void
aboutToAddNewMessages
(
Quotient
::
RoomEventsRange
events
);
842
void
addedMessages
(
int
fromIndex
,
int
toIndex
);
843
/// The event is about to be appended to the list of pending events
844
void
pendingEventAboutToAdd
(
Quotient
::
RoomEvent
*
event
);
845
/// An event has been appended to the list of pending events
846
void
pendingEventAdded
(
const
Quotient
::
RoomEvent
*
event
);
847
/// The remote echo has arrived with the sync and will be merged
848
/// with its local counterpart
849
/** NB: Requires a sync loop to be emitted */
850
void
pendingEventAboutToMerge
(
Quotient
::
RoomEvent
*
serverEvent
,
851
int
pendingEventIndex
);
852
/// The remote and local copies of the event have been merged
853
/** NB: Requires a sync loop to be emitted */
854
void
pendingEventMerged
();
855
/// An event will be removed from the list of pending events
856
void
pendingEventAboutToDiscard
(
int
pendingEventIndex
);
857
/// An event has just been removed from the list of pending events
858
void
pendingEventDiscarded
();
859
/// The status of a pending event has changed
860
/** \sa PendingEventItem::deliveryStatus */
861
void
pendingEventChanged
(
int
pendingEventIndex
);
862
/// The server accepted the message
863
/** This is emitted when an event sending request has successfully
864
* completed. This does not mean that the event is already in the
865
* local timeline, only that the server has accepted it.
866
* \param txnId transaction id assigned by the client during sending
867
* \param eventId event id assigned by the server upon acceptance
868
* \sa postEvent, postPlainText, postMessage, postHtmlMessage
869
* \sa pendingEventMerged, aboutToAddNewMessages
870
*/
871
void
messageSent
(
QString
txnId
,
QString
eventId
);
872
873
/** A common signal for various kinds of changes in the room
874
* Aside from all changes in the room state
875
* @param changes a set of flags describing what changes occurred
876
* upon the last sync
877
* \sa Changes
878
*/
879
void
changed
(
Quotient
::
Room
::
Changes
changes
);
880
/**
881
* \brief The room name, the canonical alias or other aliases changed
882
*
883
* Not triggered when display name changes.
884
*/
885
void
namesChanged
(
Quotient
::
Room
*
room
);
886
void
displaynameAboutToChange
(
Quotient
::
Room
*
room
);
887
void
displaynameChanged
(
Quotient
::
Room
*
room
,
QString
oldName
);
888
void
pinnedEventsChanged
();
889
void
topicChanged
();
890
void
avatarChanged
();
891
892
//! \brief A new member has joined the room
893
//!
894
//! This can be from any previous state or a member previously unknown to
895
//! the room.
896
void
memberJoined
(
RoomMember
member
);
897
898
//! \brief A member who previously joined has left
899
//!
900
//! The member will still be known to the room their membership state has changed
901
//! from Membership::Join to anything else.
902
void
memberLeft
(
RoomMember
member
);
903
904
//! A known joined member is about to update their display name
905
void
memberNameAboutToUpdate
(
RoomMember
member
,
QString
newName
);
906
907
//! A known joined member has updated their display name
908
void
memberNameUpdated
(
RoomMember
member
);
909
910
//! A known joined member has updated their avatar
911
void
memberAvatarUpdated
(
RoomMember
member
);
912
913
/// The list of members has changed
914
/** Emitted no more than once per sync, this is a good signal to
915
* for cases when some action should be done upon any change in
916
* the member list. If you need per-item granularity you should use
917
* userAdded, userRemoved and memberAboutToRename / memberRenamed
918
* instead.
919
*/
920
void
memberListChanged
();
921
922
/// The previously lazy-loaded members list is now loaded entirely
923
/// \sa setDisplayed
924
void
allMembersLoaded
();
925
void
encryption
();
926
927
void
joinStateChanged
(
Quotient
::
JoinState
oldState
,
928
Quotient
::
JoinState
newState
);
929
930
//! The list of members sending typing indicators has changed.
931
void
typingChanged
();
932
933
void
highlightCountChanged
();
///< \sa highlightCount
934
void
notificationCountChanged
();
///< \sa notificationCount
935
936
void
displayedChanged
(
bool
displayed
);
937
void
firstDisplayedEventChanged
();
938
void
lastDisplayedEventChanged
();
939
//! The event the m.read receipt points to has changed for the listed users
940
//! \sa lastReadReceipt
941
void
lastReadEventChanged
(
QVector
<
QString
>
userIds
);
942
void
fullyReadMarkerMoved
(
QString
fromEventId
,
QString
toEventId
);
943
void
partiallyReadStatsChanged
();
944
void
unreadStatsChanged
();
945
void
allHistoryLoadedChanged
();
946
947
void
accountDataAboutToChange
(
QString
type
);
948
void
accountDataChanged
(
QString
type
);
949
void
tagsAboutToChange
();
950
void
tagsChanged
();
951
952
void
updatedEvent
(
QString
eventId
);
953
void
replacedEvent
(
const
Quotient
::
RoomEvent
*
newEvent
,
954
const
Quotient
::
RoomEvent
*
oldEvent
);
955
956
void
newFileTransfer
(
QString
id
,
QUrl
localFile
);
957
void
fileTransferProgress
(
QString
id
,
qint64
progress
,
qint64
total
);
958
void
fileTransferCompleted
(
QString
id
,
QUrl
localFile
,
959
FileSourceInfo
fileMetadata
);
960
void
fileTransferFailed
(
QString
id
,
QString
errorMessage
= {});
961
// fileTransferCancelled() is no more here; use fileTransferFailed() and
962
// check the transfer status instead
963
964
void
callEvent
(
Quotient
::
Room
*
room
,
const
Quotient
::
RoomEvent
*
event
);
965
966
/// The room's version stability may have changed
967
void
stabilityUpdated
(
QString
recommendedDefault
,
968
QStringList
stableVersions
);
969
/// This room has been upgraded and won't receive updates any more
970
void
upgraded
(
QString
serverMessage
,
Quotient
::
Room
*
successor
);
971
/// An attempted room upgrade has failed
972
void
upgradeFailed
(
QString
errorMessage
);
973
974
/// The room is about to be deleted
975
void
beforeDestruction
(
Quotient
::
Room
*);
976
977
protected
:
978
virtual
Changes
processStateEvent
(
const
RoomEvent
&
e
);
979
virtual
Changes
processEphemeralEvent
(
EventPtr
&&
event
);
980
virtual
Changes
processAccountDataEvent
(
EventPtr
&&
event
);
981
virtual
void
onAddNewTimelineEvents
(
timeline_iter_t
/*from*/
) {}
982
virtual
void
onAddHistoricalTimelineEvents
(
rev_iter_t
/*from*/
) {}
983
virtual
void
onRedaction
(
const
RoomEvent
&
/*prevEvent*/
,
984
const
RoomEvent
&
/*after*/
)
985
{}
986
virtual
QJsonObject
toJson
()
const
;
987
virtual
void
updateData
(
SyncRoomData
&&
data
,
bool
fromCache
=
false
);
988
virtual
Notification
checkForNotifications
(
const
TimelineItem
&
ti
);
989
990
private
:
991
friend
class
Connection
;
992
993
class
Private
;
994
Private
*
d
;
995
996
// This is called from Connection, reflecting a state change that
997
// arrived from the server. Clients should use
998
// Connection::joinRoom() and Room::leaveRoom() to change the state.
999
void
setJoinState
(
JoinState
state
);
1000
};
1001
1002
template
<
template
<
class
>
class
ContT>
1003
inline
typename
ContT<RoomMember>::
size_type
lowerBoundMemberIndex
(
const
ContT<RoomMember>& c,
1004
const
auto
& v,
1005
MemberSorter ms = {})
1006
{
1007
return
std::ranges::lower_bound(c, v, ms) - c.begin();
1008
}
1009
1010
template
<
template
<
class
>
class
ContT>
1011
inline
typename
ContT
<
QString
>::
size_type
lowerBoundMemberIndex
(
const
ContT<QString>& c,
1012
const
auto
& v,
const
Room* r,
1013
MemberSorter ms = {})
1014
{
1015
return
std::ranges::lower_bound(c, v, ms, std::bind_front(&Room::member, r)) - c.begin();
1016
}
1017
1018
}
// namespace Quotient
1019
Q_DECLARE_METATYPE
(
Quotient
::
FileTransferInfo
)
1020
Q_DECLARE_METATYPE(Quotient::ReadReceipt)
1021
Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::Room::Changes)
Quotient::FileTransferInfo
Definition
room.h:53
Quotient::ReadReceipt
Data structure for a room member's read receipt.
Definition
room.h:81
Quotient::Room
Definition
room.h:118
Quotient
Definition
accountregistry.h:13
Quotient::swap
void swap(ReadReceipt &lhs, ReadReceipt &rhs)
Definition
room.h:98
Quotient::lowerBoundMemberIndex
ContT< QString >::size_type lowerBoundMemberIndex(const ContT< QString > &c, const auto &v, const Room *r, MemberSorter ms={})
Definition
room.h:1011
Quotient::lowerBoundMemberIndex
ContT< RoomMember >::size_type lowerBoundMemberIndex(const ContT< RoomMember > &c, const auto &v, MemberSorter ms={})
Definition
room.h:1003
QUO_DECLARE_FLAGS
#define QUO_DECLARE_FLAGS(Flags, Enum)
Quotient replacement for the Q_FLAG/Q_DECLARE_FLAGS combination.
Definition
quotient_common.h:29
QUOTIENT_API
#define QUOTIENT_API
Definition
quotient_export.h:22
Quotient::Notification
Definition
room.h:107
Quotient::Notification::Type
Type
Definition
room.h:108
Quotient::Notification::None
@ None
Definition
room.h:108
Quotient::Notification::Highlight
@ Highlight
Definition
room.h:108
Quotient::Notification::Basic
@ Basic
Definition
room.h:108
Quotient
room.h
Generated by
1.9.8