From 9286b74ed8e9f2f416165d8c19fb6f8e98c2fcb3 Mon Sep 17 00:00:00 2001 From: vsr Date: Fri, 18 Jul 2008 12:22:24 +0000 Subject: [PATCH] Fix problem with 'cleared' state of the combo box (infinite loop) --- src/Qtx/QtxComboBox.cxx | 187 ++++++++++++++++++++++++++-------------- src/Qtx/QtxComboBox.h | 11 +-- 2 files changed, 129 insertions(+), 69 deletions(-) diff --git a/src/Qtx/QtxComboBox.cxx b/src/Qtx/QtxComboBox.cxx index 817138c96..656579d8b 100755 --- a/src/Qtx/QtxComboBox.cxx +++ b/src/Qtx/QtxComboBox.cxx @@ -21,7 +21,95 @@ #include "QtxComboBox.h" +#include #include +#include +#include + +/*! + \class QtxComboBox::Model + \brief Internal view model, used to process 'cleared' state of the combo box. + \internal +*/ +class QtxComboBox::Model : public QStandardItemModel +{ +public: + Model( QObject* parent = 0 ); + ~Model(); + void setCleared( const bool ); + + QVariant data( const QModelIndex&, int = Qt::DisplayRole ) const; + +private: + bool myCleared; +}; + +/*! + \brief Constructor + \internal + \param parent parent object +*/ +QtxComboBox::Model::Model( QObject* parent ) + : QStandardItemModel( 0, 1, parent ), + myCleared( false ) +{ +} + +/*! + \brief Destructor + \internal +*/ +QtxComboBox::Model::~Model() +{ +} + +/*! + \brief Set 'cleared' state + \param isClear new 'cleared' state + \internal +*/ +void QtxComboBox::Model::setCleared( const bool isClear ) +{ + if ( myCleared == isClear ) + return; + + myCleared = isClear; +} + +/*! + \brief Get model data. + \param index model index + \param role data role + \return data of role \a role for the \a index + \internal +*/ +QVariant QtxComboBox::Model::data( const QModelIndex& index, int role ) const +{ + return myCleared ? QVariant() : QStandardItemModel::data( index, role ); +} + +/*! + \class QtxComboBox::ClearEvent + \brief Custom event, used to process 'cleared' state of the combo box + in the editable mode. + \internal +*/ + +#define CLEAR_EVENT QEvent::Type( QEvent::User + 123 ) + +class QtxComboBox::ClearEvent : public QEvent +{ +public: + ClearEvent(); +}; + +/*! + \brief Constructor + \internal +*/ +QtxComboBox::ClearEvent::ClearEvent() : QEvent( CLEAR_EVENT ) +{ +} /*! \class QtxComboBox @@ -41,8 +129,10 @@ QtxComboBox::QtxComboBox( QWidget* parent ) : QComboBox( parent ), myCleared( false ) { - connect( this, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) ); connect( this, SIGNAL( activated( const QString& ) ), this, SLOT( onActivated( const QString& ) ) ); + connect( this, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onCurrentChanged( int ) ) ); + setModel( new Model( this ) ); } /*! @@ -73,32 +163,11 @@ void QtxComboBox::setCleared( const bool isClear ) return; myCleared = isClear; - - if ( isEditable() ) - { - if ( myCleared ) - lineEdit()->setText( "" ); - else - lineEdit()->setText( itemText( currentIndex() ) ); - } - - update(); -} - -/*! - \brief Set current item. - Does nothing if the item index is out of range. + if ( lineEdit() ) + lineEdit()->setText( myCleared ? QString( "" ) : itemText( currentIndex() ) ); - \param idx item index -*/ -void QtxComboBox::setCurrentIndex( int idx ) -{ - if ( idx < 0 || idx >= count() ) - return; - - myCleared = false; - QComboBox::setCurrentIndex( idx ); + update(); } /*! @@ -135,10 +204,30 @@ void QtxComboBox::setId( const int index, const int id ) */ void QtxComboBox::paintEvent( QPaintEvent* e ) { - if ( !count() || !myCleared || isEditable() ) - QComboBox::paintEvent( e ); - else - paintClear( e ); + Model* m = dynamic_cast( model() ); + m->setCleared( myCleared ); + QComboBox::paintEvent( e ); + m->setCleared( false ); +} + +/*! + \brief Customize child addition/removal event + \param e child event +*/ +void QtxComboBox::childEvent( QChildEvent* e ) +{ + if ( e->added() || e->polished() && qobject_cast( e->child() ) ) + QApplication::postEvent( this, new ClearEvent() ); +} + +/*! + \brief Process custom events + \param e custom event +*/ +void QtxComboBox::customEvent( QEvent* e ) +{ + if ( e->type() == CLEAR_EVENT && lineEdit() && myCleared ) + lineEdit()->setText( "" ); } /*! @@ -148,17 +237,17 @@ void QtxComboBox::paintEvent( QPaintEvent* e ) void QtxComboBox::onActivated( int idx ) { resetClear(); - emit activatedId( id( idx ) ); } /*! - \brief Called when any item is activated by the user. - \param txt activated item text (not used) + \brief Called when current item is chaned (by the user or programmatically). + \param idx item being set current */ -void QtxComboBox::onActivated( const QString& /*txt*/ ) +void QtxComboBox::onCurrentChanged( int idx ) { - resetClear(); + if ( idx != -1 ) + resetClear(); } /*! @@ -173,30 +262,6 @@ void QtxComboBox::resetClear() update(); } -/*! - \brief Draw combobox in the "cleared" state. - \param e paint event -*/ -void QtxComboBox::paintClear( QPaintEvent* e ) -{ - int curIndex = currentIndex(); - QString curText = itemText( curIndex ); - QIcon curIcon = itemIcon( curIndex ); - - bool upd = updatesEnabled(); - setUpdatesEnabled( false ); - - setItemIcon( curIndex, QIcon() ); - setItemText( curIndex, QString() ); - - QComboBox::paintEvent( e ); - - setItemText( curIndex, curText ); - setItemIcon( curIndex, curIcon ); - - setUpdatesEnabled( upd ); -} - /*! \brief Get item ID by the index. \param idx item index @@ -242,9 +307,3 @@ bool QtxComboBox::hasId( const int idx ) const \brief Emitted when the item with identificator \a id is activated. \param id item ID */ - -/*! - \fn void QtxComboBox::highlightedId( int id ) - \brief Emitted when the item with identificator \a id is highlighted. - \param id item ID -*/ diff --git a/src/Qtx/QtxComboBox.h b/src/Qtx/QtxComboBox.h index c821ffaed..f1b4f91ec 100755 --- a/src/Qtx/QtxComboBox.h +++ b/src/Qtx/QtxComboBox.h @@ -35,6 +35,9 @@ class QTX_EXPORT QtxComboBox : public QComboBox { Q_OBJECT + class Model; + class ClearEvent; + public: QtxComboBox( QWidget* = 0 ); virtual ~QtxComboBox(); @@ -42,8 +45,6 @@ public: bool isCleared() const; void setCleared( const bool ); - virtual void setCurrentIndex( int ); - int currentId() const; void setCurrentId( int ); @@ -55,18 +56,18 @@ public: signals: void activatedId( int ); - void highlightedId( int ); private slots: void onActivated( int ); - void onActivated( const QString& ); + void onCurrentChanged( int ); protected: virtual void paintEvent( QPaintEvent* ); + virtual void childEvent( QChildEvent* ); + virtual void customEvent( QEvent* ); private: void resetClear(); - void paintClear( QPaintEvent* ); private: enum { IdRole = Qt::UserRole + 10 }; -- 2.39.2