libyui-qt  2.43.5
 All Classes Functions Variables
YQWizard.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YQWizard.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23  Textdomain "qt"
24 
25 /-*/
26 
27 #include "YQWizard.h"
28 #define YUILogComponent "qt-wizard"
29 #include <yui/YUILog.h>
30 
31 #include <string>
32 #include <yui/YShortcut.h>
33 
34 #include <QDialog>
35 #include <QSvgRenderer>
36 #include <QPainter>
37 #include <QStackedWidget>
38 #include <qimage.h>
39 #include <qlabel.h>
40 #include <qlayout.h>
41 #include <qmenubar.h>
42 #include <qmenudata.h>
43 #include <qobject.h>
44 #include <qpixmap.h>
45 #include <qpushbutton.h>
46 #include <qregexp.h>
47 #include <qtabwidget.h>
48 #include <qtoolbutton.h>
49 #include <QGraphicsDropShadowEffect>
50 
51 #include "QY2ListView.h"
52 #include "QY2Styler.h"
53 #include "QY2HelpDialog.h"
54 #include <QGridLayout>
55 #include <QHeaderView>
56 #include <qevent.h>
57 
58 #include "utf8.h"
59 #include "YQi18n.h"
60 #include "YQUI.h"
61 #include "YQApplication.h"
62 #include "YQDialog.h"
63 #include "YQAlignment.h"
64 #include "YQReplacePoint.h"
65 #include "YQEmpty.h"
66 #include "YQLabel.h"
67 #include "YQWizardButton.h"
68 #include "YQWidgetFactory.h"
69 #include "YQSignalBlocker.h"
70 #include <yui/YEvent.h>
71 #include "YQMainWinDock.h"
72 
73 
74 using std::string;
75 
76 #ifdef TEXTDOMAIN
77 # undef TEXTDOMAIN
78 #endif
79 
80 #define TEXTDOMAIN "qt"
81 
82 #define USE_ICON_ON_HELP_BUTTON 0
83 
84 YQWizard *YQWizard::main_wizard = 0;
85 
86 YQWizard::YQWizard( YWidget * parent,
87  const std::string & backButtonLabel,
88  const std::string & abortButtonLabel,
89  const std::string & nextButtonLabel,
90  YWizardMode wizardMode )
91  : QSplitter( Qt::Horizontal, (QWidget *) parent->widgetRep() )
92 
93  , YWizard( parent,
94  backButtonLabel,
95  abortButtonLabel,
96  nextButtonLabel,
97  wizardMode )
98  , _backButtonLabel( backButtonLabel )
99  , _abortButtonLabel( abortButtonLabel )
100  , _nextButtonLabel( nextButtonLabel )
101  , _helpDlg ( NULL )
102 {
103  setObjectName( "wizard" );
104  setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
105 
106  QHBoxLayout* layout = new QHBoxLayout( this );
107  layout->setSpacing( 0 );
108  layout->setMargin( 0 );
109 
110  setWidgetRep( this );
111 
112  //either main wizard with `opt(`stepsEnabled), or sub-wizard of steps-enabled wizard
113  _stepsEnabled = ( (wizardMode == YWizardMode_Steps) || main_wizard );
114  _treeEnabled = (wizardMode == YWizardMode_Tree);
115 
116  _stepsRegistered = false;
117  _stepsDirty = false;
118  _direction = YQWizard::Forward;
119 
120  _sideBar = 0;
121  _stepsPanel = 0;
122  _helpButton = 0;
123  _stepsButton = 0;
124  _treeButton = 0;
125  _releaseNotesButton = 0;
126  _treePanel = 0;
127  _tree = 0;
128  _workArea = 0;
129  _clientArea = 0;
130  _menuBar = 0;
131  _dialogIcon = 0;
132  _dialogHeading = 0;
133  _contents = 0;
134  _backButton = 0;
135  _abortButton = 0;
136  _nextButton = 0;
137  _sendButtonEvents = true;
138  _contentsReplacePoint = 0;
139 
140  _previousWindowIcon = topLevelWidget()->windowIcon();
141 
142  YQUI::setTextdomain( TEXTDOMAIN );
143 
144  //layoutTitleBar( this );
145 
146  if( topLevelWidget()->windowTitle().isEmpty() )
147  {
148  topLevelWidget()->setWindowTitle ( YQUI::ui()->applicationTitle() );
149  QPixmap pixmap ( YUI::app()->applicationIcon().c_str() );
150  if ( !pixmap.isNull() )
151  setWindowIcon ( QIcon ( pixmap ) );
152  }
153 
154  layout->addLayout( layoutSideBar( this ) );
155  layout->addWidget( layoutWorkArea( this ) );
156 
157  setStretchFactor(indexOf(_sideBar),0);
158  setStretchFactor(indexOf(_workArea),1);
159 
160  /* If steps are enabled, we want to delay
161  the registering for after we have steps registered */
162  if ( !_stepsEnabled )
163  QY2Styler::styler()->registerWidget( this );
164 
165  if ( !main_wizard && _stepsEnabled )
166  {
167  main_wizard = this;
168  }
169  else if ( main_wizard )
170  {
171  copySteps( main_wizard );
173  }
174 
175 }
176 
177 
179 {
180  deleteSteps();
181  if ( this == main_wizard )
182  {
183  main_wizard = 0;
184  }
185  else if ( main_wizard )
186  {
187  //transfer the widget ratio to the main wizard
188  main_wizard->setSizes( sizes() );
189  }
190 
191  delete _helpDlg;
192 
193  QY2Styler::styler()->unregisterWidget( this );
194  topLevelWidget()->setWindowIcon( _previousWindowIcon );
195 }
196 
197 
199 {
200  return this != main_wizard;
201 }
202 
203 
204 void YQWizard::layoutTitleBar( QWidget * parent )
205 {
206  QFrame * titleBar = new QFrame( parent );
207  YUI_CHECK_NEW( titleBar );
208 
209  QHBoxLayout *layout = new QHBoxLayout( titleBar );
210  titleBar->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); // hor/vert
211 
212  //
213  // Left logo
214  //
215 
216  QLabel * left = new QLabel( titleBar );
217  layout->addWidget( left );
218  left->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
219  left->setObjectName( "titleBar-left" );
220 
221  //
222  // Center stretch space
223  //
224 
225  layout->addStretch( 10 );
226 
227 
228  //
229  // Right logo
230  //
231 
232  QLabel * right = new QLabel( titleBar );
233  YUI_CHECK_NEW( right );
234 
235  layout->addWidget( right );
236  right->setObjectName( "titleBar-right" );
237 }
238 
239 
240 QLayout *YQWizard::layoutSideBar( QWidget * parent )
241 {
242  _sideBar = new QStackedWidget( parent );
243  YUI_CHECK_NEW( _sideBar );
244  // _sideBar->setMinimumWidth( YQUI::ui()->defaultSize( YD_HORIZ ) / 5 );
245  _sideBar->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) ); // hor/vert
246  _sideBar->setObjectName( QString( "_sideBar-%1" ).arg( long( this ) ) );
247  _sideBar->installEventFilter( this );
248 
249  QVBoxLayout *vbox = new QVBoxLayout( );
250  vbox->addWidget( _sideBar );
251 
252  if ( _treeEnabled )
253  {
254  layoutTreePanel();
255  showTree();
256  }
257  else if ( _stepsEnabled )
258  {
259  layoutStepsPanel();
260  showSteps();
261  } else {
262  _sideBar->hide();
263  }
264 
265  return vbox;
266 }
267 
268 
269 void YQWizard::layoutStepsPanel()
270 {
271  // Steps
272  _stepsPanel = new QFrame( _sideBar );
273  _sideBar->addWidget( _stepsPanel );
274  _stepsPanel->setObjectName( "steps" );
275  QY2Styler::styler()->registerChildWidget( this, _stepsPanel );
276  _stepsPanel->setProperty( "class", "steps QFrame" );
277 
278  // Steps panel bottom buttons ("Help", "Release Notes")
279 
280  // Layouts for the buttons
281 
282  _releaseNotesButton = new QPushButton( _( "Release Notes..." ), _stepsPanel );
283  _releaseNotesButton->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ) ); // hor/vert
284 
285  connect( _releaseNotesButton, SIGNAL( clicked() ),
286  this, SLOT ( releaseNotesClicked() ) );
287 
288  _releaseNotesButton->hide(); // hidden until showReleaseNotesButton() is called
289 
290  _stepsDirty = true; // no layout yet
291 }
292 
293 
294 void YQWizard::addStep( const std::string & text, const std::string & id )
295 {
296  QString qId = fromUTF8( id );
297 
298  if ( _stepsIDs[ qId ] )
299  {
300  yuiError() << "Step ID \"" << id << "\" (\"" << text
301  <<"\") already used for \"" << _stepsIDs[ qId ]->name() <<"\""
302  << std::endl;
303  return;
304  }
305 
306  if ( !_stepsList.empty() && _stepsList.last()->name() == fromUTF8( text ) )
307  {
308  // Consecutive steps with the same name will be shown as one single step.
309  //
310  // Since steps are always added at the end of the list, it is
311  // sufficient to check the last step of the list. If the texts are the
312  // same, the other with the same text needs to get another (additional)
313  // ID to make sure setCurrentStep() works as it should.
314  _stepsList.last()->addID( qId );
315  }
316  else
317  {
318  _stepsList.append( new YQWizard::Step( fromUTF8( text ), qId ) );
319  _stepsDirty = true;
320  }
321 
322  _stepsIDs.insert( qId, _stepsList.last() );
323 
324  // make sure we always have a current step if we have steps
325  if ( _currentStepID.isNull() )
326  _currentStepID = qId;
327 }
328 
329 
330 void YQWizard::addStepHeading( const std::string & text )
331 {
332  _stepsList.append( new YQWizard::StepHeading( fromUTF8( text ) ) );
333  _stepsDirty = true;
334 }
335 
336 
338 {
339  if ( ! _stepsPanel )
340  return;
341 
342  yuiDebug() << "updateSteps" << std::endl;
343 
344  if ( !_stepsRegistered )
345  setUpdatesEnabled(false);
346 
347  // Create a grid layout for the steps
348  delete _stepsPanel->layout();
349  _stepsPanel->setMaximumWidth( 65000 );
350 
351  QVBoxLayout *_stepsVBox = new QVBoxLayout( _stepsPanel );
352 
353  QGridLayout *_stepsGrid = new QGridLayout( );
354  _stepsGrid->setObjectName( QString( "_stepsGrid_%1" ).arg( long( this ) ) );
355  YUI_CHECK_NEW( _stepsGrid );
356  _stepsVBox->addLayout( _stepsGrid );
357  _stepsGrid->setColumnMinimumWidth( 0, 10 );
358  _stepsGrid->setRowStretch( 0, 1 );
359  _stepsGrid->setRowStretch( 1, 1 );
360  _stepsGrid->setRowStretch( 2, 99 );
361 
362  const int statusCol = 1;
363  const int nameCol = 2;
364 
365  int row = 0;
366 
367  //
368  // Create widgets for all steps and step headings in the internal list
369  //
370 
371  for ( QList<Step*>::iterator i = _stepsList.begin(); i != _stepsList.end(); ++i)
372  {
373  YQWizard::Step * step = *i;
374 
375  step->deleteLabels();
376 
377  if ( step->isHeading() )
378  {
379  //
380  // Heading
381  //
382 
383  yuiDebug() << "Adding StepHeading \"" << step->name() << "\"" << std::endl;
384  QLabel * label = new QLabel( step->name(), _stepsPanel );
385  YUI_CHECK_NEW( label );
386  label->setObjectName( step->name() );
387  label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
388  label->setProperty( "class", "steps_heading" );
389 
390  step->setNameLabel( label );
391  _stepsGrid->addWidget( label,
392  row, statusCol,
393  1, nameCol - statusCol + 1);
394  }
395  else // No heading - ordinary step
396  {
397  //
398  // Step status
399  //
400 
401  yuiDebug() << "Adding Step \"" << step->name() << "\"" << std::endl;
402 
403  QLabel * statusLabel = new QLabel( _stepsPanel );
404  YUI_CHECK_NEW( statusLabel );
405 
406  step->setStatusLabel( statusLabel );
407  statusLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
408  _stepsGrid->addWidget( statusLabel, row, statusCol );
409 
410  //
411  // Step name
412  //
413 
414  QLabel * nameLabel = new QLabel( step->name(), _stepsPanel );
415  YUI_CHECK_NEW( nameLabel );
416  nameLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
417  nameLabel->setObjectName( step->name() );
418 
419  step->setNameLabel( nameLabel );
420  _stepsGrid->addWidget( nameLabel, row, nameCol );
421  }
422 
423  step->setStatus( Step::Todo );
424  row++;
425  }
426 
427  _stepsVBox->addStretch( 99 );
428  QVBoxLayout *rbl = new QVBoxLayout();
429  rbl->addWidget( _releaseNotesButton, 0, Qt::AlignCenter );
430 
431  _stepsVBox->addLayout( rbl );
432  _stepsVBox->addStretch( 29 );
433 
434  _stepsDirty = false;
435 
436  if ( !_stepsRegistered )
437  {
438  QY2Styler::styler()->registerWidget( this );
439  setUpdatesEnabled( true );
440  QY2Styler::styler()->updateRendering( this );
441  _stepsRegistered = true;
442  }
443 }
444 
445 
447 {
448  yuiDebug() << "steps dirty: " << _stepsDirty << std::endl;
449 
450  if ( _stepsDirty )
451  updateSteps();
452 
453  YQWizard::Step * currentStep = findStep( _currentStepID );
454  QList<YQWizard::Step*>::iterator step = _stepsList.begin();
455 
456  if ( currentStep )
457  {
458  // Set status icon and color for the current step
459  currentStep->setStatus( Step::Current );
460 
461  //
462  // Set all steps before the current to "done"
463  //
464 
465  while ( step != _stepsList.end() && *step != currentStep )
466  {
467  ( *step )->setStatus( Step::Done );
468  step++;
469  }
470 
471  // Skip the current step - continue with the step after it
472 
473  if ( step != _stepsList.end() )
474  step++;
475  }
476 
477  //
478  // Set all steps after the current to "to do"
479  //
480 
481  while ( step != _stepsList.end() )
482  {
483  ( *step )->setStatus( Step::Todo );
484  step++;
485  }
486 }
487 
488 
489 void YQWizard::setCurrentStep( const std::string & id )
490 {
491  yuiDebug() << "Setting current step to \"" << id << "\"" << std::endl;
492 
493  _currentStepID = fromUTF8( id );
495 }
496 
498 {
499  QList<Step*> _oldSteps = wizard->stepsList();
500 
501  if (_oldSteps.empty())
502  return;
503 
504  foreach( Step *oldStep, _oldSteps)
505  {
506  Step *newStep;
507 
508  if( !oldStep->isHeading() )
509  newStep = new Step( oldStep->name());
510  else
511  newStep = new StepHeading( oldStep->name());
512 
513  foreach( QString oneId, oldStep->id())
514  {
515  newStep->addID( oneId);
516  _stepsIDs.insert( oneId, newStep );
517  }
518 
519  newStep->setEnabled( oldStep->isEnabled());
520  _stepsList.append(newStep);
521 
522  }
523 
524  setCurrentStep( wizard->currentStep().toStdString() );
525  setSizes( main_wizard->sizes());
526 }
527 
528 
530 {
531  yuiDebug() << "Deleting steps" << std::endl;
532 
533  if ( _stepsPanel )
534  _stepsPanel->setFixedWidth( _stepsPanel->width() );
535 
536  qDeleteAll(_stepsList);
537  _stepsList.clear();
538  _stepsIDs.clear();
539  _currentStepID = QString::null;
540  _stepsDirty = true;
541 }
542 
543 
544 YQWizard::Step * YQWizard::findStep( const QString & id )
545 {
546  if ( id.isEmpty() )
547  return 0;
548 
549  return _stepsIDs[ id ];
550 }
551 
552 
553 void YQWizard::layoutTreePanel()
554 {
555  _treePanel = new QFrame( _sideBar );
556  YUI_CHECK_NEW( _treePanel );
557  QHBoxLayout *layout = new QHBoxLayout( _treePanel );
558  _sideBar->addWidget( _treePanel );
559 
560  QVBoxLayout * vbox = new QVBoxLayout();
561  YUI_CHECK_NEW( vbox );
562  layout->addLayout( vbox );
563 
564  // Selection tree
565 
566  _tree = new QY2ListView( _treePanel );
567  YUI_CHECK_NEW( _tree );
568  vbox->addWidget( _tree );
569 
570  _tree->header()->hide();
571  _tree->header()->setResizeMode( 0, QHeaderView::Stretch );
572 
573  _tree->setRootIsDecorated( true );
574  _tree->setSortByInsertionSequence( true );
575 
576  connect( _tree, SIGNAL( itemSelectionChanged ( void ) ),
577  this, SLOT ( treeSelectionChanged ( void ) ) );
578 
579  connect( _tree, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int ) ),
580  this, SLOT ( sendTreeEvent ( QTreeWidgetItem * ) ) );
581 
582 }
583 
584 
585 void YQWizard::addTreeItem( const std::string & parentID, const std::string & text, const std::string & id )
586 {
587  QString qId = fromUTF8( id );
588 
589  if ( ! _tree )
590  {
591  yuiError() << "YQWizard widget not created with `opt(`treeEnabled) !" << std::endl;
592  return;
593  }
594 
595  YQWizard::TreeItem * item = 0;
596  YQWizard::TreeItem * parent = 0;
597 
598  if ( ! parentID.empty() )
599  {
600  parent = findTreeItem( parentID );
601  }
602 
603  if ( parent )
604  {
605  item = new YQWizard::TreeItem( parent, fromUTF8( text ), qId );
606  YUI_CHECK_NEW( item );
607  }
608  else
609  {
610  item = new YQWizard::TreeItem( _tree, fromUTF8( text ), qId );
611  YUI_CHECK_NEW( item );
612  }
613 
614  if ( ! qId.isEmpty() )
615  _treeIDs.insert( qId, item );
616 }
617 
618 
619 
621 {
622  if ( _tree )
623  _tree->clear();
624 
625  _treeIDs.clear();
626 }
627 
628 
629 
630 YQWizard::TreeItem * YQWizard::findTreeItem( const std::string & id )
631 {
632  if ( id.empty() )
633  return 0;
634 
635  return _treeIDs[ fromUTF8( id ) ];
636 }
637 
638 
639 void YQWizard::selectTreeItem( const std::string & id )
640 {
641  if ( _tree )
642  {
643  YQWizard::TreeItem * item = findTreeItem( id );
644 
645  if ( item )
646  {
647  YQSignalBlocker sigBlocker( _tree );
648 
649  _tree->setCurrentItem(item);
650  _tree->scrollToItem(item);
651  }
652  }
653 }
654 
655 
656 void YQWizard::sendTreeEvent( QTreeWidgetItem * listViewItem )
657 {
658  if ( listViewItem )
659  {
660  YQWizard::TreeItem * item = dynamic_cast<YQWizard::TreeItem *> ( listViewItem );
661 
662  if ( item && ! item->id().isEmpty() )
663  sendEvent( toUTF8( item->id() ) );
664  }
665 }
666 
667 
669 { //FIXME is currentItem correct or selected.first
670  if ( _tree )
671  sendTreeEvent( _tree->currentItem() );
672 }
673 
674 
676 {
677  if ( _tree )
678  {
679  QTreeWidgetItem * sel = _tree->currentItem();
680 
681  if ( sel )
682  {
683  YQWizard::TreeItem * item = dynamic_cast<YQWizard::TreeItem *> (sel);
684 
685  if ( item && ! item->id().isEmpty() )
686  return toUTF8( item->id() );
687  }
688  }
689 
690  return std::string();
691 }
692 
693 
694 
695 QWidget *YQWizard::layoutWorkArea( QWidget * parent )
696 {
697  _workArea = new QFrame( parent );
698  _workArea->setObjectName( "work_area" );
699 
700  QY2Styler::styler()->registerChildWidget( this, _workArea );
701 
702  QVBoxLayout *vbox = new QVBoxLayout( _workArea );
703  YUI_CHECK_NEW( vbox );
704 
705  //
706  // Menu bar
707  //
708 
709  _menuBar = new QMenuBar( _workArea );
710  YUI_CHECK_NEW( _menuBar );
711 
712  _menuBar->hide(); // will be made visible when menus are added
713  vbox->addWidget( _menuBar );
714 
715 
716  QVBoxLayout *innerbox = new QVBoxLayout( _workArea );
717  YUI_CHECK_NEW( innerbox );
718 
719  innerbox->setMargin ( YQWidgetMargin );
720 
721  vbox->addLayout(innerbox);
722  vbox->setMargin( 0 );
723 
724 
725  //
726  // Dialog icon and heading
727  //
728 
729  QHBoxLayout * headingHBox = new QHBoxLayout();
730  YUI_CHECK_NEW( headingHBox );
731  //headingHBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); // hor/vert
732  innerbox->addLayout( headingHBox );
733 
734  _dialogIcon = new QLabel( _workArea );
735  YUI_CHECK_NEW( _dialogIcon );
736  headingHBox->addWidget( _dialogIcon );
737  _dialogIcon->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) ); // hor/vert
738  _dialogIcon->setObjectName( "DialogIcon" );
739 
740  _dialogHeading = new QLabel( _workArea );
741  YUI_CHECK_NEW( _dialogHeading );
742  headingHBox->addWidget( _dialogHeading );
743  _dialogHeading->setAlignment( Qt::AlignLeft );
744  _dialogHeading->setWordWrap( true );
745  _dialogHeading->setTextFormat( Qt::PlainText );
746  _dialogHeading->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); // hor/vert
747  _dialogHeading->setObjectName( "DialogHeading" );
748 
749 
750  //
751  // Client area (the part that belongs to the YCP application)
752  //
753 
754  layoutClientArea( _workArea );
755  innerbox->addWidget( _clientArea );
756 
757  //
758  // Button box
759  //
760 
761  QLayout *bb = layoutButtonBox( _workArea );
762  innerbox->addLayout( bb );
763 
764  return _workArea;
765 }
766 
767 
768 
769 void YQWizard::layoutClientArea( QWidget * parent )
770 {
771  _clientArea = new QFrame( parent );
772  YUI_CHECK_NEW( _clientArea );
773  _clientArea->setObjectName("_clientArea");
774  QVBoxLayout *layout = new QVBoxLayout( _clientArea );
775  layout->setMargin( 0 );
776 
777  //
778  // HVCenter for wizard contents
779  //
780 
781  _contents = new YQAlignment( this, _clientArea, YAlignCenter, YAlignCenter );
782  YUI_CHECK_NEW( _contents );
783  layout->addWidget( _contents );
784  _contents->QObject::setProperty( "class", "Contents" );
785 
786  _contents->setStretchable( YD_HORIZ, true );
787  _contents->setStretchable( YD_VERT, true );
788  _contents->installEventFilter( this );
789  _contents->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
790 
791  //
792  // Replace point for wizard contents
793  //
794 
795  _contentsReplacePoint = YUI::widgetFactory()->createReplacePoint( _contents );
796 
797  //
798  // Initial YEmpty widget contents of replace point
799  //
800 
801  YUI::widgetFactory()->createEmpty( _contentsReplacePoint );
802  _contentsReplacePoint->showChild();
803 
804 }
805 
806 
807 
808 QLayout *YQWizard::layoutButtonBox( QWidget * parent )
809 {
810  //
811  // QHBoxLayout for the buttons
812  //
813 
814  QHBoxLayout * hbox = new QHBoxLayout(); // parent, spacing
815  YUI_CHECK_NEW( hbox );
816 
817  hbox->setSpacing( 0 );
818  hbox->setMargin( 0 );
819 
820  // Help button - intentionally without keyboard shortcut
821  _helpButton = new QPushButton( _( "Help" ), parent );
822  YUI_CHECK_NEW( _helpButton );
823  _helpButton->setShortcut( Qt::Key_F1 );
824 
825  connect( _helpButton, SIGNAL( clicked() ),
826  this, SLOT ( showHelp() ) );
827 
828  hbox->addWidget( _helpButton );
829 
830  hbox->addStretch( 10 );
831 
832  //
833  // "Abort" button
834  //
835 
836  _abortButton = new YQWizardButton( this, parent, _abortButtonLabel );
837  YUI_CHECK_NEW( _abortButton );
838 
839  hbox->addWidget( (QWidget *) _abortButton->widgetRep() );
840  connect( _abortButton, SIGNAL( clicked() ),
841  this, SLOT ( slotAbortClicked() ) );
842 
843  hbox->addSpacing( 10 );
844 
845  //
846  // "Back" button
847  //
848 
849  _backButton = new YQWizardButton( this, parent, _backButtonLabel );
850  YUI_CHECK_NEW( _backButton );
851 
852  hbox->addWidget( (QWidget *) _backButton->widgetRep() );
853  connect( _backButton, SIGNAL( clicked() ),
854  this, SLOT ( slotBackClicked() ) );
855 
856  if ( _backButton->text().isEmpty() )
857  _backButton->hide();
858 
859  //
860  // "Next" button
861  //
862 
863  hbox->addSpacing( 5 );
864 
865  _nextButton = new YQWizardButton( this, parent, _nextButtonLabel );
866  YUI_CHECK_NEW( _nextButton );
867 
868  hbox->addWidget( (QWidget *) _nextButton->widgetRep() );
869  connect( _nextButton, SIGNAL( clicked() ),
870  this, SLOT ( slotNextClicked() ) );
871 
872  return hbox;
873 }
874 
875 
877 {
878  delete _backButton;
879  _backButton = 0;
880 
881  delete _abortButton;
882  _abortButton = 0;
883 
884  delete _nextButton;
885  _nextButton = 0;
886 }
887 
888 
889 void YQWizard::connectNotify ( const char * signal )
890 {
891  if ( QString( signal ).contains( "nextClicked()" ) )
892  {
893  yuiDebug() << "nextClicked connected, no longer directly sending button events" << std::endl;
894  _sendButtonEvents = false;
895  }
896 }
897 
898 
899 void YQWizard::disconnectNotify ( const char * signal )
900 {
901  if ( QString( signal ).contains( "nextClicked()" ) )
902  {
903  yuiDebug() << "nextClicked disconnected, directly sending button events again" << std::endl;
904  _sendButtonEvents = true;
905  }
906 }
907 
908 
909 void YQWizard::setDialogIcon( const std::string & iconName )
910 {
911  if ( _dialogIcon )
912  {
913  if ( ! iconName.empty() )
914  {
915  QPixmap icon( iconName.c_str() );
916 
917  if ( icon.isNull() )
918  yuiWarning() << "Couldn't load dialog icon \"" << iconName << "\"" << std::endl;
919  else
920  {
921  _dialogIcon->setPixmap( icon );
922  topLevelWidget()->setWindowIcon( icon );
923  }
924  }
925  else
926  {
927  _dialogIcon->clear();
928  topLevelWidget()->setWindowIcon( QIcon() );
929  }
930  }
931 }
932 
933 
934 void YQWizard::setDialogTitle( const std::string & titleText )
935 {
936  QString title = fromUTF8( titleText.c_str() );
937 
938  if ( !title.isEmpty() )
939  topLevelWidget()->setWindowTitle( YQUI::ui()->applicationTitle() + QString(" - ") + title );
940  else
941  topLevelWidget()->setWindowTitle( YQUI::ui()->applicationTitle() );
942 }
943 
944 
945 void YQWizard::setDialogHeading( const std::string & headingText )
946 {
947  if ( _dialogHeading )
948  {
949  if ( ! headingText.empty() )
950  _dialogHeading->setText( fromUTF8( headingText ) );
951  else
952  _dialogHeading->clear();
953  }
954 }
955 
956 string YQWizard::debugLabel() const
957 {
958  if ( _dialogHeading )
959  {
960  QString label = _dialogHeading->text();
961  label = label.simplified(); // Replace any embedded newline with a single blank
962 
963  if ( ! label.isEmpty() )
964  return toUTF8( label );
965  }
966 
967  return "untitled YQWizard";
968 }
969 
970 
971 void YQWizard::setHelpText( const std::string & helpText )
972 {
973  _qHelpText = fromUTF8( helpText );
974  _qHelpText.replace( "&product;", fromUTF8( YUI::app()->productName() ) );
975 }
976 
977 
979 {
980  emit backClicked();
981 
982  if ( _sendButtonEvents )
983  YQUI::ui()->sendEvent( new YWidgetEvent( _backButton, YEvent::Activated ) );
984 
985  _direction = YQWizard::Backward;
986 }
987 
988 
990 {
991  emit abortClicked();
992 
993  if ( _sendButtonEvents )
994  YQUI::ui()->sendEvent( new YWidgetEvent( _abortButton, YEvent::Activated ) );
995 }
996 
997 
999 {
1000  emit nextClicked();
1001 
1002  if ( _sendButtonEvents )
1003  YQUI::ui()->sendEvent( new YWidgetEvent( _nextButton, YEvent::Activated ) );
1004 
1005  _direction = YQWizard::Forward;
1006 }
1007 
1008 
1010 {
1011 
1012  if (!_helpDlg)
1013  _helpDlg = new QY2HelpDialog ( _qHelpText, NULL );
1014  else
1015  {
1016  _helpDlg->setHelpText( _qHelpText );
1017  _helpDlg->hide(); // workaround for icewm (see: bnc #397083)
1018  }
1019 
1020  _helpDlg->show();
1021  _helpDlg->raise();
1022  _helpDlg->activateWindow();
1023 }
1024 
1025 
1027 {
1028  YQUI::ui()->sendEvent( new YWidgetEvent( _nextButton, YEvent::Activated ) );
1029 
1030  if ( ! _releaseNotesButtonId.empty() )
1031  {
1032  yuiMilestone() << "Release Notes button clicked" << std::endl;
1033  sendEvent( _releaseNotesButtonId );
1034  }
1035 }
1036 
1037 
1039 {
1040  if ( _sideBar && _stepsPanel )
1041  {
1042  _sideBar->setCurrentWidget( _stepsPanel );
1043  }
1044 }
1045 
1046 
1048 {
1049  if ( _sideBar && _treePanel )
1050  {
1051  _sideBar->setCurrentWidget( _treePanel );
1052  }
1053 }
1054 
1055 
1056 void YQWizard::addMenu( const std::string & text,
1057  const std::string & id )
1058 {
1059  if ( _menuBar )
1060  {
1061  QMenu * menu = new QMenu( _menuBar );
1062  YUI_CHECK_NEW( menu );
1063 
1064  _menuIDs.insert( fromUTF8( id ), menu );
1065  _menuBar->addMenu( menu );
1066  menu->setTitle( fromUTF8( text ) );
1067 
1068  connect( menu, SIGNAL( triggered ( QAction * ) ),
1069  this, SLOT ( sendMenuEvent( QAction * ) ) );
1070 
1071  _menuBar->show();
1072  }
1073 }
1074 
1075 
1076 void YQWizard::addSubMenu( const std::string & parentMenuID,
1077  const std::string & text,
1078  const std::string & id )
1079 {
1080  QMenu* parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1081 
1082  if ( parentMenu )
1083  {
1084  QMenu * menu = new QMenu( _menuBar );
1085  YUI_CHECK_NEW( menu );
1086 
1087  _menuIDs.insert( fromUTF8( id ), menu );
1088  //FIXME parentMenu->insertItem( fromUTF8( text ), menu );
1089 
1090  connect( menu, SIGNAL( triggered ( QAction * ) ),
1091  this, SLOT ( sendMenuEvent( QAction * ) ) );
1092  }
1093  else
1094  {
1095  yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
1096  }
1097 }
1098 
1099 
1100 void YQWizard::addMenuEntry( const std::string & parentMenuID,
1101  const std::string & text,
1102  const std::string & idString )
1103 {
1104  QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1105 
1106  if ( parentMenu )
1107  {
1108 #if 0
1109  int id = _menuEntryIDs.size();
1110 #endif
1111  QAction *action;
1112  action = parentMenu->addAction( fromUTF8( text ) );
1113  _menuEntryIDs[ action ] = idString ;
1114 
1115  }
1116  else
1117  {
1118  yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
1119  }
1120 }
1121 
1122 
1123 void YQWizard::addMenuSeparator( const std::string & parentMenuID )
1124 {
1125  QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1126 
1127  if ( parentMenu )
1128  {
1129  parentMenu->addSeparator();
1130  }
1131  else
1132  {
1133  yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
1134  }
1135 }
1136 
1137 
1139 {
1140  if ( _menuBar )
1141  {
1142  _menuBar->hide();
1143  _menuBar->clear();
1144  _menuIDs.clear();
1145  _menuEntryIDs.clear();
1146  }
1147 }
1148 
1149 
1150 void YQWizard::sendMenuEvent( QAction *action )
1151 {
1152  if ( _menuEntryIDs.contains( action ) )
1153  {
1154  sendEvent( _menuEntryIDs[ action ] );
1155  }
1156  else
1157  {
1158  yuiError() << "Invalid menu ID " << std::endl;
1159  }
1160 }
1161 
1162 
1163 void YQWizard::sendEvent( const std::string & id )
1164 {
1165  YQUI::ui()->sendEvent( new YMenuEvent( id ) );
1166 }
1167 
1168 
1170 {
1171  return sizeHint().width();
1172 }
1173 
1174 
1176 {
1177  return sizeHint().height();
1178 }
1179 
1180 
1181 void YQWizard::setSize( int newWidth, int newHeight )
1182 {
1183  resize( newWidth, newHeight );
1184  resizeClientArea();
1185 }
1186 
1188 {
1189  QSize contentsRect = _clientArea->contentsRect().size();
1190  _contents->setSize( contentsRect.width(), contentsRect.height() );
1191 }
1192 
1193 bool YQWizard::eventFilter( QObject * obj, QEvent * ev )
1194 {
1195  if ( ev->type() == QEvent::Resize && obj == _contents )
1196  {
1197  resizeClientArea();
1198  return true; // Event handled
1199  }
1200 
1201  if ( ev->type() == QEvent::Resize && obj == _sideBar && main_wizard == this && _stepsPanel )
1202  {
1203  YQMainWinDock::mainWinDock()->setSideBarWidth( _sideBar->width() );
1204  return true; // Event handled
1205  }
1206 
1207  return QWidget::eventFilter( obj, ev );
1208 }
1209 
1210 
1211 void YQWizard::setButtonLabel( YPushButton * button, const std::string & newLabel )
1212 {
1213  button->setLabel( newLabel );
1214  YDialog::currentDialog()->checkShortcuts();
1215 
1216  YQWizardButton * wizardButton = dynamic_cast<YQWizardButton *> (button);
1217 
1218  if ( wizardButton ) {
1219  // QWizardButton only implements hide and show, not setVisible
1220  if ( newLabel.empty() )
1221  wizardButton->hide();
1222  else
1223  wizardButton->show();
1224  }
1225 }
1226 
1227 
1228 void YQWizard::showReleaseNotesButton( const std::string & label, const std::string & id )
1229 {
1230  return; // no longer supported!
1231 
1232  if ( ! _releaseNotesButton )
1233  {
1234  yuiError() << "NULL Release Notes button" << std::endl;
1235 
1236  if ( ! _stepsPanel )
1237  yuiError() << "This works only if there is a \"steps\" panel!" << std::endl;
1238 
1239  return;
1240  }
1241 
1242  // no way to check the shortcut, so strip it
1243  _releaseNotesButton->setText( fromUTF8( YShortcut::cleanShortcutString( label ) ) );
1244  _releaseNotesButtonId = id;
1245 
1246  _releaseNotesButton->show();
1247 }
1248 
1249 
1251 {
1252  if ( _releaseNotesButton && !_releaseNotesButton->isHidden() )
1253  _releaseNotesButton->hide();
1254 }
1255 
1256 
1258 {
1259  YQUI::setTextdomain( TEXTDOMAIN );
1260 
1261  if ( _helpButton )
1262  // "Help" button - intentionally without keyboard shortcut
1263  _helpButton->setText( _( "Help" ) );
1264 
1265  if ( _stepsButton )
1266  // "Steps" button - intentionally without keyboard shortcut
1267  _stepsButton->setText( _( "Steps" ) );
1268 
1269  if ( _treeButton )
1270  // "Tree" button - intentionally without keyboard shortcut
1271  _treeButton->setText( _( "Tree" ) );
1272 
1273  if ( _helpDlg )
1274  _helpDlg->retranslate();
1275 
1276 }
1277 
1278 
1279 void YQWizard::Step::deleteLabels()
1280 {
1281  delete _statusLabel;
1282  _statusLabel = 0;
1283  delete _nameLabel;
1284  _nameLabel = 0;
1285 }
1286 
1287 
1289 {
1290  deleteLabels();
1291 }
1292 
1293 
1295 {
1296  if ( !_statusLabel || !_nameLabel || _status == s )
1297  return;
1298 
1299  _status = s;
1300 
1301  if ( s == Todo )
1302  {
1303  _statusLabel->setProperty( "class", "todo-step-status QLabel" );
1304  _nameLabel->setProperty ( "class", "todo-step-name QLabel" );
1305  }
1306 
1307  if ( s == Done )
1308  {
1309  _statusLabel->setProperty( "class", "done-step-status QLabel" );
1310  _nameLabel->setProperty ( "class", "done-step-name QLabel" );
1311  }
1312 
1313  if ( s == Current )
1314  {
1315  _statusLabel->setProperty( "class", "current-step-status QLabel" );
1316  _nameLabel->setProperty ( "class", "current-step-name QLabel" );
1317  }
1318 
1319  _statusLabel->style()->unpolish( _statusLabel );
1320  _statusLabel->style()->polish( _statusLabel );
1321  _nameLabel->style()->unpolish( _nameLabel );
1322  _nameLabel->style()->polish( _nameLabel );
1323 }
1324 
1325 #include "YQWizard.moc"