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

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
Channel::addMessage(std::shared_ptr<messages::Message> message)
{
this->messageMutex.lock();
this->messages.append(message);
this->messageMutex.unlock();
std::shared_ptr<messages::Message> deleted;
Windows::repaintVisibleChatWidgets();
if (this->messages.appendItem(message, deleted)) {
this->messageRemovedFromStart(deleted);
}
this->messageAppended(message);
Windows::repaintVisibleChatWidgets(this);
}
}

View file

@ -3,11 +3,13 @@
#include "concurrentmap.h"
#include "messages/lazyloadedimage.h"
#include "messages/limitedqueue.h"
#include <QMap>
#include <QMutex>
#include <QString>
#include <QVector>
#include <boost/signals2.hpp>
#include <memory>
namespace chatterino {
@ -20,6 +22,11 @@ class Channel
public:
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
ConcurrentMap<QString, messages::LazyLoadedImage *> &
getBttvChannelEmotes()
@ -95,25 +102,23 @@ public:
}
// methods
void addMessage(std::shared_ptr<messages::Message> message);
QVector<std::shared_ptr<messages::Message>> getMessagesClone();
QVector<std::shared_ptr<messages::Message>> &
getMessages()
messages::LimitedQueueSnapshot<std::shared_ptr<messages::Message>>
getMessageSnapshot()
{
return messages;
return messages.getSnapshot();
}
void addMessage(std::shared_ptr<messages::Message> message);
void
reloadChannelEmotes()
{
reloadBttvEmotes();
reloadFfzEmotes();
this->reloadBttvEmotes();
this->reloadFfzEmotes();
}
private:
QVector<std::shared_ptr<messages::Message>> messages;
messages::LimitedQueue<std::shared_ptr<messages::Message>> messages;
QString name;
int roomID;

View file

@ -95,7 +95,9 @@ HEADERS += account.h \
windows.h \
widgets/resizingtextedit.h \
settingssnapshot.h \
logging.h
logging.h \
messages/limitedqueue.h \
messages/limitedqueuesnapshot.h
PRECOMPILED_HEADER =

97
messages/limitedqueue.h Normal file
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

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

View file

@ -16,7 +16,7 @@ class Message
{
public:
Message(const QString &text);
Message(const IrcPrivateMessage &ircMessage, Channel &Channel,
Message(const IrcPrivateMessage &ircMessage, Channel &channel,
bool enablePingSound = true, bool isReceivedWhisper = false,
bool isSentWhisper = false, bool includeChannel = false);

View file

@ -47,17 +47,19 @@ ChatWidgetView::layoutMessages()
bool showScrollbar = false;
auto messages = c->getMessagesClone();
auto messages = c->getMessageSnapshot();
bool redraw = false;
for (std::shared_ptr<messages::Message> &message : messages) {
redraw |= message.get()->layout(this->width(), true);
}
// for (std::shared_ptr<messages::Message> &message : messages) {
// redraw |= message.get()->layout(this->width(), true);
// }
redraw = true;
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();
message->layout(this->width(), true);
@ -65,7 +67,7 @@ ChatWidgetView::layoutMessages()
h -= message->getHeight();
if (h < 0) {
this->scrollbar.setLargeChange((messages.size() - i) +
this->scrollbar.setLargeChange((messages.getLength() - i) +
(qreal)h / message->getHeight());
this->scrollbar.setDesiredValue(this->scrollbar.getDesiredValue());
@ -76,7 +78,7 @@ ChatWidgetView::layoutMessages()
this->scrollbar.setVisible(showScrollbar);
this->scrollbar.setMaximum(c->getMessages().size());
this->scrollbar.setMaximum(messages.getLength());
return redraw;
}
@ -138,18 +140,18 @@ ChatWidgetView::paintEvent(QPaintEvent *)
if (c == NULL)
return;
auto messages = c->getMessagesClone();
auto messages = c->getMessageSnapshot();
int start = this->scrollbar.getCurrentValue();
if (start >= messages.length()) {
if (start >= messages.getLength()) {
return;
}
int y = -(messages[start].get()->getHeight() *
(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();
for (messages::WordPart const &wordPart : message->getWordParts()) {

View file

@ -133,12 +133,8 @@ Notebook::tabAt(QPoint point, int &index)
void
Notebook::rearrangePage(NotebookPage *page, int index)
{
int i1 = pages.indexOf(page);
pages.move(pages.indexOf(page), index);
int i2 = pages.indexOf(page);
performLayout();
}

View file

@ -28,10 +28,11 @@ ScrollBar::ScrollBar(QWidget *widget)
, currentValueChanged()
, currentValue()
{
resize(16, 100);
this->resize(16, 100);
currentValueAnimation.setDuration(300);
currentValueAnimation.setEasingCurve(QEasingCurve(QEasingCurve::OutCubic));
this->currentValueAnimation.setDuration(300);
this->currentValueAnimation.setEasingCurve(
QEasingCurve(QEasingCurve::OutCubic));
this->setMouseTracking(true);
}
@ -211,7 +212,7 @@ ScrollBar::updateScroll()
this->thumbRect =
QRect(0,
(int)(this->desiredValue / this->maximum * this->trackHeight) +
(int)(this->currentValue / this->maximum * this->trackHeight) +
1 + this->buttonHeight,
width(),
(int)(this->largeChange / this->maximum * this->trackHeight) +

View file

@ -63,8 +63,6 @@ public:
value = std::max(this->minimum,
std::min(this->maximum - this->largeChange, value));
this->desiredValue = value;
if (this->desiredValue != value) {
if (animated) {
this->currentValueAnimation.stop();
@ -78,6 +76,8 @@ public:
this->setCurrentValue(value);
}
}
this->desiredValue = value;
}
qreal