mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Implemented a new, better looking tooltip. (#158)
* Implemented a new, better looking tooltip. * Pajlada fix. * Fixed dragging behaving incorrectly. * Fixed out of focus hovering getting stuck.
This commit is contained in:
parent
fc81b118c7
commit
a617873f6a
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#include "util/benchmark.hpp"
|
||||
#include "util/distancebetweenpoints.hpp"
|
||||
#include "widgets/split.hpp"
|
||||
#include "widgets/tooltipwidget.hpp"
|
||||
#include "windowmanager.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QPainter>
|
||||
#include <QToolTip>
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
@ -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<Window*>(_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<messages::MessageRef> 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 = "<style>.center { text-align: center; }</style>"
|
||||
"<p class = \"center\">" +
|
||||
tooltip + "</p>";
|
||||
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
|
||||
|
|
|
@ -164,7 +164,6 @@ private:
|
|||
boost::signals2::connection layoutConnection;
|
||||
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
|
||||
|
||||
private slots:
|
||||
void wordTypeMaskChanged()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "util/urlfetch.hpp"
|
||||
#include "widgets/split.hpp"
|
||||
#include "widgets/splitcontainer.hpp"
|
||||
#include "widgets/tooltipwidget.hpp"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDrag>
|
||||
|
@ -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,8 +112,8 @@ void SplitHeader::updateChannelText()
|
|||
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
||||
|
||||
if (twitchChannel != nullptr && twitchChannel->isLive) {
|
||||
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
|
||||
this->setToolTip("<style>.center { text-align: center; }</style>"
|
||||
this->isLive = true;
|
||||
this->tooltip = "<style>.center { text-align: center; }</style>"
|
||||
"<p class = \"center\">" +
|
||||
twitchChannel->streamStatus + "<br><br>" + twitchChannel->streamGame +
|
||||
"<br>"
|
||||
|
@ -115,10 +121,12 @@ void SplitHeader::updateChannelText()
|
|||
twitchChannel->streamUptime + " with " +
|
||||
twitchChannel->streamViewerCount +
|
||||
" viewers"
|
||||
"</p>");
|
||||
"</p>";
|
||||
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
|
||||
} 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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
52
src/widgets/tooltipwidget.cpp
Normal file
52
src/widgets/tooltipwidget.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "tooltipwidget.hpp"
|
||||
#include "colorscheme.hpp"
|
||||
#include "fontmanager.hpp"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
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
|
34
src/widgets/tooltipwidget.hpp
Normal file
34
src/widgets/tooltipwidget.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "widgets/basewidget.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
|
||||
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
|
|
@ -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;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <pajlada/settings/setting.hpp>
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
|
@ -55,9 +56,13 @@ public:
|
|||
|
||||
boost::signals2::signal<void()> 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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue