File indexing completed on 2024-05-12 16:06:01
0001 /* 0002 SPDX-FileCopyrightText: 2020 Simone Gaiarin <simgunz@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // clazy:excludeall=qstring-allocations 0008 0009 #include <QTest> 0010 0011 #include <QMenu> 0012 #include <QTabBar> 0013 #include <QTabWidget> 0014 #include <QToolBar> 0015 #include <QWidget> 0016 0017 #include <KActionCollection> 0018 #include <KSelectAction> 0019 0020 #include "../core/page.h" 0021 #include "../part/pageview.h" 0022 #include "../part/part.h" 0023 #include "../part/toggleactionmenu.h" 0024 #include "../settings.h" 0025 #include "../shell/okular_main.h" 0026 #include "../shell/shell.h" 0027 #include "../shell/shellutils.h" 0028 #include "closedialoghelper.h" 0029 0030 namespace Okular 0031 { 0032 class PartTest 0033 { 0034 public: 0035 Okular::Document *partDocument(Okular::Part *part) const 0036 { 0037 return part->m_document; 0038 } 0039 PageView *pageView(Okular::Part *part) const 0040 { 0041 return part->m_pageView; 0042 } 0043 }; 0044 } 0045 0046 class AnnotationToolBarTest : public QObject, public Okular::PartTest 0047 { 0048 Q_OBJECT 0049 0050 public: 0051 static void initMain(); 0052 static QTabWidget *tabWidget(Shell *s) 0053 { 0054 return s->m_tabWidget; 0055 } 0056 0057 private Q_SLOTS: 0058 void initTestCase(); 0059 void init(); 0060 void cleanup(); 0061 0062 void testAnnotationToolBar(); 0063 void testAnnotationToolBar_data(); 0064 void testAnnotationToolBarActionsEnabledState(); 0065 void testAnnotationToolBarActionsEnabledState_data(); 0066 void testAnnotationToolBarConfigActionsEnabledState(); 0067 void testAnnotationToolBarConfigActionsEnabledState_data(); 0068 0069 private: 0070 bool simulateAddPopupAnnotation(Okular::Part *part, int mouseX, int mouseY); 0071 }; 0072 0073 Shell *findShell(Shell *ignore = nullptr) 0074 { 0075 const QWidgetList wList = QApplication::topLevelWidgets(); 0076 for (QWidget *widget : wList) { 0077 Shell *s = qobject_cast<Shell *>(widget); 0078 if (s && s != ignore) { 0079 return s; 0080 } 0081 } 0082 return nullptr; 0083 } 0084 0085 void AnnotationToolBarTest::initMain() 0086 { 0087 // Ensure consistent configs/caches and Default UI 0088 QTemporaryDir homeDir; 0089 Q_ASSERT(homeDir.isValid()); 0090 QByteArray homePath = QFile::encodeName(homeDir.path()); 0091 qputenv("USERPROFILE", homePath); 0092 qputenv("HOME", homePath); 0093 qputenv("XDG_DATA_HOME", QByteArray(homePath + "/.local")); 0094 qputenv("XDG_CONFIG_HOME", QByteArray(homePath + "/.kde-unit-test/xdg/config")); 0095 } 0096 0097 void AnnotationToolBarTest::initTestCase() 0098 { 0099 QStandardPaths::setTestModeEnabled(true); 0100 // Don't pollute people's okular settings 0101 Okular::Settings::instance(QStringLiteral("annotationtoolbartest")); 0102 } 0103 0104 void AnnotationToolBarTest::init() 0105 { 0106 // Default settings for every test 0107 Okular::Settings::self()->setDefaults(); 0108 } 0109 0110 void AnnotationToolBarTest::cleanup() 0111 { 0112 Shell *s; 0113 while ((s = findShell())) { 0114 delete s; 0115 } 0116 } 0117 0118 bool AnnotationToolBarTest::simulateAddPopupAnnotation(Okular::Part *part, int mouseX, int mouseY) 0119 { 0120 int annotationCount = partDocument(part)->page(0)->annotations().size(); 0121 QTest::mouseMove(pageView(part)->viewport(), QPoint(mouseX, mouseY)); 0122 QTest::mouseClick(pageView(part)->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(mouseX, mouseY)); 0123 bool annotationAdded = partDocument(part)->page(0)->annotations().size() == annotationCount + 1; 0124 return annotationAdded; 0125 } 0126 0127 void AnnotationToolBarTest::testAnnotationToolBar() 0128 { 0129 // Using tabs we test that the annotation toolbar works on each Okular::Part 0130 Okular::Settings::self()->setShellOpenFileInTabs(true); 0131 0132 const QStringList paths = {QStringLiteral(KDESRCDIR "data/file1.pdf"), QStringLiteral(KDESRCDIR "data/file2.pdf")}; 0133 QString serializedOptions = ShellUtils::serializeOptions(false, false, false, false, false, QString(), QString(), QString()); 0134 0135 Okular::Status status = Okular::main(paths, serializedOptions); 0136 QCOMPARE(status, Okular::Success); 0137 Shell *s = findShell(); 0138 QVERIFY(s); 0139 QVERIFY(QTest::qWaitForWindowExposed(s)); 0140 QFETCH(int, tabIndex); 0141 s->m_tabWidget->tabBar()->setCurrentIndex(tabIndex); 0142 Okular::Part *part = dynamic_cast<Okular::Part *>(s->m_tabs[tabIndex].part); 0143 QVERIFY(part); 0144 0145 QToolBar *annToolBar = s->findChild<QToolBar *>(QStringLiteral("annotationToolBar")); 0146 QVERIFY(annToolBar); 0147 0148 // Check config action default enabled states 0149 QAction *aQuickTools = part->actionCollection()->action(QStringLiteral("annotation_favorites")); 0150 QAction *aAddToQuickTools = part->actionCollection()->action(QStringLiteral("annotation_bookmark")); 0151 QAction *aAdvancedSettings = part->actionCollection()->action(QStringLiteral("annotation_settings_advanced")); 0152 QAction *aContinuousMode = part->actionCollection()->action(QStringLiteral("annotation_settings_pin")); 0153 QVERIFY(aQuickTools->isEnabled()); 0154 QVERIFY(!aAddToQuickTools->isEnabled()); 0155 QVERIFY(!aAdvancedSettings->isEnabled()); 0156 QVERIFY(aContinuousMode->isEnabled()); 0157 0158 // Ensure that the 'Quick Annotations' action is correctly populated 0159 // (at least the 'Configure Annotations...' action must be present) 0160 QVERIFY(!aQuickTools->menu()->actions().isEmpty()); 0161 0162 // Test annotation toolbar visibility triggers 0163 QAction *toggleAnnotationToolBar = part->actionCollection()->action(QStringLiteral("mouse_toggle_annotate")); 0164 QAction *aHideToolBar = part->actionCollection()->action(QStringLiteral("hide_annotation_toolbar")); 0165 QVERIFY(toggleAnnotationToolBar); 0166 QVERIFY(aHideToolBar); 0167 toggleAnnotationToolBar->setChecked(false); 0168 QTRY_VERIFY(!annToolBar->isVisible()); 0169 toggleAnnotationToolBar->trigger(); 0170 QTRY_VERIFY2(annToolBar->isVisible(), "Annotation action failed to show."); 0171 toggleAnnotationToolBar->trigger(); 0172 QTRY_VERIFY2(!annToolBar->isVisible(), "Annotation action failed to hide."); 0173 0174 toggleAnnotationToolBar->setChecked(true); 0175 QTRY_VERIFY(annToolBar->isVisible()); 0176 aHideToolBar->trigger(); 0177 QTRY_VERIFY2(!annToolBar->isVisible(), "Hide toolbar action failed to hide."); 0178 0179 toggleAnnotationToolBar->setChecked(false); 0180 QTRY_VERIFY(!annToolBar->isVisible()); 0181 QTest::keyClick(part->widget(), Qt::Key_1, Qt::AltModifier); 0182 QTRY_VERIFY2(annToolBar->isVisible(), "ToolBar not shown when triggering annotation using shortcut."); 0183 toggleAnnotationToolBar->setChecked(false); 0184 QTRY_VERIFY(!annToolBar->isVisible()); 0185 QTest::keyClick(part->widget(), Qt::Key_3); 0186 QTRY_VERIFY2(!annToolBar->isVisible(), "ToolBar shown when triggering quick annotation using shortcut."); 0187 0188 // set mouse mode to browse before starting the tests on the annotation actions 0189 QAction *aMouseNormal = part->actionCollection()->action(QStringLiteral("mouse_drag")); 0190 QVERIFY(aMouseNormal); 0191 aMouseNormal->trigger(); 0192 QTRY_COMPARE(Okular::Settings::mouseMode(), static_cast<int>(Okular::Settings::EnumMouseMode::Browse)); 0193 0194 // Click an annotation action to enable it 0195 QAction *aPopupNote = part->actionCollection()->action(QStringLiteral("annotation_popup_note")); 0196 QVERIFY(aPopupNote); 0197 aPopupNote->trigger(); 0198 int mouseX = 350; 0199 int mouseY = 100; 0200 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0201 QTRY_COMPARE(aMouseNormal->isChecked(), false); 0202 0203 // Click again the same annotation action to disable it 0204 aPopupNote->trigger(); 0205 mouseY = 150; 0206 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), false); 0207 QTRY_COMPARE(aMouseNormal->isChecked(), true); 0208 0209 // Trigger the action using a shortcut 0210 QTest::keyClick(part->widget(), Qt::Key_7, Qt::AltModifier); 0211 mouseY = 200; 0212 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0213 QTRY_COMPARE(aMouseNormal->isChecked(), false); 0214 0215 // Click Esc to disable all annotations 0216 QTest::keyClick(pageView(part), Qt::Key_Escape); 0217 mouseY = 250; 0218 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), false); 0219 QTRY_COMPARE(aMouseNormal->isChecked(), true); 0220 0221 // Trigger the action using a quick annotation shortcut 0222 QTest::keyClick(part->widget(), Qt::Key_6); 0223 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0224 QTRY_COMPARE(aMouseNormal->isChecked(), false); 0225 0226 // Test pin/continuous mode action 0227 QVERIFY(aContinuousMode->isEnabled()); 0228 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0229 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0230 aContinuousMode->trigger(); 0231 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0232 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), false); 0233 0234 // Test adding a tool to the quick tool list using the bookmark action 0235 QScopedPointer<TestingUtils::CloseDialogHelper> closeDialogHelper; 0236 closeDialogHelper.reset(new TestingUtils::CloseDialogHelper(QDialogButtonBox::Ok)); 0237 aPopupNote->trigger(); 0238 QVERIFY(aPopupNote->isChecked()); 0239 int quickActionCount = aQuickTools->menu()->actions().size(); 0240 aAddToQuickTools->trigger(); 0241 QTRY_COMPARE(aQuickTools->menu()->actions().size(), quickActionCount + 1); 0242 // Trigger the quick tool that was just added 0243 aQuickTools->menu()->actions().at(6)->trigger(); 0244 QCOMPARE(simulateAddPopupAnnotation(part, mouseX, mouseY), true); 0245 } 0246 0247 void AnnotationToolBarTest::testAnnotationToolBar_data() 0248 { 0249 QTest::addColumn<int>("tabIndex"); 0250 QTest::addRow("first tab") << 0; 0251 QTest::addRow("second tab") << 1; 0252 } 0253 0254 void AnnotationToolBarTest::testAnnotationToolBarActionsEnabledState() 0255 { 0256 QFETCH(QString, document); 0257 0258 const QStringList paths = {document}; 0259 QString serializedOptions = ShellUtils::serializeOptions(false, false, false, false, false, QString(), QString(), QString()); 0260 0261 Okular::Status status = Okular::main(paths, serializedOptions); 0262 QCOMPARE(status, Okular::Success); 0263 Shell *s = findShell(); 0264 QVERIFY(s); 0265 QVERIFY(QTest::qWaitForWindowExposed(s)); 0266 0267 Okular::Part *part = s->findChild<Okular::Part *>(); 0268 QVERIFY(part); 0269 0270 KActionCollection *ac = part->actionCollection(); 0271 QAction *aQuickTools = ac->action(QStringLiteral("annotation_favorites")); 0272 QAction *aHighlighter = ac->action(QStringLiteral("annotation_highlighter")); 0273 QAction *aUnderline = ac->action(QStringLiteral("annotation_underline")); 0274 QAction *aSquiggle = ac->action(QStringLiteral("annotation_squiggle")); 0275 QAction *aStrikeout = ac->action(QStringLiteral("annotation_strike_out")); 0276 QAction *aTypewriter = ac->action(QStringLiteral("annotation_typewriter")); 0277 QAction *aInlineNote = ac->action(QStringLiteral("annotation_inline_note")); 0278 QAction *aPopupNote = ac->action(QStringLiteral("annotation_popup_note")); 0279 QAction *aFreehandLine = ac->action(QStringLiteral("annotation_freehand_line")); 0280 QAction *aGeomShapes = ac->action(QStringLiteral("annotation_geometrical_shape")); 0281 QAction *aStamp = ac->action(QStringLiteral("annotation_stamp")); 0282 0283 QFETCH(bool, aQuickToolsEnabled); 0284 QFETCH(bool, aHighlighterEnabled); 0285 QFETCH(bool, aUnderlineEnabled); 0286 QFETCH(bool, aSquiggleEnabled); 0287 QFETCH(bool, aStrikeoutEnabled); 0288 QFETCH(bool, aTypewriterEnabled); 0289 QFETCH(bool, aInlineNoteEnabled); 0290 QFETCH(bool, aPopupNoteEnabled); 0291 QFETCH(bool, aFreehandLineEnabled); 0292 QFETCH(bool, aGeomShapesEnabled); 0293 QFETCH(bool, aStampEnabled); 0294 0295 QCOMPARE(aQuickTools->isEnabled(), aQuickToolsEnabled); 0296 QCOMPARE(aHighlighter->isEnabled(), aHighlighterEnabled); 0297 QCOMPARE(aUnderline->isEnabled(), aUnderlineEnabled); 0298 QCOMPARE(aSquiggle->isEnabled(), aSquiggleEnabled); 0299 QCOMPARE(aStrikeout->isEnabled(), aStrikeoutEnabled); 0300 QCOMPARE(aTypewriter->isEnabled(), aTypewriterEnabled); 0301 QCOMPARE(aInlineNote->isEnabled(), aInlineNoteEnabled); 0302 QCOMPARE(aPopupNote->isEnabled(), aPopupNoteEnabled); 0303 QCOMPARE(aFreehandLine->isEnabled(), aFreehandLineEnabled); 0304 QCOMPARE(aGeomShapes->isEnabled(), aGeomShapesEnabled); 0305 QCOMPARE(aStamp->isEnabled(), aStampEnabled); 0306 0307 // trigger a reparsing of the tools to ensure that the enabled/disabled state is not changed (bug: 424296) 0308 QAction *aMouseSelect = ac->action(QStringLiteral("mouse_select")); 0309 QAction *aMouseNormal = ac->action(QStringLiteral("mouse_drag")); 0310 aMouseSelect->trigger(); 0311 aMouseNormal->trigger(); 0312 0313 QCOMPARE(aQuickTools->isEnabled(), aQuickToolsEnabled); 0314 QCOMPARE(aHighlighter->isEnabled(), aHighlighterEnabled); 0315 QCOMPARE(aUnderline->isEnabled(), aUnderlineEnabled); 0316 QCOMPARE(aSquiggle->isEnabled(), aSquiggleEnabled); 0317 QCOMPARE(aStrikeout->isEnabled(), aStrikeoutEnabled); 0318 QCOMPARE(aTypewriter->isEnabled(), aTypewriterEnabled); 0319 QCOMPARE(aInlineNote->isEnabled(), aInlineNoteEnabled); 0320 QCOMPARE(aPopupNote->isEnabled(), aPopupNoteEnabled); 0321 QCOMPARE(aFreehandLine->isEnabled(), aFreehandLineEnabled); 0322 QCOMPARE(aGeomShapes->isEnabled(), aGeomShapesEnabled); 0323 QCOMPARE(aStamp->isEnabled(), aStampEnabled); 0324 } 0325 0326 void AnnotationToolBarTest::testAnnotationToolBarActionsEnabledState_data() 0327 { 0328 QTest::addColumn<QString>("document"); 0329 QTest::addColumn<bool>("aQuickToolsEnabled"); 0330 QTest::addColumn<bool>("aHighlighterEnabled"); 0331 QTest::addColumn<bool>("aUnderlineEnabled"); 0332 QTest::addColumn<bool>("aSquiggleEnabled"); 0333 QTest::addColumn<bool>("aStrikeoutEnabled"); 0334 QTest::addColumn<bool>("aTypewriterEnabled"); 0335 QTest::addColumn<bool>("aInlineNoteEnabled"); 0336 QTest::addColumn<bool>("aPopupNoteEnabled"); 0337 QTest::addColumn<bool>("aFreehandLineEnabled"); 0338 QTest::addColumn<bool>("aGeomShapesEnabled"); 0339 QTest::addColumn<bool>("aStampEnabled"); 0340 0341 QTest::addRow("pdf") << QStringLiteral(KDESRCDIR "data/file1.pdf") << true << true << true << true << true << true << true << true << true << true << true; 0342 QTest::addRow("protected-pdf") << QStringLiteral(KDESRCDIR "data/protected.pdf") << false << false << false << false << false << false << false << false << false << false << false; 0343 QTest::addRow("image") << QStringLiteral(KDESRCDIR "data/potato.jpg") << true << false << false << false << false << true << true << true << true << true << true; 0344 } 0345 0346 void AnnotationToolBarTest::testAnnotationToolBarConfigActionsEnabledState() 0347 { 0348 const QStringList paths = {QStringLiteral(KDESRCDIR "data/file1.pdf")}; 0349 QString serializedOptions = ShellUtils::serializeOptions(false, false, false, false, false, QString(), QString(), QString()); 0350 0351 Okular::Status status = Okular::main(paths, serializedOptions); 0352 QCOMPARE(status, Okular::Success); 0353 Shell *s = findShell(); 0354 QVERIFY(s); 0355 QVERIFY(QTest::qWaitForWindowExposed(s)); 0356 0357 Okular::Part *part = s->findChild<Okular::Part *>(); 0358 QVERIFY(part); 0359 0360 KActionCollection *ac = part->actionCollection(); 0361 QAction *aWidth = ac->action(QStringLiteral("annotation_settings_width")); 0362 QAction *aColor = ac->action(QStringLiteral("annotation_settings_color")); 0363 QAction *aInnerColor = ac->action(QStringLiteral("annotation_settings_inner_color")); 0364 QAction *aOpacity = ac->action(QStringLiteral("annotation_settings_opacity")); 0365 QAction *aFont = ac->action(QStringLiteral("annotation_settings_font")); 0366 0367 QFETCH(QString, annotationActionName); 0368 QFETCH(bool, widthEnabled); 0369 QFETCH(bool, colorEnabled); 0370 QFETCH(bool, innerColorEnabled); 0371 QFETCH(bool, opacityEnabled); 0372 QFETCH(bool, fontEnabled); 0373 0374 QAction *annotationAction = ac->action(annotationActionName); 0375 annotationAction->trigger(); 0376 0377 QCOMPARE(aWidth->isEnabled(), widthEnabled); 0378 QCOMPARE(aColor->isEnabled(), colorEnabled); 0379 QCOMPARE(aInnerColor->isEnabled(), innerColorEnabled); 0380 QCOMPARE(aOpacity->isEnabled(), opacityEnabled); 0381 QCOMPARE(aFont->isEnabled(), fontEnabled); 0382 } 0383 0384 void AnnotationToolBarTest::testAnnotationToolBarConfigActionsEnabledState_data() 0385 { 0386 QTest::addColumn<QString>("annotationActionName"); 0387 QTest::addColumn<bool>("widthEnabled"); 0388 QTest::addColumn<bool>("colorEnabled"); 0389 QTest::addColumn<bool>("innerColorEnabled"); 0390 QTest::addColumn<bool>("opacityEnabled"); 0391 QTest::addColumn<bool>("fontEnabled"); 0392 0393 QTest::addRow("annotation_highlighter") << QStringLiteral("annotation_highlighter") << false << true << false << true << false; 0394 QTest::addRow("annotation_underline") << QStringLiteral("annotation_underline") << false << true << false << true << false; 0395 QTest::addRow("annotation_squiggle") << QStringLiteral("annotation_squiggle") << false << true << false << true << false; 0396 QTest::addRow("annotation_strike_out") << QStringLiteral("annotation_strike_out") << false << true << false << true << false; 0397 QTest::addRow("annotation_typewriter") << QStringLiteral("annotation_typewriter") << false << true << false << true << true; 0398 QTest::addRow("annotation_inline_note") << QStringLiteral("annotation_inline_note") << false << true << false << true << true; 0399 QTest::addRow("annotation_popup_note") << QStringLiteral("annotation_popup_note") << false << true << false << true << false; 0400 QTest::addRow("annotation_freehand_line") << QStringLiteral("annotation_freehand_line") << true << true << false << true << false; 0401 QTest::addRow("annotation_line") << QStringLiteral("annotation_straight_line") << true << true << false << true << false; 0402 QTest::addRow("annotation_rectangle") << QStringLiteral("annotation_rectangle") << true << true << true << true << false; 0403 } 0404 0405 QTEST_MAIN(AnnotationToolBarTest) 0406 #include "annotationtoolbartest.moc"