File indexing completed on 2024-05-12 05:46:54

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