libQuotient
A Qt library for building matrix clients
eventstats.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Quotient contributors
2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 
4 #pragma once
5 
6 #include "room.h"
7 
8 namespace Quotient {
9 
10 //! \brief Counters of unread events and highlights with a precision flag
11 //!
12 //! This structure contains a static snapshot with values of unread counters
13 //! returned by Room::partiallyReadStats and Room::unreadStats (properties
14 //! or methods).
15 //!
16 //! \note It's just a simple grouping of counters and is not automatically
17 //! updated from the room as subsequent syncs arrive.
18 //! \sa Room::unreadStats, Room::partiallyReadStats, Room::isEventNotable
19 struct QUOTIENT_API EventStats {
20  Q_GADGET
21  Q_PROPERTY(qsizetype notableCount MEMBER notableCount CONSTANT)
22  Q_PROPERTY(qsizetype highlightCount MEMBER highlightCount CONSTANT)
23  Q_PROPERTY(bool isEstimate MEMBER isEstimate CONSTANT)
24 public:
25  //! The number of "notable" events in an events range
26  //! \sa Room::isEventNotable
27  qsizetype notableCount = 0;
28  qsizetype highlightCount = 0;
29  //! \brief Whether the counter values above are exact
30  //!
31  //! This is false when the end marker (m.read receipt or m.fully_read) used
32  //! to collect the stats points to an event loaded locally and the counters
33  //! can therefore be calculated exactly using the locally available segment
34  //! of the timeline; true when the marker points to an event outside of
35  //! the local timeline (in which case the estimation is made basing on
36  //! the data supplied by the homeserver as well as counters saved from
37  //! the previous run of the client).
38  bool isEstimate = true;
39 
40  // TODO: replace with = default once C++20 becomes a requirement on clients
41  bool operator==(const EventStats& rhs) const
42  {
43  return notableCount == rhs.notableCount
44  && highlightCount == rhs.highlightCount
45  && isEstimate == rhs.isEstimate;
46  }
47  bool operator!=(const EventStats& rhs) const { return !operator==(rhs); }
48 
49  //! \brief Check whether the event statistics are empty
50  //!
51  //! Empty statistics have notable and highlight counters of zero and
52  //! isEstimate set to false.
53  Q_INVOKABLE bool empty() const
54  {
55  return notableCount == 0 && !isEstimate && highlightCount == 0;
56  }
57 
58  using marker_t = Room::rev_iter_t;
59 
60  //! \brief Build event statistics on a range of events
61  //!
62  //! This is a factory that returns an EventStats instance with counts of
63  //! notable and highlighted events between \p from and \p to reverse
64  //! timeline iterators; the \p init parameter allows to override
65  //! the initial statistics object and start from other values.
66  static EventStats fromRange(const Room* room, const marker_t& from,
67  const marker_t& to,
68  const EventStats& init = { 0, 0, false });
69 
70  //! \brief Build event statistics on a range from sync edge to marker
71  //!
72  //! This is mainly a shortcut for \code
73  //! <tt>fromRange(room, marker_t(room->syncEdge()), marker)</tt>
74  //! \endcode except that it also sets isEstimate to true if (and only if)
75  //! <tt>to == room->historyEdge()</tt>.
76  static EventStats fromMarker(const Room* room, const marker_t& marker);
77 
78  //! \brief Loads a statistics object from the cached counters
79  //!
80  //! Sets isEstimate to `true` unless both notableCount and highlightCount
81  //! are equal to -1.
82  static EventStats fromCachedCounters(std::optional<int> notableCount,
83  std::optional<int> highlightCount = {});
84 
85  //! \brief Update statistics when a read marker moves down the timeline
86  //!
87  //! Removes events between oldMarker and newMarker from statistics
88  //! calculation if \p oldMarker points to an existing event in the timeline,
89  //! or recalculates the statistics entirely if \p oldMarker points
90  //! to <tt>room->historyEdge()</tt>. Always results in exact statistics
91  //! (<tt>isEstimate == false</tt>.
92  //! \param oldMarker Must point correspond to the _current_ statistics
93  //! isEstimate state, i.e. it should point to
94  //! <tt>room->historyEdge()</tt> if <tt>isEstimate == true</tt>, or
95  //! to a valid position within the timeline otherwise
96  //! \param newMarker Must point to a valid position in the timeline (not to
97  //! <tt>room->historyEdge()</tt> that is equal to or closer to
98  //! the sync edge than \p oldMarker
99  //! \return true if either notableCount or highlightCount changed, or if
100  //! the statistics was completely recalculated; false otherwise
101  bool updateOnMarkerMove(const Room* room, const marker_t& oldMarker,
102  const marker_t& newMarker);
103 
104  //! \brief Validate the statistics object against the given marker
105  //!
106  //! Checks whether the statistics object data are valid for a given marker.
107  //! No stats recalculation takes place, only isEstimate and zero-ness
108  //! of notableCount are checked.
109  bool isValidFor(const Room* room, const marker_t& marker) const;
110 };
111 
112 QUOTIENT_API QDebug operator<<(QDebug dbg, const EventStats& es);
113 
114 }