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