1 /*
2 Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2007 Staikos Computing Services Inc.
4 Copyright (C) 2007 Apple Inc.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #include "qwebpage.h"
24
25 #include "qwebview.h"
26 #include "qwebframe.h"
27 #include "qwebpage_p.h"
28 #include "qwebframe_p.h"
29 #include "qwebhistory.h"
30 #include "qwebhistory_p.h"
31 #include "qwebinspector.h"
32 #include "qwebinspector_p.h"
33 #include "qwebsettings.h"
34 #include "qwebkitplatformplugin.h"
35 #include "qwebkitversion.h"
36
37 #include "CSSComputedStyleDeclaration.h"
38 #include "CSSParser.h"
39 #include "ApplicationCacheStorage.h"
40 #include "BackForwardListImpl.h"
41 #include "MemoryCache.h"
42 #include "Chrome.h"
43 #include "ChromeClientQt.h"
44 #include "ClientRect.h"
45 #include "ContextMenu.h"
46 #include "ContextMenuClientQt.h"
47 #include "ContextMenuController.h"
48 #include "DeviceMotionClientQt.h"
49 #include "DeviceOrientationClientQt.h"
50 #include "DocumentLoader.h"
51 #include "DragClientQt.h"
52 #include "DragController.h"
53 #include "DragData.h"
54 #include "Editor.h"
55 #include "EditorClientQt.h"
56 #include "FocusController.h"
57 #include "FormState.h"
58 #include "Frame.h"
59 #include "FrameLoadRequest.h"
60 #include "FrameLoader.h"
61 #include "FrameLoader.h"
62 #include "FrameLoaderClientQt.h"
63 #include "FrameTree.h"
64 #include "FrameView.h"
65 #if ENABLE(CLIENT_BASED_GEOLOCATION)
66 #include "GeolocationClientMock.h"
67 #include "GeolocationClientQt.h"
68 #endif // CLIENT_BASED_GEOLOCATION
69 #include "GeolocationPermissionClientQt.h"
70 #include "HTMLFormElement.h"
71 #include "HTMLFrameOwnerElement.h"
72 #include "HTMLInputElement.h"
73 #include "HTMLNames.h"
74 #include "HashMap.h"
75 #include "HitTestResult.h"
76 #include "Image.h"
77 #include "InspectorClientQt.h"
78 #include "InspectorController.h"
79 #include "InspectorServerQt.h"
80 #include "KURL.h"
81 #include "LocalizedStrings.h"
82 #include "Logging.h"
83 #include "MIMETypeRegistry.h"
84 #include "NavigationAction.h"
85 #include "NetworkingContext.h"
86 #include "NodeList.h"
87 #include "NotificationPresenterClientQt.h"
88 #include "NotImplemented.h"
89 #include "Page.h"
90 #include "PageClientQt.h"
91 #include "PageGroup.h"
92 #include "Pasteboard.h"
93 #include "PlatformKeyboardEvent.h"
94 #include "PlatformTouchEvent.h"
95 #include "PlatformWheelEvent.h"
96 #include "PluginDatabase.h"
97 #include "PluginDatabase.h"
98 #include "PluginPackage.h"
99 #include "ProgressTracker.h"
100 #include "QtPlatformPlugin.h"
101 #include "RefPtr.h"
102 #include "RenderTextControl.h"
103 #include "SchemeRegistry.h"
104 #include "Scrollbar.h"
105 #include "SecurityOrigin.h"
106 #include "Settings.h"
107 #if defined Q_OS_WIN32
108 #include "SystemInfo.h"
109 #endif // Q_OS_WIN32
110 #include "TextIterator.h"
111 #include "WebPlatformStrategies.h"
112 #if USE(QTKIT)
113 #include "WebSystemInterface.h"
114 #endif
115 #include "WindowFeatures.h"
116 #include "WorkerThread.h"
117 #include "runtime/InitializeThreading.h"
118 #include "wtf/Threading.h"
119
120 #include <QApplication>
121 #include <QBasicTimer>
122 #include <QBitArray>
123 #include <QDebug>
124 #include <QDesktopWidget>
125 #include <QDragEnterEvent>
126 #include <QDragLeaveEvent>
127 #include <QDragMoveEvent>
128 #include <QDropEvent>
129 #include <QFileDialog>
130 #include <QHttpRequestHeader>
131 #include <QInputDialog>
132 #include <QMessageBox>
133 #include <QNetworkProxy>
134 #include <QUndoStack>
135 #include <QUrl>
136 #include <QPainter>
137 #include <QClipboard>
138 #include <QSslSocket>
139 #include <QStyle>
140 #include <QSysInfo>
141 #include <QTextCharFormat>
142 #include <QTextDocument>
143 #include <QTouchEvent>
144 #include <QNetworkAccessManager>
145 #include <QNetworkRequest>
146 #if defined(Q_WS_X11)
147 #include <QX11Info>
148 #endif
149 #if USE(QT_MOBILITY_SYSTEMINFO)
150 #include <qsysteminfo.h>
151 #endif
152
153 using namespace WebCore;
154
155 // from text/qfont.cpp
156 QT_BEGIN_NAMESPACE
157 extern Q_GUI_EXPORT int qt_defaultDpi();
158 QT_END_NAMESPACE
159
160 bool QWebPagePrivate::drtRun = false;
161
162 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
163 static const char* editorCommandWebActions[] =
164 {
165 0, // OpenLink,
166
167 0, // OpenLinkInNewWindow,
168 0, // OpenFrameInNewWindow,
169
170 0, // DownloadLinkToDisk,
171 0, // CopyLinkToClipboard,
172
173 0, // OpenImageInNewWindow,
174 0, // DownloadImageToDisk,
175 0, // CopyImageToClipboard,
176
177 0, // Back,
178 0, // Forward,
179 0, // Stop,
180 0, // Reload,
181
182 "Cut", // Cut,
183 "Copy", // Copy,
184 "Paste", // Paste,
185
186 "Undo", // Undo,
187 "Redo", // Redo,
188 "MoveForward", // MoveToNextChar,
189 "MoveBackward", // MoveToPreviousChar,
190 "MoveWordForward", // MoveToNextWord,
191 "MoveWordBackward", // MoveToPreviousWord,
192 "MoveDown", // MoveToNextLine,
193 "MoveUp", // MoveToPreviousLine,
194 "MoveToBeginningOfLine", // MoveToStartOfLine,
195 "MoveToEndOfLine", // MoveToEndOfLine,
196 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
197 "MoveToEndOfParagraph", // MoveToEndOfBlock,
198 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
199 "MoveToEndOfDocument", // MoveToEndOfDocument,
200 "MoveForwardAndModifySelection", // SelectNextChar,
201 "MoveBackwardAndModifySelection", // SelectPreviousChar,
202 "MoveWordForwardAndModifySelection", // SelectNextWord,
203 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
204 "MoveDownAndModifySelection", // SelectNextLine,
205 "MoveUpAndModifySelection", // SelectPreviousLine,
206 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
207 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
208 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
209 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
210 "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
211 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
212 "DeleteWordBackward", // DeleteStartOfWord,
213 "DeleteWordForward", // DeleteEndOfWord,
214
215 0, // SetTextDirectionDefault,
216 0, // SetTextDirectionLeftToRight,
217 0, // SetTextDirectionRightToLeft,
218
219 "ToggleBold", // ToggleBold,
220 "ToggleItalic", // ToggleItalic,
221 "ToggleUnderline", // ToggleUnderline,
222
223 0, // InspectElement,
224
225 "InsertNewline", // InsertParagraphSeparator
226 "InsertLineBreak", // InsertLineSeparator
227
228 "SelectAll", // SelectAll
229 0, // ReloadAndBypassCache,
230
231 "PasteAndMatchStyle", // PasteAndMatchStyle
232 "RemoveFormat", // RemoveFormat
233 "Strikethrough", // ToggleStrikethrough,
234 "Subscript", // ToggleSubscript
235 "Superscript", // ToggleSuperscript
236 "InsertUnorderedList", // InsertUnorderedList
237 "InsertOrderedList", // InsertOrderedList
238 "Indent", // Indent
239 "Outdent", // Outdent,
240
241 "AlignCenter", // AlignCenter,
242 "AlignJustified", // AlignJustified,
243 "AlignLeft", // AlignLeft,
244 "AlignRight", // AlignRight,
245
246 0, // StopScheduledPageRefresh,
247
248 0, // CopyImageUrlToClipboard,
249
250 0 // WebActionCount
251 };
252
253 // Lookup the appropriate editor command to use for WebAction \a action
editorCommandForWebActions(QWebPage::WebAction action)254 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
255 {
256 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
257 return editorCommandWebActions[action];
258 return 0;
259 }
260
dropActionToDragOp(Qt::DropActions actions)261 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
262 {
263 unsigned result = 0;
264 if (actions & Qt::CopyAction)
265 result |= DragOperationCopy;
266 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
267 // hence it should be considered as "move"
268 if (actions & Qt::MoveAction)
269 result |= (DragOperationMove | DragOperationGeneric);
270 if (actions & Qt::LinkAction)
271 result |= DragOperationLink;
272 if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
273 result = DragOperationEvery;
274 return (DragOperation)result;
275 }
276
dragOpToDropAction(unsigned actions)277 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
278 {
279 Qt::DropAction result = Qt::IgnoreAction;
280 if (actions & DragOperationCopy)
281 result = Qt::CopyAction;
282 else if (actions & DragOperationMove)
283 result = Qt::MoveAction;
284 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
285 // hence it should be considered as "move"
286 else if (actions & DragOperationGeneric)
287 result = Qt::MoveAction;
288 else if (actions & DragOperationLink)
289 result = Qt::LinkAction;
290 return result;
291 }
292
QWebPagePrivate(QWebPage * qq)293 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
294 : q(qq)
295 , page(0)
296 , mainFrame(0)
297 #ifndef QT_NO_UNDOSTACK
298 , undoStack(0)
299 #endif
300 , insideOpenCall(false)
301 , m_totalBytes(0)
302 , m_bytesReceived()
303 , clickCausedFocus(false)
304 , networkManager(0)
305 , forwardUnsupportedContent(false)
306 , smartInsertDeleteEnabled(true)
307 , selectTrailingWhitespaceEnabled(false)
308 , linkPolicy(QWebPage::DontDelegateLinks)
309 , viewportSize(QSize(0, 0))
310 , pixelRatio(1)
311 #ifndef QT_NO_CONTEXTMENU
312 , currentContextMenu(0)
313 #endif
314 , settings(0)
315 , useFixedLayout(false)
316 , pluginFactory(0)
317 , inspectorFrontend(0)
318 , inspector(0)
319 , inspectorIsInternalOnly(false)
320 , m_lastDropAction(Qt::IgnoreAction)
321 {
322 WebCore::InitializeLoggingChannelsIfNecessary();
323 ScriptController::initializeThreading();
324 WTF::initializeMainThread();
325 WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
326
327 WebPlatformStrategies::initialize();
328
329 #if USE(QTKIT)
330 InitWebCoreSystemInterface();
331 #endif
332
333 Page::PageClients pageClients;
334 pageClients.chromeClient = new ChromeClientQt(q);
335 pageClients.contextMenuClient = new ContextMenuClientQt();
336 pageClients.editorClient = new EditorClientQt(q);
337 pageClients.dragClient = new DragClientQt(q);
338 pageClients.inspectorClient = new InspectorClientQt(q);
339 #if ENABLE(DEVICE_ORIENTATION)
340 pageClients.deviceOrientationClient = new DeviceOrientationClientQt(q);
341 pageClients.deviceMotionClient = new DeviceMotionClientQt(q);
342 #endif
343 #if ENABLE(CLIENT_BASED_GEOLOCATION)
344 if (QWebPagePrivate::drtRun)
345 pageClients.geolocationClient = new GeolocationClientMock();
346 else
347 pageClients.geolocationClient = new GeolocationClientQt(q);
348 #endif
349 page = new Page(pageClients);
350
351 // By default each page is put into their own unique page group, which affects popup windows
352 // and visited links. Page groups (per process only) is a feature making it possible to use
353 // separate settings for each group, so that for instance an integrated browser/email reader
354 // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
355 // as expected out of the box, we use a default group similar to what other ports are doing.
356 page->setGroupName("Default Group");
357
358 #if ENABLE(CLIENT_BASED_GEOLOCATION)
359 // In case running in DumpRenderTree mode set the controller to mock provider.
360 if (QWebPagePrivate::drtRun)
361 static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(page->geolocationController());
362 #endif
363 settings = new QWebSettings(page->settings());
364
365 history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
366 memset(actions, 0, sizeof(actions));
367
368 PageGroup::setShouldTrackVisitedLinks(true);
369
370 #if ENABLE(NOTIFICATIONS)
371 NotificationPresenterClientQt::notificationPresenter()->addClient();
372 #endif
373 }
374
~QWebPagePrivate()375 QWebPagePrivate::~QWebPagePrivate()
376 {
377 if (inspector && inspectorIsInternalOnly) {
378 // Since we have to delete an internal inspector,
379 // call setInspector(0) directly to prevent potential crashes
380 setInspector(0);
381 }
382 #ifndef QT_NO_CONTEXTMENU
383 delete currentContextMenu;
384 #endif
385 #ifndef QT_NO_UNDOSTACK
386 delete undoStack;
387 #endif
388 delete settings;
389 delete page;
390
391 if (inspector)
392 inspector->setPage(0);
393
394 #if ENABLE(NOTIFICATIONS)
395 NotificationPresenterClientQt::notificationPresenter()->removeClient();
396 #endif
397 }
398
viewportArguments()399 WebCore::ViewportArguments QWebPagePrivate::viewportArguments()
400 {
401 return page ? page->viewportArguments() : WebCore::ViewportArguments();
402 }
403
core(const QWebPage * page)404 WebCore::Page* QWebPagePrivate::core(const QWebPage* page)
405 {
406 return page->d->page;
407 }
408
priv(QWebPage * page)409 QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page)
410 {
411 return page->d;
412 }
413
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)414 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
415 {
416 if (insideOpenCall
417 && frame == mainFrame)
418 return true;
419 return q->acceptNavigationRequest(frame, request, type);
420 }
421
createMainFrame()422 void QWebPagePrivate::createMainFrame()
423 {
424 if (!mainFrame) {
425 QWebFrameData frameData(page);
426 mainFrame = new QWebFrame(q, &frameData);
427
428 emit q->frameCreated(mainFrame);
429 }
430 }
431
webActionForContextMenuAction(WebCore::ContextMenuAction action)432 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
433 {
434 switch (action) {
435 case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
436 case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
437 case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
438 case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
439 case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
440 case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
441 case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
442 case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard;
443 case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
444 case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
445 case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
446 case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
447 case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
448 case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
449 case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
450 case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
451 case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
452 case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
453 case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
454 case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
455 case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
456 case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
457 case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll;
458 #if ENABLE(INSPECTOR)
459 case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
460 #endif
461 default: break;
462 }
463 return QWebPage::NoWebAction;
464 }
465
466 #ifndef QT_NO_CONTEXTMENU
createContextMenu(const WebCore::ContextMenu * webcoreMenu,const QList<WebCore::ContextMenuItem> * items,QBitArray * visitedWebActions)467 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
468 const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
469 {
470 if (!client || !webcoreMenu)
471 return 0;
472
473 QMenu* menu = new QMenu(client->ownerWidget());
474 for (int i = 0; i < items->count(); ++i) {
475 const ContextMenuItem &item = items->at(i);
476 switch (item.type()) {
477 case WebCore::CheckableActionType: /* fall through */
478 case WebCore::ActionType: {
479 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
480 QAction *a = q->action(action);
481 if (a) {
482 ContextMenuItem it(item);
483 page->contextMenuController()->checkOrEnableIfNeeded(it);
484 PlatformMenuItemDescription desc = it.releasePlatformDescription();
485 a->setEnabled(desc.enabled);
486 a->setChecked(desc.checked);
487 a->setCheckable(item.type() == WebCore::CheckableActionType);
488
489 menu->addAction(a);
490 visitedWebActions->setBit(action);
491 }
492 break;
493 }
494 case WebCore::SeparatorType:
495 menu->addSeparator();
496 break;
497 case WebCore::SubmenuType: {
498 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
499
500 bool anyEnabledAction = false;
501
502 QList<QAction *> actions = subMenu->actions();
503 for (int i = 0; i < actions.count(); ++i) {
504 if (actions.at(i)->isVisible())
505 anyEnabledAction |= actions.at(i)->isEnabled();
506 }
507
508 // don't show sub-menus with just disabled actions
509 if (anyEnabledAction) {
510 subMenu->setTitle(item.title());
511 menu->addAction(subMenu->menuAction());
512 } else
513 delete subMenu;
514 break;
515 }
516 }
517 }
518 return menu;
519 }
520 #endif // QT_NO_CONTEXTMENU
521
522 #ifndef QT_NO_ACTION
_q_webActionTriggered(bool checked)523 void QWebPagePrivate::_q_webActionTriggered(bool checked)
524 {
525 QAction *a = qobject_cast<QAction *>(q->sender());
526 if (!a)
527 return;
528 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
529 q->triggerAction(action, checked);
530 }
531 #endif // QT_NO_ACTION
532
_q_cleanupLeakMessages()533 void QWebPagePrivate::_q_cleanupLeakMessages()
534 {
535 #ifndef NDEBUG
536 // Need this to make leak messages accurate.
537 memoryCache()->setCapacities(0, 0, 0);
538 #endif
539 }
540
updateAction(QWebPage::WebAction action)541 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
542 {
543 #ifdef QT_NO_ACTION
544 Q_UNUSED(action)
545 #else
546 QAction *a = actions[action];
547 if (!a || !mainFrame)
548 return;
549
550 WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
551 WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
552
553 bool enabled = a->isEnabled();
554 bool checked = a->isChecked();
555
556 switch (action) {
557 case QWebPage::Back:
558 enabled = page->canGoBackOrForward(-1);
559 break;
560 case QWebPage::Forward:
561 enabled = page->canGoBackOrForward(1);
562 break;
563 case QWebPage::Stop:
564 enabled = loader->isLoading();
565 break;
566 case QWebPage::Reload:
567 case QWebPage::ReloadAndBypassCache:
568 enabled = !loader->isLoading();
569 break;
570 #ifndef QT_NO_UNDOSTACK
571 case QWebPage::Undo:
572 case QWebPage::Redo:
573 // those two are handled by QUndoStack
574 break;
575 #endif // QT_NO_UNDOSTACK
576 case QWebPage::SelectAll: // editor command is always enabled
577 break;
578 case QWebPage::SetTextDirectionDefault:
579 case QWebPage::SetTextDirectionLeftToRight:
580 case QWebPage::SetTextDirectionRightToLeft:
581 enabled = editor->canEdit();
582 checked = false;
583 break;
584 default: {
585 // see if it's an editor command
586 const char* commandName = editorCommandForWebActions(action);
587
588 // if it's an editor command, let it's logic determine state
589 if (commandName) {
590 Editor::Command command = editor->command(commandName);
591 enabled = command.isEnabled();
592 if (enabled)
593 checked = command.state() != FalseTriState;
594 else
595 checked = false;
596 }
597 break;
598 }
599 }
600
601 a->setEnabled(enabled);
602
603 if (a->isCheckable())
604 a->setChecked(checked);
605 #endif // QT_NO_ACTION
606 }
607
updateNavigationActions()608 void QWebPagePrivate::updateNavigationActions()
609 {
610 updateAction(QWebPage::Back);
611 updateAction(QWebPage::Forward);
612 updateAction(QWebPage::Stop);
613 updateAction(QWebPage::Reload);
614 updateAction(QWebPage::ReloadAndBypassCache);
615 }
616
updateEditorActions()617 void QWebPagePrivate::updateEditorActions()
618 {
619 updateAction(QWebPage::Cut);
620 updateAction(QWebPage::Copy);
621 updateAction(QWebPage::Paste);
622 updateAction(QWebPage::MoveToNextChar);
623 updateAction(QWebPage::MoveToPreviousChar);
624 updateAction(QWebPage::MoveToNextWord);
625 updateAction(QWebPage::MoveToPreviousWord);
626 updateAction(QWebPage::MoveToNextLine);
627 updateAction(QWebPage::MoveToPreviousLine);
628 updateAction(QWebPage::MoveToStartOfLine);
629 updateAction(QWebPage::MoveToEndOfLine);
630 updateAction(QWebPage::MoveToStartOfBlock);
631 updateAction(QWebPage::MoveToEndOfBlock);
632 updateAction(QWebPage::MoveToStartOfDocument);
633 updateAction(QWebPage::MoveToEndOfDocument);
634 updateAction(QWebPage::SelectNextChar);
635 updateAction(QWebPage::SelectPreviousChar);
636 updateAction(QWebPage::SelectNextWord);
637 updateAction(QWebPage::SelectPreviousWord);
638 updateAction(QWebPage::SelectNextLine);
639 updateAction(QWebPage::SelectPreviousLine);
640 updateAction(QWebPage::SelectStartOfLine);
641 updateAction(QWebPage::SelectEndOfLine);
642 updateAction(QWebPage::SelectStartOfBlock);
643 updateAction(QWebPage::SelectEndOfBlock);
644 updateAction(QWebPage::SelectStartOfDocument);
645 updateAction(QWebPage::SelectEndOfDocument);
646 updateAction(QWebPage::DeleteStartOfWord);
647 updateAction(QWebPage::DeleteEndOfWord);
648 updateAction(QWebPage::SetTextDirectionDefault);
649 updateAction(QWebPage::SetTextDirectionLeftToRight);
650 updateAction(QWebPage::SetTextDirectionRightToLeft);
651 updateAction(QWebPage::ToggleBold);
652 updateAction(QWebPage::ToggleItalic);
653 updateAction(QWebPage::ToggleUnderline);
654 updateAction(QWebPage::InsertParagraphSeparator);
655 updateAction(QWebPage::InsertLineSeparator);
656 updateAction(QWebPage::PasteAndMatchStyle);
657 updateAction(QWebPage::RemoveFormat);
658 updateAction(QWebPage::ToggleStrikethrough);
659 updateAction(QWebPage::ToggleSubscript);
660 updateAction(QWebPage::ToggleSuperscript);
661 updateAction(QWebPage::InsertUnorderedList);
662 updateAction(QWebPage::InsertOrderedList);
663 updateAction(QWebPage::Indent);
664 updateAction(QWebPage::Outdent);
665 updateAction(QWebPage::AlignCenter);
666 updateAction(QWebPage::AlignJustified);
667 updateAction(QWebPage::AlignLeft);
668 updateAction(QWebPage::AlignRight);
669 }
670
timerEvent(QTimerEvent * ev)671 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
672 {
673 int timerId = ev->timerId();
674 if (timerId == tripleClickTimer.timerId())
675 tripleClickTimer.stop();
676 else
677 q->timerEvent(ev);
678 }
679
680 template<class T>
mouseMoveEvent(T * ev)681 void QWebPagePrivate::mouseMoveEvent(T* ev)
682 {
683 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
684 if (!frame->view())
685 return;
686
687 bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
688 ev->setAccepted(accepted);
689 }
690
691 template<class T>
mousePressEvent(T * ev)692 void QWebPagePrivate::mousePressEvent(T* ev)
693 {
694 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
695 if (!frame->view())
696 return;
697
698 RefPtr<WebCore::Node> oldNode;
699 Frame* focusedFrame = page->focusController()->focusedFrame();
700 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
701 oldNode = focusedDocument->focusedNode();
702
703 if (tripleClickTimer.isActive()
704 && (ev->pos() - tripleClick).manhattanLength()
705 < QApplication::startDragDistance()) {
706 mouseTripleClickEvent(ev);
707 return;
708 }
709
710 bool accepted = false;
711 adjustPointForClicking(ev);
712 PlatformMouseEvent mev(ev, 1);
713 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
714 if (mev.button() != NoButton)
715 accepted = frame->eventHandler()->handleMousePressEvent(mev);
716 ev->setAccepted(accepted);
717
718 RefPtr<WebCore::Node> newNode;
719 focusedFrame = page->focusController()->focusedFrame();
720 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
721 newNode = focusedDocument->focusedNode();
722
723 if (newNode && oldNode != newNode)
724 clickCausedFocus = true;
725 }
726
727 template<class T>
mouseDoubleClickEvent(T * ev)728 void QWebPagePrivate::mouseDoubleClickEvent(T *ev)
729 {
730 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
731 if (!frame->view())
732 return;
733
734 bool accepted = false;
735 PlatformMouseEvent mev(ev, 2);
736 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
737 if (mev.button() != NoButton)
738 accepted = frame->eventHandler()->handleMousePressEvent(mev);
739 ev->setAccepted(accepted);
740
741 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
742 tripleClick = QPointF(ev->pos()).toPoint();
743 }
744
745 template<class T>
mouseTripleClickEvent(T * ev)746 void QWebPagePrivate::mouseTripleClickEvent(T *ev)
747 {
748 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
749 if (!frame->view())
750 return;
751
752 bool accepted = false;
753 PlatformMouseEvent mev(ev, 3);
754 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
755 if (mev.button() != NoButton)
756 accepted = frame->eventHandler()->handleMousePressEvent(mev);
757 ev->setAccepted(accepted);
758 }
759
handleClipboard(QEvent * ev,Qt::MouseButton button)760 void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
761 {
762 #ifndef QT_NO_CLIPBOARD
763 if (QApplication::clipboard()->supportsSelection()) {
764 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
765 Pasteboard::generalPasteboard()->setSelectionMode(true);
766 WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
767 if (button == Qt::LeftButton) {
768 if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
769 Pasteboard::generalPasteboard()->writeSelection(focusFrame->editor()->selectedRange().get(), focusFrame->editor()->canSmartCopyOrDelete(), focusFrame);
770 ev->setAccepted(true);
771 }
772 } else if (button == Qt::MidButton) {
773 if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
774 focusFrame->editor()->paste();
775 ev->setAccepted(true);
776 }
777 }
778 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
779 }
780 #endif
781 }
782
783 template<class T>
mouseReleaseEvent(T * ev)784 void QWebPagePrivate::mouseReleaseEvent(T *ev)
785 {
786 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
787 if (!frame->view())
788 return;
789
790 bool accepted = false;
791 adjustPointForClicking(ev);
792 PlatformMouseEvent mev(ev, 0);
793 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
794 if (mev.button() != NoButton)
795 accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
796 ev->setAccepted(accepted);
797
798 handleClipboard(ev, ev->button());
799 handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
800 }
801
handleSoftwareInputPanel(Qt::MouseButton button,const QPoint & pos)802 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
803 {
804 Frame* frame = page->focusController()->focusedFrame();
805 if (!frame)
806 return;
807
808 if (client && client->inputMethodEnabled()
809 && frame->document()->focusedNode()
810 && button == Qt::LeftButton && qApp->autoSipEnabled()) {
811 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
812 client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
813 if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
814 HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false);
815 if (result.isContentEditable()) {
816 QEvent event(QEvent::RequestSoftwareInputPanel);
817 QApplication::sendEvent(client->ownerWidget(), &event);
818 }
819 }
820 }
821
822 clickCausedFocus = false;
823 }
824
825 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(const QPoint & globalPos)826 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
827 {
828 QMenu *menu = q->createStandardContextMenu();
829 if (menu) {
830 menu->exec(globalPos);
831 delete menu;
832 }
833 }
834 #endif // QT_NO_CONTEXTMENU
835
836 /*!
837 \since 4.5
838 This function creates the standard context menu which is shown when
839 the user clicks on the web page with the right mouse button. It is
840 called from the default contextMenuEvent() handler. The popup menu's
841 ownership is transferred to the caller.
842 */
createStandardContextMenu()843 QMenu *QWebPage::createStandardContextMenu()
844 {
845 #ifndef QT_NO_CONTEXTMENU
846 QMenu *menu = d->currentContextMenu;
847 d->currentContextMenu = 0;
848 return menu;
849 #else
850 return 0;
851 #endif
852 }
853
854 #ifndef QT_NO_WHEELEVENT
855 template<class T>
wheelEvent(T * ev)856 void QWebPagePrivate::wheelEvent(T *ev)
857 {
858 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
859 if (!frame->view())
860 return;
861
862 WebCore::PlatformWheelEvent pev(ev);
863 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
864 ev->setAccepted(accepted);
865 }
866 #endif // QT_NO_WHEELEVENT
867
868 #ifndef QT_NO_SHORTCUT
editorActionForKeyEvent(QKeyEvent * event)869 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
870 {
871 static struct {
872 QKeySequence::StandardKey standardKey;
873 QWebPage::WebAction action;
874 } editorActions[] = {
875 { QKeySequence::Cut, QWebPage::Cut },
876 { QKeySequence::Copy, QWebPage::Copy },
877 { QKeySequence::Paste, QWebPage::Paste },
878 { QKeySequence::Undo, QWebPage::Undo },
879 { QKeySequence::Redo, QWebPage::Redo },
880 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
881 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
882 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
883 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
884 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
885 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
886 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
887 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
888 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
889 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
890 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
891 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
892 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
893 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
894 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
895 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
896 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
897 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
898 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
899 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
900 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
901 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
902 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
903 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
904 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
905 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
906 { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
907 { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
908 { QKeySequence::SelectAll, QWebPage::SelectAll },
909 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
910 };
911
912 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
913 if (event == editorActions[i].standardKey)
914 return editorActions[i].action;
915
916 return QWebPage::NoWebAction;
917 }
918 #endif // QT_NO_SHORTCUT
919
keyPressEvent(QKeyEvent * ev)920 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
921 {
922 bool handled = false;
923 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
924 // we forward the key event to WebCore first to handle potential DOM
925 // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
926 // to trigger editor commands via triggerAction().
927 if (!handled)
928 handled = frame->eventHandler()->keyEvent(ev);
929 if (!handled) {
930 handled = true;
931 if (!handleScrolling(ev, frame)) {
932 switch (ev->key()) {
933 case Qt::Key_Back:
934 q->triggerAction(QWebPage::Back);
935 break;
936 case Qt::Key_Forward:
937 q->triggerAction(QWebPage::Forward);
938 break;
939 case Qt::Key_Stop:
940 q->triggerAction(QWebPage::Stop);
941 break;
942 case Qt::Key_Refresh:
943 q->triggerAction(QWebPage::Reload);
944 break;
945 case Qt::Key_Backspace:
946 if (ev->modifiers() == Qt::ShiftModifier)
947 q->triggerAction(QWebPage::Forward);
948 else
949 q->triggerAction(QWebPage::Back);
950 break;
951 default:
952 handled = false;
953 break;
954 }
955 }
956 }
957
958 ev->setAccepted(handled);
959 }
960
keyReleaseEvent(QKeyEvent * ev)961 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
962 {
963 if (ev->isAutoRepeat()) {
964 ev->setAccepted(true);
965 return;
966 }
967
968 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
969 bool handled = frame->eventHandler()->keyEvent(ev);
970 ev->setAccepted(handled);
971 }
972
focusInEvent(QFocusEvent *)973 void QWebPagePrivate::focusInEvent(QFocusEvent*)
974 {
975 FocusController *focusController = page->focusController();
976 focusController->setActive(true);
977 focusController->setFocused(true);
978 if (!focusController->focusedFrame())
979 focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
980 }
981
focusOutEvent(QFocusEvent *)982 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
983 {
984 // only set the focused frame inactive so that we stop painting the caret
985 // and the focus frame. But don't tell the focus controller so that upon
986 // focusInEvent() we can re-activate the frame.
987 FocusController *focusController = page->focusController();
988 // Call setFocused first so that window.onblur doesn't get called twice
989 focusController->setFocused(false);
990 focusController->setActive(false);
991 }
992
993 template<class T>
dragEnterEvent(T * ev)994 void QWebPagePrivate::dragEnterEvent(T* ev)
995 {
996 #ifndef QT_NO_DRAGANDDROP
997 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
998 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
999 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1000 ev->setDropAction(action);
1001 ev->acceptProposedAction();
1002 #endif
1003 }
1004
1005 template<class T>
dragLeaveEvent(T * ev)1006 void QWebPagePrivate::dragLeaveEvent(T *ev)
1007 {
1008 #ifndef QT_NO_DRAGANDDROP
1009 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1010 page->dragController()->dragExited(&dragData);
1011 ev->accept();
1012 #endif
1013 }
1014
1015 template<class T>
dragMoveEvent(T * ev)1016 void QWebPagePrivate::dragMoveEvent(T *ev)
1017 {
1018 #ifndef QT_NO_DRAGANDDROP
1019 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1020 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1021 m_lastDropAction = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1022 ev->setDropAction(m_lastDropAction);
1023 if (m_lastDropAction != Qt::IgnoreAction)
1024 ev->accept();
1025 #endif
1026 }
1027
1028 template<class T>
dropEvent(T * ev)1029 void QWebPagePrivate::dropEvent(T *ev)
1030 {
1031 #ifndef QT_NO_DRAGANDDROP
1032 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1033 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1034 if (page->dragController()->performDrag(&dragData)) {
1035 ev->setDropAction(m_lastDropAction);
1036 ev->accept();
1037 }
1038 #endif
1039 }
1040
leaveEvent(QEvent *)1041 void QWebPagePrivate::leaveEvent(QEvent*)
1042 {
1043 // Fake a mouse move event just outside of the widget, since all
1044 // the interesting mouse-out behavior like invalidating scrollbars
1045 // is handled by the WebKit event handler's mouseMoved function.
1046 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1047 mouseMoveEvent(&fakeEvent);
1048 }
1049
1050 /*!
1051 \property QWebPage::palette
1052 \brief the page's palette
1053
1054 The base brush of the palette is used to draw the background of the main frame.
1055
1056 By default, this property contains the application's default palette.
1057 */
setPalette(const QPalette & pal)1058 void QWebPage::setPalette(const QPalette &pal)
1059 {
1060 d->palette = pal;
1061 if (!d->mainFrame || !d->mainFrame->d->frame->view())
1062 return;
1063
1064 QBrush brush = pal.brush(QPalette::Base);
1065 QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1066 QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1067 }
1068
palette() const1069 QPalette QWebPage::palette() const
1070 {
1071 return d->palette;
1072 }
1073
inputMethodEvent(QInputMethodEvent * ev)1074 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1075 {
1076 WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1077 WebCore::Editor *editor = frame->editor();
1078
1079 if (!editor->canEdit()) {
1080 ev->ignore();
1081 return;
1082 }
1083
1084 Node* node = 0;
1085 if (frame->selection()->rootEditableElement())
1086 node = frame->selection()->rootEditableElement()->shadowAncestorNode();
1087
1088 Vector<CompositionUnderline> underlines;
1089 bool hasSelection = false;
1090
1091 for (int i = 0; i < ev->attributes().size(); ++i) {
1092 const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1093 switch (a.type) {
1094 case QInputMethodEvent::TextFormat: {
1095 QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1096 QColor qcolor = textCharFormat.underlineColor();
1097 underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1098 break;
1099 }
1100 case QInputMethodEvent::Cursor: {
1101 frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1102 if (a.length > 0) {
1103 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1104 if (caretRenderer) {
1105 QColor qcolor = a.value.value<QColor>();
1106 caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1107 }
1108 }
1109 break;
1110 }
1111 case QInputMethodEvent::Selection: {
1112 hasSelection = true;
1113 // A selection in the inputMethodEvent is always reflected in the visible text
1114 if (node)
1115 setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1116
1117 if (!ev->preeditString().isEmpty())
1118 editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1119 else {
1120 // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
1121 // cancels the current composition
1122 if (editor->hasComposition() && (a.start + a.length == 0))
1123 editor->setComposition(QString(), underlines, 0, 0);
1124 }
1125 break;
1126 }
1127 default:
1128 break;
1129 }
1130 }
1131
1132 if (node && ev->replacementLength() > 0) {
1133 int cursorPos = frame->selection()->extent().offsetInContainerNode();
1134 int start = cursorPos + ev->replacementStart();
1135 setSelectionRange(node, start, start + ev->replacementLength());
1136 // Commit regardless of whether commitString is empty, to get rid of selection.
1137 editor->confirmComposition(ev->commitString());
1138 } else if (!ev->commitString().isEmpty()) {
1139 if (editor->hasComposition())
1140 editor->confirmComposition(ev->commitString());
1141 else
1142 editor->insertText(ev->commitString(), 0);
1143 } else if (!hasSelection && !ev->preeditString().isEmpty())
1144 editor->setComposition(ev->preeditString(), underlines, 0, 0);
1145 else if (ev->preeditString().isEmpty() && editor->hasComposition())
1146 editor->confirmComposition(String());
1147
1148 ev->accept();
1149 }
1150
1151 #ifndef QT_NO_PROPERTIES
1152 typedef struct {
1153 const char* name;
1154 double deferredRepaintDelay;
1155 double initialDeferredRepaintDelayDuringLoading;
1156 double maxDeferredRepaintDelayDuringLoading;
1157 double deferredRepaintDelayIncrementDuringLoading;
1158 } QRepaintThrottlingPreset;
1159
dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent * event)1160 void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event)
1161 {
1162 if (event->propertyName() == "_q_viewMode") {
1163 page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString()));
1164 } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
1165 int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt();
1166 q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize);
1167 } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
1168 double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble();
1169 q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
1170 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
1171 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
1172 FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
1173 } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
1174 double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
1175 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
1176 } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
1177 double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
1178 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
1179 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
1180 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
1181 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
1182 } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
1183 static const QRepaintThrottlingPreset presets[] = {
1184 { "NoThrottling", 0, 0, 0, 0 },
1185 { "Legacy", 0.025, 0, 2.5, 0.5 },
1186 { "Minimal", 0.01, 0, 1, 0.2 },
1187 { "Medium", 0.025, 1, 5, 0.5 },
1188 { "Heavy", 0.1, 2, 10, 1 }
1189 };
1190
1191 QString p = q->property("_q_RepaintThrottlingPreset").toString();
1192 for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
1193 if (p == QLatin1String(presets[i].name)) {
1194 FrameView::setRepaintThrottlingDeferredRepaintDelay(
1195 presets[i].deferredRepaintDelay);
1196 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(
1197 presets[i].initialDeferredRepaintDelayDuringLoading);
1198 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(
1199 presets[i].maxDeferredRepaintDelayDuringLoading);
1200 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(
1201 presets[i].deferredRepaintDelayIncrementDuringLoading);
1202 break;
1203 }
1204 }
1205 }
1206 #if ENABLE(TILED_BACKING_STORE)
1207 else if (event->propertyName() == "_q_TiledBackingStoreTileSize") {
1208 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1209 if (!frame->tiledBackingStore())
1210 return;
1211 QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize();
1212 frame->tiledBackingStore()->setTileSize(tileSize);
1213 } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") {
1214 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1215 if (!frame->tiledBackingStore())
1216 return;
1217 int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt();
1218 frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.);
1219 } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") {
1220 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1221 if (!frame->tiledBackingStore())
1222 return;
1223 FloatSize keepMultiplier;
1224 FloatSize coverMultiplier;
1225 frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1226 QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF();
1227 keepMultiplier = FloatSize(qSize.width(), qSize.height());
1228 frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1229 } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") {
1230 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1231 if (!frame->tiledBackingStore())
1232 return;
1233 FloatSize keepMultiplier;
1234 FloatSize coverMultiplier;
1235 frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1236 QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF();
1237 coverMultiplier = FloatSize(qSize.width(), qSize.height());
1238 frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1239 }
1240 #endif
1241 else if (event->propertyName() == "_q_webInspectorServerPort") {
1242 InspectorServerQt* inspectorServer = InspectorServerQt::server();
1243 inspectorServer->listen(inspectorServerPort());
1244 } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
1245 double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble();
1246 memoryCache()->setDeadDecodedDataDeletionInterval(interval);
1247 }
1248 }
1249 #endif
1250
shortcutOverrideEvent(QKeyEvent * event)1251 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1252 {
1253 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1254 WebCore::Editor* editor = frame->editor();
1255 if (editor->canEdit()) {
1256 if (event->modifiers() == Qt::NoModifier
1257 || event->modifiers() == Qt::ShiftModifier
1258 || event->modifiers() == Qt::KeypadModifier) {
1259 if (event->key() < Qt::Key_Escape) {
1260 event->accept();
1261 } else {
1262 switch (event->key()) {
1263 case Qt::Key_Return:
1264 case Qt::Key_Enter:
1265 case Qt::Key_Delete:
1266 case Qt::Key_Home:
1267 case Qt::Key_End:
1268 case Qt::Key_Backspace:
1269 case Qt::Key_Left:
1270 case Qt::Key_Right:
1271 case Qt::Key_Up:
1272 case Qt::Key_Down:
1273 case Qt::Key_Tab:
1274 event->accept();
1275 default:
1276 break;
1277 }
1278 }
1279 }
1280 #ifndef QT_NO_SHORTCUT
1281 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1282 event->accept();
1283 #endif
1284 }
1285 }
1286
handleScrolling(QKeyEvent * ev,Frame * frame)1287 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1288 {
1289 ScrollDirection direction;
1290 ScrollGranularity granularity;
1291
1292 #ifndef QT_NO_SHORTCUT
1293 if (ev == QKeySequence::MoveToNextPage
1294 || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1295 granularity = ScrollByPage;
1296 direction = ScrollDown;
1297 } else if (ev == QKeySequence::MoveToPreviousPage
1298 || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1299 granularity = ScrollByPage;
1300 direction = ScrollUp;
1301 } else
1302 #endif // QT_NO_SHORTCUT
1303 if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1304 || ev->key() == Qt::Key_Home) {
1305 granularity = ScrollByDocument;
1306 direction = ScrollUp;
1307 } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1308 || ev->key() == Qt::Key_End) {
1309 granularity = ScrollByDocument;
1310 direction = ScrollDown;
1311 } else {
1312 switch (ev->key()) {
1313 case Qt::Key_Up:
1314 granularity = ScrollByLine;
1315 direction = ScrollUp;
1316 break;
1317 case Qt::Key_Down:
1318 granularity = ScrollByLine;
1319 direction = ScrollDown;
1320 break;
1321 case Qt::Key_Left:
1322 granularity = ScrollByLine;
1323 direction = ScrollLeft;
1324 break;
1325 case Qt::Key_Right:
1326 granularity = ScrollByLine;
1327 direction = ScrollRight;
1328 break;
1329 default:
1330 return false;
1331 }
1332 }
1333
1334 return frame->eventHandler()->scrollRecursively(direction, granularity);
1335 }
1336
adjustPointForClicking(QMouseEvent *)1337 void QWebPagePrivate::adjustPointForClicking(QMouseEvent*)
1338 {
1339 notImplemented();
1340 }
1341
1342 #if !defined(QT_NO_GRAPHICSVIEW)
adjustPointForClicking(QGraphicsSceneMouseEvent * ev)1343 void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev)
1344 {
1345 QtPlatformPlugin platformPlugin;
1346 OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
1347 if (!touchModifier)
1348 return;
1349
1350 unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
1351 unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
1352 unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
1353 unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
1354
1355 touchModifier = nullptr;
1356
1357 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
1358 return;
1359
1360 Document* startingDocument = page->mainFrame()->document();
1361 if (!startingDocument)
1362 return;
1363
1364 IntPoint originalPoint(QPointF(ev->pos()).toPoint());
1365 TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding);
1366 IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument);
1367 if (adjustedPoint == IntPoint::zero())
1368 return;
1369
1370 ev->setPos(QPointF(adjustedPoint));
1371 }
1372 #endif
1373
touchEvent(QTouchEvent * event)1374 bool QWebPagePrivate::touchEvent(QTouchEvent* event)
1375 {
1376 #if ENABLE(TOUCH_EVENTS)
1377 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
1378 if (!frame->view())
1379 return false;
1380
1381 // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
1382 event->setAccepted(true);
1383
1384 // Return whether the default action was cancelled in the JS event handler
1385 return frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1386 #else
1387 event->ignore();
1388 return false;
1389 #endif
1390 }
1391
1392 /*!
1393 This method is used by the input method to query a set of properties of the page
1394 to be able to support complex input method operations as support for surrounding
1395 text and reconversions.
1396
1397 \a property specifies which property is queried.
1398
1399 \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1400 */
inputMethodQuery(Qt::InputMethodQuery property) const1401 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1402 {
1403 Frame* frame = d->page->focusController()->focusedFrame();
1404 if (!frame)
1405 return QVariant();
1406
1407 WebCore::Editor* editor = frame->editor();
1408
1409 RenderObject* renderer = 0;
1410 RenderTextControl* renderTextControl = 0;
1411
1412 if (frame->selection()->rootEditableElement())
1413 renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1414
1415 if (renderer && renderer->isTextControl())
1416 renderTextControl = toRenderTextControl(renderer);
1417
1418 switch (property) {
1419 case Qt::ImMicroFocus: {
1420 WebCore::FrameView* view = frame->view();
1421 if (view && view->needsLayout()) {
1422 // We can't access absoluteCaretBounds() while the view needs to layout.
1423 return QVariant();
1424 }
1425 return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
1426 }
1427 case Qt::ImFont: {
1428 if (renderTextControl) {
1429 RenderStyle* renderStyle = renderTextControl->style();
1430 return QVariant(QFont(renderStyle->font().font()));
1431 }
1432 return QVariant(QFont());
1433 }
1434 case Qt::ImCursorPosition: {
1435 if (editor->hasComposition())
1436 return QVariant(frame->selection()->end().offsetInContainerNode());
1437 return QVariant(frame->selection()->extent().offsetInContainerNode());
1438 }
1439 case Qt::ImSurroundingText: {
1440 if (renderTextControl) {
1441 QString text = renderTextControl->text();
1442 RefPtr<Range> range = editor->compositionRange();
1443 if (range)
1444 text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1445 return QVariant(text);
1446 }
1447 return QVariant();
1448 }
1449 case Qt::ImCurrentSelection: {
1450 if (!editor->hasComposition() && renderTextControl) {
1451 int start = frame->selection()->start().offsetInContainerNode();
1452 int end = frame->selection()->end().offsetInContainerNode();
1453 if (end > start)
1454 return QVariant(QString(renderTextControl->text()).mid(start, end - start));
1455 }
1456 return QVariant();
1457
1458 }
1459 case Qt::ImAnchorPosition: {
1460 if (editor->hasComposition())
1461 return QVariant(frame->selection()->start().offsetInContainerNode());
1462 return QVariant(frame->selection()->base().offsetInContainerNode());
1463 }
1464 case Qt::ImMaximumTextLength: {
1465 if (frame->selection()->isContentEditable()) {
1466 if (frame->document() && frame->document()->focusedNode()) {
1467 if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1468 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1469 return QVariant(inputElement->maxLength());
1470 }
1471 }
1472 return QVariant(InputElement::s_maximumLength);
1473 }
1474 return QVariant(0);
1475 }
1476 default:
1477 return QVariant();
1478 }
1479 }
1480
1481 /*!
1482 \internal
1483 */
setInspector(QWebInspector * insp)1484 void QWebPagePrivate::setInspector(QWebInspector* insp)
1485 {
1486 if (inspector)
1487 inspector->d->setFrontend(0);
1488
1489 if (inspectorIsInternalOnly) {
1490 QWebInspector* inspToDelete = inspector;
1491 inspector = 0;
1492 inspectorIsInternalOnly = false;
1493 delete inspToDelete; // Delete after to prevent infinite recursion
1494 }
1495
1496 inspector = insp;
1497
1498 // Give inspector frontend web view if previously created
1499 if (inspector && inspectorFrontend)
1500 inspector->d->setFrontend(inspectorFrontend);
1501 }
1502
1503 /*!
1504 \internal
1505 Returns the inspector and creates it if it wasn't created yet.
1506 The instance created here will not be available through QWebPage's API.
1507 */
getOrCreateInspector()1508 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1509 {
1510 #if ENABLE(INSPECTOR)
1511 if (!inspector) {
1512 QWebInspector* insp = new QWebInspector;
1513 insp->setPage(q);
1514 inspectorIsInternalOnly = true;
1515
1516 Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1517 }
1518 #endif
1519 return inspector;
1520 }
1521
1522 /*! \internal */
inspectorController()1523 InspectorController* QWebPagePrivate::inspectorController()
1524 {
1525 #if ENABLE(INSPECTOR)
1526 return page->inspectorController();
1527 #else
1528 return 0;
1529 #endif
1530 }
1531
inspectorServerPort()1532 quint16 QWebPagePrivate::inspectorServerPort()
1533 {
1534 #if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
1535 if (q && q->property("_q_webInspectorServerPort").isValid())
1536 return q->property("_q_webInspectorServerPort").toInt();
1537 #endif
1538 return 0;
1539 }
1540
hasMouseListener(Element * element)1541 static bool hasMouseListener(Element* element)
1542 {
1543 ASSERT(element);
1544 return element->hasEventListeners(eventNames().clickEvent)
1545 || element->hasEventListeners(eventNames().mousedownEvent)
1546 || element->hasEventListeners(eventNames().mouseupEvent);
1547 }
1548
isClickableElement(Element * element,RefPtr<NodeList> list)1549 static bool isClickableElement(Element* element, RefPtr<NodeList> list)
1550 {
1551 ASSERT(element);
1552 bool isClickable = hasMouseListener(element);
1553 if (!isClickable && list) {
1554 Element* parent = element->parentElement();
1555 unsigned count = list->length();
1556 for (unsigned i = 0; i < count && parent; i++) {
1557 if (list->item(i) != parent)
1558 continue;
1559
1560 isClickable = hasMouseListener(parent);
1561 if (isClickable)
1562 break;
1563
1564 parent = parent->parentElement();
1565 }
1566 }
1567
1568 ExceptionCode ec = 0;
1569 return isClickable
1570 || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec)
1571 || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer";
1572 }
1573
isValidFrameOwner(Element * element)1574 static bool isValidFrameOwner(Element* element)
1575 {
1576 ASSERT(element);
1577 return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame();
1578 }
1579
nodeToElement(Node * node)1580 static Element* nodeToElement(Node* node)
1581 {
1582 if (node && node->isElementNode())
1583 return static_cast<Element*>(node);
1584 return 0;
1585 }
1586
TouchAdjuster(unsigned topPadding,unsigned rightPadding,unsigned bottomPadding,unsigned leftPadding)1587 QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
1588 : m_topPadding(topPadding)
1589 , m_rightPadding(rightPadding)
1590 , m_bottomPadding(bottomPadding)
1591 , m_leftPadding(leftPadding)
1592 {
1593 }
1594
findCandidatePointForTouch(const IntPoint & touchPoint,Document * document) const1595 IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const
1596 {
1597 if (!document)
1598 return IntPoint();
1599
1600 int x = touchPoint.x();
1601 int y = touchPoint.y();
1602
1603 RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false);
1604 if (!intersectedNodes)
1605 return IntPoint();
1606
1607 Element* closestClickableElement = 0;
1608 IntRect largestIntersectionRect;
1609 FrameView* view = document->frame()->view();
1610
1611 // Touch rect in contents coordinates.
1612 IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding));
1613
1614 // Iterate over the list of nodes hit looking for the one whose bounding area
1615 // has largest intersection with the touch area (point + padding).
1616 for (unsigned i = 0; i < intersectedNodes->length(); i++) {
1617 Node* currentNode = intersectedNodes->item(i);
1618
1619 Element* currentElement = nodeToElement(currentNode);
1620 if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement)))
1621 continue;
1622
1623 IntRect currentElementBoundingRect = currentElement->getRect();
1624 currentElementBoundingRect.intersect(touchRect);
1625
1626 if (currentElementBoundingRect.isEmpty())
1627 continue;
1628
1629 int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height();
1630 int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height();
1631 if (currentIntersectionRectArea > largestIntersectionRectArea) {
1632 closestClickableElement = currentElement;
1633 largestIntersectionRect = currentElementBoundingRect;
1634 }
1635 }
1636
1637 if (largestIntersectionRect.isEmpty())
1638 return IntPoint();
1639
1640 // Handle the case when user taps a inner frame. It is done in three steps:
1641 // 1) Transform the original touch point to the inner document coordinates;
1642 // 1) Call nodesFromRect for the inner document in case;
1643 // 3) Re-add the inner frame offset (location) before passing the new clicking
1644 // position to WebCore.
1645 if (closestClickableElement->isFrameOwnerElement()) {
1646 // Adjust client coordinates' origin to be top left of inner frame viewport.
1647 PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect();
1648 IntPoint newTouchPoint = touchPoint;
1649 IntSize offset = IntSize(rect->left(), rect->top());
1650 newTouchPoint -= offset;
1651
1652 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement);
1653 Document* childDocument = owner->contentFrame()->document();
1654 return findCandidatePointForTouch(newTouchPoint, childDocument);
1655 }
1656 return view->contentsToWindow(largestIntersectionRect).center();
1657 }
1658
1659 /*!
1660 \enum QWebPage::FindFlag
1661
1662 This enum describes the options available to the findText() function. The options
1663 can be OR-ed together from the following list:
1664
1665 \value FindBackward Searches backwards instead of forwards.
1666 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1667 changes the behaviour to a case sensitive find operation.
1668 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1669 was reached and the text was not found.
1670 \value HighlightAllOccurrences Highlights all existing occurrences of a specific string. (This value was introduced in 4.6.)
1671 */
1672
1673 /*!
1674 \enum QWebPage::LinkDelegationPolicy
1675
1676 This enum defines the delegation policies a webpage can have when activating links and emitting
1677 the linkClicked() signal.
1678
1679 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1680 \value DelegateExternalLinks When activating links that point to documents not stored on the
1681 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1682 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1683
1684 \sa QWebPage::linkDelegationPolicy
1685 */
1686
1687 /*!
1688 \enum QWebPage::NavigationType
1689
1690 This enum describes the types of navigation available when browsing through hyperlinked
1691 documents.
1692
1693 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1694 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1695 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1696 \value NavigationTypeReload The user activated the reload action.
1697 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1698 \value NavigationTypeOther A navigation to another document using a method not listed above.
1699
1700 \sa acceptNavigationRequest()
1701 */
1702
1703 /*!
1704 \enum QWebPage::WebAction
1705
1706 This enum describes the types of action which can be performed on the web page.
1707
1708 Actions only have an effect when they are applicable. The availability of
1709 actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1710 action returned by action().
1711
1712 One method of enabling the text editing, cursor movement, and text selection actions
1713 is by setting \l contentEditable to true.
1714
1715 \value NoWebAction No action is triggered.
1716 \value OpenLink Open the current link.
1717 \value OpenLinkInNewWindow Open the current link in a new window.
1718 \value OpenFrameInNewWindow Replicate the current frame in a new window.
1719 \value DownloadLinkToDisk Download the current link to the disk.
1720 \value CopyLinkToClipboard Copy the current link to the clipboard.
1721 \value OpenImageInNewWindow Open the highlighted image in a new window.
1722 \value DownloadImageToDisk Download the highlighted image to the disk.
1723 \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1724 \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1725 \value Back Navigate back in the history of navigated links.
1726 \value Forward Navigate forward in the history of navigated links.
1727 \value Stop Stop loading the current page.
1728 \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests.
1729 \value Reload Reload the current page.
1730 \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1731 \value Cut Cut the content currently selected into the clipboard.
1732 \value Copy Copy the content currently selected into the clipboard.
1733 \value Paste Paste content from the clipboard.
1734 \value Undo Undo the last editing action.
1735 \value Redo Redo the last editing action.
1736 \value MoveToNextChar Move the cursor to the next character.
1737 \value MoveToPreviousChar Move the cursor to the previous character.
1738 \value MoveToNextWord Move the cursor to the next word.
1739 \value MoveToPreviousWord Move the cursor to the previous word.
1740 \value MoveToNextLine Move the cursor to the next line.
1741 \value MoveToPreviousLine Move the cursor to the previous line.
1742 \value MoveToStartOfLine Move the cursor to the start of the line.
1743 \value MoveToEndOfLine Move the cursor to the end of the line.
1744 \value MoveToStartOfBlock Move the cursor to the start of the block.
1745 \value MoveToEndOfBlock Move the cursor to the end of the block.
1746 \value MoveToStartOfDocument Move the cursor to the start of the document.
1747 \value MoveToEndOfDocument Move the cursor to the end of the document.
1748 \value SelectNextChar Select to the next character.
1749 \value SelectPreviousChar Select to the previous character.
1750 \value SelectNextWord Select to the next word.
1751 \value SelectPreviousWord Select to the previous word.
1752 \value SelectNextLine Select to the next line.
1753 \value SelectPreviousLine Select to the previous line.
1754 \value SelectStartOfLine Select to the start of the line.
1755 \value SelectEndOfLine Select to the end of the line.
1756 \value SelectStartOfBlock Select to the start of the block.
1757 \value SelectEndOfBlock Select to the end of the block.
1758 \value SelectStartOfDocument Select to the start of the document.
1759 \value SelectEndOfDocument Select to the end of the document.
1760 \value DeleteStartOfWord Delete to the start of the word.
1761 \value DeleteEndOfWord Delete to the end of the word.
1762 \value SetTextDirectionDefault Set the text direction to the default direction.
1763 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1764 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1765 \value ToggleBold Toggle the formatting between bold and normal weight.
1766 \value ToggleItalic Toggle the formatting between italic and normal style.
1767 \value ToggleUnderline Toggle underlining.
1768 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1769 \value InsertParagraphSeparator Insert a new paragraph.
1770 \value InsertLineSeparator Insert a new line.
1771 \value SelectAll Selects all content.
1772 \value PasteAndMatchStyle Paste content from the clipboard with current style.
1773 \value RemoveFormat Removes formatting and style.
1774 \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1775 \value ToggleSubscript Toggle the formatting between subscript and baseline.
1776 \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1777 \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1778 \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1779 \value Indent Increases the indentation of the currently selected format block by one increment.
1780 \value Outdent Decreases the indentation of the currently selected format block by one increment.
1781 \value AlignCenter Applies center alignment to content.
1782 \value AlignJustified Applies full justification to content.
1783 \value AlignLeft Applies left justification to content.
1784 \value AlignRight Applies right justification to content.
1785
1786
1787 \omitvalue WebActionCount
1788
1789 */
1790
1791 /*!
1792 \enum QWebPage::WebWindowType
1793
1794 This enum describes the types of window that can be created by the createWindow() function.
1795
1796 \value WebBrowserWindow The window is a regular web browser window.
1797 \value WebModalDialog The window acts as modal dialog.
1798 */
1799
1800
1801 /*!
1802 \class QWebPage::ViewportAttributes
1803 \since 4.7
1804 \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1805
1806 QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1807 initial scale factor with limits, plus information about whether a user should be able
1808 to scale the contents in the viewport or not, ie. by zooming.
1809
1810 ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1811 at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1812
1813 All values might not be set, as such when dealing with the hints, the developer needs to
1814 check whether the values are valid. Negative values denote an invalid qreal value.
1815
1816 \inmodule QtWebKit
1817 */
1818
1819 /*!
1820 Constructs an empty QWebPage::ViewportAttributes.
1821 */
ViewportAttributes()1822 QWebPage::ViewportAttributes::ViewportAttributes()
1823 : d(0)
1824 , m_initialScaleFactor(-1.0)
1825 , m_minimumScaleFactor(-1.0)
1826 , m_maximumScaleFactor(-1.0)
1827 , m_devicePixelRatio(-1.0)
1828 , m_isUserScalable(true)
1829 , m_isValid(false)
1830 {
1831
1832 }
1833
1834 /*!
1835 Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1836 */
ViewportAttributes(const QWebPage::ViewportAttributes & other)1837 QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1838 : d(other.d)
1839 , m_initialScaleFactor(other.m_initialScaleFactor)
1840 , m_minimumScaleFactor(other.m_minimumScaleFactor)
1841 , m_maximumScaleFactor(other.m_maximumScaleFactor)
1842 , m_devicePixelRatio(other.m_devicePixelRatio)
1843 , m_isUserScalable(other.m_isUserScalable)
1844 , m_isValid(other.m_isValid)
1845 , m_size(other.m_size)
1846 {
1847
1848 }
1849
1850 /*!
1851 Destroys the QWebPage::ViewportAttributes.
1852 */
~ViewportAttributes()1853 QWebPage::ViewportAttributes::~ViewportAttributes()
1854 {
1855
1856 }
1857
1858 /*!
1859 Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1860 reference to this.
1861 */
operator =(const QWebPage::ViewportAttributes & other)1862 QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1863 {
1864 if (this != &other) {
1865 d = other.d;
1866 m_initialScaleFactor = other.m_initialScaleFactor;
1867 m_minimumScaleFactor = other.m_minimumScaleFactor;
1868 m_maximumScaleFactor = other.m_maximumScaleFactor;
1869 m_isUserScalable = other.m_isUserScalable;
1870 m_isValid = other.m_isValid;
1871 m_size = other.m_size;
1872 }
1873
1874 return *this;
1875 }
1876
1877 /*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1878 Returns whether this is a valid ViewportAttributes or not.
1879
1880 An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1881 true for the boolean isUserScalable.
1882 */
1883
1884 /*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1885 Returns the size of the viewport.
1886 */
1887
1888 /*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1889 Returns the initial scale of the viewport as a multiplier.
1890 */
1891
1892 /*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1893 Returns the minimum scale value of the viewport as a multiplier.
1894 */
1895
1896 /*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1897 Returns the maximum scale value of the viewport as a multiplier.
1898 */
1899
1900 /*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1901 Determines whether or not the scale can be modified by the user.
1902 */
1903
1904
1905 /*!
1906 \class QWebPage
1907 \since 4.4
1908 \brief The QWebPage class provides an object to view and edit web documents.
1909
1910 \inmodule QtWebKit
1911
1912 QWebPage holds a main frame responsible for web content, settings, the history
1913 of navigated links and actions. This class can be used, together with QWebFrame,
1914 to provide functionality like QWebView in a widget-less environment.
1915
1916 QWebPage's API is very similar to QWebView, as you are still provided with
1917 common functions like action() (known as
1918 \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1919 findText() and settings(). More QWebView-like functions can be found in the
1920 main frame of QWebPage, obtained via the mainFrame() function. For example,
1921 the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1922 \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1923 using QWebFrame.
1924
1925 The loadStarted() signal is emitted when the page begins to load.The
1926 loadProgress() signal, on the other hand, is emitted whenever an element
1927 of the web page completes loading, such as an embedded image, a script,
1928 etc. Finally, the loadFinished() signal is emitted when the page contents
1929 are loaded completely, independent of script execution or page rendering.
1930 Its argument, either true or false, indicates whether or not the load
1931 operation succeeded.
1932
1933 \section1 Using QWebPage in a Widget-less Environment
1934
1935 Before you begin painting a QWebPage object, you need to set the size of
1936 the viewport by calling setViewportSize(). Then, you invoke the main
1937 frame's render function (QWebFrame::render()). An example of this
1938 is shown in the code snippet below.
1939
1940 Suppose we have a \c Thumbnail class as follows:
1941
1942 \snippet webkitsnippets/webpage/main.cpp 0
1943
1944 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1945 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1946 \c render().
1947
1948 \snippet webkitsnippets/webpage/main.cpp 1
1949
1950 The \c render() function shows how we can paint a thumbnail using a
1951 QWebPage object.
1952
1953 \snippet webkitsnippets/webpage/main.cpp 2
1954
1955 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1956 then we instantiate a QImage object, \c image, with the same size as our
1957 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1958 as a parameter to \c painter. Next, we render the contents of the main
1959 frame and its subframes into \c painter. Finally, we save the scaled image.
1960
1961 \sa QWebFrame
1962 */
1963
1964 /*!
1965 Constructs an empty QWebPage with parent \a parent.
1966 */
QWebPage(QObject * parent)1967 QWebPage::QWebPage(QObject *parent)
1968 : QObject(parent)
1969 , d(new QWebPagePrivate(this))
1970 {
1971 setView(qobject_cast<QWidget*>(parent));
1972
1973 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1974 #ifndef NDEBUG
1975 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1976 #endif
1977 }
1978
1979 /*!
1980 Destroys the web page.
1981 */
~QWebPage()1982 QWebPage::~QWebPage()
1983 {
1984 d->createMainFrame();
1985 FrameLoader *loader = d->mainFrame->d->frame->loader();
1986 if (loader)
1987 loader->detachFromParent();
1988 delete d;
1989 }
1990
1991 /*!
1992 Returns the main frame of the page.
1993
1994 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1995 want to explicitly render a web page into a given painter.
1996
1997 \sa currentFrame()
1998 */
mainFrame() const1999 QWebFrame *QWebPage::mainFrame() const
2000 {
2001 d->createMainFrame();
2002 return d->mainFrame;
2003 }
2004
2005 /*!
2006 Returns the frame currently active.
2007
2008 \sa mainFrame(), frameCreated()
2009 */
currentFrame() const2010 QWebFrame *QWebPage::currentFrame() const
2011 {
2012 d->createMainFrame();
2013 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2014 return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject());
2015 }
2016
2017
2018 /*!
2019 \since 4.6
2020
2021 Returns the frame at the given point \a pos, or 0 if there is no frame at
2022 that position.
2023
2024 \sa mainFrame(), currentFrame()
2025 */
frameAt(const QPoint & pos) const2026 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
2027 {
2028 QWebFrame* webFrame = mainFrame();
2029 if (!webFrame->geometry().contains(pos))
2030 return 0;
2031 QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
2032 return hitTestResult.frame();
2033 }
2034
2035 /*!
2036 Returns a pointer to the view's history of navigated web pages.
2037 */
history() const2038 QWebHistory *QWebPage::history() const
2039 {
2040 d->createMainFrame();
2041 return &d->history;
2042 }
2043
2044 /*!
2045 Sets the \a view that is associated with the web page.
2046
2047 \sa view()
2048 */
setView(QWidget * view)2049 void QWebPage::setView(QWidget* view)
2050 {
2051 if (this->view() == view)
2052 return;
2053
2054 d->view = view;
2055 setViewportSize(view ? view->size() : QSize(0, 0));
2056
2057 // If we have no client, we install a special client delegating
2058 // the responsibility to the QWidget. This is the code path
2059 // handling a.o. the "legacy" QWebView.
2060 //
2061 // If such a special delegate already exist, we substitute the view.
2062
2063 if (d->client) {
2064 if (d->client->isQWidgetClient())
2065 static_cast<PageClientQWidget*>(d->client.get())->view = view;
2066 return;
2067 }
2068
2069 if (view)
2070 d->client = adoptPtr(new PageClientQWidget(view, this));
2071 }
2072
2073 /*!
2074 Returns the view widget that is associated with the web page.
2075
2076 \sa setView()
2077 */
view() const2078 QWidget *QWebPage::view() const
2079 {
2080 return d->view.data();
2081 }
2082
2083 /*!
2084 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
2085
2086 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
2087
2088 The default implementation prints nothing.
2089 */
javaScriptConsoleMessage(const QString & message,int lineNumber,const QString & sourceID)2090 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
2091 {
2092 Q_UNUSED(sourceID)
2093
2094 // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
2095 // At this point DRT's WebPage has already been destroyed
2096 if (QWebPagePrivate::drtRun) {
2097 if (message == QLatin1String("PLUGIN: NPP_Destroy"))
2098 fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData());
2099 }
2100 }
2101
2102 /*!
2103 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
2104 the message \a msg.
2105
2106 The default implementation shows the message, \a msg, with QMessageBox::information.
2107 */
javaScriptAlert(QWebFrame * frame,const QString & msg)2108 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
2109 {
2110 Q_UNUSED(frame)
2111 #ifndef QT_NO_MESSAGEBOX
2112 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2113 QMessageBox::information(parent, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
2114 #endif
2115 }
2116
2117 /*!
2118 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
2119 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
2120
2121 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2122 */
javaScriptConfirm(QWebFrame * frame,const QString & msg)2123 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
2124 {
2125 Q_UNUSED(frame)
2126 #ifdef QT_NO_MESSAGEBOX
2127 return true;
2128 #else
2129 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2130 return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
2131 #endif
2132 }
2133
2134 /*!
2135 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
2136 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
2137
2138 If the prompt was cancelled by the user the implementation should return false; otherwise the
2139 result should be written to \a result and true should be returned. If the prompt was not cancelled by the
2140 user, the implementation should return true and the result string must not be null.
2141
2142 The default implementation uses QInputDialog::getText().
2143 */
javaScriptPrompt(QWebFrame * frame,const QString & msg,const QString & defaultValue,QString * result)2144 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
2145 {
2146 Q_UNUSED(frame)
2147 bool ok = false;
2148 #ifndef QT_NO_INPUTDIALOG
2149 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2150 QString x = QInputDialog::getText(parent, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
2151 if (ok && result)
2152 *result = x;
2153 #endif
2154 return ok;
2155 }
2156
2157 /*!
2158 \fn bool QWebPage::shouldInterruptJavaScript()
2159 \since 4.6
2160 This function is called when a JavaScript program is running for a long period of time.
2161
2162 If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
2163
2164 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2165
2166 \warning Because of binary compatibility constraints, this function is not virtual. If you want to
2167 provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
2168 slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
2169 */
shouldInterruptJavaScript()2170 bool QWebPage::shouldInterruptJavaScript()
2171 {
2172 #ifdef QT_NO_MESSAGEBOX
2173 return false;
2174 #else
2175 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2176 return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
2177 #endif
2178 }
2179
setFeaturePermission(QWebFrame * frame,Feature feature,PermissionPolicy policy)2180 void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
2181 {
2182 switch (feature) {
2183 case Notifications:
2184 #if ENABLE(NOTIFICATIONS)
2185 if (policy == PermissionGrantedByUser)
2186 NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame);
2187 #endif
2188 break;
2189 case Geolocation:
2190 #if ENABLE(GEOLOCATION)
2191 GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy);
2192 #endif
2193 break;
2194
2195 default:
2196 break;
2197 }
2198 }
2199
2200 /*!
2201 This function is called whenever WebKit wants to create a new window of the given \a type, for
2202 example when a JavaScript program requests to open a document in a new window.
2203
2204 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
2205
2206 If the view associated with the web page is a QWebView object, then the default implementation forwards
2207 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
2208
2209 If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
2210
2211 \note In the cases when the window creation is being triggered by JavaScript, apart from
2212 reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
2213 of QWebSettings to true in order for it to get called.
2214
2215 \sa acceptNavigationRequest(), QWebView::createWindow()
2216 */
createWindow(WebWindowType type)2217 QWebPage *QWebPage::createWindow(WebWindowType type)
2218 {
2219 QWebView *webView = qobject_cast<QWebView*>(view());
2220 if (webView) {
2221 QWebView *newView = webView->createWindow(type);
2222 if (newView)
2223 return newView->page();
2224 }
2225 return 0;
2226 }
2227
2228 /*!
2229 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
2230 called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
2231 correspond to the HTML object element attributes and child elements to configure the embeddable object.
2232 */
createPlugin(const QString & classid,const QUrl & url,const QStringList & paramNames,const QStringList & paramValues)2233 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues)
2234 {
2235 Q_UNUSED(classid)
2236 Q_UNUSED(url)
2237 Q_UNUSED(paramNames)
2238 Q_UNUSED(paramValues)
2239 return 0;
2240 }
2241
extractContentTypeFromHash(const HashSet<String> & types,QStringList * list)2242 static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
2243 {
2244 if (!list)
2245 return;
2246
2247 HashSet<String>::const_iterator endIt = types.end();
2248 for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
2249 *list << *it;
2250 }
2251
extractContentTypeFromPluginVector(const Vector<PluginPackage * > & plugins,QStringList * list)2252 static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
2253 {
2254 if (!list)
2255 return;
2256
2257 for (unsigned int i = 0; i < plugins.size(); ++i) {
2258 MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin();
2259 MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end();
2260 for (; map_it != map_end; ++map_it)
2261 *list << map_it->first;
2262 }
2263 }
2264
2265 /*!
2266 * Returns the list of all content types supported by QWebPage.
2267 */
supportedContentTypes() const2268 QStringList QWebPage::supportedContentTypes() const
2269 {
2270 QStringList mimeTypes;
2271
2272 extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
2273 extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
2274 if (d->page->settings() && d->page->settings()->arePluginsEnabled())
2275 extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
2276
2277 return mimeTypes;
2278 }
2279
2280 /*!
2281 * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
2282 */
supportsContentType(const QString & mimeType) const2283 bool QWebPage::supportsContentType(const QString& mimeType) const
2284 {
2285 const String type = mimeType.toLower();
2286 if (MIMETypeRegistry::isSupportedImageMIMEType(type))
2287 return true;
2288
2289 if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
2290 return true;
2291
2292 if (d->page->settings() && d->page->settings()->arePluginsEnabled()
2293 && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
2294 return true;
2295
2296 return false;
2297 }
2298
frameLoadRequest(const QUrl & url,WebCore::Frame * frame)2299 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
2300 {
2301 return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
2302 WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
2303 }
2304
openNewWindow(const QUrl & url,WebCore::Frame * frame)2305 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
2306 {
2307 if (Page* oldPage = frame->page()) {
2308 WindowFeatures features;
2309 NavigationAction action;
2310 FrameLoadRequest request = frameLoadRequest(url, frame);
2311 if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) {
2312 newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer);
2313 newPage->chrome()->show();
2314 }
2315 }
2316 }
2317
collectChildFrames(QWebFrame * frame,QList<QWebFrame * > & list)2318 static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
2319 {
2320 list << frame->childFrames();
2321 QListIterator<QWebFrame*> it(frame->childFrames());
2322 while (it.hasNext()) {
2323 collectChildFrames(it.next(), list);
2324 }
2325 }
2326
2327 /*!
2328 This function can be called to trigger the specified \a action.
2329 It is also called by QtWebKit if the user triggers the action, for example
2330 through a context menu item.
2331
2332 If \a action is a checkable action then \a checked specified whether the action
2333 is toggled or not.
2334
2335 \sa action()
2336 */
triggerAction(WebAction action,bool)2337 void QWebPage::triggerAction(WebAction action, bool)
2338 {
2339 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2340 if (!frame)
2341 return;
2342 WebCore::Editor *editor = frame->editor();
2343 const char *command = 0;
2344
2345 switch (action) {
2346 case OpenLink:
2347 if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2348 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2349 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2350 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2351 /*FormState*/ 0, SendReferrer);
2352 break;
2353 }
2354 // fall through
2355 case OpenLinkInNewWindow:
2356 openNewWindow(d->hitTestResult.linkUrl(), frame);
2357 break;
2358 case OpenFrameInNewWindow: {
2359 KURL url = frame->loader()->documentLoader()->unreachableURL();
2360 if (url.isEmpty())
2361 url = frame->loader()->documentLoader()->url();
2362 openNewWindow(url, frame);
2363 break;
2364 }
2365 case CopyLinkToClipboard: {
2366 #if defined(Q_WS_X11)
2367 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2368 Pasteboard::generalPasteboard()->setSelectionMode(true);
2369 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2370 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2371 #endif
2372 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2373 break;
2374 }
2375 case OpenImageInNewWindow:
2376 openNewWindow(d->hitTestResult.imageUrl(), frame);
2377 break;
2378 case DownloadImageToDisk:
2379 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2380 break;
2381 case DownloadLinkToDisk:
2382 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2383 break;
2384 #ifndef QT_NO_CLIPBOARD
2385 case CopyImageToClipboard:
2386 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2387 break;
2388 case CopyImageUrlToClipboard:
2389 QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
2390 break;
2391 #endif
2392 case Back:
2393 d->page->goBack();
2394 break;
2395 case Forward:
2396 d->page->goForward();
2397 break;
2398 case Stop:
2399 mainFrame()->d->frame->loader()->stopForUserCancel();
2400 d->updateNavigationActions();
2401 break;
2402 case Reload:
2403 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2404 break;
2405 case ReloadAndBypassCache:
2406 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2407 break;
2408 case SetTextDirectionDefault:
2409 editor->setBaseWritingDirection(NaturalWritingDirection);
2410 break;
2411 case SetTextDirectionLeftToRight:
2412 editor->setBaseWritingDirection(LeftToRightWritingDirection);
2413 break;
2414 case SetTextDirectionRightToLeft:
2415 editor->setBaseWritingDirection(RightToLeftWritingDirection);
2416 break;
2417 case InspectElement: {
2418 #if ENABLE(INSPECTOR)
2419 if (!d->hitTestResult.isNull()) {
2420 d->getOrCreateInspector(); // Make sure the inspector is created
2421 d->inspector->show(); // The inspector is expected to be shown on inspection
2422 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2423 }
2424 #endif
2425 break;
2426 }
2427 case StopScheduledPageRefresh: {
2428 QWebFrame* topFrame = mainFrame();
2429 topFrame->d->frame->navigationScheduler()->cancel();
2430 QList<QWebFrame*> childFrames;
2431 collectChildFrames(topFrame, childFrames);
2432 QListIterator<QWebFrame*> it(childFrames);
2433 while (it.hasNext())
2434 it.next()->d->frame->navigationScheduler()->cancel();
2435 break;
2436 }
2437 default:
2438 command = QWebPagePrivate::editorCommandForWebActions(action);
2439 break;
2440 }
2441
2442 if (command)
2443 editor->command(command).execute();
2444 }
2445
viewportSize() const2446 QSize QWebPage::viewportSize() const
2447 {
2448 if (d->mainFrame && d->mainFrame->d->frame->view())
2449 return d->mainFrame->d->frame->view()->frameRect().size();
2450
2451 return d->viewportSize;
2452 }
2453
2454 /*!
2455 \property QWebPage::viewportSize
2456 \brief the size of the viewport
2457
2458 The size affects for example the visibility of scrollbars
2459 if the document is larger than the viewport.
2460
2461 By default, for a newly-created Web page, this property contains a size with
2462 zero width and height.
2463
2464 \sa QWebFrame::render(), preferredContentsSize
2465 */
setViewportSize(const QSize & size) const2466 void QWebPage::setViewportSize(const QSize &size) const
2467 {
2468 d->viewportSize = size;
2469
2470 QWebFrame *frame = mainFrame();
2471 if (frame->d->frame && frame->d->frame->view()) {
2472 WebCore::FrameView* view = frame->d->frame->view();
2473 view->resize(size);
2474 view->adjustViewSize();
2475 }
2476 }
2477
getintenv(const char * variable)2478 static int getintenv(const char* variable)
2479 {
2480 bool ok;
2481 int value = qgetenv(variable).toInt(&ok);
2482 return (ok) ? value : -1;
2483 }
2484
queryDeviceSizeForScreenContainingWidget(const QWidget * widget)2485 static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2486 {
2487 QDesktopWidget* desktop = QApplication::desktop();
2488 if (!desktop)
2489 return QSize();
2490
2491 QSize size;
2492
2493 if (widget) {
2494 // Returns the available geometry of the screen which contains widget.
2495 // NOTE: this must be the the full screen size including any fixed status areas etc.
2496 size = desktop->availableGeometry(widget).size();
2497 } else
2498 size = desktop->availableGeometry().size();
2499
2500 // This must be in portrait mode, adjust if not.
2501 if (size.width() > size.height()) {
2502 int width = size.width();
2503 size.setWidth(size.height());
2504 size.setHeight(width);
2505 }
2506
2507 return size;
2508 }
2509
2510 /*!
2511 Computes the optimal viewport configuration given the \a availableSize, when
2512 user interface components are disregarded.
2513
2514 The configuration is also dependent on the device screen size which is obtained
2515 automatically. For testing purposes the size can be overridden by setting two
2516 environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2517 both needs to be set.
2518
2519 The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2520 the web author though the -webkit-pixel-ratio media feature. This is the ratio
2521 between 1 density-independent pixel (DPI) and physical pixels.
2522
2523 A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2524 so on our platform assumes that as the baseline density.
2525
2526 The conversion of DIP units to screen pixels is quite simple:
2527
2528 pixels = DIPs * (density / 160).
2529
2530 Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2531
2532 An invalid instance will be returned in the case an empty size is passed to the
2533 method.
2534
2535 \note The density is automatically obtained from the DPI of the screen where the page
2536 is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2537 override it using QX11Info::setAppDpiY().
2538 */
2539
viewportAttributesForSize(const QSize & availableSize) const2540 QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2541 {
2542 static int desktopWidth = 980;
2543
2544 ViewportAttributes result;
2545
2546 if (availableSize.isEmpty())
2547 return result; // Returns an invalid instance.
2548
2549 int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH");
2550 int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT");
2551
2552 // Both environment variables need to be set - or they will be ignored.
2553 if (deviceWidth < 0 && deviceHeight < 0) {
2554 QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0);
2555 deviceWidth = size.width();
2556 deviceHeight = size.height();
2557 }
2558
2559 WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, qt_defaultDpi(), availableSize);
2560
2561 result.m_isValid = true;
2562 result.m_size = conf.layoutSize;
2563 result.m_initialScaleFactor = conf.initialScale;
2564 result.m_minimumScaleFactor = conf.minimumScale;
2565 result.m_maximumScaleFactor = conf.maximumScale;
2566 result.m_devicePixelRatio = conf.devicePixelRatio;
2567 result.m_isUserScalable = static_cast<bool>(conf.userScalable);
2568
2569 d->pixelRatio = conf.devicePixelRatio;
2570
2571 return result;
2572 }
2573
preferredContentsSize() const2574 QSize QWebPage::preferredContentsSize() const
2575 {
2576 QWebFrame* frame = d->mainFrame;
2577 if (frame) {
2578 WebCore::FrameView* view = frame->d->frame->view();
2579 if (view && view->useFixedLayout())
2580 return d->mainFrame->d->frame->view()->fixedLayoutSize();
2581 }
2582
2583 return d->fixedLayoutSize;
2584 }
2585
2586 /*!
2587 \property QWebPage::preferredContentsSize
2588 \since 4.6
2589 \brief a custom size used for laying out the page contents.
2590
2591 By default all pages are laid out using the viewport of the page as the base.
2592
2593 As pages mostly are designed for desktop usage, they often do not layout properly
2594 on small devices as the contents require a certain view width. For this reason
2595 it is common to use a different layout size and then scale the contents to fit
2596 within the actual view.
2597
2598 If this property is set to a valid size, this size is used for all layout needs
2599 instead of the size of the viewport.
2600
2601 Setting an invalid size, makes the page fall back to using the viewport size for layout.
2602
2603 \sa viewportSize
2604 */
setPreferredContentsSize(const QSize & size) const2605 void QWebPage::setPreferredContentsSize(const QSize& size) const
2606 {
2607 // FIXME: Rename this method to setCustomLayoutSize
2608
2609 d->fixedLayoutSize = size;
2610
2611 QWebFrame* frame = mainFrame();
2612 if (!frame->d->frame || !frame->d->frame->view())
2613 return;
2614
2615 WebCore::FrameView* view = frame->d->frame->view();
2616
2617 if (size.isValid()) {
2618 view->setUseFixedLayout(true);
2619 view->setFixedLayoutSize(size);
2620 } else if (view->useFixedLayout())
2621 view->setUseFixedLayout(false);
2622
2623 view->layout();
2624 }
2625
2626 /*
2627 This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2628 scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2629 the application to pan the actual view, which then resizes itself to the size of the contents.
2630
2631 \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2632 again, call this method with an empty rect.
2633
2634 \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2635 */
setActualVisibleContentRect(const QRect & rect) const2636 void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2637 {
2638 QWebFrame* frame = mainFrame();
2639 if (!frame->d->frame || !frame->d->frame->view())
2640 return;
2641
2642 WebCore::FrameView* view = frame->d->frame->view();
2643 view->setActualVisibleContentRect(rect);
2644 }
2645
2646 /*!
2647 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2648
2649 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2650 the specified navigation type \a type.
2651
2652 If \a frame is a null pointer then navigation to a new window is requested. If the request is
2653 accepted createWindow() will be called.
2654
2655 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2656 to let QWebPage handle the navigation itself.
2657
2658 \sa createWindow()
2659 */
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)2660 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2661 {
2662 Q_UNUSED(frame)
2663 if (type == NavigationTypeLinkClicked) {
2664 switch (d->linkPolicy) {
2665 case DontDelegateLinks:
2666 return true;
2667
2668 case DelegateExternalLinks:
2669 if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2670 return true;
2671 emit linkClicked(request.url());
2672 return false;
2673
2674 case DelegateAllLinks:
2675 emit linkClicked(request.url());
2676 return false;
2677 }
2678 }
2679 return true;
2680 }
2681
2682 /*!
2683 \property QWebPage::hasSelection
2684 \brief whether this page contains selected content or not.
2685
2686 \sa selectionChanged()
2687 */
hasSelection() const2688 bool QWebPage::hasSelection() const
2689 {
2690 d->createMainFrame();
2691 WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2692 if (frame)
2693 return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
2694 return false;
2695 }
2696
2697 /*!
2698 \property QWebPage::selectedText
2699 \brief the text currently selected
2700
2701 By default, this property contains an empty string.
2702
2703 \sa selectionChanged(), selectedHtml()
2704 */
selectedText() const2705 QString QWebPage::selectedText() const
2706 {
2707 d->createMainFrame();
2708 WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2709 if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection)
2710 return QString();
2711 return frame->editor()->selectedText();
2712 }
2713
2714 /*!
2715 \since 4.8
2716 \property QWebPage::selectedHtml
2717 \brief the HTML currently selected
2718
2719 By default, this property contains an empty string.
2720
2721 \sa selectionChanged(), selectedText()
2722 */
selectedHtml() const2723 QString QWebPage::selectedHtml() const
2724 {
2725 d->createMainFrame();
2726 return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML();
2727 }
2728
2729 #ifndef QT_NO_ACTION
2730 /*!
2731 Returns a QAction for the specified WebAction \a action.
2732
2733 The action is owned by the QWebPage but you can customize the look by
2734 changing its properties.
2735
2736 QWebPage also takes care of implementing the action, so that upon
2737 triggering the corresponding action is performed on the page.
2738
2739 \sa triggerAction()
2740 */
action(WebAction action) const2741 QAction *QWebPage::action(WebAction action) const
2742 {
2743 if (action == QWebPage::NoWebAction) return 0;
2744 if (d->actions[action])
2745 return d->actions[action];
2746
2747 QString text;
2748 QIcon icon;
2749 QStyle *style = d->client ? d->client->style() : qApp->style();
2750 bool checkable = false;
2751
2752 switch (action) {
2753 case OpenLink:
2754 text = contextMenuItemTagOpenLink();
2755 break;
2756 case OpenLinkInNewWindow:
2757 text = contextMenuItemTagOpenLinkInNewWindow();
2758 break;
2759 case OpenFrameInNewWindow:
2760 text = contextMenuItemTagOpenFrameInNewWindow();
2761 break;
2762
2763 case DownloadLinkToDisk:
2764 text = contextMenuItemTagDownloadLinkToDisk();
2765 break;
2766 case CopyLinkToClipboard:
2767 text = contextMenuItemTagCopyLinkToClipboard();
2768 break;
2769
2770 case OpenImageInNewWindow:
2771 text = contextMenuItemTagOpenImageInNewWindow();
2772 break;
2773 case DownloadImageToDisk:
2774 text = contextMenuItemTagDownloadImageToDisk();
2775 break;
2776 case CopyImageToClipboard:
2777 text = contextMenuItemTagCopyImageToClipboard();
2778 break;
2779 case CopyImageUrlToClipboard:
2780 text = contextMenuItemTagCopyImageUrlToClipboard();
2781 break;
2782
2783 case Back:
2784 text = contextMenuItemTagGoBack();
2785 icon = style->standardIcon(QStyle::SP_ArrowBack);
2786 break;
2787 case Forward:
2788 text = contextMenuItemTagGoForward();
2789 icon = style->standardIcon(QStyle::SP_ArrowForward);
2790 break;
2791 case Stop:
2792 text = contextMenuItemTagStop();
2793 icon = style->standardIcon(QStyle::SP_BrowserStop);
2794 break;
2795 case Reload:
2796 text = contextMenuItemTagReload();
2797 icon = style->standardIcon(QStyle::SP_BrowserReload);
2798 break;
2799
2800 case Cut:
2801 text = contextMenuItemTagCut();
2802 break;
2803 case Copy:
2804 text = contextMenuItemTagCopy();
2805 break;
2806 case Paste:
2807 text = contextMenuItemTagPaste();
2808 break;
2809 case SelectAll:
2810 text = contextMenuItemTagSelectAll();
2811 break;
2812 #ifndef QT_NO_UNDOSTACK
2813 case Undo: {
2814 QAction *a = undoStack()->createUndoAction(d->q);
2815 d->actions[action] = a;
2816 return a;
2817 }
2818 case Redo: {
2819 QAction *a = undoStack()->createRedoAction(d->q);
2820 d->actions[action] = a;
2821 return a;
2822 }
2823 #endif // QT_NO_UNDOSTACK
2824 case MoveToNextChar:
2825 text = tr("Move the cursor to the next character");
2826 break;
2827 case MoveToPreviousChar:
2828 text = tr("Move the cursor to the previous character");
2829 break;
2830 case MoveToNextWord:
2831 text = tr("Move the cursor to the next word");
2832 break;
2833 case MoveToPreviousWord:
2834 text = tr("Move the cursor to the previous word");
2835 break;
2836 case MoveToNextLine:
2837 text = tr("Move the cursor to the next line");
2838 break;
2839 case MoveToPreviousLine:
2840 text = tr("Move the cursor to the previous line");
2841 break;
2842 case MoveToStartOfLine:
2843 text = tr("Move the cursor to the start of the line");
2844 break;
2845 case MoveToEndOfLine:
2846 text = tr("Move the cursor to the end of the line");
2847 break;
2848 case MoveToStartOfBlock:
2849 text = tr("Move the cursor to the start of the block");
2850 break;
2851 case MoveToEndOfBlock:
2852 text = tr("Move the cursor to the end of the block");
2853 break;
2854 case MoveToStartOfDocument:
2855 text = tr("Move the cursor to the start of the document");
2856 break;
2857 case MoveToEndOfDocument:
2858 text = tr("Move the cursor to the end of the document");
2859 break;
2860 case SelectNextChar:
2861 text = tr("Select to the next character");
2862 break;
2863 case SelectPreviousChar:
2864 text = tr("Select to the previous character");
2865 break;
2866 case SelectNextWord:
2867 text = tr("Select to the next word");
2868 break;
2869 case SelectPreviousWord:
2870 text = tr("Select to the previous word");
2871 break;
2872 case SelectNextLine:
2873 text = tr("Select to the next line");
2874 break;
2875 case SelectPreviousLine:
2876 text = tr("Select to the previous line");
2877 break;
2878 case SelectStartOfLine:
2879 text = tr("Select to the start of the line");
2880 break;
2881 case SelectEndOfLine:
2882 text = tr("Select to the end of the line");
2883 break;
2884 case SelectStartOfBlock:
2885 text = tr("Select to the start of the block");
2886 break;
2887 case SelectEndOfBlock:
2888 text = tr("Select to the end of the block");
2889 break;
2890 case SelectStartOfDocument:
2891 text = tr("Select to the start of the document");
2892 break;
2893 case SelectEndOfDocument:
2894 text = tr("Select to the end of the document");
2895 break;
2896 case DeleteStartOfWord:
2897 text = tr("Delete to the start of the word");
2898 break;
2899 case DeleteEndOfWord:
2900 text = tr("Delete to the end of the word");
2901 break;
2902
2903 case SetTextDirectionDefault:
2904 text = contextMenuItemTagDefaultDirection();
2905 break;
2906 case SetTextDirectionLeftToRight:
2907 text = contextMenuItemTagLeftToRight();
2908 checkable = true;
2909 break;
2910 case SetTextDirectionRightToLeft:
2911 text = contextMenuItemTagRightToLeft();
2912 checkable = true;
2913 break;
2914
2915 case ToggleBold:
2916 text = contextMenuItemTagBold();
2917 checkable = true;
2918 break;
2919 case ToggleItalic:
2920 text = contextMenuItemTagItalic();
2921 checkable = true;
2922 break;
2923 case ToggleUnderline:
2924 text = contextMenuItemTagUnderline();
2925 checkable = true;
2926 break;
2927
2928 case InspectElement:
2929 text = contextMenuItemTagInspectElement();
2930 break;
2931
2932 case InsertParagraphSeparator:
2933 text = tr("Insert a new paragraph");
2934 break;
2935 case InsertLineSeparator:
2936 text = tr("Insert a new line");
2937 break;
2938
2939 case PasteAndMatchStyle:
2940 text = tr("Paste and Match Style");
2941 break;
2942 case RemoveFormat:
2943 text = tr("Remove formatting");
2944 break;
2945
2946 case ToggleStrikethrough:
2947 text = tr("Strikethrough");
2948 checkable = true;
2949 break;
2950 case ToggleSubscript:
2951 text = tr("Subscript");
2952 checkable = true;
2953 break;
2954 case ToggleSuperscript:
2955 text = tr("Superscript");
2956 checkable = true;
2957 break;
2958 case InsertUnorderedList:
2959 text = tr("Insert Bulleted List");
2960 checkable = true;
2961 break;
2962 case InsertOrderedList:
2963 text = tr("Insert Numbered List");
2964 checkable = true;
2965 break;
2966 case Indent:
2967 text = tr("Indent");
2968 break;
2969 case Outdent:
2970 text = tr("Outdent");
2971 break;
2972 case AlignCenter:
2973 text = tr("Center");
2974 break;
2975 case AlignJustified:
2976 text = tr("Justify");
2977 break;
2978 case AlignLeft:
2979 text = tr("Align Left");
2980 break;
2981 case AlignRight:
2982 text = tr("Align Right");
2983 break;
2984 case NoWebAction:
2985 return 0;
2986 default:
2987 break;
2988 }
2989
2990 if (text.isEmpty())
2991 return 0;
2992
2993 QAction *a = new QAction(d->q);
2994 a->setText(text);
2995 a->setData(action);
2996 a->setCheckable(checkable);
2997 a->setIcon(icon);
2998
2999 connect(a, SIGNAL(triggered(bool)),
3000 this, SLOT(_q_webActionTriggered(bool)));
3001
3002 d->actions[action] = a;
3003 d->updateAction(action);
3004 return a;
3005 }
3006 #endif // QT_NO_ACTION
3007
3008 /*!
3009 \property QWebPage::modified
3010 \brief whether the page contains unsubmitted form data, or the contents have been changed.
3011
3012 By default, this property is false.
3013
3014 \sa contentsChanged(), contentEditable, undoStack()
3015 */
isModified() const3016 bool QWebPage::isModified() const
3017 {
3018 #ifdef QT_NO_UNDOSTACK
3019 return false;
3020 #else
3021 if (!d->undoStack)
3022 return false;
3023 return d->undoStack->canUndo();
3024 #endif // QT_NO_UNDOSTACK
3025 }
3026
3027 #ifndef QT_NO_UNDOSTACK
3028 /*!
3029 Returns a pointer to the undo stack used for editable content.
3030
3031 \sa modified
3032 */
undoStack() const3033 QUndoStack *QWebPage::undoStack() const
3034 {
3035 if (!d->undoStack)
3036 d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
3037
3038 return d->undoStack;
3039 }
3040 #endif // QT_NO_UNDOSTACK
3041
3042 /*! \reimp
3043 */
event(QEvent * ev)3044 bool QWebPage::event(QEvent *ev)
3045 {
3046 switch (ev->type()) {
3047 case QEvent::Timer:
3048 d->timerEvent(static_cast<QTimerEvent*>(ev));
3049 break;
3050 case QEvent::MouseMove:
3051 d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
3052 break;
3053 case QEvent::MouseButtonPress:
3054 d->mousePressEvent(static_cast<QMouseEvent*>(ev));
3055 break;
3056 case QEvent::MouseButtonDblClick:
3057 d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
3058 break;
3059 case QEvent::MouseButtonRelease:
3060 d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
3061 break;
3062 #if !defined(QT_NO_GRAPHICSVIEW)
3063 case QEvent::GraphicsSceneMouseMove:
3064 d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3065 break;
3066 case QEvent::GraphicsSceneMousePress:
3067 d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3068 break;
3069 case QEvent::GraphicsSceneMouseDoubleClick:
3070 d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3071 break;
3072 case QEvent::GraphicsSceneMouseRelease:
3073 d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3074 break;
3075 #endif
3076 #ifndef QT_NO_CONTEXTMENU
3077 case QEvent::ContextMenu:
3078 d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
3079 break;
3080 #if !defined(QT_NO_GRAPHICSVIEW)
3081 case QEvent::GraphicsSceneContextMenu:
3082 d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
3083 break;
3084 #endif
3085 #endif
3086 #ifndef QT_NO_WHEELEVENT
3087 case QEvent::Wheel:
3088 d->wheelEvent(static_cast<QWheelEvent*>(ev));
3089 break;
3090 #if !defined(QT_NO_GRAPHICSVIEW)
3091 case QEvent::GraphicsSceneWheel:
3092 d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
3093 break;
3094 #endif
3095 #endif
3096 case QEvent::KeyPress:
3097 d->keyPressEvent(static_cast<QKeyEvent*>(ev));
3098 break;
3099 case QEvent::KeyRelease:
3100 d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
3101 break;
3102 case QEvent::FocusIn:
3103 d->focusInEvent(static_cast<QFocusEvent*>(ev));
3104 break;
3105 case QEvent::FocusOut:
3106 d->focusOutEvent(static_cast<QFocusEvent*>(ev));
3107 break;
3108 #ifndef QT_NO_DRAGANDDROP
3109 case QEvent::DragEnter:
3110 d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
3111 break;
3112 case QEvent::DragLeave:
3113 d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
3114 break;
3115 case QEvent::DragMove:
3116 d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
3117 break;
3118 case QEvent::Drop:
3119 d->dropEvent(static_cast<QDropEvent*>(ev));
3120 break;
3121 #if !defined(QT_NO_GRAPHICSVIEW)
3122 case QEvent::GraphicsSceneDragEnter:
3123 d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3124 break;
3125 case QEvent::GraphicsSceneDragMove:
3126 d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3127 break;
3128 case QEvent::GraphicsSceneDragLeave:
3129 d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3130 break;
3131 case QEvent::GraphicsSceneDrop:
3132 d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3133 break;
3134 #endif
3135
3136 #endif
3137 case QEvent::InputMethod:
3138 d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
3139 break;
3140 case QEvent::ShortcutOverride:
3141 d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
3142 break;
3143 case QEvent::Leave:
3144 d->leaveEvent(ev);
3145 break;
3146 case QEvent::TouchBegin:
3147 case QEvent::TouchUpdate:
3148 case QEvent::TouchEnd:
3149 // Return whether the default action was cancelled in the JS event handler
3150 return d->touchEvent(static_cast<QTouchEvent*>(ev));
3151 #ifndef QT_NO_PROPERTIES
3152 case QEvent::DynamicPropertyChange:
3153 d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev));
3154 break;
3155 #endif
3156 default:
3157 return QObject::event(ev);
3158 }
3159
3160 return true;
3161 }
3162
3163 /*!
3164 Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element
3165 if \a next is true; otherwise the previous element is focused.
3166
3167 Returns true if it can find a new focusable element, or false if it can't.
3168 */
focusNextPrevChild(bool next)3169 bool QWebPage::focusNextPrevChild(bool next)
3170 {
3171 QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
3172 d->keyPressEvent(&ev);
3173 bool hasFocusedNode = false;
3174 Frame *frame = d->page->focusController()->focusedFrame();
3175 if (frame) {
3176 Document *document = frame->document();
3177 hasFocusedNode = document && document->focusedNode();
3178 }
3179 //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
3180 return hasFocusedNode;
3181 }
3182
3183 /*!
3184 \property QWebPage::contentEditable
3185 \brief whether the content in this QWebPage is editable or not
3186 \since 4.5
3187
3188 If this property is enabled the contents of the page can be edited by the user through a visible
3189 cursor. If disabled (the default) only HTML elements in the web page with their
3190 \c{contenteditable} attribute set are editable.
3191
3192 \sa modified, contentsChanged(), WebAction
3193 */
setContentEditable(bool editable)3194 void QWebPage::setContentEditable(bool editable)
3195 {
3196 if (isContentEditable() != editable) {
3197 d->page->setEditable(editable);
3198 d->page->setTabKeyCyclesThroughElements(!editable);
3199 if (d->mainFrame) {
3200 WebCore::Frame* frame = d->mainFrame->d->frame;
3201 if (editable) {
3202 frame->editor()->applyEditingStyleToBodyElement();
3203 // FIXME: mac port calls this if there is no selectedDOMRange
3204 //frame->setSelectionFromNone();
3205 }
3206 }
3207
3208 d->updateEditorActions();
3209 }
3210 }
3211
isContentEditable() const3212 bool QWebPage::isContentEditable() const
3213 {
3214 return d->page->isEditable();
3215 }
3216
setDevicePixelRatio(qreal devicePixelRatio)3217 void QWebPage::setDevicePixelRatio(qreal devicePixelRatio)
3218 {
3219 d->pixelRatio = devicePixelRatio;
3220 }
3221
3222 /*!
3223 \property QWebPage::forwardUnsupportedContent
3224 \brief whether QWebPage should forward unsupported content
3225
3226 If enabled, the unsupportedContent() signal is emitted with a network reply that
3227 can be used to read the content.
3228
3229 If disabled, the download of such content is aborted immediately.
3230
3231 By default unsupported content is not forwarded.
3232 */
3233
setForwardUnsupportedContent(bool forward)3234 void QWebPage::setForwardUnsupportedContent(bool forward)
3235 {
3236 d->forwardUnsupportedContent = forward;
3237 }
3238
forwardUnsupportedContent() const3239 bool QWebPage::forwardUnsupportedContent() const
3240 {
3241 return d->forwardUnsupportedContent;
3242 }
3243
3244 /*!
3245 \property QWebPage::linkDelegationPolicy
3246 \brief how QWebPage should delegate the handling of links through the
3247 linkClicked() signal
3248
3249 The default is to delegate no links.
3250 */
3251
setLinkDelegationPolicy(LinkDelegationPolicy policy)3252 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
3253 {
3254 d->linkPolicy = policy;
3255 }
3256
linkDelegationPolicy() const3257 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
3258 {
3259 return d->linkPolicy;
3260 }
3261
3262 #ifndef QT_NO_CONTEXTMENU
3263 /*!
3264 Filters the context menu event, \a event, through handlers for scrollbars and
3265 custom event handlers in the web page. Returns true if the event was handled;
3266 otherwise false.
3267
3268 A web page may swallow a context menu event through a custom event handler, allowing for context
3269 menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
3270 Maps}, for example.
3271 */
swallowContextMenuEvent(QContextMenuEvent * event)3272 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
3273 {
3274 d->page->contextMenuController()->clearContextMenu();
3275
3276 if (QWebFrame* webFrame = frameAt(event->pos())) {
3277 Frame* frame = QWebFramePrivate::core(webFrame);
3278 if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
3279 return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
3280 }
3281
3282 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3283 focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
3284 ContextMenu *menu = d->page->contextMenuController()->contextMenu();
3285 // If the website defines its own handler then sendContextMenuEvent takes care of
3286 // calling/showing it and the context menu pointer will be zero. This is the case
3287 // on maps.google.com for example.
3288
3289 return !menu;
3290 }
3291 #endif // QT_NO_CONTEXTMENU
3292
3293 /*!
3294 Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
3295 element the CopyImageToClipboard action is enabled.
3296 */
updatePositionDependentActions(const QPoint & pos)3297 void QWebPage::updatePositionDependentActions(const QPoint &pos)
3298 {
3299 #ifndef QT_NO_ACTION
3300 // First we disable all actions, but keep track of which ones were originally enabled.
3301 QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
3302 for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
3303 QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
3304 if (QAction *a = this->action(action)) {
3305 originallyEnabledWebActions.setBit(action, a->isEnabled());
3306 a->setEnabled(false);
3307 }
3308 }
3309 #endif // QT_NO_ACTION
3310
3311 d->createMainFrame();
3312 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3313 HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
3314
3315 if (result.scrollbar())
3316 d->hitTestResult = QWebHitTestResult();
3317 else
3318 d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
3319
3320 d->page->contextMenuController()->setHitTestResult(result);
3321 d->page->contextMenuController()->populate();
3322
3323 #if ENABLE(INSPECTOR)
3324 if (d->page->inspectorController()->enabled())
3325 d->page->contextMenuController()->addInspectElementItem();
3326 #endif
3327
3328 QBitArray visitedWebActions(QWebPage::WebActionCount);
3329
3330 #ifndef QT_NO_CONTEXTMENU
3331 delete d->currentContextMenu;
3332
3333 // Then we let createContextMenu() enable the actions that are put into the menu
3334 d->currentContextMenu = d->createContextMenu(d->page->contextMenuController()->contextMenu(), d->page->contextMenuController()->contextMenu()->platformDescription(), &visitedWebActions);
3335 #endif // QT_NO_CONTEXTMENU
3336
3337 #ifndef QT_NO_ACTION
3338 // Finally, we restore the original enablement for the actions that were not put into the menu.
3339 originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
3340 for (int i = 0; i < QWebPage::WebActionCount; ++i) {
3341 if (originallyEnabledWebActions.at(i)) {
3342 if (QAction *a = this->action(QWebPage::WebAction(i)))
3343 a->setEnabled(true);
3344 }
3345 }
3346 #endif // QT_NO_ACTION
3347
3348 // This whole process ensures that any actions put into to the context menu has the right
3349 // enablement, while also keeping the correct enablement for actions that were left out of
3350 // the menu.
3351
3352 }
3353
3354
3355
3356 /*!
3357 \enum QWebPage::Extension
3358
3359 This enum describes the types of extensions that the page can support. Before using these extensions, you
3360 should verify that the extension is supported by calling supportsExtension().
3361
3362 \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
3363 This extension is invoked when the web content requests one or more file names, for example
3364 as a result of the user clicking on a "file upload" button in a HTML form where multiple
3365 file selection is allowed.
3366
3367 \value ErrorPageExtension Whether the web page can provide an error page when loading fails.
3368 (introduced in Qt 4.6)
3369
3370 \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn
3371 */
3372
3373 /*!
3374 \enum QWebPage::ErrorDomain
3375 \since 4.6
3376
3377 This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred).
3378
3379 \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError.
3380 \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute).
3381 \value WebKit The error is an internal WebKit error.
3382 */
3383
3384 /*!
3385 \class QWebPage::ExtensionOption
3386 \since 4.4
3387 \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
3388
3389 \inmodule QtWebKit
3390
3391 \sa QWebPage::extension() QWebPage::ExtensionReturn
3392 */
3393
3394
3395 /*!
3396 \class QWebPage::ExtensionReturn
3397 \since 4.4
3398 \brief The ExtensionReturn class provides an output result from a QWebPage's extension.
3399
3400 \inmodule QtWebKit
3401
3402 \sa QWebPage::extension() QWebPage::ExtensionOption
3403 */
3404
3405 /*!
3406 \class QWebPage::ErrorPageExtensionOption
3407 \since 4.6
3408 \brief The ErrorPageExtensionOption class describes the option
3409 for the error page extension.
3410
3411 \inmodule QtWebKit
3412
3413 The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as
3414 the associated \a frame.
3415
3416 The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
3417
3418 \sa QWebPage::extension() QWebPage::ErrorPageExtensionReturn
3419 */
3420
3421 /*!
3422 \variable QWebPage::ErrorPageExtensionOption::url
3423 \brief the url for which an error occurred
3424 */
3425
3426 /*!
3427 \variable QWebPage::ErrorPageExtensionOption::frame
3428 \brief the frame associated with the error
3429 */
3430
3431 /*!
3432 \variable QWebPage::ErrorPageExtensionOption::domain
3433 \brief the domain that reported the error
3434 */
3435
3436 /*!
3437 \variable QWebPage::ErrorPageExtensionOption::error
3438 \brief the error code. Interpretation of the value depends on the \a domain
3439 \sa QWebPage::ErrorDomain
3440 */
3441
3442 /*!
3443 \variable QWebPage::ErrorPageExtensionOption::errorString
3444 \brief a string that describes the error
3445 */
3446
3447 /*!
3448 \class QWebPage::ErrorPageExtensionReturn
3449 \since 4.6
3450 \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
3451 frame for which the error occured.
3452
3453 \inmodule QtWebKit
3454
3455 The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
3456 optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
3457 is assumed to be UTF-8 if not indicated otherwise.
3458
3459 The error page is stored in the \a content byte array, as HTML content. In order to convert a
3460 QString to a byte array, the QString::toUtf8() method can be used.
3461
3462 External objects such as stylesheets or images referenced in the HTML are located relative to
3463 \a baseUrl.
3464
3465 \sa QWebPage::extension() QWebPage::ErrorPageExtensionOption, QString::toUtf8()
3466 */
3467
3468 /*!
3469 \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
3470
3471 Constructs a new error page object.
3472 */
3473
3474
3475 /*!
3476 \variable QWebPage::ErrorPageExtensionReturn::contentType
3477 \brief the error page's content type
3478 */
3479
3480 /*!
3481 \variable QWebPage::ErrorPageExtensionReturn::encoding
3482 \brief the error page encoding
3483 */
3484
3485 /*!
3486 \variable QWebPage::ErrorPageExtensionReturn::baseUrl
3487 \brief the base url
3488
3489 External objects such as stylesheets or images referenced in the HTML are located relative to this url.
3490 */
3491
3492 /*!
3493 \variable QWebPage::ErrorPageExtensionReturn::content
3494 \brief the HTML content of the error page
3495 */
3496
3497 /*!
3498 \class QWebPage::ChooseMultipleFilesExtensionOption
3499 \since 4.5
3500 \brief The ChooseMultipleFilesExtensionOption class describes the option
3501 for the multiple files selection extension.
3502
3503 \inmodule QtWebKit
3504
3505 The ChooseMultipleFilesExtensionOption class holds the frame originating the request
3506 and the suggested filenames which might be provided.
3507
3508 \sa QWebPage::extension() QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
3509 */
3510
3511 /*!
3512 \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame
3513 \brief The frame in which the request originated
3514 */
3515
3516 /*!
3517 \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames
3518 \brief The suggested filenames
3519 */
3520
3521 /*!
3522 \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames
3523 \brief The selected filenames
3524 */
3525
3526 /*!
3527 \class QWebPage::ChooseMultipleFilesExtensionReturn
3528 \since 4.5
3529 \brief The ChooseMultipleFilesExtensionReturn describes the return value
3530 for the multiple files selection extension.
3531
3532 \inmodule QtWebKit
3533
3534 The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
3535 when the extension is invoked.
3536
3537 \sa QWebPage::extension() QWebPage::ChooseMultipleFilesExtensionOption
3538 */
3539
3540 /*!
3541 This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
3542 argument is provided as input to the extension; the output results can be stored in \a output.
3543
3544 The behavior of this function is determined by \a extension. The \a option
3545 and \a output values are typically casted to the corresponding types (for
3546 example, ChooseMultipleFilesExtensionOption and
3547 ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension).
3548
3549 You can call supportsExtension() to check if an extension is supported by the page.
3550
3551 Returns true if the extension was called successfully; otherwise returns false.
3552
3553 \sa supportsExtension(), Extension
3554 */
extension(Extension extension,const ExtensionOption * option,ExtensionReturn * output)3555 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
3556 {
3557 #ifndef QT_NO_FILEDIALOG
3558 if (extension == ChooseMultipleFilesExtension) {
3559 // FIXME: do not ignore suggestedFiles
3560 QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
3561 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3562 QStringList names = QFileDialog::getOpenFileNames(parent, QString::null);
3563 static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
3564 return true;
3565 }
3566 #endif
3567
3568 return false;
3569 }
3570
3571 /*!
3572 This virtual function returns true if the web page supports \a extension; otherwise false is returned.
3573
3574 \sa extension()
3575 */
supportsExtension(Extension extension) const3576 bool QWebPage::supportsExtension(Extension extension) const
3577 {
3578 #ifndef QT_NO_FILEDIALOG
3579 return extension == ChooseMultipleFilesExtension;
3580 #else
3581 Q_UNUSED(extension);
3582 return false;
3583 #endif
3584 }
3585
3586 /*!
3587 Finds the specified string, \a subString, in the page, using the given \a options.
3588
3589 If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
3590 that exist in the page. All subsequent calls will extend the highlight, rather than
3591 replace it, with occurrences of the new string.
3592
3593 If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
3594 and all subsequent calls will replace the current occurrence with the next one.
3595
3596 To clear the selection, just pass an empty string.
3597
3598 Returns true if \a subString was found; otherwise returns false.
3599 */
findText(const QString & subString,FindFlags options)3600 bool QWebPage::findText(const QString &subString, FindFlags options)
3601 {
3602 ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
3603 if (options & FindCaseSensitively)
3604 caseSensitivity = ::TextCaseSensitive;
3605
3606 if (options & HighlightAllOccurrences) {
3607 if (subString.isEmpty()) {
3608 d->page->unmarkAllTextMatches();
3609 return true;
3610 } else
3611 return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
3612 } else {
3613 if (subString.isEmpty()) {
3614 d->page->mainFrame()->selection()->clear();
3615 Frame* frame = d->page->mainFrame()->tree()->firstChild();
3616 while (frame) {
3617 frame->selection()->clear();
3618 frame = frame->tree()->traverseNextWithWrap(false);
3619 }
3620 }
3621 ::FindDirection direction = ::FindDirectionForward;
3622 if (options & FindBackward)
3623 direction = ::FindDirectionBackward;
3624
3625 const bool shouldWrap = options & FindWrapsAroundDocument;
3626
3627 return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3628 }
3629 }
3630
3631 /*!
3632 Returns a pointer to the page's settings object.
3633
3634 \sa QWebSettings::globalSettings()
3635 */
settings() const3636 QWebSettings *QWebPage::settings() const
3637 {
3638 return d->settings;
3639 }
3640
3641 /*!
3642 This function is called when the web content requests a file name, for example
3643 as a result of the user clicking on a "file upload" button in a HTML form.
3644
3645 A suggested filename may be provided in \a suggestedFile. The frame originating the
3646 request is provided as \a parentFrame.
3647
3648 \sa ChooseMultipleFilesExtension
3649 */
chooseFile(QWebFrame * parentFrame,const QString & suggestedFile)3650 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3651 {
3652 Q_UNUSED(parentFrame)
3653 #ifndef QT_NO_FILEDIALOG
3654 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3655 return QFileDialog::getOpenFileName(parent, QString::null, suggestedFile);
3656 #else
3657 return QString::null;
3658 #endif
3659 }
3660
3661 /*!
3662 Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3663 QWebPage.
3664
3665 \note It is currently not supported to change the network access manager after the
3666 QWebPage has used it. The results of doing this are undefined.
3667
3668 \sa networkAccessManager()
3669 */
setNetworkAccessManager(QNetworkAccessManager * manager)3670 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3671 {
3672 if (manager == d->networkManager)
3673 return;
3674 if (d->networkManager && d->networkManager->parent() == this)
3675 delete d->networkManager;
3676 d->networkManager = manager;
3677 }
3678
3679 /*!
3680 Returns the QNetworkAccessManager that is responsible for serving network
3681 requests for this QWebPage.
3682
3683 \sa setNetworkAccessManager()
3684 */
networkAccessManager() const3685 QNetworkAccessManager *QWebPage::networkAccessManager() const
3686 {
3687 if (!d->networkManager) {
3688 QWebPage *that = const_cast<QWebPage *>(this);
3689 that->d->networkManager = new QNetworkAccessManager(that);
3690 }
3691 return d->networkManager;
3692 }
3693
3694 /*!
3695 Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3696 QWebPage.
3697
3698 Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3699
3700 \sa pluginFactory()
3701 */
setPluginFactory(QWebPluginFactory * factory)3702 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3703 {
3704 d->pluginFactory = factory;
3705 }
3706
3707 /*!
3708 Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3709 this QWebPage. If no plugin factory is installed a null pointer is returned.
3710
3711 \sa setPluginFactory()
3712 */
pluginFactory() const3713 QWebPluginFactory *QWebPage::pluginFactory() const
3714 {
3715 return d->pluginFactory;
3716 }
3717
3718 /*!
3719 This function is called when a user agent for HTTP requests is needed. You can reimplement this
3720 function to dynamically return different user agents for different URLs, based on the \a url parameter.
3721
3722 The default implementation returns the following value:
3723
3724 "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3725
3726 On mobile platforms such as Symbian S60 and Maemo, "Mobile Safari" is used instead of "Safari".
3727
3728 In this string the following values are replaced at run-time:
3729 \list
3730 \o %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; ").
3731 \o %Security% expands to "N; " if SSL is disabled.
3732 \o %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5").
3733 \o %WebKitVersion% is the version of WebKit the application was compiled against.
3734 \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3735 \endlist
3736 */
userAgentForUrl(const QUrl &) const3737 QString QWebPage::userAgentForUrl(const QUrl&) const
3738 {
3739 // splitting the string in three and user QStringBuilder is better than using QString::arg()
3740 static QString firstPart;
3741 static QString secondPart;
3742 static QString thirdPart;
3743
3744 if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) {
3745 QString firstPartTemp;
3746 firstPartTemp.reserve(150);
3747 firstPartTemp += QString::fromLatin1("Mozilla/5.0 ("
3748
3749 // Platform
3750 #ifdef Q_WS_MAC
3751 "Macintosh; "
3752 #elif defined Q_WS_QWS
3753 "QtEmbedded; "
3754 #elif defined Q_WS_MAEMO_5
3755 "Maemo"
3756 #elif defined Q_WS_MAEMO_6
3757 "MeeGo"
3758 #elif defined Q_WS_WIN
3759 // Nothing
3760 #elif defined Q_WS_X11
3761 "X11; "
3762 #elif defined Q_OS_SYMBIAN
3763 "Symbian"
3764 #else
3765 "Unknown; "
3766 #endif
3767 );
3768
3769 #if defined Q_OS_SYMBIAN
3770 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3771 switch (symbianVersion) {
3772 case QSysInfo::SV_9_2:
3773 firstPartTemp += QString::fromLatin1("OS/9.2; ");
3774 break;
3775 case QSysInfo::SV_9_3:
3776 firstPartTemp += QString::fromLatin1("OS/9.3; ");
3777 break;
3778 case QSysInfo::SV_9_4:
3779 firstPartTemp += QString::fromLatin1("OS/9.4; ");
3780 break;
3781 case QSysInfo::SV_SF_2:
3782 firstPartTemp += QString::fromLatin1("/2; ");
3783 break;
3784 case QSysInfo::SV_SF_3:
3785 firstPartTemp += QString::fromLatin1("/3; ");
3786 break;
3787 case QSysInfo::SV_SF_4:
3788 firstPartTemp += QString::fromLatin1("/4; ");
3789 break;
3790 default:
3791 firstPartTemp += QString::fromLatin1("; ");
3792 break;
3793 }
3794 #endif
3795
3796 #if defined(QT_NO_OPENSSL)
3797 // No SSL support
3798 firstPartTemp += QString::fromLatin1("N; ");
3799 #endif
3800
3801 // Operating system
3802 #ifdef Q_OS_AIX
3803 firstPartTemp += QString::fromLatin1("AIX");
3804 #elif defined Q_OS_WIN32
3805 firstPartTemp += windowsVersionForUAString();
3806 #elif defined Q_OS_DARWIN
3807 #if CPU(X86) || CPU(X86_64)
3808 firstPartTemp += QString::fromLatin1("Intel Mac OS X");
3809 #else
3810 firstPartTemp += QString::fromLatin1("PPC Mac OS X");
3811 #endif
3812
3813 #elif defined Q_OS_BSDI
3814 firstPartTemp += QString::fromLatin1("BSD");
3815 #elif defined Q_OS_BSD4
3816 firstPartTemp += QString::fromLatin1("BSD Four");
3817 #elif defined Q_OS_CYGWIN
3818 firstPartTemp += QString::fromLatin1("Cygwin");
3819 #elif defined Q_OS_DGUX
3820 firstPartTemp += QString::fromLatin1("DG/UX");
3821 #elif defined Q_OS_DYNIX
3822 firstPartTemp += QString::fromLatin1("DYNIX/ptx");
3823 #elif defined Q_OS_FREEBSD
3824 firstPartTemp += QString::fromLatin1("FreeBSD");
3825 #elif defined Q_OS_HPUX
3826 firstPartTemp += QString::fromLatin1("HP-UX");
3827 #elif defined Q_OS_HURD
3828 firstPartTemp += QString::fromLatin1("GNU Hurd");
3829 #elif defined Q_OS_IRIX
3830 firstPartTemp += QString::fromLatin1("SGI Irix");
3831 #elif defined Q_OS_LINUX
3832 #if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6)
3833
3834 #if defined(__x86_64__)
3835 firstPartTemp += QString::fromLatin1("Linux x86_64");
3836 #elif defined(__i386__)
3837 firstPartTemp += QString::fromLatin1("Linux i686");
3838 #else
3839 firstPartTemp += QString::fromLatin1("Linux");
3840 #endif
3841 #endif
3842
3843 #elif defined Q_OS_LYNX
3844 firstPartTemp += QString::fromLatin1("LynxOS");
3845 #elif defined Q_OS_NETBSD
3846 firstPartTemp += QString::fromLatin1("NetBSD");
3847 #elif defined Q_OS_OS2
3848 firstPartTemp += QString::fromLatin1("OS/2");
3849 #elif defined Q_OS_OPENBSD
3850 firstPartTemp += QString::fromLatin1("OpenBSD");
3851 #elif defined Q_OS_OS2EMX
3852 firstPartTemp += QString::fromLatin1("OS/2");
3853 #elif defined Q_OS_OSF
3854 firstPartTemp += QString::fromLatin1("HP Tru64 UNIX");
3855 #elif defined Q_OS_QNX6
3856 firstPartTemp += QString::fromLatin1("QNX RTP Six");
3857 #elif defined Q_OS_QNX
3858 firstPartTemp += QString::fromLatin1("QNX");
3859 #elif defined Q_OS_RELIANT
3860 firstPartTemp += QString::fromLatin1("Reliant UNIX");
3861 #elif defined Q_OS_SCO
3862 firstPartTemp += QString::fromLatin1("SCO OpenServer");
3863 #elif defined Q_OS_SOLARIS
3864 firstPartTemp += QString::fromLatin1("Sun Solaris");
3865 #elif defined Q_OS_ULTRIX
3866 firstPartTemp += QString::fromLatin1("DEC Ultrix");
3867 #elif defined Q_OS_SYMBIAN
3868 firstPartTemp += QLatin1Char(' ');
3869 QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3870 switch (s60Version) {
3871 case QSysInfo::SV_S60_3_1:
3872 firstPartTemp += QString::fromLatin1("Series60/3.1");
3873 break;
3874 case QSysInfo::SV_S60_3_2:
3875 firstPartTemp += QString::fromLatin1("Series60/3.2");
3876 break;
3877 case QSysInfo::SV_S60_5_0:
3878 firstPartTemp += QString::fromLatin1("Series60/5.0");
3879 break;
3880 default:
3881 break;
3882 }
3883 #elif defined Q_OS_UNIX
3884 firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system");
3885 #elif defined Q_OS_UNIXWARE
3886 firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight");
3887 #else
3888 firstPartTemp += QString::fromLatin1("Unknown");
3889 #endif
3890
3891 #if USE(QT_MOBILITY_SYSTEMINFO)
3892 // adding Model Number
3893 QtMobility::QSystemDeviceInfo systemDeviceInfo;
3894
3895 QString model = systemDeviceInfo.model();
3896 if (!model.isEmpty()) {
3897 if (!firstPartTemp.endsWith("; "))
3898 firstPartTemp += QString::fromLatin1("; ");
3899 firstPartTemp += systemDeviceInfo.model();
3900 }
3901 #endif
3902 firstPartTemp.squeeze();
3903 firstPart = firstPartTemp;
3904
3905 QString secondPartTemp;
3906 secondPartTemp.reserve(150);
3907 secondPartTemp += QString::fromLatin1(") ");
3908
3909 // webkit/qt version
3910 secondPartTemp += QString::fromLatin1("AppleWebKit/");
3911 secondPartTemp += qWebKitVersion();
3912 secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) ");
3913
3914
3915 // Application name split the third part
3916 secondPartTemp.squeeze();
3917 secondPart = secondPartTemp;
3918
3919 QString thirdPartTemp;
3920 thirdPartTemp.reserve(150);
3921 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
3922 thirdPartTemp += QLatin1String(" Mobile Safari/");
3923 #else
3924 thirdPartTemp += QLatin1String(" Safari/");
3925 #endif
3926 thirdPartTemp += qWebKitVersion();
3927 thirdPartTemp.squeeze();
3928 thirdPart = thirdPartTemp;
3929 Q_ASSERT(!firstPart.isNull());
3930 Q_ASSERT(!secondPart.isNull());
3931 Q_ASSERT(!thirdPart.isNull());
3932 }
3933
3934 // Application name/version
3935 QString appName = QCoreApplication::applicationName();
3936 if (!appName.isEmpty()) {
3937 QString appVer = QCoreApplication::applicationVersion();
3938 if (!appVer.isEmpty())
3939 appName.append(QLatin1Char('/') + appVer);
3940 } else {
3941 // Qt version
3942 appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion());
3943 }
3944
3945 return firstPart + secondPart + appName + thirdPart;
3946 }
3947
3948
_q_onLoadProgressChanged(int)3949 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3950 {
3951 m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3952 m_bytesReceived = page->progress()->totalBytesReceived();
3953 }
3954
3955
3956 /*!
3957 Returns the total number of bytes that were received from the network to render the current page,
3958 including extra content such as embedded images.
3959
3960 \sa bytesReceived()
3961 */
totalBytes() const3962 quint64 QWebPage::totalBytes() const
3963 {
3964 return d->m_totalBytes;
3965 }
3966
3967
3968 /*!
3969 Returns the number of bytes that were received from the network to render the current page.
3970
3971 \sa totalBytes(), loadProgress()
3972 */
bytesReceived() const3973 quint64 QWebPage::bytesReceived() const
3974 {
3975 return d->m_bytesReceived;
3976 }
3977
3978 /*!
3979 \since 4.8
3980 \fn void QWebPage::viewportChangeRequested()
3981
3982 Page authors can provide the supplied values by using the viewport meta tag. More information
3983 about this can be found at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
3984
3985 \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale()
3986 */
3987
3988 /*!
3989 \fn void QWebPage::loadStarted()
3990
3991 This signal is emitted when a page starts loading content.
3992
3993 \sa loadFinished()
3994 */
3995
3996 /*!
3997 \fn void QWebPage::loadProgress(int progress)
3998
3999 This signal is emitted when the global progress status changes.
4000 The current value is provided by \a progress and scales from 0 to 100,
4001 which is the default range of QProgressBar.
4002 It accumulates changes from all the child frames.
4003
4004 \sa bytesReceived()
4005 */
4006
4007 /*!
4008 \fn void QWebPage::loadFinished(bool ok)
4009
4010 This signal is emitted when the page finishes loading content. This signal
4011 is independant of script execution or page rendering.
4012 \a ok will indicate whether the load was successful or any error occurred.
4013
4014 \sa loadStarted(), ErrorPageExtension
4015 */
4016
4017 /*!
4018 \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
4019
4020 This signal is emitted when the mouse hovers over a link.
4021
4022 \a link contains the link url.
4023 \a title is the link element's title, if it is specified in the markup.
4024 \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
4025
4026 When the mouse leaves the link element the signal is emitted with empty parameters.
4027
4028 \sa linkClicked()
4029 */
4030
4031 /*!
4032 \fn void QWebPage::statusBarMessage(const QString& text)
4033
4034 This signal is emitted when the statusbar \a text is changed by the page.
4035 */
4036
4037 /*!
4038 \fn void QWebPage::frameCreated(QWebFrame *frame)
4039
4040 This signal is emitted whenever the page creates a new \a frame.
4041
4042 \sa currentFrame()
4043 */
4044
4045 /*!
4046 \fn void QWebPage::selectionChanged()
4047
4048 This signal is emitted whenever the selection changes, either interactively
4049 or programmatically (e.g. by calling triggerAction() with a selection action).
4050
4051 \sa selectedText()
4052 */
4053
4054 /*!
4055 \fn void QWebPage::contentsChanged()
4056 \since 4.5
4057
4058 This signal is emitted whenever the text in form elements changes
4059 as well as other editable content.
4060
4061 \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText()
4062 */
4063
4064 /*!
4065 \fn void QWebPage::geometryChangeRequested(const QRect& geom)
4066
4067 This signal is emitted whenever the document wants to change the position and size of the
4068 page to \a geom. This can happen for example through JavaScript.
4069 */
4070
4071 /*!
4072 \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
4073
4074 This signal is emitted whenever this QWebPage should be updated. It's useful
4075 when rendering a QWebPage without a QWebView or QGraphicsWebView.
4076 \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
4077 the mainFrame() and call the render(QPainter*, const QRegion&) method with the
4078 \a dirtyRect as the second parameter.
4079
4080 \sa mainFrame()
4081 \sa view()
4082 */
4083
4084 /*!
4085 \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
4086
4087 This signal is emitted whenever the content given by \a rectToScroll needs
4088 to be scrolled \a dx and \a dy downwards and no view was set.
4089
4090 \sa view()
4091 */
4092
4093 /*!
4094 \fn void QWebPage::windowCloseRequested()
4095
4096 This signal is emitted whenever the page requests the web browser window to be closed,
4097 for example through the JavaScript \c{window.close()} call.
4098 */
4099
4100 /*!
4101 \fn void QWebPage::printRequested(QWebFrame *frame)
4102
4103 This signal is emitted whenever the page requests the web browser to print \a frame,
4104 for example through the JavaScript \c{window.print()} call.
4105
4106 \sa QWebFrame::print(), QPrintPreviewDialog
4107 */
4108
4109 /*!
4110 \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
4111
4112 This signal is emitted when WebKit cannot handle a link the user navigated to or a
4113 web server's response includes a "Content-Disposition" header with the 'attachment'
4114 directive. If "Content-Disposition" is present in \a reply, the web server is indicating
4115 that the client should prompt the user to save the content regardless of content-type.
4116 See RFC 2616 sections 19.5.1 for details about Content-Disposition.
4117
4118 At signal emission time the meta-data of the QNetworkReply \a reply is available.
4119
4120 \note The receiving slot is responsible for deleting the QNetworkReply \a reply.
4121
4122 \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
4123
4124 \sa downloadRequested()
4125 */
4126
4127 /*!
4128 \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
4129
4130 This signal is emitted when the user decides to download a link. The url of
4131 the link as well as additional meta-information is contained in \a request.
4132
4133 \sa unsupportedContent()
4134 */
4135
4136 /*!
4137 \fn void QWebPage::microFocusChanged()
4138
4139 This signal is emitted when for example the position of the cursor in an editable form
4140 element changes. It is used to inform input methods about the new on-screen position where
4141 the user is able to enter text. This signal is usually connected to the
4142 QWidget::updateMicroFocus() slot.
4143 */
4144
4145 /*!
4146 \fn void QWebPage::linkClicked(const QUrl &url)
4147
4148 This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
4149 property is set to delegate the link handling for the specified \a url.
4150
4151 By default no links are delegated and are handled by QWebPage instead.
4152
4153 \note This signal possibly won't be emitted for clicked links which use
4154 JavaScript to trigger navigation.
4155
4156 \sa linkHovered()
4157 */
4158
4159 /*!
4160 \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
4161
4162 This signal is emitted whenever the visibility of the toolbar in a web browser
4163 window that hosts QWebPage should be changed to \a visible.
4164 */
4165
4166 /*!
4167 \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
4168
4169 This signal is emitted whenever the visibility of the statusbar in a web browser
4170 window that hosts QWebPage should be changed to \a visible.
4171 */
4172
4173 /*!
4174 \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
4175
4176 This signal is emitted whenever the visibility of the menubar in a web browser
4177 window that hosts QWebPage should be changed to \a visible.
4178 */
4179
4180 /*!
4181 \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
4182 \since 4.5
4183
4184 This signal is emitted whenever the web site shown in \a frame is asking to store data
4185 to the database \a databaseName and the quota allocated to that web site is exceeded.
4186
4187 \sa QWebDatabase
4188 */
4189 /*!
4190 \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota);
4191
4192 This signal is emitted whenever the web site is asking to store data to the application cache
4193 database databaseName and the quota allocated to that web site is exceeded.
4194
4195 */
4196
4197 /*!
4198 \since 4.5
4199 \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
4200
4201 This signal is emitted shortly before the history of navigated pages
4202 in \a frame is changed, for example when navigating back in the history.
4203
4204 The provided QWebHistoryItem, \a item, holds the history entry of the frame before
4205 the change.
4206
4207 A potential use-case for this signal is to store custom data in
4208 the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
4209 */
4210
4211 /*!
4212 \since 4.5
4213 \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
4214
4215 This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
4216 */
4217
4218 /*!
4219 \fn QWebPagePrivate* QWebPage::handle() const
4220 \internal
4221 */
4222
4223 #include "moc_qwebpage.cpp"
4224