]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxDialog.cxx
Salome HOME
Bug fix for SSPP10924
[modules/gui.git] / src / Qtx / QtxDialog.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/
18 //
19 // File:      QtxDialog.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxDialog.h"
23
24 #include "QtxGroupBox.h"
25
26 #include <qlabel.h>
27 #include <qframe.h>
28 #include <qlayout.h>
29 #include <qpushbutton.h>
30 #include <qapplication.h>
31
32 /*!
33         Class: QtxDialog::Area
34         Level: Internal
35 */
36
37 class QtxDialog::Area : public QFrame
38 {
39 public:
40         Area( Orientation, QtxDialog*, QWidget* = 0 );
41         virtual ~Area();
42
43         bool                     isBorderEnabled() const;
44         void                     setBorderEnabled( const bool );
45
46         void                     setBorderWidget( QLabel* );
47
48         void                     insertButton( QButton* );
49         void                     removeButton( QButton* );
50         bool                     contains( QButton* ) const;
51
52         int                      policy() const;
53         void                     setPolicy( const int );
54
55         void                     layoutButtons();
56
57         const QPtrList<QButton>& buttons() const;
58
59 private:
60         void                     updateBorder();
61
62 private:
63         QtxDialog*               myDlg;
64         QLabel*                  myLine;
65         bool                     myBorder;
66         int                      myPolicy;
67         QPtrList<QButton>        myButtons;
68         Orientation              myOrientation;
69 };
70
71 QtxDialog::Area::Area( Orientation o, QtxDialog* dlg, QWidget* parent )
72 : QFrame( parent ),
73 myDlg( dlg ),
74 myLine( 0 ),
75 myBorder( false ),
76 myPolicy( Position ),
77 myOrientation( o )
78 {
79         if ( myOrientation == Qt::Horizontal )
80                 setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum ) );
81         else
82                 setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ) );
83
84         hide();
85 }
86
87 QtxDialog::Area::~Area()
88 {
89 }
90
91 void QtxDialog::Area::insertButton( QButton* b )
92 {
93         if ( !b || myButtons.findRef( b ) != -1 )
94                 return;
95
96         QWidget* parent = b->parentWidget();
97         if ( parent != this )
98                 b->reparent( this, 0, QPoint( 0, 0 ), b->isVisibleTo( parent ) );
99
100         myButtons.append( b );
101
102         if ( myDlg )
103                 myDlg->adjustButtons();
104         layoutButtons();
105
106         show();
107
108         updateBorder();
109 }
110
111 void QtxDialog::Area::removeButton( QButton* b )
112 {
113         if ( !b )
114                 return;
115
116         myButtons.removeRef( b );
117
118         if ( myButtons.isEmpty() )
119                 hide();
120
121         updateBorder();
122
123         if ( myDlg )
124                 myDlg->adjustButtons();
125
126         layoutButtons();
127 }
128
129 bool QtxDialog::Area::contains( QButton* b ) const
130 {
131         return myButtons.containsRef( b );
132 }
133
134 int QtxDialog::Area::policy() const
135 {
136         return myPolicy;
137 }
138
139 void QtxDialog::Area::setPolicy( const int p )
140 {
141         if ( myPolicy == p )
142                 return;
143
144         myPolicy = p;
145         layoutButtons();
146 }
147
148 bool QtxDialog::Area::isBorderEnabled() const
149 {
150         return myLine && myBorder;
151 }
152
153 void QtxDialog::Area::setBorderEnabled( const bool on )
154 {
155         if ( !myLine || myBorder == on )
156                 return;
157
158         myBorder = on;
159         updateBorder();
160 }
161
162 void QtxDialog::Area::setBorderWidget( QLabel* line )
163 {
164         if ( myLine == line )
165                 return;
166
167         delete myLine;
168         myLine = line;
169         updateBorder();
170 }
171
172 const QPtrList<QButton>& QtxDialog::Area::buttons() const
173 {
174         return myButtons;
175 }
176
177 void QtxDialog::Area::updateBorder()
178 {
179         if ( !myLine )
180                 return;
181
182         bool isVis = isVisibleTo( parentWidget() );
183 #if QT_VER >= 3    
184         if ( isVis )
185 #else
186         if ( isVis && myBorder )
187 #endif
188                 myLine->show();
189         else
190                 myLine->hide();
191
192         myLine->setLineWidth( myBorder ? 1 : 0 );
193 }
194
195 void QtxDialog::Area::layoutButtons()
196 {
197         int aPolicy = policy();
198
199         QMap<QButton*, int> buttonId;
200         for ( QPtrListIterator<QButton> it1( myButtons ); it1.current(); ++it1 )
201                 buttonId.insert( it1.current(), 0 );
202
203         QPtrList<QButton> src;
204         for ( ButtonMap::Iterator mit = myDlg->myButton.begin();
205                   mit != myDlg->myButton.end(); ++mit )
206         {
207                 if ( buttonId.contains( mit.data() ) )
208                 {
209                         buttonId[mit.data()] = mit.key();
210                         if ( mit.key() >= 0 )
211                                 src.append( mit.data() );
212                 }
213         }
214
215         for ( QPtrListIterator<QButton> it2( myButtons ); it2.current(); ++it2 )
216                 if ( buttonId[it2.current()] < 0 )
217                         src.append( it2.current() );
218
219         QPtrList<QButton> left, right, center, other;
220         for ( QPtrListIterator<QButton> it( src ); it.current(); ++it )
221         {
222                 if ( !it.current()->isVisibleTo( this ) )
223                         continue;
224
225                 int aPosition = myDlg->buttonPosition( it.current() );
226                 if ( aPosition == -1 )
227                         continue;
228
229                 if ( aPolicy != QtxDialog::Position )
230                         other.append( it.current() );
231                 else if ( aPosition == QtxDialog::Left )
232                         left.append( it.current() );
233                 else if ( aPosition == QtxDialog::Right )
234                         right.append( it.current() );
235                 else if ( aPosition == QtxDialog::Center )
236                         center.append( it.current() );
237         }
238
239     delete layout();
240
241         QBoxLayout* buttonLayout = 0;
242         if ( myOrientation == Qt::Vertical )
243                 buttonLayout = new QVBoxLayout( this, 0, 5 );
244         else
245                 buttonLayout = new QHBoxLayout( this, 0, 5 );
246
247         if ( !buttonLayout )
248                 return;
249
250         if ( aPolicy == QtxDialog::Position )
251         {
252                 for ( QPtrListIterator<QButton> lit( left ); lit.current(); ++lit )
253                         buttonLayout->addWidget( lit.current() );
254                 buttonLayout->addStretch( 1 );
255                 for ( QPtrListIterator<QButton> cit( center ); cit.current(); ++cit )
256                         buttonLayout->addWidget( cit.current() );
257                 buttonLayout->addStretch( 1 );
258                 for ( QPtrListIterator<QButton> rit( right ); rit.current(); ++rit )
259                         buttonLayout->addWidget( rit.current() );
260         }
261         else
262         {
263                 for ( QPtrListIterator<QButton> oit( other ); oit.current(); ++oit )
264                 {
265                         buttonLayout->addWidget( oit.current() );
266                         if ( aPolicy == QtxDialog::Uniform && !oit.atLast() )
267                                 buttonLayout->addStretch( 1 );
268                 }
269         }
270 }
271
272 /*!
273         Class: QtxDialog::Border
274         Level: Internal
275 */
276
277 class QtxDialog::Border : public QLabel
278 {
279 public:
280         Border( QWidget* = 0 );
281         virtual ~Border();
282
283         virtual void setLineWidth( int );
284
285         virtual QSize sizeHint() const;
286         virtual QSize minimumSizeHint() const;
287 };
288
289 QtxDialog::Border::Border( QWidget* parent )
290 : QLabel( parent )
291 {
292     setAlignment( Qt::AlignCenter );
293 }
294
295 QtxDialog::Border::~Border()
296 {
297 }
298
299 void QtxDialog::Border::setLineWidth( int lw )
300 {
301   bool isOn = lineWidth() > 0;
302
303   QLabel::setLineWidth( lw );
304     
305   if ( isOn != ( lineWidth() > 0 ) )
306     updateGeometry();
307 }
308
309 QSize QtxDialog::Border::sizeHint() const
310 {
311   QSize sz( 5, 5 );
312
313 #if QT_VER >= 3    
314   if ( lineWidth() > 0 )
315         {
316     if ( frameShape() == VLine )
317       sz += QSize( 5 + lineWidth(), 0 );
318                 else if ( frameShape() == HLine )
319       sz += QSize( 0, 5 + lineWidth() );
320         }
321 #endif
322
323   return sz;
324 }
325
326 QSize QtxDialog::Border::minimumSizeHint() const
327 {
328         return sizeHint();
329 }
330
331 /*!
332         Class: QtxDialog
333         Level: Public
334 */
335
336 /*!
337         Name: QtxDialog [public]
338         Desc: Construct a dialog with specified parent and name.
339           Parameter 'modal' define modal status of dialog (default non modal
340                   dialog created). If parameter 'allowResize' is true then dialog
341                   can be resize by user (default non resizable dialog created).
342                   Button flags specified control buttons for dialog (default buttons
343                   is OK, Cancel and Help). Widget flags used as in any widget.
344 */
345
346 QtxDialog::QtxDialog( QWidget* parent, const char* name,
347                                           bool modal, bool allowResize, const int f, WFlags wf )
348 : QDialog( parent, name, modal,
349 #ifdef WIN32
350            wf | WStyle_Customize | WStyle_Title | WStyle_SysMenu |
351            ( allowResize ? WStyle_NormalBorder : WStyle_NoBorderEx ) ),
352 #else
353            wf | WStyle_NormalBorder | WStyle_Customize | WStyle_Title | WStyle_SysMenu ),
354 #endif
355 mySender( 0 ),
356 myAlignment( 0 ),
357 myInited( false ),
358 myDialogFlags( Accept | SetFocus )
359 {
360         QVBoxLayout* base = new QVBoxLayout( this, 5, 0 );
361         QtxGroupBox* main = new QtxGroupBox( 1, Qt::Horizontal, "", this );
362         main->setFrameStyle( QFrame::NoFrame );
363         main->setInsideMargin( 0 );
364         main->setInsideSpacing( 0 );
365         base->addWidget( main );
366
367         Area* topArea = new Area( Qt::Horizontal, this, main );
368         QLabel* topLine = new Border( main );
369         QtxGroupBox* midGroup = new QtxGroupBox( 1, Qt::Vertical, "", main );
370         QLabel* botLine = new Border( main );
371         Area* botArea = new Area( Qt::Horizontal, this, main );
372
373         midGroup->setFrameStyle( QFrame::NoFrame );
374         midGroup->setInsideMargin( 0 );
375         midGroup->setInsideSpacing( 0 );
376
377         Area* leftArea = new Area( Qt::Vertical, this, midGroup );
378         QLabel* leftLine = new Border( midGroup );
379         myMainFrame = new QFrame( midGroup );
380         QLabel* rightLine = new Border( midGroup );
381         Area* rightArea = new Area( Qt::Vertical, this, midGroup );
382
383         myMainFrame->setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
384                                                                                                 QSizePolicy::Expanding ) );
385
386         topLine->setFrameStyle( QFrame::Sunken | QFrame::HLine );
387         botLine->setFrameStyle( QFrame::Sunken | QFrame::HLine );
388         leftLine->setFrameStyle( QFrame::Sunken | QFrame::VLine );
389         rightLine->setFrameStyle( QFrame::Sunken | QFrame::VLine );
390         topArea->setBorderWidget( topLine );
391         botArea->setBorderWidget( botLine );
392         leftArea->setBorderWidget( leftLine );
393         rightArea->setBorderWidget( rightLine );
394
395         myArea.insert( TopArea,    topArea );
396         myArea.insert( BottomArea, botArea );
397         myArea.insert( LeftArea,   leftArea );
398         myArea.insert( RightArea,  rightArea );
399
400         for ( AreaMap::Iterator itr = myArea.begin(); itr != myArea.end(); ++ itr )
401                 itr.data()->setBorderEnabled( false );
402
403         myButton.insert( OK,     new QPushButton( tr( "&OK" ),     this ) );
404         myButton.insert( Cancel, new QPushButton( tr( "&Cancel" ), this ) );
405         myButton.insert( Close,  new QPushButton( tr( "C&lose" ),  this ) );
406         myButton.insert( Help,   new QPushButton( tr( "&Help" ),   this ) );
407         myButton.insert( Apply,  new QPushButton( tr( "&Apply" ),  this ) );
408         myButton.insert( Yes,    new QPushButton( tr( "&Yes" ),    this ) );
409         myButton.insert( No,     new QPushButton( tr( "&No" ),     this ) );
410
411         for ( ButtonMap::Iterator it = myButton.begin(); it != myButton.end(); ++it )
412         {
413                 ((QPushButton*)it.data())->setAutoDefault( false );
414 #if QT_VER >= 3
415                 connect( it.data(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
416 #endif
417         }
418
419         setButtonPosition( Left,   OK | Cancel | Apply );
420         setButtonPosition( Center, Yes | No | Close );
421         setButtonPosition( Right,  Help );
422         setButtonPlace( BottomArea, All );
423
424         connect( myButton[Apply],  SIGNAL( clicked() ), this, SIGNAL( dlgApply() ) );
425         connect( myButton[Help],   SIGNAL( clicked() ), this, SIGNAL( dlgHelp() ) );
426
427         connect( myButton[OK],     SIGNAL( clicked() ), this, SLOT( onAccept() ) );
428         connect( myButton[Cancel], SIGNAL( clicked() ), this, SLOT( onReject() ) );
429         connect( myButton[Yes],    SIGNAL( clicked() ), this, SLOT( onAccept() ) );
430         connect( myButton[No],     SIGNAL( clicked() ), this, SLOT( onReject() ) );
431         connect( myButton[Close],  SIGNAL( clicked() ), this, SLOT( onReject() ) );
432
433         QPixmap icon;
434         if ( qApp && qApp->mainWidget() && qApp->mainWidget()->icon() )
435                 setIcon( *qApp->mainWidget()->icon() );
436
437         myButtonFlags = f;
438
439 #ifndef WIN32
440         if ( !allowResize )
441                 setMaximumSize( minimumSize() );
442 #endif
443
444         update();
445 }
446
447 /*!
448         Name: ~QtxDialog [public]
449         Desc: Destructor
450 */
451
452 QtxDialog::~QtxDialog()
453 {
454 }
455
456 /*!
457         Name: setButtonFlags [public]
458         Desc: Allow to set specified control button(s) into dialog.
459 */
460
461 void QtxDialog::setButtonFlags( const int f )
462 {
463         int old = myButtonFlags;
464         myButtonFlags = myButtonFlags | f;
465         if ( old != myButtonFlags )
466                 update();
467 }
468
469 /*!
470         Name: clearButtonFlags [public]
471         Desc: Allow to unset specified control button(s) from dialog.
472 */
473
474 void QtxDialog::clearButtonFlags( const int f )
475 {
476         int old = myButtonFlags;
477         myButtonFlags = myButtonFlags & ~f;
478         if ( old != myButtonFlags )
479                 update();
480 }
481
482 /*!
483         Name: testButtonFlags [public]
484         Desc: Return true if specified control button is used in dialog.
485 */
486
487 bool QtxDialog::testButtonFlags( const int f ) const
488 {
489     return ( myButtonFlags & f ) == f;
490 }
491
492 /*!
493         Name: setDialogFlags [public]
494         Desc: Allow to set the dialog flags.
495
496                   Following flags can be used:
497                         Accept    - Allow to control dialog accepting. See also acceptData().
498                         Reject    - Allow to control dialog rejecting. See also rejectData().
499                         AlignOnce - Allow to align dialog only when it first time shown.
500                         SetFocus  - Allow to set focus on dialog when it shown. User can use
501                   setFocusProxy() and specify own initial focus widget.
502 */
503
504 void QtxDialog::setDialogFlags( const int f )
505 {
506         myDialogFlags = myDialogFlags | f;
507 }
508
509 /*!
510         Name: clearDialogFlags [public]
511         Desc: Allow to clear the dialog flags. See also setDialogFlags().
512 */
513
514 void QtxDialog::clearDialogFlags( const int f )
515 {
516         myDialogFlags = myDialogFlags & ~f;
517 }
518
519 /*!
520         Name: testDialogFlags [public]
521         Desc: Returns true if specified dialog flag is setted (see setDialogFlags()).
522 */
523
524 bool QtxDialog::testDialogFlags( const int f ) const
525 {
526     return ( myDialogFlags & f ) == f;
527 }
528
529 /*!
530         Name: mainFrame [public]
531         Desc: Returns main frame of dialog. Main frame should contains all
532           elements of dialog except control buttons.
533 */
534
535 QFrame* QtxDialog::mainFrame() const
536 {
537     return myMainFrame;
538 }
539
540 /*!
541         Name: buttonPosition [public]
542         Desc: Returns position of specified button.
543 */
544
545 int QtxDialog::buttonPosition( const int id ) const
546 {
547         int pos = -1;
548         if ( myPosition.contains( id ) )
549                 pos = myPosition[id];
550         return pos;
551 }
552
553 /*!
554         Name: setButtonPosition [public]
555         Desc: Sets the position for specified button(s). Following positions
556                   may be used: Left, Right, Center, Top, Bottom.
557 */
558
559 void QtxDialog::setButtonPosition( const int pos, const int id )
560 {
561         ButtonMap map = buttons( id );
562
563         QMap<QObject*, int> changed;
564         for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
565         {
566                 if ( myPosition[it.key()] == pos )
567                         continue;
568       
569                 myPosition[it.key()] = pos;
570                 if ( button( it.key() ) )
571                         changed.insert( button( it.key() )->parent(), 0 );
572     }
573
574         for ( AreaMap::Iterator itr = myArea.begin(); itr != myArea.end(); ++itr )
575                 if ( changed.contains( itr.data() ) )
576                         itr.data()->layoutButtons();
577 }
578
579 /*!
580         Name: setPlacePosition [public]
581         Desc: Sets button position for all buttons in given place.
582 */
583
584 void QtxDialog::setPlacePosition( const int pos, const int area )
585 {
586         if ( !myArea.contains( area ) )
587                 return;
588
589         Area* anArea = myArea[area];
590
591         bool changed = false;
592         for ( ButtonMap::Iterator it = myButton.begin(); it != myButton.end(); ++it )
593         {
594                 if ( !anArea->contains( it.data() ) )
595                         continue;
596
597                 changed = changed &&  myPosition[it.key()] != pos;
598
599                 myPosition[it.key()] = pos;
600     }
601
602         if ( changed )
603                 anArea->layoutButtons();
604 }
605
606 /*!
607         Name: placePolicy [public]
608         Desc: Returns policy of button layouting for specified place.
609
610                   Following place may be used:
611                         TopArea    - Horizontal area in the top side of dialog.
612                         BottomArea - Horizontal area in the bottom side of dialog.
613                         LeftArea   - Vertical area in the left side of dialog.
614                         RightArea  - Vertical area in the right side of dialog.
615
616                   Following policy may be used:
617                     Position - Buttons placed according their position.
618                         Expand   - Buttons fills all available space.
619                         Uniform  - Buttons uniformly placed in area.
620 */
621
622 int QtxDialog::placePolicy( const int area ) const
623 {
624         int res = -1;
625         if ( myArea.contains( area ) )
626                 res = myArea[area]->policy();
627         return res;
628 }
629
630 /*!
631         Name: setPlacePolicy [public]
632         Desc: Sets the policy of button layouting for specified place.
633                   See also placePolicy().
634 */
635
636 void QtxDialog::setPlacePolicy( const int policy, const int area )
637 {
638         if ( area < 0 )
639                 for ( AreaMap::Iterator itr = myArea.begin(); itr != myArea.end(); ++itr )
640                         itr.data()->setPolicy( policy );
641         else if ( myArea.contains( area ) )
642                 myArea[area]->setPolicy( policy );
643 }
644
645 /*!
646         Name: setButtonPlace [public]
647         Desc: Move given button(s) into specified place.
648 */
649
650 void QtxDialog::setButtonPlace( const int area, const int ids )
651 {
652         if ( !myArea.contains( area ) )
653                 return;
654
655         Area* anArea = myArea[area];
656
657         ButtonMap map = buttons( ids );
658
659         QMap<Area*, int> areaMap;
660         for ( AreaMap::ConstIterator aIt = myArea.begin(); aIt != myArea.end(); ++aIt )
661                 areaMap.insert( aIt.data(), 0 );
662
663         for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
664         {
665                 Area* old = (Area*)it.data()->parent();
666                 if ( old == anArea )
667                         continue;
668
669                 if ( areaMap.contains( old ) )
670                         old->removeButton( it.data() );
671                 anArea->insertButton( it.data() );
672     }
673 }
674
675 /*!
676         Name: isBorderEnabled [public]
677         Desc: Returns true if border is shown for specified button area.
678 */
679
680 bool QtxDialog::isBorderEnabled( const int area ) const
681 {
682         bool res = false;
683         if ( myArea.contains( area ) )
684                 res  = myArea[area]->isBorderEnabled();
685         return res;
686 }
687
688 /*!
689         Name: setBorderEnabled [public]
690         Desc: Show/hide border for specified button area. Border are
691               line which separate main frame and control buttons.
692 */
693
694 void QtxDialog::setBorderEnabled( const bool on, const int area )
695 {
696         if ( !myArea.contains( area ) )
697                 return;
698
699         if ( myArea[area]->isBorderEnabled() == on )
700                 return;
701
702         myArea[area]->setBorderEnabled( on );
703
704         if ( isVisible() )
705         {
706                 QApplication::sendPostedEvents();
707                 adjustSize();
708         }
709 }
710
711 /*!
712         Name: isButtonEnabled [public]
713         Desc: Returns true if all specified button(s) is enabled.
714 */
715
716 bool QtxDialog::isButtonEnabled( const int f ) const
717 {
718         ButtonMap map = buttons( f );
719         bool result = !map.isEmpty();
720         for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
721                 result = result && it.data()->isEnabled();
722         return result;
723 }
724
725 /*!
726         Name: setButtonEnabled [public]
727         Desc: Enable/disable specified button(s).
728 */
729
730 void QtxDialog::setButtonEnabled( const bool on, const int ids )
731 {
732         ButtonMap map = buttons( ids );
733         for ( ButtonMap::Iterator it = map.begin(); it != map.end(); ++it )
734                 it.data()->setEnabled( on );
735 }
736
737 /*!
738         Name: hasButtonFocus [public]
739         Desc: Retruns true if specified button has keyboard focus.
740 */
741
742 bool QtxDialog::hasButtonFocus( const int id ) const
743 {
744         bool res = false;
745         QButton* pb = button( id );
746         if ( pb )
747         res = pb->hasFocus();
748         return res;
749 }
750
751 /*!
752         Name: setButtonFocus [public]
753         Desc: Sets the keyboard focus on specified button.
754 */
755
756 void QtxDialog::setButtonFocus( const int id )
757 {
758         QButton* pb = button( id );
759         if ( pb )
760             pb->setFocus();
761 }
762
763 /*!
764         Name: buttonText [public]
765         Desc: Return text of specified button.
766 */
767
768 QString QtxDialog::buttonText( const int id )
769 {
770         QString retval;
771         QButton* but = button( id );
772         if ( but )
773                 retval = but->text();
774         return retval;
775 }
776
777 /*!
778         Name: setButtonText [public]
779         Desc: Sets text to specified button.
780 */
781
782 void QtxDialog::setButtonText( const int id, const QString& text )
783 {
784         QButton* but = button( id );
785         if ( but && but->text() != text )
786         {
787                 but->setText( text );
788                 adjustButtons();
789         }
790 }
791
792 /*!
793         Name: setAlignment [public]
794         Desc: Sets alignment policy. Returns the previous alignment.
795                   Use the function before the first show of the dialog.
796                   If dialog flag AlignOnce is setted then align will performed
797                   only one time otherwise dialog will be aligned every time
798                   when it shown. Dialog will be aligned relative to it parent.
799
800                   Following align flags may be used:
801                         Qtx::AlignAuto      - Align to center of desktop (default).
802                         Qtx::AlignLeft      - Align left side of dialog to left side of parent.
803                         Qtx::AlignRight     - Align right side of dialog to right side of parent.
804                         Qtx::AlignTop       - Align top side of dialog to top side of parent.
805                         Qtx::AlignBottom    - Align bottom side of dialog to bottom side of parent.
806                         Qtx::AlignHCenter   - Align dialog to center of parent in horizontal dimension.
807                         Qtx::AlignVCenter   - Align dialog to center of parent in vertical dimension.
808                         Qtx::AlignCenter    - Align dialog to center of parent in both dimensions.
809                         Qtx::AlignOutLeft   - Align right side of dialog to left side of parent.
810                         Qtx::AlignOutRight  - Align left side of dialog to right side of parent.
811                         Qtx::AlignOutTop    - Align bottom side of dialog to top side of parent.
812                         Qtx::AlignOutBottom - Align top side of dialog to bottom side of parent.
813 */
814
815 uint QtxDialog::setAlignment( uint align )
816 {
817   uint oldAlign = myAlignment;
818   myAlignment = align;
819   return oldAlign;
820 }
821
822 /*!
823         Name: update [virtual public slot]
824         Desc: Updates dialog, show selected buttons and hide unselected.
825 */
826
827 void QtxDialog::update()
828 {
829         for ( ButtonMap::Iterator it = myButton.begin(); it != myButton.end(); ++it )
830                 if ( it.key() >= 0 )
831                         testButtonFlags( it.key() ) ? it.data()->show() : it.data()->hide();
832
833         for ( AreaMap::Iterator itr = myArea.begin(); itr != myArea.end(); ++itr )
834                 itr.data()->layoutButtons();
835
836         adjustButtons();
837
838         QDialog::update();
839 }
840
841 /*!
842         Name: show [virtual public]
843         Desc: Show dialog, set keyboard focus on dialog.
844 */
845
846 void QtxDialog::show()
847 {
848         QDialog::show();
849
850         if ( testDialogFlags( SetFocus ) )
851           setFocus();
852
853         myInited = true;
854 }
855
856 /*!
857         Name: hide [virtual public]
858         Desc: Hides dialog, processed all posted events.
859 */
860
861 void QtxDialog::hide()
862 {
863         QDialog::hide();
864         qApp->processEvents();
865 }
866
867 /*!
868         Name: userButton [public]
869         Desc: Return user dialog button using specified identificator.
870 */
871
872 QButton* QtxDialog::userButton( const int id ) const
873 {
874         QButton* b = 0;
875         if ( id < -1 && myButton.contains( id ) )
876                 b = myButton[id];
877     return b;
878 }
879
880 /*!
881         Name: userButtonIds [public]
882         Desc: Return list of user dialog button identificators.
883 */
884
885 QValueList<int> QtxDialog::userButtonIds() const
886 {
887         QValueList<int> retlist;
888         for ( ButtonMap::ConstIterator it = myButton.begin(); it != myButton.end(); ++it )
889                 if ( it.key() < 0 )
890                         retlist.append( it.key() );
891         return retlist;
892 }
893
894 /*!
895         Name: insertButton [public]
896         Desc: Add new user dialog button. Function return identificator of
897                   newly added button in successfull case otherwise -1 will be returned.
898 */
899
900 int QtxDialog::insertButton( const QString& text, const int area )
901 {
902         if ( !myArea.contains( area ) )
903                 return -1;
904
905         int id = -2;
906         while ( myButton.contains( id ) )
907                 id--;
908
909         Area* anArea = myArea[area];
910         QButton* b = createButton( this );
911         if ( b )
912         {
913                 b->setText( text );
914                 myButton.insert( id, b );
915                 myPosition.insert( id, Left );
916
917                 connect( b, SIGNAL( clicked() ), this, SLOT( onButton() ) );
918 #if QT_VER >= 3
919                 connect( b, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
920 #endif
921
922                 anArea->insertButton( b );
923                 update();
924         }
925         else
926                 id = -1;
927
928         return id;
929 }
930
931 /*!
932         Name: removeButton [public]
933         Desc: Remove user dialog button with specified identificator. If
934                   identificator equal -1 then method will remove all user dialog buttons.
935 */
936
937 void QtxDialog::removeButton( const int id )
938 {
939         if ( id >= 0 )
940                 return;
941
942         ButtonMap map;
943         if ( id == -1 )
944         {
945                 for ( ButtonMap::Iterator it = myButton.begin(); it != myButton.end(); ++it )
946                 {
947                         if ( it.key() < 0 )
948                                 map.insert( it.key(), it.data() );
949                 }
950         }
951         else if ( myButton.contains( id ) )
952                 map.insert( id, myButton[id] );
953
954         for ( ButtonMap::Iterator itr = map.begin(); itr != map.end(); ++itr )
955         {
956                 for ( AreaMap::Iterator it = myArea.begin(); it != myArea.end(); ++it )
957                         it.data()->removeButton( itr.data() );
958
959                 myButton.remove( itr.key() );
960                 myPosition.remove( itr.key() );
961
962                 delete itr.data();
963         }
964     update();
965 }
966
967 /*!
968         Name: setUnits [static public]
969         Desc: Sets specified measure units in given label. Measure units close
970                   in braces. If measure units not exist then they will be added.
971                   For example:
972                         1. Label contains text 'Radius'.
973                            setUnits( aLabel, "mm" )    => aLabel contains 'Radius (mm)'
974                setUnits( aLabel, "cm" )    => aLabel contains 'Radius (cm)'
975             2. Label "aLabel" contains text 'Radius ():'.
976                setUnits( aLabel, "mm" )    => aLabel contains 'Radius (mm):'
977                setUnits( aLabel, "cm" )    => aLabel contains 'Radius (cm):'
978 */
979
980 void QtxDialog::setUnits( QLabel* aLabel, const QString& aUnits )
981 {
982         QString label = aLabel->text();
983         int begin;
984         int end = label.findRev( ')' );
985
986         QString startLabel = label;
987         QString finalLabel;
988
989         if ( end != -1 )
990         {
991                 begin = label.left( end ).findRev( '(' );
992                 if ( begin != -1 )
993                 {
994                         startLabel = label.mid( 0, begin );
995                         finalLabel = label.mid( end + 1 );
996                 }
997         }
998         else
999         {
1000                 startLabel = startLabel.stripWhiteSpace();
1001                 if ( startLabel.at( startLabel.length() - 1 ) == ':' )
1002                 {
1003                         finalLabel = startLabel.mid( startLabel.length() - 1 );
1004                         startLabel = startLabel.mid( 0, startLabel.length() - 1 );
1005                 }
1006         }
1007         if ( aUnits.length() )
1008                 label = startLabel.stripWhiteSpace() +
1009                 " (" + aUnits + ") " + finalLabel.stripWhiteSpace();
1010         else
1011                 label = startLabel.stripWhiteSpace() +
1012                 " " + finalLabel.stripWhiteSpace();
1013         aLabel->setText( label );
1014 }
1015
1016 /*!
1017         Name: acceptData [virtual protected]
1018         Desc: If returns true dialog will be accepted and closed. This method
1019               called if dialog flag Accept is setted.
1020 */
1021
1022 bool QtxDialog::acceptData() const
1023 {
1024   return true;
1025 }
1026
1027 /*!
1028         Name: rejectData [virtual protected]
1029         Desc: If returns true dialog will be rejected and closed. This method
1030               called if dialog flag Reject is setted.
1031 */
1032
1033 bool QtxDialog::rejectData() const
1034 {
1035         return true;
1036 }
1037
1038 /*!
1039         Name: createButton [virtual protected]
1040         Desc: Create new user button. Invoked from method "insertButton".
1041 */
1042
1043 QButton* QtxDialog::createButton( QWidget* parent )
1044 {
1045         QPushButton* pb = new QPushButton( parent );
1046         pb->setAutoDefault( false );
1047         return pb;
1048 }
1049
1050 /*!
1051         Name: button [protected]
1052         Desc: Return pointer on control button specified by identifier.
1053                   If identifier is wrong then null pointer will returned.
1054 */
1055
1056 QButton* QtxDialog::button( const int f ) const
1057 {
1058         QButton* retval = 0;
1059         if ( myButton.contains( f ) )
1060                 retval = myButton[f];
1061         return retval;
1062 }
1063
1064 /*!
1065         Name: buttons [protected]
1066         Desc: Return map with control dialog buttons accordance to given button flags.
1067 */
1068
1069 QtxDialog::ButtonMap QtxDialog::buttons( const int f ) const
1070 {
1071         ButtonMap retmap;
1072         if ( f < -1 )
1073         {
1074                 if ( myButton.contains( f ) )
1075                         retmap.insert( f, myButton[f] );
1076         }
1077         else
1078         {
1079                 for ( ButtonMap::ConstIterator it = myButton.begin(); it != myButton.end(); ++it )
1080                         if ( f == -1 || ( it.key() >= 0 && f & it.key() ) )
1081                                 retmap.insert( it.key(), it.data() );
1082         }
1083
1084         return retmap;
1085 }
1086
1087 /*!
1088         Name: buttonId [protected]
1089         Desc: Return identifier of specified button.
1090 */
1091
1092 int QtxDialog::buttonId( const QButton* b ) const
1093 {
1094         int id = -1;
1095         for ( ButtonMap::ConstIterator it = myButton.begin(); it != myButton.end() && id == -1; ++it )
1096                 if ( it.data() == b )
1097                         id = it.key();
1098         return id;
1099 }
1100
1101 /*!
1102         Name: buttonPosition
1103         Desc: Returns position of specified button. [protected]
1104 */
1105
1106 int QtxDialog::buttonPosition( QButton* b ) const
1107 {
1108         return buttonPosition( buttonId( b ) );
1109 }
1110
1111 /*!
1112         Name: showEvent [virtual protected]
1113         Desc: Aligns this dialog according the parent widget and alignment
1114               policy before the show.
1115 */
1116
1117 void QtxDialog::showEvent( QShowEvent* e )
1118 {
1119         if ( !testDialogFlags( AlignOnce ) || !myInited )
1120                 Qtx::alignWidget( this, parentWidget(), myAlignment );
1121         QDialog::showEvent( e );
1122 }
1123
1124 /*!
1125         Name: hideEvent [virtual protected]
1126         Desc: Process all existing events when dialog is closed.
1127 */
1128
1129 void QtxDialog::hideEvent( QHideEvent* e )
1130 {
1131         qApp->processEvents();
1132         QDialog::hideEvent( e );
1133 }
1134
1135 /*!
1136         Name: childEvent [virtual protected]
1137         Desc: Setting up layout when size grip is added.
1138 */
1139
1140 void QtxDialog::childEvent( QChildEvent* e )
1141 {
1142         QDialog::childEvent( e );
1143         if ( layout() && e->inserted() && e->child()->inherits( "QSizeGrip" ) )
1144         {
1145                 layout()->setMargin( 12 );
1146 #if QT_VER >= 3
1147                 connect( e->child(), SIGNAL( destroyed() ), this, SLOT( onSizeGripDestroyed() ) );
1148 #endif
1149         }
1150 }
1151
1152 /*!
1153         Name: keyPressEvent [virtual protected]
1154         Desc: Calls reject() if key Escape is pressed.
1155               Calls accept() if key "Ctrl+Enter" is pressed.
1156                   Process key "F1" and emit signal dlgHelp().
1157                   Transfer key "Ctrl+(Shift+)Tab" press event to Tab Widget.
1158 */
1159
1160 void QtxDialog::keyPressEvent( QKeyEvent* e )
1161 {
1162         QDialog::keyPressEvent( e );
1163         if ( e->isAccepted() )
1164             return;
1165
1166         if ( ( e->state() == 0 ) && ( e->key() == Key_Escape ) )
1167                 reject();
1168
1169         if ( ( e->state() == ControlButton ) && ( e->key() == Key_Return ) )
1170         {
1171                 if ( testButtonFlags( OK ) || testButtonFlags( Yes ) )
1172                         accept();
1173                 else if ( testButtonFlags( Apply ) && isButtonEnabled( Apply ) )
1174                         emit dlgApply();
1175                 e->accept();
1176         }
1177
1178         if ( e->key() == Key_F1 && testButtonFlags( Help ) && isButtonEnabled( Help ) )
1179         {
1180                 e->accept();
1181                 emit dlgHelp();
1182         }
1183
1184         if ( ( e->key() == Key_Tab ) && ( e->state() & ControlButton ) )
1185         {
1186                 QObject* tab = child( 0, "QTabWidget" );
1187                 if ( tab )
1188                         tab->event( e );
1189         }
1190 }
1191
1192 /*!
1193         Name: closeEvent [virtual protected]
1194         Desc: Reject the dialog.
1195 */
1196
1197 void QtxDialog::closeEvent( QCloseEvent* )
1198 {
1199         reject();
1200 }
1201
1202 /*!
1203         Name: accept [virtual protected slot]
1204         Desc: Invoke function acceptData() if it needed and if acceptData() return
1205                   false does nothing. Otherwise hides the dialog and sets the result code
1206                   to Accepted. Emit signal according to the pressed control button.
1207 */
1208
1209 void QtxDialog::accept()
1210 {
1211         if ( !mySender )
1212         {
1213                 if ( testButtonFlags( OK ) )
1214                         mySender = button( OK );
1215                 else if ( testButtonFlags( Yes ) )
1216                         mySender = button( Yes );
1217                 else
1218                         mySender = button( Close );
1219         }
1220
1221   if ( !mySender || !mySender->isWidgetType() ||
1222        !((QWidget*)mySender)->isEnabled() )
1223                 return;
1224
1225         if ( testDialogFlags( Accept ) && !acceptData() )
1226                 return;
1227
1228         QDialog::accept();
1229
1230         emitSignal();
1231 }
1232
1233 /*!
1234         Name: reject [virtual protected slot]
1235         Desc: Invoke function rejectData() if it needed and if rejectData() return
1236                   false does nothing. Otherwise hides the dialog and sets the result code
1237                   to Rejected. Emit signal according to the pressed control button. (If
1238                   dialog was closed by key Escape or by close event emit signal dlgCancel(),
1239                   or dlgClose(), or dlgNo().
1240 */
1241
1242 void QtxDialog::reject()
1243 {
1244         if ( testDialogFlags( Reject ) && !rejectData() )
1245                 return;
1246
1247         if ( !mySender )
1248         {
1249                 if ( testButtonFlags( Cancel ) )
1250                         mySender = button( Cancel );
1251                 else if ( testButtonFlags( No ) )
1252                         mySender = button( No );
1253                 else
1254                         mySender = button( Close );
1255         }
1256
1257     if ( !mySender || !mySender->isWidgetType() ||
1258          !((QWidget*)mySender)->isEnabled() )
1259         return;
1260
1261         QDialog::reject();
1262
1263         emitSignal();
1264 }
1265
1266 /*!
1267         Name: reject [private]
1268         Desc: Emit signal appropriate to control button.
1269 */
1270
1271 void QtxDialog::emitSignal()
1272 {
1273         qApp->processEvents();
1274         QApplication::syncX();
1275
1276         int id = buttonId( (QButton*)mySender );
1277         mySender = 0;
1278
1279         switch ( id )
1280         {
1281         case OK:
1282                 emit dlgOk();
1283                 break;
1284         case Cancel:
1285                 emit dlgCancel();
1286                 break;
1287         case Close:
1288                 emit dlgClose();
1289                 break;
1290         case Yes:
1291                 emit dlgYes();
1292                 break;
1293         case No:
1294                 emit dlgNo();
1295                 break;
1296         }
1297 }
1298
1299 /*!
1300         Name: onAccept [private slot]
1301         Desc: Process signals "clicked()" from control buttons "OK", "Yes". Invoke accept().
1302 */
1303
1304 void QtxDialog::onAccept()
1305 {
1306     const QObject* obj = sender();
1307     mySender = obj;
1308     accept();
1309 }
1310
1311 /*!
1312         Name: onReject [private slot]
1313         Desc: Process signals "clicked()" from control buttons "Cancel", "No", "Close".
1314                   Invoke reject().
1315 */
1316
1317 void QtxDialog::onReject()
1318 {
1319   const QObject* obj = sender();
1320   mySender = obj;
1321   reject();
1322 }
1323
1324 /*!
1325         Name: onButton [private slot]
1326         Desc: Receive signal "clicked()" from user buttons and emit signal
1327                   "dlgButton( int )" with identificator of clicked user button.
1328 */
1329
1330 void QtxDialog::onButton()
1331 {
1332         int id = buttonId( (QButton*)sender() );
1333         if ( id != -1 )
1334                 emit dlgButton( id );
1335 }
1336
1337 /*!
1338         Name: onDestroyed [private slot]
1339         Desc: Remove user button if it was destroyed.
1340 */
1341
1342 void QtxDialog::onDestroyed( QObject* obj )
1343 {
1344         QButton* b = (QButton*)obj;
1345         int id = buttonId( b );
1346         if ( id == -1 )
1347                 return;
1348
1349         myButton.remove( id );
1350         myPosition.remove( id );
1351         for ( AreaMap::Iterator it = myArea.begin(); it != myArea.end(); ++it )
1352                 it.data()->removeButton( b );
1353 }
1354
1355 /*!
1356         Name: onSizeGripDestroyed [private slot]
1357         Desc: Setting up layout when size grip is destroyed.
1358 */
1359
1360 void QtxDialog::onSizeGripDestroyed()
1361 {
1362         if ( layout() )
1363                 layout()->setMargin( 5 );
1364 }
1365
1366 /*!
1367         Name: adjustButtons [private]
1368         Desc: Setting the equal with for all buttons.
1369 */
1370
1371 void QtxDialog::adjustButtons()
1372 {
1373         int minWidth = 0;
1374         for ( AreaMap::Iterator aIt = myArea.begin(); aIt != myArea.end(); ++aIt )
1375                 for ( QPtrListIterator<QButton> bIt( aIt.data()->buttons() ); bIt.current(); ++bIt )
1376                         if ( bIt.current()->isVisibleTo( this ) )
1377                                 minWidth = QMAX( minWidth, bIt.current()->sizeHint().width() );
1378
1379         for ( AreaMap::Iterator aItr = myArea.begin(); aItr != myArea.end(); ++aItr )
1380                 for ( QPtrListIterator<QButton> bItr( aItr.data()->buttons() ); bItr.current(); ++bItr )
1381                         if ( bItr.current()->isVisibleTo( this ) )
1382                                 bItr.current()->setMinimumWidth( minWidth );
1383 }