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:
Cranken 2017-12-23 22:17:38 +01:00 committed by pajlada
parent fc81b118c7
commit a617873f6a
11 changed files with 172 additions and 37 deletions

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -164,7 +164,6 @@ private:
boost::signals2::connection layoutConnection;
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
private slots:
void wordTypeMaskChanged()
{

View file

@ -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,19 +112,21 @@ void SplitHeader::updateChannelText()
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
if (twitchChannel != nullptr && twitchChannel->isLive) {
this->isLive = true;
this->tooltip = "<style>.center { text-align: center; }</style>"
"<p class = \"center\">" +
twitchChannel->streamStatus + "<br><br>" + twitchChannel->streamGame +
"<br>"
"Live for " +
twitchChannel->streamUptime + " with " +
twitchChannel->streamViewerCount +
" viewers"
"</p>";
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
this->setToolTip("<style>.center { text-align: center; }</style>"
"<p class = \"center\">" +
twitchChannel->streamStatus + "<br><br>" + twitchChannel->streamGame +
"<br>"
"Live for " +
twitchChannel->streamUptime + " with " +
twitchChannel->streamViewerCount +
" viewers"
"</p>");
} 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) {

View file

@ -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();

View 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

View 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

View file

@ -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;

View file

@ -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;