Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / Qtx / QtxTable.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File:      QtxTable.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxTable.h"
23
24 #ifndef QT_NO_TABLE
25
26 #include <qlineedit.h>
27
28 /*!
29   Constructor
30 */
31 QtxTable::QtxTable( QWidget* parent, const char* name )
32 : QTable( parent, name ),
33 myHeaderEditor( 0 ),
34 myEditedHeader( 0 ),
35 myEditedSection( -1 )
36 {
37   connect( verticalHeader(), SIGNAL( sizeChange( int, int, int ) ),
38            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
39   connect( horizontalHeader(), SIGNAL( sizeChange( int, int, int ) ),
40            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
41   connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
42   connect( horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
43 }
44
45 /*!
46   Constructor
47 */
48 QtxTable::QtxTable( int numRows, int numCols, QWidget* parent, const char* name )
49 : QTable( numRows, numCols, parent, name ),
50 myHeaderEditor( 0 ),
51 myEditedHeader( 0 ),
52 myEditedSection( -1 )
53 {
54   connect( verticalHeader(), SIGNAL( sizeChange( int, int, int ) ),
55            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
56   connect( horizontalHeader(), SIGNAL( sizeChange( int, int, int ) ),
57            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
58   connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
59   connect( horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
60 }
61
62 /*!
63   Destructor
64 */
65 QtxTable::~QtxTable()
66 {
67 }
68
69 /*!
70   \return true if header is editable
71   \param o - header orientation
72 */
73 bool QtxTable::headerEditable( Orientation o ) const
74 {
75   return myHeaderEditable.contains( o ) ? myHeaderEditable[o] : false;
76 }
77
78 /*!
79   Changes editable state of header
80   \param o - header orientation
81   \param on - new state
82 */
83 void QtxTable::setHeaderEditable( Orientation o, const bool on )
84 {
85   if ( headerEditable( o ) == on )
86     return;
87
88   myHeaderEditable.insert( o, on );
89
90   QHeader* hdr = header( o );
91
92   if ( !on && myEditedHeader == hdr )
93     endHeaderEdit( false );
94
95   if ( on )
96     hdr->installEventFilter( this );
97   else
98     hdr->removeEventFilter( this );
99 }
100
101 /*!
102   Starts edition of header
103   \param o - header orientation
104   \param sec - column/row
105 */
106 bool QtxTable::editHeader( Orientation o, const int sec )
107 {
108   return beginHeaderEdit( o, sec );
109 }
110
111 /*!
112   Finishes edition of header
113   \param accept - whether new value must be accepted
114 */
115 void QtxTable::endEditHeader( const bool accept )
116 {
117   endHeaderEdit( accept );
118 }
119
120 /*!
121   Finishes edition and hides table
122 */
123 void QtxTable::hide()
124 {
125   endHeaderEdit();
126
127   QTable::hide();
128 }
129
130 /*!
131   Custom event filter
132   Starts edition of header by double click
133   Finishes edition by escape/return/enter pressing
134 */
135 bool QtxTable::eventFilter( QObject* o, QEvent* e )
136 {
137   if ( e->type() == QEvent::MouseButtonDblClick )
138   {
139     QMouseEvent* me = (QMouseEvent*)e;
140     if ( o == horizontalHeader() )
141     {
142       beginHeaderEdit( Horizontal, me->pos() );
143       return true;
144     }
145     else if ( o == verticalHeader() )
146     {
147       beginHeaderEdit( Vertical, me->pos() );
148       return true;
149     }
150   }
151
152   if ( o == myHeaderEditor && e->type() == QEvent::KeyPress && isHeaderEditing() )
153   {
154           QKeyEvent* ke = (QKeyEvent*)e;
155     if ( ke->key() == Key_Escape )
156     {
157       endHeaderEdit( false );
158       return true;
159     }
160
161     if ( ke->key() == Key_Return || ke->key() == Key_Enter )
162     {
163       endHeaderEdit( true );
164       return true;
165     }
166
167     return false;
168   }
169
170   if ( o == myHeaderEditor && e->type() == QEvent::FocusOut &&
171        isHeaderEditing() && ((QFocusEvent*)e)->reason() != QFocusEvent::Popup )
172   {
173                 endHeaderEdit();
174                 return true;
175   }
176
177   if ( e->type() == QEvent::Wheel && isHeaderEditing() )
178     return true;
179
180   return QTable::eventFilter( o, e );
181 }
182
183 /*!
184   SLOT: called on scroll
185 */
186 void QtxTable::onScrollBarMoved( int )
187 {
188   updateHeaderEditor();
189 }
190
191 /*!
192   SLOT: called on header size changing
193 */
194 void QtxTable::onHeaderSizeChange( int, int, int )
195 {
196   if ( sender() == myEditedHeader )
197     updateHeaderEditor();
198 }
199
200 /*!
201   Custom resize event handler
202 */
203 void QtxTable::resizeEvent( QResizeEvent* e )
204 {
205   QTable::resizeEvent( e );
206
207   updateHeaderEditor();
208 }
209
210 /*!
211   Starts edition of header
212   \param o - header orientation
213   \param sec - column/row
214 */
215 bool QtxTable::beginHeaderEdit( Orientation o, const int section )
216 {
217   if ( !headerEditable( o ) || !header( o ) || !header( o )->isVisibleTo( this ) )
218     return false;
219
220   endHeaderEdit();
221
222   QHeader* hdr = header( o );
223
224   QRect r = headerSectionRect( hdr, section );
225   if ( !r.isValid() )
226     return false;
227
228   if ( o == Horizontal )
229     r.setLeft( QMAX( r.left(), leftMargin() ) );
230   else
231     r.setTop( QMAX( r.top(), topMargin() ) );
232
233   myHeaderEditor = createHeaderEditor( hdr, section );
234   if ( !myHeaderEditor )
235     return false;
236
237   myEditedHeader = hdr;
238   myEditedSection = section;
239
240   myHeaderEditor->reparent( this, QPoint( 0, 0 ), false );
241
242   updateHeaderEditor();
243
244   myHeaderEditor->show();
245
246   myHeaderEditor->setActiveWindow();
247   myHeaderEditor->setFocus();
248
249   myHeaderEditor->installEventFilter( this );
250
251   return true;
252 }
253
254 /*!
255   Finishes edition of header
256   \param accept - whether new value must be accepted
257 */
258 void QtxTable::endHeaderEdit( const bool accept )
259 {
260   if ( !isHeaderEditing() )
261     return;
262
263   QString oldTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null;
264
265   if ( accept && myEditedHeader )
266     setHeaderContentFromEditor( myEditedHeader, myEditedSection, myHeaderEditor );
267
268   QString newTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null;
269
270   int sec = myEditedSection;
271   QHeader* hdr = myEditedHeader;
272
273   myEditedHeader = 0;
274   myEditedSection = -1;
275
276   myHeaderEditor->hide();
277   myHeaderEditor->deleteLater();
278   myHeaderEditor = 0;
279
280   if ( oldTxt != newTxt )
281   {
282     emit headerEdited( hdr, sec );
283     emit headerEdited( hdr == horizontalHeader() ? Horizontal : Vertical, sec );
284   }
285 }
286
287 /*!
288   \return true if header is being edited
289 */
290 bool QtxTable::isHeaderEditing() const
291 {
292   return myHeaderEditor && myEditedHeader && myEditedSection != -1;
293 }
294
295 /*!
296   Creates and \return header editor
297   \param hdr - header
298   \param sec - column/row
299   \param init - init editor with value
300 */
301 QWidget* QtxTable::createHeaderEditor( QHeader* hdr, const int sec, const bool init )
302 {
303   QLineEdit* ed = new QLineEdit( 0 );
304
305   if ( init && hdr )
306     ed->setText( hdr->label( sec ) );
307
308   return ed;
309 }
310
311 /*!
312   Initialize editor with value
313   \param hdr - header
314   \param sec - column/row
315   \param editor - editor
316 */
317 void QtxTable::setHeaderContentFromEditor( QHeader* hdr, const int sec, QWidget* editor )
318 {
319   if ( !hdr || !editor )
320     return;
321
322   if ( editor->inherits( "QLineEdit" ) )
323     hdr->setLabel( sec, ((QLineEdit*)editor)->text() );
324 }
325
326 /*!
327   \return header
328   \param o - orientation
329 */
330 QHeader* QtxTable::header( Orientation o ) const
331 {
332   return o == Horizontal ? horizontalHeader() : verticalHeader();
333 }
334
335 /*!
336   Starts edition of header
337   \param o - header orientation
338   \param p - point
339 */
340 void QtxTable::beginHeaderEdit( Orientation o, const QPoint& p )
341 {
342   QHeader* hdr = header( o );
343   if ( !hdr )
344     return;
345
346   int pos = o == Horizontal ? p.x() : p.y();
347   int sec = hdr->sectionAt( hdr->offset() + pos );
348
349   beginHeaderEdit( o, sec );
350 }
351
352 /*!
353   \return rectangle of header section
354   \param hdr - header
355   \param sec - column/row
356 */
357 QRect QtxTable::headerSectionRect( QHeader* hdr, const int sec ) const
358 {
359   QRect r( -1, -1, -1, -1 );
360
361   if ( !hdr )
362     return r;
363
364   r = hdr->sectionRect( sec );
365   if ( r.isValid() )
366     r = QRect( mapFromGlobal( hdr->mapToGlobal( r.topLeft() ) ), r.size() );
367
368   return r;
369 }
370
371 /*!
372   Updates header editor
373 */
374 void QtxTable::updateHeaderEditor()
375 {
376   if ( !myHeaderEditor || !myEditedHeader || myEditedSection < 0 )
377     return;
378
379   QRect r = headerSectionRect( myEditedHeader, myEditedSection );
380   if ( !r.isValid() )
381     return;
382
383   if ( myEditedHeader == horizontalHeader() )
384   {
385     r.setLeft( QMAX( r.left(), leftMargin() ) );
386     r.setRight( QMIN( r.right(), width() - rightMargin() - 2 ) );
387   }
388   else
389   {
390     r.setTop( QMAX( r.top(), topMargin() ) );
391     r.setBottom( QMIN( r.bottom(), height() - bottomMargin() - 2 ) );
392   }
393
394   myHeaderEditor->resize( r.size() );
395   myHeaderEditor->move( r.topLeft() );
396 }
397
398 #endif