Salome HOME
Copyright update 2022
[modules/gui.git] / src / Qtx / QtxComboBox.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File:      QtxComboBox.cxx
23 // Author:    Sergey TELKOV
24
25 #include "QtxComboBox.h"
26
27 #include <QStandardItemModel>
28 #include <QLineEdit>
29 #include <QEvent>
30 #include <QApplication>
31
32 /*!
33   \class QtxComboBox::Model
34   \brief Internal view model, used to process 'cleared' state of the combo box.
35   \internal
36 */
37 class QtxComboBox::Model : public QStandardItemModel
38 {
39 public:
40   Model( QObject* parent = 0 );
41   ~Model();
42   void setCleared( const bool );
43
44   QVariant data( const QModelIndex&, int = Qt::DisplayRole ) const;
45
46 private:
47   bool   myCleared;
48 };
49
50 /*!
51   \brief Constructor.
52   \internal
53   \param parent parent object
54 */
55 QtxComboBox::Model::Model( QObject* parent )
56   : QStandardItemModel( 0, 1, parent ),
57     myCleared( false )
58 {
59 }
60
61 /*!
62   \brief Destructor.
63   \internal
64 */
65 QtxComboBox::Model::~Model()
66 {
67 }
68
69 /*!
70   \brief Set 'cleared' state.
71   \param isClear new 'cleared' state
72   \internal
73 */
74 void QtxComboBox::Model::setCleared( const bool isClear )
75 {
76   if ( myCleared == isClear )
77     return;
78   
79   myCleared = isClear;
80 }
81
82 /*!
83   \brief Get model data.
84   \param index model index
85   \param role data role
86   \return data of \a role for given \a index
87   \internal
88 */
89 QVariant QtxComboBox::Model::data( const QModelIndex& index, int role ) const
90 {
91   return ( myCleared && ( role == Qt::DisplayRole || role == Qt::DecorationRole ) ) ?
92     QVariant() : QStandardItemModel::data( index, role );
93 }
94
95 /*!
96   \class QtxComboBox::ClearEvent
97   \brief Custom event, used to process 'cleared' state of the combo box
98   in editable mode.
99   \internal
100 */
101
102 #define CLEAR_EVENT QEvent::Type( QEvent::User + 123 )
103
104 class QtxComboBox::ClearEvent : public QEvent
105 {
106 public:
107   ClearEvent();
108 };
109
110 /*!
111   \brief Constructor.
112   \internal
113 */
114 QtxComboBox::ClearEvent::ClearEvent() : QEvent( CLEAR_EVENT )
115 {
116 }
117
118 /*!
119   \class QtxComboBox
120   \brief Enhanced version of Qt combo box class.
121
122   In addition to the QComboBox class, QtxComboBox supports 
123   adding/removing the items with the associated unique identifiers.
124   It also provides a way to set "cleared" state to the combo box -
125   when no item is selected.
126 */
127
128 /*!
129   \brief Constructor.
130   \param parent parent widget
131 */
132 QtxComboBox::QtxComboBox( QWidget* parent )
133 : QComboBox( parent ),
134   myCleared( false )
135 {
136   connect( this, SIGNAL( currentIndexChanged( int ) ),  this, SLOT( onCurrentChanged( int ) ) );
137   setModel( new Model( this ) );
138 }
139
140 /*!
141   \brief Destructor.
142 */
143 QtxComboBox::~QtxComboBox()
144 {
145 }
146
147 /*!
148   \brief Check if combo box is in "cleared" state.
149   \return \c true if combo box is in "cleared" state or \c false otherwise
150 */
151 bool QtxComboBox::isCleared() const
152 {
153   return myCleared;
154 }
155
156 /*!
157   \brief Set "cleared" state.
158   \param isClear new "cleared" state
159 */
160 void QtxComboBox::setCleared( const bool isClear )
161 {
162   if ( myCleared == isClear )
163     return;
164     
165   myCleared = isClear;
166
167   if ( lineEdit() )
168     lineEdit()->setText( myCleared ? QString( "" ) : itemText( currentIndex() ) );
169
170   update();
171 }
172
173 /*!
174   \brief Get current item's identifier.
175   \return current item's identifier
176 */
177 QVariant QtxComboBox::currentId() const
178 {
179   return id( currentIndex() );
180 }
181
182 /*!
183   \brief Set current item by identifier.
184   \param ident item's identifier
185 */
186 void QtxComboBox::setCurrentId( const QVariant& ident )
187 {
188   setCurrentIndex( index( ident ) );
189 }
190
191 /*!
192   \brief Assign identifier to specified item.
193   \param idx item's index
194   \param ident item's identifier
195 */
196 void QtxComboBox::setId( const int idx, const QVariant& ident )
197 {
198   setItemData( idx, ident, (Qt::ItemDataRole)IdRole );
199 }
200
201 /*!
202   \brief Customize paint event.
203   \param e paint event
204 */
205 void QtxComboBox::paintEvent( QPaintEvent* e )
206 {
207   Model* m = dynamic_cast<Model*>( model() );
208   if ( m )
209     m->setCleared( myCleared );
210   QComboBox::paintEvent( e );
211   if ( m )
212     m->setCleared( false );
213 }
214
215 /*!
216   \brief Customize child addition/removal event.
217   \param e child event
218 */
219 void QtxComboBox::childEvent( QChildEvent* e )
220 {
221   if ( ( e->added() || e->polished() ) && qobject_cast<QLineEdit*>( e->child() ) )
222     QApplication::postEvent( this, new ClearEvent() );
223 }
224
225 /*!
226   \brief Process custom events
227   \param e custom event
228 */
229 void QtxComboBox::customEvent( QEvent* e )
230 {
231   if ( e->type() == CLEAR_EVENT && lineEdit() && myCleared )
232     lineEdit()->setText( "" );
233 }
234
235 /*!
236   \brief Called when current item is changed (by user or programmatically).
237   \param idx index of item being set current
238 */
239 void QtxComboBox::onCurrentChanged( int idx )
240 {
241   if ( idx != -1 )
242   {
243     resetClear();
244     QVariant ident = id( idx );
245     emit activatedId( id( idx ) );
246     if ( ident.type() == QVariant::Int )
247       emit activatedId( ident.toInt() );
248     else if ( ident.type() == QVariant::String )
249       emit activatedId( ident.toString() );
250   }
251 }
252
253 /*!
254   \brief Reset "cleared" state and update combo box.
255 */
256 void QtxComboBox::resetClear()
257 {
258   if ( !myCleared )
259     return;
260   
261   myCleared = false;
262   update();
263 }
264
265 /*!
266   \brief Get item's identifier by index.
267   \param idx item's index
268   \return item's identifier or invalid QVariant if index is out of range
269   or identifier is not assigned to item
270 */
271 QVariant QtxComboBox::id( const int idx ) const
272 {
273   return itemData( idx, (Qt::ItemDataRole)IdRole );
274 }
275
276 /*!
277   \brief Get item index by identifier.
278   \param ident item's identifier
279   \return item's index or -1 if \a ident is invalid of if item is not found
280 */
281 int QtxComboBox::index( const QVariant& ident ) const
282 {
283   if ( !ident.isValid() ) return -1;
284   return findData( ident, (Qt::ItemDataRole)IdRole );
285 }
286
287 /*!
288   \brief Check if item has assigned identifier.
289   \param idx item's index
290   \return \c true if item with given index has identifier of \c false otherwise
291 */
292 bool QtxComboBox::hasId( const int idx ) const
293 {
294   QVariant v = itemData( idx, (Qt::ItemDataRole)IdRole );
295   return !v.isNull();
296 }
297
298 /*!
299   \fn void QtxComboBox::activatedId( QVariant ident )
300   \brief Emitted when item with identificator \a ident is activated.
301   \param ident item's identifier
302 */
303
304 /*!
305   \fn void QtxComboBox::activatedId( int ident )
306   \brief Emitted when item with integer identificator \a ident is activated.
307   \param ident item's identifier
308 */
309
310 /*!
311   \fn void QtxComboBox::activatedId( QString ident )
312   \brief Emitted when item with string identificator \a ident is activated.
313   \param ident item's identifier
314 */