1 //=============================================================================
2 //
3 //   File : KvsObject_webView.cpp
4 //   Creation date : Wed Mar 9 23:34:48 CEST 2011
5 //   by Alessandro Carbone(Noldor)
6 //
7 //   This file is part of the KVIrc IRC client distribution
8 //   Copyright (C) 2011 Alessandro Carbone (elfonol at gmail dot com)
9 //
10 //   This program is FREE software. You can redistribute it and/or
11 //   modify it under the terms of the GNU General Public License
12 //   as published by the Free Software Foundation; either version 2
13 //   of the License, or (at your option) any later version.
14 //
15 //   This program is distributed in the HOPE that it will be USEFUL,
16 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 //   See the GNU General Public License for more details.
19 //
20 //   You should have received a copy of the GNU General Public License
21 //   along with this program. If not, write to the Free Software Foundation,
22 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 //=============================================================================
25 //
26 
27 #include "kvi_settings.h"
28 #include "kvi_debug.h"
29 #include "KvsObject_webView.h"
30 #include "KvsObject_pixmap.h"
31 #include "KviError.h"
32 #include "KviLocale.h"
33 
34 #include <QMenu>
35 
36 #if defined(COMPILE_WEBKIT_SUPPORT)
37 #include <QWebView>
38 #include <QWebSettings>
39 #include <QWebElement>
40 #include <QNetworkRequest>
41 #include <QNetworkReply>
42 #include <QPixmap>
43 #include <QFile>
44 #include <QSize>
45 #include <QPoint>
46 #include <QVariant>
47 #include <QToolTip>
48 
49 static int g_iDownloadId = 1;
KviKvsDownloadHandler(KvsObject_webView * pParent,QFile * pFile,QNetworkReply * pNetReply,int iId)50 KviKvsDownloadHandler::KviKvsDownloadHandler(KvsObject_webView * pParent, QFile * pFile, QNetworkReply * pNetReply, int iId)
51     : QObject(pParent)
52 {
53 
54 	m_Id = iId;
55 	m_pParentScript = pParent;
56 	m_pReply = pNetReply;
57 	m_pFile = pFile;
58 	connect(m_pReply, SIGNAL(finished()), this, SLOT(slotReplyFinished()));
59 	connect(m_pReply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
60 }
61 
slotReplyFinished()62 void KviKvsDownloadHandler::slotReplyFinished()
63 {
64 	KviKvsVariantList params(new KviKvsVariant((kvs_int_t)m_Id));
65 	m_pParentScript->callFunction(m_pParentScript, "downloadCompletedEvent", &params);
66 	m_pFile->close();
67 	delete m_pFile;
68 	m_pFile = nullptr;
69 	m_pReply->deleteLater();
70 	m_pReply = nullptr;
71 	this->deleteLater();
72 }
73 
~KviKvsDownloadHandler()74 KviKvsDownloadHandler::~KviKvsDownloadHandler()
75 {
76 	if(m_pFile)
77 	{
78 		m_pFile->close();
79 		delete m_pFile;
80 		m_pFile = nullptr;
81 	}
82 	if(m_pReply)
83 	{
84 		delete m_pReply;
85 		m_pReply = nullptr;
86 	}
87 }
slotReadyRead()88 void KviKvsDownloadHandler::slotReadyRead()
89 {
90 	QVariant vSize = m_pReply->header(QNetworkRequest::ContentLengthHeader);
91 	int iSize = 0;
92 	if(!vSize.isNull())
93 	{
94 		bool bOk;
95 		iSize = vSize.toInt(&bOk);
96 	}
97 
98 	QByteArray bytes = m_pReply->readAll();
99 	KviKvsVariantList params(new KviKvsVariant((kvs_int_t)bytes.count()),
100 	    new KviKvsVariant((kvs_int_t)m_Id), new KviKvsVariant((kvs_int_t)iSize));
101 	m_pParentScript->callFunction(m_pParentScript, "downloadProgressEvent", &params);
102 	m_pFile->write(bytes);
103 }
104 
105 const char * const webattributes_tbl[] = {
106 	"JavascriptEnabled",
107 	"PluginsEnabled",
108 	"JavascriptCanOpenWindows",
109 	"JavascriptCanAccessClipboard",
110 	"ZoomTextOnly",
111 	"LocalContentCanAccessFileUrls"
112 };
113 
114 const QWebSettings::WebAttribute webattributes_cod[] = {
115 	QWebSettings::JavascriptEnabled,
116 	QWebSettings::PluginsEnabled,
117 	QWebSettings::JavascriptCanOpenWindows,
118 	QWebSettings::JavascriptCanAccessClipboard,
119 	QWebSettings::ZoomTextOnly,
120 	QWebSettings::LocalContentCanAccessFileUrls
121 };
122 
123 const char * const findflag_tbl[] = {
124 	"FindBackward",
125 	"FindCaseSensitively",
126 	"FindWrapsAroundDocument",
127 	"HighlightAllOccurrences"
128 };
129 
130 const QWebPage::FindFlag findflag_cod[] = {
131 	QWebPage::FindBackward,
132 	QWebPage::FindCaseSensitively,
133 	QWebPage::FindWrapsAroundDocument,
134 	QWebPage::HighlightAllOccurrences
135 };
136 
137 const QWebPage::WebAction actions_cod[] = {
138 	QWebPage::OpenLink,
139 	QWebPage::DownloadLinkToDisk,
140 	QWebPage::CopyLinkToClipboard,
141 	QWebPage::OpenImageInNewWindow,
142 	QWebPage::DownloadImageToDisk,
143 	QWebPage::CopyImageToClipboard,
144 	QWebPage::Back,
145 	QWebPage::Forward,
146 	QWebPage::Stop,
147 	QWebPage::Reload,
148 	QWebPage::Cut,
149 	QWebPage::Copy,
150 	QWebPage::Paste,
151 	QWebPage::InspectElement,
152 	QWebPage::SelectAll
153 };
154 
155 const char * const actions_tbl[] = {
156 	"OpenLink",
157 	"DownloadLinkToDisk",
158 	"CopyLinkToClipboard",
159 	"OpenImageInNewWindow",
160 	"DownloadImageToDisk",
161 	"CopyImageToClipboard",
162 	"Back",
163 	"Forward",
164 	"Stop",
165 	"Reload",
166 	"Cut",
167 	"Copy",
168 	"Paste",
169 	"InspectElement",
170 	"SelectAll"
171 };
172 
173 #define webattributes_num (sizeof(webattributes_tbl) / sizeof(webattributes_tbl[0]))
174 #define findflag_num (sizeof(findflag_tbl) / sizeof(findflag_tbl[0]))
175 #define actions_num (sizeof(actions_tbl) / sizeof(actions_tbl[0]))
176 
177 /*
178 	@doc:	webview
179 	@keyterms:
180 		An embedded webview widget,
181 	@title:
182 		webview
183 	@type:
184 		class
185 	@short:
186 		Provides web support in a widget using webkit.
187 	@inherits:
188 		[class]object[/class]
189 		[class]widget[/class]
190 	@description:
191 		Provides an embedded web browser using webkit. Page structure can be managed by web element's unique identifiers.
192 	@functions:
193 		!fn: $load(<url:string>)
194 		Sets the current URL for the webView and starts loading it
195 		!fn: $setHtml(<html_code:string>,[<baseurl:string>])
196 		Sets the content of the web view to the specified <html_code>.
197 		External objects such as stylesheets or images referenced in the HTML document are located relative to <baseurl>.
198 		The html is loaded immediately; external objects are loaded asynchronously.
199 		!fn: $findText(<txt:string>,[flag 1,flag 2,..;string])
200 		Finds the specified string, in the page, using the given options.
201 		Valid flags are:
202 		[pre]
203 			FindBackward		- Searches backwards instead of forwards;
204 			FindCaseSensitively	- Changes the behaviour to a case sensitive find operation.
205 			FindWrapsAroundDocument	- Restart from the beginning of the document if the end was reached and the text was not found.
206 			HighlightAllOccurrences	- Highlights all existing occurrences.
207 		[/pre]
208 		!fn: <array> $frames()
209 		Returns an array containing the names of the document frames.
210 		!fn: appendWebViewActionToMenu(<menu:h_object>,<webview_action:string>,[<icon_identifier>])
211 		!fn: <id:integer> $firstChild(<element_id:integer>)
212 		Return the identifier of element's first child.
213 		!fn: <array> $findAll(<element_id:integer>,<query:string>)
214 		Searches for all the elements named <query> and stores them in an array of element's identifiers.
215 		!fn: <id:integer> $findFirst(<element_id:integer>,<query:string>)
216 		Searches for the first element named <query>; returns the identifier.
217 		!fn: <id:integer> $parentElement(<element_id:integer>,)
218 		Returns the parent of <element_id>.
219 		!fn: <id:integer> $nextSibling(<element_id>)
220 		Returns the element just after <element_id>.
221 		!fn: $appendInside(<element_id>,<html_code>)
222 		!fn: $appendOutside(<element_id>,<html_code>)
223 		!fn: <string> $elementTagName(<element_id>)
224 		Returns the tag name of the <element_id>.
225 		!fn: <id:integer> $getDocumentElement([frame_name:string])
226 		Return as unique identifier the document element of the frame [frame_name].
227 		If no value has been specified for [frame_name], the main frame of the page will be used.
228 		!fn: string $attributeNames(<element_id>)
229 		Returns a comma-separated list of the attribute names set on element <element_id>.
230 		!fn: string $attribute(<element_id>,<name:string>)
231 		Returns the value of the attribute <name> for element <element_id>.
232 		!fn: setStyleProperty(<element_id>,<name:string>,<value:string>)
233 		Sets the value of the inline style on element <element_id> with the given name to <value> .
234 		In order to ensure that the value will be applied, you may have to append "!important" to the value.
235 		!fn: <value:string> styleProperty(<element_id>,<name:string>,<style_resolve_strategy:string>)
236 		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.
237 		Possible value for <style_resolve_strategy> are:
238 		[pre]
239 			CascadedStyle  - the property's value is determined using the rules defined in the document's stylesheet. [b]This is the default strategy[/b].
240 			InlineStyle    - the property's value is determined by element definition, without respecting CSS rules.
241 			ComputedStyle  - the property's value is determined by the style property resolved from the environment.
242 		[/pre]
243 		!fn: pixmap $makePreview()
244 		Returns a 212x142 thumbnail of the current webView constants.
245 		The returned object is an instance of the pixmap class.
246 		!fn: string $toPlainText(<element_id>)
247 		Returns the string representation of element <element_id>.
248 		!fn: string $setPlainText(<element_id>)
249 		Set the string representation of the  element <element_id>.
250 		!fn: $setElementAttribute(<element_id>,<name:string>,<value:string>)
251 		Sets the attribute <name> with value <value> to the element <element_id>.
252 		!fn: $setWebSetting(<name:string>,<value:bool>)
253 		Enables or disables the <name> setting depending on <value>.
254 		Valid settings name: JavascriptEnabled, PluginsEnabled, JavascriptCanOpenWindows, JavascriptCanAccessClipboard, ZoomTextOnly, LocalContentCanAccessFileUrls.
255 		!fn: $removeFromDocument(<element_id>)
256 		Removes the element <element_id> from the document.
257 		!fn: $removeClass(<element_id>,<class_name:string>)
258 		Removes a class from the element <element_id>.
259 		!fn: string $classes(<element_id>)
260 		Returns a comma-separated list of classes set on the element <element_id>.
261 		!fn: $setLinkDelegationPolicy(<policy:string>)
262 		Sets the link delegation policy: what happens when the users click on a link. Valid values:
263 		[br] DontDelegateLinks: No links are delegated. Instead, webView tries to handle them all.
264 		[br] DelegateExternalLinks: When activating links that point to documents not stored on the local filesystem or an equivalent then $linkClickedEvent() is executed.
265 		[br] DelegateAllLinks: Whenever a link is activated the $linkClickedEvent() is executed.
266 		!fn: $linkClickedEvent()
267 		This function can be called when the user clicks on a link, depending no the current link delegation policy.
268 		The argument of the function is the URL that has been clicked.[br]
269 		The default implementation emits the [classfnc:webview]$linkClicked[/classfnc]() signal.
270 		!fn: $loadStartedEvent()
271 		This function is called when the load of the page has started.
272 		The default implementation emits the [classfnc:webview]$loadStarted[/classfnc]() signal.
273 		!fn: $loadProgressEvent()
274 		This function can be called during the page load progress.
275 		The argument of the function is an int value that represent the loading progress status, ranging from 0 to 100.[br]
276 		The default implementation emits the [classfnc:webview]$loadProgress[/classfnc]() signal.
277 		!fn: $loadFinishedEvent()
278 		This function is called when the load of the page has finished.
279 		The argument of the function is a bool value that is true if the page has been loaded successfully, false otherwise.[br]
280 		The default implementation emits the [classfnc:webview]$loadFinished[/classfnc]() signal.
281 		!fn: $downloadRequestEvent()
282 		This function is called when the user tries to download a file.
283 		The argument of the function is the URL of the file.[br]
284 		You should return a valid path in the filesystem where to save the file.[br]
285 		The default implementation emits the [classfnc:webview]$downloadRequest[/classfnc]() signal.
286 		!fn: $downloadProgressEvent()
287 		This function can be called during the download of a file.
288 		Three integer arguments are passed to this function: the number of downloaded bytes, the download ID, the size of the remove file (if known).
289 		The default implementation emits the [classfnc:webview]$downloadProgress[/classfnc]() signal.
290 		!fn: $downloadCompletedEvent()
291 		This function can be called when a file download finishes.
292 		The argument of the function is the an integer value containing the download ID.
293 		The default implementation emits the [classfnc:webview]$downloadCompleted[/classfnc]() signal.
294 	@signals:
295 		!sg: linkClicked()
296 		This signal is emitted by the default implementation of [classfnc:webview]linkClickedEvent[/classfnc]().
297 		!sg: loadStarted()
298 		This signal is emitted by the default implementation of [classfnc:webview]loadStartedEvent[/classfnc]().
299 		!sg: loadProgress()
300 		This signal is emitted by the default implementation of [classfnc:webview]loadProgressEvent[/classfnc]().
301 		!sg: loadFinished()
302 		This signal is emitted by the default implementation of [classfnc:webview]loadFinishedEvent[/classfnc]().
303 		!sg: downloadRequest()
304 		This signal is emitted by the default implementation of [classfnc:webview]downloadRequestEvent[/classfnc]().
305 		!sg: downloadProgress()
306 		This signal is emitted by the default implementation of [classfnc:webview]downloadProgressEvent[/classfnc]().
307 		!sg: downloadCompleted()
308 		This signal is emitted by the default implementation of [classfnc:webview]downloadCompletedEvent[/classfnc]().
309 */
310 
311 KVSO_BEGIN_REGISTERCLASS(KvsObject_webView, "webview", "widget")
312 
313 // page related
314 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, load)
315 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setHtml)
316 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, frames)
317 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, makePreview)
318 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendWebViewActionToMenu)
319 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setLinkDelegationPolicy)
320 
321 // navigationn through the dom's tree
322 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, firstChild)
323 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, lastChild)
324 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendInside)
325 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, appendOutside)
326 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, parentElement)
327 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, nextSibling)
328 
329 // find dom's elements
330 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findAll)
331 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findFirst)
332 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, findText)
333 
334 // element info
335 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementTagName)
336 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, getDocumentElement)
337 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementAttributeNames)
338 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setElementAttribute)
339 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, elementAttribute)
340 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, hitTestContent)
341 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, toPlainText)
342 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setPlainText)
343 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, removeFromDocument)
344 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, removeClass)
345 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, addClass)
346 
347 // css
348 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setStyleProperty)
349 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, styleProperty)
350 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setWebSetting)
351 
352 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, classes)
353 
354 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, setEventFilter)
355 
356 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, addToJavaScriptWindowObject)
357 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, evaluateJavaScript)
358 
359 // events
360 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsChangeEvent)
361 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsSubmitEvent)
362 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsClickEvent)
363 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsMouseOverEvent)
364 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, jsMouseOutEvent)
365 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, linkClickedEvent)
366 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadFinishedEvent)
367 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadProgressEvent)
368 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, loadStartedEvent)
369 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadCompletedEvent)
370 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadRequestEvent)
371 KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_webView, downloadProgressEvent)
372 
373 KVSO_END_REGISTERCLASS(KvsObject_webView)
374 
375 KVSO_BEGIN_CONSTRUCTOR(KvsObject_webView, KviKvsObject)
376 
377 KVSO_END_CONSTRUCTOR(KvsObject_webView)
378 
379 KVSO_BEGIN_DESTRUCTOR(KvsObject_webView)
380 
381 m_elementMapper.clear();
KVSO_END_CONSTRUCTOR(KvsObject_webView)382 KVSO_END_CONSTRUCTOR(KvsObject_webView)
383 
384 bool KvsObject_webView::init(KviKvsRunTimeContext * c, KviKvsVariantList *)
385 {
386 	//SET_OBJECT(KviKvsWebview);
387 	setObject(new KviKvsWebView(parentScriptWidget(), getName().toUtf8().data(), this), true);
388 	elementMapId = 1;
389 	m_pContext = c;
390 	m_pNetworkManager = new QNetworkAccessManager(this);
391 	QWebPage * pPage = ((QWebView *)widget())->page();
392 	connect(((QWebView *)widget()), SIGNAL(loadStarted()), this, SLOT(slotLoadStarted()));
393 	connect(((QWebView *)widget()), SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool)));
394 	connect(((QWebView *)widget()), SIGNAL(loadProgress(int)), this, SLOT(slotLoadProgress(int)));
395 	connect(pPage, SIGNAL(linkClicked(const QUrl &)), this, SLOT(slotLinkClicked(const QUrl &)));
396 	connect(pPage, SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(slotDownloadRequest(const QNetworkRequest &)));
397 	return true;
398 }
insertElement(const QWebElement & ele)399 int KvsObject_webView::insertElement(const QWebElement & ele)
400 {
401 	int eleid = getElementId(ele);
402 	if(!eleid)
403 	{
404 		m_elementMapper[elementMapId] = ele;
405 		return elementMapId++;
406 	}
407 	else
408 		return eleid;
409 }
getElementId(const QWebElement & ele)410 int KvsObject_webView::getElementId(const QWebElement & ele)
411 {
412 	QHashIterator<int, QWebElement> it(m_elementMapper);
413 	while(it.hasNext())
414 	{
415 		it.next();
416 		if(it.value() == ele)
417 			return it.key();
418 	}
419 	return 0;
420 }
421 
getElement(int iIdx)422 QWebElement KvsObject_webView::getElement(int iIdx)
423 {
424 	return m_elementMapper.value(iIdx);
425 }
getFrames(QWebFrame * pCurFrame,QStringList & szFramesNames)426 void KvsObject_webView::getFrames(QWebFrame * pCurFrame, QStringList & szFramesNames)
427 {
428 	szFramesNames.append(pCurFrame->title());
429 	QList<QWebFrame *> lFrames = pCurFrame->childFrames();
430 	for(int i = 0; i < lFrames.count(); i++)
431 	{
432 		QWebFrame * pChildFrame = lFrames.at(i);
433 		if(pChildFrame->childFrames().count())
434 			getFrames(pChildFrame, szFramesNames);
435 	}
436 }
findFrame(QWebFrame * pCurFrame,QString & szFrameName)437 QWebFrame * KvsObject_webView::findFrame(QWebFrame * pCurFrame, QString & szFrameName)
438 {
439 	if(pCurFrame->title() == szFrameName)
440 		return pCurFrame;
441 	QList<QWebFrame *> lFrames = pCurFrame->childFrames();
442 	for(int i = 0; i < lFrames.count(); i++)
443 	{
444 		QWebFrame * pChildFrame = lFrames.at(i);
445 		if(pChildFrame->childFrames().count())
446 		{
447 			pCurFrame = findFrame(pChildFrame, szFrameName);
448 			if(pCurFrame)
449 				return pCurFrame;
450 		}
451 	}
452 	return nullptr;
453 }
454 
KVSO_CLASS_FUNCTION(webView,setLinkDelegationPolicy)455 KVSO_CLASS_FUNCTION(webView, setLinkDelegationPolicy)
456 {
457 	CHECK_INTERNAL_POINTER(widget())
458 	QString szPolicy;
459 	KVSO_PARAMETERS_BEGIN(c)
460 	KVSO_PARAMETER("policy", KVS_PT_STRING, 0, szPolicy)
461 	KVSO_PARAMETERS_END(c)
462 	QWebPage::LinkDelegationPolicy policy = QWebPage::DontDelegateLinks;
463 	if(KviQString::equalCI(szPolicy, "DontDelegateLinks"))
464 		policy = QWebPage::DontDelegateLinks;
465 	else if(KviQString::equalCI(szPolicy, "DelegateExternalLinks"))
466 		policy = QWebPage::DelegateExternalLinks;
467 	else if(KviQString::equalCI(szPolicy, "DelegateAllLinks"))
468 		policy = QWebPage::DelegateAllLinks;
469 	else
470 		c->warning(__tr2qs_ctx("Unknown delegation policy '%Q'- Switch do default dontDelegateLinks", "objects"), &szPolicy);
471 	((QWebView *)widget())->page()->setLinkDelegationPolicy(policy);
472 	return true;
473 }
474 
KVSO_CLASS_FUNCTION(webView,load)475 KVSO_CLASS_FUNCTION(webView, load)
476 {
477 	CHECK_INTERNAL_POINTER(widget())
478 	QString szUrl;
479 	KVSO_PARAMETERS_BEGIN(c)
480 	KVSO_PARAMETER("url", KVS_PT_STRING, 0, szUrl)
481 	KVSO_PARAMETERS_END(c)
482 	((QWebView *)widget())->load(QUrl(szUrl));
483 	return true;
484 }
KVSO_CLASS_FUNCTION(webView,setHtml)485 KVSO_CLASS_FUNCTION(webView, setHtml)
486 {
487 	CHECK_INTERNAL_POINTER(widget())
488 	QString szHtml, szUrlBase;
489 	KVSO_PARAMETERS_BEGIN(c)
490 	KVSO_PARAMETER("szHtml", KVS_PT_STRING, 0, szHtml)
491 	KVSO_PARAMETER("urlbase", KVS_PT_STRING, KVS_PF_OPTIONAL, szUrlBase)
492 	KVSO_PARAMETERS_END(c)
493 	((QWebView *)widget())->setHtml(szHtml, QUrl(szUrlBase));
494 	return true;
495 }
KVSO_CLASS_FUNCTION(webView,makePreview)496 KVSO_CLASS_FUNCTION(webView, makePreview)
497 {
498 	CHECK_INTERNAL_POINTER(widget())
499 	QSize size = ((QWebView *)widget())->page()->mainFrame()->contentsSize();
500 	QImage * pImage = new QImage(212, 142, QImage::Format_RGB32);
501 	QWebFrame * pFrame = ((QWebView *)widget())->page()->mainFrame();
502 	QPainter painter(pImage);
503 	painter.setRenderHint(QPainter::Antialiasing, true);
504 	painter.setRenderHint(QPainter::TextAntialiasing, true);
505 	painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
506 	double dWScale = size.width() > 0 ? (212.0 / (double)(size.width())) : 0;
507 	double dHScale = dWScale;
508 	if((size.height() * dWScale) < 142)
509 	{
510 		// solution 1 is to fill the missing bacgkround
511 		painter.fillRect(0, 0, 212, 142, QColor(255, 255, 255));
512 		// solution 2 is to stretch the contents, but this doesn't work well because
513 		// the frame reports a size that doesn't exactly match the document
514 		//dHScale = 142.0 / (double)(size.height());
515 	}
516 	painter.scale(dWScale, dHScale);
517 	pFrame->documentElement().render(&painter);
518 	painter.end();
519 	KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass("pixmap");
520 	KviKvsVariantList params;
521 	KviKvsObject * pObject = pClass->allocateInstance(nullptr, "internalpixmap", c->context(), &params);
522 	((KvsObject_pixmap *)pObject)->setInternalImage(pImage);
523 	c->returnValue()->setHObject(pObject->handle());
524 	return true;
525 }
526 
KVSO_CLASS_FUNCTION(webView,findAll)527 KVSO_CLASS_FUNCTION(webView, findAll)
528 {
529 	CHECK_INTERNAL_POINTER(widget())
530 	QString szQuery;
531 	KviKvsArray * pArray;
532 	kvs_int_t iEleId;
533 	KVSO_PARAMETERS_BEGIN(c)
534 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
535 	KVSO_PARAMETER("query", KVS_PT_STRING, 0, szQuery)
536 	KVSO_PARAMETERS_END(c)
537 	QWebElement element = getElement(iEleId);
538 	if(element.isNull())
539 	{
540 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
541 		return true;
542 	}
543 	QWebElementCollection elementCollection = element.findAll(szQuery);
544 	if(!elementCollection.count())
545 		return true;
546 	//qDebug("collection %i",elementCollection.count());
547 	int idx = 0;
548 	pArray = new KviKvsArray();
549 	for(int i = 0; i < elementCollection.count(); i++)
550 	{
551 		QWebElement element = elementCollection.at(i);
552 		int id = insertElement(element);
553 		pArray->set(idx, new KviKvsVariant((kvs_int_t)id));
554 		idx++;
555 	}
556 	c->returnValue()->setArray(pArray);
557 	return true;
558 }
559 
KVSO_CLASS_FUNCTION(webView,evaluateJavaScript)560 KVSO_CLASS_FUNCTION(webView, evaluateJavaScript)
561 {
562 	CHECK_INTERNAL_POINTER(widget())
563 	QString szScript;
564 	kvs_int_t iEleId;
565 	KVSO_PARAMETERS_BEGIN(c)
566 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
567 	KVSO_PARAMETER("script_code", KVS_PT_STRING, 0, szScript)
568 	KVSO_PARAMETERS_END(c)
569 	QWebElement element = getElement(iEleId);
570 	if(element.isNull())
571 	{
572 		c->warning(__tr2qs_ctx("Document element is null: you must call getDocumentElement first", "objects"));
573 		return true;
574 	}
575 	QVariant vRes = element.evaluateJavaScript(szScript);
576 	if(vRes.type() == QVariant::String)
577 	{
578 		QString szVal = vRes.toString();
579 		c->returnValue()->setString(szVal);
580 	}
581 	else
582 		c->warning(__tr2qs_ctx("Unsupported datatype", "objects"));
583 	return true;
584 }
585 
KVSO_CLASS_FUNCTION(webView,findFirst)586 KVSO_CLASS_FUNCTION(webView, findFirst)
587 {
588 	QString szQuery;
589 	kvs_int_t iEleId;
590 	KVSO_PARAMETERS_BEGIN(c)
591 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
592 	KVSO_PARAMETER("query", KVS_PT_STRING, 0, szQuery)
593 	KVSO_PARAMETERS_END(c)
594 	QWebElement element = getElement(iEleId);
595 	if(element.isNull())
596 	{
597 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
598 		return true;
599 	}
600 	QWebElement tempElement = element.findFirst(szQuery);
601 	if(tempElement.isNull())
602 	{
603 		c->returnValue()->setInteger(-1);
604 		return true;
605 	}
606 	int id = insertElement(tempElement);
607 	c->returnValue()->setInteger((kvs_int_t)id);
608 	return true;
609 }
610 
KVSO_CLASS_FUNCTION(webView,removeFromDocument)611 KVSO_CLASS_FUNCTION(webView, removeFromDocument)
612 {
613 	kvs_int_t iEleId;
614 	KVSO_PARAMETERS_BEGIN(c)
615 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
616 	KVSO_PARAMETERS_END(c)
617 	QWebElement element = getElement(iEleId);
618 	if(element.isNull())
619 	{
620 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
621 		return true;
622 	}
623 	element.removeFromDocument();
624 	return true;
625 }
626 
KVSO_CLASS_FUNCTION(webView,appendInside)627 KVSO_CLASS_FUNCTION(webView, appendInside)
628 {
629 	kvs_int_t iEleId;
630 	QString szCode;
631 	KVSO_PARAMETERS_BEGIN(c)
632 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
633 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szCode)
634 	KVSO_PARAMETERS_END(c)
635 	QWebElement element = getElement(iEleId);
636 	if(element.isNull())
637 	{
638 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
639 		return true;
640 	}
641 	element.appendInside(szCode);
642 	return true;
643 }
644 
KVSO_CLASS_FUNCTION(webView,appendOutside)645 KVSO_CLASS_FUNCTION(webView, appendOutside)
646 {
647 	kvs_int_t iEleId;
648 	QString szCode;
649 	KVSO_PARAMETERS_BEGIN(c)
650 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
651 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szCode)
652 	KVSO_PARAMETERS_END(c)
653 	QWebElement element = getElement(iEleId);
654 	if(element.isNull())
655 	{
656 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
657 		return true;
658 	}
659 	element.appendOutside(szCode);
660 	return true;
661 }
KVSO_CLASS_FUNCTION(webView,nextSibling)662 KVSO_CLASS_FUNCTION(webView, nextSibling)
663 {
664 	CHECK_INTERNAL_POINTER(widget())
665 	kvs_int_t iEleId;
666 	KVSO_PARAMETERS_BEGIN(c)
667 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
668 	KVSO_PARAMETERS_END(c)
669 	QWebElement element = getElement(iEleId);
670 	if(element.isNull())
671 	{
672 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
673 		return true;
674 	}
675 	QWebElement tempElement = element.nextSibling();
676 	if(tempElement.isNull())
677 	{
678 		c->returnValue()->setInteger(-1);
679 		return true;
680 	}
681 	int id = insertElement(tempElement);
682 	c->returnValue()->setInteger((kvs_int_t)id);
683 	return true;
684 }
685 
KVSO_CLASS_FUNCTION(webView,frames)686 KVSO_CLASS_FUNCTION(webView, frames)
687 {
688 	CHECK_INTERNAL_POINTER(widget())
689 	QWebFrame * pFrame = ((QWebView *)widget())->page()->mainFrame();
690 	QStringList szFramesNames;
691 	getFrames(pFrame, szFramesNames);
692 	KviKvsArray * pArray = new KviKvsArray();
693 	c->returnValue()->setArray(pArray);
694 	return true;
695 }
696 
KVSO_CLASS_FUNCTION(webView,elementTagName)697 KVSO_CLASS_FUNCTION(webView, elementTagName)
698 {
699 	CHECK_INTERNAL_POINTER(widget())
700 	kvs_int_t iEleId;
701 	KVSO_PARAMETERS_BEGIN(c)
702 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
703 	KVSO_PARAMETERS_END(c)
704 	QWebElement element = getElement(iEleId);
705 	if(element.isNull())
706 	{
707 		//	qDebug("isnull ad index %i",iEleId);
708 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
709 		return true;
710 	}
711 	c->returnValue()->setString(element.tagName());
712 	return true;
713 }
714 
KVSO_CLASS_FUNCTION(webView,setElementAttribute)715 KVSO_CLASS_FUNCTION(webView, setElementAttribute)
716 {
717 	CHECK_INTERNAL_POINTER(widget())
718 	QString szName, szValue;
719 	kvs_int_t iEleId;
720 	KVSO_PARAMETERS_BEGIN(c)
721 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
722 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName)
723 	KVSO_PARAMETER("value", KVS_PT_STRING, 0, szValue)
724 	KVSO_PARAMETERS_END(c)
725 	QWebElement element = getElement(iEleId);
726 	if(element.isNull())
727 	{
728 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
729 		return true;
730 	}
731 	element.setAttribute(szName, szValue);
732 	return true;
733 }
734 
KVSO_CLASS_FUNCTION(webView,removeClass)735 KVSO_CLASS_FUNCTION(webView, removeClass)
736 {
737 	CHECK_INTERNAL_POINTER(widget())
738 	QString szClassName;
739 	kvs_int_t iEleId;
740 	KVSO_PARAMETERS_BEGIN(c)
741 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
742 	KVSO_PARAMETER("class_name", KVS_PT_NONEMPTYSTRING, 0, szClassName)
743 	KVSO_PARAMETERS_END(c)
744 	QWebElement element = getElement(iEleId);
745 	if(element.isNull())
746 	{
747 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
748 		return true;
749 	}
750 	element.removeClass(szClassName);
751 	return true;
752 }
KVSO_CLASS_FUNCTION(webView,addClass)753 KVSO_CLASS_FUNCTION(webView, addClass)
754 {
755 	CHECK_INTERNAL_POINTER(widget())
756 	QString szClassName;
757 	kvs_int_t iEleId;
758 	KVSO_PARAMETERS_BEGIN(c)
759 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
760 	KVSO_PARAMETER("class_name", KVS_PT_NONEMPTYSTRING, 0, szClassName)
761 	KVSO_PARAMETERS_END(c)
762 	QWebElement element = getElement(iEleId);
763 	if(element.isNull())
764 	{
765 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
766 		return true;
767 	}
768 	element.addClass(szClassName);
769 	return true;
770 }
KVSO_CLASS_FUNCTION(webView,setWebSetting)771 KVSO_CLASS_FUNCTION(webView, setWebSetting)
772 {
773 	CHECK_INTERNAL_POINTER(widget())
774 	QString szName;
775 	bool bEnabled;
776 	KVSO_PARAMETERS_BEGIN(c)
777 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName)
778 	KVSO_PARAMETER("value", KVS_PT_BOOLEAN, 0, bEnabled)
779 	KVSO_PARAMETERS_END(c)
780 	bool found = false;
781 	unsigned int j = 0;
782 	for(; j < webattributes_num; j++)
783 	{
784 		if(KviQString::equalCI(szName, webattributes_tbl[j]))
785 		{
786 			found = true;
787 			break;
788 		}
789 	}
790 	if(found)
791 		((QWebView *)widget())->settings()->setAttribute(webattributes_cod[j], bEnabled);
792 	else
793 		c->warning(__tr2qs_ctx("Unknown web setting '%Q'", "objects"), &szName);
794 	return true;
795 }
KVSO_CLASS_FUNCTION(webView,findText)796 KVSO_CLASS_FUNCTION(webView, findText)
797 {
798 	CHECK_INTERNAL_POINTER(widget())
799 	QString szName;
800 	QStringList szFindFlag;
801 	KVSO_PARAMETERS_BEGIN(c)
802 	KVSO_PARAMETER("find_text", KVS_PT_NONEMPTYSTRING, 0, szName)
803 	KVSO_PARAMETER("find_flag", KVS_PT_STRINGLIST, KVS_PF_OPTIONAL, szFindFlag)
804 	KVSO_PARAMETERS_END(c)
805 	int findflag = 0;
806 	int sum = 0;
807 	for(auto & it : szFindFlag)
808 	{
809 		findflag = 0;
810 		for(unsigned int j = 0; j < findflag_num; j++)
811 		{
812 			if(KviQString::equalCI(it, findflag_tbl[j]))
813 			{
814 				findflag = findflag_cod[j];
815 				break;
816 			}
817 		}
818 		if(findflag)
819 			sum = sum | findflag;
820 		else
821 			c->warning(__tr2qs_ctx("Unknown findflag  '%Q'", "objects"), &it);
822 	}
823 	((QWebView *)widget())->findText(szName, (QWebPage::FindFlags)findflag);
824 	return true;
825 }
KVSO_CLASS_FUNCTION(webView,elementAttribute)826 KVSO_CLASS_FUNCTION(webView, elementAttribute)
827 {
828 	CHECK_INTERNAL_POINTER(widget())
829 	QString szName;
830 	kvs_int_t iEleId;
831 	KVSO_PARAMETERS_BEGIN(c)
832 	KVSO_PARAMETER("element_identifier", KVS_PT_INTEGER, 0, iEleId)
833 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName)
834 	KVSO_PARAMETERS_END(c)
835 	QWebElement element = getElement(iEleId);
836 	if(element.isNull())
837 	{
838 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
839 		return true;
840 	}
841 
842 	// workaround for this issue: https://bugreports.qt.nokia.com//browse/QTWEBKIT-88
843 	if(KviQString::equalCI(element.tagName(), "input"))
844 	{
845 		QVariant value = element.evaluateJavaScript("this." + szName);
846 		c->returnValue()->setString(value.toString());
847 		return true;
848 	}
849 	c->returnValue()->setString(element.attribute(szName));
850 	return true;
851 }
852 
KVSO_CLASS_FUNCTION(webView,elementAttributeNames)853 KVSO_CLASS_FUNCTION(webView, elementAttributeNames)
854 {
855 	CHECK_INTERNAL_POINTER(widget())
856 	kvs_int_t iEleId;
857 	KVSO_PARAMETERS_BEGIN(c)
858 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
859 	KVSO_PARAMETERS_END(c)
860 	QString szAttributeNames;
861 	QWebElement element = getElement(iEleId);
862 	if(element.isNull())
863 	{
864 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
865 		return true;
866 	}
867 	szAttributeNames = element.attributeNames().join(",");
868 	c->returnValue()->setString(szAttributeNames);
869 	return true;
870 }
KVSO_CLASS_FUNCTION(webView,classes)871 KVSO_CLASS_FUNCTION(webView, classes)
872 {
873 	CHECK_INTERNAL_POINTER(widget())
874 	kvs_int_t iEleId;
875 	KVSO_PARAMETERS_BEGIN(c)
876 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
877 	KVSO_PARAMETERS_END(c)
878 	QWebElement element = getElement(iEleId);
879 	if(element.isNull())
880 	{
881 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
882 		return true;
883 	}
884 	QString szClasses;
885 	szClasses = element.classes().join(",");
886 	c->returnValue()->setString(szClasses);
887 	return true;
888 }
889 
KVSO_CLASS_FUNCTION(webView,toPlainText)890 KVSO_CLASS_FUNCTION(webView, toPlainText)
891 {
892 	CHECK_INTERNAL_POINTER(widget())
893 	kvs_int_t iEleId;
894 	KVSO_PARAMETERS_BEGIN(c)
895 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
896 	KVSO_PARAMETERS_END(c)
897 	QWebElement element = getElement(iEleId);
898 	if(element.isNull())
899 	{
900 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
901 		return true;
902 	}
903 	c->returnValue()->setString(element.toPlainText());
904 	return true;
905 }
KVSO_CLASS_FUNCTION(webView,setPlainText)906 KVSO_CLASS_FUNCTION(webView, setPlainText)
907 {
908 	CHECK_INTERNAL_POINTER(widget())
909 	QString szText;
910 	kvs_int_t iEleId;
911 	KVSO_PARAMETERS_BEGIN(c)
912 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
913 	KVSO_PARAMETER("plaintext", KVS_PT_STRING, 0, szText)
914 	KVSO_PARAMETERS_END(c)
915 	QWebElement element = getElement(iEleId);
916 	if(element.isNull())
917 	{
918 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
919 		return true;
920 	}
921 	element.setPlainText(szText);
922 	return true;
923 }
924 
KVSO_CLASS_FUNCTION(webView,firstChild)925 KVSO_CLASS_FUNCTION(webView, firstChild)
926 {
927 	CHECK_INTERNAL_POINTER(widget())
928 	kvs_int_t iEleId;
929 	KVSO_PARAMETERS_BEGIN(c)
930 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
931 	KVSO_PARAMETERS_END(c)
932 	QWebElement element = getElement(iEleId);
933 	if(element.isNull())
934 	{
935 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
936 		return true;
937 	}
938 
939 	QWebElement tempElement = element.firstChild();
940 	if(tempElement.isNull())
941 	{
942 		c->returnValue()->setInteger(-1);
943 		return true;
944 	}
945 	int id = insertElement(tempElement);
946 	c->returnValue()->setInteger((kvs_int_t)id);
947 	return true;
948 }
KVSO_CLASS_FUNCTION(webView,lastChild)949 KVSO_CLASS_FUNCTION(webView, lastChild)
950 {
951 	CHECK_INTERNAL_POINTER(widget())
952 	kvs_int_t iEleId;
953 	KVSO_PARAMETERS_BEGIN(c)
954 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
955 	KVSO_PARAMETERS_END(c)
956 	QWebElement element = getElement(iEleId);
957 	if(element.isNull())
958 	{
959 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
960 		return true;
961 	}
962 
963 	QWebElement tempElement = element.lastChild();
964 	if(tempElement.isNull())
965 	{
966 		c->returnValue()->setInteger(-1);
967 		return true;
968 	}
969 	int id = insertElement(tempElement);
970 	c->returnValue()->setInteger((kvs_int_t)id);
971 	return true;
972 }
KVSO_CLASS_FUNCTION(webView,parentElement)973 KVSO_CLASS_FUNCTION(webView, parentElement)
974 {
975 	CHECK_INTERNAL_POINTER(widget())
976 	kvs_int_t iEleId;
977 	KVSO_PARAMETERS_BEGIN(c)
978 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
979 	KVSO_PARAMETERS_END(c)
980 	QWebElement element = getElement(iEleId);
981 	if(element.isNull())
982 	{
983 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
984 		return true;
985 	}
986 
987 	QWebElement tempElement = element.parent();
988 	if(tempElement.isNull())
989 	{
990 		c->returnValue()->setInteger(-1);
991 		return true;
992 	}
993 	int id = insertElement(tempElement);
994 	c->returnValue()->setInteger((kvs_int_t)id);
995 	return true;
996 }
997 
KVSO_CLASS_FUNCTION(webView,styleProperty)998 KVSO_CLASS_FUNCTION(webView, styleProperty)
999 {
1000 	CHECK_INTERNAL_POINTER(widget())
1001 	QString szName, szStyleResolveStrategy;
1002 	kvs_int_t iEleId;
1003 	KVSO_PARAMETERS_BEGIN(c)
1004 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
1005 	KVSO_PARAMETER("name", KVS_PT_NONEMPTYSTRING, 0, szName)
1006 	KVSO_PARAMETER("style_resolve_strategy", KVS_PT_STRING, KVS_PF_OPTIONAL, szStyleResolveStrategy)
1007 	KVSO_PARAMETERS_END(c)
1008 	QWebElement element = getElement(iEleId);
1009 	if(element.isNull())
1010 	{
1011 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
1012 		return true;
1013 	}
1014 	QWebElement::StyleResolveStrategy styleStrategy = QWebElement::CascadedStyle;
1015 	if(!szStyleResolveStrategy.isEmpty())
1016 	{
1017 		if(KviQString::equalCI(szStyleResolveStrategy, "InlineStyle"))
1018 			styleStrategy = QWebElement::InlineStyle;
1019 		else if(KviQString::equalCI(szStyleResolveStrategy, "CascadedStyle"))
1020 			styleStrategy = QWebElement::CascadedStyle;
1021 		else if(KviQString::equalCI(szStyleResolveStrategy, "ComputedStyle"))
1022 			styleStrategy = QWebElement::ComputedStyle;
1023 		else
1024 		{
1025 			c->warning(__tr2qs_ctx("Unknown styleResolveStrategy: '%Q' - Switching to default CascadedStyle strategy", "objects"), &szStyleResolveStrategy);
1026 		}
1027 	}
1028 	c->returnValue()->setString(element.styleProperty(szName, styleStrategy));
1029 	return true;
1030 }
KVSO_CLASS_FUNCTION(webView,setStyleProperty)1031 KVSO_CLASS_FUNCTION(webView, setStyleProperty)
1032 {
1033 	CHECK_INTERNAL_POINTER(widget())
1034 	QString szProperty, szValue;
1035 	kvs_int_t iEleId;
1036 	KVSO_PARAMETERS_BEGIN(c)
1037 	KVSO_PARAMETER("identifier", KVS_PT_INTEGER, 0, iEleId)
1038 	KVSO_PARAMETER("property", KVS_PT_STRING, 0, szProperty)
1039 	KVSO_PARAMETER("value", KVS_PT_STRING, 0, szValue)
1040 	KVSO_PARAMETERS_END(c)
1041 	QWebElement element = getElement(iEleId);
1042 	if(element.isNull())
1043 	{
1044 		c->warning(__tr2qs_ctx("Document element with ID %d doesn't exist", "objects"), iEleId);
1045 		return true;
1046 	}
1047 	element.setStyleProperty(szProperty, szValue);
1048 	return true;
1049 }
1050 
KVSO_CLASS_FUNCTION(webView,getDocumentElement)1051 KVSO_CLASS_FUNCTION(webView, getDocumentElement)
1052 {
1053 	CHECK_INTERNAL_POINTER(widget())
1054 	QString szFrameName;
1055 	KVSO_PARAMETERS_BEGIN(c)
1056 	KVSO_PARAMETER("frame_name", KVS_PT_STRING, KVS_PF_OPTIONAL, szFrameName)
1057 	KVSO_PARAMETERS_END(c)
1058 	QWebFrame * pFrame;
1059 	pFrame = ((QWebView *)widget())->page()->mainFrame();
1060 	if(!szFrameName.isEmpty())
1061 	{
1062 		pFrame = findFrame(pFrame, szFrameName);
1063 		if(!pFrame)
1064 		{
1065 			c->warning(__tr2qs_ctx("Unknown frame '%Q'", "objects"), &szFrameName);
1066 			return true;
1067 		}
1068 	}
1069 	int id = insertElement(pFrame->documentElement());
1070 	c->returnValue()->setInteger((kvs_int_t)id);
1071 	return true;
1072 }
KVSO_CLASS_FUNCTION(webView,addToJavaScriptWindowObject)1073 KVSO_CLASS_FUNCTION(webView, addToJavaScriptWindowObject)
1074 {
1075 	CHECK_INTERNAL_POINTER(widget())
1076 	QString szFrameName, szObjectName;
1077 	KVSO_PARAMETERS_BEGIN(c)
1078 	KVSO_PARAMETER("object_name", KVS_PT_NONEMPTYSTRING, 0, szObjectName)
1079 	KVSO_PARAMETER("frame_name", KVS_PT_STRING, KVS_PF_OPTIONAL, szFrameName)
1080 	KVSO_PARAMETERS_END(c)
1081 	QWebFrame * pFrame;
1082 	pFrame = ((QWebView *)widget())->page()->mainFrame();
1083 	if(!szFrameName.isEmpty())
1084 	{
1085 		pFrame = findFrame(pFrame, szFrameName);
1086 		if(!pFrame)
1087 		{
1088 			c->warning(__tr2qs_ctx("Unknown frame '%Q'", "objects"), &szFrameName);
1089 			return true;
1090 		}
1091 	}
1092 	pFrame->addToJavaScriptWindowObject(szObjectName, this);
1093 	return true;
1094 }
KVSO_CLASS_FUNCTION(webView,setEventFilter)1095 KVSO_CLASS_FUNCTION(webView, setEventFilter)
1096 {
1097 	QWebFrame * pFrame;
1098 	pFrame = ((QWebView *)widget())->page()->mainFrame();
1099 	pFrame->addToJavaScriptWindowObject("kvs", this);
1100 	return true;
1101 }
1102 
KVSO_CLASS_FUNCTION(webView,hitTestContent)1103 KVSO_CLASS_FUNCTION(webView, hitTestContent)
1104 {
1105 	CHECK_INTERNAL_POINTER(widget())
1106 	kvs_int_t iYPos, iXPos;
1107 	KVSO_PARAMETERS_BEGIN(c)
1108 	KVSO_PARAMETER("x_pos", KVS_PT_INT, 0, iXPos)
1109 	KVSO_PARAMETER("y_pos", KVS_PT_INT, 0, iYPos)
1110 	KVSO_PARAMETERS_END(c)
1111 	QWebFrame * pFrame;
1112 	pFrame = ((QWebView *)widget())->page()->mainFrame();
1113 	QWebHitTestResult res = pFrame->hitTestContent(QPoint(iXPos, iYPos));
1114 	if(res.isNull())
1115 		return true;
1116 	KviKvsHash * pHash = new KviKvsHash();
1117 	pHash->set("imageurl", new KviKvsVariant(res.imageUrl().toString()));
1118 	pHash->set("linktitle", new KviKvsVariant(res.linkTitle().toString()));
1119 	pHash->set("linktext", new KviKvsVariant(res.linkText()));
1120 	pHash->set("linkelement", new KviKvsVariant((kvs_int_t)insertElement(res.linkElement())));
1121 	pHash->set("enclosingelement", new KviKvsVariant((kvs_int_t)insertElement(res.enclosingBlockElement())));
1122 	pHash->set("element", new KviKvsVariant((kvs_int_t)insertElement(res.element())));
1123 	c->returnValue()->setHash(pHash);
1124 	return true;
1125 }
1126 
KVSO_CLASS_FUNCTION(webView,appendWebViewActionToMenu)1127 KVSO_CLASS_FUNCTION(webView, appendWebViewActionToMenu)
1128 {
1129 	CHECK_INTERNAL_POINTER(widget())
1130 	KviKvsObject * ob;
1131 	kvs_hobject_t hObject;
1132 	QString szActionName, szIcon;
1133 	KVSO_PARAMETERS_BEGIN(c)
1134 	KVSO_PARAMETER("popup", KVS_PT_HOBJECT, 0, hObject)
1135 	KVSO_PARAMETER("action_name", KVS_PT_NONEMPTYSTRING, 0, szActionName)
1136 	KVSO_PARAMETER("icon", KVS_PT_STRING, KVS_PF_OPTIONAL, szIcon)
1137 	KVSO_PARAMETERS_END(c)
1138 	ob = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
1139 	if(!ob)
1140 	{
1141 		c->warning(__tr2qs_ctx("Widget parameter is not an object", "objects"));
1142 		return true;
1143 	}
1144 	if(!ob->object())
1145 	{
1146 		c->warning(__tr2qs_ctx("Widget parameter is not a valid object", "objects"));
1147 		return true;
1148 	}
1149 	if(!ob->inheritsClass("popupmenu"))
1150 	{
1151 		c->warning(__tr2qs_ctx("Can't add a non-popupmenu object", "objects"));
1152 		return true;
1153 	}
1154 	QAction * pAction = nullptr;
1155 	for(unsigned int i = 0; i < actions_num; i++)
1156 	{
1157 		if(KviQString::equalCI(szActionName, actions_tbl[i]))
1158 		{
1159 			pAction = ((QWebView *)widget())->pageAction(actions_cod[i]);
1160 			break;
1161 		}
1162 	}
1163 	if(!pAction)
1164 	{
1165 		c->warning(__tr2qs_ctx("Unknown action '%Q':", "objects"), &szActionName);
1166 		return true;
1167 	}
1168 	if(!szIcon.isEmpty())
1169 	{
1170 		QPixmap * pix;
1171 		pix = g_pIconManager->getImage(szIcon);
1172 		if(pix)
1173 			pAction->setIcon(*pix);
1174 		else
1175 			c->warning(__tr2qs_ctx("Icon '%Q' doesn't exist", "objects"), &szIcon);
1176 	}
1177 	((QMenu *)(ob->object()))->addAction(pAction);
1178 	return true;
1179 }
1180 
KVSO_CLASS_FUNCTION(webView,loadFinishedEvent)1181 KVSO_CLASS_FUNCTION(webView, loadFinishedEvent)
1182 {
1183 	emitSignal("loadFinished", c, c->params());
1184 	return true;
1185 }
1186 
KVSO_CLASS_FUNCTION(webView,loadProgressEvent)1187 KVSO_CLASS_FUNCTION(webView, loadProgressEvent)
1188 {
1189 	emitSignal("loadProgress", c, c->params());
1190 	return true;
1191 }
1192 
KVSO_CLASS_FUNCTION(webView,loadStartedEvent)1193 KVSO_CLASS_FUNCTION(webView, loadStartedEvent)
1194 {
1195 	emitSignal("loadStarted", c);
1196 	return true;
1197 }
1198 
KVSO_CLASS_FUNCTION(webView,downloadCompletedEvent)1199 KVSO_CLASS_FUNCTION(webView, downloadCompletedEvent)
1200 {
1201 	emitSignal("downloadCompleted", c, c->params());
1202 	return true;
1203 }
1204 
KVSO_CLASS_FUNCTION(webView,downloadProgressEvent)1205 KVSO_CLASS_FUNCTION(webView, downloadProgressEvent)
1206 {
1207 	emitSignal("downloadProgress", c, c->params());
1208 	return true;
1209 }
1210 
KVSO_CLASS_FUNCTION(webView,linkClickedEvent)1211 KVSO_CLASS_FUNCTION(webView, linkClickedEvent)
1212 {
1213 	emitSignal("linkClicked", c, c->params());
1214 	return true;
1215 }
1216 
KVSO_CLASS_FUNCTION(webView,downloadRequestEvent)1217 KVSO_CLASS_FUNCTION(webView, downloadRequestEvent)
1218 {
1219 	emitSignal("downloadRequest", c, c->params());
1220 	return true;
1221 }
1222 
KVSO_CLASS_FUNCTION(webView,jsSubmitEvent)1223 KVSO_CLASS_FUNCTION(webView, jsSubmitEvent)
1224 {
1225 	emitSignal("jssubmit", c, c->params());
1226 	return true;
1227 }
KVSO_CLASS_FUNCTION(webView,jsChangeEvent)1228 KVSO_CLASS_FUNCTION(webView, jsChangeEvent)
1229 {
1230 	emitSignal("jschange", c, c->params());
1231 	return true;
1232 }
KVSO_CLASS_FUNCTION(webView,jsClickEvent)1233 KVSO_CLASS_FUNCTION(webView, jsClickEvent)
1234 {
1235 	emitSignal("jsclick", c, c->params());
1236 	return true;
1237 }
KVSO_CLASS_FUNCTION(webView,jsMouseOverEvent)1238 KVSO_CLASS_FUNCTION(webView, jsMouseOverEvent)
1239 {
1240 	emitSignal("jsmouseover", c, c->params());
1241 	return true;
1242 }
KVSO_CLASS_FUNCTION(webView,jsMouseOutEvent)1243 KVSO_CLASS_FUNCTION(webView, jsMouseOutEvent)
1244 {
1245 	emitSignal("jsmouseout", c, c->params());
1246 	return true;
1247 }
slotOnChange(QString szParam)1248 void KvsObject_webView::slotOnChange(QString szParam)
1249 {
1250 	//qDebug("change");
1251 	KviKvsVariantList params(new KviKvsVariant(szParam));
1252 	callFunction(this, "jsChangeEvent", &params);
1253 }
1254 
slotOnSubmit(QString szParam)1255 void KvsObject_webView::slotOnSubmit(QString szParam)
1256 {
1257 	// ,QString szParam2,QString szParam3
1258 	//qDebug("slotonsubmit");
1259 	KviKvsVariantList params(new KviKvsVariant(szParam));
1260 	callFunction(this, "jsSubmitEvent", &params);
1261 }
1262 
slotOnClick(QString szParam)1263 void KvsObject_webView::slotOnClick(QString szParam)
1264 {
1265 	KviKvsVariantList params(new KviKvsVariant(szParam));
1266 	callFunction(this, "jsClickEvent", &params);
1267 }
slotOnMouseOver(QString szParam)1268 void KvsObject_webView::slotOnMouseOver(QString szParam)
1269 {
1270 	KviKvsVariantList params(new KviKvsVariant(szParam));
1271 	callFunction(this, "jsMouseOverEvent", &params);
1272 }
slotOnMouseOut(QString szParam)1273 void KvsObject_webView::slotOnMouseOut(QString szParam)
1274 {
1275 	KviKvsVariantList params(new KviKvsVariant(szParam));
1276 	callFunction(this, "jsMouseOutEvent", &params);
1277 }
1278 
1279 // slots
slotLoadFinished(bool bOk)1280 void KvsObject_webView::slotLoadFinished(bool bOk)
1281 {
1282 	if(bOk)
1283 		m_currentElement = ((QWebView *)widget())->page()->mainFrame()->documentElement();
1284 	KviKvsVariantList params(new KviKvsVariant(bOk));
1285 	callFunction(this, "loadFinishedEvent", &params);
1286 }
1287 
slotLoadStarted()1288 void KvsObject_webView::slotLoadStarted()
1289 {
1290 	KviKvsVariantList * lParams = nullptr;
1291 	callFunction(this, "loadStartedEvent", lParams);
1292 }
1293 
slotLoadProgress(int iProgress)1294 void KvsObject_webView::slotLoadProgress(int iProgress)
1295 {
1296 	KviKvsVariantList params(new KviKvsVariant((kvs_int_t)iProgress));
1297 	callFunction(this, "loadProgressEvent", &params);
1298 }
1299 
slotLinkClicked(const QUrl & url)1300 void KvsObject_webView::slotLinkClicked(const QUrl & url)
1301 {
1302 	QString szUrl = url.toString();
1303 	KviKvsVariantList params(new KviKvsVariant(szUrl));
1304 	callFunction(this, "linkClickedEvent", &params);
1305 }
1306 
slotDownloadRequest(const QNetworkRequest & r)1307 void KvsObject_webView::slotDownloadRequest(const QNetworkRequest & r)
1308 {
1309 	QNetworkReply * pReply = m_pNetworkManager->get(r);
1310 	QString szFilePath = "";
1311 	KviKvsVariant * filepathret = new KviKvsVariant(szFilePath);
1312 	KviKvsVariantList params(new KviKvsVariant(r.url().toString()));
1313 	callFunction(this, "downloadRequestEvent", filepathret, &params);
1314 	filepathret->asString(szFilePath);
1315 	if(!szFilePath.isEmpty())
1316 	{
1317 		QFile * pFile = new QFile(szFilePath);
1318 		if(!pFile->open(QIODevice::WriteOnly))
1319 		{
1320 			m_pContext->warning(__tr2qs_ctx("Invalid file path '%Q'", "objects"), &szFilePath);
1321 			pReply->abort();
1322 			pReply->deleteLater();
1323 			return;
1324 		}
1325 		(void)new KviKvsDownloadHandler(this, pFile, pReply, g_iDownloadId);
1326 		g_iDownloadId++;
1327 	}
1328 }
1329 
KviKvsWebView(QWidget * par,const char * name,KvsObject_webView * parent)1330 KviKvsWebView::KviKvsWebView(QWidget * par, const char * name, KvsObject_webView * parent)
1331     : QWebView(par)
1332 {
1333 	m_pParentScript = parent;
1334 	setObjectName(name);
1335 }
1336 
mouseMoveEvent(QMouseEvent * ev)1337 void KviKvsWebView::mouseMoveEvent(QMouseEvent * ev)
1338 {
1339 	KviKvsVariant vRetValue;
1340 	KviKvsVariantList lParams;
1341 	lParams.append(new KviKvsVariant((kvs_int_t)ev->x()));
1342 	lParams.append(new KviKvsVariant((kvs_int_t)ev->y()));
1343 	if(!m_pParentScript->callFunction(m_pParentScript, "mouseMoveEvent", &vRetValue, &lParams))
1344 		QWebView::mouseMoveEvent(ev); // ignore results of a broken event handler
1345 	else
1346 	{
1347 		if(!vRetValue.asBoolean())
1348 			QWebView::mouseMoveEvent(ev);
1349 	}
1350 }
contextMenuEvent(QContextMenuEvent * ev)1351 void KviKvsWebView::contextMenuEvent(QContextMenuEvent * ev)
1352 {
1353 	KviKvsVariant vRetValue;
1354 	KviKvsVariantList lParams;
1355 	lParams.append(new KviKvsVariant((kvs_int_t)ev->x()));
1356 	lParams.append(new KviKvsVariant((kvs_int_t)ev->y()));
1357 	if(!m_pParentScript->callFunction(m_pParentScript, "customContextMenuRequestedEvent", &vRetValue, &lParams))
1358 		QWebView::contextMenuEvent(ev); // ignore results of a broken event handler
1359 	else
1360 	{
1361 		if(!vRetValue.asBoolean())
1362 			QWebView::contextMenuEvent(ev);
1363 	}
1364 }
event(QEvent * e)1365 bool KviKvsWebView::event(QEvent * e)
1366 {
1367 
1368 	if(e->type() == QEvent::ToolTip)
1369 	{
1370 		QHelpEvent * helpEvent = static_cast<QHelpEvent *>(e);
1371 		QString szTooltip = "";
1372 		KviKvsVariant * tipret = new KviKvsVariant(szTooltip);
1373 		KviKvsVariantList params(new KviKvsVariant((kvs_int_t)helpEvent->x()), new KviKvsVariant((kvs_int_t)helpEvent->y()));
1374 		m_pParentScript->callFunction(m_pParentScript, "maybeTipEvent", tipret, &params);
1375 		tipret->asString(szTooltip);
1376 		if(!szTooltip.isEmpty())
1377 		{
1378 			QToolTip::showText(helpEvent->globalPos(), szTooltip);
1379 			return false;
1380 		}
1381 	}
1382 	return QWebView::event(e);
1383 }
1384 KviKvsWebView::~KviKvsWebView()
1385     = default;
1386 #endif // COMPILE_WEBKIT_SUPPORT
1387