File indexing completed on 2024-10-13 12:17:29
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2018 Dominik Haumann <dhaumann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "inlinenote_test.h" 0009 #include "moc_inlinenote_test.cpp" 0010 0011 #include <katedocument.h> 0012 #include <kateglobal.h> 0013 #include <kateview.h> 0014 #include <ktexteditor/inlinenote.h> 0015 #include <ktexteditor/inlinenoteinterface.h> 0016 #include <ktexteditor/inlinenoteprovider.h> 0017 0018 #include <QPainter> 0019 #include <QTemporaryFile> 0020 #include <QtTestWidgets> 0021 0022 using namespace KTextEditor; 0023 0024 QTEST_MAIN(InlineNoteTest) 0025 0026 namespace 0027 { 0028 QWidget *findViewInternal(KTextEditor::View *view) 0029 { 0030 for (QObject *child : view->children()) { 0031 if (child->metaObject()->className() == QByteArrayLiteral("KateViewInternal")) { 0032 return qobject_cast<QWidget *>(child); 0033 } 0034 } 0035 return nullptr; 0036 } 0037 0038 class NoteProvider : public InlineNoteProvider 0039 { 0040 public: 0041 QVector<int> inlineNotes(int line) const override 0042 { 0043 if (line == 0) { 0044 return {5, 10}; 0045 } 0046 0047 return {}; 0048 } 0049 0050 QSize inlineNoteSize(const InlineNote ¬e) const override 0051 { 0052 if (note.position().column() == 5) { 0053 const auto xWidth = QFontMetrics(note.font()).boundingRect(QStringLiteral("x")).width(); 0054 return QSize(xWidth, note.lineHeight()); 0055 } else if (note.position().column() == 10) { 0056 return QSize(note.lineHeight(), note.lineHeight()); 0057 } 0058 0059 return QSize(); 0060 } 0061 0062 void paintInlineNote(const InlineNote ¬e, QPainter &painter) const override 0063 { 0064 if (note.position().column() == 5) { 0065 painter.setPen(Qt::darkGreen); 0066 painter.setBrush(Qt::green); 0067 painter.drawEllipse(1, 1, note.width() - 2, note.lineHeight() - 2); 0068 } else if (note.position().column() == 10) { 0069 painter.setPen(Qt::darkRed); 0070 if (note.underMouse()) { 0071 painter.setBrush(Qt::red); 0072 } else { 0073 painter.setBrush(Qt::yellow); 0074 } 0075 painter.drawRoundedRect(1, 1, note.width() - 2, note.lineHeight() - 2, 2, 2); 0076 } 0077 } 0078 0079 void inlineNoteActivated(const InlineNote ¬e, Qt::MouseButtons buttons, const QPoint &globalPos) override 0080 { 0081 Q_UNUSED(buttons) 0082 Q_UNUSED(globalPos) 0083 ++noteActivatedCount; 0084 lastUnderMouse = note.underMouse(); 0085 } 0086 0087 void inlineNoteFocusInEvent(const InlineNote ¬e, const QPoint &globalPos) override 0088 { 0089 Q_UNUSED(globalPos) 0090 ++focusInCount; 0091 lastUnderMouse = note.underMouse(); 0092 } 0093 0094 void inlineNoteFocusOutEvent(const InlineNote ¬e) override 0095 { 0096 ++focusOutCount; 0097 // Here it should not be under the mosu 0098 lastUnderMouse = note.underMouse(); 0099 } 0100 0101 void inlineNoteMouseMoveEvent(const InlineNote ¬e, const QPoint &globalPos) override 0102 { 0103 Q_UNUSED(globalPos) 0104 ++mouseMoveCount; 0105 lastUnderMouse = note.underMouse(); 0106 } 0107 0108 public: 0109 int noteActivatedCount = 0; 0110 int focusInCount = 0; 0111 int focusOutCount = 0; 0112 int mouseMoveCount = 0; 0113 bool lastUnderMouse = false; 0114 }; 0115 } 0116 0117 InlineNoteTest::InlineNoteTest() 0118 : QObject() 0119 { 0120 KTextEditor::EditorPrivate::enableUnitTestMode(); 0121 } 0122 0123 InlineNoteTest::~InlineNoteTest() 0124 { 0125 } 0126 0127 void InlineNoteTest::testInlineNote() 0128 { 0129 KTextEditor::DocumentPrivate doc; 0130 doc.setText(QLatin1String("xxxxxxxxxx\nxxxxxxxxxx")); 0131 0132 KTextEditor::ViewPrivate view(&doc, nullptr); 0133 view.show(); 0134 0135 QTest::qWait(100); 0136 0137 view.setCursorPosition({0, 5}); 0138 QCOMPARE(view.cursorPosition(), Cursor(0, 5)); 0139 0140 const auto coordCol04 = view.cursorToCoordinate({0, 4}); 0141 const auto coordCol05 = view.cursorToCoordinate({0, 5}); 0142 const auto coordCol10 = view.cursorToCoordinate({0, 10}); 0143 QVERIFY(coordCol05.x() > coordCol04.x()); 0144 QVERIFY(coordCol10.x() > coordCol05.x()); 0145 0146 const auto xWidth = coordCol05.x() - coordCol04.x(); 0147 0148 auto iface = qobject_cast<KTextEditor::InlineNoteInterface *>(&view); 0149 QVERIFY(iface != nullptr); 0150 0151 NoteProvider noteProvider; 0152 const QVector<int> expectedColumns = {5, 10}; 0153 QCOMPARE(noteProvider.inlineNotes(0), expectedColumns); 0154 QCOMPARE(noteProvider.inlineNotes(1), QVector<int>()); 0155 iface->registerInlineNoteProvider(¬eProvider); 0156 0157 QTest::qWait(100); 0158 0159 const auto newCoordCol04 = view.cursorToCoordinate({0, 4}); 0160 const auto newCoordCol05 = view.cursorToCoordinate({0, 5}); 0161 const auto newCoordCol10 = view.cursorToCoordinate({0, 10}); 0162 0163 QVERIFY(newCoordCol05.x() > newCoordCol04.x()); 0164 QVERIFY(newCoordCol10.x() > newCoordCol05.x()); 0165 0166 QCOMPARE(newCoordCol04, coordCol04); 0167 QVERIFY(newCoordCol05.x() > coordCol05.x()); 0168 QVERIFY(newCoordCol10.x() > coordCol10.x()); 0169 0170 // so far, we should not have any activation event 0171 QCOMPARE(noteProvider.noteActivatedCount, 0); 0172 QCOMPARE(noteProvider.focusInCount, 0); 0173 QCOMPARE(noteProvider.focusOutCount, 0); 0174 QCOMPARE(noteProvider.mouseMoveCount, 0); 0175 QVERIFY(noteProvider.lastUnderMouse == false); 0176 0177 // ATM fails on Windows, mark as such to be able to enforce test success in CI 0178 #ifdef Q_OS_WIN 0179 QSKIP("Fails ATM, please fix"); 0180 #endif 0181 0182 // move mouse onto first note 0183 auto internalView = findViewInternal(&view); 0184 QVERIFY(internalView); 0185 0186 // focus in 0187 QTest::mouseMove(&view, coordCol05 + QPoint(xWidth / 2, 1)); 0188 QTest::qWait(100); 0189 QCOMPARE(noteProvider.focusInCount, 1); 0190 QCOMPARE(noteProvider.focusOutCount, 0); 0191 QCOMPARE(noteProvider.mouseMoveCount, 0); 0192 QCOMPARE(noteProvider.noteActivatedCount, 0); 0193 QVERIFY(noteProvider.lastUnderMouse); 0194 0195 // move one pixel 0196 QTest::mouseMove(&view, coordCol05 + QPoint(xWidth / 2 + 1, 1)); 0197 QTest::qWait(100); 0198 QCOMPARE(noteProvider.focusInCount, 1); 0199 QCOMPARE(noteProvider.focusOutCount, 0); 0200 QCOMPARE(noteProvider.mouseMoveCount, 1); 0201 QCOMPARE(noteProvider.noteActivatedCount, 0); 0202 QVERIFY(noteProvider.lastUnderMouse); 0203 0204 // activate 0205 QTest::mousePress(internalView, Qt::LeftButton, Qt::NoModifier, internalView->mapFromGlobal(view.mapToGlobal(coordCol05 + QPoint(xWidth / 2 + 1, 1)))); 0206 QTest::mouseRelease(internalView, Qt::LeftButton, Qt::NoModifier, internalView->mapFromGlobal(view.mapToGlobal(coordCol05 + QPoint(xWidth / 2 + 1, 1)))); 0207 QTest::qWait(100); 0208 QCOMPARE(noteProvider.focusInCount, 1); 0209 QCOMPARE(noteProvider.focusOutCount, 0); 0210 QCOMPARE(noteProvider.mouseMoveCount, 1); 0211 QCOMPARE(noteProvider.noteActivatedCount, 1); 0212 QVERIFY(noteProvider.lastUnderMouse); 0213 0214 // focus out 0215 QTest::mouseMove(&view, coordCol04 + QPoint(0, 1)); 0216 QTest::mouseMove(&view, coordCol04 + QPoint(-1, 1)); 0217 QTest::qWait(200); 0218 QCOMPARE(noteProvider.focusInCount, 1); 0219 QCOMPARE(noteProvider.focusOutCount, 1); 0220 QCOMPARE(noteProvider.mouseMoveCount, 1); 0221 QCOMPARE(noteProvider.noteActivatedCount, 1); 0222 QVERIFY(noteProvider.lastUnderMouse == false); 0223 0224 iface->unregisterInlineNoteProvider(¬eProvider); 0225 } 0226 0227 // kate: indent-mode cstyle; indent-width 4; replace-tabs on;