diff --git a/core/document.cpp b/core/document.cpp index 7cf346132..585b7306a 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -83,6 +83,7 @@ #include "utils_p.h" #include "view.h" #include "view_p.h" +#include "form.h" #include @@ -3408,6 +3409,54 @@ void Document::redo() d->m_undoStack->redo(); } +void Document::editFormText( int pageNumber, + Okular::FormFieldText* form, + const QString & newContents, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos ) +{ + QUndoCommand *uc = new EditFormTextCommand( this, form, pageNumber, newContents, newCursorPos, form->text(), prevCursorPos, prevAnchorPos ); + d->m_undoStack->push( uc ); +} + +void Document::editFormList( int pageNumber, + FormFieldChoice* form, + const QList< int > & newChoices ) +{ + const QList< int > prevChoices = form->currentChoices(); + QUndoCommand *uc = new EditFormListCommand( this, form, pageNumber, newChoices, prevChoices ); + d->m_undoStack->push( uc ); +} + +void Document::editFormCombo( int pageNumber, + FormFieldChoice* form, + const QString & newText, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos ) +{ + + QString prevText; + if ( form->currentChoices().isEmpty() ) + { + prevText = form->editChoice(); + } + else + { + prevText = form->choices()[form->currentChoices()[0]]; + } + + QUndoCommand *uc = new EditFormComboCommand( this, form, pageNumber, newText, newCursorPos, prevText, prevCursorPos, prevAnchorPos ); + d->m_undoStack->push( uc ); +} + +void Document::editFormButtons( int pageNumber, const QList< FormFieldButton* >& formButtons, const QList< bool >& newButtonStates ) +{ + QUndoCommand *uc = new EditFormButtonsCommand( this, pageNumber, formButtons, newButtonStates ); + d->m_undoStack->push( uc ); +} + BookmarkManager * Document::bookmarkManager() const { return d->m_bookmarkManager; diff --git a/core/document.h b/core/document.h index d443917d2..fe296e049 100644 --- a/core/document.h +++ b/core/document.h @@ -44,6 +44,9 @@ class DocumentViewport; class EmbeddedFile; class ExportFormat; class FontInfo; +class FormFieldText; +class FormFieldButton; +class FormFieldChoice; class Generator; class Action; class MovieAction; @@ -746,6 +749,52 @@ class OKULAR_EXPORT Document : public QObject */ void redo(); + /** + * Edit the text contents of the specified @p form on page @p page to be @p newContents. + * The new text cursor position (@p newCursorPos), previous text cursor position (@p prevCursorPos), + * and previous cursor anchor position will be restored by the undo / redo commands. + * @since 0.17 (KDE 4.11) + */ + void editFormText( int pageNumber, + Okular::FormFieldText* form, + const QString & newContents, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos ); + + /** + * Edit the selected list entries in @p form on page @p page to be @p newChoices. + * @since 0.17 (KDE 4.11) + */ + void editFormList( int pageNumber, + Okular::FormFieldChoice* form, + const QList & newChoices ); + + + /** + * Set the active choice in the combo box @p form on page @p page to @p newText + * The new cursor position (@p newCursorPos), previous cursor position + * (@p prevCursorPos), and previous anchor position (@p prevAnchorPos) + * will be restored by the undo / redo commands. + * + * @since 0.17 (KDE 4.11) + */ + void editFormCombo( int pageNumber, + Okular::FormFieldChoice *form, + const QString & newText, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos ); + + /** + * Set the states of the group of form buttons @p formButtons on page @p page to @p newButtonStates. + * The lists @p formButtons and @p newButtonStates should be the same length and true values + * in @p newButtonStates indicate that the corresponding entry in @p formButtons should be enabled. + */ + void editFormButtons( int pageNumber, + const QList< Okular::FormFieldButton* > & formButtons, + const QList< bool > & newButtonStates ); + Q_SIGNALS: /** * This signal is emitted whenever an action requests a @@ -882,12 +931,46 @@ class OKULAR_EXPORT Document : public QObject */ void annotationContentsChangedByUndoRedo( Okular::Annotation* annotation, const QString & contents, int cursorPos, int anchorPos ); + /** + * This signal is emmitted whenever the text contents of the given text @p form on the given @p page + * are changed by an undo or redo action. + * + * The new text contents (@p contents), cursor position (@p cursorPos), and anchor position (@p anchorPos) are + * included + * @since 0.17 (KDE 4.11) + */ + void formTextChangedByUndoRedo( int page, Okular::FormFieldText* form, const QString & contents, int cursorPos, int anchorPos ); + + /** + * This signal is emmitted whenever the selected @p choices for the given list @p form on the + * given @p page are changed by an undo or redo action. + * @since 0.17 (KDE 4.11) + */ + void formListChangedByUndoRedo( int page, Okular::FormFieldChoice* form, const QList< int > & choices ); + + /** + * This signal is emmitted whenever the active @p text for the given combo @p form on the + * given @p page is changed by an undo or redo action. + * @since 0.17 (KDE 4.11) + */ + void formComboChangedByUndoRedo( int page, Okular::FormFieldChoice* form, const QString & text, int cursorPos, int anchorPos ); + + /** + * This signal is emmitted whenever the state of the specified group of form buttons (@p formButtons) on the + * given @p page is changed by an undo or redo action. + * @since 0.17 (KDE 4.11) + */ + void formButtonsChangedByUndoRedo( int page, const QList< Okular::FormFieldButton* > & formButtons ); private: /// @cond PRIVATE friend class DocumentPrivate; friend class Part; friend class ::DocumentItem; friend class EditAnnotationContentsCommand; + friend class EditFormTextCommand; + friend class EditFormListCommand; + friend class EditFormComboCommand; + friend class EditFormButtonsCommand; /// @endcond DocumentPrivate *const d; diff --git a/core/documentcommands.cpp b/core/documentcommands.cpp index 5fcc195dc..7799bb0d4 100644 --- a/core/documentcommands.cpp +++ b/core/documentcommands.cpp @@ -12,6 +12,7 @@ #include "annotations.h" #include "debug_p.h" #include "document_p.h" +#include "form.h" #include @@ -288,5 +289,209 @@ bool EditAnnotationContentsCommand::mergeWith(const QUndoCommand* uc) } } +EditFormTextCommand::EditFormTextCommand( Okular::Document* doc, + Okular::FormFieldText* form, + int pageNumber, + const QString & newContents, + int newCursorPos, + const QString & prevContents, + int prevCursorPos, + int prevAnchorPos ) +: EditTextCommand( newContents, newCursorPos, prevContents, prevCursorPos, prevAnchorPos ), + m_doc ( doc ), + m_form( form ), + m_pageNumber( pageNumber ) +{ + setText( i18nc( "Edit an form's text contents", "edit form contents" ) ); +} + +void EditFormTextCommand::undo() +{ + m_form->setText( m_prevContents ); + m_doc->formTextChangedByUndoRedo( m_pageNumber, m_form, m_prevContents, m_prevCursorPos, m_prevAnchorPos ); +} + +void EditFormTextCommand::redo() +{ + m_form->setText( m_newContents ); + m_doc->formTextChangedByUndoRedo( m_pageNumber, m_form, m_newContents, m_newCursorPos, m_newCursorPos ); +} + +int EditFormTextCommand::id() const +{ + return 3; +} + +bool EditFormTextCommand::mergeWith(const QUndoCommand* uc) +{ + EditFormTextCommand *euc = (EditFormTextCommand*)uc; + // Only attempt merge of euc into this if they modify the same form + if ( m_form == euc->m_form ) + { + return EditTextCommand::mergeWith( uc ); + } + else + { + return false; + } +} + +EditFormListCommand::EditFormListCommand( Okular::Document* doc, + FormFieldChoice* form, + int pageNumber, + const QList< int > & newChoices, + const QList< int > & prevChoices ) +: m_doc( doc ), + m_form( form ), + m_pageNumber( pageNumber ), + m_newChoices( newChoices ), + m_prevChoices( prevChoices ) +{ + setText( i18nc( "Edit a list form's choices", "edit list form choices" ) ); +} + +void EditFormListCommand::undo() +{ + m_form->setCurrentChoices( m_prevChoices ); + m_doc->formListChangedByUndoRedo( m_pageNumber, m_form, m_prevChoices ); +} + +void EditFormListCommand::redo() +{ + m_form->setCurrentChoices( m_newChoices ); + m_doc->formListChangedByUndoRedo( m_pageNumber, m_form, m_newChoices ); +} + +EditFormComboCommand::EditFormComboCommand( Okular::Document* doc, + FormFieldChoice* form, + int pageNumber, + const QString & newContents, + int newCursorPos, + const QString & prevContents, + int prevCursorPos, + int prevAnchorPos ) +: EditTextCommand( newContents, newCursorPos, prevContents, prevCursorPos, prevAnchorPos ), + m_doc( doc ), + m_form( form ), + m_pageNumber( pageNumber ), + m_newIndex( -1 ), + m_prevIndex( -1 ) +{ + setText( i18nc( "Edit a combo form's selection", "edit combo form selection" ) ); + + // Determine new and previous choice indices (if any) + for ( int i = 0; i < m_form->choices().size(); i++ ) + { + if ( m_form->choices()[i] == m_prevContents ) + { + m_prevIndex = i; + } + + if ( m_form->choices()[i] == m_newContents ) + { + m_newIndex = i; + } + } +} + +void EditFormComboCommand::undo() +{ + if ( m_prevIndex != -1 ) + { + m_form->setCurrentChoices( QList() << m_prevIndex ); + } + else + { + m_form->setEditChoice( m_prevContents ); + } + m_doc->formComboChangedByUndoRedo( m_pageNumber, m_form, m_prevContents, m_prevCursorPos, m_prevAnchorPos ); +} + +void EditFormComboCommand::redo() +{ + if ( m_newIndex != -1 ) + { + m_form->setCurrentChoices( QList() << m_newIndex ); + } + else + { + m_form->setEditChoice( m_newContents ); + } + m_doc->formComboChangedByUndoRedo( m_pageNumber, m_form, m_newContents, m_newCursorPos, m_newCursorPos ); +} + +int EditFormComboCommand::id() const +{ + return 4; +} + +bool EditFormComboCommand::mergeWith( const QUndoCommand *uc ) +{ + EditFormComboCommand *euc = (EditFormComboCommand*)uc; + // Only attempt merge of euc into this if they modify the same form + if ( m_form == euc->m_form ) + { + bool shouldMerge = EditTextCommand::mergeWith( uc ); + if( shouldMerge ) + { + m_newIndex = euc->m_newIndex; + } + return shouldMerge; + } + else + { + return false; + } +} + +EditFormButtonsCommand::EditFormButtonsCommand( Okular::Document* doc, + int pageNumber, + const QList< FormFieldButton* > & formButtons, + const QList< bool > & newButtonStates ) +: m_doc( doc ), + m_pageNumber( pageNumber ), + m_formButtons( formButtons ), + m_newButtonStates( newButtonStates ), + m_prevButtonStates( QList< bool >() ) +{ + setText( i18nc( "Edit the state of a group of form buttons", "edit form button states" ) ); + foreach( FormFieldButton* formButton, m_formButtons ) + { + m_prevButtonStates.append( formButton->state() ); + } +} + +void EditFormButtonsCommand::undo() +{ + clearFormButtonStates(); + for( int i = 0; i < m_formButtons.size(); i++ ) + { + bool checked = m_prevButtonStates.at( i ); + if ( checked ) + m_formButtons.at( i )->setState( checked ); + } + m_doc->formButtonsChangedByUndoRedo( m_pageNumber, m_formButtons ); +} + +void EditFormButtonsCommand::redo() +{ + clearFormButtonStates(); + for( int i = 0; i < m_formButtons.size(); i++ ) + { + bool checked = m_newButtonStates.at( i ); + if ( checked ) + m_formButtons.at( i )->setState( checked ); + } + m_doc->formButtonsChangedByUndoRedo( m_pageNumber, m_formButtons ); +} + +void EditFormButtonsCommand::clearFormButtonStates() +{ + foreach( FormFieldButton* formButton, m_formButtons ) + { + formButton->setState( false ); + } +} + } diff --git a/core/documentcommands_p.h b/core/documentcommands_p.h index a9775a621..fe1c577dd 100644 --- a/core/documentcommands_p.h +++ b/core/documentcommands_p.h @@ -17,8 +17,12 @@ namespace Okular { +class Document; class Annotation; class DocumentPrivate; +class FormFieldText; +class FormFieldButton; +class FormFieldChoice; class AddAnnotationCommand : public QUndoCommand { @@ -157,8 +161,98 @@ class EditAnnotationContentsCommand : public EditTextCommand int m_pageNumber; }; -} +class EditFormTextCommand : public EditTextCommand +{ + public: + EditFormTextCommand( Okular::Document* doc, + Okular::FormFieldText* form, + int pageNumber, + const QString & newContents, + int newCursorPos, + const QString & prevContents, + int prevCursorPos, + int prevAnchorPos ); + virtual void undo(); + virtual void redo(); + virtual int id() const; + virtual bool mergeWith( const QUndoCommand *uc ); + private: + Okular::Document* m_doc; + Okular::FormFieldText* m_form; + int m_pageNumber; +}; + +class EditFormListCommand : public QUndoCommand +{ + public: + EditFormListCommand( Okular::Document* doc, + FormFieldChoice* form, + int pageNumber, + const QList< int > & newChoices, + const QList< int > & prevChoices + ); + + virtual void undo(); + virtual void redo(); + + private: + Okular::Document* m_doc; + FormFieldChoice* m_form; + int m_pageNumber; + QList< int > m_newChoices; + QList< int > m_prevChoices; +}; + +class EditFormComboCommand : public EditTextCommand +{ + public: + EditFormComboCommand( Okular::Document* doc, + FormFieldChoice* form, + int pageNumber, + const QString & newText, + int newCursorPos, + const QString & prevText, + int prevCursorPos, + int prevAnchorPos + ); + virtual void undo(); + virtual void redo(); + virtual int id() const; + virtual bool mergeWith( const QUndoCommand *uc ); + + private: + Okular::Document* m_doc; + FormFieldChoice* m_form; + int m_pageNumber; + int m_newIndex; + int m_prevIndex; +}; + +class EditFormButtonsCommand : public QUndoCommand +{ + public: + EditFormButtonsCommand( Okular::Document* doc, + int pageNumber, + const QList< FormFieldButton* > & formButtons, + const QList< bool > & newButtonStates + ); + + virtual void undo(); + virtual void redo(); + + private: + void clearFormButtonStates(); + + private: + Okular::Document* m_doc; + int m_pageNumber; + QList< FormFieldButton* > m_formButtons; + QList< bool > m_newButtonStates; + QList< bool > m_prevButtonStates; +}; + +} #endif /* kate: replace-tabs on; indent-width 4; */ diff --git a/ui/formwidgets.cpp b/ui/formwidgets.cpp index 57ecceb50..023a25ffc 100644 --- a/ui/formwidgets.cpp +++ b/ui/formwidgets.cpp @@ -8,56 +8,112 @@ ***************************************************************************/ #include "formwidgets.h" +#include "pageviewutils.h" #include +#include +#include +#include #include #include +#include +#include // local includes #include "core/form.h" - -FormWidgetsController::FormWidgetsController( QObject *parent ) - : QObject( parent ) -{ +#include "core/document.h" + +FormWidgetsController::FormWidgetsController( Okular::Document *doc ) + : QObject( doc ), m_doc( doc ) +{ + // emit changed signal when a form has changed + connect( this, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ), + this, SIGNAL( changed( int ) ) ); + connect( this, SIGNAL( formListChangedByUndoRedo(int, Okular::FormFieldChoice*, QList ) ), + this, SIGNAL( changed( int ) ) ); + connect( this, SIGNAL( formComboChangedByUndoRedo(int, Okular::FormFieldChoice*, QString, int, int ) ), + this, SIGNAL( changed( int ) ) ); + + // connect form modification signals to and from document + connect( this, SIGNAL( formTextChangedByWidget( int, Okular::FormFieldText*, QString, int, int, int ) ), + doc, SLOT( editFormText( int, Okular::FormFieldText*, QString, int, int, int ) ) ); + connect( doc, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ), + this, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ) ); + + connect( this, SIGNAL( formListChangedByWidget( int, Okular::FormFieldChoice*, QList ) ), + doc, SLOT( editFormList( int, Okular::FormFieldChoice*, QList ) ) ); + connect( doc, SIGNAL( formListChangedByUndoRedo( int, Okular::FormFieldChoice*, QList ) ), + this, SIGNAL( formListChangedByUndoRedo( int,Okular::FormFieldChoice*, QList ) ) ); + + connect( this, SIGNAL( formComboChangedByWidget( int, Okular::FormFieldChoice*, QString, int, int, int ) ), + doc, SLOT( editFormCombo( int, Okular::FormFieldChoice*, QString, int, int, int ) ) ); + connect( doc, SIGNAL( formComboChangedByUndoRedo( int, Okular::FormFieldChoice*, QString, int, int ) ), + this, SIGNAL( formComboChangedByUndoRedo( int, Okular::FormFieldChoice*, QString, int, int ) ) ); + + connect( this, SIGNAL( formButtonsChangedByWidget( int, QList, QList ) ), + doc, SLOT( editFormButtons( int, QList, QList ) ) ); + connect( doc, SIGNAL( formButtonsChangedByUndoRedo( int, QList ) ), + this, SLOT( slotFormButtonsChangedByUndoRedo(int,QList ) ) ); + + // Connect undo/redo signals + connect( this, SIGNAL( requestUndo() ), + doc, SLOT( undo() ) ); + connect( this, SIGNAL( requestRedo() ), + doc, SLOT( redo() ) ); + + connect( doc, SIGNAL( canUndoChanged( bool ) ), + this, SIGNAL( canUndoChanged( bool ) ) ); + connect( doc, SIGNAL( canRedoChanged( bool ) ), + this, SIGNAL( canRedoChanged( bool ) ) ); } FormWidgetsController::~FormWidgetsController() { } -void FormWidgetsController::signalChanged( FormWidgetIface *w ) -{ - emit changed( w ); -} - void FormWidgetsController::signalAction( Okular::Action *a ) { emit action( a ); } -QButtonGroup* FormWidgetsController::registerRadioButton( FormWidgetIface* widget, const QList< int >& siblings ) +QButtonGroup* FormWidgetsController::registerRadioButton( QAbstractButton *button, Okular::FormFieldButton *formButton ) { - if ( !widget->button() ) + if ( !button ) return 0; + + QList< RadioData >::iterator it = m_radios.begin(), itEnd = m_radios.end(); - const int id = widget->formField()->id(); + const int id = formButton->id(); + m_formButtons.insert( id, formButton ); + m_buttons.insert( id, button ); for ( ; it != itEnd; ++it ) { const QList< int >::const_iterator idsIt = qFind( (*it).ids, id ); if ( idsIt != (*it).ids.constEnd() ) { - (*it).group->addButton( widget->button() ); + kDebug(4700) << "Adding id" << id << "To group including" << (*it).ids; + (*it).group->addButton( button ); + (*it).group->setId( button, id ); return (*it).group; } } + + const QList< int > siblings = formButton->siblings(); + RadioData newdata; newdata.ids = siblings; newdata.ids.append( id ); newdata.group = new QButtonGroup(); - newdata.group->addButton( widget->button() ); - connect( newdata.group, SIGNAL(buttonClicked(QAbstractButton*)), - this, SLOT(slotButtonClicked(QAbstractButton*)) ); + newdata.group->addButton( button ); + newdata.group->setId( button, id ); + + // Groups of 1 (like checkboxes) can't be exclusive + if (siblings.isEmpty()) + newdata.group->setExclusive( false ); + + connect( newdata.group, SIGNAL( buttonClicked(QAbstractButton* ) ), + this, SLOT( slotButtonClicked( QAbstractButton* ) ) ); m_radios.append( newdata ); return newdata.group; } @@ -70,16 +126,60 @@ void FormWidgetsController::dropRadioButtons() delete (*it).group; } m_radios.clear(); + m_buttons.clear(); + m_formButtons.clear(); +} + +bool FormWidgetsController::canUndo() +{ + return m_doc->canUndo(); +} + +bool FormWidgetsController::canRedo() +{ + return m_doc->canRedo(); } void FormWidgetsController::slotButtonClicked( QAbstractButton *button ) { + int pageNumber = -1; if ( CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button ) ) - emit changed( check ); + { + pageNumber = check->pageItem()->pageNumber(); + } else if ( RadioButtonEdit *radio = qobject_cast< RadioButtonEdit * >( button ) ) - emit changed( radio ); + { + pageNumber = radio->pageItem()->pageNumber(); + } + + const QList< QAbstractButton* > buttons = button->group()->buttons(); + QList< bool > checked; + QList< bool > prevChecked; + QList< Okular::FormFieldButton*> formButtons; + + foreach ( QAbstractButton* button, buttons ) + { + checked.append( button->isChecked() ); + int id = button->group()->id( button ); + formButtons.append( m_formButtons[id] ); + prevChecked.append( m_formButtons[id]->state() ); + } + if (checked != prevChecked) + emit formButtonsChangedByWidget( pageNumber, formButtons, checked ); } +void FormWidgetsController::slotFormButtonsChangedByUndoRedo( int pageNumber, const QList< Okular::FormFieldButton* > & formButtons) +{ + foreach ( Okular::FormFieldButton* formButton, formButtons ) + { + int id = formButton->id(); + QAbstractButton* button = m_buttons[id]; + bool checked = formButton->state(); + button->setChecked( checked ); + button->setFocus(); + } + emit changed( pageNumber ); +} FormWidgetIface * FormWidgetFactory::createWidget( Okular::FormField * ff, QWidget * parent ) { @@ -242,13 +342,8 @@ CheckBoxEdit::CheckBoxEdit( Okular::FormFieldButton * button, QWidget * parent ) void CheckBoxEdit::setFormWidgetsController( FormWidgetsController *controller ) { FormWidgetIface::setFormWidgetsController( controller ); - - const QList< int > siblings = m_form->siblings(); - if ( !siblings.isEmpty() ) - m_controller->registerRadioButton( this, siblings ); - - setCheckState( m_form->state() ? Qt::Checked : Qt::Unchecked ); - + m_controller->registerRadioButton( button(), m_form ); + setChecked( m_form->state() ); connect( this, SIGNAL(stateChanged(int)), this, SLOT(slotStateChanged(int)) ); } @@ -259,11 +354,6 @@ QAbstractButton* CheckBoxEdit::button() void CheckBoxEdit::slotStateChanged( int state ) { - m_form->setState( state == Qt::Checked ); - - if ( !group() ) - m_controller->signalChanged( this ); - if ( state == Qt::Checked && m_form->activationAction() ) m_controller->signalAction( m_form->activationAction() ); } @@ -282,12 +372,8 @@ RadioButtonEdit::RadioButtonEdit( Okular::FormFieldButton * button, QWidget * pa void RadioButtonEdit::setFormWidgetsController( FormWidgetsController *controller ) { FormWidgetIface::setFormWidgetsController( controller ); - - m_controller->registerRadioButton( this, m_form->siblings() ); - + m_controller->registerRadioButton( button(), m_form ); setChecked( m_form->state() ); - - connect( this, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool)) ); } QAbstractButton* RadioButtonEdit::button() @@ -295,15 +381,6 @@ QAbstractButton* RadioButtonEdit::button() return this; } -void RadioButtonEdit::slotToggled( bool checked ) -{ - m_form->setState( checked ); - - if ( !group() ) - m_controller->signalChanged( this ); -} - - FormLineEdit::FormLineEdit( Okular::FormFieldText * text, QWidget * parent ) : QLineEdit( parent ), FormWidgetIface( this, text ), m_form( text ) { @@ -316,36 +393,220 @@ FormLineEdit::FormLineEdit( Okular::FormFieldText * text, QWidget * parent ) setEchoMode( QLineEdit::Password ); setReadOnly( m_form->isReadOnly() ); - connect( this, SIGNAL(textEdited(QString)), this, SLOT(textEdited(QString)) ); + m_prevCursorPos = cursorPosition(); + m_prevAnchorPos = cursorPosition(); + + connect( this, SIGNAL( textEdited( QString ) ), this, SLOT( slotChanged() ) ); + connect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); setVisible( m_form->isVisible() ); } -void FormLineEdit::textEdited( const QString& ) +void FormLineEdit::setFormWidgetsController(FormWidgetsController* controller) { - m_form->setText( text() ); + FormWidgetIface::setFormWidgetsController(controller); + connect( m_controller, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ), + this, SLOT( slotHandleTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ) ); +} - m_controller->signalChanged( this ); +bool FormLineEdit::event( QEvent* e ) +{ + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent *keyEvent = static_cast< QKeyEvent* >( e ); + if ( keyEvent == QKeySequence::Undo ) + { + emit m_controller->requestUndo(); + return true; + } + else if ( keyEvent == QKeySequence::Redo ) + { + emit m_controller->requestRedo(); + return true; + } + } + return QLineEdit::event( e ); +} + +void FormLineEdit::contextMenuEvent( QContextMenuEvent* event ) +{ + QMenu *menu = createStandardContextMenu(); + + QList actionList = menu->actions(); + enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct }; + + KAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu ); + KAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu ); + connect( m_controller, SIGNAL( canUndoChanged( bool ) ), kundo, SLOT( setEnabled( bool ) ) ); + connect( m_controller, SIGNAL( canRedoChanged( bool ) ), kredo, SLOT( setEnabled( bool ) ) ); + kundo->setEnabled( m_controller->canUndo() ); + kredo->setEnabled( m_controller->canRedo() ); + + QAction *oldUndo, *oldRedo; + oldUndo = actionList[UndoAct]; + oldRedo = actionList[RedoAct]; + + menu->insertAction( oldUndo, kundo ); + menu->insertAction( oldRedo, kredo ); + + menu->removeAction( oldUndo ); + menu->removeAction( oldRedo ); + + menu->exec( event->globalPos() ); + delete menu; } +void FormLineEdit::slotChanged() +{ + QString contents = text(); + int cursorPos = cursorPosition(); + if ( contents != m_form->text() ) + { + m_controller->formTextChangedByWidget( pageItem()->pageNumber(), + m_form, + contents, + cursorPos, + m_prevCursorPos, + m_prevAnchorPos ); + } + + m_prevCursorPos = cursorPos; + m_prevAnchorPos = cursorPos; + if ( hasSelectedText() ) { + if ( cursorPos == selectionStart() ) { + m_prevAnchorPos = selectionStart() + selectedText().size(); + } else { + m_prevAnchorPos = selectionStart(); + } + } +} + +void FormLineEdit::slotHandleTextChangedByUndoRedo( int pageNumber, + Okular::FormFieldText* textForm, + const QString & contents, + int cursorPos, + int anchorPos ) +{ + if ( textForm != m_form || contents == text() ) + { + return; + } + disconnect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); + setText(contents); + setCursorPosition(anchorPos); + cursorForward( true, cursorPos - anchorPos ); + connect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); + m_prevCursorPos = cursorPos; + m_prevAnchorPos = anchorPos; + setFocus(); +} TextAreaEdit::TextAreaEdit( Okular::FormFieldText * text, QWidget * parent ) - : KTextEdit( parent ), FormWidgetIface( this, text ), m_form( text ) +: KTextEdit( parent ), FormWidgetIface( this, text ), m_form( text ) { setAcceptRichText( m_form->isRichText() ); setCheckSpellingEnabled( m_form->canBeSpellChecked() ); setAlignment( m_form->textAlignment() ); setPlainText( m_form->text() ); setReadOnly( m_form->isReadOnly() ); + setUndoRedoEnabled( false ); - connect( this, SIGNAL(textChanged()), this, SLOT(slotChanged()) ); + connect( this, SIGNAL( textChanged() ), this, SLOT( slotChanged() ) ); + connect( this, SIGNAL( cursorPositionChanged() ), this, SLOT( slotChanged() ) ); + + connect( this, SIGNAL( aboutToShowContextMenu( QMenu* ) ), + this, SLOT( slotUpdateUndoAndRedoInContextMenu( QMenu* ) ) ); + + m_prevCursorPos = textCursor().position(); + m_prevAnchorPos = textCursor().anchor(); setVisible( m_form->isVisible() ); } -void TextAreaEdit::slotChanged() +bool TextAreaEdit::event( QEvent* e ) +{ + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent *keyEvent = static_cast< QKeyEvent* >(e); + if ( keyEvent == QKeySequence::Undo ) + { + emit m_controller->requestUndo(); + return true; + } + else if ( keyEvent == QKeySequence::Redo ) + { + emit m_controller->requestRedo(); + return true; + } + } + return KTextEdit::event( e ); +} + +void TextAreaEdit::slotUpdateUndoAndRedoInContextMenu( QMenu* menu ) +{ + if ( !menu ) return; + + QList actionList = menu->actions(); + enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, ClearAct, SelectAllAct, NCountActs }; + + KAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu ); + KAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu ); + connect(m_controller, SIGNAL( canUndoChanged( bool ) ), kundo, SLOT( setEnabled( bool ) ) ); + connect(m_controller, SIGNAL( canRedoChanged( bool ) ), kredo, SLOT( setEnabled( bool ) ) ); + kundo->setEnabled( m_controller->canUndo() ); + kredo->setEnabled( m_controller->canRedo() ); + + QAction *oldUndo, *oldRedo; + oldUndo = actionList[UndoAct]; + oldRedo = actionList[RedoAct]; + + menu->insertAction( oldUndo, kundo ); + menu->insertAction( oldRedo, kredo ); + + menu->removeAction( oldUndo ); + menu->removeAction( oldRedo ); +} + +void TextAreaEdit::setFormWidgetsController( FormWidgetsController* controller ) +{ + FormWidgetIface::setFormWidgetsController( controller ); + connect( m_controller, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ), + this, SLOT( slotHandleTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ) ); +} + +void TextAreaEdit::slotHandleTextChangedByUndoRedo( int pageNumber, + Okular::FormFieldText* textForm, + const QString & contents, + int cursorPos, + int anchorPos ) { - m_form->setText( toPlainText() ); + if ( textForm != m_form ) + { + return; + } + setPlainText( contents ); + QTextCursor c = textCursor(); + c.setPosition( anchorPos ); + c.setPosition( cursorPos,QTextCursor::KeepAnchor ); + m_prevCursorPos = cursorPos; + m_prevAnchorPos = anchorPos; + setTextCursor( c ); + setFocus(); +} - m_controller->signalChanged( this ); +void TextAreaEdit::slotChanged() +{ + QString contents = toPlainText(); + int cursorPos = textCursor().position(); + if (contents != m_form->text()) + { + m_controller->formTextChangedByWidget( pageItem()->pageNumber(), + m_form, + contents, + cursorPos, + m_prevCursorPos, + m_prevAnchorPos ); + } + m_prevCursorPos = cursorPos; + m_prevAnchorPos = textCursor().anchor(); } @@ -358,17 +619,120 @@ FileEdit::FileEdit( Okular::FormFieldText * text, QWidget * parent ) lineEdit()->setAlignment( m_form->textAlignment() ); setEnabled( !m_form->isReadOnly() ); - connect( this, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString)) ); + m_prevCursorPos = lineEdit()->cursorPosition(); + m_prevAnchorPos = lineEdit()->cursorPosition(); + + connect( this, SIGNAL( textChanged( QString ) ), this, SLOT( slotChanged() ) ); + connect( lineEdit(), SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); setVisible( m_form->isVisible() ); } -void FileEdit::slotChanged( const QString& ) +void FileEdit::setFormWidgetsController( FormWidgetsController* controller ) +{ + FormWidgetIface::setFormWidgetsController( controller ); + connect( m_controller, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ), + this, SLOT( slotHandleFileChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ) ); +} + +bool FileEdit::eventFilter( QObject* obj, QEvent* event ) +{ + if ( obj == lineEdit() ) { + if ( event->type() == QEvent::KeyPress ) + { + QKeyEvent *keyEvent = static_cast< QKeyEvent* >( event ); + if ( keyEvent == QKeySequence::Undo ) + { + emit m_controller->requestUndo(); + return true; + } + else if ( keyEvent == QKeySequence::Redo ) + { + emit m_controller->requestRedo(); + return true; + } + } + else if( event->type() == QEvent::ContextMenu ) + { + QContextMenuEvent *contextMenuEvent = static_cast< QContextMenuEvent* >( event ); + + QMenu *menu = ( (QLineEdit*) lineEdit() )->createStandardContextMenu(); + + QList< QAction* > actionList = menu->actions(); + enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct }; + + KAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu ); + KAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu ); + connect(m_controller, SIGNAL( canUndoChanged( bool ) ), kundo, SLOT( setEnabled( bool ) ) ); + connect(m_controller, SIGNAL( canRedoChanged( bool ) ), kredo, SLOT( setEnabled( bool ) ) ); + kundo->setEnabled( m_controller->canUndo() ); + kredo->setEnabled( m_controller->canRedo() ); + + QAction *oldUndo, *oldRedo; + oldUndo = actionList[UndoAct]; + oldRedo = actionList[RedoAct]; + + menu->insertAction( oldUndo, kundo ); + menu->insertAction( oldRedo, kredo ); + + menu->removeAction( oldUndo ); + menu->removeAction( oldRedo ); + + menu->exec( contextMenuEvent->globalPos() ); + delete menu; + return true; + } + } + return KUrlRequester::eventFilter( obj, event ); +} + +void FileEdit::slotChanged() { - m_form->setText( url().toLocalFile() ); + // Make sure line edit's text matches url expansion + if ( text() != url().toLocalFile() ) + this->setText( url().toLocalFile() ); + + QString contents = text(); + int cursorPos = lineEdit()->cursorPosition(); + if (contents != m_form->text()) + { + m_controller->formTextChangedByWidget( pageItem()->pageNumber(), + m_form, + contents, + cursorPos, + m_prevCursorPos, + m_prevAnchorPos ); + } - m_controller->signalChanged( this ); + m_prevCursorPos = cursorPos; + m_prevAnchorPos = cursorPos; + if ( lineEdit()->hasSelectedText() ) { + if ( cursorPos == lineEdit()->selectionStart() ) { + m_prevAnchorPos = lineEdit()->selectionStart() + lineEdit()->selectedText().size(); + } else { + m_prevAnchorPos = lineEdit()->selectionStart(); + } + } } +void FileEdit::slotHandleFileChangedByUndoRedo( int pageNumber, + Okular::FormFieldText* form, + const QString & contents, + int cursorPos, + int anchorPos ) +{ + if ( form != m_form || contents == text() ) + { + return; + } + disconnect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); + setText( contents ); + lineEdit()->setCursorPosition( anchorPos ); + lineEdit()->cursorForward( true, cursorPos - anchorPos ); + connect( this, SIGNAL(cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) ); + m_prevCursorPos = cursorPos; + m_prevAnchorPos = anchorPos; + setFocus(); +} ListEdit::ListEdit( Okular::FormFieldChoice * choice, QWidget * parent ) : QListWidget( parent ), FormWidgetIface( this, choice ), m_form( choice ) @@ -398,17 +762,44 @@ ListEdit::ListEdit( Okular::FormFieldChoice * choice, QWidget * parent ) setCursor( Qt::ArrowCursor ); } +void ListEdit::setFormWidgetsController( FormWidgetsController* controller ) +{ + FormWidgetIface::setFormWidgetsController( controller ); + connect( m_controller, SIGNAL( formListChangedByUndoRedo(int, Okular::FormFieldChoice*, QList ) ), + this, SLOT( slotHandleFormListChangedByUndoRedo( int, Okular::FormFieldChoice*, QList ) ) ); +} + void ListEdit::slotSelectionChanged() { QList< QListWidgetItem * > selection = selectedItems(); QList< int > rows; foreach( const QListWidgetItem * item, selection ) rows.append( row( item ) ); - m_form->setCurrentChoices( rows ); - m_controller->signalChanged( this ); + if ( rows != m_form->currentChoices() ) { + m_controller->formListChangedByWidget( pageItem()->pageNumber(), + m_form, + rows ); + } } +void ListEdit::slotHandleFormListChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice* listForm, + const QList< int > & choices ) +{ + if ( m_form != listForm ) { + return; + } + + disconnect( this, SIGNAL( itemSelectionChanged() ), this, SLOT( slotSelectionChanged() ) ); + for(int i=0; i < count(); i++) + { + item( i )->setSelected( choices.contains(i) ); + } + connect( this, SIGNAL( itemSelectionChanged() ), this, SLOT( slotSelectionChanged() ) ); + + setFocus(); +} ComboEdit::ComboEdit( Okular::FormFieldChoice * choice, QWidget * parent ) : QComboBox( parent ), FormWidgetIface( this, choice ), m_form( choice ) @@ -427,27 +818,143 @@ ComboEdit::ComboEdit( Okular::FormFieldChoice * choice, QWidget * parent ) connect( this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotValueChanged()) ); connect( this, SIGNAL(editTextChanged(QString)), this, SLOT(slotValueChanged()) ); + connect( lineEdit(), SIGNAL(cursorPositionChanged(int,int)), this, SLOT(slotValueChanged())); + setVisible( m_form->isVisible() ); setCursor( Qt::ArrowCursor ); + m_prevCursorPos = lineEdit()->cursorPosition(); + m_prevAnchorPos = lineEdit()->cursorPosition(); +} + +void ComboEdit::setFormWidgetsController(FormWidgetsController* controller) +{ + FormWidgetIface::setFormWidgetsController(controller); + connect( m_controller, SIGNAL(formComboChangedByUndoRedo(int,Okular::FormFieldChoice*, QString, int, int )), + this, SLOT(slotHandleFormComboChangedByUndoRedo(int,Okular::FormFieldChoice*, QString, int, int ))); + } void ComboEdit::slotValueChanged() { - const int index = currentIndex(); - const QString text = currentText(); - const bool isCustomValue = ( index == -1 || itemText( index ) != text ); + const QString text = lineEdit()->text(); + + QString prevText; + if ( m_form->currentChoices().isEmpty() ) + { + prevText = m_form->editChoice(); + } + else + { + prevText = m_form->choices()[m_form->currentChoices()[0]]; + } + + int cursorPos = lineEdit()->cursorPosition(); + if ( text != prevText ) + { + m_controller->formComboChangedByWidget( pageItem()->pageNumber(), + m_form, + currentText(), + cursorPos, + m_prevCursorPos, + m_prevAnchorPos + ); + } + prevText = text; + m_prevCursorPos = cursorPos; + m_prevAnchorPos = cursorPos; + if ( lineEdit()->hasSelectedText() ) { + if ( cursorPos == lineEdit()->selectionStart() ) { + m_prevAnchorPos = lineEdit()->selectionStart() + lineEdit()->selectedText().size(); + } else { + m_prevAnchorPos = lineEdit()->selectionStart(); + } + } +} +void ComboEdit::slotHandleFormComboChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice* form, + const QString & text, + int cursorPos, + int anchorPos ) +{ + if ( m_form != form ) { + return; + } + + // Determine if text corrisponds to an index choices + int index = -1; + for ( int i = 0; i < count(); i++ ) + { + if ( itemText(i) == text ) + { + index = i; + } + } + + m_prevCursorPos = cursorPos; + m_prevAnchorPos = anchorPos; + + disconnect( lineEdit(), SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotValueChanged() ) ); + const bool isCustomValue = index == -1; if ( isCustomValue ) { - m_form->setEditChoice( text ); + setEditText( text ); } else { - m_form->setCurrentChoices( QList< int >() << index ); + setCurrentIndex( index ); } + lineEdit()->setCursorPosition( anchorPos ); + lineEdit()->cursorForward( true, cursorPos - anchorPos ); + connect( lineEdit(), SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotValueChanged() ) ); + setFocus(); +} + +void ComboEdit::contextMenuEvent( QContextMenuEvent* event ) +{ + QMenu *menu = lineEdit()->createStandardContextMenu(); + + QList actionList = menu->actions(); + enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct }; + + KAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu ); + KAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu ); + connect( m_controller, SIGNAL( canUndoChanged( bool ) ), kundo, SLOT( setEnabled( bool ) ) ); + connect( m_controller, SIGNAL( canRedoChanged( bool ) ), kredo, SLOT( setEnabled( bool ) ) ); + kundo->setEnabled( m_controller->canUndo() ); + kredo->setEnabled( m_controller->canRedo() ); - m_controller->signalChanged( this ); + QAction *oldUndo, *oldRedo; + oldUndo = actionList[UndoAct]; + oldRedo = actionList[RedoAct]; + + menu->insertAction( oldUndo, kundo ); + menu->insertAction( oldRedo, kredo ); + + menu->removeAction( oldUndo ); + menu->removeAction( oldRedo ); + + menu->exec( event->globalPos() ); + delete menu; } +bool ComboEdit::event( QEvent* e ) +{ + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent *keyEvent = static_cast< QKeyEvent* >(e); + if ( keyEvent == QKeySequence::Undo ) + { + emit m_controller->requestUndo(); + return true; + } + else if ( keyEvent == QKeySequence::Redo ) + { + emit m_controller->requestRedo(); + return true; + } + } + return QComboBox::event( e ); +} #include "formwidgets.moc" diff --git a/ui/formwidgets.h b/ui/formwidgets.h index 24108b80b..9b5d455e6 100644 --- a/ui/formwidgets.h +++ b/ui/formwidgets.h @@ -21,10 +21,13 @@ #include #include +class ComboEdit; +class QMenu; class QButtonGroup; class FormWidgetIface; class PageViewItem; class RadioButtonEdit; +class QEvent; namespace Okular { class Action; @@ -32,6 +35,7 @@ class FormField; class FormFieldButton; class FormFieldChoice; class FormFieldText; +class Document; } struct RadioData @@ -47,24 +51,81 @@ class FormWidgetsController : public QObject Q_OBJECT public: - FormWidgetsController( QObject *parent = 0 ); + FormWidgetsController( Okular::Document *doc ); virtual ~FormWidgetsController(); - void signalChanged( FormWidgetIface *w ); void signalAction( Okular::Action *action ); - QButtonGroup* registerRadioButton( FormWidgetIface* widget, const QList< int >& siblings ); + QButtonGroup* registerRadioButton( QAbstractButton *button, Okular::FormFieldButton *formButton ); void dropRadioButtons(); + bool canUndo(); + bool canRedo(); signals: - void changed( FormWidgetIface *w ); + void changed( int pageNumber ); + void requestUndo(); + void requestRedo(); + void canUndoChanged( bool undoAvailable ); + void canRedoChanged( bool redoAvailable); + void formTextChangedByWidget( int pageNumber, + Okular::FormFieldText *form, + const QString & newContents, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos ); + + void formTextChangedByUndoRedo( int pageNumber, + Okular::FormFieldText *form, + const QString & contents, + int cursorPos, + int anchorPos ); + + void formListChangedByWidget( int pageNumber, + Okular::FormFieldChoice *form, + const QList< int > & newChoices ); + + void formListChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice *form, + const QList< int > & choices ); + + void formComboChangedByWidget( int pageNumber, + Okular::FormFieldChoice *form, + const QString & newText, + int newCursorPos, + int prevCursorPos, + int prevAnchorPos + ); + + void formComboChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice *form, + const QString & text, + int cursorPos, + int anchorPos + ); + + void formButtonsChangedByWidget( int pageNumber, + const QList< Okular::FormFieldButton* > & formButtons, + const QList< bool > & newButtonStates ); + + void action( Okular::Action *action ); private slots: void slotButtonClicked( QAbstractButton *button ); + void slotFormButtonsChangedByUndoRedo( int pageNumber, + const QList< Okular::FormFieldButton* > & formButtons ); private: + friend class TextAreaEdit; + friend class FormLineEdit; + friend class FileEdit; + friend class ListEdit; + friend class ComboEdit; + QList< RadioData > m_radios; + QHash< int, Okular::FormFieldButton* > m_formButtons; + QHash< int, QAbstractButton* > m_buttons; + Okular::Document* m_doc; }; @@ -147,9 +208,6 @@ class RadioButtonEdit : public QRadioButton, public FormWidgetIface void setFormWidgetsController( FormWidgetsController *controller ); QAbstractButton* button(); - private slots: - void slotToggled( bool checked ); - private: Okular::FormFieldButton * m_form; }; @@ -160,12 +218,24 @@ class FormLineEdit : public QLineEdit, public FormWidgetIface public: explicit FormLineEdit( Okular::FormFieldText * text, QWidget * parent = 0 ); + void setFormWidgetsController( FormWidgetsController *controller ); + virtual bool event ( QEvent * e ); + virtual void contextMenuEvent( QContextMenuEvent* event ); + + public slots: + void slotHandleTextChangedByUndoRedo( int pageNumber, + Okular::FormFieldText* textForm, + const QString & contents, + int cursorPos, + int anchorPos ); private slots: - void textEdited( const QString& ); + void slotChanged(); private: Okular::FormFieldText * m_form; + int m_prevCursorPos; + int m_prevAnchorPos; }; class TextAreaEdit : public KTextEdit, public FormWidgetIface @@ -174,12 +244,25 @@ class TextAreaEdit : public KTextEdit, public FormWidgetIface public: explicit TextAreaEdit( Okular::FormFieldText * text, QWidget * parent = 0 ); + void setFormWidgetsController( FormWidgetsController *controller ); + virtual bool event ( QEvent * e ); + + + public slots: + void slotHandleTextChangedByUndoRedo( int pageNumber, + Okular::FormFieldText * textForm, + const QString & contents, + int cursorPos, + int anchorPos ); + void slotUpdateUndoAndRedoInContextMenu( QMenu* menu ); private slots: void slotChanged(); private: Okular::FormFieldText * m_form; + int m_prevCursorPos; + int m_prevAnchorPos; }; @@ -189,12 +272,23 @@ class FileEdit : public KUrlRequester, public FormWidgetIface public: explicit FileEdit( Okular::FormFieldText * text, QWidget * parent = 0 ); + void setFormWidgetsController( FormWidgetsController *controller ); + + protected: + bool eventFilter( QObject *obj, QEvent *event ); - private slots: - void slotChanged( const QString& ); + private slots: + void slotChanged(); + void slotHandleFileChangedByUndoRedo( int pageNumber, + Okular::FormFieldText * form, + const QString & contents, + int cursorPos, + int anchorPos ); private: Okular::FormFieldText * m_form; + int m_prevCursorPos; + int m_prevAnchorPos; }; @@ -204,9 +298,13 @@ class ListEdit : public QListWidget, public FormWidgetIface public: explicit ListEdit( Okular::FormFieldChoice * choice, QWidget * parent = 0 ); + void setFormWidgetsController( FormWidgetsController *controller ); private slots: void slotSelectionChanged(); + void slotHandleFormListChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice * listForm, + const QList< int > & choices ); private: Okular::FormFieldChoice * m_form; @@ -219,13 +317,23 @@ class ComboEdit : public QComboBox, public FormWidgetIface public: explicit ComboEdit( Okular::FormFieldChoice * choice, QWidget * parent = 0 ); + void setFormWidgetsController( FormWidgetsController *controller ); + virtual bool event ( QEvent * e ); + virtual void contextMenuEvent( QContextMenuEvent* event ); private slots: void slotValueChanged(); + void slotHandleFormComboChangedByUndoRedo( int pageNumber, + Okular::FormFieldChoice * comboForm, + const QString & text, + int cursorPos, + int anchorPos + ); private: - Okular::FormFieldChoice * m_form; + int m_prevCursorPos; + int m_prevAnchorPos; }; #endif diff --git a/ui/pageview.cpp b/ui/pageview.cpp index 180cc6e0f..6567d5b81 100644 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -223,11 +223,11 @@ FormWidgetsController* PageViewPrivate::formWidgetsController() { if ( !formsWidgetController ) { - formsWidgetController = new FormWidgetsController(); - QObject::connect( formsWidgetController, SIGNAL(changed(FormWidgetIface*)), - q, SLOT(slotFormWidgetChanged(FormWidgetIface*)) ); - QObject::connect( formsWidgetController, SIGNAL(action(Okular::Action*)), - q, SLOT(slotAction(Okular::Action*)) ); + formsWidgetController = new FormWidgetsController( document ); + QObject::connect( formsWidgetController, SIGNAL( changed( int ) ), + q, SLOT( slotFormChanged( int ) ) ); + QObject::connect( formsWidgetController, SIGNAL( action( Okular::Action* ) ), + q, SLOT( slotAction( Okular::Action* ) ) ); } return formsWidgetController; @@ -4642,17 +4642,22 @@ void PageView::slotToggleForms() toggleFormWidgets( !d->m_formsVisible ); } -void PageView::slotFormWidgetChanged( FormWidgetIface *w ) +void PageView::slotFormChanged( int pageNumber ) { if ( !d->refreshTimer ) { d->refreshTimer = new QTimer( this ); d->refreshTimer->setSingleShot( true ); - connect( d->refreshTimer, SIGNAL(timeout()), - this, SLOT(slotRefreshPage()) ); + connect( d->refreshTimer, SIGNAL( timeout() ), + this, SLOT( slotRefreshPage() ) ); } - d->refreshPage = w->pageItem()->pageNumber(); - d->refreshTimer->start( 1000 ); + d->refreshPage = pageNumber; + int delay = 0; + if ( d->m_formsVisible ) + { + delay = 1000; + } + d->refreshTimer->start( delay ); } void PageView::slotRefreshPage() diff --git a/ui/pageview.h b/ui/pageview.h index bb74e6f38..a9a291c3c 100644 --- a/ui/pageview.h +++ b/ui/pageview.h @@ -248,7 +248,7 @@ Q_OBJECT void slotPageSizes( int ); void slotTrimMarginsToggled( bool ); void slotToggleForms(); - void slotFormWidgetChanged( FormWidgetIface *w ); + void slotFormChanged( int pageNumber ); void slotRefreshPage(); void slotSpeakDocument(); void slotSpeakCurrentPage();