Salome HOME
Fix for bug 10438: Crash during Explode on Blocks operation (Global selection on...
[modules/gui.git] / src / Qtx / QtxTable.cxx
1 // File:      QtxTable.cxx
2 // Author:    Sergey TELKOV
3
4 #include "QtxTable.h"
5
6 #ifndef QT_NO_TABLE
7
8 #include <qlineedit.h>
9
10 QtxTable::QtxTable( QWidget* parent, const char* name )
11 : QTable( parent, name ),
12 myHeaderEditor( 0 ),
13 myEditedHeader( 0 ),
14 myEditedSection( -1 )
15 {
16   connect( verticalHeader(), SIGNAL( sizeChange( int, int, int ) ),
17            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
18   connect( horizontalHeader(), SIGNAL( sizeChange( int, int, int ) ),
19            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
20   connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
21   connect( horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
22 }
23
24 QtxTable::QtxTable( int numRows, int numCols, QWidget* parent, const char* name )
25 : QTable( numRows, numCols, parent, name ),
26 myHeaderEditor( 0 ),
27 myEditedHeader( 0 ),
28 myEditedSection( -1 )
29 {
30   connect( verticalHeader(), SIGNAL( sizeChange( int, int, int ) ),
31            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
32   connect( horizontalHeader(), SIGNAL( sizeChange( int, int, int ) ),
33            this, SLOT( onHeaderSizeChange( int, int, int ) ) );
34   connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
35   connect( horizontalScrollBar(), SIGNAL( valueChanged( int ) ), this, SLOT( onScrollBarMoved( int ) ) );
36 }
37
38 QtxTable::~QtxTable()
39 {
40 }
41
42 bool QtxTable::headerEditable( Orientation o ) const
43 {
44   return myHeaderEditable.contains( o ) ? myHeaderEditable[o] : false;
45 }
46
47 void QtxTable::setHeaderEditable( Orientation o, const bool on )
48 {
49   if ( headerEditable( o ) == on )
50     return;
51
52   myHeaderEditable.insert( o, on );
53
54   QHeader* hdr = header( o );
55
56   if ( !on && myEditedHeader == hdr )
57     endHeaderEdit( false );
58
59   if ( on )
60     hdr->installEventFilter( this );
61   else
62     hdr->removeEventFilter( this );
63 }
64
65 bool QtxTable::editHeader( Orientation o, const int sec )
66 {
67   return beginHeaderEdit( o, sec );
68 }
69
70 void QtxTable::endEditHeader( const bool accept )
71 {
72   endHeaderEdit( accept );
73 }
74
75 void QtxTable::hide()
76 {
77   endHeaderEdit();
78
79   QTable::hide();
80 }
81
82 bool QtxTable::eventFilter( QObject* o, QEvent* e )
83 {
84   if ( e->type() == QEvent::MouseButtonDblClick )
85   {
86     QMouseEvent* me = (QMouseEvent*)e;
87     if ( o == horizontalHeader() )
88     {
89       beginHeaderEdit( Horizontal, me->pos() );
90       return true;
91     }
92     else if ( o == verticalHeader() )
93     {
94       beginHeaderEdit( Vertical, me->pos() );
95       return true;
96     }
97   }
98
99   if ( o == myHeaderEditor && e->type() == QEvent::KeyPress && isHeaderEditing() )
100   {
101           QKeyEvent* ke = (QKeyEvent*)e;
102     if ( ke->key() == Key_Escape )
103     {
104       endHeaderEdit( false );
105       return true;
106     }
107
108     if ( ke->key() == Key_Return || ke->key() == Key_Enter )
109     {
110       endHeaderEdit( true );
111       return true;
112     }
113
114     return false;
115   }
116
117   if ( o == myHeaderEditor && e->type() == QEvent::FocusOut &&
118        isHeaderEditing() && ((QFocusEvent*)e)->reason() != QFocusEvent::Popup )
119   {
120                 endHeaderEdit();
121                 return true;
122   }
123
124   if ( e->type() == QEvent::Wheel && isHeaderEditing() )
125     return true;
126
127   return QTable::eventFilter( o, e );
128 }
129
130 void QtxTable::onScrollBarMoved( int )
131 {
132   updateHeaderEditor();
133 }
134
135 void QtxTable::onHeaderSizeChange( int, int, int )
136 {
137   if ( sender() == myEditedHeader )
138     updateHeaderEditor();
139 }
140
141 void QtxTable::resizeEvent( QResizeEvent* e )
142 {
143   QTable::resizeEvent( e );
144
145   updateHeaderEditor();
146 }
147
148 bool QtxTable::beginHeaderEdit( Orientation o, const int section )
149 {
150   if ( !headerEditable( o ) || !header( o ) || !header( o )->isVisibleTo( this ) )
151     return false;
152
153   endHeaderEdit();
154
155   QHeader* hdr = header( o );
156
157   QRect r = headerSectionRect( hdr, section );
158   if ( !r.isValid() )
159     return false;
160
161   if ( o == Horizontal )
162     r.setLeft( QMAX( r.left(), leftMargin() ) );
163   else
164     r.setTop( QMAX( r.top(), topMargin() ) );
165
166   myHeaderEditor = createHeaderEditor( hdr, section );
167   if ( !myHeaderEditor )
168     return false;
169
170   myEditedHeader = hdr;
171   myEditedSection = section;
172
173   myHeaderEditor->reparent( this, QPoint( 0, 0 ), false );
174
175   updateHeaderEditor();
176
177   myHeaderEditor->show();
178
179   myHeaderEditor->setActiveWindow();
180   myHeaderEditor->setFocus();
181
182   myHeaderEditor->installEventFilter( this );
183
184   return true;
185 }
186
187 void QtxTable::endHeaderEdit( const bool accept )
188 {
189   if ( !isHeaderEditing() )
190     return;
191
192   QString oldTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null;
193
194   if ( accept && myEditedHeader )
195     setHeaderContentFromEditor( myEditedHeader, myEditedSection, myHeaderEditor );
196
197   QString newTxt = myEditedHeader ? myEditedHeader->label( myEditedSection ) : QString::null;
198
199   int sec = myEditedSection;
200   QHeader* hdr = myEditedHeader;
201
202   myEditedHeader = 0;
203   myEditedSection = -1;
204
205   myHeaderEditor->hide();
206   myHeaderEditor->deleteLater();
207   myHeaderEditor = 0;
208
209   if ( oldTxt != newTxt )
210   {
211     emit headerEdited( hdr, sec );
212     emit headerEdited( hdr == horizontalHeader() ? Horizontal : Vertical, sec );
213   }
214 }
215
216 bool QtxTable::isHeaderEditing() const
217 {
218   return myHeaderEditor && myEditedHeader && myEditedSection != -1;
219 }
220
221 QWidget* QtxTable::createHeaderEditor( QHeader* hdr, const int sec, const bool init )
222 {
223   QLineEdit* ed = new QLineEdit( 0 );
224
225   if ( init && hdr )
226     ed->setText( hdr->label( sec ) );
227
228   return ed;
229 }
230
231 void QtxTable::setHeaderContentFromEditor( QHeader* hdr, const int sec, QWidget* editor )
232 {
233   if ( !hdr || !editor )
234     return;
235
236   if ( editor->inherits( "QLineEdit" ) )
237     hdr->setLabel( sec, ((QLineEdit*)editor)->text() );
238 }
239
240 QHeader* QtxTable::header( Orientation o ) const
241 {
242   return o == Horizontal ? horizontalHeader() : verticalHeader();
243 }
244
245 void QtxTable::beginHeaderEdit( Orientation o, const QPoint& p )
246 {
247   QHeader* hdr = header( o );
248   if ( !hdr )
249     return;
250
251   int pos = o == Horizontal ? p.x() : p.y();
252   int sec = hdr->sectionAt( hdr->offset() + pos );
253
254   beginHeaderEdit( o, sec );
255 }
256
257 QRect QtxTable::headerSectionRect( QHeader* hdr, const int sec ) const
258 {
259   QRect r( -1, -1, -1, -1 );
260
261   if ( !hdr )
262     return r;
263
264   r = hdr->sectionRect( sec );
265   if ( r.isValid() )
266     r = QRect( mapFromGlobal( hdr->mapToGlobal( r.topLeft() ) ), r.size() );
267
268   return r;
269 }
270
271 void QtxTable::updateHeaderEditor()
272 {
273   if ( !myHeaderEditor || !myEditedHeader || myEditedSection < 0 )
274     return;
275
276   QRect r = headerSectionRect( myEditedHeader, myEditedSection );
277   if ( !r.isValid() )
278     return;
279
280   if ( myEditedHeader == horizontalHeader() )
281   {
282     r.setLeft( QMAX( r.left(), leftMargin() ) );
283     r.setRight( QMIN( r.right(), width() - rightMargin() - 2 ) );
284   }
285   else
286   {
287     r.setTop( QMAX( r.top(), topMargin() ) );
288     r.setBottom( QMIN( r.bottom(), height() - bottomMargin() - 2 ) );
289   }
290
291   myHeaderEditor->resize( r.size() );
292   myHeaderEditor->move( r.topLeft() );
293 }
294
295 #endif