diff --git a/messages/limitedqueue.h b/messages/limitedqueue.h index 9e6356ba4..ba218a6ba 100644 --- a/messages/limitedqueue.h +++ b/messages/limitedqueue.h @@ -15,7 +15,7 @@ template class LimitedQueue { public: - LimitedQueue(int limit = 10, int buffer = 5) + LimitedQueue(int limit = 100, int buffer = 25) : vector(new std::vector(limit + buffer)) , vectorPtr(this->vector) , mutex() diff --git a/messages/limitedqueuesnapshot.h b/messages/limitedqueuesnapshot.h index 60045d612..c1816814e 100644 --- a/messages/limitedqueuesnapshot.h +++ b/messages/limitedqueuesnapshot.h @@ -29,8 +29,8 @@ public: T const &operator[](int index) const { - assert(index >= 0); - assert(index < length); + // assert(index >= 0); + // assert(index < length); return vector->at(index + offset); } diff --git a/messages/messageref.cpp b/messages/messageref.cpp index cbb42dd5b..f67b0a9fb 100644 --- a/messages/messageref.cpp +++ b/messages/messageref.cpp @@ -2,6 +2,8 @@ #include "emotes.h" #include "settings.h" +#include + #define MARGIN_LEFT 8 #define MARGIN_RIGHT 8 #define MARGIN_TOP 8 @@ -14,6 +16,7 @@ MessageRef::MessageRef(std::shared_ptr message) : message(message.get()) , messagePtr(message) , wordParts() + , buffer() { } @@ -22,46 +25,50 @@ MessageRef::layout(int width, bool enableEmoteMargins) { auto &settings = Settings::getInstance(); - width = width - (width % 2); - - int mediumTextLineHeight = Fonts::getFontMetrics(Fonts::Medium).height(); + bool sizeChanged = width != this->currentLayoutWidth; + bool redraw = width != this->currentLayoutWidth; int spaceWidth = 4; - bool redraw = width != this->currentLayoutWidth || this->relayoutRequested; + { + int mediumTextLineHeight = + Fonts::getFontMetrics(Fonts::Medium).height(); - bool recalculateImages = this->emoteGeneration != Emotes::getGeneration(); - bool recalculateText = this->fontGeneration != Fonts::getGeneration(); + bool recalculateImages = + this->emoteGeneration != Emotes::getGeneration(); + bool recalculateText = this->fontGeneration != Fonts::getGeneration(); - qreal emoteScale = settings.emoteScale.get(); - bool scaleEmotesByLineHeight = settings.scaleEmotesByLineHeight.get(); + qreal emoteScale = settings.emoteScale.get(); + bool scaleEmotesByLineHeight = settings.scaleEmotesByLineHeight.get(); - if (recalculateImages || recalculateText) { - this->emoteGeneration = Emotes::getGeneration(); - this->fontGeneration = Fonts::getGeneration(); + if (recalculateImages || recalculateText) { + this->emoteGeneration = Emotes::getGeneration(); + this->fontGeneration = Fonts::getGeneration(); - redraw = true; + redraw = true; - for (auto &word : this->message->getWords()) { - if (word.isImage()) { - if (recalculateImages) { - auto &image = word.getImage(); + for (auto &word : this->message->getWords()) { + if (word.isImage()) { + if (recalculateImages) { + auto &image = word.getImage(); - qreal w = image.getWidth(); - qreal h = image.getHeight(); + qreal w = image.getWidth(); + qreal h = image.getHeight(); - if (scaleEmotesByLineHeight) { - word.setSize(w * mediumTextLineHeight / h * emoteScale, - mediumTextLineHeight * emoteScale); - } else { - word.setSize(w * image.getScale() * emoteScale, - h * image.getScale() * emoteScale); + if (scaleEmotesByLineHeight) { + word.setSize( + w * mediumTextLineHeight / h * emoteScale, + mediumTextLineHeight * emoteScale); + } else { + word.setSize(w * image.getScale() * emoteScale, + h * image.getScale() * emoteScale); + } + } + } else { + if (recalculateText) { + QFontMetrics &metrics = word.getFontMetrics(); + word.setSize(metrics.width(word.getText()), + metrics.height()); } - } - } else { - if (recalculateText) { - QFontMetrics &metrics = word.getFontMetrics(); - word.setSize(metrics.width(word.getText()), - metrics.height()); } } } @@ -71,6 +78,8 @@ MessageRef::layout(int width, bool enableEmoteMargins) return false; } + this->currentLayoutWidth = width; + int x = MARGIN_LEFT; int y = MARGIN_TOP; @@ -184,7 +193,16 @@ MessageRef::layout(int width, bool enableEmoteMargins) this->alignWordParts(lineStart, lineHeight); - this->height = y + lineHeight; + if (this->height != y + lineHeight) { + sizeChanged = true; + this->height = y + lineHeight; + } + + if (sizeChanged) { + this->buffer = nullptr; + } + + this->updateBuffer = true; return true; } diff --git a/messages/messageref.h b/messages/messageref.h index 1ed7a0d0c..fba83fea1 100644 --- a/messages/messageref.h +++ b/messages/messageref.h @@ -1,9 +1,11 @@ #ifndef MESSAGEREF_H #define MESSAGEREF_H -#include #include "messages/message.h" +#include +#include + namespace chatterino { namespace messages { @@ -26,18 +28,15 @@ public: bool layout(int width, bool enableEmoteMargins = true); - void - requestRelayout() - { - relayoutRequested = true; - } - const std::vector & getWordParts() const { return wordParts; } + std::shared_ptr buffer = nullptr; + bool updateBuffer = false; + private: Message *message; std::shared_ptr messagePtr; @@ -47,7 +46,6 @@ private: int height = 0; int currentLayoutWidth = -1; - bool relayoutRequested = true; int fontGeneration = -1; int emoteGeneration = -1; diff --git a/widgets/chatwidgetheader.cpp b/widgets/chatwidgetheader.cpp index f68fd5f34..9e2bab37f 100644 --- a/widgets/chatwidgetheader.cpp +++ b/widgets/chatwidgetheader.cpp @@ -46,6 +46,7 @@ ChatWidgetHeader::ChatWidgetHeader(ChatWidget *parent) this->leftMenu.addAction("Close split", this, SLOT(menuCloseSplit()), QKeySequence(tr("Ctrl+W"))); this->leftMenu.addAction("Move split", this, SLOT(menuMoveSplit())); + this->leftMenu.addAction("Popup", this, SLOT(menuPopup())); this->leftMenu.addSeparator(); this->leftMenu.addAction("Change channel", this, SLOT(menuChangeChannel()), QKeySequence(tr("Ctrl+R"))); @@ -182,6 +183,13 @@ ChatWidgetHeader::menuMoveSplit() { } void +ChatWidgetHeader::menuPopup() +{ + auto widget = new ChatWidget(); + widget->setChannelName(this->chatWidget->getChannelName()); + widget->show(); +} +void ChatWidgetHeader::menuChangeChannel() { this->chatWidget->showChangeChannelPopup(); diff --git a/widgets/chatwidgetheader.h b/widgets/chatwidgetheader.h index 82162eb55..b6937d1ea 100644 --- a/widgets/chatwidgetheader.h +++ b/widgets/chatwidgetheader.h @@ -61,6 +61,7 @@ private slots: void menuAddSplit(); void menuCloseSplit(); void menuMoveSplit(); + void menuPopup(); void menuChangeChannel(); void menuClearChat(); void menuOpenChannel(); diff --git a/widgets/chatwidgetview.cpp b/widgets/chatwidgetview.cpp index 8a2aa921f..0f2407aa8 100644 --- a/widgets/chatwidgetview.cpp +++ b/widgets/chatwidgetview.cpp @@ -37,17 +37,33 @@ ChatWidgetView::~ChatWidgetView() bool ChatWidgetView::layoutMessages() { - bool showScrollbar = false; - auto messages = chatWidget->getMessagesSnapshot(); - bool redraw = false; + if (messages.getLength() == 0) { + this->scrollbar.setVisible(false); - // for (std::shared_ptr &message : messages) { - // redraw |= message.get()->layout(this->width(), true); - // } + return false; + } - redraw = true; + bool showScrollbar = false, redraw = false; + + int start = this->scrollbar.getCurrentValue(); + + int y = -(messages[start].get()->getHeight() * + (fmod(this->scrollbar.getCurrentValue(), 1))); + + for (int i = start; i < messages.getLength(); ++i) { + auto messagePtr = messages[i]; + auto message = messagePtr.get(); + + redraw |= message->layout(this->width(), true); + + y += message->getHeight(); + + if (y >= height()) { + break; + } + } int h = this->height() - 8; @@ -87,18 +103,15 @@ ChatWidgetView::resizeEvent(QResizeEvent *) void ChatWidgetView::paintEvent(QPaintEvent *) { - QPainter painter(this); + QPainter _painter(this); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - - // auto c = this->chatWidget->getChannel(); - - QColor color; + _painter.setRenderHint(QPainter::SmoothPixmapTransform); ColorScheme &scheme = ColorScheme::getInstance(); // code for tesing colors /* + QColor color; static ConcurrentMap imgCache; std::function getImg = [&scheme](qreal light) { @@ -129,11 +142,6 @@ ChatWidgetView::paintEvent(QPaintEvent *) painter.fillRect(QRect(0, 9, 500, 2), QColor(0, 0, 0));*/ - // if (c == NULL) - // return; - - // auto messages = c->getMessageSnapshot(); - auto messages = chatWidget->getMessagesSnapshot(); int start = this->scrollbar.getCurrentValue(); @@ -148,40 +156,64 @@ ChatWidgetView::paintEvent(QPaintEvent *) for (int i = start; i < messages.getLength(); ++i) { messages::MessageRef *messageRef = messages[i].get(); - for (messages::WordPart const &wordPart : messageRef->getWordParts()) { - painter.setPen(QColor(255, 0, 0)); - painter.drawRect(wordPart.getX(), wordPart.getY() + y, - wordPart.getWidth(), wordPart.getHeight()); + std::shared_ptr bufferPtr = messageRef->buffer; + QPixmap *buffer = bufferPtr.get(); - // image - if (wordPart.getWord().isImage()) { - messages::LazyLoadedImage &lli = wordPart.getWord().getImage(); + bool updateBuffer = messageRef->updateBuffer; - const QPixmap *image = lli.getPixmap(); + if (buffer == nullptr) { + buffer = new QPixmap(this->width(), messageRef->getHeight()); + bufferPtr = std::shared_ptr(buffer); + updateBuffer = true; + } - if (image != NULL) { - painter.drawPixmap( - QRect(wordPart.getX(), wordPart.getY() + y, - wordPart.getWidth(), wordPart.getHeight()), - *image); + if (updateBuffer) { + QPainter painter(buffer); + painter.fillRect(buffer->rect(), scheme.ChatBackground); + + for (messages::WordPart const &wordPart : + messageRef->getWordParts()) { + painter.setPen(QColor(255, 0, 0)); + painter.drawRect(wordPart.getX(), wordPart.getY(), + wordPart.getWidth(), wordPart.getHeight()); + + // image + if (wordPart.getWord().isImage()) { + messages::LazyLoadedImage &lli = + wordPart.getWord().getImage(); + + const QPixmap *image = lli.getPixmap(); + + if (image != NULL) { + painter.drawPixmap( + QRect(wordPart.getX(), wordPart.getY(), + wordPart.getWidth(), wordPart.getHeight()), + *image); + } + } + // text + else { + QColor color = wordPart.getWord().getColor(); + + ColorScheme::getInstance().normalizeColor(color); + + painter.setPen(color); + painter.setFont(wordPart.getWord().getFont()); + + painter.drawText( + QRectF(wordPart.getX(), wordPart.getY(), 10000, 10000), + wordPart.getText(), + QTextOption(Qt::AlignLeft | Qt::AlignTop)); } } - // text - else { - QColor color = wordPart.getWord().getColor(); - ColorScheme::getInstance().normalizeColor(color); - - painter.setPen(color); - painter.setFont(wordPart.getWord().getFont()); - - painter.drawText( - QRectF(wordPart.getX(), wordPart.getY() + y, 10000, 10000), - wordPart.getText(), - QTextOption(Qt::AlignLeft | Qt::AlignTop)); - } + messageRef->updateBuffer = false; } + messageRef->buffer = bufferPtr; + + _painter.drawPixmap(0, y, *buffer); + y += messageRef->getHeight(); if (y > height()) {