00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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;
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
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
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
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 }