1 | #include <QtTest/QTest> |
2 | |
3 | #include <poppler-qt6.h> |
4 | #include <poppler-form.h> |
5 | #include <poppler-private.h> |
6 | #include <Form.h> |
7 | |
8 | class TestForms : public QObject |
9 | { |
10 | Q_OBJECT |
11 | public: |
12 | explicit TestForms(QObject *parent = nullptr) : QObject(parent) { } |
13 | private slots: |
14 | void testCheckbox(); // Test for issue #655 |
15 | void testCheckboxIssue159(); // Test for issue #159 |
16 | void testSetIcon(); // Test that setIcon will always be valid. |
17 | void testSetPrintable(); |
18 | void testSetAppearanceText(); |
19 | void testStandAloneWidgets(); // check for 'de facto' tooltips. Issue #34 |
20 | void testUnicodeFieldAttributes(); |
21 | }; |
22 | |
23 | void TestForms::testCheckbox() |
24 | { |
25 | // Test for checkbox issue #655 |
26 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/latex-hyperref-checkbox-issue-655.pdf" ); |
27 | QVERIFY(document); |
28 | |
29 | std::unique_ptr<Poppler::Page> page(document->page(index: 0)); |
30 | QVERIFY(page); |
31 | |
32 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
33 | QCOMPARE(forms.size(), 1); |
34 | |
35 | Poppler::FormField *form = forms.at(n: 0).get(); |
36 | QCOMPARE(form->type(), Poppler::FormField::FormButton); |
37 | |
38 | Poppler::FormFieldButton *chkFormFieldButton = static_cast<Poppler::FormFieldButton *>(form); |
39 | |
40 | // Test this is actually a Checkbox |
41 | QCOMPARE(chkFormFieldButton->buttonType(), Poppler::FormFieldButton::CheckBox); |
42 | |
43 | // checkbox comes initially 'unchecked' |
44 | QCOMPARE(chkFormFieldButton->state(), false); |
45 | // let's mark it as 'checked' |
46 | chkFormFieldButton->setState(true); |
47 | // now test if it was succesfully 'checked' |
48 | QCOMPARE(chkFormFieldButton->state(), true); |
49 | } |
50 | |
51 | void TestForms::testStandAloneWidgets() |
52 | { |
53 | // Check for 'de facto' tooltips. Issue #34 |
54 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/tooltip.pdf" ); |
55 | QVERIFY(document); |
56 | |
57 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
58 | QVERIFY(page); |
59 | |
60 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
61 | |
62 | QCOMPARE(forms.size(), 3); |
63 | |
64 | for (const std::unique_ptr<Poppler::FormField> &field : forms) { |
65 | QCOMPARE(field->type(), Poppler::FormField::FormButton); |
66 | |
67 | Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field.get()); |
68 | QCOMPARE(fieldButton->buttonType(), Poppler::FormFieldButton::Push); |
69 | |
70 | FormField *ff = Poppler::FormFieldData::getFormWidget(f: fieldButton)->getField(); |
71 | QVERIFY(ff); |
72 | QCOMPARE(ff->isStandAlone(), true); |
73 | |
74 | // tooltip.pdf has only these 3 standalone widgets |
75 | QVERIFY(field->uiName() == QStringLiteral("This is a tooltip!" ) || // clazy:exclude=qstring-allocations |
76 | field->uiName() == QStringLiteral("Sulfuric acid" ) || field->uiName() == QString::fromUtf8("little Gauß" )); |
77 | } |
78 | } |
79 | |
80 | void TestForms::testCheckboxIssue159() |
81 | { |
82 | // Test for checkbox issue #159 |
83 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/checkbox_issue_159.pdf" ); |
84 | QVERIFY(document); |
85 | |
86 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
87 | QVERIFY(page); |
88 | |
89 | Poppler::FormFieldButton *beerFieldButton = nullptr; |
90 | Poppler::FormFieldButton *wineFieldButton = nullptr; |
91 | |
92 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
93 | |
94 | // Let's find and assign the "Wine" and "Beer" radio buttons |
95 | for (const std::unique_ptr<Poppler::FormField> &field : forms) { |
96 | if (field->type() != Poppler::FormField::FormButton) { |
97 | continue; |
98 | } |
99 | |
100 | Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field.get()); |
101 | if (fieldButton->buttonType() != Poppler::FormFieldButton::Radio) { |
102 | continue; |
103 | } |
104 | |
105 | // printf("%s \n", fieldButton->caption().toLatin1().data()); |
106 | if (fieldButton->caption() == QStringLiteral("Wine" )) { |
107 | wineFieldButton = fieldButton; |
108 | } else if (fieldButton->caption() == QStringLiteral("Beer" )) { |
109 | beerFieldButton = fieldButton; |
110 | } |
111 | } |
112 | |
113 | // "Beer" and "Wine" radiobuttons belong to the same RadioButton group. |
114 | // So selecting one should unselect the other. |
115 | QVERIFY(beerFieldButton); |
116 | QVERIFY(wineFieldButton); |
117 | |
118 | // Test that the RadioButton group comes with "Beer" initially selected |
119 | QCOMPARE(beerFieldButton->state(), true); |
120 | |
121 | // Now select "Wine". As a result "Beer" should no longer be selected. |
122 | wineFieldButton->setState(true); |
123 | |
124 | // Test that "Beer" is indeed not reporting as being selected |
125 | QCOMPARE(beerFieldButton->state(), false); |
126 | } |
127 | |
128 | void TestForms::testSetIcon() |
129 | { |
130 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/form_set_icon.pdf" ); |
131 | QVERIFY(document); |
132 | |
133 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
134 | QVERIFY(page); |
135 | |
136 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
137 | |
138 | Poppler::FormFieldButton *anmButton = nullptr; |
139 | |
140 | // First we are finding the field which will have its icon changed |
141 | for (const std::unique_ptr<Poppler::FormField> &field : forms) { |
142 | |
143 | if (field->type() != Poppler::FormField::FormButton) { |
144 | continue; |
145 | } |
146 | |
147 | Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field.get()); |
148 | if (field->name() == QStringLiteral("anm0" )) { |
149 | anmButton = fieldButton; |
150 | } |
151 | } |
152 | |
153 | QVERIFY(anmButton); |
154 | |
155 | // Then we set the Icon on this field, for every other field |
156 | // And verify if it has a valid icon |
157 | for (const std::unique_ptr<Poppler::FormField> &field : forms) { |
158 | |
159 | if (field->type() != Poppler::FormField::FormButton) { |
160 | continue; |
161 | } |
162 | |
163 | Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field.get()); |
164 | if (field->name() == QStringLiteral("anm0" )) { |
165 | continue; |
166 | } |
167 | |
168 | Poppler::FormFieldIcon newIcon = fieldButton->icon(); |
169 | |
170 | anmButton->setIcon(newIcon); |
171 | |
172 | Poppler::FormFieldIcon anmIcon = anmButton->icon(); |
173 | |
174 | QVERIFY(Poppler::FormFieldIconData::getData(anmIcon)); |
175 | QVERIFY(Poppler::FormFieldIconData::getData(anmIcon)->icon); |
176 | |
177 | QCOMPARE(Poppler::FormFieldIconData::getData(anmIcon)->icon->lookupNF("AP" ).dictLookupNF("N" ).getRef().num, Poppler::FormFieldIconData::getData(newIcon)->icon->lookupNF("AP" ).dictLookupNF("N" ).getRef().num); |
178 | } |
179 | |
180 | // Just making sure that setting a invalid icon will still produce a valid icon. |
181 | anmButton->setIcon(Poppler::FormFieldIcon(nullptr)); |
182 | Poppler::FormFieldIcon anmIcon = anmButton->icon(); |
183 | |
184 | QVERIFY(Poppler::FormFieldIconData::getData(anmIcon)); |
185 | QVERIFY(Poppler::FormFieldIconData::getData(anmIcon)->icon); |
186 | } |
187 | |
188 | void TestForms::testSetPrintable() |
189 | { |
190 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/form_set_icon.pdf" ); |
191 | QVERIFY(document); |
192 | |
193 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
194 | QVERIFY(page); |
195 | |
196 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
197 | |
198 | for (std::unique_ptr<Poppler::FormField> &field : forms) { |
199 | field->setPrintable(true); |
200 | QCOMPARE(field->isPrintable(), true); |
201 | |
202 | field->setPrintable(false); |
203 | QCOMPARE(field->isPrintable(), false); |
204 | } |
205 | } |
206 | |
207 | void TestForms::testSetAppearanceText() |
208 | { |
209 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/checkbox_issue_159.pdf" ); |
210 | QVERIFY(document); |
211 | |
212 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
213 | QVERIFY(page); |
214 | |
215 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
216 | |
217 | int nTextForms = 0; |
218 | |
219 | for (std::unique_ptr<Poppler::FormField> &field : forms) { |
220 | |
221 | if (field->type() != Poppler::FormField::FormText) { |
222 | continue; |
223 | } |
224 | |
225 | nTextForms++; |
226 | |
227 | Poppler::FormFieldText *fft = static_cast<Poppler::FormFieldText *>(field.get()); |
228 | |
229 | const QString textToSet = "HOLA" + fft->name(); |
230 | fft->setAppearanceText(textToSet); |
231 | |
232 | Dict *dict = Poppler::FormFieldData::getFormWidget(f: fft)->getObj()->getDict(); |
233 | Object strObject = dict->lookup(key: "AP" ).dictLookup(key: "N" ); |
234 | |
235 | QVERIFY(strObject.isStream()); |
236 | |
237 | GooString s; |
238 | strObject.getStream()->fillGooString(s: &s); |
239 | |
240 | const QString textToFind = QStringLiteral("\n(%1) Tj\n" ).arg(a: textToSet); |
241 | QVERIFY(s.toStr().find(textToFind.toStdString()) != std::string::npos); |
242 | } |
243 | |
244 | QCOMPARE(nTextForms, 5); |
245 | } |
246 | |
247 | void TestForms::testUnicodeFieldAttributes() |
248 | { |
249 | std::unique_ptr<Poppler::Document> document = Poppler::Document::load(TESTDATADIR "/unittestcases/fieldWithUtf16Names.pdf" ); |
250 | QVERIFY(document); |
251 | |
252 | std::unique_ptr<Poppler::Page> page = document->page(index: 0); |
253 | QVERIFY(page); |
254 | |
255 | std::vector<std::unique_ptr<Poppler::FormField>> forms = page->formFields(); |
256 | |
257 | Poppler::FormField *field = forms.front().get(); |
258 | |
259 | QCOMPARE(field->name(), QStringLiteral("Tex" )); |
260 | QCOMPARE(field->uiName(), QStringLiteral("Texto de ayuda" )); |
261 | } |
262 | |
263 | QTEST_GUILESS_MAIN(TestForms) |
264 | #include "check_forms.moc" |
265 | |