From 0f4ec70bf30c09333312ef37a6471d1790073486 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 23 Jan 2018 22:48:33 +0100 Subject: [PATCH] Fixes #53 last read message indicator --- src/messages/layouts/messagelayout.cpp | 13 +++++++++++- src/messages/layouts/messagelayout.hpp | 3 ++- src/widgets/helper/channelview.cpp | 22 +++++++++++++++++++- src/widgets/helper/channelview.hpp | 2 ++ src/widgets/settingspages/behaviourpage.cpp | 2 +- src/widgets/split.cpp | 5 +++++ src/widgets/split.hpp | 1 + src/widgets/splitcontainer.cpp | 2 +- src/widgets/splitcontainer.hpp | 2 +- src/widgets/window.cpp | 23 ++++++++++++++++++++- src/widgets/window.hpp | 1 + 11 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 31c69e0ca..aec1df3b1 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -145,7 +145,8 @@ void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags) } // Painting -void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection) +void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection, + bool isLastReadMessage, bool isWindowFocused) { QPixmap *pixmap = this->buffer.get(); singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance(); @@ -180,6 +181,16 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection // draw gif emotes this->container.paintAnimatedElements(painter, y); + // draw last read message line + if (isLastReadMessage) { + QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color() + : themeManager.tabs.selected.backgrounds.unfocused.color(); + + QBrush brush = QBrush(color, Qt::VerPattern); + + painter.fillRect(0, y + this->container.getHeight() - 1, this->container.width, 1, brush); + } + this->bufferValid = true; } diff --git a/src/messages/layouts/messagelayout.hpp b/src/messages/layouts/messagelayout.hpp index 52f1bf73e..44143a552 100644 --- a/src/messages/layouts/messagelayout.hpp +++ b/src/messages/layouts/messagelayout.hpp @@ -41,7 +41,8 @@ public: bool layout(int width, float scale, MessageElement::Flags flags); // Painting - void paint(QPainter &painter, int y, int messageIndex, Selection &selection); + void paint(QPainter &painter, int y, int messageIndex, Selection &selection, + bool isLastReadMessage, bool isWindowFocused); void invalidateBuffer(); void deleteBuffer(); diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 888254c88..85fa42069 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -96,6 +96,9 @@ ChannelView::ChannelView(BaseWidget *parent) auto e = new QResizeEvent(this->size(), this->size()); this->resizeEvent(e); delete e; + + singletons::SettingManager::getInstance().showLastMessageIndicator.connect( + [this](auto, auto) { this->update(); }, this->managedConnections); } ChannelView::~ChannelView() @@ -410,6 +413,17 @@ void ChannelView::pause(int msecTimeout) this->pauseTimeout.start(msecTimeout); } +void ChannelView::updateLastReadMessage() +{ + auto _snapshot = this->getMessagesSnapshot(); + + if (_snapshot.getLength() > 0) { + this->lastReadMessage = _snapshot[_snapshot.getLength() - 1]; + } + + this->update(); +} + void ChannelView::resizeEvent(QResizeEvent *) { this->scrollBar.resize(this->scrollBar.width(), height()); @@ -477,11 +491,17 @@ void ChannelView::drawMessages(QPainter &painter) (fmod(this->scrollBar.getCurrentValue(), 1))); messages::MessageLayout *end = nullptr; + bool windowFocused = this->window() == QApplication::activeWindow(); for (size_t i = start; i < messagesSnapshot.getLength(); ++i) { messages::MessageLayout *layout = messagesSnapshot[i].get(); - layout->paint(painter, y, i, this->selection); + bool isLastMessage = false; + if (singletons::SettingManager::getInstance().showLastMessageIndicator) { + isLastMessage = this->lastReadMessage.get() == layout; + } + + layout->paint(painter, y, i, this->selection, isLastMessage, windowFocused); y += layout->getHeight(); diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index ed222f595..2397cabe6 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -39,6 +39,7 @@ public: void setEnableScrollingToBottom(bool); bool getEnableScrollingToBottom() const; void pause(int msecTimeout); + void updateLastReadMessage(); void setChannel(SharedChannel channel); messages::LimitedQueueSnapshot getMessagesSnapshot(); @@ -72,6 +73,7 @@ private: bool messageWasAdded = false; bool paused = false; QTimer pauseTimeout; + messages::MessageLayoutPtr lastReadMessage; messages::LimitedQueueSnapshot snapshot; diff --git a/src/widgets/settingspages/behaviourpage.cpp b/src/widgets/settingspages/behaviourpage.cpp index f9a00c144..f9caa5e24 100644 --- a/src/widgets/settingspages/behaviourpage.cpp +++ b/src/widgets/settingspages/behaviourpage.cpp @@ -8,7 +8,7 @@ #define WINDOW_TOPMOST "Window always on top (requires restart)" #define INPUT_EMPTY "Hide input box when empty" -#define LAST_MSG "Show last read message indicator" +#define LAST_MSG "Show last read message indicator (marks the spot where you left the window)" #define PAUSE_HOVERING "When hovering" #define STREAMLINK_QUALITY "Choose", "Source", "High", "Medium", "Low", "Audio only" diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 6f90a597a..19ac3fa5e 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -252,6 +252,11 @@ void Split::updateGifEmotes() this->view.queueUpdate(); } +void Split::updateLastReadMessage() +{ + this->view.updateLastReadMessage(); +} + void Split::giveFocus(Qt::FocusReason reason) { this->input.textInput.setFocus(reason); diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 64100ab8b..5e5e12e31 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -70,6 +70,7 @@ public: bool hasFocus() const; void layoutMessages(); void updateGifEmotes(); + void updateLastReadMessage(); void drag(); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index d085aa6d6..ee6ad7d56 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -143,7 +143,7 @@ void SplitContainer::addToLayout(Split *widget, std::pair position) this->refreshCurrentFocusCoordinates(); } -const std::vector &SplitContainer::getChatWidgets() const +const std::vector &SplitContainer::getSplits() const { return this->splits; } diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index 601eb95a2..bf07022f3 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -33,7 +33,7 @@ public: std::pair removeFromLayout(Split *widget); void addToLayout(Split *widget, std::pair position = std::pair(-1, -1)); - const std::vector &getChatWidgets() const; + const std::vector &getSplits() const; NotebookTab *getTab() const; void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string()); diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index cf87c21fb..8a5030430 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -107,7 +107,7 @@ void Window::repaintVisibleChatWidgets(Channel *channel) return; } - const std::vector &widgets = page->getChatWidgets(); + const std::vector &widgets = page->getSplits(); for (auto it = widgets.begin(); it != widgets.end(); ++it) { Split *widget = *it; @@ -140,6 +140,27 @@ void Window::closeEvent(QCloseEvent *) this->closed(); } +bool Window::event(QEvent *e) +{ + switch (e->type()) { + case QEvent::WindowActivate: + break; + + case QEvent::WindowDeactivate: { + auto page = this->notebook.getSelectedPage(); + + if (page != nullptr) { + std::vector splits = page->getSplits(); + + for (Split *split : splits) { + split->updateLastReadMessage(); + } + } + } break; + }; + return BaseWindow::event(e); +} + void Window::loadGeometry() { bool doSetGeometry = false; diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index 475eff728..33827dbe3 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -57,6 +57,7 @@ public: protected: virtual void closeEvent(QCloseEvent *event) override; + virtual bool event(QEvent *event) override; private: singletons::ThemeManager &themeManager;