File indexing completed on 2024-04-28 15:31:54

0001 /*
0002     SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
0003     SPDX-FileCopyrightText: 2018 Michael Heidelbach <ottwolt@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "ktooltipwidgettest.h"
0009 
0010 #include <KToolTipWidget>
0011 
0012 #include <QLabel>
0013 #include <QLayout>
0014 #include <QLineEdit>
0015 #include <QScreen>
0016 #include <QSignalSpy>
0017 #include <QStyle>
0018 #include <QTest>
0019 
0020 void KToolTipWidgetTest::initTestCase()
0021 {
0022     m_screenGeometry = QGuiApplication::primaryScreen()->geometry();
0023 }
0024 
0025 void KToolTipWidgetTest::showTooltipShouldShowContent()
0026 {
0027     KToolTipWidget tooltip;
0028     QLabel label;
0029 
0030     tooltip.showAt(QPoint(10, 10), &label, nullptr);
0031     QVERIFY(tooltip.isVisible());
0032     QVERIFY(label.isVisible());
0033 }
0034 
0035 void KToolTipWidgetTest::hideLaterShouldHideAfterDelay()
0036 {
0037     KToolTipWidget tooltip;
0038     QLabel label;
0039 
0040     tooltip.showAt(QPoint(10, 10), &label, nullptr);
0041     QVERIFY(tooltip.isVisible());
0042     QVERIFY(label.isVisible());
0043 
0044     tooltip.hideLater();
0045     QVERIFY(tooltip.isVisible());
0046     QVERIFY(label.isVisible());
0047 
0048     QSignalSpy spy(&tooltip, &KToolTipWidget::hidden);
0049     connect(&tooltip, &KToolTipWidget::hidden, this, [&]() {
0050         QVERIFY(tooltip.isHidden());
0051         QVERIFY(!label.isVisible());
0052     });
0053 
0054     QEventLoop eventLoop;
0055     connect(&tooltip, &KToolTipWidget::hidden, &eventLoop, &QEventLoop::quit);
0056     QCOMPARE(eventLoop.exec(), 0);
0057     QCOMPARE(spy.count(), 1);
0058 }
0059 
0060 void KToolTipWidgetTest::setZeroDelayShouldHideImmediately()
0061 {
0062     KToolTipWidget tooltip;
0063     QLabel label;
0064 
0065     tooltip.setHideDelay(0);
0066     tooltip.showAt(QPoint(10, 10), &label, nullptr);
0067     QVERIFY(tooltip.isVisible());
0068     QVERIFY(label.isVisible());
0069 
0070     tooltip.hideLater();
0071     QVERIFY(tooltip.isHidden());
0072     QVERIFY(!label.isVisible());
0073 }
0074 
0075 void KToolTipWidgetTest::shouldHideImmediatelyIfContentDestroyed()
0076 {
0077     KToolTipWidget tooltip;
0078     auto lineEdit = new QLineEdit();
0079 
0080     tooltip.showAt(QPoint(10, 10), lineEdit, nullptr);
0081     QVERIFY(tooltip.isVisible());
0082 
0083     delete lineEdit;
0084     QVERIFY(tooltip.isHidden());
0085 }
0086 
0087 void KToolTipWidgetTest::shouldNotTakeOwnershipOfContent()
0088 {
0089     auto parent = new QWidget();
0090     auto label = new QLabel(parent);
0091     auto tooltip = new KToolTipWidget();
0092 
0093     tooltip->showAt(QPoint(10, 10), label, nullptr);
0094     QCOMPARE(label->parent(), tooltip);
0095     QVERIFY(label->isVisible());
0096 
0097     QSignalSpy spy(label, &QWidget::destroyed);
0098     delete tooltip;
0099     QVERIFY(!label->isVisible());
0100     QCOMPARE(label->parent(), parent);
0101     QCOMPARE(spy.count(), 0);
0102 
0103     delete parent;
0104     QCOMPARE(spy.count(), 1);
0105 }
0106 
0107 void KToolTipWidgetTest::shouldNotObscureTarget_data()
0108 {
0109     qDebug() << "Style used" << QApplication::style()->objectName();
0110 
0111     QTest::addColumn<QPoint>("position");
0112     QTest::addColumn<QString>("content");
0113 
0114     const QMap<QString, QPoint> positions{{QStringLiteral("topleft"), QPoint(m_offset, m_offset)},
0115                                           {QStringLiteral("topright"), QPoint(-m_offset, m_offset)},
0116                                           {QStringLiteral("bottomright"), QPoint(-m_offset, -m_offset)},
0117                                           {QStringLiteral("bottomleft"), QPoint(m_offset, -m_offset)},
0118                                           {QStringLiteral("centered"), QPoint(m_screenGeometry.width() / 2, m_screenGeometry.height() / 2)}};
0119 
0120     QMapIterator<QString, QPoint> i(positions);
0121     while (i.hasNext()) {
0122         i.next();
0123         QTest::newRow(qPrintable(QStringLiteral("small/%1").arg(i.key()))) << i.value() << QStringLiteral("dummy text");
0124 
0125         QTest::newRow(qPrintable(QStringLiteral("multiline/%1").arg(i.key()))) << i.value() << QStringLiteral("dummy text\nLine 1\nLine 2\nLine 3");
0126 
0127         QTest::newRow(qPrintable(QStringLiteral("one long line/%1").arg(i.key())))
0128             << i.value()
0129             << QStringLiteral(
0130                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec felis sed elit auctor lobortis non a urna. Quisque non posuere mauris. "
0131                    "Suspendisse potenti. In diam leo, lobortis at placerat nec, sagittis at tortor. Pellentesque scelerisque enim vel elementum scelerisque. "
0132                    "Integer eget lectus vitae lorem pulvinar hendrerit. Suspendisse auctor sapien vel semper porta. Vestibulum fringilla aliquet tincidunt. "
0133                    "Maecenas mollis mauris et erat viverra mollis. Proin suscipit felis nisi, a dapibus est hendrerit euismod. Suspendisse quis faucibus quam. "
0134                    "Fusce eu cursus magna, et egestas purus. Duis enim sapien, feugiat id facilisis non, rhoncus ut lectus. Aliquam at nisi vel ligula "
0135                    "interdum ultricies. Donec condimentum ante quam, eu congue lectus pulvinar in. Cras interdum, neque quis fermentum consequat, lectus "
0136                    "tellus eleifend turpis.");
0137 
0138         if (m_screenGeometry.width() >= 1600 && m_screenGeometry.height() >= 900) {
0139             QTest::newRow(qPrintable(QStringLiteral("super large/%1").arg(i.key())))
0140                 << i.value()
0141                 << QStringLiteral(
0142                        "dummy 0 text\nLine 1\nLine 2\nLine 3"
0143                        "dummy 1 text\nLine 1\nLine 2\nLine 3"
0144                        "dummy 2 text\nLine 1\nLine 2\nLine 3"
0145                        "dummy 3 text\nLine 1\nLine 2\nLine 3"
0146                        "dummy 4 text\nLine 1\nLine 2\nLine 3"
0147 
0148                        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec felis sed elit auctor lobortis non a urna. Quisque non posuere "
0149                        "mauris. Suspendisse potenti. In diam leo, lobortis at placerat nec, sagittis at tortor. Pellentesque scelerisque enim vel elementum "
0150                        "scelerisque. Integer eget lectus vitae lorem pulvinar hendrerit. Suspendisse auctor sapien vel semper porta. Vestibulum fringilla "
0151                        "aliquet tincidunt. Maecenas mollis mauris et erat viverra mollis. Proin suscipit felis nisi, a dapibus est hendrerit euismod. "
0152                        "Suspendisse quis faucibus quam. Fusce eu cursus magna, et egestas purus. Duis enim sapien, feugiat id facilisis non, rhoncus ut "
0153                        "lectus. Aliquam at nisi vel ligula interdum ultricies. Donec condimentum ante quam, eu congue lectus pulvinar in. Cras interdum, neque "
0154                        "quis fermentum consequat, lectus tellus eleifend turpis.");
0155         }
0156     }
0157 }
0158 
0159 void KToolTipWidgetTest::shouldNotObscureTarget()
0160 {
0161     QFETCH(QPoint, position);
0162     QFETCH(QString, content);
0163 
0164     QWidget *containerWidget = new QWidget();
0165     const int margin = containerWidget->style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth);
0166     QLabel *targetWidget = new QLabel(QStringLiteral("dummy file"));
0167     QLayout *layout = new QHBoxLayout(containerWidget);
0168     layout->addWidget(targetWidget);
0169 
0170     containerWidget->adjustSize();
0171     containerWidget->move(position.x() >= 0 ? position.x() : m_screenGeometry.right() + position.x() - containerWidget->width(),
0172                           position.y() >= 0 ? position.y() : m_screenGeometry.bottom() + position.y() - containerWidget->height());
0173     containerWidget->show();
0174     QVERIFY(QTest::qWaitForWindowExposed(containerWidget));
0175     QVERIFY(targetWidget->isVisible());
0176 
0177     QRect targetRect = QRect(targetWidget->frameGeometry());
0178     targetRect.moveTo(targetWidget->mapToGlobal(QPoint(0, 0)));
0179 
0180     QLabel *contentWidget = new QLabel(content);
0181 
0182     QVERIFY2(containerWidget->windowHandle(), "Container's window handle is invalid");
0183     KToolTipWidget tooltipWidget;
0184     tooltipWidget.showBelow(targetRect, contentWidget, containerWidget->windowHandle());
0185     QVERIFY(QTest::qWaitForWindowExposed(&tooltipWidget));
0186     const QRect tooltipRect = tooltipWidget.frameGeometry();
0187 
0188     qDebug() << QStringLiteral("tooltip: %1x%2 x=%3, y=%4").arg(tooltipRect.width()).arg(tooltipRect.height()).arg(tooltipRect.left()).arg(tooltipRect.top());
0189     qDebug() << QStringLiteral("target:  %1x%2 x=%3, y=%4").arg(targetRect.width()).arg(targetRect.height()).arg(targetRect.left()).arg(targetRect.top());
0190 
0191     QVERIFY2(!tooltipRect.intersects(targetRect), "Target obscured");
0192     QCOMPARE(tooltipRect.intersected(m_screenGeometry), tooltipRect);
0193 
0194     // Check margins
0195     if (tooltipRect.bottom() < targetRect.top()) {
0196         QCOMPARE(margin, targetRect.top() - tooltipRect.bottom());
0197     } else if (tooltipRect.top() > targetRect.bottom()) {
0198         QCOMPARE(margin, tooltipRect.top() - targetRect.bottom());
0199     } else if (tooltipRect.right() < targetRect.left()) {
0200         QCOMPARE(margin, targetRect.left() - tooltipRect.right());
0201     } else if (tooltipRect.left() > targetRect.right()) {
0202         QCOMPARE(margin, tooltipRect.left() - targetRect.right());
0203     }
0204 
0205     tooltipWidget.hide();
0206     QVERIFY(tooltipWidget.isHidden());
0207 
0208     delete contentWidget;
0209     delete containerWidget;
0210 }
0211 
0212 QTEST_MAIN(KToolTipWidgetTest)
0213 
0214 #include "moc_ktooltipwidgettest.cpp"