#pragma once #include #include #include #include #include #include "util/assertinguithread.hpp" namespace chatterino { namespace util { template class ReadOnlySignalVector : boost::noncopyable { public: ReadOnlySignalVector() { QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, [this] { this->delayedItemsChanged.invoke(); }); } virtual ~ReadOnlySignalVector() = default; struct ItemArgs { const TVectorItem &item; int index; void *caller; }; pajlada::Signals::Signal itemInserted; pajlada::Signals::Signal itemRemoved; pajlada::Signals::NoArgSignal delayedItemsChanged; const std::vector &getVector() const { util::assertInGuiThread(); return this->vector; } void invokeDelayedItemsChanged() { util::assertInGuiThread(); if (!this->itemsChangedTimer.isActive()) { itemsChangedTimer.start(); } } protected: std::vector vector; QTimer itemsChangedTimer; }; template class BaseSignalVector : public ReadOnlySignalVector { public: virtual void appendItem(const TVectorItem &item, void *caller = 0) = 0; void removeItem(int index, void *caller = 0) { util::assertInGuiThread(); assert(index >= 0 && index < this->vector.size()); TVectorItem item = this->vector[index]; this->vector.erase(this->vector.begin() + index); ItemArgs args{item, args, caller}; this->itemRemoved.invoke(args); } }; template class UnsortedSignalVector : public BaseSignalVector { public: void insertItem(const TVectorItem &item, int index, void *caller = 0) { util::assertInGuiThread(); assert(index >= 0 && index <= this->vector.size()); this->vector.insert(this->vector.begin() + index, item); ItemArgs args{item, index, caller}; this->itemInserted.invoke(args); } virtual void appendItem(const TVectorItem &item, void *caller = 0) override { this->insertItem(item, this->vector.size(), caller); } }; template class SortedSignalVector : public BaseSignalVector { public: virtual void appendItem(const TVectorItem &item, void *caller = 0) override { util::assertInGuiThread(); int index = this->vector.insert( std::lower_bound(this->vector.begin(), this->vector.end(), item), item) - this->vector.begin(); ItemArgs args{item, index, caller}; this->itemInserted.invoke(args); } }; } // namespace util } // namespace chatterino