/* stock_icon_tool_button.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include // We want nice icons that render correctly, and that are responsive // when the user hovers and clicks them. // Using setIcon renders correctly on normal and retina displays. It is // not completely responsive, particularly on macOS. // Calling setStyleSheet is responsive, but does not render correctly on // retina displays: https://bugreports.qt.io/browse/QTBUG-36825 // Subclass QToolButton, which lets us catch events and set icons as needed. StockIconToolButton::StockIconToolButton(QWidget * parent, QString stock_icon_name) : QToolButton(parent), leave_timer_(0) { setStockIcon(stock_icon_name); } void StockIconToolButton::setIconMode(QIcon::Mode mode) { QIcon mode_icon; QList states = QList() << QIcon::Off << QIcon::On; foreach (QIcon::State state, states) { foreach (QSize size, base_icon_.availableSizes(mode, state)) { mode_icon.addPixmap(base_icon_.pixmap(size, mode, state), mode, state); } } setIcon(mode_icon); } void StockIconToolButton::setStockIcon(QString icon_name) { if (!icon_name.isEmpty()) { icon_name_ = icon_name; } if (icon_name_.isEmpty()) { return; } base_icon_ = StockIcon(icon_name_); setIconMode(); } bool StockIconToolButton::event(QEvent *event) { switch (event->type()) { case QEvent::Enter: if (isEnabled()) { setIconMode(QIcon::Active); if (leave_timer_ > 0) killTimer(leave_timer_); leave_timer_ = startTimer(leave_interval_); } break; case QEvent::MouseButtonPress: if (isEnabled()) { setIconMode(QIcon::Selected); } break; case QEvent::Leave: if (leave_timer_ > 0) killTimer(leave_timer_); leave_timer_ = 0; // Fall through case QEvent::MouseButtonRelease: setIconMode(); break; case QEvent::Timer: { // We can lose QEvent::Leave, QEvent::HoverLeave and underMouse() // on macOS if a tooltip appears: // https://bugreports.qt.io/browse/QTBUG-46379 // Work around the issue by periodically checking the mouse // position and scheduling a fake leave event when the mouse // moves away. QTimerEvent *te = (QTimerEvent *) event; bool under_mouse = rect().contains(mapFromGlobal(QCursor::pos())); if (te->timerId() == leave_timer_ && !under_mouse) { killTimer(leave_timer_); leave_timer_ = 0; QMouseEvent *me = new QMouseEvent(QEvent::Leave, mapFromGlobal(QCursor::pos()), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QApplication::postEvent(this, me); } break; } case QEvent::ApplicationPaletteChange: setStockIcon(); break; default: break; } return QToolButton::event(event); } /* * Editor modelines * * Local Variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */