From df81a0e5a5390f6ef6d16b8d5a9ccc0fc024fddb Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 5 Jan 2018 11:22:51 +0100 Subject: [PATCH] Pause chat while hovering. Fixes #208 Also pauses when clicking with double-click-links enabled and while selecting text --- src/messages/limitedqueuesnapshot.hpp | 5 ++ src/singletons/settingsmanager.hpp | 1 + src/widgets/helper/channelview.cpp | 57 ++++++++++++++++++---- src/widgets/helper/channelview.hpp | 8 ++++ src/widgets/settingsdialog.cpp | 69 ++++++++++++++++----------- 5 files changed, 103 insertions(+), 37 deletions(-) diff --git a/src/messages/limitedqueuesnapshot.hpp b/src/messages/limitedqueuesnapshot.hpp index 6b9ae77a7..3e1ece0c3 100644 --- a/src/messages/limitedqueuesnapshot.hpp +++ b/src/messages/limitedqueuesnapshot.hpp @@ -10,6 +10,11 @@ template class LimitedQueueSnapshot { public: + LimitedQueueSnapshot() + : length(0) + { + } + LimitedQueueSnapshot(std::shared_ptr>>> _chunks, size_t _length, size_t _firstChunkOffset, size_t _lastChunkEnd) : chunks(_chunks) diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index 8a440d2f5..f9b4d6719 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -50,6 +50,7 @@ public: FloatSetting mouseScrollMultiplier = {"/behaviour/mouseScrollMultiplier", 1.0}; StringSetting streamlinkPath = {"/behaviour/streamlink/path", ""}; StringSetting preferredQuality = {"/behaviour/streamlink/quality", "Choose"}; + BoolSetting pauseChatHover = {"/behaviour/pauseChatHover", false}; /// Commands BoolSetting allowCommandsAtEnd = {"/commands/allowCommandsAtEnd", false}; diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 7eae59f0f..12434f289 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -26,6 +26,7 @@ #define LAYOUT_WIDTH \ (this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getDpiMultiplier()) +#define PAUSE_TIME 1000 using namespace chatterino::messages; @@ -91,6 +92,8 @@ ChannelView::ChannelView(BaseWidget *parent) this->updateTimer.start(); } }); + + this->pauseTimeout.setSingleShot(true); } ChannelView::~ChannelView() @@ -357,7 +360,11 @@ bool ChannelView::getEnableScrollingToBottom() const messages::LimitedQueueSnapshot ChannelView::getMessagesSnapshot() { - return this->messages.getSnapshot(); + if (!this->paused) { + this->snapshot = this->messages.getSnapshot(); + } + + return this->snapshot; } void ChannelView::setChannel(std::shared_ptr newChannel) @@ -446,6 +453,13 @@ void ChannelView::detachChannel() this->messageRemovedConnection.disconnect(); } +void ChannelView::pause(int msecTimeout) +{ + this->paused = true; + + this->pauseTimeout.start(msecTimeout); +} + void ChannelView::resizeEvent(QResizeEvent *) { this->scrollBar.resize(this->scrollBar.width(), height()); @@ -882,8 +896,22 @@ void ChannelView::wheelEvent(QWheelEvent *event) } } +void ChannelView::enterEvent(QEvent *) +{ + // this->pause(PAUSE_TIME); +} + +void ChannelView::leaveEvent(QEvent *) +{ + this->paused = false; +} + void ChannelView::mouseMoveEvent(QMouseEvent *event) { + if (singletons::SettingManager::getInstance().pauseChatHover.getValue()) { + this->pause(300); + } + auto tooltipWidget = TooltipWidget::getInstance(); std::shared_ptr message; QPoint relativePos; @@ -896,6 +924,16 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } + // is selecting + if (this->selecting) { + this->pause(500); + int index = message->getSelectionIndex(relativePos); + + this->setSelection(this->selection.start, SelectionItem(messageIndex, index)); + + this->queueUpdate(); + } + // message under cursor is collapsed if (message->isCollapsed()) { this->setCursor(Qt::PointingHandCursor); @@ -903,15 +941,6 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } - // is selecting - if (this->selecting) { - int index = message->getSelectionIndex(relativePos); - - this->setSelection(this->selection.start, SelectionItem(messageIndex, index)); - - this->repaint(); - } - // check if word underneath cursor const messages::Word *hoverWord; if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) { @@ -937,6 +966,10 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) void ChannelView::mousePressEvent(QMouseEvent *event) { + if (singletons::SettingManager::getInstance().linksDoubleClickOnly.getValue()) { + this->pause(200); + } + this->isMouseDown = true; this->lastPressPosition = event->screenPos(); @@ -989,6 +1022,10 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event) return; } + if (this->selecting) { + this->paused = false; + } + this->isMouseDown = false; this->selecting = false; diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index 5d50565ec..37a7b2319 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -39,6 +39,7 @@ public: void clearSelection(); void setEnableScrollingToBottom(bool); bool getEnableScrollingToBottom() const; + void pause(int msecTimeout); void setChannel(std::shared_ptr channel); messages::LimitedQueueSnapshot getMessagesSnapshot(); @@ -56,6 +57,9 @@ protected: virtual void paintEvent(QPaintEvent *) override; virtual void wheelEvent(QWheelEvent *event) override; + virtual void enterEvent(QEvent *) override; + virtual void leaveEvent(QEvent *) override; + virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void mousePressEvent(QMouseEvent *event) override; virtual void mouseReleaseEvent(QMouseEvent *event) override; @@ -72,6 +76,10 @@ private: QTimer updateTimer; bool updateQueued = false; bool messageWasAdded = false; + bool paused = false; + QTimer pauseTimeout; + + messages::LimitedQueueSnapshot snapshot; void detachChannel(); void actuallyLayoutMessages(); diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp index cd713a11a..2e87c0267 100644 --- a/src/widgets/settingsdialog.cpp +++ b/src/widgets/settingsdialog.cpp @@ -327,35 +327,50 @@ QVBoxLayout *SettingsDialog::createBehaviourTab() auto form = new QFormLayout(); - form->addRow("Window:", - createCheckbox("Window always on top (requires restart)", settings.windowTopMost)); - // form->addRow("Messages:", createCheckbox("Mention users with a @ (except in - // commands)", - // settings.mentionUsersWithAt)); - form->addRow("Messages:", createCheckbox("Hide input box if empty", settings.hideEmptyInput)); - form->addRow( - "", createCheckbox("Show last read message indicator", settings.showLastMessageIndicator)); + // WINDOW + { + form->addRow("Window:", createCheckbox("Window always on top (requires restart)", + settings.windowTopMost)); + // form->addRow("Messages:", createCheckbox("Mention users with a @ (except in + // commands)", + // settings.mentionUsersWithAt)); + } + // MESSAGES + { + form->addRow("Messages:", + createCheckbox("Hide input box if empty", settings.hideEmptyInput)); + form->addRow("", createCheckbox("Show last read message indicator", + settings.showLastMessageIndicator)); + } + // PAUSE + { + form->addRow("Pause chat:", createCheckbox("When hovering", settings.pauseChatHover)); + } + // MOUSE SCROLL SPEED + { + auto scroll = new QSlider(Qt::Horizontal); + form->addRow("Mouse scroll speed:", scroll); - auto scroll = new QSlider(Qt::Horizontal); - form->addRow("Mouse scroll speed:", scroll); + float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier; + int scrollValue = ((currentValue - 0.1f) / 2.f) * 99.f; + scroll->setValue(scrollValue); - float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier; - int scrollValue = ((currentValue - 0.1f) / 2.f) * 99.f; - scroll->setValue(scrollValue); - - connect(scroll, &QSlider::valueChanged, [](int newValue) { - float mul = static_cast(newValue) / 99.f; - float newScrollValue = (mul * 2.1f) + 0.1f; - singletons::SettingManager::getInstance().mouseScrollMultiplier = newScrollValue; - }); - - form->addRow("Streamlink path:", createLineEdit(settings.streamlinkPath)); - form->addRow(this->createCombobox( - "Preferred quality:", settings.preferredQuality, - {"Choose", "Source", "High", "Medium", "Low", "Audio only"}, - [](const QString &newValue, pajlada::Settings::Setting &setting) { - setting = newValue.toStdString(); - })); + connect(scroll, &QSlider::valueChanged, [](int newValue) { + float mul = static_cast(newValue) / 99.f; + float newScrollValue = (mul * 2.1f) + 0.1f; + singletons::SettingManager::getInstance().mouseScrollMultiplier = newScrollValue; + }); + } + // STREAMLINK + { + form->addRow("Streamlink path:", createLineEdit(settings.streamlinkPath)); + form->addRow(this->createCombobox( + "Preferred quality:", settings.preferredQuality, + {"Choose", "Source", "High", "Medium", "Low", "Audio only"}, + [](const QString &newValue, pajlada::Settings::Setting &setting) { + setting = newValue.toStdString(); + })); + } layout->addLayout(form);