libyui-qt  2.43.5
/usr/src/RPM/BUILD/libyui-qt-2.43.5/src/YQWizard.cc
00001 /*
00002   Copyright (C) 2000-2012 Novell, Inc
00003   This library is free software; you can redistribute it and/or modify
00004   it under the terms of the GNU Lesser General Public License as
00005   published by the Free Software Foundation; either version 2.1 of the
00006   License, or (at your option) version 3.0 of the License. This library
00007   is distributed in the hope that it will be useful, but WITHOUT ANY
00008   WARRANTY; without even the implied warranty of MERCHANTABILITY or
00009   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00010   License for more details. You should have received a copy of the GNU
00011   Lesser General Public License along with this library; if not, write
00012   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00013   Floor, Boston, MA 02110-1301 USA
00014 */
00015 
00016 
00017 /*-/
00018 
00019   File:         YQWizard.cc
00020 
00021   Author:       Stefan Hundhammer <sh@suse.de>
00022 
00023   Textdomain    "qt"
00024 
00025 /-*/
00026 
00027 #include "YQWizard.h"
00028 #define YUILogComponent "qt-wizard"
00029 #include <yui/YUILog.h>
00030 
00031 #include <string>
00032 #include <yui/YShortcut.h>
00033 
00034 #include <QDialog>
00035 #include <QSvgRenderer>
00036 #include <QPainter>
00037 #include <QStackedWidget>
00038 #include <qimage.h>
00039 #include <qlabel.h>
00040 #include <qlayout.h>
00041 #include <qmenubar.h>
00042 #include <qmenudata.h>
00043 #include <qobject.h>
00044 #include <qpixmap.h>
00045 #include <qpushbutton.h>
00046 #include <qregexp.h>
00047 #include <qtabwidget.h>
00048 #include <qtoolbutton.h>
00049 #include <QGraphicsDropShadowEffect>
00050 
00051 #include "QY2ListView.h"
00052 #include "QY2Styler.h"
00053 #include "QY2HelpDialog.h"
00054 #include <QGridLayout>
00055 #include <QHeaderView>
00056 #include <qevent.h>
00057 
00058 #include "utf8.h"
00059 #include "YQi18n.h"
00060 #include "YQUI.h"
00061 #include "YQApplication.h"
00062 #include "YQDialog.h"
00063 #include "YQAlignment.h"
00064 #include "YQReplacePoint.h"
00065 #include "YQEmpty.h"
00066 #include "YQLabel.h"
00067 #include "YQWizardButton.h"
00068 #include "YQWidgetFactory.h"
00069 #include "YQSignalBlocker.h"
00070 #include <yui/YEvent.h>
00071 #include "YQMainWinDock.h"
00072 
00073 
00074 using std::string;
00075 
00076 #ifdef TEXTDOMAIN
00077 #    undef TEXTDOMAIN
00078 #endif
00079 
00080 #define TEXTDOMAIN "qt"
00081 
00082 #define USE_ICON_ON_HELP_BUTTON         0
00083 
00084 YQWizard *YQWizard::main_wizard = 0;
00085 
00086 YQWizard::YQWizard( YWidget *           parent,
00087                     const std::string &         backButtonLabel,
00088                     const std::string &         abortButtonLabel,
00089                     const std::string &         nextButtonLabel,
00090                     YWizardMode         wizardMode )
00091     : QSplitter( Qt::Horizontal, (QWidget *) parent->widgetRep() )
00092 
00093     , YWizard( parent,
00094                backButtonLabel,
00095                abortButtonLabel,
00096                nextButtonLabel,
00097                wizardMode )
00098     , _backButtonLabel( backButtonLabel )
00099     , _abortButtonLabel( abortButtonLabel )
00100     , _nextButtonLabel( nextButtonLabel )
00101     , _helpDlg ( NULL )
00102 {
00103     setObjectName( "wizard" );
00104     setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
00105 
00106     QHBoxLayout* layout = new QHBoxLayout( this );
00107     layout->setSpacing( 0 );
00108     layout->setMargin( 0 );
00109 
00110     setWidgetRep( this );
00111 
00112     //either main wizard with `opt(`stepsEnabled), or sub-wizard of steps-enabled wizard
00113     _stepsEnabled = ( (wizardMode == YWizardMode_Steps) || main_wizard );
00114     _treeEnabled  = (wizardMode == YWizardMode_Tree);
00115 
00116     _stepsRegistered    = false;
00117     _stepsDirty         = false;
00118     _direction          = YQWizard::Forward;
00119 
00120     _sideBar            = 0;
00121     _stepsPanel         = 0;
00122     _helpButton         = 0;
00123     _stepsButton        = 0;
00124     _treeButton         = 0;
00125     _releaseNotesButton = 0;
00126     _treePanel          = 0;
00127     _tree               = 0;
00128     _workArea           = 0;
00129     _clientArea         = 0;
00130     _menuBar            = 0;
00131     _dialogIcon         = 0;
00132     _dialogHeading      = 0;
00133     _contents           = 0;
00134     _backButton         = 0;
00135     _abortButton        = 0;
00136     _nextButton         = 0;
00137     _sendButtonEvents   = true;
00138     _contentsReplacePoint = 0;
00139 
00140     _previousWindowIcon = topLevelWidget()->windowIcon();
00141 
00142     YQUI::setTextdomain( TEXTDOMAIN );
00143 
00144     //layoutTitleBar( this );
00145 
00146     if( topLevelWidget()->windowTitle().isEmpty() )
00147     {
00148         topLevelWidget()->setWindowTitle ( YQUI::ui()->applicationTitle() );
00149         QPixmap pixmap ( YUI::app()->applicationIcon().c_str() );
00150         if ( !pixmap.isNull() )
00151             setWindowIcon ( QIcon ( pixmap ) );
00152     }
00153 
00154     layout->addLayout( layoutSideBar( this ) );
00155     layout->addWidget( layoutWorkArea( this ) );
00156 
00157     setStretchFactor(indexOf(_sideBar),0);
00158     setStretchFactor(indexOf(_workArea),1);
00159 
00160     /* If steps are enabled, we want to delay
00161        the registering for after we have steps registered */
00162     if ( !_stepsEnabled )
00163         QY2Styler::styler()->registerWidget( this );
00164 
00165     if ( !main_wizard && _stepsEnabled )
00166     {
00167         main_wizard = this;
00168     }
00169     else if ( main_wizard )
00170     {
00171         copySteps( main_wizard );
00172         YQMainWinDock::mainWinDock()->resizeVisibleChild();
00173     }
00174 
00175 }
00176 
00177 
00178 YQWizard::~YQWizard()
00179 {
00180     deleteSteps();
00181     if ( this == main_wizard )
00182     {
00183         main_wizard = 0;
00184     }
00185     else if ( main_wizard )
00186     {
00187         //transfer the widget ratio to the main wizard
00188         main_wizard->setSizes( sizes() );
00189     }
00190 
00191     delete _helpDlg;
00192 
00193     QY2Styler::styler()->unregisterWidget( this );
00194     topLevelWidget()->setWindowIcon( _previousWindowIcon );
00195 }
00196 
00197 
00198 bool YQWizard::isSecondary() const
00199 {
00200     return this != main_wizard;
00201 }
00202 
00203 
00204 void YQWizard::layoutTitleBar( QWidget * parent )
00205 {
00206     QFrame * titleBar = new QFrame( parent );
00207     YUI_CHECK_NEW( titleBar );
00208 
00209     QHBoxLayout *layout = new QHBoxLayout( titleBar );
00210     titleBar->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); // hor/vert
00211 
00212     //
00213     // Left logo
00214     //
00215 
00216     QLabel * left = new QLabel( titleBar );
00217     layout->addWidget( left );
00218     left->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
00219     left->setObjectName( "titleBar-left" );
00220 
00221     //
00222     // Center stretch space
00223     //
00224 
00225     layout->addStretch( 10 );
00226 
00227 
00228     //
00229     // Right logo
00230     //
00231 
00232     QLabel * right = new QLabel( titleBar );
00233     YUI_CHECK_NEW( right );
00234 
00235     layout->addWidget( right );
00236     right->setObjectName( "titleBar-right" );
00237 }
00238 
00239 
00240 QLayout *YQWizard::layoutSideBar( QWidget * parent )
00241 {
00242     _sideBar = new QStackedWidget( parent );
00243     YUI_CHECK_NEW( _sideBar );
00244     // _sideBar->setMinimumWidth( YQUI::ui()->defaultSize( YD_HORIZ ) / 5 );
00245     _sideBar->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) ); // hor/vert
00246     _sideBar->setObjectName( QString( "_sideBar-%1" ).arg( long( this ) ) );
00247     _sideBar->installEventFilter( this );
00248 
00249     QVBoxLayout *vbox = new QVBoxLayout( );
00250     vbox->addWidget( _sideBar );
00251 
00252     if ( _treeEnabled )
00253     {
00254         layoutTreePanel();
00255         showTree();
00256     }
00257     else if ( _stepsEnabled )
00258     {
00259         layoutStepsPanel();
00260         showSteps();
00261     } else {
00262         _sideBar->hide();
00263     }
00264 
00265     return vbox;
00266 }
00267 
00268 
00269 void YQWizard::layoutStepsPanel()
00270 {
00271     // Steps
00272     _stepsPanel = new QFrame( _sideBar );
00273     _sideBar->addWidget( _stepsPanel );
00274     _stepsPanel->setObjectName( "steps" );
00275     QY2Styler::styler()->registerChildWidget( this, _stepsPanel );
00276     _stepsPanel->setProperty( "class", "steps QFrame" );
00277 
00278     // Steps panel bottom buttons ("Help", "Release Notes")
00279 
00280     // Layouts for the buttons
00281 
00282     _releaseNotesButton = new QPushButton( _( "Release Notes..." ), _stepsPanel );
00283     _releaseNotesButton->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ) ); // hor/vert
00284 
00285     connect( _releaseNotesButton,       SIGNAL( clicked()  ),
00286              this,                      SLOT  ( releaseNotesClicked() ) );
00287 
00288     _releaseNotesButton->hide();        // hidden until showReleaseNotesButton() is called
00289 
00290     _stepsDirty = true; // no layout yet
00291 }
00292 
00293 
00294 void YQWizard::addStep( const std::string & text, const std::string & id )
00295 {
00296     QString qId = fromUTF8( id );
00297 
00298     if ( _stepsIDs[ qId ] )
00299     {
00300         yuiError() << "Step ID \"" << id << "\" (\"" << text
00301                    <<"\") already used for \"" << _stepsIDs[ qId ]->name() <<"\""
00302                    << std::endl;
00303         return;
00304     }
00305 
00306     if ( !_stepsList.empty() && _stepsList.last()->name() == fromUTF8( text ) )
00307     {
00308         // Consecutive steps with the same name will be shown as one single step.
00309         //
00310         // Since steps are always added at the end of the list, it is
00311         // sufficient to check the last step of the list. If the texts are the
00312         // same, the other with the same text needs to get another (additional)
00313         // ID to make sure setCurrentStep() works as it should.
00314         _stepsList.last()->addID( qId );
00315     }
00316     else
00317     {
00318         _stepsList.append( new YQWizard::Step( fromUTF8( text ), qId ) );
00319         _stepsDirty = true;
00320     }
00321 
00322     _stepsIDs.insert( qId, _stepsList.last() );
00323 
00324     // make sure we always have a current step if we have steps
00325     if ( _currentStepID.isNull() )
00326         _currentStepID = qId;
00327 }
00328 
00329 
00330 void YQWizard::addStepHeading( const std::string & text )
00331 {
00332     _stepsList.append( new YQWizard::StepHeading( fromUTF8( text ) ) );
00333     _stepsDirty = true;
00334 }
00335 
00336 
00337 void YQWizard::updateSteps()
00338 {
00339     if ( ! _stepsPanel )
00340         return;
00341 
00342     yuiDebug() << "updateSteps" << std::endl;
00343 
00344     if ( !_stepsRegistered )
00345         setUpdatesEnabled(false);
00346 
00347     // Create a grid layout for the steps
00348     delete _stepsPanel->layout();
00349     _stepsPanel->setMaximumWidth( 65000 );
00350 
00351     QVBoxLayout *_stepsVBox = new QVBoxLayout( _stepsPanel );
00352 
00353     QGridLayout *_stepsGrid = new QGridLayout( );
00354     _stepsGrid->setObjectName( QString( "_stepsGrid_%1" ).arg(  long( this ) ) );
00355     YUI_CHECK_NEW( _stepsGrid );
00356     _stepsVBox->addLayout( _stepsGrid );
00357     _stepsGrid->setColumnMinimumWidth( 0, 10 );
00358     _stepsGrid->setRowStretch( 0, 1 );
00359     _stepsGrid->setRowStretch( 1, 1 );
00360     _stepsGrid->setRowStretch( 2, 99 );
00361 
00362     const int statusCol = 1;
00363     const int nameCol   = 2;
00364 
00365     int row = 0;
00366 
00367     //
00368     // Create widgets for all steps and step headings in the internal list
00369     //
00370 
00371     for ( QList<Step*>::iterator i = _stepsList.begin(); i != _stepsList.end(); ++i)
00372     {
00373         YQWizard::Step * step = *i;
00374 
00375         step->deleteLabels();
00376 
00377         if ( step->isHeading() )
00378         {
00379             //
00380             // Heading
00381             //
00382 
00383             yuiDebug() << "Adding StepHeading \"" << step->name() << "\"" << std::endl;
00384             QLabel * label = new QLabel( step->name(), _stepsPanel );
00385             YUI_CHECK_NEW( label );
00386             label->setObjectName( step->name() );
00387             label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
00388             label->setProperty( "class", "steps_heading" );
00389 
00390             step->setNameLabel( label );
00391             _stepsGrid->addWidget( label,
00392                                    row, statusCol,
00393                                    1, nameCol - statusCol + 1);
00394         }
00395         else    // No heading - ordinary step
00396         {
00397             //
00398             // Step status
00399             //
00400 
00401             yuiDebug() << "Adding Step \"" << step->name() << "\"" << std::endl;
00402 
00403             QLabel * statusLabel = new QLabel( _stepsPanel );
00404             YUI_CHECK_NEW( statusLabel );
00405 
00406             step->setStatusLabel( statusLabel );
00407             statusLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
00408             _stepsGrid->addWidget( statusLabel, row, statusCol );
00409 
00410             //
00411             // Step name
00412             //
00413 
00414             QLabel * nameLabel = new QLabel( step->name(), _stepsPanel );
00415             YUI_CHECK_NEW( nameLabel );
00416             nameLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
00417             nameLabel->setObjectName( step->name() );
00418 
00419             step->setNameLabel( nameLabel );
00420             _stepsGrid->addWidget( nameLabel, row, nameCol );
00421         }
00422 
00423         step->setStatus( Step::Todo );
00424         row++;
00425     }
00426 
00427     _stepsVBox->addStretch( 99 );
00428     QVBoxLayout *rbl = new QVBoxLayout();
00429     rbl->addWidget( _releaseNotesButton, 0, Qt::AlignCenter );
00430 
00431     _stepsVBox->addLayout( rbl );
00432     _stepsVBox->addStretch( 29 );
00433 
00434     _stepsDirty = false;
00435 
00436     if ( !_stepsRegistered )
00437     {
00438         QY2Styler::styler()->registerWidget( this );
00439         setUpdatesEnabled( true );
00440         QY2Styler::styler()->updateRendering( this );
00441         _stepsRegistered = true;
00442     }
00443 }
00444 
00445 
00446 void YQWizard::updateStepStates()
00447 {
00448     yuiDebug() << "steps dirty: " << _stepsDirty << std::endl;
00449 
00450     if ( _stepsDirty )
00451         updateSteps();
00452 
00453     YQWizard::Step * currentStep = findStep( _currentStepID );
00454     QList<YQWizard::Step*>::iterator step = _stepsList.begin();
00455 
00456     if ( currentStep )
00457     {
00458         // Set status icon and color for the current step
00459         currentStep->setStatus( Step::Current );
00460 
00461         //
00462         // Set all steps before the current to "done"
00463         //
00464 
00465         while ( step != _stepsList.end() && *step != currentStep )
00466         {
00467             ( *step )->setStatus( Step::Done );
00468             step++;
00469         }
00470 
00471         // Skip the current step - continue with the step after it
00472 
00473         if ( step != _stepsList.end() )
00474             step++;
00475     }
00476 
00477     //
00478     // Set all steps after the current to "to do"
00479     //
00480 
00481     while ( step != _stepsList.end() )
00482     {
00483         ( *step )->setStatus( Step::Todo );
00484         step++;
00485     }
00486 }
00487 
00488 
00489 void YQWizard::setCurrentStep( const std::string & id )
00490 {
00491     yuiDebug() << "Setting current step to \"" << id << "\"" << std::endl;
00492 
00493     _currentStepID = fromUTF8( id );
00494     updateStepStates();
00495 }
00496 
00497 void YQWizard::copySteps( YQWizard *wizard)
00498 {
00499     QList<Step*> _oldSteps = wizard->stepsList();
00500 
00501     if (_oldSteps.empty())
00502         return;
00503 
00504     foreach( Step *oldStep, _oldSteps)
00505     {
00506         Step *newStep;
00507 
00508         if( !oldStep->isHeading() )
00509             newStep = new Step( oldStep->name());
00510         else
00511             newStep = new StepHeading( oldStep->name());
00512 
00513         foreach( QString oneId, oldStep->id())
00514         {
00515             newStep->addID( oneId);
00516             _stepsIDs.insert( oneId, newStep );
00517         }
00518 
00519         newStep->setEnabled( oldStep->isEnabled());
00520         _stepsList.append(newStep);
00521 
00522     }
00523 
00524     setCurrentStep(  wizard->currentStep().toStdString() );
00525     setSizes( main_wizard->sizes());
00526 }
00527 
00528 
00529 void YQWizard::deleteSteps()
00530 {
00531     yuiDebug() << "Deleting steps" << std::endl;
00532 
00533     if ( _stepsPanel )
00534         _stepsPanel->setFixedWidth( _stepsPanel->width() );
00535 
00536     qDeleteAll(_stepsList);
00537     _stepsList.clear();
00538     _stepsIDs.clear();
00539     _currentStepID = QString::null;
00540     _stepsDirty = true;
00541 }
00542 
00543 
00544 YQWizard::Step * YQWizard::findStep( const QString & id )
00545 {
00546     if ( id.isEmpty() )
00547         return 0;
00548 
00549     return _stepsIDs[ id ];
00550 }
00551 
00552 
00553 void YQWizard::layoutTreePanel()
00554 {
00555     _treePanel = new QFrame( _sideBar );
00556     YUI_CHECK_NEW( _treePanel );
00557     QHBoxLayout *layout = new QHBoxLayout( _treePanel );
00558     _sideBar->addWidget( _treePanel );
00559 
00560     QVBoxLayout * vbox = new QVBoxLayout();
00561     YUI_CHECK_NEW( vbox );
00562     layout->addLayout( vbox );
00563 
00564     // Selection tree
00565 
00566     _tree = new QY2ListView( _treePanel );
00567     YUI_CHECK_NEW( _tree );
00568     vbox->addWidget( _tree );
00569 
00570     _tree->header()->hide();
00571     _tree->header()->setResizeMode( 0, QHeaderView::Stretch );
00572 
00573     _tree->setRootIsDecorated( true );
00574     _tree->setSortByInsertionSequence( true );
00575 
00576     connect( _tree,     SIGNAL( itemSelectionChanged    ( void ) ),
00577              this,      SLOT  ( treeSelectionChanged    ( void ) ) );
00578 
00579     connect( _tree,     SIGNAL( itemDoubleClicked       ( QTreeWidgetItem *, int ) ),
00580              this,      SLOT  ( sendTreeEvent           ( QTreeWidgetItem *      ) ) );
00581 
00582 }
00583 
00584 
00585 void YQWizard::addTreeItem( const std::string & parentID, const std::string & text, const std::string & id )
00586 {
00587     QString qId = fromUTF8( id );
00588 
00589     if ( ! _tree )
00590     {
00591         yuiError() << "YQWizard widget not created with `opt(`treeEnabled) !" << std::endl;
00592         return;
00593     }
00594 
00595     YQWizard::TreeItem * item   = 0;
00596     YQWizard::TreeItem * parent = 0;
00597 
00598     if ( ! parentID.empty() )
00599     {
00600         parent = findTreeItem( parentID );
00601     }
00602 
00603     if ( parent )
00604     {
00605         item = new YQWizard::TreeItem( parent, fromUTF8( text ), qId );
00606         YUI_CHECK_NEW( item );
00607     }
00608     else
00609     {
00610         item = new YQWizard::TreeItem( _tree, fromUTF8( text ), qId );
00611         YUI_CHECK_NEW( item );
00612     }
00613 
00614     if ( ! qId.isEmpty() )
00615         _treeIDs.insert( qId, item );
00616 }
00617 
00618 
00619 
00620 void YQWizard::deleteTreeItems()
00621 {
00622     if ( _tree )
00623         _tree->clear();
00624 
00625     _treeIDs.clear();
00626 }
00627 
00628 
00629 
00630 YQWizard::TreeItem * YQWizard::findTreeItem( const std::string & id )
00631 {
00632     if ( id.empty() )
00633         return 0;
00634 
00635     return _treeIDs[ fromUTF8( id ) ];
00636 }
00637 
00638 
00639 void YQWizard::selectTreeItem( const std::string & id )
00640 {
00641     if ( _tree )
00642     {
00643         YQWizard::TreeItem * item = findTreeItem( id );
00644 
00645         if ( item )
00646         {
00647             YQSignalBlocker sigBlocker( _tree );
00648 
00649       _tree->setCurrentItem(item);
00650             _tree->scrollToItem(item);
00651         }
00652     }
00653 }
00654 
00655 
00656 void YQWizard::sendTreeEvent( QTreeWidgetItem * listViewItem )
00657 {
00658     if ( listViewItem )
00659     {
00660         YQWizard::TreeItem * item = dynamic_cast<YQWizard::TreeItem *> ( listViewItem );
00661 
00662         if ( item && ! item->id().isEmpty() )
00663             sendEvent( toUTF8( item->id() ) );
00664     }
00665 }
00666 
00667 
00668 void YQWizard::treeSelectionChanged()
00669 { //FIXME is currentItem correct or selected.first
00670     if ( _tree )
00671         sendTreeEvent( _tree->currentItem() );
00672 }
00673 
00674 
00675 string YQWizard::currentTreeSelection()
00676 {
00677     if ( _tree )
00678     {
00679         QTreeWidgetItem * sel = _tree->currentItem();
00680 
00681         if ( sel )
00682         {
00683             YQWizard::TreeItem * item = dynamic_cast<YQWizard::TreeItem *> (sel);
00684 
00685             if ( item && ! item->id().isEmpty() )
00686                 return toUTF8( item->id() );
00687         }
00688     }
00689 
00690     return std::string();
00691 }
00692 
00693 
00694 
00695 QWidget *YQWizard::layoutWorkArea( QWidget * parent )
00696 {
00697     _workArea = new QFrame( parent );
00698     _workArea->setObjectName( "work_area" );
00699 
00700     QY2Styler::styler()->registerChildWidget( this, _workArea );
00701 
00702     QVBoxLayout *vbox = new QVBoxLayout( _workArea );
00703     YUI_CHECK_NEW( vbox );
00704 
00705     //
00706     // Menu bar
00707     //
00708 
00709     _menuBar = new QMenuBar( _workArea );
00710     YUI_CHECK_NEW( _menuBar );
00711 
00712     _menuBar->hide(); // will be made visible when menus are added
00713     vbox->addWidget( _menuBar );
00714 
00715 
00716     QVBoxLayout *innerbox = new QVBoxLayout( _workArea );
00717     YUI_CHECK_NEW( innerbox );
00718 
00719     innerbox->setMargin ( YQWidgetMargin  );
00720 
00721     vbox->addLayout(innerbox);
00722     vbox->setMargin( 0 );
00723 
00724 
00725     //
00726     // Dialog icon and heading
00727     //
00728 
00729     QHBoxLayout * headingHBox = new QHBoxLayout();
00730     YUI_CHECK_NEW( headingHBox );
00731     //headingHBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); // hor/vert
00732     innerbox->addLayout( headingHBox );
00733 
00734     _dialogIcon = new QLabel( _workArea );
00735     YUI_CHECK_NEW( _dialogIcon );
00736     headingHBox->addWidget( _dialogIcon );
00737     _dialogIcon->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) ); // hor/vert
00738     _dialogIcon->setObjectName( "DialogIcon" );
00739 
00740     _dialogHeading = new QLabel( _workArea );
00741     YUI_CHECK_NEW( _dialogHeading );
00742     headingHBox->addWidget( _dialogHeading );
00743     _dialogHeading->setAlignment( Qt::AlignLeft );
00744     _dialogHeading->setWordWrap( true );
00745     _dialogHeading->setTextFormat( Qt::PlainText );
00746     _dialogHeading->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); // hor/vert
00747     _dialogHeading->setObjectName( "DialogHeading" );
00748 
00749 
00750     //
00751     // Client area (the part that belongs to the YCP application)
00752     //
00753 
00754     layoutClientArea( _workArea );
00755     innerbox->addWidget( _clientArea );
00756 
00757     //
00758     // Button box
00759     //
00760 
00761     QLayout *bb = layoutButtonBox( _workArea );
00762     innerbox->addLayout( bb );
00763 
00764     return _workArea;
00765 }
00766 
00767 
00768 
00769 void YQWizard::layoutClientArea( QWidget * parent )
00770 {
00771     _clientArea = new QFrame( parent );
00772     YUI_CHECK_NEW( _clientArea );
00773     _clientArea->setObjectName("_clientArea");
00774     QVBoxLayout *layout = new QVBoxLayout( _clientArea );
00775     layout->setMargin( 0 );
00776 
00777     //
00778     // HVCenter for wizard contents
00779     //
00780 
00781     _contents = new YQAlignment( this, _clientArea, YAlignCenter, YAlignCenter );
00782     YUI_CHECK_NEW( _contents );
00783     layout->addWidget( _contents );
00784     _contents->QObject::setProperty( "class", "Contents" );
00785 
00786     _contents->setStretchable( YD_HORIZ, true );
00787     _contents->setStretchable( YD_VERT,  true );
00788     _contents->installEventFilter( this );
00789     _contents->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
00790 
00791     //
00792     // Replace point for wizard contents
00793     //
00794 
00795     _contentsReplacePoint = YUI::widgetFactory()->createReplacePoint( _contents );
00796 
00797     //
00798     // Initial YEmpty widget contents of replace point
00799     //
00800 
00801     YUI::widgetFactory()->createEmpty( _contentsReplacePoint );
00802     _contentsReplacePoint->showChild();
00803 
00804 }
00805 
00806 
00807 
00808 QLayout *YQWizard::layoutButtonBox( QWidget * parent )
00809 {
00810     //
00811     // QHBoxLayout for the buttons
00812     //
00813 
00814     QHBoxLayout * hbox = new QHBoxLayout();             // parent, spacing
00815     YUI_CHECK_NEW( hbox );
00816 
00817     hbox->setSpacing( 0 );
00818     hbox->setMargin( 0 );
00819 
00820     // Help button - intentionally without keyboard shortcut
00821     _helpButton = new QPushButton( _( "Help" ), parent );
00822     YUI_CHECK_NEW( _helpButton );
00823     _helpButton->setShortcut( Qt::Key_F1 );
00824 
00825     connect( _helpButton, SIGNAL( clicked()  ),
00826              this,        SLOT  ( showHelp() ) );
00827 
00828     hbox->addWidget( _helpButton );
00829 
00830     hbox->addStretch( 10 );
00831 
00832     //
00833     // "Abort" button
00834     //
00835 
00836     _abortButton = new YQWizardButton( this, parent, _abortButtonLabel );
00837     YUI_CHECK_NEW( _abortButton );
00838 
00839     hbox->addWidget( (QWidget *) _abortButton->widgetRep() );
00840     connect( _abortButton,      SIGNAL( clicked()               ),
00841              this,              SLOT  ( slotAbortClicked()      ) );
00842 
00843     hbox->addSpacing( 10 );
00844 
00845     //
00846     // "Back" button
00847     //
00848 
00849     _backButton  = new YQWizardButton( this, parent, _backButtonLabel );
00850     YUI_CHECK_NEW( _backButton );
00851 
00852     hbox->addWidget( (QWidget *) _backButton->widgetRep() );
00853     connect( _backButton,       SIGNAL( clicked()               ),
00854              this,              SLOT  ( slotBackClicked()       ) );
00855 
00856     if ( _backButton->text().isEmpty() )
00857         _backButton->hide();
00858 
00859     //
00860     // "Next" button
00861     //
00862 
00863     hbox->addSpacing( 5 );
00864 
00865     _nextButton  = new YQWizardButton( this, parent, _nextButtonLabel );
00866     YUI_CHECK_NEW( _nextButton );
00867 
00868     hbox->addWidget( (QWidget *) _nextButton->widgetRep() );
00869     connect( _nextButton,       SIGNAL( clicked()               ),
00870              this,              SLOT  ( slotNextClicked()       ) );
00871 
00872     return hbox;
00873 }
00874 
00875 
00876 void YQWizard::destroyButtons()
00877 {
00878     delete _backButton;
00879     _backButton = 0;
00880 
00881     delete _abortButton;
00882     _abortButton = 0;
00883 
00884     delete _nextButton;
00885     _nextButton = 0;
00886 }
00887 
00888 
00889 void YQWizard::connectNotify ( const char * signal )
00890 {
00891     if ( QString( signal ).contains( "nextClicked()" ) )
00892     {
00893         yuiDebug() << "nextClicked connected, no longer directly sending button events" << std::endl;
00894         _sendButtonEvents = false;
00895     }
00896 }
00897 
00898 
00899 void YQWizard::disconnectNotify ( const char * signal )
00900 {
00901     if ( QString( signal ).contains( "nextClicked()" ) )
00902     {
00903         yuiDebug() << "nextClicked disconnected, directly sending button events again" << std::endl;
00904         _sendButtonEvents = true;
00905     }
00906 }
00907 
00908 
00909 void YQWizard::setDialogIcon( const std::string & iconName )
00910 {
00911     if ( _dialogIcon )
00912     {
00913         if ( ! iconName.empty() )
00914         {
00915             QPixmap icon( iconName.c_str() );
00916 
00917             if ( icon.isNull() )
00918                 yuiWarning() << "Couldn't load dialog icon \"" << iconName << "\"" << std::endl;
00919             else
00920             {
00921                 _dialogIcon->setPixmap( icon );
00922                 topLevelWidget()->setWindowIcon( icon );
00923             }
00924         }
00925         else
00926         {
00927             _dialogIcon->clear();
00928             topLevelWidget()->setWindowIcon( QIcon() );
00929         }
00930     }
00931 }
00932 
00933 
00934 void YQWizard::setDialogTitle( const std::string & titleText )
00935 {
00936     QString title = fromUTF8( titleText.c_str() );
00937 
00938     if ( !title.isEmpty() )
00939         topLevelWidget()->setWindowTitle( YQUI::ui()->applicationTitle() + QString(" - ") + title  );
00940     else
00941         topLevelWidget()->setWindowTitle( YQUI::ui()->applicationTitle() );
00942 }
00943 
00944 
00945 void YQWizard::setDialogHeading( const std::string & headingText )
00946 {
00947     if ( _dialogHeading )
00948     {
00949         if ( ! headingText.empty() )
00950             _dialogHeading->setText( fromUTF8( headingText ) );
00951         else
00952             _dialogHeading->clear();
00953     }
00954 }
00955 
00956 string YQWizard::debugLabel() const
00957 {
00958     if ( _dialogHeading )
00959     {
00960         QString label = _dialogHeading->text();
00961         label = label.simplified(); // Replace any embedded newline with a single blank
00962 
00963         if ( ! label.isEmpty() )
00964             return toUTF8( label );
00965     }
00966 
00967     return "untitled YQWizard";
00968 }
00969 
00970 
00971 void YQWizard::setHelpText( const std::string & helpText )
00972 {
00973     _qHelpText = fromUTF8( helpText );
00974     _qHelpText.replace( "&product;", fromUTF8( YUI::app()->productName() ) );
00975 }
00976 
00977 
00978 void YQWizard::slotBackClicked()
00979 {
00980     emit backClicked();
00981 
00982     if ( _sendButtonEvents )
00983         YQUI::ui()->sendEvent( new YWidgetEvent( _backButton, YEvent::Activated ) );
00984 
00985     _direction = YQWizard::Backward;
00986 }
00987 
00988 
00989 void YQWizard::slotAbortClicked()
00990 {
00991     emit abortClicked();
00992 
00993     if ( _sendButtonEvents )
00994         YQUI::ui()->sendEvent( new YWidgetEvent( _abortButton, YEvent::Activated ) );
00995 }
00996 
00997 
00998 void YQWizard::slotNextClicked()
00999 {
01000     emit nextClicked();
01001 
01002     if ( _sendButtonEvents )
01003         YQUI::ui()->sendEvent( new YWidgetEvent( _nextButton, YEvent::Activated ) );
01004 
01005     _direction = YQWizard::Forward;
01006 }
01007 
01008 
01009 void YQWizard::showHelp()
01010 {
01011 
01012     if (!_helpDlg)
01013         _helpDlg = new QY2HelpDialog ( _qHelpText, NULL );
01014     else
01015     {
01016         _helpDlg->setHelpText( _qHelpText );
01017         _helpDlg->hide(); // workaround for icewm (see: bnc #397083)
01018     }
01019 
01020     _helpDlg->show();
01021     _helpDlg->raise();
01022     _helpDlg->activateWindow();
01023 }
01024 
01025 
01026 void YQWizard::releaseNotesClicked()
01027 {
01028     YQUI::ui()->sendEvent( new YWidgetEvent( _nextButton, YEvent::Activated ) );
01029 
01030     if ( ! _releaseNotesButtonId.empty() )
01031     {
01032         yuiMilestone() << "Release Notes button clicked" << std::endl;
01033         sendEvent( _releaseNotesButtonId );
01034     }
01035 }
01036 
01037 
01038 void YQWizard::showSteps()
01039 {
01040     if ( _sideBar && _stepsPanel )
01041     {
01042         _sideBar->setCurrentWidget( _stepsPanel );
01043     }
01044 }
01045 
01046 
01047 void YQWizard::showTree()
01048 {
01049     if ( _sideBar && _treePanel )
01050     {
01051         _sideBar->setCurrentWidget( _treePanel );
01052     }
01053 }
01054 
01055 
01056 void YQWizard::addMenu( const std::string & text,
01057                         const std::string & id )
01058 {
01059     if ( _menuBar )
01060     {
01061         QMenu * menu = new QMenu( _menuBar );
01062         YUI_CHECK_NEW( menu );
01063 
01064         _menuIDs.insert( fromUTF8( id ), menu );
01065         _menuBar->addMenu( menu );
01066         menu->setTitle( fromUTF8( text ) );
01067 
01068         connect( menu, SIGNAL( triggered    ( QAction * ) ),
01069                  this, SLOT  ( sendMenuEvent( QAction * ) ) );
01070 
01071         _menuBar->show();
01072     }
01073 }
01074 
01075 
01076 void YQWizard::addSubMenu( const std::string & parentMenuID,
01077                            const std::string & text,
01078                            const std::string & id )
01079 {
01080     QMenu* parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
01081 
01082     if ( parentMenu )
01083     {
01084         QMenu * menu = new QMenu( _menuBar );
01085         YUI_CHECK_NEW( menu );
01086 
01087         _menuIDs.insert( fromUTF8( id ), menu );
01088         //FIXME parentMenu->insertItem( fromUTF8( text ), menu );
01089 
01090         connect( menu, SIGNAL( triggered    ( QAction * ) ),
01091                  this, SLOT  ( sendMenuEvent( QAction * ) ) );
01092     }
01093     else
01094     {
01095         yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
01096     }
01097 }
01098 
01099 
01100 void YQWizard::addMenuEntry( const std::string & parentMenuID,
01101                              const std::string & text,
01102                              const std::string & idString )
01103 {
01104     QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
01105 
01106     if ( parentMenu )
01107     {
01108 #if 0
01109         int id = _menuEntryIDs.size();
01110 #endif
01111         QAction *action;
01112         action = parentMenu->addAction( fromUTF8( text ) );
01113         _menuEntryIDs[ action ] = idString ;
01114 
01115     }
01116     else
01117     {
01118         yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
01119     }
01120 }
01121 
01122 
01123 void YQWizard::addMenuSeparator( const std::string & parentMenuID )
01124 {
01125     QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
01126 
01127     if ( parentMenu )
01128     {
01129         parentMenu->addSeparator();
01130     }
01131     else
01132     {
01133         yuiError() << "Can't find menu with ID " << parentMenuID << std::endl;
01134     }
01135 }
01136 
01137 
01138 void YQWizard::deleteMenus()
01139 {
01140     if ( _menuBar )
01141     {
01142         _menuBar->hide();
01143         _menuBar->clear();
01144         _menuIDs.clear();
01145         _menuEntryIDs.clear();
01146     }
01147 }
01148 
01149 
01150 void YQWizard::sendMenuEvent( QAction *action )
01151 {
01152     if (  _menuEntryIDs.contains( action ) )
01153     {
01154         sendEvent( _menuEntryIDs[ action ] );
01155     }
01156     else
01157     {
01158         yuiError() << "Invalid menu ID " <<  std::endl;
01159     }
01160 }
01161 
01162 
01163 void YQWizard::sendEvent( const std::string & id )
01164 {
01165     YQUI::ui()->sendEvent( new YMenuEvent( id ) );
01166 }
01167 
01168 
01169 int YQWizard::preferredWidth()
01170 {
01171     return sizeHint().width();
01172 }
01173 
01174 
01175 int YQWizard::preferredHeight()
01176 {
01177     return sizeHint().height();
01178 }
01179 
01180 
01181 void YQWizard::setSize( int newWidth, int newHeight )
01182 {
01183     resize( newWidth, newHeight );
01184     resizeClientArea();
01185 }
01186 
01187 void YQWizard::resizeClientArea()
01188 {
01189     QSize contentsRect = _clientArea->contentsRect().size();
01190     _contents->setSize( contentsRect.width(), contentsRect.height() );
01191 }
01192 
01193 bool YQWizard::eventFilter( QObject * obj, QEvent * ev )
01194 {
01195     if ( ev->type() == QEvent::Resize && obj == _contents )
01196     {
01197         resizeClientArea();
01198         return true;            // Event handled
01199     }
01200 
01201     if ( ev->type() == QEvent::Resize && obj == _sideBar && main_wizard == this && _stepsPanel )
01202     {
01203         YQMainWinDock::mainWinDock()->setSideBarWidth( _sideBar->width() );
01204         return true;            // Event handled
01205     }
01206 
01207     return QWidget::eventFilter( obj, ev );
01208 }
01209 
01210 
01211 void YQWizard::setButtonLabel( YPushButton * button, const std::string & newLabel )
01212 {
01213     button->setLabel( newLabel );
01214     YDialog::currentDialog()->checkShortcuts();
01215 
01216     YQWizardButton * wizardButton = dynamic_cast<YQWizardButton *> (button);
01217 
01218     if ( wizardButton ) {
01219         // QWizardButton only implements hide and show, not setVisible
01220         if ( newLabel.empty() )
01221             wizardButton->hide();
01222         else
01223             wizardButton->show();
01224     }
01225 }
01226 
01227 
01228 void YQWizard::showReleaseNotesButton( const std::string & label, const std::string & id )
01229 {
01230     return; // no longer supported!
01231 
01232     if ( ! _releaseNotesButton )
01233     {
01234         yuiError() << "NULL Release Notes button" << std::endl;
01235 
01236         if ( ! _stepsPanel )
01237             yuiError() << "This works only if there is a \"steps\" panel!" << std::endl;
01238 
01239         return;
01240     }
01241 
01242     // no way to check the shortcut, so strip it
01243     _releaseNotesButton->setText( fromUTF8( YShortcut::cleanShortcutString( label ) ) );
01244     _releaseNotesButtonId = id;
01245 
01246     _releaseNotesButton->show();
01247 }
01248 
01249 
01250 void YQWizard::hideReleaseNotesButton()
01251 {
01252     if ( _releaseNotesButton && !_releaseNotesButton->isHidden() )
01253         _releaseNotesButton->hide();
01254 }
01255 
01256 
01257 void YQWizard::retranslateInternalButtons()
01258 {
01259     YQUI::setTextdomain( TEXTDOMAIN );
01260 
01261     if ( _helpButton )
01262         // "Help" button - intentionally without keyboard shortcut
01263         _helpButton->setText( _( "Help" ) );
01264 
01265     if ( _stepsButton )
01266         // "Steps" button - intentionally without keyboard shortcut
01267         _stepsButton->setText( _( "Steps" ) );
01268 
01269     if ( _treeButton )
01270         // "Tree" button - intentionally without keyboard shortcut
01271         _treeButton->setText( _( "Tree" ) );
01272 
01273     if ( _helpDlg )
01274         _helpDlg->retranslate();
01275 
01276 }
01277 
01278 
01279 void YQWizard::Step::deleteLabels()
01280 {
01281     delete _statusLabel;
01282     _statusLabel = 0;
01283     delete _nameLabel;
01284     _nameLabel = 0;
01285 }
01286 
01287 
01288 YQWizard::Step::~Step()
01289 {
01290     deleteLabels();
01291 }
01292 
01293 
01294 void YQWizard::Step::setStatus( Status s )
01295 {
01296     if ( !_statusLabel || !_nameLabel || _status == s )
01297         return;
01298 
01299     _status = s;
01300 
01301     if ( s == Todo )
01302     {
01303         _statusLabel->setProperty( "class", "todo-step-status QLabel" );
01304         _nameLabel->setProperty  ( "class", "todo-step-name QLabel"   );
01305     }
01306 
01307     if ( s == Done )
01308     {
01309         _statusLabel->setProperty( "class", "done-step-status QLabel" );
01310         _nameLabel->setProperty  ( "class", "done-step-name QLabel"   );
01311     }
01312 
01313     if ( s == Current )
01314     {
01315         _statusLabel->setProperty( "class", "current-step-status QLabel" );
01316         _nameLabel->setProperty  ( "class", "current-step-name QLabel"   );
01317     }
01318 
01319     _statusLabel->style()->unpolish( _statusLabel );
01320     _statusLabel->style()->polish( _statusLabel );
01321     _nameLabel->style()->unpolish( _nameLabel );
01322     _nameLabel->style()->polish( _nameLabel );
01323 }
01324 
01325 #include "YQWizard.moc"
 All Classes Functions Variables