#include "BalloonToolTip.h" #include #include #include #include static constexpr int TAIL_SIZE_PX (8); BalloonToolTip::BalloonToolTip(QWidget *parent) : QWidget(parent) { setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Popup); setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_ShowWithoutActivating); animation.setTargetObject(this); animation.setPropertyName("popupOpacity"); animation.setDuration(150); label.setAlignment(Qt::AlignTop | Qt::AlignLeft); label.setStyleSheet(QLatin1String("QLabel {color : #FFFFFF; font-size: 12px;}")); label.setWordWrap(true); layout.setHorizontalSpacing(0); layout.setVerticalSpacing(0); layout.setContentsMargins(12, 10, 12, 10 + TAIL_SIZE_PX); layout.addWidget(&label, 0, 0); setLayout(&layout); installEventFilter(this); setMouseTracking(true); setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); } BalloonToolTip::~BalloonToolTip() { } void BalloonToolTip::setPopupText(const QString &text) { label.setText(text); adjustSize(); } void BalloonToolTip::show() { setWindowOpacity(0.0); animation.setStartValue(0.0); animation.setEndValue(1.0); QWidget::show(); animation.start(); } void BalloonToolTip::setPopupOpacity(float opacity) { popupOpacity = opacity; setWindowOpacity(opacity); } float BalloonToolTip::getPopupOpacity() const { return popupOpacity; } // Move widget so that the tail's tip matches p. p is in global coords. void BalloonToolTip::attachAt(const QPoint& p) { move(p - QPoint(rect().center().x(), rect().bottom())); } void BalloonToolTip::paintEvent(QPaintEvent *e) { Q_UNUSED(e) QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); // Popup dimensions QRect roundedRectDimensions (rect()); roundedRectDimensions.setBottom(roundedRectDimensions.bottom() - TAIL_SIZE_PX); const QColor balloonColor (8, 33, 44); painter.setBrush(QBrush(balloonColor)); QPen pen; pen.setColor(balloonColor); pen.setWidth(1); painter.setPen(pen); // Draw the popup balloon painter.drawRoundedRect(roundedRectDimensions, 8, 8); painter.setPen(Qt::NoPen); painter.setBrush(balloonColor); // Draw the popup tail const auto tailTipBaseX (roundedRectDimensions.center().x()); const auto tailTipBaseY (roundedRectDimensions.height()); const QPointF points[3] = { QPoint(tailTipBaseX + TAIL_SIZE_PX, tailTipBaseY), QPoint(tailTipBaseX - TAIL_SIZE_PX, tailTipBaseY), QPoint(tailTipBaseX, tailTipBaseY + TAIL_SIZE_PX) }; painter.drawPolygon(points, sizeof(points) / sizeof(QPointF)); } bool BalloonToolTip::eventFilter(QObject *o, QEvent *e) { Q_UNUSED(o) switch (e->type()) { #ifdef Q_OS_MACOS case QEvent::KeyPress: case QEvent::KeyRelease: { const int key = static_cast(e)->key(); // Anything except key modifiers or caps-lock, etc. if (key < Qt::Key_Shift || key > Qt::Key_ScrollLock) hide(); break; } #endif case QEvent::Leave: case QEvent::WindowActivate: case QEvent::WindowDeactivate: case QEvent::FocusIn: case QEvent::FocusOut: case QEvent::Close: // For QTBUG-55523 (QQC) specifically: Hide tooltip when windows are closed case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::Wheel: hide(); break; case QEvent::MouseMove: if (!rect().isNull() && !rect().contains(static_cast(e)->pos())) hide(); default: break; } return false; }