15 #include <QApplication>
17 #include <QWebHistory>
23 #include <QDomDocument>
24 #include <QNetworkCookieJar>
25 #include <QNetworkConfiguration>
53 {
"audio/mpeg3",
"mp3",
false },
54 {
"audio/x-mpeg-3",
"mp3",
false },
55 {
"audio/mpeg",
"mp2",
false },
56 {
"audio/x-mpeg",
"mp2",
false },
57 {
"audio/ogg",
"ogg",
false },
58 {
"audio/ogg",
"oga",
false },
59 {
"audio/flac",
"flac",
false },
60 {
"audio/x-ms-wma",
"wma",
false },
61 {
"audio/wav",
"wav",
false },
62 {
"audio/x-wav",
"wav",
false },
63 {
"audio/ac3",
"ac3",
false },
64 {
"audio/x-ac3",
"ac3",
false },
65 {
"audio/x-oma",
"oma",
false },
66 {
"audio/x-realaudio",
"ra",
false },
67 {
"audio/dts",
"dts",
false },
68 {
"audio/x-dts",
"dts",
false },
69 {
"audio/aac",
"aac",
false },
70 {
"audio/x-aac",
"aac",
false },
71 {
"audio/m4a",
"m4a",
false },
72 {
"audio/x-m4a",
"m4a",
false },
73 {
"video/mpeg",
"mpg",
true },
74 {
"video/mpeg",
"mpeg",
true },
75 {
"video/x-ms-wmv",
"wmv",
true },
76 {
"video/x-ms-wmv",
"avi",
true },
77 {
"application/x-troff-msvideo",
"avi",
true },
78 {
"video/avi",
"avi",
true },
79 {
"video/msvideo",
"avi",
true },
80 {
"video/x-msvideo",
"avi",
true }
85 QNetworkReply* reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
86 reply->ignoreSslErrors();
111 LOG(VB_GENERAL, LOG_DEBUG,
"Copying DLManager's Cookie Jar");
138 QWebPage *page = view->page();
142 connect(
m_frame, &QWebFrame::javaScriptWindowObjectCleared,
this,
148 m_frame->addToJavaScriptWindowObject(QString(
"MusicPlayer"),
this);
171 MythEvent me(QString(
"MUSIC_COMMAND %1 SET_VOLUME %2")
180 MythEvent me(QString(
"MUSIC_COMMAND %1 GET_VOLUME")
189 QCoreApplication::processEvents();
190 std::this_thread::sleep_for(10ms);
201 MythEvent me(QString(
"MUSIC_COMMAND %1 PLAY_FILE '%2'")
208 MythEvent me(QString(
"MUSIC_COMMAND %1 PLAY_TRACK %2")
215 MythEvent me(QString(
"MUSIC_COMMAND %1 PLAY_URL %2")
224 MythEvent me(QString(
"MUSIC_COMMAND %1 GET_METADATA")
233 QCoreApplication::processEvents();
234 std::this_thread::sleep_for(10ms);
251 const QString& message = me->
Message();
253 if (!message.startsWith(
"MUSIC_CONTROL"))
256 QStringList tokens = message.simplified().split(
" ");
258 if ((tokens.size() >= 4) && (tokens[1] ==
"ANSWER")
263 for (
int i = 4; i < tokens.size(); i++)
264 m_answer += QString(
" ") + tokens[i];
279 LOG(VB_GENERAL, LOG_DEBUG,
"Refreshing DLManager's Cookie Jar");
286 return extension == QWebPage::ErrorPageExtension;
292 if (
extension == QWebPage::ErrorPageExtension)
304 const auto *erroroption =
static_cast<const ErrorPageExtensionOption *
>(option);
305 ErrorPageExtensionReturn *erroroutput =
nullptr;
307 erroroutput =
static_cast<ErrorPageExtensionReturn *
>(
output);
309 QString
filename =
"htmls/notfound.html";
315 bool isOpened =
file.open(QIODevice::ReadOnly);
320 QString title = tr(
"Error loading page: %1").arg(erroroption->url.toString());
321 QString html = QString(QLatin1String(
file.readAll()))
323 erroroption->errorString,
324 erroroption->url.toString());
327 imageBuffer.open(QBuffer::ReadWrite);
328 QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
330 QPixmap pixmap = icon.pixmap(QSize(32, 32));
332 if (pixmap.save(&imageBuffer,
"PNG"))
334 html.replace(QLatin1String(
"IMAGE_BINARY_DATA_HERE"),
335 QString(QLatin1String(imageBuffer.buffer().toBase64())));
338 erroroutput->content = html.toUtf8();
348 return QWebPage::userAgentForUrl(url).replace(
"Safari",
"MythBrowser");
359 m_parentBrowser(parentBrowser),
364 connect(page(), &QWebPage::unsupportedContent,
367 connect(page(), &QWebPage::downloadRequested,
370 page()->setForwardUnsupportedContent(
true);
386 function activeElement()\
389 type = document.activeElement.type;\
392 activeElement();") };
398 .toString().toLower();
399 bool editHasFocus = (
type ==
"text" ||
type ==
"textarea" ||
407 QWebView::keyPressEvent(event);
414 bool handled =
false;
418 for (
int i = 0; i < actions.size() && !handled; i++)
420 const QString&
action = actions[i];
425 QKeyEvent tabKey(event->type(), Qt::Key_Tab,
426 event->modifiers(), QString(),
427 event->isAutoRepeat(), event->count());
429 QWebView::keyPressEvent(event);
432 if (
action ==
"PREVIOUSLINK")
434 QKeyEvent shiftTabKey(event->type(), Qt::Key_Tab,
435 event->modifiers() | Qt::ShiftModifier,
437 event->isAutoRepeat(), event->count());
438 *
event = shiftTabKey;
439 QWebView::keyPressEvent(event);
442 if (
action ==
"FOLLOWLINK")
444 QKeyEvent returnKey(event->type(), Qt::Key_Return,
445 event->modifiers(), QString(),
446 event->isAutoRepeat(), event->count());
448 QWebView::keyPressEvent(event);
461 if (reply->error() == QNetworkReply::NoError)
465 QVariant header = reply->header(QNetworkRequest::ContentTypeHeader);
467 if (header != QVariant())
469 LOG(VB_GENERAL, LOG_ERR,
470 QString(
"MythWebView::handleUnsupportedContent - %1")
471 .arg(header.toString()));
494 QFileInfo fi(request.url().path());
495 QString basename(fi.completeBaseName());
496 QString extension = fi.suffix().toLower();
500 QString saveBaseName = basename;
505 saveBaseName = savefi.completeBaseName();
509 if (saveBaseName.isEmpty())
510 saveBaseName =
"unnamed_download";
513 if (extension.isEmpty())
516 if (!extension.isEmpty())
517 extension =
'.' + extension;
519 QString saveFilename = QString(
"%1%2%3")
531 saveFilename = QString(
"%1%2-%3%4")
534 QString::number(i++),
549 QString msg = tr(
"Enter filename to save file");
551 false, saveFilename);
555 input->SetReturnEvent(
this,
"filenamedialog");
567 if (saveFilename.isEmpty())
583 QString msg(tr(
"Downloading..."));
585 if (!message.isEmpty())
610 if (dce->GetResult() < 0)
613 QString resultid = dce->GetId();
614 QString resulttext = dce->GetResultText();
616 if (resultid ==
"filenamedialog")
618 else if (resultid ==
"downloadmenu")
620 if (resulttext == tr(
"Play the file"))
623 QString extension = fi.suffix();
628 MythEvent me(QString(
"MUSIC_COMMAND %1 PLAY_URL %2")
640 LOG(VB_GENERAL, LOG_ERR,
641 QString(
"MythWebView: Asked to play a file with "
642 "extension '%1' but don't know how")
646 else if (resulttext == tr(
"Download the file"))
650 else if (resulttext == tr(
"Download and play the file"))
659 auto *me =
dynamic_cast<MythEvent *
>(event);
663 QStringList tokens = me->
Message().split(
" ", Qt::SkipEmptyParts);
664 if (tokens.isEmpty())
667 if (tokens[0] ==
"DOWNLOAD_FILE")
669 QStringList
args = me->ExtraDataList();
671 if (tokens[1] ==
"UPDATE")
675 else if (tokens[1] ==
"FINISHED")
677 int fileSize =
args[2].toInt();
678 int errorCode =
args[4].toInt();
683 if ((errorCode != 0) || (fileSize == 0))
698 QString extension = fi.suffix();
701 QString label = tr(
"What do you want to do with this file?");
713 menu->SetReturnEvent(
this,
"downloadmenu");
716 menu->AddButton(tr(
"Play the file"));
719 menu->AddButton(tr(
"Download and play the file"));
721 menu->AddButton(tr(
"Download the file"));
722 menu->AddButton(tr(
"Cancel"));
729 if (mimetype.isEmpty())
733 [mimetype] (
const MimeType& entry) ->
bool
734 { return mimetype == entry.m_mimeType; });
736 return it->m_extension;
743 [extension, mimetype](
const auto &entry){
746 if (!mimetype.isEmpty() &&
747 mimetype == entry.m_mimeType)
749 if (!extension.isEmpty() &&
750 extension.toLower() == entry.m_extension)
758 [extension, mimetype](
const auto &entry) {
759 if (!entry.m_isVideo)
761 if (!mimetype.isEmpty() &&
762 mimetype == entry.m_mimeType)
764 if (!extension.isEmpty() &&
765 extension.toLower() == entry.m_extension)
776 QVariant header =
m_downloadReply->header(QNetworkRequest::ContentTypeHeader);
778 if (header != QVariant())
779 mimeType = header.toString();
786 return (QWebView *)
this;
831 m_bgColor(
"White"), m_userCssFile(
""),
832 m_defaultSaveDir(
GetConfDir() +
"/MythBrowser/"),
833 m_defaultSaveFilename(
""),
834 m_lastMouseAction(
"")
875 m_browser->setPalette(QApplication::style()->standardPalette());
879 m_browser->page()->setLinkDelegationPolicy(QWebPage::DontDelegateLinks);
886 QWebFrame* frame =
m_browser->page()->currentFrame();
887 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
896 QWebFrame* frame =
m_browser->page()->currentFrame();
897 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
915 QString
filename =
"htmls/mythbrowser.css";
925 connect(
m_browser, &QWebView::loadStarted,
927 connect(
m_browser, &QWebView::loadFinished,
929 connect(
m_browser, &QWebView::loadProgress,
931 connect(
m_browser, &QWebView::titleChanged,
933 connect(
m_browser, &QWebView::iconChanged,
935 connect(
m_browser, &QWebView::statusBarMessage,
937 connect(
m_browser->page(), &QWebPage::linkHovered,
939 connect(
m_browser, &QWebView::linkClicked,
944 QObject *parentObject = parent();
953 parentObject = parentObject->parent();
957 LOG(VB_GENERAL, LOG_ERR,
958 "MythUIWebBrowser: failed to find our parent screen");
977 path +=
"/MythBrowser";
983 QWebSettings::setIconDatabasePath(path);
987 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: enabling plugins");
988 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,
993 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: disabling plugins");
994 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,
1000 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: disabling JavaScript");
1001 QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled,
false);
1079 LOG(VB_GENERAL, LOG_INFO,
1080 "MythUIWebBrowser: Loading css from - " + url.toString());
1082 m_browser->page()->settings()->setUserStyleSheetUrl(url);
1096 color.setAlpha(255);
1097 QPalette palette =
m_browser->page()->palette();
1098 palette.setBrush(QPalette::Window, QBrush(color));
1099 palette.setBrush(QPalette::Base, QBrush(color));
1132 if (QGuiApplication::platformName().contains(
"egl"))
1145 if (QGuiApplication::platformName().contains(
"egl"))
1188 if (!saveDir.isEmpty())
1221 return m_browser->history()->canGoForward();
1234 return m_browser->history()->canGoBack();
1267 return QWebSettings::iconForUrl(
m_browser->url());
1304 QWebFrame *frame =
m_browser->page()->currentFrame();
1305 return frame->evaluateJavaScript(scriptSource);
1315 QPoint startPos =
m_browser->page()->currentFrame()->scrollPosition();
1316 QPoint endPos = startPos + QPoint(dx, dy);
1334 m_browser->page()->currentFrame()->setScrollPosition(endPos);
1427 QPoint position =
m_browser->page()->currentFrame()->scrollPosition();
1431 m_browser->page()->currentFrame()->contentsSize().height() -
1441 m_browser->page()->currentFrame()->contentsSize().width() -
1477 m_browser->page()->currentFrame()->scrollPosition())
1482 m_browser->page()->currentFrame()->setScrollPosition(scrollPosition);
1500 int alphaMod, QRect clipRect)
1506 area.translate(xoffset, yoffset);
1508 p->SetClipRect(clipRect);
1509 p->DrawImage(area.x(), area.y(),
m_image, alphaMod);
1520 QStringList actions;
1521 bool handled =
false;
1524 for (
int i = 0; i < actions.size() && !handled; i++)
1526 const QString&
action = actions[i];
1529 if (
action ==
"TOGGLEINPUT")
1549 QWebFrame *frame =
m_browser->page()->currentFrame();
1552 int pos = frame->scrollPosition().y();
1563 else if (
action ==
"DOWN")
1565 int pos = frame->scrollPosition().y();
1568 if (pos != maximum.height())
1577 else if (
action ==
"LEFT")
1579 int pos = frame->scrollPosition().x();
1590 else if (
action ==
"RIGHT")
1592 int pos = frame->scrollPosition().x();
1595 if (pos != maximum.width())
1604 else if (
action ==
"PAGEUP")
1608 else if (
action ==
"PAGEDOWN")
1612 else if (
action ==
"ZOOMIN")
1616 else if (
action ==
"ZOOMOUT")
1620 else if (
action ==
"MOUSEUP" ||
action ==
"MOUSEDOWN" ||
1622 action ==
"MOUSELEFTBUTTON")
1626 else if (
action ==
"PAGELEFT")
1630 else if (
action ==
"PAGERIGHT")
1634 else if ((
action ==
"NEXTLINK") ||
1635 (
action ==
"PREVIOUSLINK") ||
1636 (
action ==
"FOLLOWLINK"))
1640 else if (
action ==
"HISTORYBACK")
1644 else if (
action ==
"HISTORYFORWARD")
1681 QPoint curPos = QCursor::pos();
1682 QCursor::setPos(curPos.x(), curPos.y() - step);
1684 else if (
action ==
"MOUSELEFT")
1686 QPoint curPos = QCursor::pos();
1687 QCursor::setPos(curPos.x() - step, curPos.y());
1689 else if (
action ==
"MOUSERIGHT")
1691 QPoint curPos = QCursor::pos();
1692 QCursor::setPos(curPos.x() + step, curPos.y());
1694 else if (
action ==
"MOUSEDOWN")
1696 QPoint curPos = QCursor::pos();
1697 QCursor::setPos(curPos.x(), curPos.y() + step);
1699 else if (
action ==
"MOUSELEFTBUTTON")
1701 QPoint curPos = QCursor::pos();
1702 QWidget *widget = QApplication::widgetAt(curPos);
1706 curPos = widget->mapFromGlobal(curPos);
1708 auto *me =
new QMouseEvent(QEvent::MouseButtonPress, curPos,
1709 Qt::LeftButton, Qt::LeftButton,
1711 QCoreApplication::postEvent(widget, me);
1713 me =
new QMouseEvent(QEvent::MouseButtonRelease, curPos,
1714 Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1715 QCoreApplication::postEvent(widget, me);
1739 const QString &
filename, QDomElement &element,
bool showWarnings)
1741 if (element.tagName() ==
"zoom")
1744 m_zoom = zoom.toDouble();
1746 else if (element.tagName() ==
"url")
1750 else if (element.tagName() ==
"userstylesheet")
1754 else if (element.tagName() ==
"updateinterval")
1759 else if (element.tagName() ==
"background")
1761 m_bgColor = QColor(element.attribute(
"color",
"#ffffff"));
1762 int alpha = element.attribute(
"alpha",
"255").toInt();
1765 else if (element.tagName() ==
"browserarea")
1769 else if (element.tagName() ==
"scrollduration")
1774 else if (element.tagName() ==
"acceptsfocus")
1794 LOG(VB_GENERAL, LOG_ERR,
"ERROR, bad parsing");
1801 m_zoom = browser->m_zoom;
1817 browser->CopyFrom(
this);