Changeset View
Changeset View
Standalone View
Standalone View
autotests/parttest.cpp
Show All 13 Lines | |||||
14 | 14 | | |||
15 | #include "../core/annotations.h" | 15 | #include "../core/annotations.h" | ||
16 | #include "../core/form.h" | 16 | #include "../core/form.h" | ||
17 | #include "../core/page.h" | 17 | #include "../core/page.h" | ||
18 | #include "../part.h" | 18 | #include "../part.h" | ||
19 | #include "../ui/toc.h" | 19 | #include "../ui/toc.h" | ||
20 | #include "../ui/sidebar.h" | 20 | #include "../ui/sidebar.h" | ||
21 | #include "../ui/pageview.h" | 21 | #include "../ui/pageview.h" | ||
22 | #include "../ui/presentationwidget.h" | ||||
23 | #include "../settings.h" | ||||
22 | 24 | | |||
23 | #include "../generators/poppler/config-okular-poppler.h" | 25 | #include "../generators/poppler/config-okular-poppler.h" | ||
24 | 26 | | |||
25 | #include <KActionCollection> | 27 | #include <KActionCollection> | ||
26 | #include <KConfigDialog> | 28 | #include <KConfigDialog> | ||
27 | #include <KParts/OpenUrlArguments> | 29 | #include <KParts/OpenUrlArguments> | ||
28 | 30 | | |||
31 | #include <QApplication> | ||||
29 | #include <QClipboard> | 32 | #include <QClipboard> | ||
30 | #include <QMessageBox> | 33 | #include <QMessageBox> | ||
31 | #include <QPushButton> | 34 | #include <QPushButton> | ||
32 | #include <QScrollBar> | 35 | #include <QScrollBar> | ||
36 | #include <QTabletEvent> | ||||
33 | #include <QTemporaryDir> | 37 | #include <QTemporaryDir> | ||
34 | #include <QTextEdit> | 38 | #include <QTextEdit> | ||
35 | #include <QTreeView> | 39 | #include <QTreeView> | ||
36 | #include <QUrl> | 40 | #include <QUrl> | ||
37 | #include <QDesktopServices> | 41 | #include <QDesktopServices> | ||
38 | #include <QMenu> | 42 | #include <QMenu> | ||
39 | 43 | | |||
40 | class CloseDialogHelper : public QObject | 44 | class CloseDialogHelper : public QObject | ||
41 | { | 45 | { | ||
42 | Q_OBJECT | 46 | Q_OBJECT | ||
43 | 47 | | |||
44 | public: | 48 | public: | ||
45 | CloseDialogHelper(Okular::Part *p, QDialogButtonBox::StandardButton b) : m_part(p), m_button(b), m_clicked(false) | 49 | CloseDialogHelper(Okular::Part *p, QDialogButtonBox::StandardButton b) : m_widget(p->widget()), m_button(b), m_clicked(false) | ||
50 | { | ||||
51 | QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog); | ||||
52 | } | ||||
53 | | ||||
54 | CloseDialogHelper(QWidget *w, QDialogButtonBox::StandardButton b) : m_widget(w), m_button(b), m_clicked(false) | ||||
46 | { | 55 | { | ||
47 | QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog); | 56 | QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog); | ||
48 | } | 57 | } | ||
49 | 58 | | |||
50 | ~CloseDialogHelper() | 59 | ~CloseDialogHelper() | ||
51 | { | 60 | { | ||
52 | QVERIFY(m_clicked); | 61 | QVERIFY(m_clicked); | ||
53 | } | 62 | } | ||
54 | 63 | | |||
55 | private slots: | 64 | private slots: | ||
56 | void closeDialog() | 65 | void closeDialog() | ||
57 | { | 66 | { | ||
58 | QDialog *dialog = m_part->widget()->findChild<QDialog*>(); | 67 | QDialog *dialog = m_widget->findChild<QDialog*>(); | ||
59 | if (!dialog) { | 68 | if (!dialog) { | ||
60 | QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog); | 69 | QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog); | ||
61 | return; | 70 | return; | ||
62 | } | 71 | } | ||
63 | QDialogButtonBox *buttonBox = dialog->findChild<QDialogButtonBox*>(); | 72 | QDialogButtonBox *buttonBox = dialog->findChild<QDialogButtonBox*>(); | ||
64 | buttonBox->button(m_button)->click(); | 73 | buttonBox->button(m_button)->click(); | ||
65 | m_clicked = true; | 74 | m_clicked = true; | ||
66 | } | 75 | } | ||
67 | 76 | | |||
68 | private: | 77 | private: | ||
69 | Okular::Part *m_part; | 78 | QWidget *m_widget; | ||
70 | QDialogButtonBox::StandardButton m_button; | 79 | QDialogButtonBox::StandardButton m_button; | ||
71 | bool m_clicked; | 80 | bool m_clicked; | ||
72 | }; | 81 | }; | ||
73 | 82 | | |||
74 | namespace Okular | 83 | namespace Okular | ||
75 | { | 84 | { | ||
76 | class PartTest | 85 | class PartTest | ||
77 | : public QObject | 86 | : public QObject | ||
Show All 17 Lines | 95 | private slots: | |||
95 | void testOpenUrlArguments(); | 104 | void testOpenUrlArguments(); | ||
96 | void test388288(); | 105 | void test388288(); | ||
97 | void testSaveAs(); | 106 | void testSaveAs(); | ||
98 | void testSaveAs_data(); | 107 | void testSaveAs_data(); | ||
99 | void testSaveAsToNonExistingPath(); | 108 | void testSaveAsToNonExistingPath(); | ||
100 | void testSaveAsToSymlink(); | 109 | void testSaveAsToSymlink(); | ||
101 | void testSaveIsSymlink(); | 110 | void testSaveIsSymlink(); | ||
102 | void testSidebarItemAfterSaving(); | 111 | void testSidebarItemAfterSaving(); | ||
112 | void testViewModeSavingPerFile(); | ||||
103 | void testSaveAsUndoStackAnnotations(); | 113 | void testSaveAsUndoStackAnnotations(); | ||
104 | void testSaveAsUndoStackAnnotations_data(); | 114 | void testSaveAsUndoStackAnnotations_data(); | ||
105 | void testSaveAsUndoStackForms(); | 115 | void testSaveAsUndoStackForms(); | ||
106 | void testSaveAsUndoStackForms_data(); | 116 | void testSaveAsUndoStackForms_data(); | ||
107 | void testMouseMoveOverLinkWhileInSelectionMode(); | 117 | void testMouseMoveOverLinkWhileInSelectionMode(); | ||
108 | void testClickUrlLinkWhileInSelectionMode(); | 118 | void testClickUrlLinkWhileInSelectionMode(); | ||
109 | void testeTextSelectionOverAndAcrossLinks_data(); | 119 | void testeTextSelectionOverAndAcrossLinks_data(); | ||
110 | void testeTextSelectionOverAndAcrossLinks(); | 120 | void testeTextSelectionOverAndAcrossLinks(); | ||
111 | void testClickUrlLinkWhileLinkTextIsSelected(); | 121 | void testClickUrlLinkWhileLinkTextIsSelected(); | ||
112 | void testRClickWhileLinkTextIsSelected(); | 122 | void testRClickWhileLinkTextIsSelected(); | ||
113 | void testRClickOverLinkWhileLinkTextIsSelected(); | 123 | void testRClickOverLinkWhileLinkTextIsSelected(); | ||
114 | void testRClickOnSelectionModeShoulShowFollowTheLinkMenu(); | 124 | void testRClickOnSelectionModeShoulShowFollowTheLinkMenu(); | ||
115 | void testClickAnywhereAfterSelectionShouldUnselect(); | 125 | void testClickAnywhereAfterSelectionShouldUnselect(); | ||
116 | void testeRectSelectionStartingOnLinks(); | 126 | void testeRectSelectionStartingOnLinks(); | ||
117 | void testCheckBoxReadOnly(); | 127 | void testCheckBoxReadOnly(); | ||
118 | void testCrashTextEditDestroy(); | 128 | void testCrashTextEditDestroy(); | ||
119 | void testAnnotWindow(); | 129 | void testAnnotWindow(); | ||
120 | void testAdditionalActionTriggers(); | 130 | void testAdditionalActionTriggers(); | ||
121 | void testJumpToPage(); | 131 | void testJumpToPage(); | ||
132 | void testTabletProximityBehavior(); | ||||
122 | 133 | | |||
123 | private: | 134 | private: | ||
124 | void simulateMouseSelection(double startX, double startY, double endX, double endY, QWidget *target); | 135 | void simulateMouseSelection(double startX, double startY, double endX, double endY, QWidget *target); | ||
125 | }; | 136 | }; | ||
126 | 137 | | |||
127 | class PartThatHijacksQueryClose : public Okular::Part | 138 | class PartThatHijacksQueryClose : public Okular::Part | ||
128 | { | 139 | { | ||
129 | public: | 140 | public: | ||
▲ Show 20 Lines • Show All 914 Lines • ▼ Show 20 Line(s) | 1047 | { | |||
1044 | part.m_sidebar->setCurrentItem(currentSidebarItem); | 1055 | part.m_sidebar->setCurrentItem(currentSidebarItem); | ||
1045 | 1056 | | |||
1046 | part.saveAs(QUrl::fromLocalFile(QStringLiteral(KDESRCDIR "data/tocreload.pdf"))); | 1057 | part.saveAs(QUrl::fromLocalFile(QStringLiteral(KDESRCDIR "data/tocreload.pdf"))); | ||
1047 | 1058 | | |||
1048 | // Check it is still thumbnails after saving | 1059 | // Check it is still thumbnails after saving | ||
1049 | QCOMPARE(currentSidebarItem, part.m_sidebar->currentItem()); | 1060 | QCOMPARE(currentSidebarItem, part.m_sidebar->currentItem()); | ||
1050 | } | 1061 | } | ||
1051 | 1062 | | |||
1063 | void PartTest::testViewModeSavingPerFile() | ||||
1064 | { | ||||
1065 | QVariantList dummyArgs; | ||||
1066 | Okular::Part part( nullptr, nullptr, dummyArgs ); | ||||
1067 | | ||||
1068 | // Open some file | ||||
1069 | QVERIFY( openDocument( &part, QStringLiteral( KDESRCDIR "data/file1.pdf" ) ) ); | ||||
1070 | | ||||
1071 | // Switch to 'continuous' view mode | ||||
1072 | part.m_pageView->setCapability( Okular::View::ViewCapability::Continuous, QVariant( true ) ); | ||||
1073 | | ||||
1074 | // Close document | ||||
1075 | part.closeUrl(); | ||||
1076 | | ||||
1077 | // Open another file | ||||
1078 | QVERIFY( openDocument( &part, QStringLiteral( KDESRCDIR "data/file2.pdf" ) ) ); | ||||
1079 | | ||||
1080 | // Switch to 'non-continuous' mode | ||||
1081 | part.m_pageView->setCapability( Okular::View::ViewCapability::Continuous, QVariant( false ) ); | ||||
1082 | | ||||
1083 | // Close that document, too | ||||
1084 | part.closeUrl(); | ||||
1085 | | ||||
1086 | // Open first document again | ||||
1087 | QVERIFY( openDocument( &part, QStringLiteral( KDESRCDIR "data/file1.pdf" ) ) ); | ||||
1088 | | ||||
1089 | // If per-file view mode saving works, the view mode should be 'continuous' again. | ||||
1090 | QVERIFY( part.m_pageView->capability( Okular::View::ViewCapability::Continuous).toBool() ); | ||||
1091 | } | ||||
1092 | | ||||
1052 | void PartTest::testSaveAsUndoStackAnnotations() | 1093 | void PartTest::testSaveAsUndoStackAnnotations() | ||
1053 | { | 1094 | { | ||
1054 | QFETCH(QString, file); | 1095 | QFETCH(QString, file); | ||
1055 | QFETCH(QString, extension); | 1096 | QFETCH(QString, extension); | ||
1056 | QFETCH(bool, nativelySupportsAnnotations); | 1097 | QFETCH(bool, nativelySupportsAnnotations); | ||
1057 | QFETCH(bool, canSwapBackingFile); | 1098 | QFETCH(bool, canSwapBackingFile); | ||
1058 | QFETCH(bool, saveToArchive); | 1099 | QFETCH(bool, saveToArchive); | ||
1059 | 1100 | | |||
▲ Show 20 Lines • Show All 546 Lines • ▼ Show 20 Line(s) | 1575 | { | |||
1606 | // Verify that both windows are partially visible | 1647 | // Verify that both windows are partially visible | ||
1607 | QVERIFY( !win1->visibleRegion().isEmpty() ); | 1648 | QVERIFY( !win1->visibleRegion().isEmpty() ); | ||
1608 | QVERIFY( !win2->visibleRegion().isEmpty() ); | 1649 | QVERIFY( !win2->visibleRegion().isEmpty() ); | ||
1609 | 1650 | | |||
1610 | // Click the second annotation window to raise it (move mouse for visual feedback) | 1651 | // Click the second annotation window to raise it (move mouse for visual feedback) | ||
1611 | auto widget = win2->window()->childAt(win2->mapTo(win2->window(), QPoint(10, 10))); | 1652 | auto widget = win2->window()->childAt(win2->mapTo(win2->window(), QPoint(10, 10))); | ||
1612 | QTest::mouseMove(win2->window(), win2->mapTo(win2->window(), QPoint(10, 10))); | 1653 | QTest::mouseMove(win2->window(), win2->mapTo(win2->window(), QPoint(10, 10))); | ||
1613 | QTest::mouseClick(widget, Qt::LeftButton, Qt::NoModifier, widget->mapFrom(win2, QPoint(10, 10))); | 1654 | QTest::mouseClick(widget, Qt::LeftButton, Qt::NoModifier, widget->mapFrom(win2, QPoint(10, 10))); | ||
1614 | QVERIFY( win1->visibleRegion().rects().count() == 3); | 1655 | QVERIFY( win1->visibleRegion().rectCount() == 3); | ||
1615 | QVERIFY( win2->visibleRegion().rects().count() == 4); | 1656 | QVERIFY( win2->visibleRegion().rectCount() == 4); | ||
1616 | } | 1657 | } | ||
1617 | 1658 | | |||
1618 | // Helper for testAdditionalActionTriggers | 1659 | // Helper for testAdditionalActionTriggers | ||
1619 | static void verifyTargetStates( const QString & triggerName, | 1660 | static void verifyTargetStates( const QString & triggerName, | ||
1620 | const QMap<QString, Okular::FormField *> &fields, | 1661 | const QMap<QString, Okular::FormField *> &fields, | ||
1621 | bool focusVisible, bool cursorVisible, bool mouseVisible, | 1662 | bool focusVisible, bool cursorVisible, bool mouseVisible, | ||
1622 | int line) | 1663 | int line) | ||
1623 | { | 1664 | { | ||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Line(s) | 1797 | void PartTest::testJumpToPage() { | |||
1777 | /* | 1818 | /* | ||
1778 | * This is a test for a "known by trial" displacement. | 1819 | * This is a test for a "known by trial" displacement. | ||
1779 | * We'd need access to part.m_pageView->d->items[targetPage]->croppedGeometry().top(), | 1820 | * We'd need access to part.m_pageView->d->items[targetPage]->croppedGeometry().top(), | ||
1780 | * to determine the expected viewport position, but we don't have access. | 1821 | * to determine the expected viewport position, but we don't have access. | ||
1781 | */ | 1822 | */ | ||
1782 | QCOMPARE(part.m_pageView->verticalScrollBar()->value(), pageWithSpaceTop - 4); | 1823 | QCOMPARE(part.m_pageView->verticalScrollBar()->value(), pageWithSpaceTop - 4); | ||
1783 | } | 1824 | } | ||
1784 | 1825 | | |||
1826 | void PartTest::testTabletProximityBehavior() | ||||
1827 | { | ||||
1828 | QVariantList dummyArgs; | ||||
1829 | Okular::Part part{ nullptr, nullptr, dummyArgs }; | ||||
1830 | QVERIFY( openDocument( &part, QStringLiteral( KDESRCDIR "data/file1.pdf" ) ) ); | ||||
1831 | part.slotShowPresentation(); | ||||
1832 | PresentationWidget *w = part.m_presentationWidget; | ||||
1833 | QVERIFY( w ); | ||||
1834 | part.widget()->show(); | ||||
1835 | | ||||
1836 | // close the KMessageBox "There are two ways of exiting[...]" | ||||
1837 | CloseDialogHelper closeDialogHelper( w, QDialogButtonBox::Ok ); // confirm the "To leave, press ESC" | ||||
1838 | | ||||
1839 | QTabletEvent enterProximityEvent{ QEvent::TabletEnterProximity, | ||||
1840 | QPoint( 10, 10 ), QPoint( 10, 10 ), | ||||
1841 | QTabletEvent::Stylus, QTabletEvent::Pen, | ||||
1842 | 1., 0, 0, 1., 1., 0, | ||||
1843 | Qt::NoModifier, 0, Qt::NoButton, Qt::NoButton }; | ||||
1844 | QTabletEvent leaveProximityEvent{ QEvent::TabletLeaveProximity, | ||||
1845 | QPoint( 10, 10 ), QPoint( 10, 10 ), | ||||
1846 | QTabletEvent::Stylus, QTabletEvent::Pen, | ||||
1847 | 1., 0, 0, 1., 1., 0, | ||||
1848 | Qt::NoModifier, 0, Qt::NoButton, Qt::NoButton }; | ||||
1849 | | ||||
1850 | // Test with the Okular::Settings::EnumSlidesCursor::Visible setting | ||||
1851 | Okular::Settings::self()->setSlidesCursor( Okular::Settings::EnumSlidesCursor::Visible ); | ||||
1852 | | ||||
1853 | // Send an enterProximity event | ||||
1854 | qApp->notify( qApp, &enterProximityEvent ); | ||||
1855 | | ||||
1856 | // The cursor should be a cross-hair | ||||
1857 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::CrossCursor ) ); | ||||
1858 | | ||||
1859 | // Send a leaveProximity event | ||||
1860 | qApp->notify( qApp, &leaveProximityEvent ); | ||||
1861 | | ||||
1862 | // After the leaveProximityEvent, the cursor should be an arrow again, because | ||||
1863 | // we have set the slidesCursor mode to 'Visible' | ||||
1864 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::ArrowCursor ) ); | ||||
1865 | | ||||
1866 | | ||||
1867 | // Test with the Okular::Settings::EnumSlidesCursor::Hidden setting | ||||
1868 | Okular::Settings::self()->setSlidesCursor( Okular::Settings::EnumSlidesCursor::Hidden ); | ||||
1869 | | ||||
1870 | qApp->notify( qApp, &enterProximityEvent ); | ||||
1871 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::CrossCursor ) ); | ||||
1872 | qApp->notify( qApp, &leaveProximityEvent ); | ||||
1873 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::BlankCursor ) ); | ||||
1874 | | ||||
1875 | // Moving the mouse should not bring the cursor back | ||||
1876 | QTest::mouseMove( w, QPoint( 100, 100 ) ); | ||||
1877 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::BlankCursor ) ); | ||||
1878 | | ||||
1879 | | ||||
1880 | // First test with the Okular::Settings::EnumSlidesCursor::HiddenDelay setting | ||||
1881 | Okular::Settings::self()->setSlidesCursor( Okular::Settings::EnumSlidesCursor::HiddenDelay ); | ||||
1882 | | ||||
1883 | qApp->notify( qApp, &enterProximityEvent ); | ||||
1884 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::CrossCursor ) ); | ||||
1885 | qApp->notify( qApp, &leaveProximityEvent ); | ||||
1886 | | ||||
1887 | // After the leaveProximityEvent, the cursor should be blank, because | ||||
1888 | // we have set the slidesCursor mode to 'HiddenDelay' | ||||
1889 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::BlankCursor ) ); | ||||
1890 | | ||||
1891 | // Moving the mouse should bring the cursor back | ||||
1892 | QTest::mouseMove(w, QPoint( 150, 150 )); | ||||
1893 | QVERIFY( w->cursor().shape() == Qt::CursorShape( Qt::ArrowCursor ) ); | ||||
1894 | } | ||||
1895 | | ||||
1785 | } // namespace Okular | 1896 | } // namespace Okular | ||
1786 | 1897 | | |||
1787 | int main(int argc, char *argv[]) | 1898 | int main(int argc, char *argv[]) | ||
1788 | { | 1899 | { | ||
1789 | // Force consistent locale | 1900 | // Force consistent locale | ||
1790 | QLocale locale(QStringLiteral("en_US.UTF-8")); | 1901 | QLocale locale(QStringLiteral("en_US.UTF-8")); | ||
1791 | if (locale == QLocale::c()) { // This is the way to check if the above worked | 1902 | if (locale == QLocale::c()) { // This is the way to check if the above worked | ||
1792 | locale = QLocale(QLocale::English, QLocale::UnitedStates); | 1903 | locale = QLocale(QLocale::English, QLocale::UnitedStates); | ||
Show All 32 Lines |