//============================================================================= // // File : KvsObject_webView.cpp // Creation date : Wed Mar 9 23:34:48 CEST 2011 // by Alessandro Carbone(Noldor) // // This file is part of the KVIrc IRC client distribution // Copyright (C) 2011 Alessandro Carbone (elfonol at gmail dot com) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= // #include "kvi_settings.h" #include "kvi_debug.h" #include "KvsObject_webView.h" #include "KvsObject_pixmap.h" #include "KviError.h" #include "KviLocale.h" #include #if defined(COMPILE_WEBKIT_SUPPORT) #include #include #include #include #include #include #include #include #include #include #include static int g_iDownloadId = 1; KviKvsDownloadHandler::KviKvsDownloadHandler(KvsObject_webView * pParent, QFile * pFile, QNetworkReply * pNetReply, int iId) : QObject(pParent) { m_Id = iId; m_pParentScript = pParent; m_pReply = pNetReply; m_pFile = pFile; connect(m_pReply, SIGNAL(finished()), this, SLOT(slotReplyFinished())); connect(m_pReply, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); } void KviKvsDownloadHandler::slotReplyFinished() { KviKvsVariantList params(new KviKvsVariant((kvs_int_t)m_Id)); m_pParentScript->callFunction(m_pParentScript, "downloadCompletedEvent", ¶ms); m_pFile->close(); delete m_pFile; m_pFile = nullptr; m_pReply->deleteLater(); m_pReply = nullptr; this->deleteLater(); } KviKvsDownloadHandler::~KviKvsDownloadHandler() { if(m_pFile) { m_pFile->close(); delete m_pFile; m_pFile = nullptr; } if(m_pReply) { delete m_pReply; m_pReply = nullptr; } } void KviKvsDownloadHandler::slotReadyRead() { QVariant vSize = m_pReply->header(QNetworkRequest::ContentLengthHeader); int iSize = 0; if(!vSize.isNull()) { bool bOk; iSize = vSize.toInt(&bOk); } QByteArray bytes = m_pReply->readAll(); KviKvsVariantList params(new KviKvsVariant((kvs_int_t)bytes.count()), new KviKvsVariant((kvs_int_t)m_Id), new KviKvsVariant((kvs_int_t)iSize)); m_pParentScript->callFunction(m_pParentScript, "downloadProgressEvent", ¶ms); m_pFile->write(bytes); } const char * const webattributes_tbl[] = { "JavascriptEnabled", "PluginsEnabled", "JavascriptCanOpenWindows", "JavascriptCanAccessClipboard", "ZoomTextOnly", "LocalContentCanAccessFileUrls" }; const QWebSettings::WebAttribute webattributes_cod[] = { QWebSettings::JavascriptEnabled, QWebSettings::PluginsEnabled, QWebSettings::JavascriptCanOpenWindows, QWebSettings::JavascriptCanAccessClipboard, QWebSettings::ZoomTextOnly, QWebSettings::LocalContentCanAccessFileUrls }; const char * const findflag_tbl[] = { "FindBackward", "FindCaseSensitively", "FindWrapsAroundDocument", "HighlightAllOccurrences" }; const QWebPage::FindFlag findflag_cod[] = { QWebPage::FindBackward, QWebPage::FindCaseSensitively, QWebPage::FindWrapsAroundDocument, QWebPage::HighlightAllOccurrences }; const QWebPage::WebAction actions_cod[] = { QWebPage::OpenLink, QWebPage::DownloadLinkToDisk, QWebPage::CopyLinkToClipboard, QWebPage::OpenImageInNewWindow, QWebPage::DownloadImageToDisk, QWebPage::CopyImageToClipboard, QWebPage::Back, QWebPage::Forward, QWebPage::Stop, QWebPage::Reload, QWebPage::Cut, QWebPage::Copy, QWebPage::Paste, QWebPage::InspectElement, QWebPage::SelectAll }; const char * const actions_tbl[] = { "OpenLink", "DownloadLinkToDisk", "CopyLinkToClipboard", "OpenImageInNewWindow", "DownloadImageToDisk", "CopyImageToClipboard", "Back", "Forward", "Stop", "Reload", "Cut", "Copy", "Paste", "InspectElement", "SelectAll" }; #define webattributes_num (sizeof(webattributes_tbl) / sizeof(webattributes_tbl[0])) #define findflag_num (sizeof(findflag_tbl) / sizeof(findflag_tbl[0])) #define actions_num (sizeof(actions_tbl) / sizeof(actions_tbl[0])) /* @doc: webview @keyterms: An embedded webview widget, @title: webview @type: class @short: Provides web support in a widget using webkit. @inherits: [class]object[/class] [class]widget[/class] @description: Provides an embedded web browser using webkit. Page structure can be managed by web element's unique identifiers. @functions: !fn: $load() Sets the current URL for the webView and starts loading it !fn: $setHtml(,[]) Sets the content of the web view to the specified . External objects such as stylesheets or images referenced in the HTML document are located relative to . The html is loaded immediately; external objects are loaded asynchronously. !fn: $findText(,[flag 1,flag 2,..;string]) Finds the specified string, in the page, using the given options. Valid flags are: [pre] FindBackward - Searches backwards instead of forwards; FindCaseSensitively - Changes the behaviour to a case sensitive find operation. FindWrapsAroundDocument - Restart from the beginning of the document if the end was reached and the text was not found. HighlightAllOccurrences - Highlights all existing occurrences. [/pre] !fn: $frames() Returns an array containing the names of the document frames. !fn: appendWebViewActionToMenu(,,[]) !fn: $firstChild() Return the identifier of element's first child. !fn: $findAll(,) Searches for all the elements named and stores them in an array of element's identifiers. !fn: $findFirst(,) Searches for the first element named ; returns the identifier. !fn: $parentElement(,) Returns the parent of . !fn: $nextSibling() Returns the element just after . !fn: $appendInside(,) !fn: $appendOutside(,) !fn: $elementTagName() Returns the tag name of the . !fn: $getDocumentElement([frame_name:string]) Return as unique identifier the document element of the frame [frame_name]. If no value has been specified for [frame_name], the main frame of the page will be used. !fn: string $attributeNames() Returns a comma-separated list of the attribute names set on element . !fn: string $attribute(,) Returns the value of the attribute for element . !fn: setStyleProperty(,,) Sets the value of the inline style on element with the given name to . In order to ensure that the value will be applied, you may have to append "!important" to the value. !fn: styleProperty(,,) Returns the value of the style with the given name using the specified strategy. If a style with name does not exist, an empty string is returned. Possible value for are: [pre] CascadedStyle - the property's value is determined using the rules defined in the document's stylesheet. [b]This is the default strategy[/b]. InlineStyle - the property's value is determined by element definition, without respecting CSS rules. ComputedStyle - the property's value is determined by the style property resolved from the environment. [/pre] !fn: pixmap $makePreview() Returns a 212x142 thumbnail of the current webView constants. The returned object is an instance of the pixmap class. !fn: string $toPlainText() Returns the string representation of element . !fn: string $setPlainText() Set the string representation of the element . !fn: $setElementAttribute(,,) Sets the attribute with value to the element . !fn: $setWebSetting(,) Enables or disables the setting depending on . Valid settings name: JavascriptEnabled, PluginsEnabled, JavascriptCanOpenWindows, JavascriptCanAccessClipboard, ZoomTextOnly, LocalContentCanAccessFileUrls. !fn: $removeFromDocument() Removes the element from the document. !fn: $removeClass(,) Removes a class from the element . !fn: string $classes() Returns a comma-separated list of classes set on the element . !fn: $setLinkDelegationPolicy() Sets the link delegation policy: what happens when the users click on a link. Valid values: [br] DontDelegateLinks: No links are delegated. Instead, webView tries to handle them all. [br] DelegateExternalLinks: When activating links that point to documents not stored on the local filesystem or an equivalent then $linkClickedEvent() is executed. [br] DelegateAllLinks: Whenever a link is activated the $linkClickedEvent() is executed. !fn: $linkClickedEvent() This function can be called when the user clicks on a link, depending no the current link delegation policy. The argument of the function is the URL that has been clicked.[br] The default implementation emits the [classfnc:webview]$linkClicked[/classfnc]() signal. !fn: $loadStartedEvent() This function is called when the load of the page has started. The default implementation emits the [classfnc:webview]$loadStarted[/classfnc]() signal. !fn: $loadProgressEvent() This function can be called during the page load progress. The argument of the function is an int value that represent the loading progress status, ranging from 0 to 100.[br] The default implementation emits the [classfnc:webview]$loadProgress[/classfnc]() signal. !fn: $loadFinishedEvent() This function is called when the load of the page has finished. The argument of the function is a bool value that is true if the page has been loaded successfully, false otherwise.[br] The default implementation emits the [classfnc:webview]$loadFinished[/classfnc]() signal. !fn: $downloadRequestEvent() This function is called when the user tries to download a file. The argument of the function is the URL of the file.[br] You should return a valid path in the filesystem where to save the file.[br] The default implementation emits the [classfnc:webview]$downloadRequest[/classfnc]() signal. !fn: $downloadProgressEvent() This function can be called during the download of a file. Three integer arguments are passed to this function: the number of downloaded bytes, the download ID, the size of the remove file (if known). The default implementation emits the [classfnc:webview]$downloadProgress[/classfnc]() signal. !fn: $downloadCompletedEvent() This function can be called when a file download finishes. The argument of the function is the an integer value containing the download ID. The default implementation emits the [classfnc:webview]$downloadCompleted[/classfnc]() signal. @signals: !sg: linkClicked() This signal is emitted by the default implementation of [classfnc:webview]linkClickedEvent[/classfnc](). !sg: loadStarted() This signal is emitted by the default implementation of [classfnc:webview]loadStartedEvent[/classfnc](). !sg: loadProgress() This signal is emitted by the default implementation of [classfnc:webview]loadProgressEvent[/classfnc](). !sg: loadFinished() This signal is emitted by the default implementation of [classfnc:webview]loadFinishedEvent[/classfnc](). !sg: downloadRequest() This signal is emitted by the default implementation of [classfnc:webview]downloadRequestEvent[/classfnc](). !sg: downloadProgress() This signal is emitted by the default implementation of [classfnc:webview]downloadProgressEvent[/classfnc](). !sg: downloadCompleted() This signal is emitted by the default implementation of [classfnc:webview]downloadCompletedEvent[/classfnc](). */ KVSO_BEGIN_REGISTERCLASS(KvsObject_webView, "webview", "widget") // page related KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, load) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setHtml) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, frames) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, makePreview) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendWebViewActionToMenu) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setLinkDelegationPolicy) // navigationn through the dom's tree KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, firstChild) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, lastChild) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendInside) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendOutside) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, parentElement) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, nextSibling) // find dom's elements KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findAll) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findFirst) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findText) // element info KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementTagName) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, getDocumentElement) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementAttributeNames) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setElementAttribute) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementAttribute) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, hitTestContent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, toPlainText) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setPlainText) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, removeFromDocument) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, removeClass) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, addClass) // css KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setStyleProperty) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, styleProperty) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setWebSetting) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, classes) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setEventFilter) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, addToJavaScriptWindowObject) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, evaluateJavaScript) // events KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsChangeEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsSubmitEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsClickEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsMouseOverEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsMouseOutEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, linkClickedEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadFinishedEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadProgressEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadStartedEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadCompletedEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadRequestEvent) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadProgressEvent) KVSO_END_REGISTERCLASS(KvsObject_webView) KVSO_BEGIN_CONSTRUCTOR(KvsObject_webView, KviKvsObject) KVSO_END_CONSTRUCTOR(KvsObject_webView) KVSO_BEGIN_DESTRUCTOR(KvsObject_webView) m_elementMapper.clear(); KVSO_END_CONSTRUCTOR(KvsObject_webView) bool KvsObject_webView::init(KviKvsRunTimeContext * c, KviKvsVariantList *) { //SET_OBJECT(KviKvsWebview); setObject(new KviKvsWebView(parentScriptWidget(), getName().toUtf8().data(), this), true); elementMapId = 1; m_pContext = c; m_pNetworkManager = new QNetworkAccessManager(this); QWebPage * pPage = ((QWebView *)widget())->page(); connect(((QWebView *)widget()), SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); connect(((QWebView *)widget()), SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); connect(((QWebView *)widget()), SIGNAL(loadProgress(int)), this, SLOT(slotLoadProgress(int))); connect(pPage, SIGNAL(linkClicked(const QUrl &)), this, SLOT(slotLinkClicked(const QUrl &))); connect(pPage, SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(slotDownloadRequest(const QNetworkRequest &))); return true; } int KvsObject_webView::insertElement(const QWebElement & ele) { int eleid = getElementId(ele); if(!eleid) { m_elementMapper[elementMapId] = ele; return elementMapId++; } else return eleid; } int KvsObject_webView::getElementId(const QWebElement & ele) { QHashIterator it(m_elementMapper); while(it.hasNext()) { it.next(); if(it.value() == ele) return it.key(); } return 0; } QWebElement KvsObject_webView::getElement(int iIdx) { return m_elementMapper.value(iIdx); } void KvsObject_webView::getFrames(QWebFrame * pCurFrame, QStringList & szFramesNames) { szFramesNames.append(pCurFrame->title()); QList lFrames = pCurFrame->childFrames(); for(int i = 0; i < lFrames.count(); i++) { QWebFrame * pChildFrame = lFrames.at(i); if(pChildFrame->childFrames().count()) getFrames(pChildFrame, szFramesNames); } } QWebFrame * KvsObject_webView::findFrame(QWebFrame * pCurFrame, QString & szFrameName) { if(pCurFrame->title() == szFrameName) return pCurFrame; QList lFrames = pCurFrame->childFrames(); for(int i = 0; i < lFrames.count(); i++) { QWebFrame * pChildFrame = lFrames.at(i); if(pChildFrame->childFrames().count()) { pCurFrame = findFrame(pChildFrame, szFrameName); if(pCurFrame) return pCurFrame; } } return nullptr; } KVSO_CLASS_FUNCTION(webView, setLinkDelegationPolicy) { CHECK_INTERNAL_POINTER(widget()) QString szPolicy; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("policy", KVS_PT_STRING, 0, szPolicy) KVSO_PARAMETERS_END(c) QWebPage::LinkDelegationPolicy policy = QWebPage::DontDelegateLinks; if(KviQString::equalCI(szPolicy, "DontDelegateLinks")) policy = QWebPage::DontDelegateLinks; else if(KviQString::equalCI(szPolicy, "DelegateExternalLinks")) policy = QWebPage::DelegateExternalLinks; else if(KviQString::equalCI(szPolicy, "DelegateAllLinks")) policy = QWebPage::DelegateAllLinks; else c->warning(__tr2qs_ctx("Unknown delegation policy '%Q'- Switch do default dontDelegateLinks", "objects"), &szPolicy); ((QWebView *)widget())->page()->setLinkDelegationPolicy(policy); return true; } KVSO_CLASS_FUNCTION(webView, load) { CHECK_INTERNAL_POINTER(widget()) QString szUrl; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("url", KVS_PT_STRING, 0, szUrl) KVSO_PARAMETERS_END(c) ((QWebView *)widget())->load(QUrl(szUrl)); return true; } KVSO_CLASS_FUNCTION(webView, setHtml) { CHECK_INTERNAL_POINTER(widget()) QString szHtml, szUrlBase; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("szHtml", KVS_PT_STRING, 0, szHtml) KVSO_PARAMETER("urlbase", KVS_PT_STRING, KVS_PF_OPTIONAL, szUrlBase) KVSO_PARAMETERS_END(c) ((QWebView *)widget())->setHtml(szHtml, QUrl(szUrlBase)); return true; } KVSO_CLASS_FUNCTION(webView, makePreview) { CHECK_INTERNAL_POINTER(widget()) QSize size = ((QWebView *)widget())->page()->mainFrame()->contentsSize(); QImage * pImage = new QImage(212, 142, QImage::Format_RGB32); QWebFrame * pFrame = ((QWebView *)widget())->page()->mainFrame(); QPainter painter(pImage); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::TextAntialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); double dWScale = size.width() > 0 ? (212.0 / (double)(size.width())) : 0; double dHScale = dWScale; if((size.height() * dWScale) < 142) { // solution 1 is to fill the missing bacgkround painter.fillRect(0, 0, 212, 142, QColor(255, 255, 255)); // solution 2 is to stretch the contents, but this doesn't work well because // the frame reports a size that doesn't exactly match the document //dHScale = 142.0 / (double)(size.height()); } painter.scale(dWScale, dHScale); pFrame->documentElement().render(&painter); painter.end(); KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass("pixmap"); KviKvsVariantList params; KviKvsObject * pObject = pClass->allocateInstance(nullptr, "internalpixmap", c->context(), ¶ms); ((KvsObject_pixmap *)pObject)->setInternalImage(pImage); c->returnValue()->setHObject(pObject->handle()); return true; } KVSO_CLASS_FUNCTION(webView, findAll) { CHECK_INTERNAL_POINTER(widget()) QString szQuery; KviKvsArray * pArray; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("query", KVS_PT_STRING, 0, szQuery) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElementCollection elementCollection = element.findAll(szQuery); if(!elementCollection.count()) return true; //qDebug("collection %i",elementCollection.count()); int idx = 0; pArray = new KviKvsArray(); for(int i = 0; i < elementCollection.count(); i++) { QWebElement element = elementCollection.at(i); int id = insertElement(element); pArray->set(idx, new KviKvsVariant((kvs_int_t)id)); idx++; } c->returnValue()->setArray(pArray); return true; } KVSO_CLASS_FUNCTION(webView, evaluateJavaScript) { CHECK_INTERNAL_POINTER(widget()) QString szScript; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("script_code", KVS_PT_STRING, 0, szScript) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element is null: you must call getDocumentElement first", "objects")); return true; } QVariant vRes = element.evaluateJavaScript(szScript); if(vRes.type() == QVariant::String) { QString szVal = vRes.toString(); c->returnValue()->setString(szVal); } else c->warning(__tr2qs_ctx("Unsupported datatype", "objects")); return true; } KVSO_CLASS_FUNCTION(webView, findFirst) { QString szQuery; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("query", KVS_PT_STRING, 0, szQuery) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement tempElement = element.findFirst(szQuery); if(tempElement.isNull()) { c->returnValue()->setInteger(-1); return true; } int id = insertElement(tempElement); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, removeFromDocument) { kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.removeFromDocument(); return true; } KVSO_CLASS_FUNCTION(webView, appendInside) { kvs_int_t iEleId; QString szCode; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szCode) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.appendInside(szCode); return true; } KVSO_CLASS_FUNCTION(webView, appendOutside) { kvs_int_t iEleId; QString szCode; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szCode) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.appendOutside(szCode); return true; } KVSO_CLASS_FUNCTION(webView, nextSibling) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement tempElement = element.nextSibling(); if(tempElement.isNull()) { c->returnValue()->setInteger(-1); return true; } int id = insertElement(tempElement); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, frames) { CHECK_INTERNAL_POINTER(widget()) QWebFrame * pFrame = ((QWebView *)widget())->page()->mainFrame(); QStringList szFramesNames; getFrames(pFrame, szFramesNames); KviKvsArray * pArray = new KviKvsArray(); c->returnValue()->setArray(pArray); return true; } KVSO_CLASS_FUNCTION(webView, elementTagName) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { // qDebug("isnull ad index %i",iEleId); c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } c->returnValue()->setString(element.tagName()); return true; } KVSO_CLASS_FUNCTION(webView, setElementAttribute) { CHECK_INTERNAL_POINTER(widget()) QString szName, szValue; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName) KVSO_PARAMETER("value", KVS_PT_STRING, 0, szValue) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.setAttribute(szName, szValue); return true; } KVSO_CLASS_FUNCTION(webView, removeClass) { CHECK_INTERNAL_POINTER(widget()) QString szClassName; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("class_name", KVS_PT_NONEMPTYSTRING, 0, szClassName) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.removeClass(szClassName); return true; } KVSO_CLASS_FUNCTION(webView, addClass) { CHECK_INTERNAL_POINTER(widget()) QString szClassName; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("class_name", KVS_PT_NONEMPTYSTRING, 0, szClassName) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.addClass(szClassName); return true; } KVSO_CLASS_FUNCTION(webView, setWebSetting) { CHECK_INTERNAL_POINTER(widget()) QString szName; bool bEnabled; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName) KVSO_PARAMETER("value", KVS_PT_BOOLEAN, 0, bEnabled) KVSO_PARAMETERS_END(c) bool found = false; unsigned int j = 0; for(; j < webattributes_num; j++) { if(KviQString::equalCI(szName, webattributes_tbl[j])) { found = true; break; } } if(found) ((QWebView *)widget())->settings()->setAttribute(webattributes_cod[j], bEnabled); else c->warning(__tr2qs_ctx("Unknown web setting '%Q'", "objects"), &szName); return true; } KVSO_CLASS_FUNCTION(webView, findText) { CHECK_INTERNAL_POINTER(widget()) QString szName; QStringList szFindFlag; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("find_text", KVS_PT_NONEMPTYSTRING, 0, szName) KVSO_PARAMETER("find_flag", KVS_PT_STRINGLIST, KVS_PF_OPTIONAL, szFindFlag) KVSO_PARAMETERS_END(c) int findflag = 0; int sum = 0; for(auto & it : szFindFlag) { findflag = 0; for(unsigned int j = 0; j < findflag_num; j++) { if(KviQString::equalCI(it, findflag_tbl[j])) { findflag = findflag_cod[j]; break; } } if(findflag) sum = sum | findflag; else c->warning(__tr2qs_ctx("Unknown findflag '%Q'", "objects"), &it); } ((QWebView *)widget())->findText(szName, (QWebPage::FindFlags)findflag); return true; } KVSO_CLASS_FUNCTION(webView, elementAttribute) { CHECK_INTERNAL_POINTER(widget()) QString szName; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } // workaround for this issue: https://bugreports.qt.nokia.com//browse/QTWEBKIT-88 if(KviQString::equalCI(element.tagName(), "input")) { QVariant value = element.evaluateJavaScript("this." + szName); c->returnValue()->setString(value.toString()); return true; } c->returnValue()->setString(element.attribute(szName)); return true; } KVSO_CLASS_FUNCTION(webView, elementAttributeNames) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QString szAttributeNames; QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } szAttributeNames = element.attributeNames().join(","); c->returnValue()->setString(szAttributeNames); return true; } KVSO_CLASS_FUNCTION(webView, classes) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QString szClasses; szClasses = element.classes().join(","); c->returnValue()->setString(szClasses); return true; } KVSO_CLASS_FUNCTION(webView, toPlainText) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } c->returnValue()->setString(element.toPlainText()); return true; } KVSO_CLASS_FUNCTION(webView, setPlainText) { CHECK_INTERNAL_POINTER(widget()) QString szText; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("plaintext", KVS_PT_STRING, 0, szText) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.setPlainText(szText); return true; } KVSO_CLASS_FUNCTION(webView, firstChild) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement tempElement = element.firstChild(); if(tempElement.isNull()) { c->returnValue()->setInteger(-1); return true; } int id = insertElement(tempElement); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, lastChild) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement tempElement = element.lastChild(); if(tempElement.isNull()) { c->returnValue()->setInteger(-1); return true; } int id = insertElement(tempElement); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, parentElement) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement tempElement = element.parent(); if(tempElement.isNull()) { c->returnValue()->setInteger(-1); return true; } int id = insertElement(tempElement); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, styleProperty) { CHECK_INTERNAL_POINTER(widget()) QString szName, szStyleResolveStrategy; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName) KVSO_PARAMETER("style_resolve_strategy", KVS_PT_STRING, KVS_PF_OPTIONAL, szStyleResolveStrategy) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } QWebElement::StyleResolveStrategy styleStrategy = QWebElement::CascadedStyle; if(!szStyleResolveStrategy.isEmpty()) { if(KviQString::equalCI(szStyleResolveStrategy, "InlineStyle")) styleStrategy = QWebElement::InlineStyle; else if(KviQString::equalCI(szStyleResolveStrategy, "CascadedStyle")) styleStrategy = QWebElement::CascadedStyle; else if(KviQString::equalCI(szStyleResolveStrategy, "ComputedStyle")) styleStrategy = QWebElement::ComputedStyle; else { c->warning(__tr2qs_ctx("Unknown styleResolveStrategy: '%Q' - Switching to default CascadedStyle strategy", "objects"), &szStyleResolveStrategy); } } c->returnValue()->setString(element.styleProperty(szName, styleStrategy)); return true; } KVSO_CLASS_FUNCTION(webView, setStyleProperty) { CHECK_INTERNAL_POINTER(widget()) QString szProperty, szValue; kvs_int_t iEleId; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId) KVSO_PARAMETER("property", KVS_PT_STRING, 0, szProperty) KVSO_PARAMETER("value", KVS_PT_STRING, 0, szValue) KVSO_PARAMETERS_END(c) QWebElement element = getElement(iEleId); if(element.isNull()) { c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId); return true; } element.setStyleProperty(szProperty, szValue); return true; } KVSO_CLASS_FUNCTION(webView, getDocumentElement) { CHECK_INTERNAL_POINTER(widget()) QString szFrameName; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("frame_name", KVS_PT_STRING, KVS_PF_OPTIONAL, szFrameName) KVSO_PARAMETERS_END(c) QWebFrame * pFrame; pFrame = ((QWebView *)widget())->page()->mainFrame(); if(!szFrameName.isEmpty()) { pFrame = findFrame(pFrame, szFrameName); if(!pFrame) { c->warning(__tr2qs_ctx("Unknown frame '%Q'", "objects"), &szFrameName); return true; } } int id = insertElement(pFrame->documentElement()); c->returnValue()->setInteger((kvs_int_t)id); return true; } KVSO_CLASS_FUNCTION(webView, addToJavaScriptWindowObject) { CHECK_INTERNAL_POINTER(widget()) QString szFrameName, szObjectName; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("object_name", KVS_PT_NONEMPTYSTRING, 0, szObjectName) KVSO_PARAMETER("frame_name", KVS_PT_STRING, KVS_PF_OPTIONAL, szFrameName) KVSO_PARAMETERS_END(c) QWebFrame * pFrame; pFrame = ((QWebView *)widget())->page()->mainFrame(); if(!szFrameName.isEmpty()) { pFrame = findFrame(pFrame, szFrameName); if(!pFrame) { c->warning(__tr2qs_ctx("Unknown frame '%Q'", "objects"), &szFrameName); return true; } } pFrame->addToJavaScriptWindowObject(szObjectName, this); return true; } KVSO_CLASS_FUNCTION(webView, setEventFilter) { QWebFrame * pFrame; pFrame = ((QWebView *)widget())->page()->mainFrame(); pFrame->addToJavaScriptWindowObject("kvs", this); return true; } KVSO_CLASS_FUNCTION(webView, hitTestContent) { CHECK_INTERNAL_POINTER(widget()) kvs_int_t iYPos, iXPos; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("x_pos", KVS_PT_INT, 0, iXPos) KVSO_PARAMETER("y_pos", KVS_PT_INT, 0, iYPos) KVSO_PARAMETERS_END(c) QWebFrame * pFrame; pFrame = ((QWebView *)widget())->page()->mainFrame(); QWebHitTestResult res = pFrame->hitTestContent(QPoint(iXPos, iYPos)); if(res.isNull()) return true; KviKvsHash * pHash = new KviKvsHash(); pHash->set("imageurl", new KviKvsVariant(res.imageUrl().toString())); pHash->set("linktitle", new KviKvsVariant(res.linkTitle().toString())); pHash->set("linktext", new KviKvsVariant(res.linkText())); pHash->set("linkelement", new KviKvsVariant((kvs_int_t)insertElement(res.linkElement()))); pHash->set("enclosingelement", new KviKvsVariant((kvs_int_t)insertElement(res.enclosingBlockElement()))); pHash->set("element", new KviKvsVariant((kvs_int_t)insertElement(res.element()))); c->returnValue()->setHash(pHash); return true; } KVSO_CLASS_FUNCTION(webView, appendWebViewActionToMenu) { CHECK_INTERNAL_POINTER(widget()) KviKvsObject * ob; kvs_hobject_t hObject; QString szActionName, szIcon; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("popup", KVS_PT_HOBJECT, 0, hObject) KVSO_PARAMETER("action_name", KVS_PT_NONEMPTYSTRING, 0, szActionName) KVSO_PARAMETER("icon", KVS_PT_STRING, KVS_PF_OPTIONAL, szIcon) KVSO_PARAMETERS_END(c) ob = KviKvsKernel::instance()->objectController()->lookupObject(hObject); if(!ob) { c->warning(__tr2qs_ctx("Widget parameter is not an object", "objects")); return true; } if(!ob->object()) { c->warning(__tr2qs_ctx("Widget parameter is not a valid object", "objects")); return true; } if(!ob->inheritsClass("popupmenu")) { c->warning(__tr2qs_ctx("Can't add a non-popupmenu object", "objects")); return true; } QAction * pAction = nullptr; for(unsigned int i = 0; i < actions_num; i++) { if(KviQString::equalCI(szActionName, actions_tbl[i])) { pAction = ((QWebView *)widget())->pageAction(actions_cod[i]); break; } } if(!pAction) { c->warning(__tr2qs_ctx("Unknown action '%Q':", "objects"), &szActionName); return true; } if(!szIcon.isEmpty()) { QPixmap * pix; pix = g_pIconManager->getImage(szIcon); if(pix) pAction->setIcon(*pix); else c->warning(__tr2qs_ctx("Icon '%Q' doesn't exist", "objects"), &szIcon); } ((QMenu *)(ob->object()))->addAction(pAction); return true; } KVSO_CLASS_FUNCTION(webView, loadFinishedEvent) { emitSignal("loadFinished", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, loadProgressEvent) { emitSignal("loadProgress", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, loadStartedEvent) { emitSignal("loadStarted", c); return true; } KVSO_CLASS_FUNCTION(webView, downloadCompletedEvent) { emitSignal("downloadCompleted", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, downloadProgressEvent) { emitSignal("downloadProgress", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, linkClickedEvent) { emitSignal("linkClicked", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, downloadRequestEvent) { emitSignal("downloadRequest", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, jsSubmitEvent) { emitSignal("jssubmit", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, jsChangeEvent) { emitSignal("jschange", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, jsClickEvent) { emitSignal("jsclick", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, jsMouseOverEvent) { emitSignal("jsmouseover", c, c->params()); return true; } KVSO_CLASS_FUNCTION(webView, jsMouseOutEvent) { emitSignal("jsmouseout", c, c->params()); return true; } void KvsObject_webView::slotOnChange(QString szParam) { //qDebug("change"); KviKvsVariantList params(new KviKvsVariant(szParam)); callFunction(this, "jsChangeEvent", ¶ms); } void KvsObject_webView::slotOnSubmit(QString szParam) { // ,QString szParam2,QString szParam3 //qDebug("slotonsubmit"); KviKvsVariantList params(new KviKvsVariant(szParam)); callFunction(this, "jsSubmitEvent", ¶ms); } void KvsObject_webView::slotOnClick(QString szParam) { KviKvsVariantList params(new KviKvsVariant(szParam)); callFunction(this, "jsClickEvent", ¶ms); } void KvsObject_webView::slotOnMouseOver(QString szParam) { KviKvsVariantList params(new KviKvsVariant(szParam)); callFunction(this, "jsMouseOverEvent", ¶ms); } void KvsObject_webView::slotOnMouseOut(QString szParam) { KviKvsVariantList params(new KviKvsVariant(szParam)); callFunction(this, "jsMouseOutEvent", ¶ms); } // slots void KvsObject_webView::slotLoadFinished(bool bOk) { if(bOk) m_currentElement = ((QWebView *)widget())->page()->mainFrame()->documentElement(); KviKvsVariantList params(new KviKvsVariant(bOk)); callFunction(this, "loadFinishedEvent", ¶ms); } void KvsObject_webView::slotLoadStarted() { KviKvsVariantList * lParams = nullptr; callFunction(this, "loadStartedEvent", lParams); } void KvsObject_webView::slotLoadProgress(int iProgress) { KviKvsVariantList params(new KviKvsVariant((kvs_int_t)iProgress)); callFunction(this, "loadProgressEvent", ¶ms); } void KvsObject_webView::slotLinkClicked(const QUrl & url) { QString szUrl = url.toString(); KviKvsVariantList params(new KviKvsVariant(szUrl)); callFunction(this, "linkClickedEvent", ¶ms); } void KvsObject_webView::slotDownloadRequest(const QNetworkRequest & r) { QNetworkReply * pReply = m_pNetworkManager->get(r); QString szFilePath = ""; KviKvsVariant * filepathret = new KviKvsVariant(szFilePath); KviKvsVariantList params(new KviKvsVariant(r.url().toString())); callFunction(this, "downloadRequestEvent", filepathret, ¶ms); filepathret->asString(szFilePath); if(!szFilePath.isEmpty()) { QFile * pFile = new QFile(szFilePath); if(!pFile->open(QIODevice::WriteOnly)) { m_pContext->warning(__tr2qs_ctx("Invalid file path '%Q'", "objects"), &szFilePath); pReply->abort(); pReply->deleteLater(); return; } (void)new KviKvsDownloadHandler(this, pFile, pReply, g_iDownloadId); g_iDownloadId++; } } KviKvsWebView::KviKvsWebView(QWidget * par, const char * name, KvsObject_webView * parent) : QWebView(par) { m_pParentScript = parent; setObjectName(name); } void KviKvsWebView::mouseMoveEvent(QMouseEvent * ev) { KviKvsVariant vRetValue; KviKvsVariantList lParams; lParams.append(new KviKvsVariant((kvs_int_t)ev->x())); lParams.append(new KviKvsVariant((kvs_int_t)ev->y())); if(!m_pParentScript->callFunction(m_pParentScript, "mouseMoveEvent", &vRetValue, &lParams)) QWebView::mouseMoveEvent(ev); // ignore results of a broken event handler else { if(!vRetValue.asBoolean()) QWebView::mouseMoveEvent(ev); } } void KviKvsWebView::contextMenuEvent(QContextMenuEvent * ev) { KviKvsVariant vRetValue; KviKvsVariantList lParams; lParams.append(new KviKvsVariant((kvs_int_t)ev->x())); lParams.append(new KviKvsVariant((kvs_int_t)ev->y())); if(!m_pParentScript->callFunction(m_pParentScript, "customContextMenuRequestedEvent", &vRetValue, &lParams)) QWebView::contextMenuEvent(ev); // ignore results of a broken event handler else { if(!vRetValue.asBoolean()) QWebView::contextMenuEvent(ev); } } bool KviKvsWebView::event(QEvent * e) { if(e->type() == QEvent::ToolTip) { QHelpEvent * helpEvent = static_cast(e); QString szTooltip = ""; KviKvsVariant * tipret = new KviKvsVariant(szTooltip); KviKvsVariantList params(new KviKvsVariant((kvs_int_t)helpEvent->x()), new KviKvsVariant((kvs_int_t)helpEvent->y())); m_pParentScript->callFunction(m_pParentScript, "maybeTipEvent", tipret, ¶ms); tipret->asString(szTooltip); if(!szTooltip.isEmpty()) { QToolTip::showText(helpEvent->globalPos(), szTooltip); return false; } } return QWebView::event(e); } KviKvsWebView::~KviKvsWebView() = default; #endif // COMPILE_WEBKIT_SUPPORT