15#include <QApplication>
16#include <QWebEngineHistory>
17#include <QWebEngineSettings>
18#include <QWebEngineScript>
19#include <QWebEngineScriptCollection>
24#include <QDomDocument>
54 {
"audio/mpeg3",
"mp3",
false },
55 {
"audio/x-mpeg-3",
"mp3",
false },
56 {
"audio/mpeg",
"mp2",
false },
57 {
"audio/x-mpeg",
"mp2",
false },
58 {
"audio/ogg",
"ogg",
false },
59 {
"audio/ogg",
"oga",
false },
60 {
"audio/flac",
"flac",
false },
61 {
"audio/x-ms-wma",
"wma",
false },
62 {
"audio/wav",
"wav",
false },
63 {
"audio/x-wav",
"wav",
false },
64 {
"audio/ac3",
"ac3",
false },
65 {
"audio/x-ac3",
"ac3",
false },
66 {
"audio/x-oma",
"oma",
false },
67 {
"audio/x-realaudio",
"ra",
false },
68 {
"audio/dts",
"dts",
false },
69 {
"audio/x-dts",
"dts",
false },
70 {
"audio/aac",
"aac",
false },
71 {
"audio/x-aac",
"aac",
false },
72 {
"audio/m4a",
"m4a",
false },
73 {
"audio/x-m4a",
"m4a",
false },
74 {
"video/mpeg",
"mpg",
true },
75 {
"video/mpeg",
"mpeg",
true },
76 {
"video/x-ms-wmv",
"wmv",
true },
77 {
"video/x-ms-wmv",
"avi",
true },
78 {
"application/x-troff-msvideo",
"avi",
true },
79 {
"video/avi",
"avi",
true },
80 {
"video/msvideo",
"avi",
true },
81 {
"video/x-msvideo",
"avi",
true }
91 : QWebEngineView(parent), m_parentBrowser(parentBrowser)
93 m_profile =
new QWebEngineProfile(
"MythTV",
this);
95 m_profile->setPersistentCookiesPolicy(QWebEngineProfile::AllowPersistentCookies);
101 installEventFilter(
this);
112 if (event->type() == QEvent::ShortcutOverride)
115 auto *keyEvent =
dynamic_cast<QKeyEvent *
>(event);
116 if (keyEvent ==
nullptr)
118 LOG(VB_GENERAL, LOG_ALERT,
119 "MythWebEngineView::eventFilter() couldn't cast event");
133 return QWebEngineView::eventFilter(obj, event);
138 for (QObject* obj : children())
140 if (qobject_cast<QWidget*>(obj))
142 auto *
event =
new QKeyEvent(QEvent::KeyPress, key, modifiers, text,
false, 1);
143 QCoreApplication::postEvent(obj, event);
154 for (
int i = 0; i < actions.size() && !handled; i++)
156 const QString&
action = actions[i];
161 if (history()->canGoBack())
169 else if (
action ==
"NEXTLINK")
171 if (event->key() != Qt::Key_Tab)
173 sendKeyPress(Qt::Key_Tab, Qt::NoModifier, QString(
'\t'));
179 else if (
action ==
"PREVIOUSLINK")
181 if (event->key() != Qt::Key_Tab)
183 sendKeyPress(Qt::Key_Tab, Qt::ShiftModifier, QString(
'\t'));
189 else if (
action ==
"FOLLOWLINK")
191 if (event->key() != Qt::Key_Return)
193 sendKeyPress(Qt::Key_Return, Qt::NoModifier, QString(
'\r'));
199 else if (
action ==
"TOGGLEINPUT")
212 else if (
action ==
"ZOOMIN")
216 else if (
action ==
"ZOOMOUT")
220 else if (
action ==
"RELOAD")
224 else if (
action ==
"FULLRELOAD")
228 else if (
action ==
"MOUSEUP" ||
action ==
"MOUSEDOWN" ||
230 action ==
"MOUSELEFTBUTTON")
234 else if (
action ==
"HISTORYBACK")
238 else if (
action ==
"HISTORYFORWARD")
256 QString msg(tr(
"Downloading..."));
258 if (!message.isEmpty())
283 if (dce->GetResult() < 0)
286 QString resultid = dce->GetId();
287 QString resulttext = dce->GetResultText();
289 if (resultid ==
"filenamedialog")
293 else if (resultid ==
"downloadmenu")
295 if (resulttext == tr(
"Play the file"))
298 QString extension = fi.suffix();
303 MythEvent me(QString(
"MUSIC_COMMAND %1 PLAY_URL %2")
315 LOG(VB_GENERAL, LOG_ERR,
316 QString(
"MythWebEngineView: Asked to play a file with "
317 "extension '%1' but don't know how")
321 else if (resulttext == tr(
"Download the file"))
325 else if (resulttext == tr(
"Download and play the file"))
334 auto *me =
dynamic_cast<MythEvent *
>(event);
338 QStringList tokens = me->
Message().split(
" ", Qt::SkipEmptyParts);
339 if (tokens.isEmpty())
342 if (tokens[0] ==
"DOWNLOAD_FILE")
344 QStringList
args = me->ExtraDataList();
346 if (tokens[1] ==
"UPDATE")
350 else if (tokens[1] ==
"FINISHED")
352 int fileSize =
args[2].toInt();
353 int errorCode =
args[4].toInt();
358 if ((errorCode != 0) || (fileSize == 0))
369 if (event->type() == QEvent::UpdateRequest)
371 LOG(VB_GENERAL, LOG_ERR, QString(
"MythWebEngineView: customeEvent: QEvent::UpdateRequest"));
379 QString extension = fi.suffix();
382 QString label = tr(
"What do you want to do with this file?");
394 menu->SetReturnEvent(
this,
"downloadmenu");
397 menu->AddButton(tr(
"Play the file"));
400 menu->AddButton(tr(
"Download and play the file"));
402 menu->AddButton(tr(
"Download the file"));
403 menu->AddButton(tr(
"Cancel"));
410 if (mimetype.isEmpty())
416 return it->m_extension;
423 [extension, mimetype](
const auto &entry){
426 if (!mimetype.isEmpty() &&
427 mimetype == entry.m_mimeType)
429 if (!extension.isEmpty() &&
430 extension.toLower() == entry.m_extension)
438 [extension, mimetype](
const auto &entry) {
439 if (!entry.m_isVideo)
441 if (!mimetype.isEmpty() &&
442 mimetype == entry.m_mimeType)
444 if (!extension.isEmpty() &&
445 extension.toLower() == entry.m_extension)
456 QVariant header =
m_downloadReply->header(QNetworkRequest::ContentTypeHeader);
458 if (header != QVariant())
459 mimeType = header.toString();
466 return (QWebEngineView *)
this;
511 m_updateInterval(500), m_bgColor(
"Red"), m_userCssFile(
""),
512 m_defaultSaveDir(
GetConfDir() +
"/MythBrowser/"),
513 m_defaultSaveFilename(
""), m_lastMouseAction(
"")
553 m_webEngine->setPalette(QApplication::style()->standardPalette());
595 QString
filename =
"htmls/mythbrowser.css";
601 SetHttpUserAgent(
"Mozilla/5.0 (SMART-TV; Linux; Tizen 5.0) AppleWebKit/538.1 (KHTML, like Gecko) Version/5.0 NativeTVAds Safari/538.1");
622 QObject *parentObject = parent();
631 parentObject = parentObject->parent();
635 LOG(VB_GENERAL, LOG_ERR,
"MythUIWebBrowser: failed to find our parent screen");
648 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: enabling plugins");
649 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled,
true);
653 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: disabling plugins");
654 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled,
false);
659 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: disabling JavaScript");
660 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled,
false);
663 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled,
true);
664 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage,
true);
665 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled,
true);
666 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled,
true);
667 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled,
true);
668 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
true);
671 m_webEngine->page()->settings()->setAttribute(QWebEngineSettings::ShowScrollBars,
false);
673 m_webEngine->setWindowFlag(Qt::WindowStaysOnTopHint,
true);
754 LOG(VB_GENERAL, LOG_ERR,
"MythUIWebBrowser: Failed to download css from - " + url.toString());
760 LOG(VB_GENERAL, LOG_INFO,
"MythUIWebBrowser: Loading css from - " + url.toString());
762 QWebEngineScript script;
763 QString s = QString::fromLatin1(
"(function() {"\
764 " css = document.createElement('style');"\
765 " css.type = 'text/css';"\
767 " document.head.appendChild(css);"\
768 " css.innerText = '%2';"\
769 "})()").arg(name, QString(download).simplified());
771 m_webEngine->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
773 script.setName(name);
774 script.setSourceCode(s);
775 script.setInjectionPoint(QWebEngineScript::DocumentReady);
776 script.setRunsOnSubFrames(
true);
777 script.setWorldId(QWebEngineScript::ApplicationWorld);
786#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
787 QList<QWebEngineScript> scripts =
m_webEngine->page()->scripts().find(name);
789 QList<QWebEngineScript> scripts =
m_webEngine->page()->scripts().findScripts(name);
792 if (!scripts.isEmpty())
796 QString s = QString::fromLatin1(
"(function() {"\
797 " var element = document.getElementById('%1');"\
798 " element.outerHTML = '';"\
802 m_webEngine->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
827 m_webEngine->page()->profile()->setHttpUserAgent(userAgent);
843 palette.setBrush(QPalette::Window, QBrush(color));
844 palette.setBrush(QPalette::Base, QBrush(color));
946 if (!saveDir.isEmpty())
1082 LOG(VB_GENERAL, LOG_INFO, QString(
"MythUIWebBrowser::slotRenderProcessTerminated - terminationStatus: %1, exitStatus: %2").arg(terminationStatus).arg(exitCode));
1088 fullScreenRequest.accept();
1093 LOG(VB_GENERAL, LOG_INFO, QString(
"MythUIWebBrowser::slotWindowCloseRequested called"));
1098void MythUIWebBrowser::MythUIWebBrowser::slotLoadStarted(
void)
1204 QPoint position =
m_webEngine->page()->scrollPosition().toPoint();
1228 LOG(VB_GENERAL, LOG_ERR, QString(
"MythUIWebBrowser::UpdateBuffer called - m_image or m_webEngine is FALSE"));
1263 int alphaMod, QRect clipRect)
1269 area.translate(xoffset, yoffset);
1271 p->SetClipRect(clipRect);
1272 p->DrawImage(area.x(), area.y(),
m_image, alphaMod);
1299 QPoint curPos = QCursor::pos();
1300 QCursor::setPos(curPos.x(), curPos.y() - step);
1302 else if (
action ==
"MOUSELEFT")
1304 QPoint curPos = QCursor::pos();
1305 QCursor::setPos(curPos.x() - step, curPos.y());
1307 else if (
action ==
"MOUSERIGHT")
1309 QPoint curPos = QCursor::pos();
1310 QCursor::setPos(curPos.x() + step, curPos.y());
1312 else if (
action ==
"MOUSEDOWN")
1314 QPoint curPos = QCursor::pos();
1315 QCursor::setPos(curPos.x(), curPos.y() + step);
1317 else if (
action ==
"MOUSELEFTBUTTON")
1319 QPoint curPos = QCursor::pos();
1320 QWidget *widget = QApplication::widgetAt(curPos);
1324 curPos = widget->mapFromGlobal(curPos);
1326 auto *me =
new QMouseEvent(QEvent::MouseButtonPress, curPos, curPos,
1327 Qt::LeftButton, Qt::LeftButton,
1330 QCoreApplication::postEvent(widget, me);
1332 me =
new QMouseEvent(QEvent::MouseButtonRelease, curPos, curPos,
1333 Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1335 QCoreApplication::postEvent(widget, me);
1359 const QString &
filename, QDomElement &element,
bool showWarnings)
1361 if (element.tagName() ==
"zoom")
1364 m_zoom = zoom.toDouble();
1366 else if (element.tagName() ==
"url")
1370 else if (element.tagName() ==
"userstylesheet")
1374 else if (element.tagName() ==
"updateinterval")
1379 else if (element.tagName() ==
"background")
1381 m_bgColor = QColor(element.attribute(
"color",
"#ffffff"));
1382 int alpha = element.attribute(
"alpha",
"255").toInt();
1385 else if (element.tagName() ==
"browserarea")
1389 else if (element.tagName() ==
"scrollduration")
1393 else if (element.tagName() ==
"acceptsfocus")
1413 LOG(VB_GENERAL, LOG_ERR,
"ERROR, bad parsing");
1420 m_zoom = browser->m_zoom;
1436 browser->CopyFrom(
this);
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
static const Type kEventType
QString GetHostName(void)
void SaveSetting(const QString &key, int newValue)
double GetFloatSetting(const QString &key, double defaultval=0.0)
void dispatch(const MythEvent &event)
int GetNumSetting(const QString &key, int defaultval=0)
bool GetBoolSetting(const QString &key, bool defaultval=false)
Basic menu dialog, message and a list of options.
This class is used as a container for messages.
const QString & Message() const
static const Type kMythEventMessage
virtual void SetChanged(bool change=true)
void Assign(const QImage &img)
int DecrRef(void) override
Decrements reference count and deletes on 0.
QWidget * GetPaintWindow()
MythScreenStack * GetStackAt(int Position)
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
bool HandleMedia(const QString &Handler, const QString &Mrl, const QString &Plot="", const QString &Title="", const QString &Subtitle="", const QString &Director="", int Season=0, int Episode=0, const QString &Inetref="", std::chrono::minutes LenMins=2h, const QString &Year="1895", const QString &Id="", bool UseBookmarks=false)
MythImage * GetFormatImage()
Returns a blank reference counted image in the format required for the Draw functions for this painte...
void CalculateArea(QRect parentArea)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void topScreenChanged(MythScreenType *screen)
virtual MythScreenType * GetTopScreen(void) const
Screen in which all other widgets are contained and rendered.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool Create(void) override
The base class on which all widgets and screens are based.
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
virtual MythPainter * GetPainter(void)
virtual void CopyFrom(MythUIType *base)
Copy this widgets state from another.
virtual void Finalize(void)
Perform any post-xml parsing initialisation tasks.
virtual void Pulse(void)
Pulse is called 70 times a second to trigger a single frame of an animation.
virtual bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings)
Parse the xml definition of this widget setting the state of the object accordingly.
bool IsOnTopScreen(void)
is our containing screen the top screen?
MythRect m_actualBrowserArea
void iconUrlChanged(const QUrl &url)
a pages fav icon has changed
void slotScrollBarHiding(void)
~MythUIWebBrowser() override
the classes destructor
void slotLinkClicked(const QUrl &url)
QWebEngineView * m_webEngine
QString GetTitle(void)
Gets the current page's title.
void iconChanged(const QIcon &icon)
link hit test messages
MythScreenType * GetParentScreen(void)
void UpdateScrollBars(void)
float GetZoom(void) const
Get the current zoom level.
bool IsInputToggled(void) const
returns true if all keypresses are to be passed to the web page
void titleChanged(const QString &title)
% of page loaded
void SetDefaultSaveDirectory(const QString &saveDir)
void LoadPage(const QUrl &url)
Loads the specified url and displays it.
void SetZoom(double zoom)
Set the text size to specific size.
void HandleMouseAction(const QString &action)
void RemoveUserStyleSheet(const QString &name)
QElapsedTimer m_lastUpdateTime
void Finalize(void) override
Perform any post-xml parsing initialisation tasks.
void ResetScrollBars(void)
QIcon GetIcon(void)
Gets the current page's fav icon.
void Init(void)
Initializes the widget ready for use.
void slotLoadFinished(bool Ok)
void RunJavaScript(const QString &scriptSource)
void slotWindowCloseRequested(void)
void TriggerPageAction(QWebEnginePage::WebAction action, bool checked=false)
void SetInputToggled(bool inputToggled)
void SetActive(bool active)
Toggles the active state of the widget.
MythUIScrollBar * m_horizontalScrollbar
void ZoomIn(void)
Increase the text size.
void slotTopScreenChanged(MythScreenType *screen)
void slotScrollBarShowing(void)
void Reload(bool useCache=true)
void Back(void)
Got backward in page history.
MythUIWebBrowser(MythUIType *parent, const QString &name)
the classes constructor
void statusBarMessage(const QString &text)
a pages title has changed
void slotIconChanged(const QIcon &icon)
void SetHttpUserAgent(const QString &userAgent)
void loadProgress(int progress)
a page has finished loading
QString m_defaultSaveFilename
void slotTitleChanged(const QString &title)
void slotScrollPositionChanged(QPointF position)
MythScreenType * m_parentScreen
QWebEngineSettings * GetWebEngineSettings(void)
void Pulse(void) override
Pulse is called 70 times a second to trigger a single frame of an animation.
void SetDefaultSaveFilename(const QString &filename)
QWebEngineProfile * GetWebEngineProfile(void)
void SendStatusBarMessage(const QString &text)
void slotLoadStarted(void)
a file has been downloaded
void ZoomOut(void)
Decrease the text size.
QUrl GetUrl(void)
Gets the current page's url.
QString m_lastMouseAction
QElapsedTimer m_lastMouseActionTime
void LoadUserStyleSheet(const QUrl &url, const QString &name=QString("mythtv"))
Sets the specified user style sheet.
void SetBackgroundColor(QColor color)
Sets the default background color.
bool CanGoBack(void)
Can we go backward in page history.
bool CanGoForward(void)
Can go forward in page history.
void SetHtml(const QString &html, const QUrl &baseUrl=QUrl())
Sets the content of the widget to the specified html.
void Forward(void)
Got forward in page history.
void slotRenderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode)
void CopyFrom(MythUIType *base) override
Copy this widgets state from another.
MythUIScrollBar * m_verticalScrollbar
void loadFinished(bool ok)
a page is starting to load
static void slotFullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest)
void CreateCopy(MythUIType *parent) override
Copy the state of this widget to the one given, it must be of the same type.
void slotContentsSizeChanged(QSizeF size)
void slotIconUrlChanged(const QUrl &url)
void slotLoadProgress(int progress)
void DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect) override
bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings) override
Parse the xml definition of this widget setting the state of the object accordingly.
void slotStatusBarMessage(const QString &text)
Subclass of QWebEngineView.
void sendKeyPress(int key, Qt::KeyboardModifiers modifiers, const QString &text=QString())
QString getReplyMimetype(void)
MythWebEngineView(QWidget *parent, MythUIWebBrowser *parentBrowser)
QWebEngineView * createWindow(QWebEnginePage::WebWindowType type) override
QWebEngineProfile * m_profile
QNetworkRequest m_downloadRequest
MythUIWebBrowser * m_parentBrowser
static bool isMusicFile(const QString &extension, const QString &mimetype)
QWebEnginePage * m_webpage
static bool isVideoFile(const QString &extension, const QString &mimetype)
void showDownloadMenu(void)
void openBusyPopup(const QString &message)
~MythWebEngineView(void) override
void closeBusyPopup(void)
void customEvent(QEvent *e) override
bool eventFilter(QObject *obj, QEvent *event) override
static QString getExtensionForMimetype(const QString &mimetype)
bool handleKeyPress(QKeyEvent *event)
QNetworkReply * m_downloadReply
MythUIBusyDialog * m_busyPopup
static MythUIType * GetGlobalObjectStore(void)
static MythRect parseRect(const QString &text, bool normalize=true)
static QString getFirstText(QDomElement &element)
static bool parseBool(const QString &text)
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
static std::vector< uint32_t > back
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
static MythThemedMenu * menu
MythUIHelper * GetMythUI()
static const std::vector< MimeType > SupportedMimeTypes
static eu8 clamp(eu8 value, eu8 low, eu8 high)
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)