From 03ea6ff54dea0e227a44b5e1888512f872bcbc79 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Mon, 11 Feb 2008 10:41:04 +0000 Subject: [PATCH] Add the support in the core library and in the user interface for button form fields (ie, push button, check boxes and radio buttons). svn path=/trunk/KDE/kdegraphics/okular/; revision=773548 --- core/form.cpp | 38 +++++++++++++++++ core/form.h | 61 +++++++++++++++++++++++++++ ui/formwidgets.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++ ui/formwidgets.h | 64 +++++++++++++++++++++++++++- ui/pageview.cpp | 2 + 5 files changed, 266 insertions(+), 1 deletion(-) diff --git a/core/form.cpp b/core/form.cpp index 052e97923..cec52b230 100644 --- a/core/form.cpp +++ b/core/form.cpp @@ -58,6 +58,44 @@ bool FormField::isVisible() const } +class Okular::FormFieldButtonPrivate : public Okular::FormFieldPrivate +{ + public: + FormFieldButtonPrivate() + : FormFieldPrivate( FormField::FormButton ) + { + } + + Q_DECLARE_PUBLIC( FormFieldButton ) + + void setValue( const QString& v ) + { + Q_Q( FormFieldButton ); + q->setState( QVariant( v ).toBool() ); + } + + QString value() const + { + Q_Q( const FormFieldButton ); + return qVariantFromValue( q->state() ).toString(); + } +}; + + +FormFieldButton::FormFieldButton() + : FormField( *new FormFieldButtonPrivate() ) +{ +} + +FormFieldButton::~FormFieldButton() +{ +} + +void FormFieldButton::setState( bool ) +{ +} + + class Okular::FormFieldTextPrivate : public Okular::FormFieldPrivate { public: diff --git a/core/form.h b/core/form.h index f6ec3c52c..4a90a8532 100644 --- a/core/form.h +++ b/core/form.h @@ -20,6 +20,7 @@ namespace Okular { class Page; class PagePrivate; class FormFieldPrivate; +class FormFieldButtonPrivate; class FormFieldTextPrivate; class FormFieldChoicePrivate; @@ -101,6 +102,66 @@ class OKULAR_EXPORT FormField }; +/** + * @short Interface of a button form field. + * + * This is the base interface to reimplement to represent a button field, like + * a push button, a check box or a radio button. + * + * @since 0.7 (KDE 4.1) + */ +class OKULAR_EXPORT FormFieldButton : public FormField +{ + public: + /** + * The types of button field. + */ + enum ButtonType + { + Push, ///< A simple push button. + CheckBox, ///< A check box. + Radio ///< A radio button. + }; + + virtual ~FormFieldButton(); + + /** + The particular type of the button field. + */ + virtual ButtonType buttonType() const = 0; + + /** + * The caption to be used for the button. + */ + virtual QString caption() const = 0; + + /** + * The state of the button. + */ + virtual bool state() const = 0; + + /** + * Sets the state of the button to the new \p state . + */ + virtual void setState( bool state ); + + /** + * The list with the IDs of siblings (ie, buttons belonging to the same + * group as the current one. + * + * Valid only for \ref Radio buttons, an empty list otherwise. + */ + virtual QList< int > siblings() const = 0; + + protected: + FormFieldButton(); + + private: + Q_DECLARE_PRIVATE( FormFieldButton ) + Q_DISABLE_COPY( FormFieldButton ) +}; + + /** * @short Interface of a text form field. * diff --git a/ui/formwidgets.cpp b/ui/formwidgets.cpp index 177811e02..e0ebd4335 100644 --- a/ui/formwidgets.cpp +++ b/ui/formwidgets.cpp @@ -9,6 +9,7 @@ #include "formwidgets.h" +#include #include #include @@ -29,12 +30,62 @@ void FormWidgetsController::signalChanged( FormWidgetIface *w ) emit changed( w ); } +QButtonGroup* FormWidgetsController::registerRadioButton( RadioButtonEdit* radio ) +{ + QList< RadioData >::iterator it = m_radios.begin(), itEnd = m_radios.end(); + const int id = radio->buttonForm()->id(); + for ( ; it != itEnd; ++it ) + { + const QList< int >::const_iterator idsIt = qFind( (*it).ids, id ); + if ( idsIt != (*it).ids.end() ) + { + (*it).group->addButton( radio ); + return (*it).group; + } + } + RadioData newdata; + newdata.ids = radio->buttonForm()->siblings(); + newdata.ids.append( id ); + newdata.group = new QButtonGroup(); + newdata.group->addButton( radio ); + m_radios.append( newdata ); + return newdata.group; +} + +void FormWidgetsController::dropRadioButtons() +{ + QList< RadioData >::iterator it = m_radios.begin(), itEnd = m_radios.end(); + for ( ; it != itEnd; ++it ) + { + delete (*it).group; + } + m_radios.clear(); +} + FormWidgetIface * FormWidgetFactory::createWidget( Okular::FormField * ff, QWidget * parent ) { FormWidgetIface * widget = 0; switch ( ff->type() ) { + case Okular::FormField::FormButton: + { + Okular::FormFieldButton * ffb = static_cast< Okular::FormFieldButton * >( ff ); + switch ( ffb->buttonType() ) + { + case Okular::FormFieldButton::Push: + widget = new PushButtonEdit( ffb, parent ); + break; + case Okular::FormFieldButton::CheckBox: + widget = new CheckBoxEdit( ffb, parent ); + break; + case Okular::FormFieldButton::Radio: + widget = new RadioButtonEdit( ffb, parent ); + break; + default: ; + } + break; + } case Okular::FormField::FormText: { Okular::FormFieldText * fft = static_cast< Okular::FormFieldText * >( ff ); @@ -129,6 +180,57 @@ void FormWidgetIface::setFormWidgetsController( FormWidgetsController *controlle } +PushButtonEdit::PushButtonEdit( Okular::FormFieldButton * button, QWidget * parent ) + : QPushButton( parent ), FormWidgetIface( this, button ), m_form( button ) +{ + setText( m_form->caption() ); + setEnabled( !m_form->isReadOnly() ); + setVisible( m_form->isVisible() ); +} + + +CheckBoxEdit::CheckBoxEdit( Okular::FormFieldButton * button, QWidget * parent ) + : QCheckBox( parent ), FormWidgetIface( this, button ), m_form( button ) +{ + setText( m_form->caption() ); + setEnabled( !m_form->isReadOnly() ); + setCheckState( m_form->state() ? Qt::Checked : Qt::Unchecked ); + + connect( this, SIGNAL( stateChanged( int ) ), this, SLOT( slotStateChanged( int ) ) ); + setVisible( m_form->isVisible() ); +} + +void CheckBoxEdit::slotStateChanged( int state ) +{ + m_form->setState( state == Qt::Checked ); +} + + +RadioButtonEdit::RadioButtonEdit( Okular::FormFieldButton * button, QWidget * parent ) + : QRadioButton( parent ), FormWidgetIface( this, button ), m_form( button ) +{ + setText( m_form->caption() ); + setEnabled( !m_form->isReadOnly() ); + + connect( this, SIGNAL( toggled( bool ) ), this, SLOT( slotToggled( bool ) ) ); + setVisible( m_form->isVisible() ); +} + +void RadioButtonEdit::setFormWidgetsController( FormWidgetsController *controller ) +{ + FormWidgetIface::setFormWidgetsController( controller ); + + m_controller->registerRadioButton( this ); + + setChecked( m_form->state() ); +} + +void RadioButtonEdit::slotToggled( bool checked ) +{ + m_form->setState( checked ); +} + + FormLineEdit::FormLineEdit( Okular::FormFieldText * text, QWidget * parent ) : QLineEdit( parent ), FormWidgetIface( this, text ), m_form( text ) { diff --git a/ui/formwidgets.h b/ui/formwidgets.h index 2d58e62a6..4356590fe 100644 --- a/ui/formwidgets.h +++ b/ui/formwidgets.h @@ -12,22 +12,34 @@ #include "core/area.h" +#include #include #include #include #include +#include #include #include +class QButtonGroup; class FormWidgetIface; class PageViewItem; +class RadioButtonEdit; namespace Okular { class FormField; +class FormFieldButton; class FormFieldChoice; class FormFieldText; } +struct RadioData +{ + RadioData() {} + + QList< int > ids; + QButtonGroup *group; +}; class FormWidgetsController : public QObject { @@ -39,8 +51,14 @@ class FormWidgetsController : public QObject void signalChanged( FormWidgetIface *w ); + QButtonGroup* registerRadioButton( RadioButtonEdit* radio ); + void dropRadioButtons(); + signals: void changed( FormWidgetIface *w ); + + private: + QList< RadioData > m_radios; }; @@ -66,7 +84,7 @@ class FormWidgetIface void setPageItem( PageViewItem *pageItem ); PageViewItem* pageItem() const; - void setFormWidgetsController( FormWidgetsController *controller ); + virtual void setFormWidgetsController( FormWidgetsController *controller ); protected: FormWidgetsController * m_controller; @@ -78,6 +96,50 @@ class FormWidgetIface }; +class PushButtonEdit : public QPushButton, public FormWidgetIface +{ + Q_OBJECT + + public: + PushButtonEdit( Okular::FormFieldButton * button, QWidget * parent = 0 ); + + private: + Okular::FormFieldButton * m_form; +}; + +class CheckBoxEdit : public QCheckBox, public FormWidgetIface +{ + Q_OBJECT + + public: + CheckBoxEdit( Okular::FormFieldButton * button, QWidget * parent = 0 ); + + private slots: + void slotStateChanged( int state ); + + private: + Okular::FormFieldButton * m_form; +}; + +class RadioButtonEdit : public QRadioButton, public FormWidgetIface +{ + Q_OBJECT + + public: + RadioButtonEdit( Okular::FormFieldButton * button, QWidget * parent = 0 ); + + // reimplemented from FormWidgetIface + void setFormWidgetsController( FormWidgetsController *controller ); + + Okular::FormFieldButton* buttonForm() const { return m_form; } + + private slots: + void slotToggled( bool checked ); + + private: + Okular::FormFieldButton * m_form; +}; + class FormLineEdit : public QLineEdit, public FormWidgetIface { Q_OBJECT diff --git a/ui/pageview.cpp b/ui/pageview.cpp index 0382fd75f..bbbbbd20a 100644 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -693,6 +693,8 @@ void PageView::notifySetup( const QVector< Okular::Page * > & pageSet, int setup d->visibleItems.clear(); d->pagesWithTextSelection.clear(); toggleFormWidgets( false ); + if ( d->formsWidgetController ) + d->formsWidgetController->dropRadioButtons(); bool haspages = !pageSet.isEmpty(); bool hasformwidgets = false;