MythTV  0.26-pre
mythwizard.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **
00004 ** Implementation of MythWizard class.
00005 **
00006 ** Created : 990124
00007 **
00008 ** Copyright (C) 1999-2000 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the dialogs module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
00035 **
00036 **********************************************************************/
00037 
00038 #include "mythwizard.h"
00039 
00040 #include <QCoreApplication>
00041 
00042 #include <QLayout>
00043 #include <QKeyEvent>
00044 #include <QChildEvent>
00045 #include <QCursor>
00046 #include <QPainter>
00047 
00048 #include <QStackedWidget>
00049 #include <QPushButton>
00050 #include <QBoxLayout>
00051 #include <QGroupBox>
00052 #include <QLabel>
00053 
00054 #include "mythcorecontext.h"
00055 
00056 class MythWizardPrivate
00057 {
00058 public:
00059     struct Page {
00060         Page( QWidget * widget, const QString & title ):
00061             w( widget ), t( title ),
00062             backEnabled( TRUE ), nextEnabled( TRUE ), finishEnabled( FALSE ),
00063             appropriate( TRUE )
00064         {}
00065         QWidget * w;
00066         QString t;
00067         bool backEnabled;
00068         bool nextEnabled;
00069         bool finishEnabled;
00070         bool appropriate;
00071     };
00072 
00073     QVBoxLayout * v;
00074     Page * current;
00075     QStackedWidget * ws;
00076     QList<Page*> pages;
00077     QLabel * title;
00078     MythPushButton * backButton;
00079     MythPushButton * nextButton;
00080     MythPushButton * finishButton;
00081     MythPushButton * cancelButton;
00082 
00083     QGroupBox *helpgroup;
00084     QLabel *help;
00085 
00086     QFrame * hbar1, * hbar2;
00087 
00088     Page * page( const QWidget * w )
00089     {
00090         if ( !w )
00091             return 0;
00092         int i = pages.count();
00093         while( --i >= 0 && pages.at( i ) && pages.at( i )->w != w ) { }
00094         return i >= 0 ? pages.at( i ) : 0;
00095     }
00096 
00097 };
00098 
00099 MythWizard::MythWizard(MythMainWindow *parent, const char *name)
00100           : MythDialog(parent, name)
00101 {
00102     d = new MythWizardPrivate();
00103     d->current = 0; // not quite true, but...
00104     d->ws = new QStackedWidget(this);
00105     d->ws->setObjectName("MythWizard - stacked widget");
00106     d->title = new QLabel(this);
00107     d->ws->setObjectName("MythWizard - title label");
00108 
00109     // create in nice tab order
00110     d->nextButton = new MythPushButton( this, "next" );
00111     d->finishButton = new MythPushButton( this, "finish" );
00112     d->backButton = new MythPushButton( this, "back" );
00113     d->cancelButton = new MythPushButton( this, "cancel" );
00114 
00115     d->ws->installEventFilter( this );
00116 
00117     d->helpgroup = 0;
00118     d->help = 0;
00119     d->v = 0;
00120     d->hbar1 = 0;
00121     d->hbar2 = 0;
00122 
00123     d->cancelButton->setText( tr( "&Cancel" ) );
00124     d->backButton->setText( tr( "< &Back" ) );
00125     d->nextButton->setText( tr( "&Next >" ) );
00126     d->finishButton->setText( tr( "&Finish" ) );
00127 
00128     d->nextButton->setDefault( TRUE );
00129 
00130     connect( d->backButton, SIGNAL(clicked()),
00131              this, SLOT(back()) );
00132     connect( d->nextButton, SIGNAL(clicked()),
00133              this, SLOT(next()) );
00134     connect( d->finishButton, SIGNAL(clicked()),
00135              this, SLOT(accept()) );
00136     connect( d->cancelButton, SIGNAL(clicked()),
00137              this, SLOT(reject()) );
00138 }
00139 
00140 MythWizard::~MythWizard()
00141 {
00142     while (!d->pages.empty())
00143     {
00144         delete d->pages.back();
00145         d->pages.pop_back();
00146     }
00147     delete d;
00148 }
00149 
00150 void MythWizard::Show()
00151 {
00152     if ( d->current )
00153         showPage( d->current->w );
00154     else if ( pageCount() > 0 )
00155         showPage( d->pages[0]->w );
00156     else
00157         showPage( 0 );
00158 
00159     MythDialog::Show();
00160 }
00161 
00162 void MythWizard::setFont( const QFont & font )
00163 {
00164     QCoreApplication::postEvent( this, new QEvent( QEvent::LayoutRequest ) );
00165     MythDialog::setFont( font );
00166 }
00167 
00168 void MythWizard::addPage( QWidget * page, const QString & title )
00169 {
00170     if ( !page )
00171         return;
00172     if ( d->page( page ) ) {
00173         qWarning( "MythWizard::addPage(): already added %s/%s to %s/%s",
00174                   page->metaObject()->className(), qPrintable(page->objectName()),
00175                   metaObject()->className(), qPrintable(objectName()) );
00176         return;
00177     }
00178     int i = d->pages.size();
00179 
00180     if ( i > 0 )
00181         d->pages[i - 1]->nextEnabled = true;
00182 
00183     MythWizardPrivate::Page * p = new MythWizardPrivate::Page( page, title );
00184     p->backEnabled = ( i > 0 );
00185     d->ws->addWidget(page);
00186     d->pages.append( p );
00187 }
00188 
00189 void MythWizard::insertPage( QWidget * page, const QString & title, int index )
00190 {
00191     if ( !page )
00192         return;
00193     if ( d->page( page ) ) {
00194         qWarning( "MythWizard::insertPage(): already added %s/%s to %s/%s",
00195                   page->metaObject()->className(), qPrintable(page->objectName()),
00196                   metaObject()->className(), qPrintable(objectName()) );
00197         return;
00198     }
00199 
00200     if ( index < 0  || index > (int)d->pages.size() )
00201         index = d->pages.size();
00202 
00203     if ( index > 0 && ( index == (int)d->pages.size() ) )
00204         d->pages[index - 1]->nextEnabled = true;
00205 
00206     MythWizardPrivate::Page * p = new MythWizardPrivate::Page( page, title );
00207     p->backEnabled = ( index > 0 );
00208     p->nextEnabled = ( index < (int)d->pages.size() );
00209 
00210     d->ws->addWidget(page);
00211     d->pages.insert( index, p );
00212 }
00213 
00214 void MythWizard::showPage( QWidget * page )
00215 {
00216     MythWizardPrivate::Page * p = d->page( page );
00217     if ( p ) {
00218         int i;
00219         for( i = 0; i < (int)d->pages.size() && d->pages[i] != p; i++ );
00220         bool notFirst( FALSE );
00221 
00222         if (i)
00223         {
00224             i--;
00225             while ((i >= 0) && !notFirst)
00226             {
00227                 notFirst |= appropriate(d->pages[i]->w);
00228                 i--;
00229             }
00230         }
00231         setBackEnabled( notFirst );
00232         setNextEnabled( TRUE );
00233         d->ws->setCurrentWidget(page);
00234         d->current = p;
00235     }
00236 
00237     layOut();
00238     updateButtons();
00239     emit selected( p ? p->t : QString::null );
00240 
00241     if (indexOf(page) == pageCount()-1) {
00242         // last page
00243         finishButton()->setEnabled(TRUE);
00244         finishButton()->setFocus();
00245     } else {
00246         nextButton()->setFocus();
00247     }
00248 }
00249 
00250 int MythWizard::pageCount() const
00251 {
00252     return d->pages.size();
00253 }
00254 
00255 int MythWizard::indexOf( QWidget* page ) const
00256 {
00257     MythWizardPrivate::Page * p = d->page( page );
00258     if ( !p ) return -1;
00259 
00260     return d->pages.indexOf( p );
00261 }
00262 
00263 void MythWizard::back()
00264 {
00265     int i = 0;
00266 
00267     while( i < (int)d->pages.size() && d->pages[i] &&
00268            d->current && d->pages[i]->w != d->current->w )
00269         i++;
00270 
00271     i--;
00272     while( i >= 0 &&
00273            ( !d->pages[i] || !appropriate( d->pages[i]->w ) ) )
00274         i--;
00275 
00276     if ( i >= 0 )
00277        if ( d->pages[i] )
00278             showPage( d->pages[i]->w );
00279 }
00280 
00281 void MythWizard::next()
00282 {
00283     int i = 0;
00284     while( i < (int)d->pages.size() && d->pages[i] &&
00285            d->current && d->pages[i]->w != d->current->w )
00286         i++;
00287     i++;
00288     while( i <= (int)d->pages.size()-1 &&
00289            ( !d->pages[i] || !appropriate( d->pages[i]->w ) ) )
00290         i++;
00291     while ( i > 0 && (i >= (int)d->pages.size() || !d->pages[i] ) )
00292         i--;
00293     if ( d->pages[i] )
00294         showPage( d->pages[i]->w );
00295 }
00296 
00297 void MythWizard::setBackEnabled( bool enable )
00298 {
00299     d->backButton->setEnabled( enable );
00300 }
00301 
00302 void MythWizard::setNextEnabled( bool enable )
00303 {
00304     d->nextButton->setEnabled( enable );
00305 }
00306 
00307 void MythWizard::setBackEnabled( QWidget * page, bool enable )
00308 {
00309     MythWizardPrivate::Page * p = d->page( page );
00310     if ( !p )
00311         return;
00312 
00313     p->backEnabled = enable;
00314     updateButtons();
00315 }
00316 
00317 void MythWizard::setNextEnabled( QWidget * page, bool enable )
00318 {
00319     MythWizardPrivate::Page * p = d->page( page );
00320     if ( !p )
00321         return;
00322 
00323     p->nextEnabled = enable;
00324     updateButtons();
00325 }
00326 
00327 void MythWizard::setFinishEnabled( QWidget * page, bool enable )
00328 {
00329     MythWizardPrivate::Page * p = d->page( page );
00330     if ( !p )
00331         return;
00332 
00333     p->finishEnabled = enable;
00334     updateButtons();
00335 }
00336 
00337 bool MythWizard::appropriate( QWidget * page ) const
00338 {
00339     MythWizardPrivate::Page * p = d->page( page );
00340     return p ? p->appropriate : TRUE;
00341 }
00342 
00343 void MythWizard::setAppropriate( QWidget * page, bool appropriate )
00344 {
00345     MythWizardPrivate::Page * p = d->page( page );
00346     if ( p )
00347         p->appropriate = appropriate;
00348 }
00349 
00350 void MythWizard::updateButtons()
00351 {
00352     if ( !d->current )
00353         return;
00354 
00355     int i;
00356     for( i = 0; i < (int)d->pages.size() && d->pages[i] != d->current; i++ );
00357     bool notFirst( FALSE );
00358     if ( i ) {
00359         i--;
00360         while( ( i >= 0 ) && !notFirst ) {
00361             notFirst |= appropriate( d->pages[i]->w );
00362             i--;
00363         }
00364     }
00365     setBackEnabled( d->current->backEnabled && notFirst );
00366     setNextEnabled( d->current->nextEnabled );
00367     d->finishButton->setEnabled( d->current->finishEnabled );
00368 
00369     if ( ( d->current->finishEnabled && !d->finishButton->isVisible() ) ||
00370          ( d->current->backEnabled && !d->backButton->isVisible() ) ||
00371          ( d->current->nextEnabled && !d->nextButton->isVisible() ) )
00372         layOut();
00373 }
00374 
00375 QWidget * MythWizard::currentPage() const
00376 {
00377     return d->ws->currentWidget();
00378 }
00379 
00380 QString MythWizard::title( QWidget * page ) const
00381 {
00382     MythWizardPrivate::Page * p = d->page( page );
00383     return p ? p->t : QString::null;
00384 }
00385 
00386 void MythWizard::setTitle( QWidget *page, const QString &title )
00387 {
00388     MythWizardPrivate::Page * p = d->page( page );
00389     if ( p )
00390         p->t = title;
00391     if ( page == currentPage() )
00392         d->title->setText( title );
00393 }
00394 
00395 QFont MythWizard::titleFont() const
00396 {
00397     return d->title->font();
00398 }
00399 
00400 void MythWizard::setTitleFont( const QFont & font )
00401 {
00402     d->title->setFont( font );
00403 }
00404 
00405 MythPushButton * MythWizard::backButton() const
00406 {
00407     return d->backButton;
00408 }
00409 
00410 MythPushButton * MythWizard::nextButton() const
00411 {
00412     return d->nextButton;
00413 }
00414 
00415 MythPushButton * MythWizard::finishButton() const
00416 {
00417     return d->finishButton;
00418 }
00419 
00420 MythPushButton * MythWizard::cancelButton() const
00421 {
00422     return d->cancelButton;
00423 }
00424 
00425 void MythWizard::layOutButtonRow( QHBoxLayout * layout )
00426 {
00427     bool hasEarlyFinish = false;
00428 
00429     int i = d->pages.size() - 2;
00430     while ( !hasEarlyFinish && i >= 0 )
00431     {
00432         hasEarlyFinish |= (d->pages.at(i) && d->pages.at(i)->finishEnabled);
00433         i--;
00434     }
00435 
00436     QHBoxLayout *h = new QHBoxLayout();
00437     h->setSpacing(QBoxLayout::LeftToRight);
00438     layout->addLayout( h );
00439 
00440     h->addWidget( d->cancelButton );
00441 
00442     h->addStretch( 42 );
00443 
00444     h->addWidget( d->backButton );
00445 
00446     h->addSpacing( 6 );
00447 
00448     if (hasEarlyFinish)
00449     {
00450         d->nextButton->show();
00451         d->finishButton->show();
00452         h->addWidget( d->nextButton );
00453         h->addSpacing( 12 );
00454         h->addWidget( d->finishButton );
00455     }
00456     else if (d->pages.empty() ||
00457              d->current->finishEnabled ||
00458              d->current == d->pages.last())
00459     {
00460         d->nextButton->hide();
00461         d->finishButton->show();
00462         h->addWidget( d->finishButton );
00463     }
00464     else
00465     {
00466         d->nextButton->show();
00467         d->finishButton->hide();
00468         h->addWidget( d->nextButton );
00469     }
00470 
00471     // if last page is disabled - show finished btn. at lastpage-1
00472     i = d->pages.size() - 1;
00473     if (i > 0 && !appropriate(d->pages[i]->w) &&
00474         d->current == d->pages[(uint)(i) - 1])
00475     {
00476         d->nextButton->hide();
00477         d->finishButton->show();
00478         h->addWidget( d->finishButton );
00479     }
00480 }
00481 
00482 void MythWizard::layOutTitleRow( QHBoxLayout * layout, const QString & title )
00483 {
00484     d->title->setText( title );
00485     layout->addWidget( d->title, 10 );
00486 }
00487 
00488 void MythWizard::layOut()
00489 {
00490     delete d->v;
00491     d->v = new QVBoxLayout( this);
00492     d->v->setMargin(6);
00493     d->v->setSpacing(0);
00494     d->v->setObjectName("top-level layout");
00495 
00496     QHBoxLayout * l;
00497     l = new QHBoxLayout();
00498     l->setMargin(6);
00499     d->v->addLayout( l, 0 );
00500     layOutTitleRow( l, d->current ? d->current->t : QString::null );
00501 
00502     if ( ! d->hbar1 ) {
00503         d->hbar1 = new QFrame(this, 0);
00504         d->hbar1->setObjectName("MythWizard - hbar1");
00505         d->hbar1->setFrameStyle(QFrame::Sunken | QFrame::HLine);
00506         d->hbar1->setFixedHeight( 12 );
00507     }
00508 
00509     d->v->addWidget( d->hbar1 );
00510 
00511     d->v->addWidget( d->ws, 10 );
00512 
00513     if (!d->helpgroup)
00514     {
00515         d->helpgroup = new QGroupBox(this);
00516         d->helpgroup->setObjectName("MythWizard -- help group box");
00517 
00518         d->help = new QLabel(d->helpgroup);
00519         d->help->setObjectName("MythWizard -- help text");
00520 
00521         d->help->setAlignment(Qt::AlignLeft | Qt::AlignTop);
00522         d->help->setWordWrap(true);
00523 
00524         d->help->setMinimumWidth(screenwidth - (int)(40 * wmult));
00525         d->help->setMaximumHeight((int)(80 * hmult));
00526         d->help->setMinimumHeight((int)(80 * hmult));
00527 
00528         QVBoxLayout *helplayout = new QVBoxLayout(d->helpgroup);
00529         helplayout->setMargin(10);
00530         helplayout->addWidget(d->help);
00531     }
00532     else
00533     {
00534         d->help->setText("");
00535     }
00536 
00537     d->v->addWidget(d->helpgroup);
00538 
00539     if ( ! d->hbar2 ) {
00540         d->hbar2 = new QFrame( this, 0 );
00541         d->hbar2->setObjectName("MythWizard - hbar2");
00542         d->hbar2->setFrameStyle(QFrame::Sunken | QFrame::HLine);
00543         d->hbar2->setFixedHeight( 12 );
00544     }
00545     d->v->addWidget( d->hbar2 );
00546 
00547     l = new QHBoxLayout();
00548     l->setMargin(6);
00549     d->v->addLayout( l );
00550     layOutButtonRow( l );
00551     d->v->activate();
00552 }
00553 
00554 bool MythWizard::eventFilter( QObject * o, QEvent * e )
00555 {
00556     if ( o == d->ws && e && e->type() == QEvent::ChildRemoved ) {
00557         QChildEvent * c = (QChildEvent*)e;
00558         if ( c->child() && c->child()->isWidgetType() )
00559             removePage( (QWidget *)c->child() );
00560     }
00561     return QWidget::eventFilter( o, e );
00562 }
00563 
00564 void MythWizard::keyPressEvent(QKeyEvent* e)
00565 {
00566     bool handled = false;
00567     QStringList actions;
00568     handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions);
00569 
00570     for (int i = 0; i < actions.size() && !handled; i++)
00571     {
00572         QString action = actions[i];
00573         handled = true;
00574 
00575         if (action == "SELECT")
00576         {
00577             if (indexOf(currentPage()) == pageCount()-1)
00578                 accept();
00579             else
00580                 next();
00581         }
00582         else if (action == "ESCAPE")
00583         {
00584             if (indexOf(currentPage()) == 0)
00585                 reject();
00586             else
00587             {
00588                 back();
00589                 QCoreApplication::postEvent(
00590                     GetMythMainWindow(),
00591                     new QEvent(MythEvent::kExitToMainMenuEventType));
00592             }
00593         }
00594         else
00595             handled = false;
00596     }
00597 
00598     if (!handled)
00599         MythDialog::keyPressEvent(e);
00600 }
00601 
00602 void MythWizard::removePage( QWidget * page )
00603 {
00604     if ( !page )
00605         return;
00606 
00607     int i = d->pages.size();
00608     QWidget* cp = currentPage();
00609     while( --i >= 0 && d->pages[i] && d->pages[i]->w != page ) { }
00610     if ( i < 0 )
00611         return;
00612 
00613     MythWizardPrivate::Page *p = d->pages[i];
00614     d->pages.removeAll(p);
00615     delete p;
00616 
00617     d->ws->removeWidget(page);
00618 
00619     if ( cp == page ) {
00620         i--;
00621         if ( i < 0 )
00622             i = 0;
00623         if ( pageCount() > 0 )
00624             showPage( MythWizard::page( i ) );
00625     }
00626 }
00627 
00628 QWidget* MythWizard::page( int index ) const
00629 {
00630     if ( index >= pageCount() || index < 0 )
00631       return 0;
00632 
00633     return d->pages[index]->w;
00634 }
00635 
00636 void MythWizard::setHelpText(QString helptext)
00637 {
00638     if (!d->help)
00639         return;
00640 
00641     d->help->setText(helptext);
00642     d->help->setMinimumWidth(screenwidth - (int)(40 * wmult));
00643     d->help->setMaximumHeight((int)(80 * hmult));
00644 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends