diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -62,6 +62,11 @@ LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore ) +ecm_add_test(resetformstest.cpp + TEST_NAME "resetformstest" + LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore okularpart +) + if(NOT WIN32) ecm_add_test(mainshelltest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp TEST_NAME "mainshelltest" diff --git a/autotests/resetformstest.cpp b/autotests/resetformstest.cpp new file mode 100644 --- /dev/null +++ b/autotests/resetformstest.cpp @@ -0,0 +1,289 @@ +#include + +#include <../core/document> +#include "../core/annotations.h" +#include "../core/form.h" +#include "../core/page.h" +#include "../part.h" +#include "../ui/toc.h" +#include "../ui/pageview.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Okular{ + +class ResetFormsTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + void testResetRadioButtonForm(); + void testResetCheckBoxForm(); + void testResetTextLineForm(); + void testResetTextAreaForm(); + void testResetFileEditForm(); + void testResetComboEditForm(); + void testResetListSingleEdit(); + void testResetListMultiEdit(); + + // helper methods + void triggerResetAction(); + void verifyRadioButtonStates(bool state1, bool state2, bool state3); + void setRadioButtonStates(bool state1, bool state2, bool state3); + void verifyTextForm( Okular::FormFieldText *form ); + +private: + Okular::Part *part; + QVariantList dummyArgs; + PageView *m_pageView; + Okular::Document *m_document; + QList m_radioButtonForms; + QList m_checkBoxForms; + Okular::FormFieldText* m_textLineForm; + Okular::FormFieldText* m_textAreaForm; + Okular::FormFieldText* m_fileEditForm; + Okular::FormFieldChoice* m_comboEdit; + Okular::FormFieldChoice* m_listSingleEdit; + Okular::FormFieldChoice* m_listMultiEdit; +}; + +void ResetFormsTest::initTestCase() +{ + part = new Okular::Part(NULL, NULL, dummyArgs); +} + +void ResetFormsTest::cleanupTestCase() +{ + delete part; +} + +void ResetFormsTest::cleanup() +{ + part->m_document->closeDocument(); +} + +void ResetFormsTest::init() +{ + const QString testFile = QStringLiteral(KDESRCDIR "data/formSamples.pdf"); + part->openDocument( testFile ); + part->widget()->show(); + m_document = part->m_document; + + const Okular::Page* page = m_document->page( 0 ); + QLinkedList pageFields = page->formFields(); + + // Clear lists + m_checkBoxForms.clear(); + m_radioButtonForms.clear(); + + // Collect forms of the various types + QLinkedList< Okular::FormField * >::const_iterator ffIt = pageFields.constBegin(), ffEnd = pageFields.constEnd(); + for ( ; ffIt != ffEnd; ++ffIt ) + { + Okular::FormField * ff = *ffIt; + ff->type(); + + switch ( ff->type() ) + { + case Okular::FormField::FormButton: + { + Okular::FormFieldButton * ffb = static_cast< Okular::FormFieldButton * >( ff ); + switch ( ffb->buttonType() ) + { + case Okular::FormFieldButton::Push: + break; + case Okular::FormFieldButton::CheckBox: + m_checkBoxForms.append(ffb); + break; + case Okular::FormFieldButton::Radio: + m_radioButtonForms.append(ffb); + break; + default: ; + } + break; + } + case Okular::FormField::FormText: + { + Okular::FormFieldText * fft = static_cast< Okular::FormFieldText * >( ff ); + switch ( fft->textType() ) + { + case Okular::FormFieldText::Multiline: + m_textAreaForm = fft; + break; + case Okular::FormFieldText::Normal: + m_textLineForm = fft; + break; + case Okular::FormFieldText::FileSelect: + m_fileEditForm = fft; + break; + } + break; + } + case Okular::FormField::FormChoice: + { + Okular::FormFieldChoice * ffc = static_cast< Okular::FormFieldChoice * >( ff ); + switch ( ffc->choiceType() ) + { + case Okular::FormFieldChoice::ListBox: + if ( ffc->multiSelect() ) + { + m_listMultiEdit = ffc; + } + else + { + m_listSingleEdit = ffc; + } + break; + case Okular::FormFieldChoice::ComboBox: + m_comboEdit = ffc; + break; + } + break; + } + default: ; + } + } +} + + +void ResetFormsTest::testResetRadioButtonForm() +{ + // select second radio button + setRadioButtonStates(false, true, false); + triggerResetAction(); + verifyRadioButtonStates(true, false, false); +} + +void ResetFormsTest::testResetCheckBoxForm() +{ + // set all check boxes to true + m_document->editFormButtons( 0, m_checkBoxForms, QList() << true << true << true); + triggerResetAction(); + + QVERIFY ( m_checkBoxForms[0]->state() == false ); + QVERIFY ( m_checkBoxForms[1]->state() == false ); + QVERIFY ( m_checkBoxForms[2]->state() == false ); + + m_document->editFormButtons( 0, m_checkBoxForms, QList() << true << false << true); + triggerResetAction(); + + QVERIFY ( m_checkBoxForms[0]->state() == false ); + QVERIFY ( m_checkBoxForms[1]->state() == false ); + QVERIFY ( m_checkBoxForms[2]->state() == false ); +} + +void ResetFormsTest::testResetTextLineForm() +{ + verifyTextForm( m_textLineForm ); +} + +void ResetFormsTest::testResetTextAreaForm() +{ + verifyTextForm( m_textAreaForm ); +} + +void ResetFormsTest::testResetFileEditForm() +{ + verifyTextForm( m_fileEditForm ); +} + +void ResetFormsTest::testResetComboEditForm() +{ + // Select first choice + m_document->editFormCombo( 0, m_comboEdit, QStringLiteral("combo1"), 0, 0, 0); + QCOMPARE( m_comboEdit->currentChoices().length(), 1 ); + triggerResetAction(); + QCOMPARE( m_comboEdit->currentChoices().length(), 0 ); + QCOMPARE( m_comboEdit->editChoice(), QStringLiteral( "" ) ); + + // Select third choice + m_document->editFormCombo( 0, m_comboEdit, QStringLiteral("combo3"), 0, 0, 0); + QCOMPARE( m_comboEdit->currentChoices().length(), 1 ); + triggerResetAction(); + QCOMPARE( m_comboEdit->currentChoices().length(), 0 ); + QCOMPARE( m_comboEdit->editChoice(), QStringLiteral( "" ) ); +} + +void ResetFormsTest::testResetListSingleEdit() +{ + // Select first item + m_document->editFormList( 0, m_listSingleEdit, QList() << 0); + QCOMPARE( m_listSingleEdit->currentChoices().length(), 1 ); + QCOMPARE( m_listSingleEdit->currentChoices()[0], 0 ); + triggerResetAction(); + QCOMPARE( m_listSingleEdit->currentChoices().length(), 0 ); + + // Select third item + m_document->editFormList( 0, m_listSingleEdit, QList() << 2); + QCOMPARE( m_listSingleEdit->currentChoices().length(), 1 ); + QCOMPARE( m_listSingleEdit->currentChoices()[0], 2 ); + triggerResetAction(); + QCOMPARE( m_listSingleEdit->currentChoices().length(), 0 ); +} + +void ResetFormsTest::testResetListMultiEdit() +{ + // Select first and third choices + m_document->editFormList( 0, m_listMultiEdit, QList() << 0 << 2); + QCOMPARE( m_listMultiEdit->currentChoices(), QList() << 0 << 2); + triggerResetAction(); + QCOMPARE( m_listMultiEdit->currentChoices(), QList()); + + // Select all choices + m_document->editFormList( 0, m_listMultiEdit, QList() << 0 << 1 << 2); + QCOMPARE( m_listMultiEdit->currentChoices(), QList() << 0 << 1 << 2); + triggerResetAction(); + QCOMPARE( m_listMultiEdit->currentChoices(), QList()); +} + +// helper methods + +void ResetFormsTest::triggerResetAction() +{ + part->m_pageView->resetFormsAction()->trigger(); +} + +void ResetFormsTest::verifyRadioButtonStates( bool state1, bool state2, bool state3 ) +{ + QVERIFY ( m_radioButtonForms[0]->state() == state1 ); + QVERIFY ( m_radioButtonForms[1]->state() == state2 ); + QVERIFY ( m_radioButtonForms[2]->state() == state3 ); +} + +void ResetFormsTest::setRadioButtonStates( bool state1, bool state2, bool state3 ) +{ + QList newButtonStates; + newButtonStates.append(state1); + newButtonStates.append(state2); + newButtonStates.append(state3); + m_document->editFormButtons( 0, m_radioButtonForms, newButtonStates); +} + +void ResetFormsTest::verifyTextForm( Okular::FormFieldText *form ) +{ + m_document->editFormText(0, form, QStringLiteral("Hello_World"), 11, 0, 0); + QCOMPARE( form->text(), QStringLiteral("Hello_World") ); + triggerResetAction(); + + QCOMPARE( form->text(), QStringLiteral("") ); +} +} + +QTEST_MAIN( Okular::ResetFormsTest ) +#include "resetformstest.moc" \ No newline at end of file diff --git a/part.h b/part.h --- a/part.h +++ b/part.h @@ -115,7 +115,8 @@ Q_INTERFACES(Okular::ViewerInterface) friend class PartTest; - + friend class ResetFormsTest; + public: // Default constructor /** diff --git a/part.cpp b/part.cpp --- a/part.cpp +++ b/part.cpp @@ -3356,7 +3356,7 @@ // attach the actions of the children widgets too m_formsMessage->addAction( m_pageView->toggleFormsAction() ); - + m_formsMessage->addAction( m_pageView->resetFormsAction() ); // ensure history actions are in the correct state updateViewActions(); } diff --git a/part.rc b/part.rc --- a/part.rc +++ b/part.rc @@ -47,6 +47,7 @@ + &Go diff --git a/ui/pageview.h b/ui/pageview.h --- a/ui/pageview.h +++ b/ui/pageview.h @@ -35,6 +35,9 @@ namespace Okular { class Action; class Document; +class FormFieldText; +class FormFieldButton; +class FormFieldChoice; class DocumentViewport; class Annotation; class MovieAction; @@ -57,6 +60,8 @@ class PageView : public QAbstractScrollArea, public Okular::DocumentObserver, public Okular::View { Q_OBJECT + + friend class ResetFormsTest; public: PageView( QWidget *parent, Okular::Document *document ); @@ -103,6 +108,15 @@ KActionCollection *actionCollection() const; QAction *toggleFormsAction() const; + QAction *resetFormsAction() const; + + //Reset Functions for different widgets + void resetFormFieldText( int pageNumber, Okular::Document *document, Okular::FormFieldText *form ); + void resetCheckBoxForms( int pageNumber, Okular::Document *document, const QList< Okular::FormFieldButton* >& formButtons, const QList< bool >& newButtonStates ); + void resetComboForms(int pageNumber, Okular::Document *document, Okular::FormFieldChoice *m_comboEdit); + void resetListEdit(int pageNumber, Okular::Document *document, Okular::FormFieldChoice *m_listEdit); + void resetRadioButtonForms( int pageNumber, Okular::Document *document, const QList< Okular::FormFieldButton* >& formButtons, const QList< bool >& newButtonStates ); + int contentAreaWidth() const; int contentAreaHeight() const; QPoint contentAreaPosition() const; @@ -187,6 +201,7 @@ void scrollTo( int x, int y ); void toggleFormWidgets( bool on ); + void resetFormWidgets( bool on ); void resizeContentArea( const QSize & newSize ); void updatePageStep(); @@ -257,6 +272,7 @@ void slotTrimMarginsToggled( bool ); void slotTrimToSelectionToggled( bool ); void slotToggleForms(); + void slotResetForms(); void slotFormChanged( int pageNumber ); void slotRefreshPage(); #ifdef HAVE_SPEECH diff --git a/ui/pageview.cpp b/ui/pageview.cpp --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -229,6 +229,7 @@ KToggleAction * aViewContinuous; QAction * aPrevAction; QAction * aToggleForms; + QAction * aResetForms; QAction * aSpeakDoc; QAction * aSpeakPage; QAction * aSpeakStop; @@ -351,6 +352,7 @@ d->aViewContinuous = nullptr; d->aPrevAction = nullptr; d->aToggleForms = nullptr; + d->aResetForms = nullptr; d->aSpeakDoc = nullptr; d->aSpeakPage = nullptr; d->aSpeakStop = nullptr; @@ -722,6 +724,12 @@ d->aToggleForms->setEnabled( false ); toggleFormWidgets( false ); + d->aResetForms = new QAction( this ); + ac->addAction( QStringLiteral("view_reset_forms"), d->aResetForms ); + connect( d->aResetForms, &QAction::triggered, this, &PageView::slotResetForms ); + d->aResetForms->setEnabled( false ); + resetFormWidgets( false ); + // Setup undo and redo actions QAction *kundo = KStandardAction::create( KStandardAction::Undo, d->document, SLOT(undo()), ac ); QAction *kredo = KStandardAction::create( KStandardAction::Redo, d->document, SLOT(redo()), ac ); @@ -865,6 +873,11 @@ return d->aToggleForms; } +QAction *PageView::resetFormsAction() const +{ + return d->aResetForms; +} + int PageView::contentAreaWidth() const { return horizontalScrollBar()->maximum() + viewport()->width(); @@ -1215,6 +1228,11 @@ { // may be null if dummy mode is on d->aToggleForms->setEnabled( haspages && hasformwidgets ); } + if ( d->aResetForms ) + { + d->aResetForms->setEnabled( haspages && hasformwidgets ); + } + bool allowAnnotations = d->document->isAllowed( Okular::AllowNotes ); if ( d->annotator ) { @@ -4309,6 +4327,128 @@ } } +void PageView::resetFormWidgets(bool on) +{ + if(d->aResetForms) + d->aResetForms->setText( i18n( "Reset Forms" ) ); + if( d->aResetForms && on) + { + Okular::Document *document = d->document; + + for(int i = 0; i < (int)document->pages(); i++) + { + // ith page in the document + const Okular::Page *page = document->page( i ); + // get form fields in this page + QLinkedList pageFields = page->formFields(); + + QList m_checkBoxForms, m_radioButtonForms; + QList newCheckButtonStates, newRadioButtonStates; + + QLinkedList< Okular::FormField * >::const_iterator ffIt = pageFields.constBegin(), ffEnd = pageFields.constEnd(); + + for ( ; ffIt != ffEnd; ++ffIt ) + { + Okular::FormField * ff = *ffIt; + ff->type(); + + switch ( ff->type() ) + { + case Okular::FormField::FormButton: + { + Okular::FormFieldButton * ffb = static_cast< Okular::FormFieldButton * >( ff ); + switch ( ffb->buttonType() ) + { + case Okular::FormFieldButton::Push: + break; + case Okular::FormFieldButton::CheckBox: + m_checkBoxForms.append(ffb); + newCheckButtonStates.append( false ); + break; + case Okular::FormFieldButton::Radio: + m_radioButtonForms.append(ffb); + newRadioButtonStates.append( false ); + break; + default: ; + } + break; + } + case Okular::FormField::FormText: + { + Okular::FormFieldText * fft = static_cast< Okular::FormFieldText * >( ff ); + switch ( fft->textType() ) + { + case Okular::FormFieldText::Multiline: + resetFormFieldText( i, document, fft ); + break; + case Okular::FormFieldText::Normal: + resetFormFieldText( i, document, fft ); + break; + case Okular::FormFieldText::FileSelect: + resetFormFieldText( i, document, fft ); + break; + } + break; + } + case Okular::FormField::FormChoice: + { + Okular::FormFieldChoice * ffc = static_cast< Okular::FormFieldChoice * >( ff ); + switch ( ffc->choiceType() ) + { + case Okular::FormFieldChoice::ListBox: + resetListEdit(i, document, ffc); + break; + case Okular::FormFieldChoice::ComboBox: + resetComboForms(i, document, ffc); + break; + } + break; + } + default: ; + } + } + + if(m_checkBoxForms.size()) + { + resetCheckBoxForms( i, document, m_checkBoxForms, newCheckButtonStates); + } + if(m_radioButtonForms.size()) + { + newRadioButtonStates[0] = true; + resetRadioButtonForms( i, document, m_radioButtonForms, newRadioButtonStates); + } + } + + } +} + +void PageView::resetFormFieldText( int pageNumber, Okular::Document *document, Okular::FormFieldText *form ) +{ + int prevCursorPos = form->text().size(); + document->editFormText(pageNumber, form, QStringLiteral(""), 0, prevCursorPos, prevCursorPos); +} + +void PageView::resetCheckBoxForms( int pageNumber, Okular::Document *document, const QList< Okular::FormFieldButton* >& formButtons, const QList< bool >& newButtonStates ) +{ + document->editFormButtons( pageNumber, formButtons, newButtonStates); +} + +void PageView::resetComboForms(int pageNumber, Okular::Document *document, Okular::FormFieldChoice *m_comboEdit) +{ + document->editFormCombo( pageNumber, m_comboEdit, QStringLiteral(""), 0, 0, 0); +} + +void PageView::resetListEdit(int pageNumber, Okular::Document *document, Okular::FormFieldChoice *m_listEdit) +{ + document->editFormList( pageNumber, m_listEdit, QList()); +} + +void PageView::resetRadioButtonForms( int pageNumber, Okular::Document *document, const QList< Okular::FormFieldButton* >& formButtons, const QList< bool >& newButtonStates ) +{ + document->editFormButtons( pageNumber, formButtons, newButtonStates); +} + + void PageView::resizeContentArea( const QSize & newSize ) { const QSize vs = viewport()->size(); @@ -5338,6 +5478,11 @@ toggleFormWidgets( !d->m_formsVisible ); } +void PageView::slotResetForms() +{ + resetFormWidgets( d->m_formsVisible ); +} + void PageView::slotFormChanged( int pageNumber ) { if ( !d->refreshTimer )