diff --git a/CHANGELOG.md b/CHANGELOG.md index b27bd87f1..02a8e0c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,13 @@ - Bugfix: Fixed crash that could occur when changing Tab layout and utilizing multiple windows. (#4248) - Bugfix: Fixed text sometimes not pasting properly when image uploader was disabled. (#4246) - Bugfix: Fixed text cursor(caret) not showing in open channel dialog. (#4196) +- Bugfix: Fixed tooltip images not appearing if mouse hovered only first pixel. (#4268) - Dev: Remove protocol from QApplication's Organization Domain (so changed from `https://www.chatterino.com` to `chatterino.com`). (#4256) - Dev: Ignore `WM_SHOWWINDOW` hide events, causing fewer attempted rescales. (#4198) - Dev: Migrated to C++ 20 (#4252, #4257) - Dev: Enable LTO for main branch builds. (#4258, #4260) - Dev: Removed unused include directives. (#4266) +- Dev: Removed TooltipPreviewImage. (#4268) - Dev: Removed unused operators in `Image` (#4267) ## 2.4.0 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0367bb190..56e0f0aea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -316,8 +316,6 @@ set(SOURCE_FILES singletons/Theme.hpp singletons/Toasts.cpp singletons/Toasts.hpp - singletons/TooltipPreviewImage.cpp - singletons/TooltipPreviewImage.hpp singletons/Updates.cpp singletons/Updates.hpp singletons/WindowManager.cpp diff --git a/src/singletons/TooltipPreviewImage.cpp b/src/singletons/TooltipPreviewImage.cpp deleted file mode 100644 index 7b33039e8..000000000 --- a/src/singletons/TooltipPreviewImage.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "TooltipPreviewImage.hpp" - -#include "Application.hpp" -#include "singletons/WindowManager.hpp" -#include "widgets/TooltipWidget.hpp" - -namespace chatterino { - -TooltipPreviewImage &TooltipPreviewImage::instance() -{ - static TooltipPreviewImage *instance = new TooltipPreviewImage(); - return *instance; -} - -TooltipPreviewImage::TooltipPreviewImage() -{ - auto windows = getApp()->windows; - - this->connections_.managedConnect(windows->gifRepaintRequested, [&] { - if (this->image_ && this->image_->animated()) - { - this->refreshTooltipWidgetPixmap(); - } - }); - - this->connections_.managedConnect(windows->miscUpdate, [&] { - if (this->attemptRefresh) - { - this->refreshTooltipWidgetPixmap(); - } - }); -} - -void TooltipPreviewImage::setImage(ImagePtr image) -{ - this->image_ = std::move(image); - - this->refreshTooltipWidgetPixmap(); -} - -void TooltipPreviewImage::setImageScale(int w, int h) -{ - this->imageWidth_ = w; - this->imageHeight_ = h; - - this->refreshTooltipWidgetPixmap(); -} - -void TooltipPreviewImage::refreshTooltipWidgetPixmap() -{ - auto tooltipWidget = TooltipWidget::instance(); - - if (this->image_ && !tooltipWidget->isHidden()) - { - if (auto pixmap = this->image_->pixmapOrLoad()) - { - if (this->imageWidth_ != 0 && this->imageHeight_) - { - tooltipWidget->setImage(pixmap->scaled(this->imageWidth_, - this->imageHeight_, - Qt::KeepAspectRatio)); - } - else - { - tooltipWidget->setImage(*pixmap); - } - - this->attemptRefresh = false; - } - else - { - this->attemptRefresh = true; - } - } - else - { - tooltipWidget->clearImage(); - } -} - -} // namespace chatterino diff --git a/src/singletons/TooltipPreviewImage.hpp b/src/singletons/TooltipPreviewImage.hpp deleted file mode 100644 index 309d1ef15..000000000 --- a/src/singletons/TooltipPreviewImage.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "messages/Image.hpp" - -#include - -namespace chatterino { - -class TooltipPreviewImage -{ -public: - static TooltipPreviewImage &instance(); - void setImage(ImagePtr image); - void setImageScale(int w, int h); - - TooltipPreviewImage(const TooltipPreviewImage &) = delete; - -private: - TooltipPreviewImage(); - -private: - ImagePtr image_ = nullptr; - int imageWidth_ = 0; - int imageHeight_ = 0; - - pajlada::Signals::SignalHolder connections_; - - // attemptRefresh is set to true in case we want to preview an image that has not loaded yet (if pixmapOrLoad fails) - bool attemptRefresh{false}; - - // Refresh the pixmap used in the Tooltip Widget - // Called from setImage and from the "gif repaint" signal if the image is animated - void refreshTooltipWidgetPixmap(); -}; - -} // namespace chatterino diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index 2893d845a..4e7ee7697 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -1,17 +1,11 @@ #include "TooltipWidget.hpp" +#include "Application.hpp" #include "singletons/Fonts.hpp" - -#include -#include -#include -#include - -#ifdef USEWINSDK -# include -#endif +#include "singletons/WindowManager.hpp" #include +#include namespace chatterino { @@ -25,44 +19,52 @@ TooltipWidget::TooltipWidget(BaseWidget *parent) : BaseWindow({BaseWindow::TopMost, BaseWindow::DontFocus, BaseWindow::DisableLayoutSave}, parent) - , displayImage_(new QLabel()) - , displayText_(new QLabel()) + , displayImage_(new QLabel(this)) + , displayText_(new QLabel(this)) { this->setStyleSheet("color: #fff; background: rgba(11, 11, 11, 0.8)"); this->setAttribute(Qt::WA_TranslucentBackground); - //this->setWindowOpacity(0.8); - this->updateFont(); + this->setWindowFlag(Qt::WindowStaysOnTopHint, true); + this->setStayInScreenRect(true); - displayImage_->hide(); displayImage_->setAlignment(Qt::AlignHCenter); displayImage_->setStyleSheet("background: transparent"); + displayText_->setAlignment(Qt::AlignHCenter); - displayText_->setText("tooltip text"); displayText_->setStyleSheet("background: transparent"); - auto layout = new QVBoxLayout(); + + auto *layout = new QVBoxLayout(this); + layout->setSizeConstraint(QLayout::SetFixedSize); layout->setContentsMargins(10, 5, 10, 5); layout->addWidget(displayImage_); layout->addWidget(displayText_); this->setLayout(layout); - this->fontChangedConnection_ = getFonts()->fontChanged.connect([this] { + this->connections_.managedConnect(getFonts()->fontChanged, [this] { this->updateFont(); }); -} + this->updateFont(); -TooltipWidget::~TooltipWidget() -{ - this->fontChangedConnection_.disconnect(); -} + auto windows = getApp()->windows; + this->connections_.managedConnect(windows->gifRepaintRequested, [this] { + if (this->image_ && this->image_->animated()) + { + this->refreshPixmap(); + } + }); -#ifdef USEWINSDK -void TooltipWidget::raise() -{ - ::SetWindowPos(HWND(this->winId()), HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + this->connections_.managedConnect(windows->miscUpdate, [this] { + if (this->image_ && this->attemptRefresh) + { + if (this->refreshPixmap()) + { + this->attemptRefresh = false; + this->adjustSize(); + } + } + }); } -#endif void TooltipWidget::themeChangedEvent() { @@ -100,12 +102,69 @@ void TooltipWidget::setWordWrap(bool wrap) void TooltipWidget::clearImage() { this->displayImage_->hide(); + this->image_ = nullptr; + this->setImageScale(0, 0); } -void TooltipWidget::setImage(QPixmap image) +void TooltipWidget::setImage(ImagePtr image) { + if (this->image_ == image) + { + return; + } + // hide image until loaded and reset scale + this->clearImage(); + this->image_ = std::move(image); + this->refreshPixmap(); +} + +void TooltipWidget::setImageScale(int w, int h) +{ + if (this->customImgWidth == w && this->customImgHeight == h) + { + return; + } + this->customImgWidth = w; + this->customImgHeight = h; + this->refreshPixmap(); +} + +void TooltipWidget::hideEvent(QHideEvent *) +{ + this->clearImage(); +} + +void TooltipWidget::showEvent(QShowEvent *) +{ + this->adjustSize(); +} + +bool TooltipWidget::refreshPixmap() +{ + if (!this->image_) + { + return false; + } + + auto pixmap = this->image_->pixmapOrLoad(); + if (!pixmap) + { + this->attemptRefresh = true; + return false; + } + + if (this->customImgWidth > 0 || this->customImgHeight > 0) + { + this->displayImage_->setPixmap(pixmap->scaled( + this->customImgWidth, this->customImgHeight, Qt::KeepAspectRatio)); + } + else + { + this->displayImage_->setPixmap(*pixmap); + } this->displayImage_->show(); - this->displayImage_->setPixmap(image); + + return true; } void TooltipWidget::changeEvent(QEvent *) diff --git a/src/widgets/TooltipWidget.hpp b/src/widgets/TooltipWidget.hpp index 0cb513942..84db6d787 100644 --- a/src/widgets/TooltipWidget.hpp +++ b/src/widgets/TooltipWidget.hpp @@ -1,8 +1,9 @@ #pragma once +#include "messages/Image.hpp" #include "widgets/BaseWindow.hpp" -#include +#include #include #include @@ -16,18 +17,17 @@ public: static TooltipWidget *instance(); TooltipWidget(BaseWidget *parent = nullptr); - ~TooltipWidget() override; + ~TooltipWidget() override = default; void setText(QString text); void setWordWrap(bool wrap); void clearImage(); - void setImage(QPixmap image); - -#ifdef USEWINSDK - void raise(); -#endif + void setImage(ImagePtr image); + void setImageScale(int w, int h); protected: + void showEvent(QShowEvent *) override; + void hideEvent(QHideEvent *) override; void changeEvent(QEvent *) override; void leaveEvent(QEvent *) override; void themeChangedEvent() override; @@ -37,9 +37,18 @@ protected: private: void updateFont(); + // used by WindowManager::gifRepaintRequested signal to progress frames when tooltip image is animated + bool refreshPixmap(); + + // set to true when tooltip image did not finish loading yet (pixmapOrLoad returned false) + bool attemptRefresh{false}; + + ImagePtr image_ = nullptr; + int customImgWidth = 0; + int customImgHeight = 0; QLabel *displayImage_; QLabel *displayText_; - pajlada::Signals::Connection fontChangedConnection_; + pajlada::Signals::SignalHolder connections_; }; } // namespace chatterino diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 69f4efd0f..d89982cae 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -20,7 +20,6 @@ #include "singletons/Resources.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" -#include "singletons/TooltipPreviewImage.hpp" #include "singletons/WindowManager.hpp" #include "util/Clipboard.hpp" #include "util/DistanceBetweenPoints.hpp" @@ -1659,8 +1658,6 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) } else { - auto &tooltipPreviewImage = TooltipPreviewImage::instance(); - tooltipPreviewImage.setImageScale(0, 0); auto badgeElement = dynamic_cast(element); if ((badgeElement || emoteElement) && @@ -1671,18 +1668,18 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) { if (emoteElement) { - tooltipPreviewImage.setImage( + tooltipWidget->setImage( emoteElement->getEmote()->images.getImage(3.0)); } else if (badgeElement) { - tooltipPreviewImage.setImage( + tooltipWidget->setImage( badgeElement->getEmote()->images.getImage(3.0)); } } else { - tooltipPreviewImage.setImage(nullptr); + tooltipWidget->clearImage(); } } else @@ -1705,7 +1702,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) auto thumbnailSize = getSettings()->thumbnailSize; if (!thumbnailSize) { - tooltipPreviewImage.setImage(nullptr); + tooltipWidget->clearImage(); } else { @@ -1718,13 +1715,12 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) shouldHideThumbnail ? Image::fromResourcePixmap(getResources().streamerMode) : element->getThumbnail(); - tooltipPreviewImage.setImage(std::move(thumb)); + tooltipWidget->setImage(std::move(thumb)); if (element->getThumbnailType() == MessageElement::ThumbnailType::Link_Thumbnail) { - tooltipPreviewImage.setImageScale(thumbnailSize, - thumbnailSize); + tooltipWidget->setImageScale(thumbnailSize, thumbnailSize); } } } @@ -1732,10 +1728,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) tooltipWidget->moveTo(this, event->globalPos()); tooltipWidget->setWordWrap(isLinkValid); tooltipWidget->setText(element->getTooltip()); - tooltipWidget->adjustSize(); - tooltipWidget->setWindowFlag(Qt::WindowStaysOnTopHint, true); tooltipWidget->show(); - tooltipWidget->raise(); } // check if word has a link diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index af75e2a8f..b8f632188 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -13,7 +13,6 @@ #include "singletons/Resources.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" -#include "singletons/TooltipPreviewImage.hpp" #include "singletons/WindowManager.hpp" #include "util/Helpers.hpp" #include "util/LayoutCreator.hpp" @@ -928,9 +927,8 @@ void SplitHeader::enterEvent(QEvent *event) dynamic_cast(channel)->refreshTitle(); } - TooltipPreviewImage::instance().setImage(nullptr); - auto tooltip = TooltipWidget::instance(); + tooltip->clearImage(); tooltip->setText(this->tooltipText_); tooltip->setWordWrap(true); tooltip->adjustSize(); @@ -939,7 +937,6 @@ void SplitHeader::enterEvent(QEvent *event) tooltip->moveTo(this, pos, false); tooltip->show(); - tooltip->raise(); } BaseWidget::enterEvent(event);