Salome HOME
a60751a8160d899af96b7cc1c3d01c093ef96b2a
[modules/gui.git] / src / Qtx / QtxListBox.cxx
1 // File:      QtxListBox.cxx
2 // Author:    Sergey TELKOV
3
4 #include "QtxListBox.h"
5
6 #include <qpixmap.h>
7 #include <qlineedit.h>
8
9 QtxListBox::QtxListBox( QWidget* parent, const char* name, WFlags f )
10 : QListBox( parent, name, f ),
11 myEditor( 0 ),
12 myEditIndex( -1 ),
13 myEditState( false ),
14 myEditDefault( true ),
15 myModifEnabled( true )
16 {
17   connect( this, SIGNAL( contentsMoving( int, int ) ),
18            this, SLOT( onContentsMoving( int, int ) ) );
19 }
20
21 QtxListBox::~QtxListBox()
22 {
23 }
24
25 bool QtxListBox::isEditEnabled() const
26 {
27   return myEditState;
28 }
29
30 void QtxListBox::setEditEnabled( bool on )
31 {
32   if ( isEditEnabled() == on )
33     return;
34
35   myEditState = on;
36
37   if ( !isEditEnabled() )
38     endEdition( defaultEditAction() );
39 }
40
41 bool QtxListBox::defaultEditAction() const
42 {
43   return myEditDefault;
44 }
45
46 void QtxListBox::setDefaultEditAction( bool def )
47 {
48   myEditDefault = def;
49 }
50
51 bool QtxListBox::isModificationEnabled() const
52 {
53   return myModifEnabled;
54 }
55
56 void QtxListBox::setModificationEnabled( bool on )
57 {
58   myModifEnabled = on;
59 }
60
61 QListBoxItem* QtxListBox::editedItem() const
62 {
63   return item( editedIndex() );
64 }
65
66 int QtxListBox::editedIndex() const
67 {
68   return myEditIndex;
69 }
70
71 void QtxListBox::startEdition( const int idx )
72 {
73   if ( idx < 0 || editedIndex() == idx || !isEditEnabled() )
74     return;
75
76   QLineEdit* ed = editor();
77   if ( !ed )
78     return;
79
80   endEdition( defaultEditAction() );
81
82   myEditIndex = idx;
83
84   ensureItemVisible( myEditIndex );
85
86   ed->setText( text( myEditIndex ) );
87   updateEditor();
88   ed->show();
89
90   ed->setFocus();
91 }
92
93 void QtxListBox::startEdition( const QListBoxItem* item )
94 {
95   startEdition( index( item ) );
96 }
97
98 void QtxListBox::endEdition( const bool action )
99 {
100   int idx = editedIndex();
101   QLineEdit* ed = editor();
102
103   if ( idx < 0 || !ed )
104     return;
105
106   myEditIndex = -1;
107
108   ed->hide();
109
110   if ( action )
111   {
112     int cur = currentItem();
113
114     if ( pixmap( idx ) )
115       changeItem( *pixmap( idx ), ed->text(), idx );
116     else
117       changeItem( ed->text(), idx );
118
119     setCurrentItem( cur );
120
121     emit itemEdited( idx );
122     emit itemEdited( item( idx ) );
123   }
124 }
125
126 void QtxListBox::ensureItemVisible( const int idx )
127 {
128   if ( idx < 0 )
129     return;
130
131   if ( itemVisible( idx ) )
132     return;
133
134   setTopItem( idx );
135 }
136
137 void QtxListBox::ensureItemVisible( const QListBoxItem* item )
138 {
139   ensureItemVisible( index( item ) );
140 }
141
142 const QValidator* QtxListBox::validator() const
143 {
144   const QValidator* v = 0;
145   if ( editor() )
146     v = editor()->validator();
147   return v;
148 }
149
150 void QtxListBox::clearValidator()
151 {
152   if ( editor() )
153     editor()->clearValidator();
154 }
155
156 void QtxListBox::setValidator( const QValidator* v )
157 {
158   if ( editor() )
159     editor()->setValidator( v );
160 }
161
162 void QtxListBox::moveItemToTop( const int idx )
163 {
164   moveItem( idx, -idx );
165 }
166
167 void QtxListBox::moveItemToBottom( const int idx )
168 {
169   moveItem( idx, count() - idx );
170 }
171
172 void QtxListBox::moveItem( const int idx, const int step )
173 {
174   QListBoxItem* i = item( idx );
175   if ( !i || step == 0 )
176     return;
177
178   QListBoxItem* cur = item( currentItem() );
179
180   takeItem( i );
181   insertItem( i, QMAX( 0, idx + step ) );
182
183   setCurrentItem( index( cur ) );
184
185   int pos = index( i );
186   if ( myEditIndex == idx )
187     myEditIndex = pos;
188
189   updateEditor();
190
191   if ( idx != pos )
192     emit itemMoved( idx, pos );
193 }
194
195 void QtxListBox::createItem( const int i )
196 {
197   if ( !isEditEnabled() )
198     return;
199
200   int idx = i < 0 ? currentItem() : i;
201   idx = idx < 0 ? count() : idx;
202   idx = QMIN( (int)count(), idx );
203
204   insertItem( "", idx );
205   setCurrentItem( idx );
206   startEdition( idx );
207 }
208
209 void QtxListBox::deleteItem( const int i )
210 {
211   if ( !isEditEnabled() )
212     return;
213
214   int idx = i < 0 ? currentItem() : i;
215   if ( idx < 0 )
216     return;
217
218   if ( editedIndex() == idx )
219     endEdition( defaultEditAction() );
220
221   removeItem( idx );
222   updateEditor();
223 }
224
225 void QtxListBox::setContentsPos( int x, int y )
226 {
227   QListBox::setContentsPos( x, y );
228
229   updateEditor();
230 }
231
232 bool QtxListBox::eventFilter( QObject* o, QEvent* e )
233 {
234   if ( editor() == o )
235   {
236     if ( e->type() == QEvent::FocusOut )
237       endEdition( defaultEditAction() );
238
239     if ( e->type() == QEvent::KeyPress )
240     {
241       QKeyEvent* ke = (QKeyEvent*)e;
242       if ( ke->key() == Key_Escape )
243         endEdition( false );
244       else if ( ke->key() == Key_Enter || ke->key() == Key_Return )
245         endEdition( true );
246     }
247   }
248
249   return QListBox::eventFilter( o, e );
250 }
251
252 void QtxListBox::keyPressEvent( QKeyEvent* e )
253 {
254   if ( e->key() == Key_Up && e->state() & ControlButton && isModificationEnabled() )
255     moveItem( currentItem(), -1 );
256   else if ( e->key() == Key_Down && e->state() & ControlButton && isModificationEnabled() )
257     moveItem( currentItem(), 1 );
258   else if ( e->key() == Key_Home && e->state() & ControlButton && isModificationEnabled() )
259     moveItemToTop( currentItem() );
260   else if ( e->key() == Key_End && e->state() & ControlButton && isModificationEnabled() )
261     moveItemToBottom( currentItem() );
262   else if ( e->key() == Key_Insert && e->state() & ControlButton )
263     createItem( currentItem() );
264   else if ( e->key() == Key_Delete && e->state() & ControlButton )
265     deleteItem( currentItem() );
266   else
267     QListBox::keyPressEvent( e );
268 }
269
270 void QtxListBox::viewportResizeEvent( QResizeEvent* e )
271 {
272   QListBox::viewportResizeEvent( e );
273
274   updateEditor();
275 }
276
277 void QtxListBox::mouseDoubleClickEvent( QMouseEvent* e )
278 {
279   if ( isEditEnabled() )
280     startEdition( itemAt( e->pos() ) );
281   else
282     QListBox::mouseDoubleClickEvent( e );
283 }
284
285 void QtxListBox::onContentsMoving( int, int )
286 {
287   updateEditor();
288 }
289
290 QLineEdit* QtxListBox::editor() const
291 {
292   if ( !myEditor )
293   {
294     QtxListBox* that = (QtxListBox*)this;
295     that->createEditor();
296   }
297   return myEditor;
298 }
299
300 void QtxListBox::createEditor()
301 {
302   if ( myEditor )
303     return;
304
305   myEditor = new QLineEdit( viewport() );
306
307   myEditor->setLineWidth( 1 );
308   myEditor->setMidLineWidth( 0 );
309   myEditor->setFrameStyle( QFrame::Box | QFrame::Plain );
310   myEditor->installEventFilter( this );
311
312   myEditor->hide();
313
314   addChild( myEditor );
315 }
316
317 void QtxListBox::updateEditor()
318 {
319   if ( !editedItem() || !editor() )
320     return;
321
322   QRect r = itemRect( editedItem() );
323   if ( !r.isValid() )
324     return;
325
326   int m = editor()->lineWidth();
327   r.addCoords( m, 0, 0, 0 );
328
329   const QPixmap* pix = pixmap( editedIndex() );
330   if ( pix )
331     r.addCoords( pix->width() + 2, 0, 0, 0 );
332
333   editor()->setGeometry( r );
334 }