Chatterino
SignalVector.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <QStandardItemModel>
4 #include <QTimer>
5 #include <boost/noncopyable.hpp>
6 #include <pajlada/signals/signal.hpp>
7 #include <vector>
8 
10 
11 namespace chatterino {
12 
13 template <typename T>
15  const T &item;
16  int index;
17  void *caller;
18 };
19 
20 template <typename T>
21 class SignalVector : boost::noncopyable
22 {
23 public:
24  pajlada::Signals::Signal<SignalVectorItemEvent<T>> itemInserted;
25  pajlada::Signals::Signal<SignalVectorItemEvent<T>> itemRemoved;
26  pajlada::Signals::NoArgSignal delayedItemsChanged;
27 
29  : readOnly_(new std::vector<T>())
30  {
31  QObject::connect(&this->itemsChangedTimer_, &QTimer::timeout, [this] {
32  this->delayedItemsChanged.invoke();
33  });
34  this->itemsChangedTimer_.setInterval(100);
35  this->itemsChangedTimer_.setSingleShot(true);
36  }
37 
38  SignalVector(std::function<bool(const T &, const T &)> &&compare)
39  : SignalVector()
40  {
41  this->itemCompare_ = std::move(compare);
42  }
43 
44  bool isSorted() const
45  {
46  return bool(this->itemCompare_);
47  }
48 
50  std::shared_ptr<const std::vector<T>> readOnly()
51  {
52  return this->readOnly_;
53  }
54 
65  int insert(const T &item, int index = -1, void *caller = nullptr)
66  {
67  assertInGuiThread();
68 
69  if (this->isSorted())
70  {
71  auto it = std::lower_bound(this->items_.begin(), this->items_.end(),
72  item, this->itemCompare_);
73  index = it - this->items_.begin();
74  this->items_.insert(it, item);
75  }
76  else
77  {
78  if (index == -1)
79  {
80  index = this->items_.size();
81  }
82  else
83  {
84  assert(index >= 0 && index <= this->items_.size());
85  }
86 
87  this->items_.insert(this->items_.begin() + index, item);
88  }
89 
91  this->itemInserted.invoke(args);
92  this->itemsChanged_();
93 
94  return index;
95  }
96 
104  int append(const T &item, void *caller = nullptr)
105  {
106  assertInGuiThread();
107  return this->insert(item, -1, caller);
108  }
109 
110  void removeAt(int index, void *caller = nullptr)
111  {
112  assertInGuiThread();
113  assert(index >= 0 && index < int(this->items_.size()));
114 
115  T item = this->items_[index];
116  this->items_.erase(this->items_.begin() + index);
117 
119  this->itemRemoved.invoke(args);
120 
121  this->itemsChanged_();
122  }
123 
124  const std::vector<T> &raw() const
125  {
126  assertInGuiThread();
127 
128  return this->items_;
129  }
130 
131  [[deprecated]] std::vector<T> cloneVector()
132  {
133  return *this->readOnly();
134  }
135 
136  // mirror vector functions
137  auto begin() const
138  {
139  assertInGuiThread();
140  return this->items_.begin();
141  }
142 
143  auto end() const
144  {
145  assertInGuiThread();
146  return this->items_.end();
147  }
148 
149  decltype(auto) operator[](size_t index)
150  {
151  assertInGuiThread();
152  return this->items[index];
153  }
154 
155  auto empty()
156  {
157  assertInGuiThread();
158  return this->items_.empty();
159  }
160 
161 private:
162  void itemsChanged_()
163  {
164  // emit delayed event
165  if (!this->itemsChangedTimer_.isActive())
166  {
167  this->itemsChangedTimer_.start();
168  }
169 
170  // update concurrent version
171  this->readOnly_ = std::make_shared<const std::vector<T>>(this->items_);
172  }
173 
174  std::vector<T> items_;
175  std::shared_ptr<const std::vector<T>> readOnly_;
176  QTimer itemsChangedTimer_;
177  std::function<bool(const T &, const T &)> itemCompare_;
178 };
179 
180 } // namespace chatterino
Definition: SignalVector.hpp:21
int index
Definition: SignalVector.hpp:16
pajlada::Signals::Signal< SignalVectorItemEvent< T > > itemInserted
Definition: SignalVector.hpp:24
Definition: SeventvEventAPISubscription.hpp:67
pajlada::Signals::Signal< SignalVectorItemEvent< T > > itemRemoved
Definition: SignalVector.hpp:25
Definition: Application.cpp:48
SignalVector(std::function< bool(const T &, const T &)> &&compare)
Definition: SignalVector.hpp:38
pajlada::Signals::NoArgSignal delayedItemsChanged
Definition: SignalVector.hpp:26
void removeAt(int index, void *caller=nullptr)
Definition: SignalVector.hpp:110
auto begin() const
Definition: SignalVector.hpp:137
const std::vector< T > & raw() const
Definition: SignalVector.hpp:124
void * caller
Definition: SignalVector.hpp:17
SignalVector()
Definition: SignalVector.hpp:28
std::shared_ptr< const std::vector< T > > readOnly()
A read-only version of the vector which can be used concurrently.
Definition: SignalVector.hpp:50
int append(const T &item, void *caller=nullptr)
Definition: SignalVector.hpp:104
std::vector< T > cloneVector()
Definition: SignalVector.hpp:131
Definition: SignalVector.hpp:14
auto end() const
Definition: SignalVector.hpp:143
const T & item
Definition: SignalVector.hpp:15
auto empty()
Definition: SignalVector.hpp:155
bool isSorted() const
Definition: SignalVector.hpp:44
int insert(const T &item, int index=-1, void *caller=nullptr)
Definition: SignalVector.hpp:65