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