Salome HOME
Copyright update 2022
[modules/gui.git] / src / Qtx / QtxWorkstackAction.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      QtxWorkstackAction.cxx
24 // Author:    Sergey TELKOV
25 //
26 #include "QtxWorkstackAction.h"
27
28 #include "QtxWorkstack.h"
29
30 #include <QMenu>
31 #include <QWidgetList>
32 #include <QGroupBox>
33 #include <QVBoxLayout>
34 #include <QHBoxLayout>
35 #include <QRadioButton>
36 #include <QPushButton>
37 #include <QListWidget>
38 #include <QStackedLayout>
39 #include <QToolButton>
40 #include <QIcon>
41 #include <QPixmap>
42 #include <QButtonGroup>
43 #include <QCheckBox>
44 #include <QLabel>
45 #include <QComboBox>
46
47 const char* const prev_xpm[] = {
48 "16 16 12 1",
49 "       c None",
50 ".      c #111111",
51 "+      c #ACACAC",
52 "@      c #FC6D6E",
53 "#      c #FB6364",
54 "$      c #F25B5C",
55 "%      c #EA5859",
56 "&      c #C1494A",
57 "*      c #B64545",
58 "=      c #AB4040",
59 "-      c #A03C3C",
60 ";      c #99393A",
61 "        .       ",
62 "       ..+      ",
63 "      .@......  ",
64 "     .@@@@@@@.+ ",
65 "    .########.+ ",
66 "   .$$$$$$$$$.+ ",
67 "  .%%%%%%%%%%.+ ",
68 " .&&&&&&&&&&&.+ ",
69 "  .**********.+ ",
70 "  +.=========.+ ",
71 "   +.--------.+ ",
72 "    +.;;;;;;;.+ ",
73 "     +.;......+ ",
74 "      +..++++++ ",
75 "       +.+      ",
76 "        ++      "};
77
78 const char* const next_xpm[] = {
79 "16 16 12 1",
80 "       c None",
81 ".      c #111111",
82 "+      c #FC6D6E",
83 "@      c #FB6364",
84 "#      c #F25B5C",
85 "$      c #EA5859",
86 "%      c #C1494A",
87 "&      c #B64545",
88 "*      c #ACACAC",
89 "=      c #AB4040",
90 "-      c #A03C3C",
91 ";      c #99393A",
92 "       .        ",
93 "       ..       ",
94 "  ......+.      ",
95 "  .+++++++.     ",
96 "  .@@@@@@@@.    ",
97 "  .#########.   ",
98 "  .$$$$$$$$$$.  ",
99 "  .%%%%%%%%%%%. ",
100 "  .&&&&&&&&&&.**",
101 "  .=========.** ",
102 "  .--------.**  ",
103 "  .;;;;;;;.**   ",
104 "  ......;.**    ",
105 "   ****..**     ",
106 "       .**      ",
107 "       **       "};
108
109 /*!
110   \class QtxWorkstackAction
111   \brief Implements actions group for menu Windows with standard operations, like
112          "Split vertical", "Split horizontal", etc.
113 */
114
115 /*!
116   \brief Constructor.
117   \param ws workstack
118   \param parent parent object (owner of the action)
119 */
120 QtxWorkstackAction::QtxWorkstackAction( QtxWorkstack* ws, QObject* parent )
121 : QtxActionSet( parent ),
122   myWorkstack( ws ),
123   myWindowsFlag( true )
124 {
125   if ( myWorkstack )
126     insertAction( myWorkstack->action( QtxWorkstack::SplitVertical ), SplitVertical );
127   else
128     insertAction( new QtxAction( tr( "Split the active window on two vertical parts" ),
129                                  tr( "Split vertically" ), 0, this ), SplitVertical );
130
131   if ( myWorkstack )
132     insertAction( myWorkstack->action( QtxWorkstack::SplitHorizontal ), SplitHorizontal );
133   else
134     insertAction( new QtxAction( tr( "Split the active window on two horizontal parts" ),
135                                  tr( "Split horizontally" ), 0, this ), SplitHorizontal );
136
137   connect( this, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
138
139   setMenuActions( Standard );
140
141   myArrangeViewsAction = new QAction( tr( "Arrange Views" ), this );
142 }
143
144 /*!
145   \brief Destructor.
146 */
147 QtxWorkstackAction::~QtxWorkstackAction()
148 {
149 }
150
151 /*!
152   \brief Get workstack.
153   \return parent workstack
154 */
155 QtxWorkstack* QtxWorkstackAction::workstack() const
156 {
157   return myWorkstack;
158 }
159
160 /*!
161   \brief Get arrange views action.
162 */
163 QAction* QtxWorkstackAction::getArrangeViewsAction()
164 {
165   return myArrangeViewsAction;
166 }
167
168 /*!
169   \brief Set actions to be visible in the menu.
170
171   Actions, which IDs are set in \a flags parameter, will be shown in the
172   menu bar. Other actions will not be shown.
173
174   \param flags ORed together actions flags
175 */
176 void QtxWorkstackAction::setMenuActions( const int flags )
177 {
178   action( SplitVertical )->setVisible( flags & SplitVertical );
179   action( SplitHorizontal )->setVisible( flags & SplitHorizontal );
180   myWindowsFlag = flags & Windows;
181 }
182
183 /*!
184   \brief Get menu actions which are currently visible in the menu bar.
185   \return ORed together actions flags
186   \sa setMenuActions()
187 */
188 int QtxWorkstackAction::menuActions() const
189 {
190   int ret = 0;
191   ret = ret | ( action( SplitVertical )->isVisible() ? SplitVertical : 0 );
192   ret = ret | ( action( SplitHorizontal )->isVisible() ? SplitHorizontal : 0 );
193   ret = ret | ( myWindowsFlag ? Windows : 0 );
194   return ret;
195 }
196
197 /*!
198   \brief Get keyboard accelerator for the specified action.
199   \param id menu action ID
200   \return keyboard accelerator of menu item or 0 if there is no such action
201 */
202 int QtxWorkstackAction::accel( const int id ) const
203 {
204   int a = 0;
205   if ( action( id ) )
206     a = action( id )->shortcut()[0];
207   return a;
208 }
209
210 /*!
211   \brief Get icon for the specified action.
212
213   If \a id is invalid, null icon is returned.
214
215   \param id menu action ID
216   \return menu item icon
217 */
218 QIcon QtxWorkstackAction::icon( const int id ) const
219 {
220   QIcon ico;
221   if ( action( id ) )
222     ico = action( id )->icon();
223   return ico;
224 }
225
226 /*!
227   \brief Get menu item text for the specified action.
228   \param id menu action ID
229   \return menu item text or null QString if there is no such action
230 */
231 QString QtxWorkstackAction::text( const int id ) const
232 {
233   QString txt;
234   if ( action( id ) )
235     txt = action( id )->text();
236   return txt;
237 }
238
239 /*!
240   \brief Get status bar tip for the specified action.
241   \param id menu action ID
242   \return status bar tip menu item or null QString if there is no such action
243 */
244 QString QtxWorkstackAction::statusTip( const int id ) const
245 {
246   QString txt;
247   if ( action( id ) )
248     txt = action( id )->statusTip();
249   return txt;
250 }
251
252 /*!
253   \brief Set keyboard accelerator for the specified action.
254   \param id menu action ID
255   \param a new keyboard accelerator
256 */
257 void QtxWorkstackAction::setAccel( const int id, const int a )
258 {
259   if ( action( id ) )
260     action( id )->setShortcut( a );
261 }
262
263 /*!
264   \brief Set menu item icon for the specified action.
265   \param id menu action ID
266   \param ico new menu item icon
267 */
268 void QtxWorkstackAction::setIcon( const int id, const QIcon& icon )
269 {
270   if ( action( id ) )
271     action( id )->setIcon( icon );
272 }
273
274 /*!
275   \brief Set menu item text for the specified action.
276   \param id menu action ID
277   \param txt new menu item text
278 */
279 void QtxWorkstackAction::setText( const int id, const QString& txt )
280 {
281   if ( action( id ) )
282     action( id )->setText( txt );
283 }
284
285 /*!
286   \brief Set menu item status bar tip for the specified action.
287   \param id menu action ID
288   \param txt new menu item status bar tip
289 */
290 void QtxWorkstackAction::setStatusTip( const int id, const QString& txt )
291 {
292   if ( action( id ) )
293     action( id )->setStatusTip( txt );
294 }
295
296 /*!
297   \brief Process action activated by the user.
298   \param type action ID
299 */
300 void QtxWorkstackAction::perform( const int /*type*/ )
301 {
302   /*
303   switch ( type )
304   {
305   case SplitVertical:
306     splitVertical();
307     break;
308   case SplitHorizontal:
309     splitHorizontal();
310     break;
311   }
312   */
313 }
314
315 /*!
316   \brief Split the window area in the workstack in the vertical direction.
317 */
318 void QtxWorkstackAction::splitVertical()
319 {
320   QtxWorkstack* ws = workstack();
321   if ( ws )
322     ws->splitVertical();
323 }
324
325 /*!
326   \brief Split the window area in the workstack in the horizontal direction.
327 */
328 void QtxWorkstackAction::splitHorizontal()
329 {
330   QtxWorkstack* ws = workstack();
331   if ( ws )
332     ws->splitHorizontal();
333 }
334
335 /*!
336   \brief Called when action is added to the menu bar.
337   \param w menu bar widget this action is being added to
338 */
339 void QtxWorkstackAction::addedTo( QWidget* w )
340 {
341   QtxActionSet::addedTo( w );
342
343   QMenu* pm = ::qobject_cast<QMenu*>( w );
344   if ( pm )
345     connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
346 }
347
348 /*!
349   \brief Called when action is removed from the menu bar.
350   \param w menu bar widget this action is being removed from
351 */
352 void QtxWorkstackAction::removedFrom( QWidget* w )
353 {
354   QtxActionSet::removedFrom( w );
355
356   QMenu* pm = ::qobject_cast<QMenu*>( w );
357   if ( pm )
358     disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
359 }
360
361 /*!
362   \brief Update all menu action state.
363 */
364 void QtxWorkstackAction::updateContent()
365 {
366   bool count = workstack() ? workstack()->splitWindowList().count() > 1 : 0;
367   action( SplitVertical )->setEnabled( count );
368   action( SplitHorizontal )->setEnabled( count );
369   count = workstack() ? workstack()->windowList().count() > 1 : 0;
370   myArrangeViewsAction->setEnabled( count );
371
372   updateWindows();
373 }
374
375 /*!
376   \brief Update actions which refer to the opened child windows.
377 */
378 void QtxWorkstackAction::updateWindows()
379 {
380   QtxWorkstack* ws = workstack();
381   if ( !ws )
382     return;
383
384   QList<QAction*> lst = actions();
385   for ( QList<QAction*>::iterator it = lst.begin(); it != lst.end(); ++it )
386   {
387     int id = actionId( *it );
388     if ( id >= Windows )
389       removeAction( *it );
390   }
391
392   bool base = action( SplitVertical )->isVisible() || action( SplitHorizontal )->isVisible();
393
394   QList<QAction*> items;
395   QMap<QAction*, int> map;
396   if ( menuActions() & Windows )
397   {
398     int index = 1;
399     QWidgetList wList = ws->windowList();
400     for ( QWidgetList::iterator it = wList.begin(); it != wList.end(); ++it, index++ )
401     {
402       QWidget* wid = *it;
403       QAction* a = new QtxAction( wid->windowTitle(), wid->windowTitle(), 0, this, true );
404       a->setChecked( wid == ws->activeWindow() );
405       items.append( a );
406       map.insert( a, Windows + index );
407     }
408
409     if ( base && !items.isEmpty() )
410     {
411       QAction* sep = new QtxAction( this );
412       sep->setSeparator( true );
413       items.prepend( sep );
414       map.insert( sep, Windows );
415     }
416   }
417
418   if ( !items.isEmpty() )
419     insertActions( items );
420
421   for ( QMap<QAction*, int>::const_iterator itr = map.begin(); itr != map.end(); ++itr )
422     setActionId( itr.key(), itr.value() );
423 }
424
425 /*!
426   \brief Called when parent menu is about to show.
427
428   Updates all menu items.
429 */
430 void QtxWorkstackAction::onAboutToShow()
431 {
432   QMenu* pm = ::qobject_cast<QMenu*>( sender() );
433   if ( pm )
434     updateContent();
435 }
436
437 /*!
438   \brief Called when menu item corresponding to some child window is activated.
439
440   Activates correposponding child window.
441
442   \param idx menu item index
443 */
444 void QtxWorkstackAction::activateItem( const int idx )
445 {
446   QtxWorkstack* ws = workstack();
447   if ( !ws )
448     return;
449
450   QWidgetList wList = ws->windowList();
451   if ( idx >= 0 && idx < (int)wList.count() )
452     wList.at( idx )->setFocus();
453 }
454
455 /*!
456   \brief Called when menu item is activated by the user.
457
458   Perform the corresponding action.
459
460   \param id menu item identifier
461 */
462 void QtxWorkstackAction::onTriggered( int id )
463 {
464   if ( id < Windows )
465     perform( id );
466   else
467     activateItem( id - Windows - 1 );
468 }
469
470 /*!
471   \class QtxSplitDlg
472   \brief Used for arranging views(menu item "Window->Arrange Views")
473          and for creating sub-views of current view(button "Create sub-views")
474 */
475
476 /*!
477   \brief Constructor.
478   \param parent - parent object
479   \param workstack - Work Stack widget
480   \param mode - mode of current dialog
481 */
482 QtxSplitDlg::QtxSplitDlg( QWidget* parent, QtxWorkstack* workstack, QtxSplitDlgMode mode )
483 : QDialog( parent ),
484   myWorkstack( workstack ),
485   myDlgMode( mode ),
486   myViewsNB(2),
487   mySplitMode(0),
488   myNBSelectedViews(0),
489   myIsCloseViews( false )
490 {
491   Q_INIT_RESOURCE(Qtx);
492
493   setModal( true );
494   setObjectName( "Qtx_Split" );
495
496   if( mode == ArrangeViews )
497     setWindowTitle( tr( "Arrange views" ) );
498   else if( mode == CreateSubViews )
499     setWindowTitle( tr( "Create sub-views") );
500
501   QVBoxLayout* topLayout = new QVBoxLayout( this );
502   topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
503
504   /////////////////////////////////////////////////////////////////////
505   QGroupBox* aGroupViewsLayout = new QGroupBox();
506   if( mode == ArrangeViews )
507     aGroupViewsLayout->setTitle( tr("Views Layout") );
508   else if( mode == CreateSubViews )
509     aGroupViewsLayout->setTitle( tr("Sub-views Layout") );
510
511   QGridLayout* OptionsViewsLayout = new QGridLayout( aGroupViewsLayout );
512
513   // Radio Buttons for selecting the number of views
514   QVBoxLayout* RadioButtonsLayout = new QVBoxLayout();
515   myButton2Views = new QRadioButton( "2", this );
516   myButton3Views = new QRadioButton( "3", this );
517   myButton4Views = new QRadioButton( "4", this );
518
519   myButton2Views->setChecked( true );
520
521   RadioButtonsLayout->addWidget( myButton2Views );
522   RadioButtonsLayout->addWidget( myButton3Views );
523   RadioButtonsLayout->addWidget( myButton4Views );
524
525   // Buttons for possibility of switching the variants of split
526   myButtonPrevious = new QPushButton( this );
527   myButtonPrevious->setIcon( QPixmap( prev_xpm ) );
528   myButtonPrevious->setAutoDefault(true);
529   myButtonPrevious->setEnabled( false );
530
531   myButtonNext = new QPushButton( this );
532   myButtonNext->setIcon( QPixmap( next_xpm ) );
533   myButtonNext->setAutoDefault(true);
534   myButtonNext->setEnabled( false );
535
536   // Split options
537   myStackedSplitLayout = new QStackedLayout();
538
539   QButtonGroup* SplitOptions = new QButtonGroup( this );
540   SplitOptions->setExclusive( true );
541
542   // Arrange icons for 2 views according to next scheme
543   //     x
544   //     x
545   QGridLayout* aSplit2Layout = new QGridLayout();
546   for( int i=1; i<=2; i++ ) {
547     QToolButton* aSplitBtn = createSplitButton( 2, i );
548     aSplit2Layout->addWidget( aSplitBtn, i-1, 0 );
549     SplitOptions->addButton( aSplitBtn, i-1 );
550   }
551   QWidget* aSplit2Widget = new QWidget( this );
552   aSplit2Widget->setLayout( aSplit2Layout );
553   myStackedSplitLayout->addWidget( aSplit2Widget );
554
555   // Arrange icons for 3 views according to next scheme
556   //     x x x
557   //     x x x
558   QGridLayout* aSplit3Layout = new QGridLayout();
559   bool anIconPosition = 0;
560   for( int i=1; i<=6; i++ ) {
561     QToolButton* aSplitBtn = createSplitButton( 3, i );
562     aSplit3Layout->addWidget( aSplitBtn, anIconPosition, int((i-1)/2) );
563     SplitOptions->addButton( aSplitBtn, i+1 );
564     anIconPosition = !anIconPosition;
565   }
566   QWidget* aSplit3Widget = new QWidget( this );
567   aSplit3Widget->setLayout( aSplit3Layout );
568   myStackedSplitLayout->addWidget( aSplit3Widget );
569
570   // Arrange icons for 4 views according to next scheme
571   //     x x x      x x x x      x x
572   //     x x x      x x x x      x x
573   //     x x x
574   QGridLayout* aSplit4Layout = new QGridLayout();
575   int aPosition = 0;
576   for( int i=1; i<=21; i++ ) {
577     QToolButton* aSplitBtn = createSplitButton( 4, i );
578     SplitOptions->addButton( aSplitBtn, i+7 );
579     if( i <= 9 ) {
580       aSplit4Layout->addWidget( aSplitBtn, int((i-1)/3), aPosition );
581       aPosition = ( aPosition == 2 ) ? 0: aPosition + 1;
582     }
583     else if( i > 9 && i <= 17 ) {
584       aSplit4Layout->addWidget( aSplitBtn, int( (i-10)/4), aPosition );
585       aPosition = ( aPosition == 3 ) ? 0: aPosition + 1;
586     }
587     else if( i>17 ) {
588       aSplit4Layout->addWidget( aSplitBtn, int( (i-18)/2 ), aPosition );
589       aPosition = ( aPosition == 1 ) ? 0: aPosition + 1;
590     }
591     if( i == 9 || i == 17 || i == 21 ) { //finish set icon in current stack widget
592       QWidget* aSplit4Widget = new QWidget( this );
593       aSplit4Widget->setLayout( aSplit4Layout );
594       myStackedSplitLayout->addWidget( aSplit4Widget );
595       aSplit4Layout = new QGridLayout();
596     }
597   }
598
599   QHBoxLayout* ArrowLayout = new QHBoxLayout();
600   ArrowLayout->addSpacing(130);
601   ArrowLayout->addWidget( myButtonPrevious );
602   ArrowLayout->addWidget( myButtonNext );
603   ArrowLayout->addSpacing(130);
604
605   OptionsViewsLayout->addLayout( ArrowLayout, 0, 1, 1, 2);
606   OptionsViewsLayout->addLayout( RadioButtonsLayout, 1, 0 );
607   OptionsViewsLayout->addLayout( myStackedSplitLayout, 1, 1, 1, 2 );
608
609   /////////////////////////////////////////////////////////////////////
610
611   QGroupBox* GroupProperties = new QGroupBox();
612
613   if( mode == ArrangeViews ) {
614     GroupProperties->setTitle( tr("Views List") );
615
616     QVBoxLayout* ViewsListLayout = new QVBoxLayout( GroupProperties );
617
618     QWidgetList aWidgetList = myWorkstack->windowList();
619     myViewsList = new QListWidget( GroupProperties );
620     myViewsList->setSelectionMode(QAbstractItemView::SingleSelection);
621     connect( myViewsList, SIGNAL( itemClicked(QListWidgetItem*) ), this, SLOT( onSynchronize() ) );
622
623     for( int i=0; i< aWidgetList.count(); i++ ) {
624       QWidget* aWidget = aWidgetList.at(i);
625       QListWidgetItem* anItem = new QListWidgetItem( aWidget->windowTitle(), myViewsList );
626       anItem->setCheckState( Qt::Unchecked );
627       anItem->setFlags( anItem->flags() & ~Qt::ItemIsSelectable );
628     }
629
630     QRadioButton* CloseViews = new QRadioButton( GroupProperties );
631     CloseViews->setText( tr( "Close remaining views" ) );
632     connect( CloseViews, SIGNAL( pressed() ), this, SLOT( onCloseViews() ) );
633
634     QRadioButton* StackViews = new QRadioButton( GroupProperties );
635     StackViews->setText( tr( "Stack remaining views in the last area" ) );
636     StackViews->setChecked( true );
637     connect( StackViews, SIGNAL( pressed() ), this, SLOT( onStackViews() ) );
638
639     ViewsListLayout->addWidget( myViewsList );
640     ViewsListLayout->addWidget( CloseViews );
641     ViewsListLayout->addWidget( StackViews );
642   }
643   else {
644     GroupProperties->setTitle( tr( "Sub-views Properties" ) );
645     for( int i = 0; i < 4; i++ ) {
646       QLabel* SubView = new QLabel( tr( "Sub-view" ) + " " + QString::number(i+1),
647                                     GroupProperties);
648       myLabels << SubView;
649
650       QComboBox* ComboBox = new QComboBox( GroupProperties );
651       ComboBox->addItem("XYZ");
652       ComboBox->addItem("XY");
653       ComboBox->addItem("XZ");
654       ComboBox->addItem("YZ");
655       myComboBox.append( ComboBox );
656       myMapComboBoxMode.insert( ComboBox, (ViewMode)i );
657       ComboBox->setCurrentIndex(i);
658       connect( ComboBox, SIGNAL( currentIndexChanged (int) ), this, SLOT( onComboBoxChanged(int) ) );
659     }
660
661     QGridLayout* SubViewsPropLayout = new QGridLayout( GroupProperties );
662     SubViewsPropLayout->addWidget( myLabels[0],   0, 0 );
663     SubViewsPropLayout->addWidget( myComboBox[0], 0, 1 );
664     SubViewsPropLayout->addWidget( myLabels[1],   0, 2 );
665     SubViewsPropLayout->addWidget( myComboBox[1], 0, 3 );
666     SubViewsPropLayout->addWidget( myLabels[2],   1, 0 );
667     SubViewsPropLayout->addWidget( myComboBox[2], 1, 1 );
668     SubViewsPropLayout->addWidget( myLabels[3],   1, 2 );
669     SubViewsPropLayout->addWidget( myComboBox[3], 1, 3 );
670   }
671
672   /////////////////////////////////////////////////////////////////////
673
674   QGroupBox* GroupButtons = new QGroupBox();
675   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
676
677   myButtonApply = new QPushButton(tr( "&Apply" ), GroupButtons);
678   myButtonApply->setAutoDefault(true);
679   myButtonApply->setDefault(true);
680   myButtonApply->setEnabled( false );
681   QPushButton* buttonClose = new QPushButton(tr( "&Close" ), GroupButtons);
682   buttonClose->setAutoDefault(true);
683
684   GroupButtonsLayout->addWidget( myButtonApply );
685   GroupButtonsLayout->addSpacing(100);
686   GroupButtonsLayout->addWidget( buttonClose );
687
688   /////////////////////////////////////////////////////////////////////
689
690   topLayout->addWidget( aGroupViewsLayout );
691   topLayout->insertStretch(1);
692   topLayout->addWidget( GroupProperties );
693   topLayout->addWidget( GroupButtons );
694
695
696   connect( myButton2Views,   SIGNAL( pressed() ), this,    SLOT( onChangeIcons() ) );
697   connect( myButton3Views,   SIGNAL( pressed() ), this,    SLOT( onChangeIcons() ) );
698   connect( myButton4Views,   SIGNAL( pressed() ), this,    SLOT( onChangeIcons() ) );
699   connect( myButtonPrevious, SIGNAL( pressed() ), this,    SLOT( onPreviousViews() ) );
700   connect( myButtonNext,     SIGNAL( pressed() ), this,    SLOT( onNextViews() ) );
701   connect( SplitOptions,     SIGNAL( buttonClicked(int) ), SLOT( onSplitChanged(int)));
702   connect( buttonClose,      SIGNAL( pressed() ), this,    SLOT( reject() ) );
703   connect( myButtonApply,    SIGNAL( pressed() ), this,    SLOT( onApply() ) );
704
705   initialize();
706 }
707
708 /*!
709   \brief Destructor
710 */
711 QtxSplitDlg::~QtxSplitDlg()
712 {
713 }
714
715 /*!
716   \brief Return current split mode
717 */
718 int QtxSplitDlg::getSplitMode()
719 {
720   return mySplitMode;
721 }
722
723 /*!
724   \brief Return selected view modes
725 */
726 QList<int> QtxSplitDlg::getViewsMode()
727 {
728   QList<int> aList;
729   for ( int i = 0; i < myViewsNB; i++ ) {
730     int aMode = myMapComboBoxMode[myComboBox[i]];
731     aList<<aMode;
732   }
733   return aList;
734 }
735
736 /*!
737   \brief Create new QToolButton using icon of split mode
738 */
739 QToolButton* QtxSplitDlg::createSplitButton( int theViewsNB, int theSplitMode )
740 {
741   QString anImageName = QString( ":/images/qtx_split%1_%2.png" )
742                                   .arg(theViewsNB).arg(theSplitMode).toLatin1().constData();
743   QPixmap aSplitIcon( anImageName );
744   QToolButton* aSplitBtn = new QToolButton( this );
745   aSplitBtn->setCheckable( true );
746   aSplitBtn->setIcon( aSplitIcon );
747   aSplitBtn->setIconSize( QSize( aSplitIcon.width(), aSplitIcon.height() ) );
748   return aSplitBtn;
749 }
750
751 /*!
752   \brief Initialisation of widgets
753 */
754 void QtxSplitDlg::initialize()
755 {
756   if( myDlgMode == ArrangeViews ) {
757     int aViewsNumber = myWorkstack->windowList().count();
758     if( aViewsNumber == 2 ) {
759       myButton3Views->setEnabled( false );
760       myButton4Views->setEnabled( false );
761     }
762     else if( aViewsNumber == 3 )
763       myButton4Views->setEnabled( false );
764   }
765   else if( myDlgMode == CreateSubViews ) {
766     for( int i = 0; i < 4; i++) {
767       if( i < myViewsNB )
768         myMapModeIsBusy[(ViewMode)i] = true;
769       else
770         myMapModeIsBusy[ (ViewMode)i] = false;
771     }
772     onSynchronize();
773   }
774 }
775
776 /*!
777   \brief Verification if all items necessary for dialog were selected
778 */
779 void QtxSplitDlg::valid()
780 {
781   bool isValid = false;
782   if( myViewsNB == 2 )
783     isValid = ( mySplitMode >= 0 && mySplitMode < 2 )? true:false;
784   else if( myViewsNB == 3 )
785     isValid = ( mySplitMode >= 2 && mySplitMode < 8 )? true:false;
786   else if( myViewsNB == 4)
787     isValid = ( mySplitMode >=8 && mySplitMode < 29 )?true:false;
788
789   if( myDlgMode == ArrangeViews ) {
790     if( myNBSelectedViews != myViewsNB)
791       isValid = false;
792   }
793   myButtonApply->setEnabled( isValid );
794 }
795
796 /*!
797   \brief Called when number of views was changed
798          and it's necessary to set others split icons
799 */
800 void QtxSplitDlg::onChangeIcons()
801 {
802   if( myButton2Views->isDown() ) {
803     myViewsNB = 2;
804     mySplitMode = 0;
805     myStackedSplitLayout->setCurrentIndex(0);
806     myButtonPrevious->setEnabled( false );
807     myButtonNext->setEnabled( false );
808   }
809   else if( myButton3Views->isDown() ) {
810     myViewsNB = 3;
811     mySplitMode = 2;
812     myStackedSplitLayout->setCurrentIndex(1);
813     myButtonPrevious->setEnabled( false );
814     myButtonNext->setEnabled( false );
815   }
816   else if( myButton4Views->isDown() ) {
817     myViewsNB = 4;
818     mySplitMode = 8;
819     myStackedSplitLayout->setCurrentIndex(2);
820     myButtonPrevious->setEnabled( false );
821     myButtonNext->setEnabled( true );
822   }
823   onSynchronize();
824 }
825
826 /*!
827   \brief Called when user selects an icon for split
828 */
829 void QtxSplitDlg::onSplitChanged( int theMode )
830 {
831   mySplitMode = theMode;
832   valid();
833 }
834
835 /*!
836   \brief Called when user selects item of Combo Box
837 */
838 void QtxSplitDlg::onComboBoxChanged( int theItem )
839 {
840   QMap<ViewMode,bool > aModeEnabledMap;
841   for( int i = 0; i < 4; i++ )
842     aModeEnabledMap[(ViewMode)i] = false;
843   QComboBox* aSender = qobject_cast<QComboBox*>(sender());
844   for ( int i=0;i<4;i++ )
845     if( myComboBox[i] == aSender )
846       myMapComboBoxMode[myComboBox[i]]=(ViewMode)theItem;
847
848   for( int i = 0; i < 4; i++ ) {
849     if( myComboBox[i]->isVisible() ) {
850       ViewMode aViewMode = myMapComboBoxMode[myComboBox[i]];
851       aModeEnabledMap[aViewMode] = true;
852     }
853   }
854   for( int i = 0; i < 4; i++ ) {
855     if( myComboBox[i] != aSender ) {
856       ViewMode aNewMode = XYZ;
857       if( myMapComboBoxMode[myComboBox[i]] == (ViewMode)(theItem) ) {
858         for( int j = 0; j < 4; j++ )
859           if( !aModeEnabledMap[(ViewMode)j] )
860             aNewMode = (ViewMode)j;
861         myComboBox[i]->setCurrentIndex( (int)aNewMode );
862       }
863     }
864   }
865 }
866
867 /*!
868   \brief Called when user taps previous button
869 */
870 void QtxSplitDlg::onPreviousViews()
871 {
872   int aCurrentIndex = myStackedSplitLayout->currentIndex();
873   myStackedSplitLayout->setCurrentIndex( aCurrentIndex - 1 );
874   if( myStackedSplitLayout->currentIndex() == 2 )
875     myButtonPrevious->setEnabled( false );
876   if( myStackedSplitLayout->currentIndex() < 4 )
877     myButtonNext->setEnabled( true );
878 }
879
880 /*!
881   \brief Called when user taps next button
882 */
883 void QtxSplitDlg::onNextViews()
884 {
885   int aCurrentIndex = myStackedSplitLayout->currentIndex();
886   myStackedSplitLayout->setCurrentIndex( aCurrentIndex + 1 );
887   if( myStackedSplitLayout->currentIndex() == 4 )
888     myButtonNext->setEnabled( false );
889   if( myStackedSplitLayout->currentIndex() > 2 )
890     myButtonPrevious->setEnabled( true );
891 }
892
893 /*!
894   \brief Synchronize data and widgets
895 */
896 void QtxSplitDlg::onSynchronize( )
897 {
898   if( myDlgMode == ArrangeViews) {
899     int aCheckedNumber = 0;
900     for( int i=0; i < myViewsList->count(); i++ ) {
901       if( myViewsList->item(i)->checkState() == Qt::Checked )
902         aCheckedNumber++;
903       if( aCheckedNumber == myViewsNB )
904         for( int p = i+1; p < myViewsList->count(); p++ )
905           myViewsList->item(p)->setCheckState( Qt::Unchecked );
906     }
907     if( aCheckedNumber == myViewsNB ) {
908       for( int i=0; i < myViewsList->count(); i++ )
909         if( myViewsList->item(i)->checkState() == Qt::Unchecked )
910           myViewsList->item(i)->setFlags( myViewsList->item(i)->flags() & ~Qt::ItemIsEnabled );
911     }
912     else if( aCheckedNumber < myViewsNB ) {
913       for( int i=0; i < myViewsList->count(); i++ )
914         if( myViewsList->item(i)->checkState() == Qt::Unchecked )
915           myViewsList->item(i)->setFlags( myViewsList->item(i)->flags() | Qt::ItemIsEnabled );
916     }
917     myNBSelectedViews = aCheckedNumber;
918   }
919   else if( myDlgMode == CreateSubViews ) {
920     foreach( QComboBox* aBox, myComboBox )
921       aBox->setVisible( true );
922     foreach( QLabel* aLabel, myLabels )
923       aLabel->setVisible( true );
924
925     for( int i = myViewsNB; i < 4; i++ ) {
926       myComboBox[i]->setVisible( false );
927       myLabels[i]->setVisible( false );
928     }
929     for( int i = 0; i < 4; i++ )
930       myComboBox[i]->setCurrentIndex(i);
931   }
932   valid();
933 }
934
935 /*!
936   \brief Called when check box "Close remaining views" is active
937 */
938 void QtxSplitDlg::onCloseViews()
939 {
940   myIsCloseViews = true;
941 }
942
943 /*!
944   \brief Called when check box "Stack remaining views
945          in the last area" is active
946 */
947 void QtxSplitDlg::onStackViews()
948 {
949   myIsCloseViews = false;
950 }
951
952 /*!
953   \brief Apply dialog
954 */
955 void QtxSplitDlg::onApply()
956 {
957   if( myDlgMode == ArrangeViews ) {
958     myWorkstack->stack();
959     int Split3Map[6][6] = {
960     //  View, Dir, View,Move, Dir
961       {  1,    1,   2,   -1,   1 },
962       {  1,    2,   2,   -1,   2 },
963       {  2,    1,   1,   -1,   2 },
964       {  1,    1,   2,    1,   2 },
965       {  1,    2,   2,    1,   1 },
966       {  2,    2,   1,   -1,   1 },
967     };
968
969     int Split4Map[21][9] = {
970     //  View, Dir, View,Move, Dir, View,Move, Dir
971         { 1,   1,   2,   -1,   1,   3,   -1,   1 },
972         { 1,   2,   2,   -1,   2,   3,   -1,   2 },
973         { 1,   1,   2,   -1,   2,   3,    1,   2 },
974         { 2,   1,   3,   -1,   1,   1,   -1,   2 },
975         { 1,   1,   3,   -1,   1,   2,    1,   2 },
976         { 1,   1,   2,   -1,   1,   3,    2,   2 },
977         { 2,   2,   3,   -1,   2,   1,   -1,   1 },
978         { 1,   2,   3,   -1,   2,   2,    1,   1 },
979         { 1,   2,   2,   -1,   2,   3,    2,   1 },
980         { 3,   2,   2,   -1,   1,   1,   -1,   2 },
981         { 3,   2,   1,   -1,   1,   2,    1,   2 },
982         { 1,   2,   3,    1,   1,   2,    1,   2 },
983         { 1,   2,   2,    1,   1,   3,    2,   2 },
984         { 1,   1,   3,    1,   2,   2,    1,   1 },
985         { 1,   1,   2,    1,   2,   3,    2,   1 },
986         { 3,   1,   2,   -1,   2,   1,   -1,   1 },
987         { 3,   1,   1,   -1,   2,   2,    1,   1 },
988         { 1,   2,   2,    1,   1,   3,    1,   1 },
989         { 3,   2,   1,   -1,   1,   2,   -1,   1 },
990         { 3,   1,   1,   -1,   2,   2,   -1,   2 },
991         { 1,   1,   2,    1,   2,   3,    1,   2 }
992     };
993
994     QWidgetList aWidgetList = myWorkstack->windowList();
995     QWidgetList aListChecked;
996     QWidgetList aListUnchecked;
997     QtxWorkstack::SplitType aSplitType = QtxWorkstack::SplitMove;
998
999     for( int i = 0; i < myViewsList->count(); i++ ) {
1000       QString aName = myViewsList->item(i)->text();
1001       for( int j = 0; j< aWidgetList.count(); j++ ) {
1002         QWidget* aWidget = aWidgetList.at(j);
1003         if( aWidget->windowTitle() == aName ) {
1004           if( myViewsList->item(i)->checkState() == Qt::Checked )
1005             aListChecked.append( aWidget );
1006           else if( myViewsList->item(i)->checkState() == Qt::Unchecked )
1007             aListUnchecked.append( aWidget );
1008         }
1009       }
1010     }
1011
1012     if( myViewsNB == 2 )
1013     {
1014       if( aListChecked.size() != 2 )
1015         return;
1016       if( mySplitMode == 0)
1017         myWorkstack->Split( aListChecked.at(1),Qt::Horizontal, aSplitType );
1018       else if( mySplitMode == 1 )
1019         myWorkstack->Split( aListChecked.at(1),Qt::Vertical, aSplitType );
1020     }
1021     else if( myViewsNB == 3 ) {
1022       if( aListChecked.size() != 3 )
1023         return;
1024       mySplitMode = mySplitMode - 2;
1025       myWorkstack->Split( aListChecked.at( Split3Map[mySplitMode][0] ),
1026                           Qt::Orientation( Split3Map[mySplitMode][1] ),
1027                           aSplitType );
1028       if( Split3Map[mySplitMode][3] >= 0 )
1029         myWorkstack->move( aListChecked.at( Split3Map[mySplitMode][2] ),
1030                            aListChecked.at( Split3Map[mySplitMode][3] ),
1031                            false );
1032
1033       myWorkstack->Split( aListChecked.at( Split3Map[mySplitMode][2] ),
1034                           Qt::Orientation( Split3Map[mySplitMode][4] ),
1035                           aSplitType );
1036     }
1037     else if( myViewsNB == 4 ) {
1038       if( aListChecked.size() != 4 )
1039         return;
1040       mySplitMode = mySplitMode - 8;
1041       myWorkstack->Split( aListChecked.at( Split4Map[mySplitMode][0] ),
1042                           Qt::Orientation( Split4Map[mySplitMode][1] ),
1043                           aSplitType );
1044       if( Split4Map[mySplitMode][3] >= 0 )
1045         myWorkstack->move( aListChecked.at( Split4Map[mySplitMode][2] ),
1046                                  aListChecked.at( Split4Map[mySplitMode][3] ),
1047                            false );
1048
1049       myWorkstack->Split( aListChecked.at( Split4Map[mySplitMode][2] ),
1050                           Qt::Orientation( Split4Map[mySplitMode][4] ),
1051                           aSplitType );
1052       if( Split4Map[mySplitMode][6] >= 0 )
1053         myWorkstack->move( aListChecked.at( Split4Map[mySplitMode][5] ),
1054                            aListChecked.at( Split4Map[mySplitMode][6] ),
1055                            false );
1056
1057       myWorkstack->Split( aListChecked.at( Split4Map[mySplitMode][5] ),
1058                           Qt::Orientation( Split4Map[mySplitMode][7] ),
1059                           aSplitType );
1060     }
1061     for( int i = 0; i < aListUnchecked.count(); i++ ) {
1062       if( myIsCloseViews )
1063         aListUnchecked.at(i)->close();
1064       else
1065         myWorkstack->move( aListUnchecked.at(i),
1066                            aListChecked.at( myViewsNB - 1 ),
1067                            false );
1068     }
1069   }
1070   accept();
1071 }