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