added limited queue

This commit is contained in:
fourtf
2017-02-02 20:35:12 +01:00
parent 5390272279
commit 93660233fd
10 changed files with 191 additions and 46 deletions
+8 -14
View File
@@ -128,23 +128,17 @@ Channel::reloadFfzEmotes()
}); });
} }
QVector<std::shared_ptr<messages::Message>>
Channel::getMessagesClone()
{
this->messageMutex.lock();
QVector<std::shared_ptr<messages::Message>> M(this->messages);
M.detach();
this->messageMutex.unlock();
return M;
}
void void
Channel::addMessage(std::shared_ptr<messages::Message> message) Channel::addMessage(std::shared_ptr<messages::Message> message)
{ {
this->messageMutex.lock(); std::shared_ptr<messages::Message> deleted;
this->messages.append(message);
this->messageMutex.unlock();
Windows::repaintVisibleChatWidgets(); if (this->messages.appendItem(message, deleted)) {
this->messageRemovedFromStart(deleted);
}
this->messageAppended(message);
Windows::repaintVisibleChatWidgets(this);
} }
} }
+15 -10
View File
@@ -3,11 +3,13 @@
#include "concurrentmap.h" #include "concurrentmap.h"
#include "messages/lazyloadedimage.h" #include "messages/lazyloadedimage.h"
#include "messages/limitedqueue.h"
#include <QMap> #include <QMap>
#include <QMutex> #include <QMutex>
#include <QString> #include <QString>
#include <QVector> #include <QVector>
#include <boost/signals2.hpp>
#include <memory> #include <memory>
namespace chatterino { namespace chatterino {
@@ -20,6 +22,11 @@ class Channel
public: public:
Channel(const QString &channel); Channel(const QString &channel);
boost::signals2::signal<void(std::shared_ptr<messages::Message> &)>
messageRemovedFromStart;
boost::signals2::signal<void(std::shared_ptr<messages::Message> &)>
messageAppended;
// properties // properties
ConcurrentMap<QString, messages::LazyLoadedImage *> & ConcurrentMap<QString, messages::LazyLoadedImage *> &
getBttvChannelEmotes() getBttvChannelEmotes()
@@ -95,25 +102,23 @@ public:
} }
// methods // methods
void addMessage(std::shared_ptr<messages::Message> message); messages::LimitedQueueSnapshot<std::shared_ptr<messages::Message>>
getMessageSnapshot()
QVector<std::shared_ptr<messages::Message>> getMessagesClone();
QVector<std::shared_ptr<messages::Message>> &
getMessages()
{ {
return messages; return messages.getSnapshot();
} }
void addMessage(std::shared_ptr<messages::Message> message);
void void
reloadChannelEmotes() reloadChannelEmotes()
{ {
reloadBttvEmotes(); this->reloadBttvEmotes();
reloadFfzEmotes(); this->reloadFfzEmotes();
} }
private: private:
QVector<std::shared_ptr<messages::Message>> messages; messages::LimitedQueue<std::shared_ptr<messages::Message>> messages;
QString name; QString name;
int roomID; int roomID;
+3 -1
View File
@@ -95,7 +95,9 @@ HEADERS += account.h \
windows.h \ windows.h \
widgets/resizingtextedit.h \ widgets/resizingtextedit.h \
settingssnapshot.h \ settingssnapshot.h \
logging.h logging.h \
messages/limitedqueue.h \
messages/limitedqueuesnapshot.h
PRECOMPILED_HEADER = PRECOMPILED_HEADER =
+97
View File
@@ -0,0 +1,97 @@
#ifndef LIMITEDQUEUE_H
#define LIMITEDQUEUE_H
#include "messages/limitedqueuesnapshot.h"
#include <boost/signals2.hpp>
#include <memory>
#include <mutex>
#include <vector>
namespace chatterino {
namespace messages {
template <typename T>
class LimitedQueue
{
public:
LimitedQueue(int limit = 10, int buffer = 5)
: vector(new std::vector<T>(limit + buffer))
, vectorPtr(this->vector)
, mutex()
, offset(0)
, length(0)
, limit(limit)
, buffer(buffer)
{
;
}
// return true if an item was deleted
// deleted will be set if the item was deleted
bool
appendItem(const T &item, T &deleted)
{
std::lock_guard<std::mutex> lock(this->mutex);
if (this->length == this->limit) {
// vector is full
if (this->offset == this->buffer) {
deleted = this->vector->at(this->offset);
// create new vector
auto *vector = new std::vector<T>(this->limit + this->buffer);
for (int i = 0; i < this->limit; i++) {
vector->at(i) = this->vector->at(i + this->offset);
}
vector->at(limit - 1) = item;
this->offset = 0;
this->vector = vector;
this->vectorPtr = std::shared_ptr<std::vector<T>>(vector);
return true;
} else {
// append item and remove first
deleted = this->vector->at(this->offset);
this->vector->at(this->length + this->offset) = item;
this->offset++;
return true;
}
} else {
// append item
this->vector->at(this->length) = item;
this->length++;
return false;
}
}
messages::LimitedQueueSnapshot<T>
getSnapshot()
{
std::lock_guard<std::mutex> lock(mutex);
return LimitedQueueSnapshot<T>(vectorPtr, offset, length);
}
private:
std::vector<T> *vector;
std::shared_ptr<std::vector<T>> vectorPtr;
std::mutex mutex;
int offset;
int length;
int limit;
int buffer;
};
}
}
#endif // LIMITEDQUEUE_H
+48
View File
@@ -0,0 +1,48 @@
#ifndef LIMITEDQUEUESNAPSHOT_H
#define LIMITEDQUEUESNAPSHOT_H
#include <cassert>
#include <memory>
#include <vector>
namespace chatterino {
namespace messages {
template <typename T>
class LimitedQueueSnapshot
{
public:
LimitedQueueSnapshot(std::shared_ptr<std::vector<T>> ptr, int offset,
int length)
: vectorPtr(ptr)
, vector(ptr.get())
, offset(offset)
, length(length)
{
}
int
getLength()
{
return length;
}
T const &operator[](int index) const
{
assert(index >= 0);
assert(index < length);
return vector->at(index + offset);
}
private:
std::shared_ptr<std::vector<T>> vectorPtr;
std::vector<T> *vector;
int offset;
int length;
};
}
}
#endif // LIMITEDQUEUESNAPSHOT_H
+1 -1
View File
@@ -16,7 +16,7 @@ class Message
{ {
public: public:
Message(const QString &text); Message(const QString &text);
Message(const IrcPrivateMessage &ircMessage, Channel &Channel, Message(const IrcPrivateMessage &ircMessage, Channel &channel,
bool enablePingSound = true, bool isReceivedWhisper = false, bool enablePingSound = true, bool isReceivedWhisper = false,
bool isSentWhisper = false, bool includeChannel = false); bool isSentWhisper = false, bool includeChannel = false);
+12 -10
View File
@@ -47,17 +47,19 @@ ChatWidgetView::layoutMessages()
bool showScrollbar = false; bool showScrollbar = false;
auto messages = c->getMessagesClone(); auto messages = c->getMessageSnapshot();
bool redraw = false; bool redraw = false;
for (std::shared_ptr<messages::Message> &message : messages) { // for (std::shared_ptr<messages::Message> &message : messages) {
redraw |= message.get()->layout(this->width(), true); // redraw |= message.get()->layout(this->width(), true);
} // }
redraw = true;
int h = this->height() - 8; int h = this->height() - 8;
for (int i = messages.size() - 1; i >= 0; i--) { for (int i = messages.getLength() - 1; i >= 0; i--) {
auto *message = messages[i].get(); auto *message = messages[i].get();
message->layout(this->width(), true); message->layout(this->width(), true);
@@ -65,7 +67,7 @@ ChatWidgetView::layoutMessages()
h -= message->getHeight(); h -= message->getHeight();
if (h < 0) { if (h < 0) {
this->scrollbar.setLargeChange((messages.size() - i) + this->scrollbar.setLargeChange((messages.getLength() - i) +
(qreal)h / message->getHeight()); (qreal)h / message->getHeight());
this->scrollbar.setDesiredValue(this->scrollbar.getDesiredValue()); this->scrollbar.setDesiredValue(this->scrollbar.getDesiredValue());
@@ -76,7 +78,7 @@ ChatWidgetView::layoutMessages()
this->scrollbar.setVisible(showScrollbar); this->scrollbar.setVisible(showScrollbar);
this->scrollbar.setMaximum(c->getMessages().size()); this->scrollbar.setMaximum(messages.getLength());
return redraw; return redraw;
} }
@@ -138,18 +140,18 @@ ChatWidgetView::paintEvent(QPaintEvent *)
if (c == NULL) if (c == NULL)
return; return;
auto messages = c->getMessagesClone(); auto messages = c->getMessageSnapshot();
int start = this->scrollbar.getCurrentValue(); int start = this->scrollbar.getCurrentValue();
if (start >= messages.length()) { if (start >= messages.getLength()) {
return; return;
} }
int y = -(messages[start].get()->getHeight() * int y = -(messages[start].get()->getHeight() *
(fmod(this->scrollbar.getCurrentValue(), 1))); (fmod(this->scrollbar.getCurrentValue(), 1)));
for (int i = start; i < messages.size(); ++i) { for (int i = start; i < messages.getLength(); ++i) {
messages::Message *message = messages[i].get(); messages::Message *message = messages[i].get();
for (messages::WordPart const &wordPart : message->getWordParts()) { for (messages::WordPart const &wordPart : message->getWordParts()) {
-4
View File
@@ -133,12 +133,8 @@ Notebook::tabAt(QPoint point, int &index)
void void
Notebook::rearrangePage(NotebookPage *page, int index) Notebook::rearrangePage(NotebookPage *page, int index)
{ {
int i1 = pages.indexOf(page);
pages.move(pages.indexOf(page), index); pages.move(pages.indexOf(page), index);
int i2 = pages.indexOf(page);
performLayout(); performLayout();
} }
+5 -4
View File
@@ -28,10 +28,11 @@ ScrollBar::ScrollBar(QWidget *widget)
, currentValueChanged() , currentValueChanged()
, currentValue() , currentValue()
{ {
resize(16, 100); this->resize(16, 100);
currentValueAnimation.setDuration(300); this->currentValueAnimation.setDuration(300);
currentValueAnimation.setEasingCurve(QEasingCurve(QEasingCurve::OutCubic)); this->currentValueAnimation.setEasingCurve(
QEasingCurve(QEasingCurve::OutCubic));
this->setMouseTracking(true); this->setMouseTracking(true);
} }
@@ -211,7 +212,7 @@ ScrollBar::updateScroll()
this->thumbRect = this->thumbRect =
QRect(0, QRect(0,
(int)(this->desiredValue / this->maximum * this->trackHeight) + (int)(this->currentValue / this->maximum * this->trackHeight) +
1 + this->buttonHeight, 1 + this->buttonHeight,
width(), width(),
(int)(this->largeChange / this->maximum * this->trackHeight) + (int)(this->largeChange / this->maximum * this->trackHeight) +
+2 -2
View File
@@ -63,8 +63,6 @@ public:
value = std::max(this->minimum, value = std::max(this->minimum,
std::min(this->maximum - this->largeChange, value)); std::min(this->maximum - this->largeChange, value));
this->desiredValue = value;
if (this->desiredValue != value) { if (this->desiredValue != value) {
if (animated) { if (animated) {
this->currentValueAnimation.stop(); this->currentValueAnimation.stop();
@@ -78,6 +76,8 @@ public:
this->setCurrentValue(value); this->setCurrentValue(value);
} }
} }
this->desiredValue = value;
} }
qreal qreal