diff --git a/chatterino.pro b/chatterino.pro index c66fe357..83a60457 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -109,7 +109,8 @@ SOURCES += \ src/widgets/window.cpp \ src/widgets/helper/splitcolumn.cpp \ src/widgets/accountswitchwidget.cpp \ - src/widgets/accountswitchpopupwidget.cpp + src/widgets/accountswitchpopupwidget.cpp \ + src/widgets/tooltipwidget.cpp HEADERS += \ src/precompiled_headers.hpp \ @@ -186,6 +187,7 @@ HEADERS += \ src/widgets/accountswitchwidget.hpp \ src/widgets/accountswitchpopupwidget.hpp \ src/const.hpp \ + src/widgets/tooltipwidget.hpp \ src/precompiled_headers.hpp \ src/messages/wordflags.hpp diff --git a/src/fontmanager.cpp b/src/fontmanager.cpp index f44d7924..b0c11be1 100644 --- a/src/fontmanager.cpp +++ b/src/fontmanager.cpp @@ -40,6 +40,8 @@ FontManager::FontData &FontManager::Font::getFontData(Type type) switch (type) { case Small: return this->small; + case MediumSmall: + return this->mediumSmall; case Medium: return this->medium; case MediumBold: diff --git a/src/fontmanager.hpp b/src/fontmanager.hpp index 905835e7..c4bb5d1f 100644 --- a/src/fontmanager.hpp +++ b/src/fontmanager.hpp @@ -15,6 +15,7 @@ class FontManager public: enum Type : uint8_t { Small, + MediumSmall, Medium, MediumBold, MediumItalic, @@ -67,6 +68,7 @@ private: explicit Font(const char *fontFamilyName, int mediumSize) : small(QFont(fontFamilyName, mediumSize - 4)) + , mediumSmall(QFont(fontFamilyName, mediumSize -2)) , medium(QFont(fontFamilyName, mediumSize)) , mediumBold(QFont(fontFamilyName, mediumSize, 50)) , mediumItalic(QFont(fontFamilyName, mediumSize, -1, true)) @@ -78,6 +80,7 @@ private: void setFamily(const char *newFamily) { this->small.font.setFamily(newFamily); + this->mediumSmall.font.setFamily(newFamily); this->medium.font.setFamily(newFamily); this->mediumBold.font.setFamily(newFamily); this->mediumItalic.font.setFamily(newFamily); @@ -90,6 +93,7 @@ private: void setSize(int newMediumSize) { this->small.font.setPointSize(newMediumSize - 4); + this->mediumSmall.font.setPointSize(newMediumSize - 2); this->medium.font.setPointSize(newMediumSize); this->mediumBold.font.setPointSize(newMediumSize); this->mediumItalic.font.setPointSize(newMediumSize); @@ -102,6 +106,7 @@ private: void updateMetrics() { this->small.metrics = QFontMetrics(this->small.font); + this->mediumSmall.metrics = QFontMetrics(this->mediumSmall.font); this->medium.metrics = QFontMetrics(this->medium.font); this->mediumBold.metrics = QFontMetrics(this->mediumBold.font); this->mediumItalic.metrics = QFontMetrics(this->mediumItalic.font); @@ -115,6 +120,7 @@ private: QFontMetrics &getFontMetrics(Type type); FontData small; + FontData mediumSmall; FontData medium; FontData mediumBold; FontData mediumItalic; diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 0e0e2788..0be0a1a0 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -10,13 +10,13 @@ #include "util/benchmark.hpp" #include "util/distancebetweenpoints.hpp" #include "widgets/split.hpp" +#include "widgets/tooltipwidget.hpp" #include "windowmanager.hpp" #include #include #include #include -#include #include #include @@ -78,6 +78,16 @@ ChannelView::ChannelView(BaseWidget *parent) this->updateTimer.start(); }); + + auto _split = this->parent(); + auto _splitContainer = _split->parent(); + auto _notebook = _splitContainer->parent(); + auto _window = qobject_cast(_notebook->parent()); + + assert(_window); + + _window->lostFocus.connect( + [this] { TooltipWidget::getInstance()->hide(); }); } ChannelView::~ChannelView() @@ -728,6 +738,7 @@ void ChannelView::wheelEvent(QWheelEvent *event) void ChannelView::mouseMoveEvent(QMouseEvent *event) { + auto tooltipWidget = TooltipWidget::getInstance(); std::shared_ptr message; QPoint relativePos; int messageIndex; @@ -735,12 +746,14 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) // no message under cursor if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) { this->setCursor(Qt::ArrowCursor); + tooltipWidget->hide(); return; } // message under cursor is collapsed if (message->isCollapsed()) { this->setCursor(Qt::PointingHandCursor); + tooltipWidget->hide(); return; } @@ -753,38 +766,19 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) this->repaint(); } - static QTimer *tooltipTimer = new QTimer(); - // check if word underneath cursor const messages::Word *hoverWord; if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) { this->setCursor(Qt::ArrowCursor); - tooltipTimer->stop(); - QToolTip::hideText(); + tooltipWidget->hide(); return; } - const auto &tooltip = hoverWord->getTooltip(); - static QString targetTooltip; - static QPoint tooltipPos; - connect(tooltipTimer, &QTimer::timeout, []() { - assert(!targetTooltip.isEmpty()); - QToolTip::showText(tooltipPos, targetTooltip); // - }); - - tooltipTimer->setSingleShot(true); - tooltipTimer->setInterval(500); - - if (!tooltip.isEmpty()) { - tooltipPos = event->globalPos(); - targetTooltip = "" - "

" + - tooltip + "

"; - tooltipTimer->start(); - } else { - tooltipTimer->stop(); - QToolTip::hideText(); + if (hoverWord->isImage()) { + tooltipWidget->moveTo(event->globalPos()); + tooltipWidget->setText(tooltip); + tooltipWidget->show(); } // check if word has a link diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index 86e4de72..dd29224a 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -164,7 +164,6 @@ private: boost::signals2::connection layoutConnection; std::vector managedConnections; - private slots: void wordTypeMaskChanged() { diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 2566e5f6..8c61610c 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -4,6 +4,7 @@ #include "util/urlfetch.hpp" #include "widgets/split.hpp" #include "widgets/splitcontainer.hpp" +#include "widgets/tooltipwidget.hpp" #include #include @@ -21,6 +22,11 @@ SplitHeader::SplitHeader(Split *_chatWidget) , rightLabel(this) , rightMenu(this) { + this->setMouseTracking(true); + this->leftLabel.setMouseTracking(true); + this->channelNameLabel.setMouseTracking(true); + this->rightLabel.setMouseTracking(true); + this->refreshTheme(); this->updateChannelText(); @@ -106,19 +112,21 @@ void SplitHeader::updateChannelText() twitch::TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel != nullptr && twitchChannel->isLive) { + this->isLive = true; + this->tooltip = "" + "

" + + twitchChannel->streamStatus + "

" + twitchChannel->streamGame + + "
" + "Live for " + + twitchChannel->streamUptime + " with " + + twitchChannel->streamViewerCount + + " viewers" + "

"; this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)"); - this->setToolTip("" - "

" + - twitchChannel->streamStatus + "

" + twitchChannel->streamGame + - "
" - "Live for " + - twitchChannel->streamUptime + " with " + - twitchChannel->streamViewerCount + - " viewers" - "

"); } else { + this->isLive = false; this->channelNameLabel.setText(QString::fromStdString(channelName)); - this->setToolTip(""); + this->tooltip = ""; } } } @@ -141,6 +149,13 @@ void SplitHeader::mousePressEvent(QMouseEvent *event) void SplitHeader::mouseMoveEvent(QMouseEvent *event) { + if (!this->dragging && this->isLive) { + auto tooltipWidget = TooltipWidget::getInstance(); + tooltipWidget->moveTo(event->globalPos()); + tooltipWidget->setText(tooltip); + tooltipWidget->show(); + } + if (this->dragging) { if (std::abs(this->dragStart.x() - event->pos().x()) > 12 || std::abs(this->dragStart.y() - event->pos().y()) > 12) { @@ -168,11 +183,18 @@ void SplitHeader::mouseMoveEvent(QMouseEvent *event) } SplitContainer::isDraggingSplit = false; + this->dragging = false; } } } } +void SplitHeader::leaveEvent(QEvent *event) +{ + TooltipWidget::getInstance()->hide(); + BaseWidget::leaveEvent(event); +} + void SplitHeader::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { diff --git a/src/widgets/helper/splitheader.hpp b/src/widgets/helper/splitheader.hpp index 3961f88f..9a6f77e2 100644 --- a/src/widgets/helper/splitheader.hpp +++ b/src/widgets/helper/splitheader.hpp @@ -35,6 +35,7 @@ protected: virtual void paintEvent(QPaintEvent *) override; virtual void mousePressEvent(QMouseEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override; + virtual void leaveEvent(QEvent *event) override; virtual void mouseDoubleClickEvent(QMouseEvent *event) override; virtual void resizeEvent(QResizeEvent *event) override; @@ -66,6 +67,9 @@ private: void initializeChannelSignals(); + QString tooltip; + bool isLive; + public slots: void menuMoveSplit(); void menuReloadChannelEmotes(); diff --git a/src/widgets/tooltipwidget.cpp b/src/widgets/tooltipwidget.cpp new file mode 100644 index 00000000..9f5e0c85 --- /dev/null +++ b/src/widgets/tooltipwidget.cpp @@ -0,0 +1,52 @@ +#include "tooltipwidget.hpp" +#include "colorscheme.hpp" +#include "fontmanager.hpp" + +#include +#include + +namespace chatterino { +namespace widgets { + +TooltipWidget::TooltipWidget(BaseWidget *parent) + : BaseWidget(parent) + , displayText(new QLabel()) +{ + QColor black(0,0,0); + QColor white(255,255,255); + + QPalette palette; + palette.setColor(QPalette::WindowText,white); + palette.setColor(QPalette::Background,black); + this->setPalette(palette); + this->setWindowOpacity(0.8); + this->setFont(FontManager::getInstance().getFont(FontManager::Type::MediumSmall)); + + this->setAttribute(Qt::WA_ShowWithoutActivating); + this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + + displayText->setAlignment(Qt::AlignHCenter); + auto layout = new QVBoxLayout(); + layout->setContentsMargins(10,5,10,5); + layout->addWidget(displayText); + this->setLayout(layout); + + FontManager::getInstance().fontChanged.connect([this] { + this->setFont(FontManager::getInstance().getFont(FontManager::Type::MediumSmall)); + }); +} + +void TooltipWidget::setText(QString text) +{ + this->displayText->setText(text); +} + +void TooltipWidget::moveTo(QPoint point) +{ + point.rx() += 16; + point.ry() += 16; + this->move(point); +} + +} // namespace widgets +} // namespace chatterino diff --git a/src/widgets/tooltipwidget.hpp b/src/widgets/tooltipwidget.hpp new file mode 100644 index 00000000..51fd84dd --- /dev/null +++ b/src/widgets/tooltipwidget.hpp @@ -0,0 +1,34 @@ +#pragma once +#include "widgets/basewidget.hpp" + +#include +#include + +namespace chatterino { +namespace widgets { + +class TooltipWidget : public BaseWidget +{ + Q_OBJECT +public: + TooltipWidget(BaseWidget *parent = nullptr); + + void setText(QString text); + void moveTo(QPoint point); + + static TooltipWidget* getInstance() + { + static TooltipWidget *tooltipWidget = nullptr; + if(tooltipWidget == nullptr) + { + tooltipWidget = new TooltipWidget(); + } + return tooltipWidget; + } + +private: + QLabel *displayText; +}; + +} // namespace widgets +} // namespace chatterino diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index b800d17a..572f4072 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -107,6 +107,21 @@ void Window::closeEvent(QCloseEvent *) this->closed(); } +void Window::changeEvent(QEvent *event) +{ + if(!this->isActiveWindow()) + { + this->lostFocus.invoke(); + } + BaseWidget::changeEvent(event); +} + +void Window::leaveEvent(QEvent *event) +{ + this->lostFocus.invoke(); + BaseWidget::leaveEvent(event); +} + void Window::refreshTheme() { QPalette palette; diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index 5fb7e4b2..0a8a1058 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -11,6 +11,7 @@ #include #include +#include namespace chatterino { @@ -55,9 +56,13 @@ public: boost::signals2::signal closed; + pajlada::Signals::NoArgSignal lostFocus; + protected: virtual void closeEvent(QCloseEvent *event) override; + virtual void changeEvent(QEvent *event) override; + virtual void leaveEvent(QEvent *event) override; private: float dpi;