diff --git a/src/colorscheme.cpp b/src/colorscheme.cpp index 338f544f4..cf5b20419 100644 --- a/src/colorscheme.cpp +++ b/src/colorscheme.cpp @@ -41,10 +41,6 @@ ColorScheme::ColorScheme(WindowManager &windowManager) this->themeHue.getValueChangedSignal().connect([=](const auto &) { this->update(); // }); - - this->updated.connect([&windowManager] { - windowManager.repaintVisibleChatWidgets(); // - }); } void ColorScheme::update() @@ -57,7 +53,7 @@ void ColorScheme::update() void ColorScheme::setColors(double hue, double multiplier) { lightTheme = multiplier > 0; - bool hasDarkBorder = false; + // bool hasDarkBorder = false; SystemMessageColor = QColor(140, 127, 127); @@ -140,10 +136,10 @@ void ColorScheme::normalizeColor(QColor &color) } if (color.lightnessF() < 0.6f && color.hueF() > 0.54444 && color.hueF() < 0.83333) { - color.setHslF(color.hueF(), color.saturationF(), - color.lightnessF() + - sin((color.hueF() - 0.54444) / (0.8333 - 0.54444) * 3.14159) * - color.saturationF() * 0.2); + color.setHslF( + color.hueF(), color.saturationF(), + color.lightnessF() + sin((color.hueF() - 0.54444) / (0.8333 - 0.54444) * 3.14159) * + color.saturationF() * 0.2); } } } diff --git a/src/emotemanager.cpp b/src/emotemanager.cpp index 8e6db3511..05e726b30 100644 --- a/src/emotemanager.cpp +++ b/src/emotemanager.cpp @@ -517,21 +517,4 @@ EmoteData EmoteManager::getCheerImage(long long amount, bool animated) return EmoteData(); } -boost::signals2::signal &EmoteManager::getGifUpdateSignal() -{ - if (!_gifUpdateTimerInitiated) { - _gifUpdateTimerInitiated = true; - - _gifUpdateTimer.setInterval(30); - _gifUpdateTimer.start(); - - QObject::connect(&_gifUpdateTimer, &QTimer::timeout, [this] { - _gifUpdateTimerSignal(); - this->windowManager.repaintGifEmotes(); - }); - } - - return _gifUpdateTimerSignal; -} - } // namespace chatterino diff --git a/src/emotemanager.hpp b/src/emotemanager.hpp index 16469430d..53890ff8c 100644 --- a/src/emotemanager.hpp +++ b/src/emotemanager.hpp @@ -68,8 +68,6 @@ public: _generation++; } - boost::signals2::signal &getGifUpdateSignal(); - // Bit badge/emotes? ConcurrentMap miscImageCache; @@ -157,7 +155,6 @@ private: boost::signals2::signal _gifUpdateTimerSignal; QTimer _gifUpdateTimer; - bool _gifUpdateTimerInitiated = false; int _generation = 0; diff --git a/src/messages/lazyloadedimage.cpp b/src/messages/lazyloadedimage.cpp index 1d84d0263..e143f9838 100644 --- a/src/messages/lazyloadedimage.cpp +++ b/src/messages/lazyloadedimage.cpp @@ -5,13 +5,13 @@ #include "util/urlfetch.hpp" #include "windowmanager.hpp" -#include #include #include #include #include #include #include +#include #include @@ -22,7 +22,6 @@ LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_wi const QString &url, qreal scale, const QString &name, const QString &tooltip, const QMargins &margin, bool isHat) : emoteManager(_emoteManager) - , windowManager(_windowManager) , currentPixmap(nullptr) , url(url) , name(name) @@ -38,7 +37,6 @@ LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_wi QPixmap *image, qreal scale, const QString &name, const QString &tooltip, const QMargins &margin, bool isHat) : emoteManager(_emoteManager) - , windowManager(_windowManager) , currentPixmap(image) , name(name) , tooltip(tooltip) @@ -51,70 +49,51 @@ LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_wi void LazyLoadedImage::loadImage() { - std::thread([=] () { - QNetworkRequest request; - request.setUrl(QUrl(this->url)); - QNetworkAccessManager NaM; - QEventLoop eventLoop; - QNetworkReply *reply = NaM.get(request); - QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit); - eventLoop.exec(); // Wait until response is read. + std::thread([=]() { + QNetworkRequest request; + request.setUrl(QUrl(this->url)); + QNetworkAccessManager NaM; + QEventLoop eventLoop; + QNetworkReply *reply = NaM.get(request); + QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit); + eventLoop.exec(); // Wait until response is read. - qDebug() << "Received emote " << this->url; - QByteArray array = reply->readAll(); - QBuffer buffer(&array); - buffer.open(QIODevice::ReadOnly); + qDebug() << "Received emote " << this->url; + QByteArray array = reply->readAll(); + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); - QImage image; - QImageReader reader(&buffer); + QImage image; + QImageReader reader(&buffer); - bool first = true; + bool first = true; - for (int index = 0; index < reader.imageCount(); ++index) { - if (reader.read(&image)) { - auto pixmap = new QPixmap(QPixmap::fromImage(image)); + for (int index = 0; index < reader.imageCount(); ++index) { + if (reader.read(&image)) { + auto pixmap = new QPixmap(QPixmap::fromImage(image)); - if (first) { - first = false; - this->currentPixmap = pixmap; - } + if (first) { + first = false; + this->currentPixmap = pixmap; + } - FrameData data; - data.duration = std::max(20, reader.nextImageDelay()); - data.image = pixmap; + FrameData data; + data.duration = std::max(20, reader.nextImageDelay()); + data.image = pixmap; - this->allFrames.push_back(data); - } - } + this->allFrames.push_back(data); + } + } - if (this->allFrames.size() > 1) { - this->animated = true; - } + if (this->allFrames.size() > 1) { + this->animated = true; + } - this->emoteManager.incGeneration(); - this->windowManager.layoutVisibleChatWidgets(); + this->emoteManager.incGeneration(); - delete reply; - }).detach(); - this->emoteManager.getGifUpdateSignal().connect([=] () { this->gifUpdateTimout(); }); // For some reason when Boost signal is in thread scope and thread deletes the signal doesn't work, so this is the fix. -} - -void LazyLoadedImage::gifUpdateTimout() -{ - if (animated) { - this->currentFrameOffset += GIF_FRAME_LENGTH; - - while (true) { - if (this->currentFrameOffset > this->allFrames.at(this->currentFrame).duration) { - this->currentFrameOffset -= this->allFrames.at(this->currentFrame).duration; - this->currentFrame = (this->currentFrame + 1) % this->allFrames.size(); - } else { - break; - } - } - - this->currentPixmap = this->allFrames[this->currentFrame].image; - } + delete reply; + }) + .detach(); } const QPixmap *LazyLoadedImage::getPixmap() diff --git a/src/messages/lazyloadedimage.hpp b/src/messages/lazyloadedimage.hpp index c6c06125e..db0fdda6f 100644 --- a/src/messages/lazyloadedimage.hpp +++ b/src/messages/lazyloadedimage.hpp @@ -40,7 +40,6 @@ public: private: EmoteManager &emoteManager; - WindowManager &windowManager; struct FrameData { QPixmap *image; @@ -49,8 +48,6 @@ private: QPixmap *currentPixmap; std::vector allFrames; - int currentFrame = 0; - int currentFrameOffset = 0; QString url; QString name; @@ -63,7 +60,6 @@ private: bool isLoading; void loadImage(); - void gifUpdateTimout(); }; } // namespace messages diff --git a/src/messages/messagebuilder.hpp b/src/messages/messagebuilder.hpp index adda6e0f5..44d55d74d 100644 --- a/src/messages/messagebuilder.hpp +++ b/src/messages/messagebuilder.hpp @@ -29,7 +29,6 @@ public: private: std::shared_ptr message; std::vector _words; - bool highlight = false; std::chrono::time_point _parseTime; }; diff --git a/src/widgets/channelview.cpp b/src/widgets/channelview.cpp index e6eda1122..4010c19e6 100644 --- a/src/widgets/channelview.cpp +++ b/src/widgets/channelview.cpp @@ -29,38 +29,8 @@ namespace widgets { ChannelView::ChannelView(WindowManager &windowManager, BaseWidget *parent) : BaseWidget(parent) , windowManager(windowManager) - , scrollBar(this) , userPopupWidget(std::shared_ptr()) { -#ifndef Q_OS_MAC -// this->setAttribute(Qt::WA_OpaquePaintEvent); -#endif - /*this->setMouseTracking(true); - - QObject::connect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged, this, - &ChannelView::wordTypeMaskChanged); - - this->scrollBar.getCurrentValueChanged().connect([this] { - // Whenever the scrollbar value has been changed, re-render the ChatWidgetView - this->layoutMessages(); - - this->goToBottom->setVisible(this->scrollBar.isVisible() && !this->scrollBar.isAtBottom()); - - this->update(); - }); - - this->repaintGifsConnection = - windowManager.repaintGifs.connect([&] { this->updateGifEmotes(); }); - this->layoutConnection = windowManager.repaintGifs.connect([&] { this->layout(); }); - - this->goToBottom = new RippleEffectLabel(this, 0); - this->goToBottom->setStyleSheet("background-color: rgba(0,0,0,0.5); color: #FFF;"); - this->goToBottom->getLabel().setText("Jump to bottom"); - this->goToBottom->setVisible(false); - - connect(goToBottom, &RippleEffectLabel::clicked, this, - [this] { QTimer::singleShot(180, [this] { this->scrollBar.scrollToBottom(); }); });*/ - setLayout(&vbox); vbox.addWidget(&web); @@ -71,220 +41,11 @@ ChannelView::ChannelView(WindowManager &windowManager, BaseWidget *parent) ChannelView::~ChannelView() { - QObject::disconnect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged, - this, &ChannelView::wordTypeMaskChanged); -} - -bool ChannelView::layoutMessages() -{ - auto messages = this->getMessagesSnapshot(); - - if (messages.getLength() == 0) { - this->scrollBar.setVisible(false); - return false; - } - - bool showScrollbar = false; - bool redraw = false; - - // Bool indicating whether or not we were showing all messages - // True if one of the following statements are true: - // The scrollbar was not visible - // The scrollbar was visible and at the bottom - this->showingLatestMessages = this->scrollBar.isAtBottom() || !this->scrollBar.isVisible(); - - size_t start = this->scrollBar.getCurrentValue(); - int layoutWidth = - (this->scrollBar.isVisible() ? width() - this->scrollBar.width() : width()) - 4; - - // layout the visible messages in the view - if (messages.getLength() > start) { - int y = -(messages[start]->getHeight() * (fmod(this->scrollBar.getCurrentValue(), 1))); - - for (size_t i = start; i < messages.getLength(); ++i) { - auto message = messages[i]; - - redraw |= message->layout(layoutWidth, true); - - y += message->getHeight(); - - if (y >= height()) { - break; - } - } - } - - // layout the messages at the bottom to determine the scrollbar thumb size - int h = height() - 8; - - for (std::size_t i = messages.getLength() - 1; i > 0; i--) { - auto *message = messages[i].get(); - message->layout(layoutWidth, true); - - h -= message->getHeight(); - - if (h < 0) { - this->scrollBar.setLargeChange((messages.getLength() - i) + - (qreal)h / message->getHeight()); - this->scrollBar.setDesiredValue(this->scrollBar.getDesiredValue()); - - showScrollbar = true; - break; - } - } - - this->scrollBar.setVisible(showScrollbar); - - if (!showScrollbar) { - this->scrollBar.setDesiredValue(0); - } - - this->scrollBar.setMaximum(messages.getLength()); - - if (this->showingLatestMessages && showScrollbar) { - // If we were showing the latest messages and the scrollbar now wants to be rendered, scroll - // to bottom - // TODO: Do we want to check if the user is currently moving the scrollbar? - // Perhaps also if the user scrolled with the scrollwheel in this ChatWidget in the last 0.2 - // seconds or something - this->scrollBar.scrollToBottom(); - } - - return redraw; } void ChannelView::clearMessages() { - // Clear all stored messages in this chat widget this->messages.clear(); - - // Layout chat widget messages, and force an update regardless if there are no messages - this->layoutMessages(); - this->update(); -} - -void ChannelView::updateGifEmotes() -{ - this->onlyUpdateEmotes = true; - this->update(); -} - -ScrollBar &ChannelView::getScrollBar() -{ - return this->scrollBar; -} - -QString ChannelView::getSelectedText() -{ - LimitedQueueSnapshot messages = this->getMessagesSnapshot(); - - QString text; - bool isSingleMessage = this->selection.isSingleMessage(); - - size_t i = std::max(0, this->selection.min.messageIndex); - - int charIndex = 0; - - bool first = true; - - auto addPart = [&](const WordPart &part, int from = 0, int to = -1) { - if (part.getCopyText().isEmpty()) { - return; - } - - if (part.getWord().isText()) { - text += part.getText().mid(from, to); - } else { - text += part.getCopyText(); - } - }; - - // first line - for (const messages::WordPart &part : messages[i]->getWordParts()) { - int charLength = part.getCharacterLength(); - - if (charIndex + charLength < this->selection.min.charIndex) { - charIndex += charLength; - continue; - } - - if (first) { - first = false; - bool isSingleWord = - isSingleMessage && - this->selection.max.charIndex - charIndex < part.getCharacterLength(); - - if (isSingleWord) { - // return single word - addPart(part, this->selection.min.charIndex - charIndex, - this->selection.max.charIndex - this->selection.min.charIndex); - return text; - } else { - // add first word of the selection - addPart(part, this->selection.min.charIndex - charIndex); - } - } else if (isSingleMessage && charIndex + charLength >= selection.max.charIndex) { - addPart(part, 0, this->selection.max.charIndex - charIndex); - - return text; - } else { - text += part.getCopyText() + (part.hasTrailingSpace() ? " " : ""); - } - - charIndex += charLength; - } - - text += "\n"; - - // middle lines - for (i++; i < this->selection.max.messageIndex; i++) { - for (const messages::WordPart &part : messages[i]->getWordParts()) { - if (!part.getCopyText().isEmpty()) { - text += part.getCopyText(); - - if (part.hasTrailingSpace()) { - text += " "; - } - } - } - text += "\n"; - } - - // last line - charIndex = 0; - - for (const messages::WordPart &part : - messages[this->selection.max.messageIndex]->getWordParts()) { - int charLength = part.getCharacterLength(); - - if (charIndex + charLength >= this->selection.max.charIndex) { - addPart(part, 0, this->selection.max.charIndex - charIndex); - - return text; - } - - text += part.getCopyText(); - - if (part.hasTrailingSpace()) { - text += " "; - } - - charIndex += charLength; - } - - return text; -} - -bool ChannelView::hasSelection() -{ - return !this->selection.isEmpty(); -} - -void ChannelView::clearSelection() -{ - this->selection = Selection(); - layoutMessages(); - update(); } messages::LimitedQueueSnapshot ChannelView::getMessagesSnapshot() @@ -302,13 +63,13 @@ void ChannelView::setChannel(std::shared_ptr channel) // on new message this->messageAppendedConnection = channel->messageAppended.connect([this](SharedMessage &message) { - //SharedMessageRef deleted; + // SharedMessageRef deleted; auto command = QString("addMessage('%1','%2'").arg("", ""); for (const auto &word : message->getWords()) { command += ","; if (word.isText()) { - command += "{type:'text', data:'" + word.getText() + "'}"; + command += "{type:'text', data:'" + word.getText() + "'}"; } else { command += "{type:'emote', data:'" + word.getEmoteURL() + "'}"; } @@ -323,21 +84,13 @@ void ChannelView::setChannel(std::shared_ptr channel) this->getScrollBar().setDesiredValue(value, false); }*/ - //layoutMessages(); - //update(); + // layoutMessages(); + // update(); }); // on message removed this->messageRemovedConnection = - channel->messageRemovedFromStart.connect([this](SharedMessage &) { - this->selection.min.messageIndex--; - this->selection.max.messageIndex--; - this->selection.start.messageIndex--; - this->selection.end.messageIndex--; - - layoutMessages(); - update(); - }); + channel->messageRemovedFromStart.connect([](SharedMessage &) {}); auto snapshot = channel->getMessageSnapshot(); @@ -363,489 +116,5 @@ void ChannelView::detachChannel() this->messageRemovedConnection.disconnect(); } -void ChannelView::resizeEvent(QResizeEvent *) -{ - /*this->scrollBar.resize(this->scrollBar.width(), height()); - this->scrollBar.move(width() - this->scrollBar.width(), 0); - - this->goToBottom->setGeometry(0, this->height() - 32, this->width(), 32); - - this->scrollBar.raise(); - - layoutMessages(); - - this->update();*/ -} - -void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &end) -{ - // selections - this->selection = Selection(start, end); - - this->selectionChanged(); - - // qDebug() << min.messageIndex << ":" << min.charIndex << " " << max.messageIndex << ":" - // << max.charIndex; -} - -void ChannelView::paintEvent(QPaintEvent * /*event*/) -{ - QPainter painter(this); - - painter.setRenderHint(QPainter::SmoothPixmapTransform); - -// only update gif emotes -#ifndef Q_OS_MAC -// if (this->onlyUpdateEmotes) { -// this->onlyUpdateEmotes = false; - -// for (const GifEmoteData &item : this->gifEmotes) { -// painter.fillRect(item.rect, this->colorScheme.ChatBackground); - -// painter.drawPixmap(item.rect, *item.image->getPixmap()); -// } - -// return; -// } -#endif - - // update all messages - this->gifEmotes.clear(); - - painter.fillRect(rect(), this->colorScheme.ChatBackground); - - // draw messages - this->drawMessages(painter); - - // draw gif emotes - for (GifEmoteData &item : this->gifEmotes) { - painter.fillRect(item.rect, this->colorScheme.ChatBackground); - - painter.drawPixmap(item.rect, *item.image->getPixmap()); - } -} - -void ChannelView::drawMessages(QPainter &painter) -{ - auto messages = this->getMessagesSnapshot(); - - size_t start = this->scrollBar.getCurrentValue(); - - if (start >= messages.getLength()) { - return; - } - - int y = -(messages[start].get()->getHeight() * (fmod(this->scrollBar.getCurrentValue(), 1))); - - for (size_t i = start; i < messages.getLength(); ++i) { - messages::MessageRef *messageRef = messages[i].get(); - - std::shared_ptr bufferPtr = messageRef->buffer; - QPixmap *buffer = bufferPtr.get(); - - bool updateBuffer = messageRef->updateBuffer; - - if (buffer == nullptr) { - buffer = new QPixmap(width(), messageRef->getHeight()); - bufferPtr = std::shared_ptr(buffer); - updateBuffer = true; - } - - updateBuffer |= this->selecting; - - // update messages that have been changed - if (updateBuffer) { - this->updateMessageBuffer(messageRef, buffer, i); - } - - // get gif emotes - for (messages::WordPart const &wordPart : messageRef->getWordParts()) { - if (wordPart.getWord().isImage()) { - messages::LazyLoadedImage &lli = wordPart.getWord().getImage(); - - if (lli.getAnimated()) { - GifEmoteData gifEmoteData; - gifEmoteData.image = &lli; - QRect rect(wordPart.getX(), wordPart.getY() + y, wordPart.getWidth(), - wordPart.getHeight()); - - gifEmoteData.rect = rect; - - this->gifEmotes.push_back(gifEmoteData); - } - } - } - - messageRef->buffer = bufferPtr; - - // if (buffer != nullptr) { - painter.drawPixmap(0, y, *buffer); - // } - - y += messageRef->getHeight(); - - if (y > height()) { - break; - } - } -} - -void ChannelView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer, - int messageIndex) -{ - QPainter painter(buffer); - - // draw background - // if (this->selectionMin.messageIndex <= messageIndex && - // this->selectionMax.messageIndex >= messageIndex) { - // painter.fillRect(buffer->rect(), QColor(24, 55, 25)); - //} else { - painter.fillRect(buffer->rect(), - (messageRef->getMessage()->getCanHighlightTab()) - ? this->colorScheme.ChatBackgroundHighlighted - : this->colorScheme.ChatBackground); - //} - - // draw selection - if (!selection.isEmpty()) { - drawMessageSelection(painter, messageRef, messageIndex, buffer->height()); - } - - // draw message - for (messages::WordPart const &wordPart : messageRef->getWordParts()) { - // image - if (wordPart.getWord().isImage()) { - messages::LazyLoadedImage &lli = wordPart.getWord().getImage(); - - const QPixmap *image = lli.getPixmap(); - - if (image != nullptr) { - painter.drawPixmap(QRect(wordPart.getX(), wordPart.getY(), wordPart.getWidth(), - wordPart.getHeight()), - *image); - } - } - // text - else { - QColor color = wordPart.getWord().getColor().getColor(this->colorScheme); - - this->colorScheme.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)); - } - } - - messageRef->updateBuffer = false; -} - -void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef, - int messageIndex, int bufferHeight) -{ - if (this->selection.min.messageIndex > messageIndex || - this->selection.max.messageIndex < messageIndex) { - return; - } - - QColor selectionColor(255, 255, 255, 63); - - int charIndex = 0; - size_t i = 0; - auto &parts = messageRef->getWordParts(); - - int currentLineNumber = 0; - QRect rect; - - if (parts.size() > 0) { - if (selection.min.messageIndex == messageIndex) { - rect.setTop(parts.at(0).getY()); - } - rect.setLeft(parts.at(0).getX()); - } - - // skip until selection start - if (this->selection.min.messageIndex == messageIndex && this->selection.min.charIndex != 0) { - for (; i < parts.size(); i++) { - const messages::WordPart &part = parts.at(i); - auto characterLength = part.getCharacterLength(); - - if (characterLength + charIndex > selection.min.charIndex) { - break; - } - - charIndex += characterLength; - currentLineNumber = part.getLineNumber(); - } - - if (i >= parts.size()) { - return; - } - - // handle word that has a cut of selection - const messages::WordPart &part = parts.at(i); - - // check if selection if single word - int characterLength = part.getCharacterLength(); - bool isSingleWord = charIndex + characterLength > this->selection.max.charIndex && - this->selection.max.messageIndex == messageIndex; - - rect = part.getRect(); - currentLineNumber = part.getLineNumber(); - - if (part.getWord().isText()) { - int offset = this->selection.min.charIndex - charIndex; - - for (int j = 0; j < offset; j++) { - rect.setLeft(rect.left() + part.getCharacterWidth(j)); - } - - if (isSingleWord) { - int length = (this->selection.max.charIndex - charIndex) - offset; - - rect.setRight(part.getX()); - - for (int j = 0; j < offset + length; j++) { - rect.setRight(rect.right() + part.getCharacterWidth(j)); - } - - painter.fillRect(rect, selectionColor); - - return; - } - } else { - if (isSingleWord) { - if (charIndex + 1 != this->selection.max.charIndex) { - rect.setRight(part.getX() + part.getWord().getImage().getScaledWidth()); - } - painter.fillRect(rect, selectionColor); - - return; - } - - if (charIndex != this->selection.min.charIndex) { - rect.setLeft(part.getX() + part.getWord().getImage().getScaledWidth()); - } - } - - i++; - charIndex += characterLength; - } - - // go through lines and draw selection - for (; i < parts.size(); i++) { - const messages::WordPart &part = parts.at(i); - - int charLength = part.getCharacterLength(); - - bool isLastSelectedWord = this->selection.max.messageIndex == messageIndex && - charIndex + charLength > this->selection.max.charIndex; - - if (part.getLineNumber() == currentLineNumber) { - rect.setLeft(std::min(rect.left(), part.getX())); - rect.setTop(std::min(rect.top(), part.getY())); - rect.setRight(std::max(rect.right(), part.getRight())); - rect.setBottom(std::max(rect.bottom(), part.getBottom() - 1)); - } else { - painter.fillRect(rect, selectionColor); - - currentLineNumber = part.getLineNumber(); - - rect = part.getRect(); - } - - if (isLastSelectedWord) { - if (part.getWord().isText()) { - int offset = this->selection.min.charIndex - charIndex; - - int length = (this->selection.max.charIndex - charIndex) - offset; - - rect.setRight(part.getX()); - - for (int j = 0; j < offset + length; j++) { - rect.setRight(rect.right() + part.getCharacterWidth(j)); - } - } else { - if (this->selection.max.charIndex == charIndex) { - rect.setRight(part.getX()); - } - } - painter.fillRect(rect, selectionColor); - - return; - } - - charIndex += charLength; - } - - if (this->selection.max.messageIndex != messageIndex) { - rect.setBottom(bufferHeight); - } - - painter.fillRect(rect, selectionColor); -} - -void ChannelView::wheelEvent(QWheelEvent *event) -{ - if (this->scrollBar.isVisible()) { - auto mouseMultiplier = SettingsManager::getInstance().mouseScrollMultiplier.get(); - - this->scrollBar.setDesiredValue( - this->scrollBar.getDesiredValue() - event->delta() / 10.0 * mouseMultiplier, true); - } -} - -void ChannelView::mouseMoveEvent(QMouseEvent *event) -{ - std::shared_ptr message; - QPoint relativePos; - int messageIndex; - - if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) { - setCursor(Qt::ArrowCursor); - return; - } - - if (this->selecting) { - int index = message->getSelectionIndex(relativePos); - - this->setSelection(this->selection.start, SelectionItem(messageIndex, index)); - - this->repaint(); - } - - const messages::Word *hoverWord; - if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) { - setCursor(Qt::ArrowCursor); - return; - } - - if (hoverWord->getLink().isValid()) { - setCursor(Qt::PointingHandCursor); - } else { - setCursor(Qt::ArrowCursor); - } -} - -void ChannelView::mousePressEvent(QMouseEvent *event) -{ - this->isMouseDown = true; - - this->lastPressPosition = event->screenPos(); - - std::shared_ptr message; - QPoint relativePos; - int messageIndex; - - this->mouseDown(event); - - if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) { - setCursor(Qt::ArrowCursor); - - return; - } - - int index = message->getSelectionIndex(relativePos); - - auto selectionItem = SelectionItem(messageIndex, index); - this->setSelection(selectionItem, selectionItem); - this->selecting = true; - - this->repaint(); -} - -void ChannelView::mouseReleaseEvent(QMouseEvent *event) -{ - if (!this->isMouseDown) { - // We didn't grab the mouse press, so we shouldn't be handling the mouse - // release - return; - } - - this->isMouseDown = false; - this->selecting = false; - - float distance = util::distanceBetweenPoints(this->lastPressPosition, event->screenPos()); - - qDebug() << "Distance: " << distance; - - if (fabsf(distance) > 15.f) { - // It wasn't a proper click, so we don't care about that here - return; - } - - // If you clicked and released less than X pixels away, it counts - // as a click! - - // show user thing pajaW - - std::shared_ptr message; - QPoint relativePos; - int messageIndex; - - if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) { - // No message at clicked position - this->userPopupWidget.hide(); - return; - } - - const messages::Word *hoverWord; - - if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) { - return; - } - - auto &link = hoverWord->getLink(); - - switch (link.getType()) { - case messages::Link::UserInfo: { - auto user = link.getValue(); - this->userPopupWidget.setName(user); - this->userPopupWidget.move(event->screenPos().toPoint()); - this->userPopupWidget.updatePermissions(); - this->userPopupWidget.show(); - this->userPopupWidget.setFocus(); - - qDebug() << "Clicked " << user << "s message"; - break; - } - case messages::Link::Url: { - QDesktopServices::openUrl(QUrl(link.getValue())); - break; - } - } -} - -bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr &_message, - QPoint &relativePos, int &index) -{ - auto messages = this->getMessagesSnapshot(); - - size_t start = this->scrollBar.getCurrentValue(); - - if (start >= messages.getLength()) { - return false; - } - - int y = -(messages[start]->getHeight() * (fmod(this->scrollBar.getCurrentValue(), 1))); - - for (size_t i = start; i < messages.getLength(); ++i) { - auto message = messages[i]; - - if (p.y() < y + message->getHeight()) { - relativePos = QPoint(p.x(), p.y() - y); - _message = message; - index = i; - return true; - } - - y += message->getHeight(); - } - - return false; -} - } // namespace widgets } // namespace chatterino diff --git a/src/widgets/channelview.hpp b/src/widgets/channelview.hpp index 9e9cb3b0c..5a16b7df7 100644 --- a/src/widgets/channelview.hpp +++ b/src/widgets/channelview.hpp @@ -21,65 +21,6 @@ namespace chatterino { namespace widgets { -struct SelectionItem { - int messageIndex; - int charIndex; - - SelectionItem() - { - messageIndex = charIndex = 0; - } - - SelectionItem(int _messageIndex, int _charIndex) - { - this->messageIndex = _messageIndex; - this->charIndex = _charIndex; - } - - bool isSmallerThan(const SelectionItem &other) const - { - return this->messageIndex < other.messageIndex || - (this->messageIndex == other.messageIndex && this->charIndex < other.charIndex); - } - - bool equals(const SelectionItem &other) const - { - return this->messageIndex == other.messageIndex && this->charIndex == other.charIndex; - } -}; - -struct Selection { - SelectionItem start; - SelectionItem end; - SelectionItem min; - SelectionItem max; - - Selection() - { - } - - Selection(const SelectionItem &start, const SelectionItem &end) - : start(start) - , end(end) - , min(start) - , max(end) - { - if (max.isSmallerThan(min)) { - std::swap(this->min, this->max); - } - } - - bool isEmpty() const - { - return this->start.equals(this->end); - } - - bool isSingleMessage() const - { - return this->min.messageIndex == this->max.messageIndex; - } -}; - class ChannelView : public BaseWidget { Q_OBJECT @@ -88,34 +29,11 @@ public: explicit ChannelView(WindowManager &windowManager, BaseWidget *parent = 0); ~ChannelView(); - void updateGifEmotes(); - ScrollBar &getScrollBar(); - QString getSelectedText(); - bool hasSelection(); - void clearSelection(); - void setChannel(std::shared_ptr channel); messages::LimitedQueueSnapshot getMessagesSnapshot(); - bool layoutMessages(); void clearMessages(); - boost::signals2::signal mouseDown; - boost::signals2::signal selectionChanged; - -protected: - virtual void resizeEvent(QResizeEvent *) override; - - virtual void paintEvent(QPaintEvent *) override; - virtual void wheelEvent(QWheelEvent *event) override; - - virtual void mouseMoveEvent(QMouseEvent *event) override; - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void mouseReleaseEvent(QMouseEvent *event) override; - - bool tryGetMessageAt(QPoint p, std::shared_ptr &message, - QPoint &relativePos, int &index); - private: struct GifEmoteData { messages::LazyLoadedImage *image; @@ -126,49 +44,18 @@ private: void detachChannel(); - void drawMessages(QPainter &painter); - void updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer, int messageIndex); - void drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef, int messageIndex, - int bufferHeight); - void setSelection(const SelectionItem &start, const SelectionItem &end); - std::shared_ptr channel; std::vector gifEmotes; - ScrollBar scrollBar; - RippleEffectLabel *goToBottom; - - // This variable can be used to decide whether or not we should render the "Show latest - // messages" button - bool showingLatestMessages = true; - AccountPopupWidget userPopupWidget; - bool onlyUpdateEmotes = false; - - // Mouse event variables - bool isMouseDown = false; - QPointF lastPressPosition; - - Selection selection; - bool selecting = false; messages::LimitedQueue messages; boost::signals2::connection messageAppendedConnection; boost::signals2::connection messageRemovedConnection; - boost::signals2::connection repaintGifsConnection; - boost::signals2::connection layoutConnection; - QWebEngineView web; QVBoxLayout vbox; - -private slots: - void wordTypeMaskChanged() - { - layoutMessages(); - update(); - } }; } // namespace widgets diff --git a/src/widgets/chatwidget.cpp b/src/widgets/chatwidget.cpp index 825294e96..d0edad341 100644 --- a/src/widgets/chatwidget.cpp +++ b/src/widgets/chatwidget.cpp @@ -86,13 +86,6 @@ ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent) this->input.textInput.installEventFilter(parent); - this->view.mouseDown.connect([this](QMouseEvent *) { this->giveFocus(Qt::MouseFocusReason); }); - this->view.selectionChanged.connect([this]() { - if (view.hasSelection()) { - this->input.clearSelection(); - } - }); - QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &ChatWidget::test); timer->start(1000); @@ -167,21 +160,6 @@ bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty) return false; } -void ChatWidget::layoutMessages(bool forceUpdate) -{ - this->view.layoutMessages(); - this->view.update(); - - // if (this->view.layoutMessages() || forceUpdate) { - // this->view.update(); - // } -} - -void ChatWidget::updateGifEmotes() -{ - this->view.updateGifEmotes(); -} - void ChatWidget::giveFocus(Qt::FocusReason reason) { this->input.textInput.setFocus(reason); @@ -430,11 +408,6 @@ void ChatWidget::doOpenAccountPopupWidget(AccountPopupWidget *widget, QString us widget->setFocus(); } -void ChatWidget::doCopy() -{ - QApplication::clipboard()->setText(this->view.getSelectedText()); -} - static std::vector usernameVariants = { "pajlada", // "trump", // diff --git a/src/widgets/chatwidget.hpp b/src/widgets/chatwidget.hpp index 674478b6f..760a7ebb9 100644 --- a/src/widgets/chatwidget.hpp +++ b/src/widgets/chatwidget.hpp @@ -56,9 +56,6 @@ public: void giveFocus(Qt::FocusReason reason); bool hasFocus() const; - void layoutMessages(bool forceUpdate = false); - void updateGifEmotes(); - protected: virtual void paintEvent(QPaintEvent *) override; @@ -117,9 +114,6 @@ public slots: // Open twitch channel stream through streamlink void doOpenStreamlink(); - // Copy text from chat - void doCopy(); - // Open viewer list of the channel void doOpenViewerList(); diff --git a/src/widgets/chatwidgetinput.cpp b/src/widgets/chatwidgetinput.cpp index 8c782d20a..e289f34eb 100644 --- a/src/widgets/chatwidgetinput.cpp +++ b/src/widgets/chatwidgetinput.cpp @@ -160,23 +160,12 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget, EmoteManager &emoteMan notebook->previousTab(); } - } else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) { - if (this->chatWidget->view.hasSelection()) { - this->chatWidget->doCopy(); - event->accept(); - } } }); this->textLengthVisibleChangedConnection = SettingsManager::getInstance().showMessageLength.valueChanged.connect( [this](const bool &value) { this->textLengthLabel.setHidden(!value); }); - - QObject::connect(&this->textInput, &QTextEdit::copyAvailable, [this](bool available) { - if (available) { - this->chatWidget->view.clearSelection(); - } - }); } ChatWidgetInput::~ChatWidgetInput() diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp index 358ba4a72..3334760ef 100644 --- a/src/widgets/mainwindow.cpp +++ b/src/widgets/mainwindow.cpp @@ -70,15 +70,6 @@ MainWindow::~MainWindow() { } -void MainWindow::repaintVisibleChatWidgets(Channel *channel) -{ - auto *page = this->notebook.getSelectedPage(); - - if (page == nullptr) { - return; - } -} - void MainWindow::load(const boost::property_tree::ptree &tree) { this->notebook.load(tree); diff --git a/src/widgets/mainwindow.hpp b/src/widgets/mainwindow.hpp index 2b9d68ad7..ade5d90b3 100644 --- a/src/widgets/mainwindow.hpp +++ b/src/widgets/mainwindow.hpp @@ -30,8 +30,6 @@ public: CompletionManager &_completionManager); ~MainWindow(); - void repaintVisibleChatWidgets(Channel *channel = nullptr); - void load(const boost::property_tree::ptree &tree); boost::property_tree::ptree save(); void loadDefaults(); diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index 6ca9ea250..69fbf36d2 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -217,7 +217,7 @@ void Notebook::resizeEvent(QResizeEvent *) void Notebook::settingsButtonClicked() { - QTimer::singleShot(80, [this] { SettingsDialog::showDialog(); }); + QTimer::singleShot(80, [] { SettingsDialog::showDialog(); }); } void Notebook::usersButtonClicked() diff --git a/src/windowmanager.cpp b/src/windowmanager.cpp index 3792a42d4..9efe2e7ea 100644 --- a/src/windowmanager.cpp +++ b/src/windowmanager.cpp @@ -25,23 +25,6 @@ static const std::string &getSettingsPath() return path; } -void WindowManager::layoutVisibleChatWidgets(Channel *channel) -{ - this->layout(); -} - -void WindowManager::repaintVisibleChatWidgets(Channel *channel) -{ - if (this->mainWindow != nullptr) { - this->mainWindow->repaintVisibleChatWidgets(channel); - } -} - -void WindowManager::repaintGifEmotes() -{ - this->repaintGifs(); -} - // void WindowManager::updateAll() //{ // if (this->mainWindow != nullptr) { diff --git a/src/windowmanager.hpp b/src/windowmanager.hpp index 441e7b319..990b8dbc6 100644 --- a/src/windowmanager.hpp +++ b/src/windowmanager.hpp @@ -20,19 +20,11 @@ public: ColorScheme &colorScheme; CompletionManager &completionManager; - void layoutVisibleChatWidgets(Channel *channel = nullptr); - void repaintVisibleChatWidgets(Channel *channel = nullptr); - void repaintGifEmotes(); - // void updateAll(); - widgets::MainWindow &getMainWindow(); void load(); void save(); - boost::signals2::signal repaintGifs; - boost::signals2::signal layout; - private: std::mutex windowMutex;