00001
00010 #include "mythuiwebbrowser.h"
00011
00012
00013 #include <QApplication>
00014 #include <QWebFrame>
00015 #include <QWebHistory>
00016 #include <QPainter>
00017 #include <QDir>
00018 #include <QBuffer>
00019 #include <QStyle>
00020 #include <QKeyEvent>
00021 #include <QDomDocument>
00022 #include <QNetworkCookieJar>
00023
00024
00025 #include "mythpainter.h"
00026 #include "mythimage.h"
00027 #include "mythmainwindow.h"
00028 #include "mythfontproperties.h"
00029 #include "mythlogging.h"
00030 #include "mythdb.h"
00031 #include "mythdirs.h"
00032 #include "mythuihelper.h"
00033 #include "mythcorecontext.h"
00034 #include "mythdownloadmanager.h"
00035 #include "mythdialogbox.h"
00036 #include "mythprogressdialog.h"
00037 #include "mythuiscrollbar.h"
00038
00039 struct MimeType
00040 {
00041 QString mimeType;
00042 QString extension;
00043 bool isVideo;
00044 };
00045
00046 static MimeType SupportedMimeTypes[] =
00047 {
00048 { "audio/mpeg3", "mp3", false },
00049 { "audio/x-mpeg-3", "mp3", false },
00050 { "audio/mpeg", "mp2", false },
00051 { "audio/x-mpeg", "mp2", false },
00052 { "audio/ogg", "ogg", false },
00053 { "audio/ogg", "oga", false },
00054 { "audio/flac", "flac", false },
00055 { "audio/x-ms-wma", "wma", false },
00056 { "audio/wav", "wav", false },
00057 { "audio/x-wav", "wav", false },
00058 { "audio/ac3", "ac3", false },
00059 { "audio/x-ac3", "ac3", false },
00060 { "audio/x-oma", "oma", false },
00061 { "audio/x-realaudio", "ra", false },
00062 { "audio/dts", "dts", false },
00063 { "audio/x-dts", "dts", false },
00064 { "audio/aac", "aac", false },
00065 { "audio/x-aac", "aac", false },
00066 { "audio/m4a", "m4a", false },
00067 { "audio/x-m4a", "m4a", false },
00068 { "video/mpeg", "mpg", true },
00069 { "video/mpeg", "mpeg", true },
00070 { "video/x-ms-wmv", "wmv", true },
00071 { "video/x-ms-wmv", "avi", true },
00072 { "application/x-troff-msvideo", "avi", true },
00073 { "video/avi", "avi", true },
00074 { "video/msvideo", "avi", true },
00075 { "video/x-msvideo", "avi", true }
00076 };
00077
00078 static int SupportedMimeTypesCount = sizeof(SupportedMimeTypes) /
00079 sizeof(SupportedMimeTypes[0]);
00080
00081 static QNetworkAccessManager *networkManager = NULL;
00082
00083 static void DestroyNetworkAccessManager(void)
00084 {
00085 if (networkManager)
00086 {
00087 MythDownloadManager *dlmgr = GetMythDownloadManager();
00088 if (dlmgr)
00089 {
00090 LOG(VB_GENERAL, LOG_DEBUG, "Refreshing DLManager's Cookie Jar");
00091 dlmgr->refreshCookieJar(networkManager->cookieJar());
00092 }
00093
00094 delete networkManager;
00095 networkManager = NULL;
00096 }
00097 }
00098
00099 static QNetworkAccessManager *GetNetworkAccessManager(void)
00100 {
00101 if (networkManager)
00102 return networkManager;
00103
00104 networkManager = new QNetworkAccessManager();
00105 LOG(VB_GENERAL, LOG_DEBUG, "Copying DLManager's Cookie Jar");
00106 networkManager->setCookieJar(GetMythDownloadManager()->copyCookieJar());
00107
00108 atexit(DestroyNetworkAccessManager);
00109
00110 return networkManager;
00111 }
00112
00118 BrowserApi::BrowserApi(QObject *parent) : QObject(parent)
00119 {
00120 gCoreContext->addListener(this);
00121 }
00122
00123 BrowserApi::~BrowserApi(void)
00124 {
00125 gCoreContext->removeListener(this);
00126 }
00127
00128 void BrowserApi::setWebView(QWebView *view)
00129 {
00130 QWebPage *page = view->page();
00131 m_frame = page->mainFrame();
00132
00133 attachObject();
00134 connect(m_frame, SIGNAL(javaScriptWindowObjectCleared()), this,
00135 SLOT(attachObject()));
00136 }
00137
00138 void BrowserApi::attachObject(void)
00139 {
00140 m_frame->addToJavaScriptWindowObject(QString("MusicPlayer"), this);
00141 }
00142
00143 void BrowserApi::Play(void)
00144 {
00145 MythEvent me(QString("MUSIC_COMMAND %1 PLAY").arg(gCoreContext->GetHostName()));
00146 gCoreContext->dispatch(me);
00147 }
00148
00149 void BrowserApi::Stop(void)
00150 {
00151 MythEvent me(QString("MUSIC_COMMAND %1 STOP").arg(gCoreContext->GetHostName()));
00152 gCoreContext->dispatch(me);
00153 }
00154
00155 void BrowserApi::Pause(void)
00156 {
00157 MythEvent me(QString("MUSIC_COMMAND %1 PAUSE %1").arg(gCoreContext->GetHostName()));
00158 gCoreContext->dispatch(me);
00159 }
00160
00161 void BrowserApi::SetVolume(int volumn)
00162 {
00163 MythEvent me(QString("MUSIC_COMMAND %1 SET_VOLUME %2")
00164 .arg(gCoreContext->GetHostName()).arg(volumn));
00165 gCoreContext->dispatch(me);
00166 }
00167
00168 int BrowserApi::GetVolume(void)
00169 {
00170 m_gotAnswer = false;
00171
00172 MythEvent me(QString("MUSIC_COMMAND %1 GET_VOLUME")
00173 .arg(gCoreContext->GetHostName()));
00174 gCoreContext->dispatch(me);
00175
00176 QTime timer;
00177 timer.start();
00178
00179 while (timer.elapsed() < 2000 && !m_gotAnswer)
00180 {
00181 qApp->processEvents();
00182 usleep(10000);
00183 }
00184
00185 if (m_gotAnswer)
00186 return m_answer.toInt();
00187
00188 return -1;
00189 }
00190
00191 void BrowserApi::PlayFile(QString filename)
00192 {
00193 MythEvent me(QString("MUSIC_COMMAND %1 PLAY_FILE '%2'")
00194 .arg(gCoreContext->GetHostName()).arg(filename));
00195 gCoreContext->dispatch(me);
00196 }
00197
00198 void BrowserApi::PlayTrack(int trackID)
00199 {
00200 MythEvent me(QString("MUSIC_COMMAND %1 PLAY_TRACK %2")
00201 .arg(gCoreContext->GetHostName()).arg(trackID));
00202 gCoreContext->dispatch(me);
00203 }
00204
00205 void BrowserApi::PlayURL(QString url)
00206 {
00207 MythEvent me(QString("MUSIC_COMMAND %1 PLAY_URL %2")
00208 .arg(gCoreContext->GetHostName()).arg(url));
00209 gCoreContext->dispatch(me);
00210 }
00211
00212 QString BrowserApi::GetMetadata(void)
00213 {
00214 m_gotAnswer = false;
00215
00216 MythEvent me(QString("MUSIC_COMMAND %1 GET_METADATA")
00217 .arg(gCoreContext->GetHostName()));
00218 gCoreContext->dispatch(me);
00219
00220 QTime timer;
00221 timer.start();
00222
00223 while (timer.elapsed() < 2000 && !m_gotAnswer)
00224 {
00225 qApp->processEvents();
00226 usleep(10000);
00227 }
00228
00229 if (m_gotAnswer)
00230 return m_answer;
00231
00232 return QString("unknown");
00233 }
00234
00235 void BrowserApi::customEvent(QEvent *e)
00236 {
00237 if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage)
00238 {
00239 MythEvent *me = (MythEvent *)e;
00240 QString message = me->Message();
00241
00242 if (message.left(13) != "MUSIC_CONTROL")
00243 return;
00244
00245 QStringList tokens = message.simplified().split(" ");
00246
00247 if ((tokens.size() >= 4) && (tokens[1] == "ANSWER")
00248 && (tokens[2] == gCoreContext->GetHostName()))
00249 {
00250 m_answer = tokens[3];
00251
00252 for (int i = 4; i < tokens.size(); i++)
00253 m_answer += QString(" ") + tokens[i];
00254
00255 m_gotAnswer = true;
00256 }
00257 }
00258 }
00259
00260 MythWebPage::MythWebPage(QObject *parent)
00261 : QWebPage(parent)
00262 {
00263 setNetworkAccessManager(GetNetworkAccessManager());
00264 }
00265
00266 MythWebPage::~MythWebPage()
00267 {
00268 DestroyNetworkAccessManager();
00269 }
00270
00271 bool MythWebPage::supportsExtension(Extension extension) const
00272 {
00273 if (extension == QWebPage::ErrorPageExtension)
00274 return true;
00275
00276 return false;
00277 }
00278
00279 bool MythWebPage::extension(Extension extension, const ExtensionOption *option,
00280 ExtensionReturn *output)
00281 {
00282 if (extension == QWebPage::ErrorPageExtension)
00283 {
00284 ErrorPageExtensionOption *erroroption;
00285 erroroption = (ErrorPageExtensionOption *) option;
00286 ErrorPageExtensionReturn *erroroutput;
00287 erroroutput = (ErrorPageExtensionReturn *) output;
00288
00289 if (!option || !output)
00290 return false;
00291
00292 QString filename = "htmls/notfound.html";
00293
00294 if (!GetMythUI()->FindThemeFile(filename))
00295 return false;
00296
00297 QFile file(QLatin1String(qPrintable(filename)));
00298 bool isOpened = file.open(QIODevice::ReadOnly);
00299
00300 if (!isOpened)
00301 return false;
00302
00303 QString title = tr("Error loading page: %1").arg(erroroption->url.toString());
00304 QString html = QString(QLatin1String(file.readAll()))
00305 .arg(title)
00306 .arg(erroroption->errorString)
00307 .arg(erroroption->url.toString());
00308
00309 QBuffer imageBuffer;
00310 imageBuffer.open(QBuffer::ReadWrite);
00311 QIcon icon = qApp->style()->standardIcon(QStyle::SP_MessageBoxWarning,
00312 0, 0);
00313 QPixmap pixmap = icon.pixmap(QSize(32, 32));
00314
00315 if (pixmap.save(&imageBuffer, "PNG"))
00316 {
00317 html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"),
00318 QString(QLatin1String(imageBuffer.buffer().toBase64())));
00319 }
00320
00321 erroroutput->content = html.toUtf8();
00322
00323 return true;
00324 }
00325
00326 return false;
00327 }
00328
00329 QString MythWebPage::userAgentForUrl(const QUrl &url) const
00330 {
00331 return QWebPage::userAgentForUrl(url).replace("Safari", "MythBrowser");
00332 }
00333
00339 MythWebView::MythWebView(QWidget *parent, MythUIWebBrowser *parentBrowser)
00340 : QWebView(parent),
00341 m_webpage(new MythWebPage(this))
00342 {
00343 setPage(m_webpage);
00344
00345 m_parentBrowser = parentBrowser;
00346 m_busyPopup = NULL;
00347
00348 connect(page(), SIGNAL(unsupportedContent(QNetworkReply *)),
00349 this, SLOT(handleUnsupportedContent(QNetworkReply *)));
00350
00351 connect(page(), SIGNAL(downloadRequested(const QNetworkRequest &)),
00352 this, SLOT(handleDownloadRequested(QNetworkRequest)));
00353
00354 page()->setForwardUnsupportedContent(true);
00355
00356 m_api = new BrowserApi(this);
00357 m_api->setWebView(this);
00358
00359 m_downloadAndPlay = false;
00360 m_downloadReply = NULL;
00361 }
00362
00363 MythWebView::~MythWebView(void)
00364 {
00365 delete m_webpage;
00366 delete m_api;
00367 }
00368
00373 const char *kgetType = "\
00374 function activeElement()\
00375 {\
00376 var type;\
00377 type = document.activeElement.type;\
00378 return type;\
00379 }\
00380 activeElement();";
00381
00382 void MythWebView::keyPressEvent(QKeyEvent *event)
00383 {
00384
00385 QString type = m_parentBrowser->evaluateJavaScript(QString(kgetType))
00386 .toString().toLower();
00387 bool editHasFocus = (type == "text" || type == "textarea" ||
00388 type == "password");
00389
00390
00391
00392 if (editHasFocus || m_parentBrowser->IsInputToggled())
00393 {
00394
00395 QWebView::keyPressEvent(event);
00396 }
00397 else
00398 {
00399
00400
00401 QStringList actions;
00402 bool handled = false;
00403 handled = GetMythMainWindow()->TranslateKeyPress("Browser", event,
00404 actions);
00405
00406 for (int i = 0; i < actions.size() && !handled; i++)
00407 {
00408 QString action = actions[i];
00409 handled = true;
00410
00411 if (action == "NEXTLINK")
00412 {
00413 QKeyEvent tabKey(event->type(), Qt::Key_Tab,
00414 event->modifiers(), QString(),
00415 event->isAutoRepeat(), event->count());
00416 *event = tabKey;
00417 QWebView::keyPressEvent(event);
00418 return;
00419 }
00420 else if (action == "PREVIOUSLINK")
00421 {
00422 QKeyEvent shiftTabKey(event->type(), Qt::Key_Tab,
00423 event->modifiers() | Qt::ShiftModifier,
00424 QString(),
00425 event->isAutoRepeat(), event->count());
00426 *event = shiftTabKey;
00427 QWebView::keyPressEvent(event);
00428 return;
00429 }
00430 else if (action == "FOLLOWLINK")
00431 {
00432 QKeyEvent returnKey(event->type(), Qt::Key_Return,
00433 event->modifiers(), QString(),
00434 event->isAutoRepeat(), event->count());
00435 *event = returnKey;
00436 QWebView::keyPressEvent(event);
00437 return;
00438 }
00439 }
00440
00441
00442
00443 QCoreApplication::postEvent(GetMythMainWindow(), new QKeyEvent(*event));
00444 }
00445 }
00446
00447 void MythWebView::wheelEvent(QWheelEvent *event)
00448 {
00449 event->accept();
00450 QCoreApplication::postEvent(GetMythMainWindow(), new QWheelEvent(*event));
00451 }
00452
00453 void MythWebView::handleUnsupportedContent(QNetworkReply *reply)
00454 {
00455 if (reply->error() == QNetworkReply::NoError)
00456 {
00457 stop();
00458
00459 QVariant header = reply->header(QNetworkRequest::ContentTypeHeader);
00460
00461 if (header != QVariant())
00462 LOG(VB_GENERAL, LOG_ERR,
00463 QString("MythWebView::handleUnsupportedContent - %1")
00464 .arg(header.toString()));
00465
00466 m_downloadReply = reply;
00467 m_downloadRequest = reply->request();
00468 m_downloadAndPlay = false;
00469 showDownloadMenu();
00470
00471 return;
00472 }
00473 }
00474
00475 void MythWebView::handleDownloadRequested(const QNetworkRequest &request)
00476 {
00477 m_downloadReply = NULL;
00478 doDownloadRequested(request);
00479 }
00480
00481 void MythWebView::doDownloadRequested(const QNetworkRequest &request)
00482 {
00483 m_downloadRequest = request;
00484
00485
00486 QFileInfo fi(request.url().path());
00487 QString basename(fi.completeBaseName());
00488 QString extension = fi.suffix().toLower();
00489 QString mimetype = getReplyMimetype();
00490
00491
00492 QString saveBaseName = basename;
00493
00494 if (!m_parentBrowser->GetDefaultSaveFilename().isEmpty())
00495 {
00496 QFileInfo savefi(m_parentBrowser->GetDefaultSaveFilename());
00497 saveBaseName = savefi.completeBaseName();
00498 }
00499
00500
00501 if (saveBaseName.isEmpty())
00502 saveBaseName = "unnamed_download";
00503
00504
00505 if (extension.isEmpty())
00506 extension = getExtensionForMimetype(mimetype);
00507
00508 if (!extension.isEmpty())
00509 extension = '.' + extension;
00510
00511 QString saveFilename = QString("%1%2%3")
00512 .arg(m_parentBrowser->GetDefaultSaveDirectory())
00513 .arg(saveBaseName)
00514 .arg(extension);
00515
00516
00517 if (QFile::exists(saveFilename))
00518 {
00519 int i = 1;
00520
00521 do
00522 {
00523 saveFilename = QString("%1%2-%3%4")
00524 .arg(m_parentBrowser->GetDefaultSaveDirectory())
00525 .arg(saveBaseName)
00526 .arg(QString::number(i++))
00527 .arg(extension);
00528 }
00529 while (QFile::exists(saveFilename));
00530 }
00531
00532
00533 if (m_downloadAndPlay)
00534 {
00535 doDownload(saveFilename);
00536 }
00537 else
00538 {
00539 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00540
00541 QString msg = tr("Enter filename to save file");
00542 MythTextInputDialog *input = new MythTextInputDialog(popupStack, msg,
00543 FilterNone, false,
00544 saveFilename);
00545
00546 if (input->Create())
00547 {
00548 input->SetReturnEvent(this, "filenamedialog");
00549 popupStack->AddScreen(input);
00550 }
00551 else
00552 delete input;
00553 }
00554 }
00555
00556 void MythWebView::doDownload(const QString &saveFilename)
00557 {
00558 if (saveFilename.isEmpty())
00559 return;
00560
00561 openBusyPopup(QObject::tr("Downloading file. Please wait..."));
00562
00563
00564
00565 GetMythDownloadManager()->queueDownload(m_downloadRequest.url().toString(),
00566 saveFilename, this);
00567 }
00568
00569 void MythWebView::openBusyPopup(const QString &message)
00570 {
00571 if (m_busyPopup)
00572 return;
00573
00574 QString msg(tr("Downloading..."));
00575
00576 if (!message.isEmpty())
00577 msg = message;
00578
00579 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00580 m_busyPopup = new MythUIBusyDialog(msg, popupStack, "downloadbusydialog");
00581
00582 if (m_busyPopup->Create())
00583 popupStack->AddScreen(m_busyPopup, false);
00584 }
00585
00586 void MythWebView::closeBusyPopup(void)
00587 {
00588 if (m_busyPopup)
00589 m_busyPopup->Close();
00590
00591 m_busyPopup = NULL;
00592 }
00593
00594 void MythWebView::customEvent(QEvent *event)
00595 {
00596 if (event->type() == DialogCompletionEvent::kEventType)
00597 {
00598 DialogCompletionEvent *dce = (DialogCompletionEvent *)(event);
00599
00600
00601 if (dce->GetResult() < 0)
00602 return;
00603
00604 QString resultid = dce->GetId();
00605 QString resulttext = dce->GetResultText();
00606
00607 if (resultid == "filenamedialog")
00608 doDownload(resulttext);
00609 else if (resultid == "downloadmenu")
00610 {
00611 if (resulttext == tr("Play the file"))
00612 {
00613 QFileInfo fi(m_downloadRequest.url().path());
00614 QString basename(fi.baseName());
00615 QString extension = fi.suffix();
00616 QString mimeType = getReplyMimetype();
00617
00618 if (isMusicFile(extension, mimeType))
00619 {
00620 MythEvent me(QString("MUSIC_COMMAND %1 PLAY_URL %2")
00621 .arg(gCoreContext->GetHostName())
00622 .arg(m_downloadRequest.url().toString()));
00623 gCoreContext->dispatch(me);
00624 }
00625 else if (isVideoFile(extension, mimeType))
00626 GetMythMainWindow()->HandleMedia("Internal",
00627 m_downloadRequest.url().toString());
00628 else
00629 LOG(VB_GENERAL, LOG_ERR,
00630 QString("MythWebView: Asked to play a file with "
00631 "extension '%1' but don't know how")
00632 .arg(extension));
00633 }
00634 else if (resulttext == tr("Download the file"))
00635 {
00636 doDownloadRequested(m_downloadRequest);
00637 }
00638 else if (resulttext == tr("Download and play the file"))
00639 {
00640 m_downloadAndPlay = true;
00641 doDownloadRequested(m_downloadRequest);
00642 }
00643 }
00644 }
00645 else if ((MythEvent::Type)(event->type()) == MythEvent::MythEventMessage)
00646 {
00647 MythEvent *me = (MythEvent *)event;
00648 QStringList tokens = me->Message().split(" ", QString::SkipEmptyParts);
00649
00650 if (tokens.isEmpty())
00651 return;
00652
00653 if (tokens[0] == "DOWNLOAD_FILE")
00654 {
00655 QStringList args = me->ExtraDataList();
00656
00657 if (tokens[1] == "UPDATE")
00658 {
00659
00660 }
00661 else if (tokens[1] == "FINISHED")
00662 {
00663 int fileSize = args[2].toInt();
00664 int errorCode = args[4].toInt();
00665 QString filename = args[1];
00666
00667 closeBusyPopup();
00668
00669 if ((errorCode != 0) || (fileSize == 0))
00670 ShowOkPopup(tr("ERROR downloading file."));
00671 else if (m_downloadAndPlay)
00672 GetMythMainWindow()->HandleMedia("Internal", filename);
00673
00674 MythEvent me(QString("BROWSER_DOWNLOAD_FINISHED"), args);
00675 gCoreContext->dispatch(me);
00676 }
00677 }
00678 }
00679 }
00680
00681 void MythWebView::showDownloadMenu(void)
00682 {
00683 QFileInfo fi(m_downloadRequest.url().path());
00684 QString basename(fi.baseName());
00685 QString extension = fi.suffix();
00686 QString mimeType = getReplyMimetype();
00687
00688 QString label = tr("What do you want to do with this file?");
00689
00690 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00691
00692 MythDialogBox *menu = new MythDialogBox(label, popupStack, "downloadmenu");
00693
00694 if (!menu->Create())
00695 {
00696 delete menu;
00697 return;
00698 }
00699
00700 menu->SetReturnEvent(this, "downloadmenu");
00701
00702 if (isMusicFile(extension, mimeType))
00703 menu->AddButton(tr("Play the file"));
00704
00705 if (isVideoFile(extension, mimeType))
00706 menu->AddButton(tr("Download and play the file"));
00707
00708 menu->AddButton(tr("Download the file"));
00709 menu->AddButton(tr("Cancel"));
00710
00711 popupStack->AddScreen(menu);
00712 }
00713
00714 QString MythWebView::getExtensionForMimetype(const QString &mimetype)
00715 {
00716 for (int x = 0; x < SupportedMimeTypesCount; x++)
00717 {
00718 if (!mimetype.isEmpty() && mimetype == SupportedMimeTypes[x].mimeType)
00719 return SupportedMimeTypes[x].extension;
00720 }
00721
00722 return QString("");
00723 }
00724
00725 bool MythWebView::isMusicFile(const QString &extension, const QString &mimetype)
00726 {
00727 for (int x = 0; x < SupportedMimeTypesCount; x++)
00728 {
00729 if (!SupportedMimeTypes[x].isVideo)
00730 {
00731 if (!mimetype.isEmpty() &&
00732 mimetype == SupportedMimeTypes[x].mimeType)
00733 return true;
00734
00735 if (!extension.isEmpty() &&
00736 extension.toLower() == SupportedMimeTypes[x].extension)
00737 return true;
00738 }
00739 }
00740
00741 return false;
00742 }
00743
00744 bool MythWebView::isVideoFile(const QString &extension, const QString &mimetype)
00745 {
00746 for (int x = 0; x < SupportedMimeTypesCount; x++)
00747 {
00748 if (SupportedMimeTypes[x].isVideo)
00749 {
00750 if (!mimetype.isEmpty() &&
00751 mimetype == SupportedMimeTypes[x].mimeType)
00752 return true;
00753
00754 if (!extension.isEmpty() &&
00755 extension.toLower() == SupportedMimeTypes[x].extension)
00756 return true;
00757 }
00758 }
00759
00760 return false;
00761 }
00762
00763 QString MythWebView::getReplyMimetype(void)
00764 {
00765 if (!m_downloadReply)
00766 return QString();
00767
00768 QString mimeType;
00769 QVariant header = m_downloadReply->header(QNetworkRequest::ContentTypeHeader);
00770
00771 if (header != QVariant())
00772 mimeType = header.toString();
00773
00774 return mimeType;
00775 }
00776
00777 QWebView *MythWebView::createWindow(QWebPage::WebWindowType type)
00778 {
00779 (void) type;
00780 return (QWebView *) this;
00781 }
00782
00783
00825 MythUIWebBrowser::MythUIWebBrowser(MythUIType *parent, const QString &name)
00826 : MythUIType(parent, name),
00827 m_parentScreen(NULL),
00828 m_browser(NULL), m_image(NULL),
00829 m_active(false), m_wasActive(false),
00830 m_initialized(false), m_lastUpdateTime(QTime()),
00831 m_updateInterval(0), m_zoom(1.0),
00832 m_bgColor("White"), m_widgetUrl(QUrl()), m_userCssFile(""),
00833 m_defaultSaveDir(GetConfDir() + "/MythBrowser/"),
00834 m_defaultSaveFilename(""),
00835 m_inputToggled(false), m_lastMouseAction(""),
00836 m_mouseKeyCount(0), m_lastMouseActionTime(),
00837 m_horizontalScrollbar(NULL), m_verticalScrollbar(NULL)
00838 {
00839 SetCanTakeFocus(true);
00840 m_scrollAnimation.setDuration(0);
00841 }
00842
00846 void MythUIWebBrowser::Finalize(void)
00847 {
00848 Init();
00849 MythUIType::Finalize();
00850 }
00851
00859 void MythUIWebBrowser::Init(void)
00860 {
00861 if (m_initialized)
00862 return;
00863
00864 if (!m_browserArea.isValid())
00865 m_browserArea = m_Area;
00866
00867 m_browser = new MythWebView(GetMythMainWindow()->GetPaintWindow(), this);
00868 m_browser->setPalette(qApp->style()->standardPalette());
00869 m_browser->setGeometry(m_browserArea);
00870 m_browser->setFixedSize(m_browserArea.size());
00871 m_browser->move(m_browserArea.x(), m_browserArea.y());
00872 m_browser->page()->setLinkDelegationPolicy(QWebPage::DontDelegateLinks);
00873
00874 bool err = false;
00875 UIUtilW::Assign(this, m_horizontalScrollbar, "horizscrollbar", &err);
00876 UIUtilW::Assign(this, m_verticalScrollbar, "vertscrollbar", &err);
00877 if (m_horizontalScrollbar)
00878 {
00879 QWebFrame* frame = m_browser->page()->currentFrame();
00880 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
00881 }
00882
00883 if (m_verticalScrollbar)
00884 {
00885 QWebFrame* frame = m_browser->page()->currentFrame();
00886 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
00887 }
00888
00889
00890 if (!m_userCssFile.isEmpty())
00891 {
00892 QString filename = m_userCssFile;
00893
00894 if (GetMythUI()->FindThemeFile(filename))
00895 LoadUserStyleSheet(QUrl("file://" + filename));
00896 }
00897 else
00898 {
00899
00900 QString filename = "htmls/mythbrowser.css";
00901
00902 if (GetMythUI()->FindThemeFile(filename))
00903 LoadUserStyleSheet(QUrl("file://" + filename));
00904 }
00905
00906 m_browser->winId();
00907
00908 SetActive(m_active);
00909
00910 connect(m_browser, SIGNAL(loadStarted()),
00911 this, SLOT(slotLoadStarted()));
00912 connect(m_browser, SIGNAL(loadFinished(bool)),
00913 this, SLOT(slotLoadFinished(bool)));
00914 connect(m_browser, SIGNAL(loadProgress(int)),
00915 this, SLOT(slotLoadProgress(int)));
00916 connect(m_browser, SIGNAL(titleChanged(const QString &)),
00917 this, SLOT(slotTitleChanged(const QString &)));
00918 connect(m_browser, SIGNAL(iconChanged(void)),
00919 this, SLOT(slotIconChanged(void)));
00920 connect(m_browser, SIGNAL(statusBarMessage(const QString &)),
00921 this, SLOT(slotStatusBarMessage(const QString &)));
00922 connect(m_browser->page(), SIGNAL(linkHovered(const QString &,
00923 const QString &,
00924 const QString &)),
00925 this, SLOT(slotStatusBarMessage(const QString &)));
00926 connect(m_browser, SIGNAL(linkClicked(const QUrl &)),
00927 this, SLOT(slotLinkClicked(const QUrl &)));
00928
00929
00930 m_parentScreen = NULL;
00931 QObject *parentObject = parent();
00932
00933 while (parentObject)
00934 {
00935 m_parentScreen = dynamic_cast<MythScreenType *>(parentObject);
00936
00937 if (m_parentScreen)
00938 break;
00939
00940 parentObject = parentObject->parent();
00941 }
00942
00943 if (!m_parentScreen)
00944 LOG(VB_GENERAL, LOG_ERR,
00945 "MythUIWebBrowser: failed to find our parent screen");
00946
00947
00948 for (int x = 0; x < GetMythMainWindow()->GetStackCount(); x++)
00949 {
00950 MythScreenStack *stack = GetMythMainWindow()->GetStackAt(x);
00951
00952 if (stack)
00953 connect(stack, SIGNAL(topScreenChanged(MythScreenType *)),
00954 this, SLOT(slotTopScreenChanged(MythScreenType *)));
00955 }
00956
00957
00958 QString path = GetConfDir();
00959 QDir dir(path);
00960
00961 if (!dir.exists())
00962 dir.mkdir(path);
00963
00964 path += "/MythBrowser";
00965 dir.setPath(path);
00966
00967 if (!dir.exists())
00968 dir.mkdir(path);
00969
00970 QWebSettings::setIconDatabasePath(path);
00971
00972 if (gCoreContext->GetNumSetting("WebBrowserEnablePlugins", 1) == 1)
00973 {
00974 LOG(VB_GENERAL, LOG_INFO, "MythUIWebBrowser: enabling plugins");
00975 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,
00976 true);
00977 }
00978 else
00979 {
00980 LOG(VB_GENERAL, LOG_INFO, "MythUIWebBrowser: disabling plugins");
00981 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,
00982 false);
00983 }
00984
00985 QImage image = QImage(m_browserArea.size(), QImage::Format_ARGB32);
00986 m_image = GetPainter()->GetFormatImage();
00987 m_image->Assign(image);
00988
00989 SetBackgroundColor(m_bgColor);
00990 SetZoom(m_zoom);
00991
00992 if (!m_widgetUrl.isEmpty() && m_widgetUrl.isValid())
00993 LoadPage(m_widgetUrl);
00994
00995 m_initialized = true;
00996 }
00997
01001 MythUIWebBrowser::~MythUIWebBrowser()
01002 {
01003 if (m_browser)
01004 {
01005 m_browser->hide();
01006 m_browser->disconnect();
01007 m_browser->deleteLater();
01008 m_browser = NULL;
01009 }
01010
01011 if (m_image)
01012 {
01013 m_image->DownRef();
01014 m_image = NULL;
01015 }
01016 }
01017
01022 void MythUIWebBrowser::LoadPage(QUrl url)
01023 {
01024 if (!m_browser)
01025 return;
01026
01027 ResetScrollBars();
01028
01029 m_browser->setUrl(url);
01030 }
01031
01038 void MythUIWebBrowser::SetHtml(const QString &html, const QUrl &baseUrl)
01039 {
01040 if (!m_browser)
01041 return;
01042
01043 ResetScrollBars();
01044
01045 m_browser->setHtml(html, baseUrl);
01046 }
01047
01052 void MythUIWebBrowser::LoadUserStyleSheet(QUrl url)
01053 {
01054 if (!m_browser)
01055 return;
01056
01057 LOG(VB_GENERAL, LOG_INFO,
01058 "MythUIWebBrowser: Loading css from - " + url.toString());
01059
01060 m_browser->page()->settings()->setUserStyleSheetUrl(url);
01061 }
01062
01069 void MythUIWebBrowser::SetBackgroundColor(QColor color)
01070 {
01071 if (!m_browser)
01072 return;
01073
01074 color.setAlpha(255);
01075 QPalette palette = m_browser->page()->palette();
01076 palette.setBrush(QPalette::Window, QBrush(color));
01077 palette.setBrush(QPalette::Base, QBrush(color));
01078 m_browser->page()->setPalette(palette);
01079
01080 UpdateBuffer();
01081 }
01082
01093 void MythUIWebBrowser::SetActive(bool active)
01094 {
01095 if (m_active == active)
01096 return;
01097
01098 m_active = active;
01099 m_wasActive = active;
01100
01101 if (m_active)
01102 {
01103 m_browser->setUpdatesEnabled(false);
01104 m_browser->setFocus();
01105 m_browser->show();
01106 m_browser->raise();
01107 m_browser->setUpdatesEnabled(true);
01108 }
01109 else
01110 {
01111 m_browser->clearFocus();
01112 m_browser->hide();
01113 UpdateBuffer();
01114 }
01115 }
01116
01120 void MythUIWebBrowser::ZoomIn(void)
01121 {
01122 SetZoom(m_zoom + 0.1);
01123 }
01124
01128 void MythUIWebBrowser::ZoomOut(void)
01129 {
01130 SetZoom(m_zoom - 0.1);
01131 }
01132
01137 void MythUIWebBrowser::SetZoom(float zoom)
01138 {
01139 if (!m_browser)
01140 return;
01141
01142 m_zoom = zoom;
01143 m_browser->setZoomFactor(m_zoom);
01144 ResetScrollBars();
01145 UpdateBuffer();
01146 }
01147
01148 void MythUIWebBrowser::SetDefaultSaveDirectory(const QString &saveDir)
01149 {
01150 if (!saveDir.isEmpty())
01151 m_defaultSaveDir = saveDir;
01152 else
01153 m_defaultSaveDir = GetConfDir() + "/MythBrowser/";
01154 }
01155
01156 void MythUIWebBrowser::SetDefaultSaveFilename(const QString &filename)
01157 {
01158 if (!filename.isEmpty())
01159 m_defaultSaveFilename = filename;
01160 else
01161 m_defaultSaveFilename.clear();
01162 }
01163
01168 float MythUIWebBrowser::GetZoom(void)
01169 {
01170 return m_zoom;
01171 }
01172
01178 bool MythUIWebBrowser::CanGoForward(void)
01179 {
01180 if (!m_browser)
01181 return false;
01182
01183 return m_browser->history()->canGoForward();
01184 }
01185
01191 bool MythUIWebBrowser::CanGoBack(void)
01192 {
01193 if (!m_browser)
01194 return false;
01195
01196 return m_browser->history()->canGoBack();
01197 }
01198
01202 void MythUIWebBrowser::Back(void)
01203 {
01204 if (!m_browser)
01205 return;
01206
01207 m_browser->back();
01208 }
01209
01213 void MythUIWebBrowser::Forward(void)
01214 {
01215 if (!m_browser)
01216 return;
01217
01218 m_browser->forward();
01219 }
01220
01225 QIcon MythUIWebBrowser::GetIcon(void)
01226 {
01227 if (m_browser)
01228 {
01229 return QWebSettings::iconForUrl(m_browser->url());
01230 }
01231 else
01232 return QIcon();
01233 }
01234
01239 QUrl MythUIWebBrowser::GetUrl(void)
01240 {
01241 if (m_browser)
01242 {
01243 return m_browser->url();
01244 }
01245 else
01246 return QUrl();
01247 }
01248
01253 QString MythUIWebBrowser::GetTitle(void)
01254 {
01255 if (m_browser)
01256 return m_browser->title();
01257 else
01258 return QString("");
01259 }
01260
01265 QVariant MythUIWebBrowser::evaluateJavaScript(const QString &scriptSource)
01266 {
01267 if (m_browser)
01268 {
01269 QWebFrame *frame = m_browser->page()->currentFrame();
01270 return frame->evaluateJavaScript(scriptSource);
01271 }
01272 else
01273 return QVariant();
01274 }
01275
01276 void MythUIWebBrowser::Scroll(int dx, int dy)
01277 {
01278 QPoint startPos = m_browser->page()->currentFrame()->scrollPosition();
01279 QPoint endPos = startPos + QPoint(dx, dy);
01280
01281 if (GetPainter()->SupportsAnimation() && m_scrollAnimation.duration() > 0)
01282 {
01283
01284 if (m_destinationScrollPos == startPos)
01285 m_scrollAnimation.setEasingCurve(QEasingCurve::InOutCubic);
01286 else
01287 m_scrollAnimation.setEasingCurve(QEasingCurve::OutCubic);
01288
01289 m_destinationScrollPos = endPos;
01290 m_scrollAnimation.setStartValue(startPos);
01291 m_scrollAnimation.setEndValue(m_destinationScrollPos);
01292 m_scrollAnimation.Activate();
01293 }
01294 else
01295 {
01296 m_destinationScrollPos = endPos;
01297 m_browser->page()->currentFrame()->setScrollPosition(endPos);
01298 UpdateBuffer();
01299 }
01300 }
01301
01302 void MythUIWebBrowser::slotLoadStarted(void)
01303 {
01304 ResetScrollBars();
01305 emit loadStarted();
01306 }
01307
01308 void MythUIWebBrowser::slotLoadFinished(bool ok)
01309 {
01310 UpdateBuffer();
01311 emit loadFinished(ok);
01312 }
01313
01314 void MythUIWebBrowser::slotLoadProgress(int progress)
01315 {
01316 emit loadProgress(progress);
01317 }
01318
01319 void MythUIWebBrowser::slotTitleChanged(const QString &title)
01320 {
01321 emit titleChanged(title);
01322 }
01323
01324 void MythUIWebBrowser::slotStatusBarMessage(const QString &text)
01325 {
01326 emit statusBarMessage(text);
01327 }
01328
01329 void MythUIWebBrowser::slotLinkClicked(const QUrl &url)
01330 {
01331 LoadPage(url);
01332 }
01333
01334 void MythUIWebBrowser::slotIconChanged(void)
01335 {
01336 emit iconChanged();
01337 }
01338
01339 void MythUIWebBrowser::slotTopScreenChanged(MythScreenType *screen)
01340 {
01341 (void) screen;
01342
01343 if (!m_parentScreen)
01344 return;
01345
01346
01347 for (int x = GetMythMainWindow()->GetStackCount() - 1; x >= 0; x--)
01348 {
01349 MythScreenStack *stack = GetMythMainWindow()->GetStackAt(x);
01350
01351
01352 if (!stack->GetTopScreen())
01353 continue;
01354
01355 if (stack->GetTopScreen() == m_parentScreen)
01356 {
01357 SetActive(m_wasActive);
01358 break;
01359 }
01360 else
01361 {
01362 bool wasActive = (m_wasActive | m_active);
01363 SetActive(false);
01364 m_wasActive = wasActive;
01365 break;
01366 }
01367 }
01368 }
01369
01370
01371 void MythUIWebBrowser::UpdateScrollBars(void)
01372 {
01373 QPoint position = m_browser->page()->currentFrame()->scrollPosition();
01374 if (m_verticalScrollbar)
01375 {
01376 int maximum =
01377 m_browser->page()->currentFrame()->contentsSize().height() -
01378 m_browserArea.height();
01379 m_verticalScrollbar->SetMaximum(maximum);
01380 m_verticalScrollbar->SetPageStep(m_browserArea.height());
01381 m_verticalScrollbar->SetSliderPosition(position.y());
01382 }
01383
01384 if (m_horizontalScrollbar)
01385 {
01386 int maximum =
01387 m_browser->page()->currentFrame()->contentsSize().width() -
01388 m_browserArea.width();
01389 m_horizontalScrollbar->SetMaximum(maximum);
01390 m_horizontalScrollbar->SetPageStep(m_browserArea.width());
01391 m_horizontalScrollbar->SetSliderPosition(position.x());
01392 }
01393 }
01394
01395 void MythUIWebBrowser::UpdateBuffer(void)
01396 {
01397 UpdateScrollBars();
01398
01399 if (!m_active || (m_active && !m_browser->hasFocus()))
01400 {
01401 QPainter painter(m_image);
01402 m_browser->render(&painter);
01403 painter.end();
01404
01405 m_image->SetChanged();
01406 Refresh();
01407 }
01408 }
01409
01413 void MythUIWebBrowser::Pulse(void)
01414 {
01415 if (m_scrollAnimation.IsActive() &&
01416 m_destinationScrollPos !=
01417 m_browser->page()->currentFrame()->scrollPosition())
01418 {
01419 m_scrollAnimation.IncrementCurrentTime();
01420
01421 QPoint scrollPosition = m_scrollAnimation.currentValue().toPoint();
01422 m_browser->page()->currentFrame()->setScrollPosition(scrollPosition);
01423
01424 SetRedraw();
01425 UpdateBuffer();
01426 }
01427 else if (m_updateInterval && m_lastUpdateTime.elapsed() > m_updateInterval)
01428 {
01429 UpdateBuffer();
01430 m_lastUpdateTime.start();
01431 }
01432
01433 MythUIType::Pulse();
01434 }
01435
01439 void MythUIWebBrowser::DrawSelf(MythPainter *p, int xoffset, int yoffset,
01440 int alphaMod, QRect clipRegion)
01441 {
01442 if (!m_image || m_image->isNull() || !m_browser || m_browser->hasFocus())
01443 return;
01444
01445 QRect area = m_browserArea;
01446 area.translate(xoffset, yoffset);
01447
01448 p->DrawImage(area.x(), area.y(), m_image, alphaMod);
01449 }
01450
01454 bool MythUIWebBrowser::keyPressEvent(QKeyEvent *event)
01455 {
01456 QStringList actions;
01457 bool handled = false;
01458 handled = GetMythMainWindow()->TranslateKeyPress("Browser", event, actions);
01459
01460 for (int i = 0; i < actions.size() && !handled; i++)
01461 {
01462 QString action = actions[i];
01463 handled = true;
01464
01465 if (action == "TOGGLEINPUT")
01466 {
01467 m_inputToggled = !m_inputToggled;
01468 return true;
01469 }
01470
01471
01472 if (m_inputToggled)
01473 {
01474 m_browser->keyPressEvent(event);
01475 return true;
01476 }
01477
01478 QWebFrame *frame = m_browser->page()->currentFrame();
01479 if (action == "UP")
01480 {
01481 int pos = frame->scrollPosition().y();
01482
01483 if (pos > 0)
01484 {
01485 Scroll(0, -m_browserArea.height() / 10);
01486 }
01487 else
01488 handled = false;
01489 }
01490 else if (action == "DOWN")
01491 {
01492 int pos = frame->scrollPosition().y();
01493 QSize maximum = frame->contentsSize() - m_browserArea.size();
01494
01495 if (pos != maximum.height())
01496 {
01497 Scroll(0, m_browserArea.height() / 10);
01498 }
01499 else
01500 handled = false;
01501 }
01502 else if (action == "LEFT")
01503 {
01504 int pos = frame->scrollPosition().x();
01505
01506 if (pos > 0)
01507 {
01508 Scroll(-m_browserArea.width() / 10, 0);
01509 }
01510 else
01511 handled = false;
01512 }
01513 else if (action == "RIGHT")
01514 {
01515 int pos = frame->scrollPosition().x();
01516 QSize maximum = frame->contentsSize() - m_browserArea.size();
01517
01518 if (pos != maximum.width())
01519 {
01520 Scroll(m_browserArea.width() / 10, 0);
01521 }
01522 else
01523 handled = false;
01524 }
01525 else if (action == "PAGEUP")
01526 {
01527 Scroll(0, -m_browserArea.height());
01528 }
01529 else if (action == "PAGEDOWN")
01530 {
01531 Scroll(0, m_browserArea.height());
01532 }
01533 else if (action == "ZOOMIN")
01534 {
01535 ZoomIn();
01536 }
01537 else if (action == "ZOOMOUT")
01538 {
01539 ZoomOut();
01540 }
01541 else if (action == "MOUSEUP" || action == "MOUSEDOWN" ||
01542 action == "MOUSELEFT" || action == "MOUSERIGHT" ||
01543 action == "MOUSELEFTBUTTON")
01544 {
01545 HandleMouseAction(action);
01546 }
01547 else if (action == "PAGELEFT")
01548 {
01549 Scroll(-m_browserArea.width(), 0);
01550 }
01551 else if (action == "PAGERIGHT")
01552 {
01553 Scroll(m_browserArea.width(), 0);
01554 }
01555 else if (action == "NEXTLINK")
01556 {
01557 m_browser->keyPressEvent(event);
01558 }
01559 else if (action == "PREVIOUSLINK")
01560 {
01561 m_browser->keyPressEvent(event);
01562 }
01563 else if (action == "FOLLOWLINK")
01564 {
01565 m_browser->keyPressEvent(event);
01566 }
01567 else if (action == "HISTORYBACK")
01568 {
01569 Back();
01570 }
01571 else if (action == "HISTORYFORWARD")
01572 {
01573 Forward();
01574 }
01575 else
01576 handled = false;
01577 }
01578
01579 return handled;
01580 }
01581
01582 void MythUIWebBrowser::HandleMouseAction(const QString &action)
01583 {
01584 int step = 5;
01585
01586
01587 if (action == m_lastMouseAction &&
01588 m_lastMouseActionTime.msecsTo(QTime::currentTime()) < 500)
01589 {
01590 m_lastMouseActionTime = QTime::currentTime();
01591 m_mouseKeyCount++;
01592
01593 if (m_mouseKeyCount > 5)
01594 step = 25;
01595 }
01596 else
01597 {
01598 m_lastMouseAction = action;
01599 m_lastMouseActionTime = QTime::currentTime();
01600 m_mouseKeyCount = 1;
01601 }
01602
01603 if (action == "MOUSEUP")
01604 {
01605 QPoint curPos = QCursor::pos();
01606 QCursor::setPos(curPos.x(), curPos.y() - step);
01607 }
01608 else if (action == "MOUSELEFT")
01609 {
01610 QPoint curPos = QCursor::pos();
01611 QCursor::setPos(curPos.x() - step, curPos.y());
01612 }
01613 else if (action == "MOUSERIGHT")
01614 {
01615 QPoint curPos = QCursor::pos();
01616 QCursor::setPos(curPos.x() + step, curPos.y());
01617 }
01618 else if (action == "MOUSEDOWN")
01619 {
01620 QPoint curPos = QCursor::pos();
01621 QCursor::setPos(curPos.x(), curPos.y() + step);
01622 }
01623 else if (action == "MOUSELEFTBUTTON")
01624 {
01625 QPoint curPos = QCursor::pos();
01626 QWidget *widget = QApplication::widgetAt(curPos);
01627
01628 if (widget)
01629 {
01630 curPos = widget->mapFromGlobal(curPos);
01631
01632 QMouseEvent *me = new QMouseEvent(QEvent::MouseButtonPress, curPos,
01633 Qt::LeftButton, Qt::LeftButton,
01634 Qt::NoModifier);
01635 QCoreApplication::postEvent(widget, me);
01636
01637 me = new QMouseEvent(QEvent::MouseButtonRelease, curPos,
01638 Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
01639 QCoreApplication::postEvent(widget, me);
01640 }
01641 }
01642 }
01643
01644 void MythUIWebBrowser::ResetScrollBars()
01645 {
01646 if (m_verticalScrollbar)
01647 {
01648 m_verticalScrollbar->Reset();
01649 m_verticalScrollbar->Hide();
01650 }
01651
01652 if (m_horizontalScrollbar)
01653 {
01654 m_horizontalScrollbar->Reset();
01655 m_horizontalScrollbar->Hide();
01656 }
01657 }
01658
01662 bool MythUIWebBrowser::ParseElement(
01663 const QString &filename, QDomElement &element, bool showWarnings)
01664 {
01665 if (element.tagName() == "zoom")
01666 {
01667 QString zoom = getFirstText(element);
01668 m_zoom = zoom.toFloat();
01669 }
01670 else if (element.tagName() == "url")
01671 {
01672 m_widgetUrl.setUrl(getFirstText(element));
01673 }
01674 else if (element.tagName() == "userstylesheet")
01675 {
01676 m_userCssFile = getFirstText(element);
01677 }
01678 else if (element.tagName() == "updateinterval")
01679 {
01680 QString interval = getFirstText(element);
01681 m_updateInterval = interval.toInt();
01682 }
01683 else if (element.tagName() == "background")
01684 {
01685 m_bgColor = QColor(element.attribute("color", "#ffffff"));
01686 int alpha = element.attribute("alpha", "255").toInt();
01687 m_bgColor.setAlpha(alpha);
01688 }
01689 else if (element.tagName() == "browserarea")
01690 {
01691 m_browserArea = parseRect(element);
01692 }
01693 else if (element.tagName() == "scrollduration")
01694 {
01695 QString duration = getFirstText(element);
01696 m_scrollAnimation.setDuration(duration.toInt());
01697 }
01698 else
01699 {
01700 return MythUIType::ParseElement(filename, element, showWarnings);
01701 }
01702
01703 return true;
01704 }
01705
01709 void MythUIWebBrowser::CopyFrom(MythUIType *base)
01710 {
01711 MythUIWebBrowser *browser = dynamic_cast<MythUIWebBrowser *>(base);
01712
01713 if (!browser)
01714 {
01715 LOG(VB_GENERAL, LOG_ERR, "ERROR, bad parsing");
01716 return;
01717 }
01718
01719 MythUIType::CopyFrom(base);
01720
01721 m_zoom = browser->m_zoom;
01722 m_bgColor = browser->m_bgColor;
01723 m_widgetUrl = browser->m_widgetUrl;
01724 m_userCssFile = browser->m_userCssFile;
01725 m_updateInterval = browser->m_updateInterval;
01726 m_defaultSaveDir = browser->m_defaultSaveDir;
01727 m_defaultSaveFilename = browser->m_defaultSaveFilename;
01728 m_scrollAnimation.setDuration(browser->m_scrollAnimation.duration());
01729
01730 Init();
01731 }
01732
01736 void MythUIWebBrowser::CreateCopy(MythUIType *parent)
01737 {
01738 MythUIWebBrowser *browser = new MythUIWebBrowser(parent, objectName());
01739 browser->CopyFrom(this);
01740 }