mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-27 03:30:20 +00:00
Undo support for PDF forms
Together with the already commited support for undo in annotations fixes 177501 BUGS: 177501 REVIEW: 110589 FIXED-IN: 4.11.0
This commit is contained in:
parent
8d98819184
commit
b7ce9114c5
|
@ -83,6 +83,7 @@
|
|||
#include "utils_p.h"
|
||||
#include "view.h"
|
||||
#include "view_p.h"
|
||||
#include "form.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<int> & 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;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "annotations.h"
|
||||
#include "debug_p.h"
|
||||
#include "document_p.h"
|
||||
#include "form.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
|
@ -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<int>() << 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<int>() << 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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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; */
|
||||
|
|
|
@ -8,56 +8,112 @@
|
|||
***************************************************************************/
|
||||
|
||||
#include "formwidgets.h"
|
||||
#include "pageviewutils.h"
|
||||
|
||||
#include <qbuttongroup.h>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QEvent>
|
||||
#include <klineedit.h>
|
||||
#include <klocale.h>
|
||||
#include <kstandardaction.h>
|
||||
#include <kaction.h>
|
||||
|
||||
// local includes
|
||||
#include "core/form.h"
|
||||
#include "core/document.h"
|
||||
|
||||
FormWidgetsController::FormWidgetsController( QObject *parent )
|
||||
: QObject( parent )
|
||||
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<int> ) ),
|
||||
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<int> ) ),
|
||||
doc, SLOT( editFormList( int, Okular::FormFieldChoice*, QList<int> ) ) );
|
||||
connect( doc, SIGNAL( formListChangedByUndoRedo( int, Okular::FormFieldChoice*, QList<int> ) ),
|
||||
this, SIGNAL( formListChangedByUndoRedo( int,Okular::FormFieldChoice*, QList<int> ) ) );
|
||||
|
||||
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<Okular::FormFieldButton*>, QList<bool> ) ),
|
||||
doc, SLOT( editFormButtons( int, QList<Okular::FormFieldButton*>, QList<bool> ) ) );
|
||||
connect( doc, SIGNAL( formButtonsChangedByUndoRedo( int, QList<Okular::FormFieldButton*> ) ),
|
||||
this, SLOT( slotFormButtonsChangedByUndoRedo(int,QList<Okular::FormFieldButton*> ) ) );
|
||||
|
||||
// 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() );
|
||||
|
||||
m_controller->signalChanged( this );
|
||||
FormWidgetIface::setFormWidgetsController(controller);
|
||||
connect( m_controller, SIGNAL( formTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ),
|
||||
this, SLOT( slotHandleTextChangedByUndoRedo( int, Okular::FormFieldText*, QString, int, int ) ) );
|
||||
}
|
||||
|
||||
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<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( 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() );
|
||||
}
|
||||
|
||||
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<QAction *> 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 )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
void TextAreaEdit::slotChanged()
|
||||
{
|
||||
m_form->setText( toPlainText() );
|
||||
|
||||
m_controller->signalChanged( this );
|
||||
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 )
|
||||
{
|
||||
m_form->setText( url().toLocalFile() );
|
||||
|
||||
m_controller->signalChanged( this );
|
||||
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()
|
||||
{
|
||||
// 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_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<int> ) ),
|
||||
this, SLOT( slotHandleFormListChangedByUndoRedo( int, Okular::FormFieldChoice*, QList<int> ) ) );
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if ( isCustomValue )
|
||||
QString prevText;
|
||||
if ( m_form->currentChoices().isEmpty() )
|
||||
{
|
||||
m_form->setEditChoice( text );
|
||||
prevText = m_form->editChoice();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_form->setCurrentChoices( QList< int >() << index );
|
||||
prevText = m_form->choices()[m_form->currentChoices()[0]];
|
||||
}
|
||||
|
||||
m_controller->signalChanged( this );
|
||||
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 )
|
||||
{
|
||||
setEditText( text );
|
||||
}
|
||||
else
|
||||
{
|
||||
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<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( 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"
|
||||
|
|
130
ui/formwidgets.h
130
ui/formwidgets.h
|
@ -21,10 +21,13 @@
|
|||
#include <ktextedit.h>
|
||||
#include <kurlrequester.h>
|
||||
|
||||
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& );
|
||||
|
||||
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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue