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
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
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
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
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
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
00988
00989
00990
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
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
01022
01023
01024 focus_taking_widgets.clear();
01025
01026
01027
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
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
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
01104
01105
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
01127
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
01143
01144
01145 QPixmap bground(size());
01146 bground.fill(this, 0, 0);
01147
01148 QPainter tmp(&bground);
01149
01150
01151
01152
01153
01154
01155
01156 LayerSet *container = theme->GetSet("background");
01157
01158
01159
01160
01161 if (container)
01162 {
01163 container->Draw(&tmp, 0, context);
01164 tmp.end();
01165 }
01166
01167
01168
01169
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
01219
01220
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
01231
01232
01233
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
01245
01246
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
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
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 {
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
01430
01431
01432
01433
01434
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
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 }