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