File indexing completed on 2024-05-12 04:33:27

0001 /*
0002     SPDX-FileCopyrightText: 2013 Jon Mease <jon.mease@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QTest>
0008 
0009 #include "../settings_core.h"
0010 #include "core/document.h"
0011 #include <QMimeDatabase>
0012 #include <QMimeType>
0013 #include <core/form.h>
0014 #include <core/page.h>
0015 
0016 class EditFormsTest : public QObject
0017 {
0018     Q_OBJECT
0019 
0020 private Q_SLOTS:
0021     void initTestCase();
0022     void cleanupTestCase();
0023     void init();
0024     void cleanup();
0025 
0026     void testRadioButtonForm();
0027     void testCheckBoxForm();
0028     void testTextLineForm();
0029     void testTextAreaForm();
0030     void testFileEditForm();
0031     void testComboEditForm();
0032     void testListSingleEdit();
0033     void testListMultiEdit();
0034 
0035     // helper methods
0036     void verifyRadioButtonStates(bool state1, bool state2, bool state3);
0037     void setRadioButtonStates(bool state1, bool state2, bool state3);
0038     void verifyTextForm(Okular::FormFieldText *form);
0039 
0040 private:
0041     Okular::Document *m_document;
0042     QList<Okular::FormFieldButton *> m_radioButtonForms;
0043     QList<Okular::FormFieldButton *> m_checkBoxForms;
0044     Okular::FormFieldText *m_textLineForm;
0045     Okular::FormFieldText *m_textAreaForm;
0046     Okular::FormFieldText *m_fileEditForm;
0047     Okular::FormFieldChoice *m_comboEdit;
0048     Okular::FormFieldChoice *m_listSingleEdit;
0049     Okular::FormFieldChoice *m_listMultiEdit;
0050 };
0051 
0052 void EditFormsTest::initTestCase()
0053 {
0054     Okular::SettingsCore::instance(QStringLiteral("editformstest"));
0055     m_document = new Okular::Document(nullptr);
0056 }
0057 
0058 void EditFormsTest::cleanupTestCase()
0059 {
0060     delete m_document;
0061 }
0062 
0063 void EditFormsTest::init()
0064 {
0065     const QString testFile = QStringLiteral(KDESRCDIR "data/formSamples.pdf");
0066     QMimeDatabase db;
0067     const QMimeType mime = db.mimeTypeForFile(testFile);
0068     QCOMPARE(m_document->openDocument(testFile, QUrl(), mime), Okular::Document::OpenSuccess);
0069 
0070     // Undo and Redo should be unavailable when docuemnt is first opened.
0071     QVERIFY(!m_document->canUndo());
0072     QVERIFY(!m_document->canRedo());
0073 
0074     const Okular::Page *page = m_document->page(0);
0075     const QList<Okular::FormField *> pageFields = page->formFields();
0076 
0077     // Clear lists
0078     m_checkBoxForms.clear();
0079     m_radioButtonForms.clear();
0080 
0081     // Collect forms of the various types
0082     for (Okular::FormField *ff : pageFields) {
0083         ff->type();
0084 
0085         switch (ff->type()) {
0086         case Okular::FormField::FormButton: {
0087             Okular::FormFieldButton *ffb = static_cast<Okular::FormFieldButton *>(ff);
0088             switch (ffb->buttonType()) {
0089             case Okular::FormFieldButton::Push:
0090                 break;
0091             case Okular::FormFieldButton::CheckBox:
0092                 m_checkBoxForms.append(ffb);
0093                 break;
0094             case Okular::FormFieldButton::Radio:
0095                 m_radioButtonForms.append(ffb);
0096                 break;
0097             default:;
0098             }
0099             break;
0100         }
0101         case Okular::FormField::FormText: {
0102             Okular::FormFieldText *fft = static_cast<Okular::FormFieldText *>(ff);
0103             switch (fft->textType()) {
0104             case Okular::FormFieldText::Multiline:
0105                 m_textAreaForm = fft;
0106                 break;
0107             case Okular::FormFieldText::Normal:
0108                 m_textLineForm = fft;
0109                 break;
0110             case Okular::FormFieldText::FileSelect:
0111                 m_fileEditForm = fft;
0112                 break;
0113             }
0114             break;
0115         }
0116         case Okular::FormField::FormChoice: {
0117             Okular::FormFieldChoice *ffc = static_cast<Okular::FormFieldChoice *>(ff);
0118             switch (ffc->choiceType()) {
0119             case Okular::FormFieldChoice::ListBox:
0120                 if (ffc->multiSelect()) {
0121                     m_listMultiEdit = ffc;
0122                 } else {
0123                     m_listSingleEdit = ffc;
0124                 }
0125                 break;
0126             case Okular::FormFieldChoice::ComboBox:
0127                 m_comboEdit = ffc;
0128                 break;
0129             }
0130             break;
0131         }
0132         default:;
0133         }
0134     }
0135 }
0136 
0137 void EditFormsTest::cleanup()
0138 {
0139     m_document->closeDocument();
0140 }
0141 
0142 void EditFormsTest::testRadioButtonForm()
0143 {
0144     // Initially the first radio button is checked
0145     verifyRadioButtonStates(true, false, false);
0146 
0147     // Set the second radio to checked and make sure the first
0148     // is now unchecked and that an undo action is available
0149     setRadioButtonStates(false, true, false);
0150     verifyRadioButtonStates(false, true, false);
0151     QVERIFY(m_document->canUndo());
0152 
0153     // Now undo the action
0154     m_document->undo();
0155     verifyRadioButtonStates(true, false, false);
0156     QVERIFY(!m_document->canUndo());
0157     QVERIFY(m_document->canRedo());
0158 
0159     // Now redo the action
0160     m_document->redo();
0161     verifyRadioButtonStates(false, true, false);
0162     QVERIFY(m_document->canUndo());
0163     QVERIFY(!m_document->canRedo());
0164 }
0165 
0166 void EditFormsTest::testCheckBoxForm()
0167 {
0168     // Examine the first and second checkboxes
0169     // Initially both checkboxes are unchecked
0170     QVERIFY(m_checkBoxForms[0]->state() == false);
0171     QVERIFY(m_checkBoxForms[1]->state() == false);
0172 
0173     // Set checkbox 1 to true
0174     m_document->editFormButtons(0, QList<Okular::FormFieldButton *>() << m_checkBoxForms[0], QList<bool>() << true);
0175     QVERIFY(m_checkBoxForms[0]->state() == true);
0176     QVERIFY(m_checkBoxForms[1]->state() == false);
0177     QVERIFY(m_document->canUndo());
0178 
0179     // Set checkbox 2 to true
0180     m_document->editFormButtons(0, QList<Okular::FormFieldButton *>() << m_checkBoxForms[1], QList<bool>() << true);
0181     QVERIFY(m_checkBoxForms[0]->state() == true);
0182     QVERIFY(m_checkBoxForms[1]->state() == true);
0183     QVERIFY(m_document->canUndo());
0184 
0185     // Undo checking of second checkbox
0186     m_document->undo();
0187     QVERIFY(m_checkBoxForms[0]->state() == true);
0188     QVERIFY(m_checkBoxForms[1]->state() == false);
0189     QVERIFY(m_document->canUndo());
0190     QVERIFY(m_document->canRedo());
0191 
0192     // Undo checking of first checkbox
0193     m_document->undo();
0194     QVERIFY(m_checkBoxForms[0]->state() == false);
0195     QVERIFY(m_checkBoxForms[1]->state() == false);
0196     QVERIFY(!m_document->canUndo());
0197     QVERIFY(m_document->canRedo());
0198 
0199     // Redo checking of first checkbox
0200     m_document->redo();
0201     QVERIFY(m_checkBoxForms[0]->state() == true);
0202     QVERIFY(m_checkBoxForms[1]->state() == false);
0203     QVERIFY(m_document->canUndo());
0204     QVERIFY(m_document->canRedo());
0205 }
0206 
0207 void EditFormsTest::testTextLineForm()
0208 {
0209     verifyTextForm(m_textLineForm);
0210 }
0211 
0212 void EditFormsTest::testTextAreaForm()
0213 {
0214     verifyTextForm(m_textAreaForm);
0215 }
0216 
0217 void EditFormsTest::testFileEditForm()
0218 {
0219     verifyTextForm(m_fileEditForm);
0220 }
0221 
0222 void EditFormsTest::testComboEditForm()
0223 {
0224     // Editable combo with predefined choices:
0225     //     - combo1
0226     //     - combo2
0227     //     - combo3
0228 
0229     // Initially no choice is selected
0230     QCOMPARE(m_comboEdit->currentChoices().length(), 0);
0231     QCOMPARE(m_comboEdit->editChoice(), QLatin1String(""));
0232 
0233     // Select first choice
0234     m_document->editFormCombo(0, m_comboEdit, QStringLiteral("combo1"), 0, 0, 0);
0235     QCOMPARE(m_comboEdit->currentChoices().length(), 1);
0236     QCOMPARE(m_comboEdit->currentChoices().constFirst(), 0);
0237     QCOMPARE(m_comboEdit->editChoice(), QLatin1String(""));
0238     QVERIFY(m_document->canUndo());
0239     QVERIFY(!m_document->canRedo());
0240 
0241     // Select third choice
0242     m_document->editFormCombo(0, m_comboEdit, QStringLiteral("combo3"), 0, 0, 0);
0243     QCOMPARE(m_comboEdit->currentChoices().length(), 1);
0244     QCOMPARE(m_comboEdit->currentChoices().constFirst(), 2);
0245     QCOMPARE(m_comboEdit->editChoice(), QLatin1String(""));
0246     QVERIFY(m_document->canUndo());
0247     QVERIFY(!m_document->canRedo());
0248 
0249     // Undo and verify that first choice is selected
0250     m_document->undo();
0251     QCOMPARE(m_comboEdit->currentChoices().length(), 1);
0252     QCOMPARE(m_comboEdit->currentChoices().constFirst(), 0);
0253     QVERIFY(m_document->canUndo());
0254     QVERIFY(m_document->canRedo());
0255 
0256     // Redo and verify that third choice is selected
0257     m_document->redo();
0258     QCOMPARE(m_comboEdit->currentChoices().length(), 1);
0259     QCOMPARE(m_comboEdit->currentChoices().constFirst(), 2);
0260     QVERIFY(m_document->canUndo());
0261     QVERIFY(!m_document->canRedo());
0262 
0263     // Select a custom choice and verify that no predefined choices are selected
0264     m_document->editFormCombo(0, m_comboEdit, QStringLiteral("comboEdit"), 0, 0, 0);
0265     QCOMPARE(m_comboEdit->currentChoices().length(), 0);
0266     QCOMPARE(m_comboEdit->editChoice(), QStringLiteral("comboEdit"));
0267     QVERIFY(m_document->canUndo());
0268     QVERIFY(!m_document->canRedo());
0269 
0270     // Undo and verify that third choice is selected
0271     m_document->undo();
0272     QCOMPARE(m_comboEdit->currentChoices().length(), 1);
0273     QCOMPARE(m_comboEdit->currentChoices().constFirst(), 2);
0274     QVERIFY(m_document->canUndo());
0275     QVERIFY(m_document->canRedo());
0276 }
0277 
0278 void EditFormsTest::testListSingleEdit()
0279 {
0280     // A list with three items that allows only single selections
0281     // Initially no choice is selected
0282     QCOMPARE(m_listSingleEdit->currentChoices().length(), 0);
0283 
0284     // Select first item
0285     m_document->editFormList(0, m_listSingleEdit, QList<int>() << 0);
0286     QCOMPARE(m_listSingleEdit->currentChoices().length(), 1);
0287     QCOMPARE(m_listSingleEdit->currentChoices().constFirst(), 0);
0288     QVERIFY(m_document->canUndo());
0289     QVERIFY(!m_document->canRedo());
0290 
0291     // Select second item
0292     m_document->editFormList(0, m_listSingleEdit, QList<int>() << 1);
0293     QCOMPARE(m_listSingleEdit->currentChoices().length(), 1);
0294     QCOMPARE(m_listSingleEdit->currentChoices().constFirst(), 1);
0295     QVERIFY(m_document->canUndo());
0296     QVERIFY(!m_document->canRedo());
0297 
0298     // Undo and verify that first item is selected
0299     m_document->undo();
0300     QCOMPARE(m_listSingleEdit->currentChoices().length(), 1);
0301     QCOMPARE(m_listSingleEdit->currentChoices().constFirst(), 0);
0302     QVERIFY(m_document->canUndo());
0303     QVERIFY(m_document->canRedo());
0304 
0305     // Redo and verify that second item is selected
0306     m_document->redo();
0307     QCOMPARE(m_listSingleEdit->currentChoices().length(), 1);
0308     QCOMPARE(m_listSingleEdit->currentChoices().constFirst(), 1);
0309     QVERIFY(m_document->canUndo());
0310     QVERIFY(!m_document->canRedo());
0311 }
0312 
0313 void EditFormsTest::testListMultiEdit()
0314 {
0315     // A list with three items that allows for multiple selections
0316     // Initially no choice is selected
0317     QCOMPARE(m_listMultiEdit->currentChoices().length(), 0);
0318 
0319     // Select first item
0320     m_document->editFormList(0, m_listMultiEdit, QList<int>() << 0);
0321     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0);
0322     QVERIFY(m_document->canUndo());
0323     QVERIFY(!m_document->canRedo());
0324 
0325     // Select first and third items
0326     m_document->editFormList(0, m_listMultiEdit, QList<int>() << 0 << 2);
0327     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0 << 2);
0328     QVERIFY(m_document->canUndo());
0329     QVERIFY(!m_document->canRedo());
0330 
0331     // Select all three items
0332     m_document->editFormList(0, m_listMultiEdit, QList<int>() << 0 << 1 << 2);
0333     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0 << 1 << 2);
0334     QVERIFY(m_document->canUndo());
0335     QVERIFY(!m_document->canRedo());
0336 
0337     // Undo and verify that first and third items are selected
0338     m_document->undo();
0339     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0 << 2);
0340     QVERIFY(m_document->canUndo());
0341     QVERIFY(m_document->canRedo());
0342 
0343     // Undo and verify that first item is selected
0344     m_document->undo();
0345     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0);
0346     QVERIFY(m_document->canUndo());
0347     QVERIFY(m_document->canRedo());
0348 
0349     // Redo and verify that first and third items are selected
0350     m_document->redo();
0351     QCOMPARE(m_listMultiEdit->currentChoices(), QList<int>() << 0 << 2);
0352     QVERIFY(m_document->canUndo());
0353     QVERIFY(m_document->canRedo());
0354 }
0355 
0356 // helper methods
0357 void EditFormsTest::verifyRadioButtonStates(bool state1, bool state2, bool state3)
0358 {
0359     QVERIFY(m_radioButtonForms[0]->state() == state1);
0360     QVERIFY(m_radioButtonForms[1]->state() == state2);
0361     QVERIFY(m_radioButtonForms[2]->state() == state3);
0362 }
0363 
0364 void EditFormsTest::setRadioButtonStates(bool state1, bool state2, bool state3)
0365 {
0366     QList<bool> newButtonStates;
0367     newButtonStates.append(state1);
0368     newButtonStates.append(state2);
0369     newButtonStates.append(state3);
0370     m_document->editFormButtons(0, m_radioButtonForms, newButtonStates);
0371 }
0372 
0373 void EditFormsTest::verifyTextForm(Okular::FormFieldText *form)
0374 {
0375     // Text in form is initially empty
0376     QCOMPARE(form->text(), QLatin1String(""));
0377 
0378     // Insert the string "Hello" into the form
0379     m_document->editFormText(0, form, QStringLiteral("Hello"), 5, 0, 0);
0380     QCOMPARE(form->text(), QStringLiteral("Hello"));
0381     QVERIFY(m_document->canUndo());
0382     QVERIFY(!m_document->canRedo());
0383 
0384     // Undo the insertion and verify that form is empty again
0385     m_document->undo();
0386     QCOMPARE(form->text(), QLatin1String(""));
0387     QVERIFY(!m_document->canUndo());
0388     QVERIFY(m_document->canRedo());
0389 
0390     // Redo the insertion of "Hello"
0391     m_document->redo();
0392     QCOMPARE(form->text(), QStringLiteral("Hello"));
0393     QVERIFY(m_document->canUndo());
0394     QVERIFY(!m_document->canRedo());
0395 
0396     // Type "_World" after "Hello"
0397     m_document->editFormText(0, form, QStringLiteral("Hello_"), 6, 5, 5);
0398     m_document->editFormText(0, form, QStringLiteral("Hello_W"), 7, 6, 6);
0399     m_document->editFormText(0, form, QStringLiteral("Hello_Wo"), 8, 7, 7);
0400     m_document->editFormText(0, form, QStringLiteral("Hello_Wor"), 9, 8, 8);
0401     m_document->editFormText(0, form, QStringLiteral("Hello_Worl"), 10, 9, 9);
0402     m_document->editFormText(0, form, QStringLiteral("Hello_World"), 11, 10, 10);
0403 
0404     // Verify that character insertion operations were merged together into a single undo command
0405     m_document->undo();
0406     QCOMPARE(form->text(), QStringLiteral("Hello"));
0407     QVERIFY(m_document->canUndo());
0408     QVERIFY(m_document->canRedo());
0409 
0410     // Verify that one more undo gets us back to the original state (empty form)
0411     m_document->undo();
0412     QCOMPARE(form->text(), QLatin1String(""));
0413     QVERIFY(!m_document->canUndo());
0414     QVERIFY(m_document->canRedo());
0415 }
0416 
0417 QTEST_MAIN(EditFormsTest)
0418 #include "editformstest.moc"