|
MythTV
0.26-pre
|
00001 00002 #include <iostream> 00003 #include <algorithm> 00004 using namespace std; 00005 00006 #include <QCoreApplication> 00007 #include <QCursor> 00008 #include <QDialog> 00009 #include <QDir> 00010 #include <QLayout> 00011 #include <QRegExp> 00012 #include <QLabel> 00013 #include <QPixmap> 00014 #include <QKeyEvent> 00015 #include <QFrame> 00016 #include <QPaintEvent> 00017 #include <QPainter> 00018 #include <QProgressBar> 00019 00020 #ifdef QWS 00021 #include <qwindowsystem_qws.h> 00022 #endif 00023 00024 #include "uitypes.h" 00025 #include "xmlparse.h" 00026 #include "mythdialogs.h" 00027 #include "lcddevice.h" 00028 #include "mythdbcon.h" 00029 #include "mythfontproperties.h" 00030 #include "mythuihelper.h" 00031 #include "mythlogging.h" 00032 #include "mythcorecontext.h" 00033 00034 #ifdef USING_MINGW 00035 #undef LoadImage 00036 #endif 00037 00042 MythDialog::MythDialog(MythMainWindow *parent, const char *name, bool setsize) 00043 : QFrame(parent), rescode(kDialogCodeAccepted) 00044 { 00045 setObjectName(name); 00046 if (!parent) 00047 { 00048 LOG(VB_GENERAL, LOG_ALERT, 00049 "Trying to create a dialog without a parent."); 00050 return; 00051 } 00052 00053 in_loop = false; 00054 MythUIHelper *ui = GetMythUI(); 00055 00056 ui->GetScreenSettings(xbase, screenwidth, wmult, 00057 ybase, screenheight, hmult); 00058 00059 defaultBigFont = ui->GetBigFont(); 00060 defaultMediumFont = ui->GetMediumFont(); 00061 defaultSmallFont = ui->GetSmallFont(); 00062 00063 setFont(defaultMediumFont); 00064 00065 if (setsize) 00066 { 00067 move(0, 0); 00068 setFixedSize(QSize(screenwidth, screenheight)); 00069 GetMythUI()->ThemeWidget(this); 00070 } 00071 00072 setAutoFillBackground(true); 00073 00074 parent->attach(this); 00075 m_parent = parent; 00076 } 00077 00078 MythDialog::~MythDialog() 00079 { 00080 TeardownAll(); 00081 } 00082 00083 void MythDialog::deleteLater(void) 00084 { 00085 hide(); 00086 TeardownAll(); 00087 QFrame::deleteLater(); 00088 } 00089 00090 void MythDialog::TeardownAll(void) 00091 { 00092 if (m_parent) 00093 { 00094 m_parent->detach(this); 00095 m_parent = NULL; 00096 } 00097 } 00098 00099 void MythDialog::setNoErase(void) 00100 { 00101 } 00102 00103 bool MythDialog::onMediaEvent(MythMediaDevice*) 00104 { 00105 return false; 00106 } 00107 00108 00109 00110 void MythDialog::Show(void) 00111 { 00112 show(); 00113 } 00114 00115 void MythDialog::setResult(DialogCode r) 00116 { 00117 if ((r < kDialogCodeRejected) || 00118 ((kDialogCodeAccepted < r) && (r < kDialogCodeListStart))) 00119 { 00120 LOG(VB_GENERAL, LOG_ALERT, 00121 QString("MythDialog::setResult(%1) " 00122 "called with invalid DialogCode").arg(r)); 00123 } 00124 00125 rescode = r; 00126 } 00127 00128 void MythDialog::done(int r) 00129 { 00130 hide(); 00131 setResult((DialogCode) r); 00132 close(); 00133 } 00134 00135 void MythDialog::AcceptItem(int i) 00136 { 00137 if (i < 0) 00138 { 00139 LOG(VB_GENERAL, LOG_ALERT, 00140 QString("MythDialog::AcceptItem(%1) " 00141 "called with negative index").arg(i)); 00142 reject(); 00143 return; 00144 } 00145 00146 done((DialogCode)((int)kDialogCodeListStart + (int)i)); 00147 } 00148 00149 int MythDialog::CalcItemIndex(DialogCode code) 00150 { 00151 return (int)code - (int)kDialogCodeListStart; 00152 } 00153 00154 void MythDialog::accept() 00155 { 00156 done(Accepted); 00157 } 00158 00159 void MythDialog::reject() 00160 { 00161 done(Rejected); 00162 } 00163 00164 DialogCode MythDialog::exec(void) 00165 { 00166 if (in_loop) 00167 { 00168 LOG(VB_GENERAL, LOG_ALERT, 00169 "MythDialog::exec: Recursive call detected."); 00170 return kDialogCodeRejected; 00171 } 00172 00173 setResult(kDialogCodeRejected); 00174 00175 Show(); 00176 00177 in_loop = true; 00178 00179 QEventLoop eventLoop; 00180 connect(this, SIGNAL(leaveModality()), &eventLoop, SLOT(quit())); 00181 eventLoop.exec(); 00182 00183 DialogCode res = result(); 00184 00185 return res; 00186 } 00187 00188 void MythDialog::hide(void) 00189 { 00190 if (isHidden()) 00191 return; 00192 00193 // Reimplemented to exit a modal when the dialog is hidden. 00194 QWidget::hide(); 00195 if (in_loop) 00196 { 00197 in_loop = false; 00198 emit leaveModality(); 00199 } 00200 } 00201 00202 void MythDialog::keyPressEvent( QKeyEvent *e ) 00203 { 00204 bool handled = false; 00205 QStringList actions; 00206 00207 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions); 00208 00209 for (int i = 0; i < actions.size() && !handled; i++) 00210 { 00211 QString action = actions[i]; 00212 handled = true; 00213 00214 if (action == "ESCAPE") 00215 reject(); 00216 else if (action == "UP" || action == "LEFT") 00217 { 00218 if (focusWidget() && 00219 (focusWidget()->focusPolicy() == Qt::StrongFocus || 00220 focusWidget()->focusPolicy() == Qt::WheelFocus)) 00221 { 00222 } 00223 else 00224 focusNextPrevChild(false); 00225 } 00226 else if (action == "DOWN" || action == "RIGHT") 00227 { 00228 if (focusWidget() && 00229 (focusWidget()->focusPolicy() == Qt::StrongFocus || 00230 focusWidget()->focusPolicy() == Qt::WheelFocus)) 00231 { 00232 } 00233 else 00234 focusNextPrevChild(true); 00235 } 00236 else if (action == "MENU") 00237 emit menuButtonPressed(); 00238 else 00239 handled = false; 00240 } 00241 } 00242 00257 MythPopupBox::MythPopupBox(MythMainWindow *parent, const char *name) 00258 : MythDialog(parent, name, false) 00259 { 00260 float wmult, hmult; 00261 00262 GetMythUI()->GetScreenSettings(wmult, hmult); 00263 00264 setLineWidth(3); 00265 setMidLineWidth(3); 00266 setFrameShape(QFrame::Panel); 00267 setFrameShadow(QFrame::Raised); 00268 setPalette(parent->palette()); 00269 popupForegroundColor = palette().color(foregroundRole()); 00270 setFont(parent->font()); 00271 00272 hpadding = gCoreContext->GetNumSetting("PopupHeightPadding", 120); 00273 wpadding = gCoreContext->GetNumSetting("PopupWidthPadding", 80); 00274 00275 vbox = new QVBoxLayout(this); 00276 vbox->setMargin((int)(10 * hmult)); 00277 00278 setAutoFillBackground(true); 00279 setWindowFlags(Qt::FramelessWindowHint); 00280 } 00281 00282 MythPopupBox::MythPopupBox(MythMainWindow *parent, bool graphicPopup, 00283 QColor popupForeground, QColor popupBackground, 00284 QColor popupHighlight, const char *name) 00285 : MythDialog(parent, name, false) 00286 { 00287 float wmult, hmult; 00288 00289 GetMythUI()->GetScreenSettings(wmult, hmult); 00290 00291 setLineWidth(3); 00292 setMidLineWidth(3); 00293 setFrameShape(QFrame::Panel); 00294 setFrameShadow(QFrame::Raised); 00295 setFrameStyle(QFrame::Box | QFrame::Plain); 00296 setPalette(parent->palette()); 00297 setFont(parent->font()); 00298 00299 hpadding = gCoreContext->GetNumSetting("PopupHeightPadding", 120); 00300 wpadding = gCoreContext->GetNumSetting("PopupWidthPadding", 80); 00301 00302 vbox = new QVBoxLayout(this); 00303 vbox->setMargin((int)(10 * hmult)); 00304 00305 if (!graphicPopup) 00306 { 00307 QPalette palette; 00308 palette.setColor(backgroundRole(), popupBackground); 00309 setPalette(palette); 00310 } 00311 else 00312 GetMythUI()->ThemeWidget(this); 00313 00314 QPalette palette; 00315 palette.setColor(foregroundRole(), popupHighlight); 00316 setPalette(palette); 00317 00318 popupForegroundColor = popupForeground; 00319 setAutoFillBackground(true); 00320 setWindowFlags(Qt::FramelessWindowHint); 00321 } 00322 00323 00324 bool MythPopupBox::focusNextPrevChild(bool next) 00325 { 00326 // -=>TODO: Temp fix... should re-evalutate/re-code. 00327 00328 QList<QWidget *> objList = qFindChildren<QWidget *>(this); 00329 00330 QWidget *pCurr = focusWidget(); 00331 QWidget *pNew = NULL; 00332 int nCurrIdx = -1; 00333 int nIdx; 00334 00335 for (nIdx = 0; nIdx < objList.size(); ++nIdx ) 00336 { 00337 if (objList[ nIdx ] == pCurr) 00338 { 00339 nCurrIdx = nIdx; 00340 break; 00341 } 00342 } 00343 00344 if (nCurrIdx == -1) 00345 return false; 00346 00347 nIdx = nCurrIdx; 00348 00349 do 00350 { 00351 if (next) 00352 { 00353 ++nIdx; 00354 00355 if (nIdx == objList.size()) 00356 nIdx = 0; 00357 } 00358 else 00359 { 00360 --nIdx; 00361 00362 if (nIdx < 0) 00363 nIdx = objList.size() -1; 00364 } 00365 00366 pNew = objList[ nIdx ]; 00367 00368 if (pNew && !pNew->focusProxy() && pNew->isVisibleTo( this ) && 00369 pNew->isEnabled() && (pNew->focusPolicy() != Qt::NoFocus)) 00370 { 00371 pNew->setFocus(); 00372 return true; 00373 } 00374 } 00375 while (nIdx != nCurrIdx); 00376 00377 return false; 00378 00379 #if 0 00380 QFocusData *focusList = focusData(); 00381 QObjectList *objList = queryList(NULL,NULL,false,true); 00382 00383 QWidget *startingPoint = focusList->home(); 00384 QWidget *candidate = NULL; 00385 00386 QWidget *w = (next) ? focusList->prev() : focusList->next(); 00387 00388 int countdown = focusList->count(); 00389 00390 do 00391 { 00392 if (w && w != startingPoint && !w->focusProxy() && 00393 w->isVisibleTo(this) && w->isEnabled() && 00394 (objList->find((QObject *)w) != -1)) 00395 { 00396 candidate = w; 00397 } 00398 00399 w = (next) ? focusList->prev() : focusList->next(); 00400 } 00401 while (w && !(candidate && w == startingPoint) && (countdown-- > 0)); 00402 00403 if (!candidate) 00404 return false; 00405 00406 candidate->setFocus(); 00407 return true; 00408 #endif 00409 } 00410 00411 void MythPopupBox::addWidget(QWidget *widget, bool setAppearance) 00412 { 00413 if (setAppearance == true) 00414 { 00415 widget->setPalette(palette()); 00416 widget->setFont(font()); 00417 } 00418 00419 if (widget->metaObject()->className() == QString("QLabel")) 00420 { 00421 QPalette palette; 00422 palette.setColor(widget->foregroundRole(), popupForegroundColor); 00423 widget->setPalette(palette); 00424 } 00425 00426 vbox->addWidget(widget); 00427 } 00428 00429 QLabel *MythPopupBox::addLabel(QString caption, LabelSize size, bool wrap) 00430 { 00431 QLabel *label = new QLabel(caption, this); 00432 switch (size) 00433 { 00434 case Large: label->setFont(defaultBigFont); break; 00435 case Medium: label->setFont(defaultMediumFont); break; 00436 case Small: label->setFont(defaultSmallFont); break; 00437 } 00438 00439 label->setMaximumWidth((int)m_parent->width() / 2); 00440 if (wrap) 00441 { 00442 QChar::Direction text_dir = QChar::DirL; 00443 // Get a char from within the string to determine direction. 00444 if (caption.length()) 00445 text_dir = caption[0].direction(); 00446 Qt::Alignment align = (QChar::DirAL == text_dir) ? 00447 Qt::AlignRight : Qt::AlignLeft; 00448 label->setAlignment(align); 00449 label->setWordWrap(true); 00450 } 00451 00452 label->setWordWrap(true); 00453 addWidget(label, false); 00454 return label; 00455 } 00456 00457 QAbstractButton *MythPopupBox::addButton(QString caption, QObject *target, 00458 const char *slot) 00459 { 00460 if (!target) 00461 { 00462 target = this; 00463 slot = SLOT(defaultButtonPressedHandler()); 00464 } 00465 00466 MythPushButton *button = new MythPushButton(caption, this); 00467 m_parent->connect(button, SIGNAL(pressed()), target, slot); 00468 addWidget(button, false); 00469 return button; 00470 } 00471 00472 void MythPopupBox::addLayout(QLayout *layout, int stretch) 00473 { 00474 vbox->addLayout(layout, stretch); 00475 } 00476 00477 void MythPopupBox::ShowPopup(QObject *target, const char *slot) 00478 { 00479 ShowPopupAtXY(-1, -1, target, slot); 00480 } 00481 00482 void MythPopupBox::ShowPopupAtXY(int destx, int desty, 00483 QObject *target, const char *slot) 00484 { 00485 QList< QObject* > objlist = children(); 00486 00487 for (QList< QObject* >::Iterator it = objlist.begin(); 00488 it != objlist.end(); 00489 ++it ) 00490 { 00491 QObject *objs = *it; 00492 00493 if (objs->isWidgetType()) 00494 { 00495 QWidget *widget = (QWidget *)objs; 00496 widget->adjustSize(); 00497 } 00498 } 00499 00500 ensurePolished(); 00501 00502 int x = 0, y = 0, maxw = 0, poph = 0; 00503 00504 for (QList< QObject* >::Iterator it = objlist.begin(); 00505 it != objlist.end(); 00506 ++it ) 00507 { 00508 QObject *objs = *it; 00509 00510 if (objs->isWidgetType()) 00511 { 00512 QString objname = objs->objectName(); 00513 if (objname != "nopopsize") 00514 { 00515 // little extra padding for these guys 00516 if (objs->metaObject()->className() == 00517 QString("MythListBox")) 00518 { 00519 poph += (int)(25 * hmult); 00520 } 00521 00522 QWidget *widget = (QWidget *)objs; 00523 poph += widget->height(); 00524 if (widget->width() > maxw) 00525 maxw = widget->width(); 00526 } 00527 } 00528 } 00529 00530 poph += (int)(hpadding * hmult); 00531 setMinimumHeight(poph); 00532 00533 maxw += (int)(wpadding * wmult); 00534 00535 int width = (int)(800 * wmult); 00536 int height = (int)(600 * hmult); 00537 00538 if (parentWidget()) 00539 { 00540 width = parentWidget()->width(); 00541 height = parentWidget()->height(); 00542 } 00543 00544 if (destx == -1) 00545 x = (int)(width / 2) - (int)(maxw / 2); 00546 else 00547 x = destx; 00548 00549 if (desty == -1) 00550 y = (int)(height / 2) - (int)(poph / 2); 00551 else 00552 y = desty; 00553 00554 if (poph + y > height) 00555 y = height - poph - (int)(8 * hmult); 00556 00557 setFixedSize(maxw, poph); 00558 setGeometry(x, y, maxw, poph); 00559 00560 if (target && slot) 00561 connect(this, SIGNAL(popupDone(int)), target, slot); 00562 00563 Show(); 00564 } 00565 00566 void MythPopupBox::keyPressEvent(QKeyEvent *e) 00567 { 00568 bool handled = false; 00569 QStringList actions; 00570 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions); 00571 00572 for (int i = 0; i < actions.size() && !handled; i++) 00573 { 00574 QString action = actions[i]; 00575 00576 if (action == "ESCAPE") 00577 { 00578 reject(); 00579 handled = true; 00580 } 00581 } 00582 00583 if (!handled) 00584 MythDialog::keyPressEvent(e); 00585 } 00586 00587 void MythPopupBox::AcceptItem(int i) 00588 { 00589 MythDialog::AcceptItem(i); 00590 emit popupDone(rescode); 00591 } 00592 00593 void MythPopupBox::accept(void) 00594 { 00595 MythDialog::done(MythDialog::Accepted); 00596 emit popupDone(MythDialog::Accepted); 00597 } 00598 00599 void MythPopupBox::reject(void) 00600 { 00601 MythDialog::done(MythDialog::Rejected); 00602 emit popupDone(MythDialog::Rejected); 00603 } 00604 00605 DialogCode MythPopupBox::ExecPopup(QObject *target, const char *slot) 00606 { 00607 if (!target) 00608 ShowPopup(this, SLOT(done(int))); 00609 else 00610 ShowPopup(target, slot); 00611 00612 return exec(); 00613 } 00614 00615 DialogCode MythPopupBox::ExecPopupAtXY(int destx, int desty, 00616 QObject *target, const char *slot) 00617 { 00618 if (!target) 00619 ShowPopupAtXY(destx, desty, this, SLOT(done(int))); 00620 else 00621 ShowPopupAtXY(destx, desty, target, slot); 00622 00623 return exec(); 00624 } 00625 00626 void MythPopupBox::defaultButtonPressedHandler(void) 00627 { 00628 QList< QObject* > objlist = children(); 00629 00630 int i = 0; 00631 bool foundbutton = false; 00632 00633 for (QList< QObject* >::Iterator it = objlist.begin(); 00634 it != objlist.end(); 00635 ++it ) 00636 { 00637 QObject *objs = *it; 00638 00639 if (objs->isWidgetType()) 00640 { 00641 QWidget *widget = (QWidget *)objs; 00642 if (widget->metaObject()->className() == 00643 QString("MythPushButton")) 00644 { 00645 if (widget->hasFocus()) 00646 { 00647 foundbutton = true; 00648 break; 00649 } 00650 i++; 00651 } 00652 } 00653 } 00654 if (foundbutton) 00655 { 00656 AcceptItem(i); 00657 return; 00658 } 00659 00660 // this bit of code should always work but requires a cast 00661 i = 0; 00662 for (QList< QObject* >::Iterator it = objlist.begin(); 00663 it != objlist.end(); 00664 ++it ) 00665 { 00666 QObject *objs = *it; 00667 00668 if (objs->isWidgetType()) 00669 { 00670 QWidget *widget = (QWidget *)objs; 00671 if (widget->metaObject()->className() == 00672 QString("MythPushButton")) 00673 { 00674 MythPushButton *button = dynamic_cast<MythPushButton*>(widget); 00675 if (button && button->isDown()) 00676 { 00677 foundbutton = true; 00678 break; 00679 } 00680 i++; 00681 } 00682 } 00683 } 00684 if (foundbutton) 00685 { 00686 AcceptItem(i); 00687 return; 00688 } 00689 00690 LOG(VB_GENERAL, LOG_ALERT, "We should never get here!"); 00691 done(kDialogCodeRejected); 00692 } 00693 00694 bool MythPopupBox::showOkPopup( 00695 MythMainWindow *parent, 00696 const QString &title, 00697 const QString &message, 00698 QString button_msg) 00699 { 00700 if (button_msg.isEmpty()) 00701 button_msg = QObject::tr("OK"); 00702 00703 MythPopupBox *popup = new MythPopupBox(parent, title.toAscii().constData()); 00704 00705 popup->addLabel(message, MythPopupBox::Medium, true); 00706 QAbstractButton *okButton = popup->addButton(button_msg, popup, SLOT(accept())); 00707 okButton->setFocus(); 00708 bool ret = (kDialogCodeAccepted == popup->ExecPopup()); 00709 00710 popup->hide(); 00711 popup->deleteLater(); 00712 00713 return ret; 00714 } 00715 00716 bool MythPopupBox::showGetTextPopup(MythMainWindow *parent, QString title, 00717 QString message, QString& text) 00718 { 00719 MythPopupBox *popup = new MythPopupBox(parent, title.toAscii().constData()); 00720 00721 popup->addLabel(message, Medium, true); 00722 00723 MythRemoteLineEdit *textEdit = 00724 new MythRemoteLineEdit(popup, "chooseEdit"); 00725 00726 textEdit->setText(text); 00727 popup->addWidget(textEdit); 00728 00729 popup->addButton(tr("OK"), popup, SLOT(accept())); 00730 popup->addButton(tr("Cancel"), popup, SLOT(reject())); 00731 00732 textEdit->setFocus(); 00733 00734 bool ok = (Accepted == popup->ExecPopup()); 00735 if (ok) 00736 text = textEdit->text(); 00737 00738 popup->hide(); 00739 popup->deleteLater(); 00740 00741 return ok; 00742 } 00743 00744 DialogCode MythPopupBox::Show2ButtonPopup( 00745 MythMainWindow *parent, 00746 const QString &title, const QString &message, 00747 const QString &button1msg, const QString &button2msg, 00748 DialogCode default_button) 00749 { 00750 QStringList buttonmsgs; 00751 buttonmsgs += (button1msg.isEmpty()) ? 00752 QString("Button 1") : button1msg; 00753 buttonmsgs += (button2msg.isEmpty()) ? 00754 QString("Button 2") : button2msg; 00755 return ShowButtonPopup( 00756 parent, title, message, buttonmsgs, default_button); 00757 } 00758 00759 DialogCode MythPopupBox::ShowButtonPopup( 00760 MythMainWindow *parent, 00761 const QString &title, 00762 const QString &message, 00763 const QStringList &buttonmsgs, 00764 DialogCode default_button) 00765 { 00766 MythPopupBox *popup = new MythPopupBox(parent, title.toAscii().constData()); 00767 00768 popup->addLabel(message, Medium, true); 00769 popup->addLabel(""); 00770 00771 const int def = CalcItemIndex(default_button); 00772 for (int i = 0; i < buttonmsgs.size(); i++ ) 00773 { 00774 QAbstractButton *but = popup->addButton(buttonmsgs[i]); 00775 if (def == i) 00776 but->setFocus(); 00777 } 00778 00779 DialogCode ret = popup->ExecPopup(); 00780 00781 popup->hide(); 00782 popup->deleteLater(); 00783 00784 return ret; 00785 } 00786 00787 MythProgressDialog::MythProgressDialog( 00788 const QString &message, int totalSteps, 00789 bool cancelButton, const QObject *target, const char *slot) 00790 : MythDialog(GetMythMainWindow(), "progress", false) 00791 { 00792 setObjectName("MythProgressDialog"); 00793 int screenwidth, screenheight; 00794 float wmult, hmult; 00795 00796 GetMythUI()->GetScreenSettings(screenwidth, wmult, screenheight, hmult); 00797 00798 setFont(GetMythUI()->GetMediumFont()); 00799 00800 GetMythUI()->ThemeWidget(this); 00801 00802 int yoff = screenheight / 3; 00803 int xoff = screenwidth / 10; 00804 setGeometry(xoff, yoff, screenwidth - xoff * 2, yoff); 00805 setFixedSize(QSize(screenwidth - xoff * 2, yoff)); 00806 00807 msglabel = new QLabel(); 00808 msglabel->setText(message); 00809 00810 QVBoxLayout *vlayout = new QVBoxLayout(); 00811 vlayout->addWidget(msglabel); 00812 00813 progress = new QProgressBar(); 00814 progress->setRange(0, totalSteps); 00815 00816 QHBoxLayout *hlayout = new QHBoxLayout(); 00817 hlayout->addWidget(progress); 00818 00819 if (cancelButton && slot && target) 00820 { 00821 MythPushButton *button = new MythPushButton( 00822 QObject::tr("Cancel"), NULL); 00823 button->setFocus(); 00824 hlayout->addWidget(button); 00825 connect(button, SIGNAL(pressed()), target, slot); 00826 } 00827 00828 setTotalSteps(totalSteps); 00829 00830 if (LCD *lcddev = LCD::Get()) 00831 { 00832 QList<LCDTextItem> textItems; 00833 00834 textItems.append(LCDTextItem(1, ALIGN_CENTERED, message, "Generic", 00835 false)); 00836 lcddev->switchToGeneric(textItems); 00837 } 00838 00839 hlayout->setSpacing(5); 00840 00841 vlayout->setMargin((int)(15 * wmult)); 00842 vlayout->setStretchFactor(msglabel, 5); 00843 00844 QWidget *hbox = new QWidget(); 00845 hbox->setLayout(hlayout); 00846 vlayout->addWidget(hbox); 00847 00848 QFrame *vbox = new QFrame(this); 00849 vbox->setObjectName(objectName() + "_vbox"); 00850 vbox->setLineWidth(3); 00851 vbox->setMidLineWidth(3); 00852 vbox->setFrameShape(QFrame::Panel); 00853 vbox->setFrameShadow(QFrame::Raised); 00854 vbox->setLayout(vlayout); 00855 00856 QVBoxLayout *lay = new QVBoxLayout(); 00857 lay->addWidget(vbox); 00858 setLayout(lay); 00859 00860 show(); 00861 00862 qApp->processEvents(); 00863 } 00864 00865 MythProgressDialog::~MythProgressDialog() 00866 { 00867 } 00868 00869 void MythProgressDialog::deleteLater(void) 00870 { 00871 hide(); 00872 MythDialog::deleteLater(); 00873 } 00874 00875 void MythProgressDialog::Close(void) 00876 { 00877 accept(); 00878 00879 LCD *lcddev = LCD::Get(); 00880 if (lcddev) 00881 { 00882 lcddev->switchToNothing(); 00883 lcddev->switchToTime(); 00884 } 00885 } 00886 00887 void MythProgressDialog::setProgress(int curprogress) 00888 { 00889 progress->setValue(curprogress); 00890 if (curprogress % steps == 0) 00891 { 00892 qApp->processEvents(); 00893 if (LCD *lcddev = LCD::Get()) 00894 { 00895 float fProgress = (float)curprogress / m_totalSteps; 00896 lcddev->setGenericProgress(fProgress); 00897 } 00898 } 00899 } 00900 00901 void MythProgressDialog::setLabel(QString newlabel) 00902 { 00903 msglabel->setText(newlabel); 00904 } 00905 00906 void MythProgressDialog::keyPressEvent(QKeyEvent *e) 00907 { 00908 bool handled = false; 00909 QStringList actions; 00910 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions); 00911 00912 for (int i = 0; i < actions.size() && !handled; i++) 00913 { 00914 QString action = actions[i]; 00915 if (action == "ESCAPE") 00916 handled = true; 00917 } 00918 00919 if (!handled) 00920 MythDialog::keyPressEvent(e); 00921 } 00922 00923 void MythProgressDialog::setTotalSteps(int totalSteps) 00924 { 00925 m_totalSteps = totalSteps; 00926 progress->setRange(0, totalSteps); 00927 steps = totalSteps / 1000; 00928 if (steps == 0) 00929 steps = 1; 00930 } 00931 00932 MythThemedDialog::MythThemedDialog(MythMainWindow *parent, 00933 const QString &window_name, 00934 const QString &theme_filename, 00935 const char *name, 00936 bool setsize) 00937 : MythDialog(parent, name, setsize) 00938 { 00939 setNoErase(); 00940 00941 theme = NULL; 00942 00943 if (!loadThemedWindow(window_name, theme_filename)) 00944 { 00945 QString msg = 00946 QString(tr("Could not locate '%1' in theme '%2'." 00947 "\n\nReturning to the previous menu.")) 00948 .arg(window_name).arg(theme_filename); 00949 MythPopupBox::showOkPopup(GetMythMainWindow(), 00950 tr("Missing UI Element"), msg); 00951 reject(); 00952 return; 00953 } 00954 } 00955 00956 MythThemedDialog::MythThemedDialog( 00957 MythMainWindow *parent, const char* name, bool setsize) : 00958 MythDialog(parent, name, setsize), widget_with_current_focus(NULL), 00959 theme(NULL), context(-1) 00960 { 00961 setNoErase(); 00962 } 00963 00964 bool MythThemedDialog::loadThemedWindow(QString window_name, 00965 QString theme_filename) 00966 { 00967 if (theme) 00968 delete theme; 00969 00970 context = -1; 00971 my_containers.clear(); 00972 widget_with_current_focus = NULL; 00973 00974 redrawRect = QRect(0, 0, 0, 0); 00975 00976 theme = new XMLParse(); 00977 theme->SetWMult(wmult); 00978 theme->SetHMult(hmult); 00979 if (!theme->LoadTheme(xmldata, window_name, theme_filename)) 00980 { 00981 return false; 00982 } 00983 00984 loadWindow(xmldata); 00985 00986 // 00987 // Auto-connect signals we know about 00988 // 00989 00990 // Loop over containers 00991 QList<LayerSet*>::iterator an_it = my_containers.begin(); 00992 for (; an_it != my_containers.end(); ++an_it) 00993 { 00994 LayerSet *looper = *an_it; 00995 // Loop over UITypes within each container 00996 vector<UIType *> *all_ui_type_objects = looper->getAllTypes(); 00997 vector<UIType *>::iterator i = all_ui_type_objects->begin(); 00998 for (; i != all_ui_type_objects->end(); ++i) 00999 { 01000 UIType *type = (*i); 01001 connect(type, SIGNAL(requestUpdate()), this, 01002 SLOT(updateForeground())); 01003 connect(type, SIGNAL(requestUpdate(const QRect &)), this, 01004 SLOT(updateForeground(const QRect &))); 01005 connect(type, SIGNAL(requestRegionUpdate(const QRect &)), this, 01006 SLOT(updateForegroundRegion(const QRect &))); 01007 } 01008 } 01009 01010 buildFocusList(); 01011 01012 updateBackground(); 01013 initForeground(); 01014 01015 return true; 01016 } 01017 01018 bool MythThemedDialog::buildFocusList() 01019 { 01020 // 01021 // Build a list of widgets that will take focus 01022 // 01023 01024 focus_taking_widgets.clear(); 01025 01026 01027 // Loop over containers 01028 QList<LayerSet*>::iterator another_it = my_containers.begin(); 01029 for (; another_it != my_containers.end(); ++another_it) 01030 { 01031 LayerSet *looper = *another_it; 01032 // Loop over UITypes within each container 01033 vector<UIType *> *all_ui_type_objects = looper->getAllTypes(); 01034 vector<UIType *>::iterator i = all_ui_type_objects->begin(); 01035 for (; i != all_ui_type_objects->end(); ++i) 01036 { 01037 UIType *type = (*i); 01038 if (type->canTakeFocus() && !type->isHidden() && 01039 (context == -1 || type->GetContext() == -1 || 01040 context == type->GetContext())) 01041 { 01042 focus_taking_widgets.push_back(type); 01043 } 01044 } 01045 } 01046 01047 return !focus_taking_widgets.empty(); 01048 } 01049 01050 MythThemedDialog::~MythThemedDialog() 01051 { 01052 if (theme) 01053 { 01054 delete theme; 01055 theme = NULL; 01056 } 01057 } 01058 01059 void MythThemedDialog::deleteLater(void) 01060 { 01061 if (theme) 01062 { 01063 delete theme; 01064 theme = NULL; 01065 } 01066 MythDialog::deleteLater(); 01067 } 01068 01069 void MythThemedDialog::loadWindow(QDomElement &element) 01070 { 01071 // 01072 // Parse all the child elements in the theme 01073 // 01074 01075 for (QDomNode child = element.firstChild(); !child.isNull(); 01076 child = child.nextSibling()) 01077 { 01078 QDomElement e = child.toElement(); 01079 if (!e.isNull()) 01080 { 01081 if (e.tagName() == "font") 01082 { 01083 theme->parseFont(e); 01084 } 01085 else if (e.tagName() == "container") 01086 { 01087 parseContainer(e); 01088 } 01089 else 01090 { 01091 LOG(VB_GENERAL, LOG_ALERT, 01092 QString("MythThemedDialog::loadWindow(): Do not " 01093 "understand DOM Element: '%1'. Ignoring.") 01094 .arg(e.tagName())); 01095 } 01096 } 01097 } 01098 } 01099 01100 void MythThemedDialog::parseContainer(QDomElement &element) 01101 { 01102 // 01103 // Have the them object parse the containers 01104 // but hold a pointer to each of them so 01105 // that we can iterate over them later 01106 // 01107 01108 QRect area; 01109 QString name; 01110 int a_context; 01111 theme->parseContainer(element, name, a_context, area); 01112 if (name.length() < 1) 01113 { 01114 LOG(VB_GENERAL, LOG_ALERT, 01115 "Failed to parse a container. Ignoring."); 01116 return; 01117 } 01118 01119 LayerSet *container_reference = theme->GetSet(name); 01120 my_containers.append(container_reference); 01121 } 01122 01123 void MythThemedDialog::parseFont(QDomElement &element) 01124 { 01125 // 01126 // this is just here so you can re-implement the virtual 01127 // function and do something special if you like 01128 // 01129 01130 theme->parseFont(element); 01131 } 01132 01133 void MythThemedDialog::initForeground() 01134 { 01135 my_foreground = my_background; 01136 updateForeground(); 01137 } 01138 01139 void MythThemedDialog::updateBackground() 01140 { 01141 // 01142 // Draw the background pixmap once 01143 // 01144 01145 QPixmap bground(size()); 01146 bground.fill(this, 0, 0); 01147 01148 QPainter tmp(&bground); 01149 01150 // 01151 // Ask the container holding anything 01152 // to do with the background to draw 01153 // itself on a pixmap 01154 // 01155 01156 LayerSet *container = theme->GetSet("background"); 01157 01158 // 01159 // *IFF* there is a background, draw it 01160 // 01161 if (container) 01162 { 01163 container->Draw(&tmp, 0, context); 01164 tmp.end(); 01165 } 01166 01167 // 01168 // Copy that pixmap to the permanent one 01169 // and tell Qt about it 01170 // 01171 01172 my_background = bground; 01173 QPalette palette; 01174 palette.setBrush(backgroundRole(), QBrush(my_background)); 01175 setPalette(palette); 01176 } 01177 01178 void MythThemedDialog::updateForeground() 01179 { 01180 QRect r = this->geometry(); 01181 updateForeground(r); 01182 } 01183 01184 QString ZeroSizedRect = QString("MythThemedDialog - Something is requesting" 01185 " a screen update of zero size. A widget probably has not done" 01186 " calculateScreeArea(). Will redraw the whole screen (inefficient!)."); 01187 01188 void MythThemedDialog::updateForeground(const QRect &r) 01189 { 01190 QRect rect_to_update = r; 01191 if (r.width() == 0 || r.height() == 0) 01192 { 01193 LOG(VB_GENERAL, LOG_ALERT, ZeroSizedRect); 01194 rect_to_update = this->geometry(); 01195 } 01196 01197 redrawRect = redrawRect.unite(r); 01198 01199 update(redrawRect); 01200 } 01201 01202 void MythThemedDialog::ReallyUpdateForeground(const QRect &r) 01203 { 01204 QRect rect_to_update = r; 01205 if (r.width() == 0 || r.height() == 0) 01206 { 01207 LOG(VB_GENERAL, LOG_ALERT, ZeroSizedRect); 01208 rect_to_update = this->geometry(); 01209 } 01210 01211 UpdateForegroundRect(rect_to_update); 01212 01213 redrawRect = QRect(0, 0, 0, 0); 01214 } 01215 01216 void MythThemedDialog::updateForegroundRegion(const QRect &r) 01217 { 01218 // Note: DrawRegion is never actually called now. Instead 01219 // of controls (only UIListTreeType did it) implementing an 01220 // optimized paint, we rely on clipping regions. 01221 UpdateForegroundRect(r); 01222 01223 update(r); 01224 } 01225 01226 void MythThemedDialog::UpdateForegroundRect(const QRect &inv_rect) 01227 { 01228 QPainter whole_dialog_painter(&my_foreground); 01229 01230 // Updating the background portion isn't optional. The old 01231 // behavior left remnants during context transitions if 01232 // they happened outside active containers for the current 01233 // context. 01234 whole_dialog_painter.drawPixmap(inv_rect.topLeft(), my_background, 01235 inv_rect); 01236 01237 QList<LayerSet*>::iterator an_it = my_containers.begin(); 01238 for (; an_it != my_containers.end(); ++an_it) 01239 { 01240 LayerSet *looper = *an_it; 01241 QRect container_area = looper->GetAreaRect(); 01242 01243 // 01244 // Only paint if the container's area is valid 01245 // and it intersects with whatever Qt told us 01246 // needed to be repainted 01247 // 01248 01249 const QRect intersect = inv_rect.intersect(container_area); 01250 int looper_context = looper->GetContext(); 01251 if (container_area.isValid() && 01252 (looper_context == context || looper_context == -1) && 01253 intersect.isValid() && 01254 looper->GetName().toLower() != "background") 01255 { 01256 // 01257 // Debugging 01258 // 01259 #if 0 01260 LOG(VB_GENERAL, LOG_DEBUG, 01261 QString("A container called \"%1\" said its " 01262 "area is %2,%3 to %4,%5") 01263 .arg(looper->GetName()) 01264 .arg(container_area.left()) 01265 .arg(container_area.top()) 01266 .arg(container_area.left() + container_area.width()) 01267 .arg(container_area.top() + container_area.height())); 01268 #endif 01269 01270 // 01271 // Loop over the draworder layers 01272 01273 whole_dialog_painter.save(); 01274 01275 whole_dialog_painter.setClipRect(intersect); 01276 whole_dialog_painter.translate(container_area.left(), 01277 container_area.top()); 01278 01279 for (int i = 0; i <= looper->getLayers(); ++i) 01280 { 01281 looper->Draw(&whole_dialog_painter, i, context); 01282 } 01283 01284 whole_dialog_painter.restore(); 01285 } 01286 } 01287 } 01288 01289 void MythThemedDialog::paintEvent(QPaintEvent *e) 01290 { 01291 if (redrawRect.width() > 0 && redrawRect.height() > 0) 01292 ReallyUpdateForeground(redrawRect); 01293 01294 { // Make sure QPainter is destructed before calling MythDialog's paint.. 01295 QPainter p(this); 01296 p.drawPixmap(e->rect().topLeft(), my_foreground, e->rect()); 01297 } 01298 MythDialog::paintEvent(e); 01299 } 01300 01301 bool MythThemedDialog::assignFirstFocus() 01302 { 01303 if (widget_with_current_focus) 01304 { 01305 widget_with_current_focus->looseFocus(); 01306 } 01307 01308 vector<UIType*>::iterator an_it = focus_taking_widgets.begin(); 01309 for (; an_it != focus_taking_widgets.end(); ++an_it) 01310 { 01311 UIType *looper = *an_it; 01312 if (looper->canTakeFocus()) 01313 { 01314 widget_with_current_focus = looper; 01315 widget_with_current_focus->takeFocus(); 01316 return true; 01317 } 01318 } 01319 01320 return false; 01321 } 01322 01323 bool MythThemedDialog::nextPrevWidgetFocus(bool up_or_down) 01324 { 01325 if (up_or_down) 01326 { 01327 bool reached_current = false; 01328 01329 vector<UIType*>::iterator an_it = focus_taking_widgets.begin(); 01330 for (; an_it != focus_taking_widgets.end(); ++an_it) 01331 { 01332 UIType *looper = *an_it; 01333 if (reached_current && looper->canTakeFocus()) 01334 { 01335 widget_with_current_focus->looseFocus(); 01336 widget_with_current_focus = looper; 01337 widget_with_current_focus->takeFocus(); 01338 return true; 01339 } 01340 01341 if (looper == widget_with_current_focus) 01342 { 01343 reached_current= true; 01344 } 01345 } 01346 01347 if (assignFirstFocus()) 01348 { 01349 return true; 01350 } 01351 return false; 01352 } 01353 else 01354 { 01355 bool reached_current = false; 01356 01357 vector<UIType*>::reverse_iterator an_it = focus_taking_widgets.rbegin(); 01358 for (; an_it != focus_taking_widgets.rend(); ++an_it) 01359 { 01360 UIType *looper = *an_it; 01361 01362 if (reached_current && looper->canTakeFocus()) 01363 { 01364 widget_with_current_focus->looseFocus(); 01365 widget_with_current_focus = looper; 01366 widget_with_current_focus->takeFocus(); 01367 return true; 01368 } 01369 01370 if (looper == widget_with_current_focus) 01371 { 01372 reached_current= true; 01373 } 01374 } 01375 01376 if (reached_current) 01377 { 01378 an_it = focus_taking_widgets.rbegin(); 01379 for (; an_it != focus_taking_widgets.rend(); ++an_it) 01380 { 01381 UIType *looper = *an_it; 01382 01383 if (looper->canTakeFocus()) 01384 { 01385 widget_with_current_focus->looseFocus(); 01386 widget_with_current_focus = looper; 01387 widget_with_current_focus->takeFocus(); 01388 return true; 01389 } 01390 } 01391 } 01392 return false; 01393 } 01394 return false; 01395 } 01396 01397 void MythThemedDialog::activateCurrent() 01398 { 01399 if (widget_with_current_focus) 01400 { 01401 widget_with_current_focus->activate(); 01402 } 01403 else 01404 { 01405 LOG(VB_GENERAL, LOG_ALERT, "MythThemedDialog::activateCurrent() - " 01406 "there is no current widget!"); 01407 } 01408 } 01409 01410 namespace 01411 { 01412 template <typename T> 01413 T *GetUIType(MythThemedDialog *dialog, const QString &name) 01414 { 01415 UIType *sf = dialog->getUIObject(name); 01416 if (sf) 01417 { 01418 T *ret = dynamic_cast<T *>(sf); 01419 if (ret) 01420 return ret; 01421 } 01422 return 0; 01423 } 01424 }; 01425 01426 UIType* MythThemedDialog::getUIObject(const QString &name) 01427 { 01428 // 01429 // Try and find the UIType target referenced 01430 // by "name". 01431 // 01432 // At some point, it would be nice to speed 01433 // this up with a map across all instantiated 01434 // UIType objects "owned" by this dialog 01435 // 01436 01437 QList<LayerSet*>::iterator an_it = my_containers.begin(); 01438 for (; an_it != my_containers.end(); ++an_it) 01439 { 01440 UIType *hunter = (*an_it)->GetType(name); 01441 if (hunter) 01442 return hunter; 01443 } 01444 01445 return NULL; 01446 } 01447 01448 UIType* MythThemedDialog::getCurrentFocusWidget() 01449 { 01450 if (widget_with_current_focus) 01451 { 01452 return widget_with_current_focus; 01453 } 01454 return NULL; 01455 } 01456 01457 void MythThemedDialog::setCurrentFocusWidget(UIType* widget) 01458 { 01459 // make sure this widget is in the list of widgets that can take focus 01460 vector<UIType*>::iterator it = 01461 std::find(focus_taking_widgets.begin(), 01462 focus_taking_widgets.end(), widget); 01463 if (it == focus_taking_widgets.end()) 01464 return; 01465 01466 if (widget_with_current_focus) 01467 widget_with_current_focus->looseFocus(); 01468 01469 widget_with_current_focus = widget; 01470 widget_with_current_focus->takeFocus(); 01471 } 01472 01473 UIKeyboardType *MythThemedDialog::getUIKeyboardType(const QString &name) 01474 { 01475 return GetUIType<UIKeyboardType>(this, name); 01476 } 01477 01478 LayerSet *MythThemedDialog::getContainer(const QString &name) 01479 { 01480 QList<LayerSet*>::iterator an_it = my_containers.begin(); 01481 for (; an_it != my_containers.end(); ++an_it) 01482 { 01483 if ((*an_it)->GetName() == name) 01484 return *an_it; 01485 } 01486 01487 return NULL; 01488 } 01489 01490 fontProp* MythThemedDialog::getFont(const QString &name) 01491 { 01492 fontProp* font = NULL; 01493 if (theme) 01494 font = theme->GetFont(name, true); 01495 01496 return font; 01497 }
1.7.6.1