added limited queue
This commit is contained in:
+8
-14
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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 =
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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
@@ -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()) {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user