2019-10-13 20:20:32 +02:00
|
|
|
#include <QToolTip>
|
|
|
|
#include <QStyle>
|
|
|
|
#include <QStylePainter>
|
|
|
|
#include <QStyleOptionFrame>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QMouseEvent>
|
2020-12-22 22:09:09 +01:00
|
|
|
#include <QBasicTimer>
|
|
|
|
#include <QScreen>
|
2021-08-04 08:57:42 +02:00
|
|
|
#include <QVBoxLayout>
|
2019-10-13 20:20:32 +02:00
|
|
|
#include <QApplication>
|
2020-12-22 22:09:09 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
2019-10-13 20:20:32 +02:00
|
|
|
#include <QDesktopWidget>
|
2020-12-22 22:09:09 +01:00
|
|
|
#endif // QT 5.15
|
2021-08-04 08:57:42 +02:00
|
|
|
#include "tooltip.h"
|
|
|
|
#include "thumbnail.h"
|
|
|
|
#include "flowlayout.h"
|
2019-10-13 20:20:32 +02:00
|
|
|
#include "popup.h"
|
|
|
|
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
class PopupFrame : public QFrame
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
public:
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame(const ToolTip &toolTip, QWidget *parent = 0);
|
|
|
|
~PopupFrame();
|
|
|
|
|
|
|
|
const ToolTip &toolTip() const {return _toolTip;}
|
2019-10-13 20:20:32 +02:00
|
|
|
|
|
|
|
bool eventFilter(QObject *o, QEvent *ev);
|
|
|
|
void place(const QPoint &pos, QWidget *w);
|
|
|
|
void deleteAfterTimer();
|
|
|
|
void stopTimer() {_timer.stop();}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
static PopupFrame *_instance;
|
2019-10-13 20:20:32 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
void paintEvent(QPaintEvent *event);
|
|
|
|
void timerEvent(QTimerEvent *event);
|
2019-10-14 00:07:57 +02:00
|
|
|
void contextMenuEvent(QContextMenuEvent *) {}
|
2019-10-13 20:20:32 +02:00
|
|
|
|
|
|
|
private:
|
2021-08-04 08:57:42 +02:00
|
|
|
void createLayout(const ToolTip &content);
|
|
|
|
|
2019-10-13 20:20:32 +02:00
|
|
|
QBasicTimer _timer;
|
2021-08-04 08:57:42 +02:00
|
|
|
ToolTip _toolTip;
|
2019-10-13 20:20:32 +02:00
|
|
|
};
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame *PopupFrame::_instance = 0;
|
2019-10-13 20:20:32 +02:00
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame::PopupFrame(const ToolTip &toolTip, QWidget *parent)
|
|
|
|
: QFrame(parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget
|
|
|
|
| Qt::WindowDoesNotAcceptFocus), _toolTip(toolTip)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
delete _instance;
|
|
|
|
_instance = this;
|
|
|
|
|
|
|
|
setForegroundRole(QPalette::ToolTipText);
|
|
|
|
setBackgroundRole(QPalette::ToolTipBase);
|
|
|
|
setPalette(QToolTip::palette());
|
|
|
|
ensurePolished();
|
2021-08-04 08:57:42 +02:00
|
|
|
|
2019-10-13 20:20:32 +02:00
|
|
|
setFrameStyle(QFrame::NoFrame);
|
|
|
|
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0,
|
|
|
|
this) / 255.0);
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
createLayout(toolTip);
|
2019-10-13 20:20:32 +02:00
|
|
|
|
|
|
|
setMouseTracking(true);
|
|
|
|
|
|
|
|
qApp->installEventFilter(this);
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame::~PopupFrame()
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
_instance = 0;
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
void PopupFrame::createLayout(const ToolTip &content)
|
|
|
|
{
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout();
|
|
|
|
int margin = 1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0,
|
|
|
|
this);
|
|
|
|
layout->setContentsMargins(margin, margin, margin, margin);
|
|
|
|
layout->setSpacing(0);
|
|
|
|
|
|
|
|
if (!content.images().isEmpty()) {
|
|
|
|
FlowLayout *imagesLayout = new FlowLayout(0, 2, 2);
|
|
|
|
int size = qMin(960/content.images().size(), 240);
|
|
|
|
|
|
|
|
for (int i = 0; i < content.images().size(); i++)
|
|
|
|
imagesLayout->addWidget(new Thumbnail(content.images().at(i), size));
|
|
|
|
|
|
|
|
layout->addLayout(imagesLayout);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!content.list().isEmpty()) {
|
|
|
|
QString html = "<table>";
|
|
|
|
for (int i = 0; i < content.list().count(); i++)
|
|
|
|
html += "<tr><td align=\"right\"><b>" + content.list().at(i).key()
|
|
|
|
+ ": </b></td><td>" + content.list().at(i).value()
|
|
|
|
+ "</td></tr>";
|
|
|
|
html += "</table>";
|
|
|
|
|
|
|
|
QLabel *label = new QLabel(html);
|
|
|
|
label->setAlignment(Qt::AlignLeft);
|
|
|
|
label->setIndent(1);
|
|
|
|
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
|
|
label->setOpenExternalLinks(true);
|
|
|
|
label->setWordWrap(true);
|
|
|
|
|
|
|
|
layout->addWidget(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
setLayout(layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PopupFrame::paintEvent(QPaintEvent *event)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
QStylePainter p(this);
|
|
|
|
QStyleOptionFrame opt;
|
2020-12-22 22:09:09 +01:00
|
|
|
opt.initFrom(this);
|
2019-10-13 20:20:32 +02:00
|
|
|
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
|
|
|
|
p.end();
|
2021-08-04 08:57:42 +02:00
|
|
|
QFrame::paintEvent(event);
|
2019-10-13 20:20:32 +02:00
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
void PopupFrame::timerEvent(QTimerEvent *event)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
if (event->timerId() == _timer.timerId()) {
|
|
|
|
_timer.stop();
|
|
|
|
deleteLater();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
bool PopupFrame::eventFilter(QObject *o, QEvent *ev)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
Q_UNUSED(o);
|
|
|
|
|
|
|
|
switch (ev->type()) {
|
|
|
|
case QEvent::KeyPress:
|
|
|
|
case QEvent::KeyRelease: {
|
|
|
|
const int key = static_cast<QKeyEvent *>(ev)->key();
|
|
|
|
if (key == Qt::Key_Escape) {
|
|
|
|
deleteLater();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::FocusIn:
|
|
|
|
case QEvent::FocusOut:
|
|
|
|
case QEvent::WindowActivate:
|
|
|
|
case QEvent::WindowDeactivate:
|
|
|
|
case QEvent::Close:
|
|
|
|
deleteLater();
|
|
|
|
break;
|
|
|
|
case QEvent::MouseMove: {
|
|
|
|
QRectF r(geometry().adjusted(-5, -20, 5, 20));
|
2019-10-14 00:07:57 +02:00
|
|
|
QPointF p(static_cast<QMouseEvent*>(ev)->globalPos());
|
2019-10-13 20:20:32 +02:00
|
|
|
if (!r.contains(p))
|
|
|
|
deleteAfterTimer();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
void PopupFrame::place(const QPoint &pos, QWidget *w)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
2020-12-22 22:09:09 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
2019-10-13 20:20:32 +02:00
|
|
|
QRect screen = QApplication::desktop()->screenGeometry(w);
|
2020-12-22 22:09:09 +01:00
|
|
|
#else // QT 5.15
|
|
|
|
QRect screen = w->screen()->geometry();
|
|
|
|
#endif // QT 5.15
|
2019-10-13 20:20:32 +02:00
|
|
|
QPoint p(pos.x() + 2, pos.y() + 16);
|
|
|
|
|
|
|
|
if (p.x() + width() > screen.x() + screen.width())
|
|
|
|
p.rx() -= 4 + width();
|
|
|
|
if (p.y() + height() > screen.y() + screen.height())
|
|
|
|
p.ry() -= 24 + height();
|
|
|
|
if (p.y() < screen.y())
|
|
|
|
p.setY(screen.y());
|
|
|
|
if (p.x() + width() > screen.x() + screen.width())
|
|
|
|
p.setX(screen.x() + screen.width() - width());
|
|
|
|
if (p.x() < screen.x())
|
|
|
|
p.setX(screen.x());
|
|
|
|
if (p.y() + height() > screen.y() + screen.height())
|
|
|
|
p.setY(screen.y() + screen.height() - height());
|
|
|
|
|
|
|
|
this->move(p);
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
void PopupFrame::deleteAfterTimer()
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
|
|
|
if (!_timer.isActive())
|
|
|
|
_timer.start(300, this);
|
|
|
|
}
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
void Popup::show(const QPoint &pos, const ToolTip &toolTip, QWidget *w)
|
2019-10-13 20:20:32 +02:00
|
|
|
{
|
2021-08-04 08:57:42 +02:00
|
|
|
if (toolTip.isEmpty())
|
2021-02-08 19:53:24 +01:00
|
|
|
return;
|
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
if (PopupFrame::_instance) {
|
|
|
|
if (toolTip == PopupFrame::_instance->toolTip())
|
|
|
|
PopupFrame::_instance->stopTimer();
|
|
|
|
else {
|
|
|
|
delete PopupFrame::_instance;
|
|
|
|
PopupFrame::_instance = new PopupFrame(toolTip);
|
|
|
|
}
|
2019-10-14 00:07:57 +02:00
|
|
|
} else
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame::_instance = new PopupFrame(toolTip);
|
2019-10-13 20:20:32 +02:00
|
|
|
|
2021-08-04 08:57:42 +02:00
|
|
|
PopupFrame::_instance->resize(PopupFrame::_instance->sizeHint());
|
|
|
|
PopupFrame::_instance->place(pos, w);
|
|
|
|
PopupFrame::_instance->showNormal();
|
2019-10-13 20:20:32 +02:00
|
|
|
}
|
2019-12-23 16:16:15 +01:00
|
|
|
|
|
|
|
void Popup::clear()
|
|
|
|
{
|
2021-08-04 08:57:42 +02:00
|
|
|
if (PopupFrame::_instance)
|
|
|
|
delete PopupFrame::_instance;
|
2019-12-23 16:16:15 +01:00
|
|
|
}
|