diff --git a/autotests/data/checkbox_ro.pdf b/autotests/data/checkbox_ro.pdf new file mode 100644 index 000000000..e5d62b02d Binary files /dev/null and b/autotests/data/checkbox_ro.pdf differ diff --git a/autotests/parttest.cpp b/autotests/parttest.cpp index 7fd37c3c9..f2932fb1e 100644 --- a/autotests/parttest.cpp +++ b/autotests/parttest.cpp @@ -19,6 +19,8 @@ #include "../ui/toc.h" #include "../ui/pageview.h" +#include "../generators/poppler/config-okular-poppler.h" + #include #include @@ -105,6 +107,7 @@ class PartTest void testRClickOnSelectionModeShoulShowFollowTheLinkMenu(); void testClickAnywhereAfterSelectionShouldUnselect(); void testeRectSelectionStartingOnLinks(); + void testCheckBoxReadOnly(); private: void simulateMouseSelection(double startX, double startY, double endX, double endY, QWidget *target); @@ -1281,6 +1284,121 @@ void PartTest::test388288() QTRY_COMPARE(part.m_pageView->cursor().shape(), Qt::OpenHandCursor); } +void PartTest::testCheckBoxReadOnly() +{ +#ifndef HAVE_POPPLER_0_64 + return; +#endif + + const QString testFile = QStringLiteral( KDESRCDIR "data/checkbox_ro.pdf" ); + Okular::Part part( nullptr, nullptr, QVariantList() ); + part.openDocument( testFile ); + + // The test document uses the activation action of checkboxes + // to update the read only state. For this we need the part so that + // undo / redo activates the activation action. + + QVERIFY( part.m_document->isOpened() ); + + const Okular::Page* page = part.m_document->page( 0 ); + + QMap fields; + + // Field names in test document are: + // CBMakeRW, CBMakeRO, TargetDefaultRO, TargetDefaultRW + + for ( Okular::FormField *ff: page->formFields() ) + { + fields.insert( ff->name(), static_cast< Okular::FormField* >( ff ) ); + } + + // First grab all fields and check that the setup is as expected. + auto cbMakeRW = dynamic_cast< Okular::FormFieldButton* > ( fields[QStringLiteral( "CBMakeRW" )] ); + auto cbMakeRO = dynamic_cast< Okular::FormFieldButton* > ( fields[QStringLiteral( "CBMakeRO" )] ); + + auto targetDefaultRW = dynamic_cast< Okular::FormFieldText* > ( fields[QStringLiteral( "TargetDefaultRw" )] ); + auto targetDefaultRO = dynamic_cast< Okular::FormFieldText* > ( fields[QStringLiteral( "TargetDefaultRo" )] ); + + QVERIFY( cbMakeRW ); + QVERIFY( cbMakeRO ); + QVERIFY( targetDefaultRW ); + QVERIFY( targetDefaultRO ); + + QVERIFY( !cbMakeRW->state() ); + QVERIFY( !cbMakeRO->state() ); + + QVERIFY( !targetDefaultRW->isReadOnly() ); + QVERIFY( targetDefaultRO->isReadOnly() ); + + QList< Okular::FormFieldButton* > btns; + btns << cbMakeRW << cbMakeRO; + + // Now check both boxes + QList< bool > btnStates; + btnStates << true << true; + + part.m_document->editFormButtons( 0, btns, btnStates ); + + // Read only should be inverted + QVERIFY( targetDefaultRW->isReadOnly() ); + QVERIFY( !targetDefaultRO->isReadOnly() ); + + // Test that undo / redo works + QVERIFY( part.m_document->canUndo() ); + part.m_document->undo(); + QVERIFY( !targetDefaultRW->isReadOnly() ); + QVERIFY( targetDefaultRO->isReadOnly() ); + + part.m_document->redo(); + QVERIFY( targetDefaultRW->isReadOnly() ); + QVERIFY( !targetDefaultRO->isReadOnly() ); + + btnStates.clear(); + btnStates << false << true; + + part.m_document->editFormButtons( 0, btns, btnStates ); + QVERIFY( targetDefaultRW->isReadOnly() ); + QVERIFY( targetDefaultRO->isReadOnly() ); + + // Now set both to checked again and confirm that + // save / load works. + btnStates.clear(); + btnStates << true << true; + part.m_document->editFormButtons( 0, btns, btnStates ); + + QTemporaryFile saveFile( QString( "%1/okrXXXXXX.pdf" ).arg( QDir::tempPath() ) ); + QVERIFY( saveFile.open() ); + saveFile.close(); + + // Save + QVERIFY( part.saveAs( QUrl::fromLocalFile( saveFile.fileName() ), Part::NoSaveAsFlags ) ); + part.closeUrl(); + + // Load + part.openDocument( saveFile.fileName() ); + QVERIFY( part.m_document->isOpened() ); + + page = part.m_document->page( 0 ); + + fields.clear(); + + for ( Okular::FormField *ff: page->formFields() ) + { + fields.insert( ff->name(), static_cast< Okular::FormField* >( ff ) ); + } + + cbMakeRW = dynamic_cast< Okular::FormFieldButton* > ( fields[QStringLiteral( "CBMakeRW" )] ); + cbMakeRO = dynamic_cast< Okular::FormFieldButton* > ( fields[QStringLiteral( "CBMakeRO" )] ); + + targetDefaultRW = dynamic_cast< Okular::FormFieldText* > ( fields[QStringLiteral( "TargetDefaultRw" )] ); + targetDefaultRO = dynamic_cast< Okular::FormFieldText* > ( fields[QStringLiteral( "TargetDefaultRo" )] ); + + QVERIFY( cbMakeRW->state() ); + QVERIFY( cbMakeRO->state() ); + QVERIFY( targetDefaultRW->isReadOnly() ); + QVERIFY( !targetDefaultRO->isReadOnly() ); +} + } int main(int argc, char *argv[]) diff --git a/core/form.cpp b/core/form.cpp index 530499fa3..35b05c2a6 100644 --- a/core/form.cpp +++ b/core/form.cpp @@ -55,6 +55,10 @@ bool FormField::isReadOnly() const return false; } +void FormField::setReadOnly( bool ) +{ +} + bool FormField::isVisible() const { return true; diff --git a/core/form.h b/core/form.h index 359019e7d..20b68c517 100644 --- a/core/form.h +++ b/core/form.h @@ -86,6 +86,13 @@ class OKULARCORE_EXPORT FormField */ virtual bool isReadOnly() const; + /** + * Whether the field is read-only. + * + * @since 1.4 + */ + virtual void setReadOnly( bool value ); + /** * Whether this form field is visible. */ diff --git a/core/script/kjs_field.cpp b/core/script/kjs_field.cpp index b3798ebb7..2cc9bd026 100644 --- a/core/script/kjs_field.cpp +++ b/core/script/kjs_field.cpp @@ -31,6 +31,23 @@ static KJSPrototype *g_fieldProto; typedef QHash< FormField *, Page * > FormCache; Q_GLOBAL_STATIC( FormCache, g_fieldCache ) + +// Helper for modified fields +static void updateField( FormField *field ) +{ + Page *page = g_fieldCache->value( field ); + if (page) + { + Document *doc = PagePrivate::get( page )->m_doc->m_parent; + QMetaObject::invokeMethod( doc, "refreshPixmaps", Qt::QueuedConnection, Q_ARG( int, page->number() ) ); + emit doc->refreshFormWidget( field ); + } + else + { + qWarning() << "Could not get page of field" << field; + } +} + // Field.doc static KJSObject fieldGetDoc( KJSContext *context, void * ) { @@ -54,16 +71,11 @@ static KJSObject fieldGetReadOnly( KJSContext *, void *object ) // Field.readonly (setter) static void fieldSetReadOnly( KJSContext *context, void *object, KJSObject value ) { -#if 0 FormField *field = reinterpret_cast< FormField * >( object ); bool b = value.toBoolean( context ); field->setReadOnly( b ); -#else - Q_UNUSED( context ); - Q_UNUSED( object ); - Q_UNUSED( value ); - qCDebug(OkularCoreDebug) << "Not implemented: setting readonly property"; -#endif + + updateField( field ); } static QString fieldGetTypeHelper( const FormField *field ) @@ -122,8 +134,11 @@ static KJSObject fieldGetValue( KJSContext */*context*/, void *object ) case FormField::FormButton: { const FormFieldButton *button = static_cast< const FormFieldButton * >( field ); - Q_UNUSED( button ); // ### - break; + if ( button->state() ) + { + return KJSString( QStringLiteral( "Yes" ) ); + } + return KJSString( QStringLiteral( "Off" ) ); } case FormField::FormText: { @@ -155,7 +170,17 @@ static void fieldSetValue( KJSContext *context, void *object, KJSObject value ) case FormField::FormButton: { FormFieldButton *button = static_cast< FormFieldButton * >( field ); - Q_UNUSED( button ); // ### + const QString text = value.toString( context ); + if ( text == QStringLiteral( "Yes" ) ) + { + button->setState( true ); + updateField( field ); + } + else if ( text == QStringLiteral( "Off" ) ) + { + button->setState( false ); + updateField( field ); + } break; } case FormField::FormText: @@ -165,18 +190,7 @@ static void fieldSetValue( KJSContext *context, void *object, KJSObject value ) if ( text != textField->text() ) { textField->setText( text ); - - Page *page = g_fieldCache->value( field ); - if (page) - { - Document *doc = PagePrivate::get( page )->m_doc->m_parent; - QMetaObject::invokeMethod( doc, "refreshPixmaps", Qt::QueuedConnection, Q_ARG( int, page->number() ) ); - emit doc->refreshFormWidget( field ); - } - else - { - qWarning() << "Could not get page of field" << field; - } + updateField( field ); } break; } diff --git a/generators/poppler/CMakeLists.txt b/generators/poppler/CMakeLists.txt index a3dd38dc9..73881f0e1 100644 --- a/generators/poppler/CMakeLists.txt +++ b/generators/poppler/CMakeLists.txt @@ -72,6 +72,16 @@ int main() } " HAVE_POPPLER_0_63) +check_cxx_source_compiles(" +#include +#include +int main() +{ + Poppler::FormField *f; + f->setReadOnly(true); +} +" HAVE_POPPLER_0_64) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-okular-poppler.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-okular-poppler.h diff --git a/generators/poppler/config-okular-poppler.h.cmake b/generators/poppler/config-okular-poppler.h.cmake index 16831f749..99f23fc86 100644 --- a/generators/poppler/config-okular-poppler.h.cmake +++ b/generators/poppler/config-okular-poppler.h.cmake @@ -24,3 +24,6 @@ /* Defined if we have the 0.63 version of the Poppler library */ #cmakedefine HAVE_POPPLER_0_63 1 + +/* Defined if we have the 0.64 version of the Poppler library */ +#cmakedefine HAVE_POPPLER_0_64 1 diff --git a/generators/poppler/formfields.cpp b/generators/poppler/formfields.cpp index 5539525e7..78fc69d12 100644 --- a/generators/poppler/formfields.cpp +++ b/generators/poppler/formfields.cpp @@ -67,6 +67,15 @@ bool PopplerFormFieldButton::isReadOnly() const return m_field->isReadOnly(); } +void PopplerFormFieldButton::setReadOnly( bool value ) +{ +#ifdef HAVE_POPPLER_0_64 + m_field->setReadOnly( value ); +#else + Q_UNUSED( value ); +#endif +} + bool PopplerFormFieldButton::isVisible() const { return m_field->isVisible(); @@ -145,6 +154,15 @@ bool PopplerFormFieldText::isReadOnly() const return m_field->isReadOnly(); } +void PopplerFormFieldText::setReadOnly( bool value ) +{ +#ifdef HAVE_POPPLER_0_64 + m_field->setReadOnly( value ); +#else + Q_UNUSED( value ); +#endif +} + bool PopplerFormFieldText::isVisible() const { return m_field->isVisible(); @@ -238,6 +256,15 @@ bool PopplerFormFieldChoice::isReadOnly() const return m_field->isReadOnly(); } +void PopplerFormFieldChoice::setReadOnly( bool value ) +{ +#ifdef HAVE_POPPLER_0_64 + m_field->setReadOnly( value ); +#else + Q_UNUSED( value ); +#endif +} + bool PopplerFormFieldChoice::isVisible() const { return m_field->isVisible(); diff --git a/generators/poppler/formfields.h b/generators/poppler/formfields.h index c5dfcf5fc..eff478e26 100644 --- a/generators/poppler/formfields.h +++ b/generators/poppler/formfields.h @@ -25,6 +25,7 @@ class PopplerFormFieldButton : public Okular::FormFieldButton QString name() const override; QString uiName() const override; bool isReadOnly() const override; + void setReadOnly( bool value ) override; bool isVisible() const override; // inherited from Okular::FormFieldButton @@ -53,6 +54,7 @@ class PopplerFormFieldText : public Okular::FormFieldText QString name() const override; QString uiName() const override; bool isReadOnly() const override; + void setReadOnly( bool value ) override; bool isVisible() const override; // inherited from Okular::FormFieldText @@ -84,6 +86,7 @@ class PopplerFormFieldChoice : public Okular::FormFieldChoice QString name() const override; QString uiName() const override; bool isReadOnly() const override; + void setReadOnly( bool value ) override; bool isVisible() const override; // inherited from Okular::FormFieldChoice diff --git a/ui/formwidgets.cpp b/ui/formwidgets.cpp index d39bd2699..68f459571 100644 --- a/ui/formwidgets.cpp +++ b/ui/formwidgets.cpp @@ -154,7 +154,8 @@ bool FormWidgetsController::canRedo() void FormWidgetsController::slotButtonClicked( QAbstractButton *button ) { int pageNumber = -1; - if ( CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button ) ) + CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button ); + if ( check ) { // Checkboxes need to be uncheckable so if clicking a checked one // disable the exclusive status temporarily and uncheck it @@ -186,6 +187,13 @@ void FormWidgetsController::slotButtonClicked( QAbstractButton *button ) } if (checked != prevChecked) emit formButtonsChangedByWidget( pageNumber, formButtons, checked ); + if ( check ) + { + // The formButtonsChangedByWidget signal changes the value of the underlying + // Okular::FormField of the checkbox. We need to execute the activiation + // action after this. + check->doActivateAction(); + } } void FormWidgetsController::slotFormButtonsChangedByUndoRedo( int pageNumber, const QList< Okular::FormFieldButton* > & formButtons) @@ -194,6 +202,11 @@ void FormWidgetsController::slotFormButtonsChangedByUndoRedo( int pageNumber, co { int id = formButton->id(); QAbstractButton* button = m_buttons[id]; + CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button ); + if ( check ) + { + emit refreshFormWidget( check->formField() ); + } // temporarily disable exclusiveness of the button group // since it breaks doing/redoing steps into which all the checkboxes // are unchecked @@ -211,9 +224,6 @@ FormWidgetIface * FormWidgetFactory::createWidget( Okular::FormField * ff, QWidg { FormWidgetIface * widget = nullptr; - if (ff->isReadOnly()) - return nullptr; - switch ( ff->type() ) { case Okular::FormField::FormButton: @@ -267,15 +277,17 @@ FormWidgetIface * FormWidgetFactory::createWidget( Okular::FormField * ff, QWidg } default: ; } + + if ( ff->isReadOnly() ) + widget->setVisibility( false ); + return widget; } -FormWidgetIface::FormWidgetIface( QWidget * w, Okular::FormField * ff, bool canBeEnabled ) - : m_controller( nullptr ), m_ff( ff ), m_widget( w ), m_pageItem( nullptr ), - m_canBeEnabled( canBeEnabled ) +FormWidgetIface::FormWidgetIface( QWidget * w, Okular::FormField * ff ) + : m_controller( nullptr ), m_ff( ff ), m_widget( w ), m_pageItem( nullptr ) { - m_widget->setEnabled( m_canBeEnabled ); } FormWidgetIface::~FormWidgetIface() @@ -308,7 +320,7 @@ bool FormWidgetIface::setVisibility( bool visible ) void FormWidgetIface::setCanBeFilled( bool fill ) { - m_widget->setEnabled( fill && m_canBeEnabled ); + m_widget->setEnabled( fill ); } void FormWidgetIface::setPageItem( PageViewItem *pageItem ) @@ -334,11 +346,27 @@ PageViewItem* FormWidgetIface::pageItem() const void FormWidgetIface::setFormWidgetsController( FormWidgetsController *controller ) { m_controller = controller; + QObject *obj = dynamic_cast< QObject * > ( this ); + QObject::connect( m_controller, &FormWidgetsController::refreshFormWidget, obj, + [this] ( Okular::FormField *form ) { + slotRefresh ( form ); + }); +} + +void FormWidgetIface::slotRefresh( Okular::FormField * form ) +{ + if ( m_ff != form ) + { + return; + } + setVisibility( form->isVisible() && !form->isReadOnly() ); + + m_widget->setEnabled( !form->isReadOnly() ); } PushButtonEdit::PushButtonEdit( Okular::FormFieldButton * button, QWidget * parent ) - : QPushButton( parent ), FormWidgetIface( this, button, !button->isReadOnly() ) + : QPushButton( parent ), FormWidgetIface( this, button ) { setText( button->caption() ); setVisible( button->isVisible() ); @@ -355,7 +383,7 @@ void PushButtonEdit::slotClicked() CheckBoxEdit::CheckBoxEdit( Okular::FormFieldButton * button, QWidget * parent ) - : QCheckBox( parent ), FormWidgetIface( this, button, !button->isReadOnly() ) + : QCheckBox( parent ), FormWidgetIface( this, button ) { setText( button->caption() ); @@ -369,19 +397,36 @@ void CheckBoxEdit::setFormWidgetsController( FormWidgetsController *controller ) FormWidgetIface::setFormWidgetsController( controller ); m_controller->registerRadioButton( this, form ); setChecked( form->state() ); - connect( this, &QCheckBox::stateChanged, this, &CheckBoxEdit::slotStateChanged ); } -void CheckBoxEdit::slotStateChanged( int state ) +void CheckBoxEdit::doActivateAction() { Okular::FormFieldButton *form = static_cast(m_ff); - if ( state == Qt::Checked && form->activationAction() ) + if ( form->activationAction() ) m_controller->signalAction( form->activationAction() ); } +void CheckBoxEdit::slotRefresh( Okular::FormField * form ) +{ + if ( form != m_ff ) + { + return; + } + FormWidgetIface::slotRefresh( form ); + + Okular::FormFieldButton *button = static_cast(m_ff); + bool oldState = isChecked(); + bool newState = button->state(); + if ( oldState != newState ) + { + setChecked( button->state() ); + doActivateAction(); + } +} + RadioButtonEdit::RadioButtonEdit( Okular::FormFieldButton * button, QWidget * parent ) - : QRadioButton( parent ), FormWidgetIface( this, button, !button->isReadOnly() ) + : QRadioButton( parent ), FormWidgetIface( this, button ) { setText( button->caption() ); @@ -399,7 +444,7 @@ void RadioButtonEdit::setFormWidgetsController( FormWidgetsController *controlle FormLineEdit::FormLineEdit( Okular::FormFieldText * text, QWidget * parent ) - : QLineEdit( parent ), FormWidgetIface( this, text, true ) + : QLineEdit( parent ), FormWidgetIface( this, text ) { int maxlen = text->maximumLength(); if ( maxlen >= 0 ) @@ -423,8 +468,6 @@ void FormLineEdit::setFormWidgetsController(FormWidgetsController* controller) FormWidgetIface::setFormWidgetsController(controller); connect( m_controller, &FormWidgetsController::formTextChangedByUndoRedo, this, &FormLineEdit::slotHandleTextChangedByUndoRedo ); - connect( m_controller, &FormWidgetsController::refreshFormWidget, - this, &FormLineEdit::slotRefresh ); } bool FormLineEdit::event( QEvent* e ) @@ -527,13 +570,14 @@ void FormLineEdit::slotRefresh( Okular::FormField *form ) { return; } - Okular::FormFieldText *text = static_cast ( form ); + FormWidgetIface::slotRefresh( form ); + Okular::FormFieldText *text = static_cast ( form ); setText( text->text() ); } TextAreaEdit::TextAreaEdit( Okular::FormFieldText * text, QWidget * parent ) -: KTextEdit( parent ), FormWidgetIface( this, text, true ) +: KTextEdit( parent ), FormWidgetIface( this, text ) { setAcceptRichText( text->isRichText() ); setCheckSpellingEnabled( text->canBeSpellChecked() ); @@ -599,8 +643,6 @@ void TextAreaEdit::setFormWidgetsController( FormWidgetsController* controller ) FormWidgetIface::setFormWidgetsController( controller ); connect( m_controller, &FormWidgetsController::formTextChangedByUndoRedo, this, &TextAreaEdit::slotHandleTextChangedByUndoRedo ); - connect( m_controller, &FormWidgetsController::refreshFormWidget, - this, &TextAreaEdit::slotRefresh ); } void TextAreaEdit::slotHandleTextChangedByUndoRedo( int pageNumber, @@ -648,13 +690,14 @@ void TextAreaEdit::slotRefresh( Okular::FormField *form ) { return; } - Okular::FormFieldText *text = static_cast ( form ); + FormWidgetIface::slotRefresh( form ); + Okular::FormFieldText *text = static_cast ( form ); setPlainText( text->text() ); } FileEdit::FileEdit( Okular::FormFieldText * text, QWidget * parent ) - : KUrlRequester( parent ), FormWidgetIface( this, text, !text->isReadOnly() ) + : KUrlRequester( parent ), FormWidgetIface( this, text ) { setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ); setFilter( i18n( "*|All Files" ) ); @@ -780,7 +823,7 @@ void FileEdit::slotHandleFileChangedByUndoRedo( int pageNumber, } ListEdit::ListEdit( Okular::FormFieldChoice * choice, QWidget * parent ) - : QListWidget( parent ), FormWidgetIface( this, choice, !choice->isReadOnly() ) + : QListWidget( parent ), FormWidgetIface( this, choice ) { addItems( choice->choices() ); setSelectionMode( choice->multiSelect() ? QAbstractItemView::ExtendedSelection : QAbstractItemView::SingleSelection ); @@ -850,7 +893,7 @@ void ListEdit::slotHandleFormListChangedByUndoRedo( int pageNumber, } ComboEdit::ComboEdit( Okular::FormFieldChoice * choice, QWidget * parent ) - : QComboBox( parent ), FormWidgetIface( this, choice, !choice->isReadOnly() ) + : QComboBox( parent ), FormWidgetIface( this, choice ) { addItems( choice->choices() ); setEditable( true ); diff --git a/ui/formwidgets.h b/ui/formwidgets.h index e0b1f03ae..22ea721af 100644 --- a/ui/formwidgets.h +++ b/ui/formwidgets.h @@ -143,7 +143,7 @@ class FormWidgetFactory class FormWidgetIface { public: - FormWidgetIface( QWidget * w, Okular::FormField * ff, bool canBeEnabled ); + FormWidgetIface( QWidget * w, Okular::FormField * ff ); virtual ~FormWidgetIface(); Okular::NormalizedRect rect() const; @@ -160,13 +160,14 @@ class FormWidgetIface virtual void setFormWidgetsController( FormWidgetsController *controller ); protected: + virtual void slotRefresh( Okular::FormField *form ); + FormWidgetsController * m_controller; Okular::FormField * m_ff; private: QWidget * m_widget; PageViewItem * m_pageItem; - bool m_canBeEnabled; }; @@ -191,8 +192,10 @@ class CheckBoxEdit : public QCheckBox, public FormWidgetIface // reimplemented from FormWidgetIface void setFormWidgetsController( FormWidgetsController *controller ) override; - private Q_SLOTS: - void slotStateChanged( int state ); + void doActivateAction(); + + protected: + void slotRefresh( Okular::FormField *form ) override; }; class RadioButtonEdit : public QRadioButton, public FormWidgetIface @@ -225,7 +228,9 @@ class FormLineEdit : public QLineEdit, public FormWidgetIface int anchorPos ); private Q_SLOTS: void slotChanged(); - void slotRefresh(Okular::FormField* form); + + protected: + void slotRefresh( Okular::FormField* form ) override; private: int m_prevCursorPos; @@ -252,7 +257,9 @@ class TextAreaEdit : public KTextEdit, public FormWidgetIface private Q_SLOTS: void slotChanged(); - void slotRefresh(Okular::FormField* form); + + protected: + void slotRefresh( Okular::FormField* form ) override; private: int m_prevCursorPos; diff --git a/ui/pageviewutils.cpp b/ui/pageviewutils.cpp index d8a8698bc..d639b0d1b 100644 --- a/ui/pageviewutils.cpp +++ b/ui/pageviewutils.cpp @@ -204,7 +204,8 @@ bool PageViewItem::setFormWidgetsVisible( bool visible ) QSet::iterator it = m_formWidgets.begin(), itEnd = m_formWidgets.end(); for ( ; it != itEnd; ++it ) { - bool hadfocus = (*it)->setVisibility( visible && (*it)->formField()->isVisible() ); + bool hadfocus = (*it)->setVisibility( visible && (*it)->formField()->isVisible() && + !(*it)->formField()->isReadOnly() ); somehadfocus = somehadfocus || hadfocus; } return somehadfocus; @@ -214,7 +215,7 @@ void PageViewItem::reloadFormWidgetsState() { foreach(FormWidgetIface *fwi, m_formWidgets) { - fwi->setVisibility( fwi->formField()->isVisible() ); + fwi->setVisibility( fwi->formField()->isVisible() && !fwi->formField()->isReadOnly() ); } }