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