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 #include "qwebview.h"
25 #include "qwebframe.h"
26 #include "qwebpage_p.h"
27 #include "qwebframe_p.h"
28 #include "qwebhistory.h"
29 #include "qwebhistory_p.h"
30 #include "qwebinspector.h"
31 #include "qwebinspector_p.h"
32 #include "qwebsettings.h"
33 #include "qwebkitversion.h"
34
35 #include "Chrome.h"
36 #include "ContextMenuController.h"
37 #include "Frame.h"
38 #include "FrameTree.h"
39 #include "FrameLoader.h"
40 #include "FrameLoaderClientQt.h"
41 #include "FrameView.h"
42 #include "FormState.h"
43 #include "ApplicationCacheStorage.h"
44 #include "ChromeClientQt.h"
45 #include "ContextMenu.h"
46 #include "ContextMenuClientQt.h"
47 #include "DocumentLoader.h"
48 #include "DragClientQt.h"
49 #include "DragController.h"
50 #include "DragData.h"
51 #include "EditorClientQt.h"
52 #include "SecurityOrigin.h"
53 #include "Settings.h"
54 #include "Page.h"
55 #include "Pasteboard.h"
56 #include "FrameLoader.h"
57 #include "FrameLoadRequest.h"
58 #include "KURL.h"
59 #include "Logging.h"
60 #include "Image.h"
61 #include "InspectorClientQt.h"
62 #include "InspectorController.h"
63 #include "FocusController.h"
64 #include "Editor.h"
65 #include "Scrollbar.h"
66 #include "PlatformKeyboardEvent.h"
67 #include "PlatformWheelEvent.h"
68 #include "PluginDatabase.h"
69 #include "ProgressTracker.h"
70 #include "RefPtr.h"
71 #include "RenderTextControl.h"
72 #include "TextIterator.h"
73 #include "HashMap.h"
74 #include "HTMLFormElement.h"
75 #include "HTMLInputElement.h"
76 #include "HTMLNames.h"
77 #include "HitTestResult.h"
78 #include "WindowFeatures.h"
79 #include "LocalizedStrings.h"
80 #include "Cache.h"
81 #include "runtime/InitializeThreading.h"
82 #include "PageGroup.h"
83 #include "QWebPageClient.h"
84 #include "WorkerThread.h"
85
86 #include <QApplication>
87 #include <QBasicTimer>
88 #include <QBitArray>
89 #include <QDebug>
90 #include <QDragEnterEvent>
91 #include <QDragLeaveEvent>
92 #include <QDragMoveEvent>
93 #include <QDropEvent>
94 #include <QFileDialog>
95 #include <QHttpRequestHeader>
96 #include <QInputDialog>
97 #include <QLocale>
98 #include <QMessageBox>
99 #include <QNetworkProxy>
100 #include <QUndoStack>
101 #include <QUrl>
102 #include <QPainter>
103 #include <QClipboard>
104 #include <QSslSocket>
105 #include <QStyle>
106 #include <QSysInfo>
107 #include <QTextCharFormat>
108 #include <QTextDocument>
109 #include <QNetworkAccessManager>
110 #include <QNetworkRequest>
111 #if defined(Q_WS_X11)
112 #include <QX11Info>
113 #endif
114
115 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
116 #include <QTouchEvent>
117 #include "PlatformTouchEvent.h"
118 #endif
119
120 using namespace WebCore;
121
qt_drt_overwritePluginDirectories()122 void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories()
123 {
124 PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false);
125
126 Vector<String> paths;
127 String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data());
128 qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths);
129
130 db->setPluginDirectories(paths);
131 db->refresh();
132 }
133
qt_drt_workerThreadCount()134 int QWEBKIT_EXPORT qt_drt_workerThreadCount()
135 {
136 #if ENABLE(WORKERS)
137 return WebCore::WorkerThread::workerThreadCount();
138 #else
139 return 0;
140 #endif
141 }
142
143 bool QWebPagePrivate::drtRun = false;
qt_drt_run(bool b)144 void QWEBKIT_EXPORT qt_drt_run(bool b)
145 {
146 QWebPagePrivate::drtRun = b;
147 }
148
qt_drt_setFrameSetFlatteningEnabled(QWebPage * page,bool enabled)149 void QWEBKIT_EXPORT qt_drt_setFrameSetFlatteningEnabled(QWebPage* page, bool enabled)
150 {
151 QWebPagePrivate::core(page)->settings()->setFrameSetFlatteningEnabled(enabled);
152 }
153
qt_webpage_setGroupName(QWebPage * page,const QString & groupName)154 void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName)
155 {
156 page->handle()->page->setGroupName(groupName);
157 }
158
qt_webpage_groupName(QWebPage * page)159 QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page)
160 {
161 return page->handle()->page->groupName();
162 }
163
164 class QWebPageWidgetClient : public QWebPageClient {
165 public:
QWebPageWidgetClient(QWidget * view)166 QWebPageWidgetClient(QWidget* view)
167 : view(view)
168 {
169 Q_ASSERT(view);
170 }
171
172 virtual void scroll(int dx, int dy, const QRect&);
173 virtual void update(const QRect& dirtyRect);
174 virtual void setInputMethodEnabled(bool enable);
175 virtual bool inputMethodEnabled() const;
176 #if QT_VERSION >= 0x040600
177 virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable);
178 #endif
179
180 #ifndef QT_NO_CURSOR
181 virtual QCursor cursor() const;
182 virtual void updateCursor(const QCursor& cursor);
183 #endif
184
185 virtual QPalette palette() const;
186 virtual int screenNumber() const;
187 virtual QWidget* ownerWidget() const;
188
189 virtual QObject* pluginParent() const;
190
191 virtual QStyle* style() const;
192
193 QWidget* view;
194 };
195
scroll(int dx,int dy,const QRect & rectToScroll)196 void QWebPageWidgetClient::scroll(int dx, int dy, const QRect& rectToScroll)
197 {
198 view->scroll(qreal(dx), qreal(dy), rectToScroll);
199 }
200
update(const QRect & dirtyRect)201 void QWebPageWidgetClient::update(const QRect & dirtyRect)
202 {
203 view->update(dirtyRect);
204 }
205
setInputMethodEnabled(bool enable)206 void QWebPageWidgetClient::setInputMethodEnabled(bool enable)
207 {
208 view->setAttribute(Qt::WA_InputMethodEnabled, enable);
209 }
210
inputMethodEnabled() const211 bool QWebPageWidgetClient::inputMethodEnabled() const
212 {
213 return view->testAttribute(Qt::WA_InputMethodEnabled);
214 }
215
216 #if QT_VERSION >= 0x040600
setInputMethodHint(Qt::InputMethodHint hint,bool enable)217 void QWebPageWidgetClient::setInputMethodHint(Qt::InputMethodHint hint, bool enable)
218 {
219 if (enable)
220 view->setInputMethodHints(view->inputMethodHints() | hint);
221 else
222 view->setInputMethodHints(view->inputMethodHints() & ~hint);
223 }
224 #endif
225 #ifndef QT_NO_CURSOR
cursor() const226 QCursor QWebPageWidgetClient::cursor() const
227 {
228 return view->cursor();
229 }
230
updateCursor(const QCursor & cursor)231 void QWebPageWidgetClient::updateCursor(const QCursor& cursor)
232 {
233 view->setCursor(cursor);
234 }
235 #endif
236
palette() const237 QPalette QWebPageWidgetClient::palette() const
238 {
239 return view->palette();
240 }
241
screenNumber() const242 int QWebPageWidgetClient::screenNumber() const
243 {
244 #if defined(Q_WS_X11)
245 if (view)
246 return view->x11Info().screen();
247 #endif
248
249 return 0;
250 }
251
ownerWidget() const252 QWidget* QWebPageWidgetClient::ownerWidget() const
253 {
254 return view;
255 }
256
pluginParent() const257 QObject* QWebPageWidgetClient::pluginParent() const
258 {
259 return view;
260 }
261
style() const262 QStyle* QWebPageWidgetClient::style() const
263 {
264 return view->style();
265 }
266
267 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
268 static const char* editorCommandWebActions[] =
269 {
270 0, // OpenLink,
271
272 0, // OpenLinkInNewWindow,
273 0, // OpenFrameInNewWindow,
274
275 0, // DownloadLinkToDisk,
276 0, // CopyLinkToClipboard,
277
278 0, // OpenImageInNewWindow,
279 0, // DownloadImageToDisk,
280 0, // CopyImageToClipboard,
281
282 0, // Back,
283 0, // Forward,
284 0, // Stop,
285 0, // Reload,
286
287 "Cut", // Cut,
288 "Copy", // Copy,
289 "Paste", // Paste,
290
291 "Undo", // Undo,
292 "Redo", // Redo,
293 "MoveForward", // MoveToNextChar,
294 "MoveBackward", // MoveToPreviousChar,
295 "MoveWordForward", // MoveToNextWord,
296 "MoveWordBackward", // MoveToPreviousWord,
297 "MoveDown", // MoveToNextLine,
298 "MoveUp", // MoveToPreviousLine,
299 "MoveToBeginningOfLine", // MoveToStartOfLine,
300 "MoveToEndOfLine", // MoveToEndOfLine,
301 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
302 "MoveToEndOfParagraph", // MoveToEndOfBlock,
303 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
304 "MoveToEndOfDocument", // MoveToEndOfDocument,
305 "MoveForwardAndModifySelection", // SelectNextChar,
306 "MoveBackwardAndModifySelection", // SelectPreviousChar,
307 "MoveWordForwardAndModifySelection", // SelectNextWord,
308 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
309 "MoveDownAndModifySelection", // SelectNextLine,
310 "MoveUpAndModifySelection", // SelectPreviousLine,
311 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
312 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
313 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
314 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
315 "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
316 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
317 "DeleteWordBackward", // DeleteStartOfWord,
318 "DeleteWordForward", // DeleteEndOfWord,
319
320 0, // SetTextDirectionDefault,
321 0, // SetTextDirectionLeftToRight,
322 0, // SetTextDirectionRightToLeft,
323
324 "ToggleBold", // ToggleBold,
325 "ToggleItalic", // ToggleItalic,
326 "ToggleUnderline", // ToggleUnderline,
327
328 0, // InspectElement,
329
330 "InsertNewline", // InsertParagraphSeparator
331 "InsertLineBreak", // InsertLineSeparator
332
333 "SelectAll", // SelectAll
334 0, // ReloadAndBypassCache,
335
336 "PasteAndMatchStyle", // PasteAndMatchStyle
337 "RemoveFormat", // RemoveFormat
338 "Strikethrough", // ToggleStrikethrough,
339 "Subscript", // ToggleSubscript
340 "Superscript", // ToggleSuperscript
341 "InsertUnorderedList", // InsertUnorderedList
342 "InsertOrderedList", // InsertOrderedList
343 "Indent", // Indent
344 "Outdent", // Outdent,
345
346 "AlignCenter", // AlignCenter,
347 "AlignJustified", // AlignJustified,
348 "AlignLeft", // AlignLeft,
349 "AlignRight", // AlignRight,
350
351 0 // WebActionCount
352 };
353
354 // Lookup the appropriate editor command to use for WebAction \a action
editorCommandForWebActions(QWebPage::WebAction action)355 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
356 {
357 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
358 return editorCommandWebActions[action];
359 return 0;
360 }
361
362 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
363 #define WEBKIT_VERSION "527+"
364
dropActionToDragOp(Qt::DropActions actions)365 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
366 {
367 unsigned result = 0;
368 if (actions & Qt::CopyAction)
369 result |= DragOperationCopy;
370 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
371 // hence it should be considered as "move"
372 if (actions & Qt::MoveAction)
373 result |= (DragOperationMove | DragOperationGeneric);
374 if (actions & Qt::LinkAction)
375 result |= DragOperationLink;
376 return (DragOperation)result;
377 }
378
dragOpToDropAction(unsigned actions)379 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
380 {
381 Qt::DropAction result = Qt::IgnoreAction;
382 if (actions & DragOperationCopy)
383 result = Qt::CopyAction;
384 else if (actions & DragOperationMove)
385 result = Qt::MoveAction;
386 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
387 // hence it should be considered as "move"
388 else if (actions & DragOperationGeneric)
389 result = Qt::MoveAction;
390 else if (actions & DragOperationLink)
391 result = Qt::LinkAction;
392 return result;
393 }
394
QWebPagePrivate(QWebPage * qq)395 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
396 : q(qq)
397 , client(0)
398 #if QT_VERSION < 0x040600
399 , view(0)
400 #endif
401 , clickCausedFocus(false)
402 , viewportSize(QSize(0, 0))
403 , inspectorFrontend(0)
404 , inspector(0)
405 , inspectorIsInternalOnly(false)
406 {
407 WebCore::InitializeLoggingChannelsIfNecessary();
408 JSC::initializeThreading();
409 WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
410
411 chromeClient = new ChromeClientQt(q);
412 contextMenuClient = new ContextMenuClientQt();
413 editorClient = new EditorClientQt(q);
414 page = new Page(chromeClient, contextMenuClient, editorClient,
415 new DragClientQt(q), new InspectorClientQt(q), 0, 0);
416
417 settings = new QWebSettings(page->settings());
418
419 #ifndef QT_NO_UNDOSTACK
420 undoStack = 0;
421 #endif
422 mainFrame = 0;
423 networkManager = 0;
424 pluginFactory = 0;
425 insideOpenCall = false;
426 forwardUnsupportedContent = false;
427 editable = false;
428 useFixedLayout = false;
429 linkPolicy = QWebPage::DontDelegateLinks;
430 #ifndef QT_NO_CONTEXTMENU
431 currentContextMenu = 0;
432 #endif
433
434 history.d = new QWebHistoryPrivate(page->backForwardList());
435 memset(actions, 0, sizeof(actions));
436
437 PageGroup::setShouldTrackVisitedLinks(true);
438 }
439
~QWebPagePrivate()440 QWebPagePrivate::~QWebPagePrivate()
441 {
442 #ifndef QT_NO_CONTEXTMENU
443 delete currentContextMenu;
444 #endif
445 #ifndef QT_NO_UNDOSTACK
446 delete undoStack;
447 #endif
448 delete settings;
449 delete page;
450 }
451
core(QWebPage * page)452 WebCore::Page* QWebPagePrivate::core(QWebPage* page)
453 {
454 return page->d->page;
455 }
456
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)457 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
458 {
459 if (insideOpenCall
460 && frame == mainFrame)
461 return true;
462 return q->acceptNavigationRequest(frame, request, type);
463 }
464
createMainFrame()465 void QWebPagePrivate::createMainFrame()
466 {
467 if (!mainFrame) {
468 QWebFrameData frameData(page);
469 mainFrame = new QWebFrame(q, &frameData);
470
471 emit q->frameCreated(mainFrame);
472 }
473 }
474
webActionForContextMenuAction(WebCore::ContextMenuAction action)475 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
476 {
477 switch (action) {
478 case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
479 case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
480 case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
481 case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
482 case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
483 case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
484 case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
485 case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
486 case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
487 case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
488 case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
489 case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
490 case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
491 case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
492 case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
493 case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
494 case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
495 case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
496 case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
497 case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
498 case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
499 #if ENABLE(INSPECTOR)
500 case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
501 #endif
502 default: break;
503 }
504 return QWebPage::NoWebAction;
505 }
506
507 #ifndef QT_NO_CONTEXTMENU
createContextMenu(const WebCore::ContextMenu * webcoreMenu,const QList<WebCore::ContextMenuItem> * items,QBitArray * visitedWebActions)508 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
509 const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
510 {
511 QMenu* menu = new QMenu(q->view());
512 for (int i = 0; i < items->count(); ++i) {
513 const ContextMenuItem &item = items->at(i);
514 switch (item.type()) {
515 case WebCore::CheckableActionType: /* fall through */
516 case WebCore::ActionType: {
517 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
518 QAction *a = q->action(action);
519 if (a) {
520 ContextMenuItem it(item);
521 webcoreMenu->checkOrEnableIfNeeded(it);
522 PlatformMenuItemDescription desc = it.releasePlatformDescription();
523 a->setEnabled(desc.enabled);
524 a->setChecked(desc.checked);
525 a->setCheckable(item.type() == WebCore::CheckableActionType);
526
527 menu->addAction(a);
528 visitedWebActions->setBit(action);
529 }
530 break;
531 }
532 case WebCore::SeparatorType:
533 menu->addSeparator();
534 break;
535 case WebCore::SubmenuType: {
536 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
537
538 bool anyEnabledAction = false;
539
540 QList<QAction *> actions = subMenu->actions();
541 for (int i = 0; i < actions.count(); ++i) {
542 if (actions.at(i)->isVisible())
543 anyEnabledAction |= actions.at(i)->isEnabled();
544 }
545
546 // don't show sub-menus with just disabled actions
547 if (anyEnabledAction) {
548 subMenu->setTitle(item.title());
549 menu->addAction(subMenu->menuAction());
550 } else
551 delete subMenu;
552 break;
553 }
554 }
555 }
556 return menu;
557 }
558 #endif // QT_NO_CONTEXTMENU
559
_q_webActionTriggered(bool checked)560 void QWebPagePrivate::_q_webActionTriggered(bool checked)
561 {
562 QAction *a = qobject_cast<QAction *>(q->sender());
563 if (!a)
564 return;
565 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
566 q->triggerAction(action, checked);
567 }
568
_q_cleanupLeakMessages()569 void QWebPagePrivate::_q_cleanupLeakMessages()
570 {
571 #ifndef NDEBUG
572 // Need this to make leak messages accurate.
573 cache()->setCapacities(0, 0, 0);
574 #endif
575 }
576
updateAction(QWebPage::WebAction action)577 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
578 {
579 QAction *a = actions[action];
580 if (!a || !mainFrame)
581 return;
582
583 WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
584 WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
585
586 bool enabled = a->isEnabled();
587 bool checked = a->isChecked();
588
589 switch (action) {
590 case QWebPage::Back:
591 enabled = page->canGoBackOrForward(-1);
592 break;
593 case QWebPage::Forward:
594 enabled = page->canGoBackOrForward(1);
595 break;
596 case QWebPage::Stop:
597 enabled = loader->isLoading();
598 break;
599 case QWebPage::Reload:
600 case QWebPage::ReloadAndBypassCache:
601 enabled = !loader->isLoading();
602 break;
603 #ifndef QT_NO_UNDOSTACK
604 case QWebPage::Undo:
605 case QWebPage::Redo:
606 // those two are handled by QUndoStack
607 break;
608 #endif // QT_NO_UNDOSTACK
609 case QWebPage::SelectAll: // editor command is always enabled
610 break;
611 case QWebPage::SetTextDirectionDefault:
612 case QWebPage::SetTextDirectionLeftToRight:
613 case QWebPage::SetTextDirectionRightToLeft:
614 enabled = editor->canEdit();
615 checked = false;
616 break;
617 default: {
618 // see if it's an editor command
619 const char* commandName = editorCommandForWebActions(action);
620
621 // if it's an editor command, let it's logic determine state
622 if (commandName) {
623 Editor::Command command = editor->command(commandName);
624 enabled = command.isEnabled();
625 if (enabled)
626 checked = command.state() != FalseTriState;
627 else
628 checked = false;
629 }
630 break;
631 }
632 }
633
634 a->setEnabled(enabled);
635
636 if (a->isCheckable())
637 a->setChecked(checked);
638 }
639
updateNavigationActions()640 void QWebPagePrivate::updateNavigationActions()
641 {
642 updateAction(QWebPage::Back);
643 updateAction(QWebPage::Forward);
644 updateAction(QWebPage::Stop);
645 updateAction(QWebPage::Reload);
646 updateAction(QWebPage::ReloadAndBypassCache);
647 }
648
updateEditorActions()649 void QWebPagePrivate::updateEditorActions()
650 {
651 updateAction(QWebPage::Cut);
652 updateAction(QWebPage::Copy);
653 updateAction(QWebPage::Paste);
654 updateAction(QWebPage::MoveToNextChar);
655 updateAction(QWebPage::MoveToPreviousChar);
656 updateAction(QWebPage::MoveToNextWord);
657 updateAction(QWebPage::MoveToPreviousWord);
658 updateAction(QWebPage::MoveToNextLine);
659 updateAction(QWebPage::MoveToPreviousLine);
660 updateAction(QWebPage::MoveToStartOfLine);
661 updateAction(QWebPage::MoveToEndOfLine);
662 updateAction(QWebPage::MoveToStartOfBlock);
663 updateAction(QWebPage::MoveToEndOfBlock);
664 updateAction(QWebPage::MoveToStartOfDocument);
665 updateAction(QWebPage::MoveToEndOfDocument);
666 updateAction(QWebPage::SelectNextChar);
667 updateAction(QWebPage::SelectPreviousChar);
668 updateAction(QWebPage::SelectNextWord);
669 updateAction(QWebPage::SelectPreviousWord);
670 updateAction(QWebPage::SelectNextLine);
671 updateAction(QWebPage::SelectPreviousLine);
672 updateAction(QWebPage::SelectStartOfLine);
673 updateAction(QWebPage::SelectEndOfLine);
674 updateAction(QWebPage::SelectStartOfBlock);
675 updateAction(QWebPage::SelectEndOfBlock);
676 updateAction(QWebPage::SelectStartOfDocument);
677 updateAction(QWebPage::SelectEndOfDocument);
678 updateAction(QWebPage::DeleteStartOfWord);
679 updateAction(QWebPage::DeleteEndOfWord);
680 updateAction(QWebPage::SetTextDirectionDefault);
681 updateAction(QWebPage::SetTextDirectionLeftToRight);
682 updateAction(QWebPage::SetTextDirectionRightToLeft);
683 updateAction(QWebPage::ToggleBold);
684 updateAction(QWebPage::ToggleItalic);
685 updateAction(QWebPage::ToggleUnderline);
686 updateAction(QWebPage::InsertParagraphSeparator);
687 updateAction(QWebPage::InsertLineSeparator);
688 updateAction(QWebPage::PasteAndMatchStyle);
689 updateAction(QWebPage::RemoveFormat);
690 updateAction(QWebPage::ToggleStrikethrough);
691 updateAction(QWebPage::ToggleSubscript);
692 updateAction(QWebPage::ToggleSuperscript);
693 updateAction(QWebPage::InsertUnorderedList);
694 updateAction(QWebPage::InsertOrderedList);
695 updateAction(QWebPage::Indent);
696 updateAction(QWebPage::Outdent);
697 updateAction(QWebPage::AlignCenter);
698 updateAction(QWebPage::AlignJustified);
699 updateAction(QWebPage::AlignLeft);
700 updateAction(QWebPage::AlignRight);
701 }
702
timerEvent(QTimerEvent * ev)703 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
704 {
705 int timerId = ev->timerId();
706 if (timerId == tripleClickTimer.timerId())
707 tripleClickTimer.stop();
708 else
709 q->QObject::timerEvent(ev);
710 }
711
mouseMoveEvent(QGraphicsSceneMouseEvent * ev)712 void QWebPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
713 {
714 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
715 if (!frame->view())
716 return;
717
718 bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
719 ev->setAccepted(accepted);
720 }
721
mouseMoveEvent(QMouseEvent * ev)722 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
723 {
724 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
725 if (!frame->view())
726 return;
727
728 bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
729 ev->setAccepted(accepted);
730 }
731
mousePressEvent(QGraphicsSceneMouseEvent * ev)732 void QWebPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev)
733 {
734 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
735 if (!frame->view())
736 return;
737
738 if (tripleClickTimer.isActive()
739 && (ev->pos().toPoint() - tripleClick).manhattanLength()
740 < QApplication::startDragDistance()) {
741 mouseTripleClickEvent(ev);
742 return;
743 }
744
745 bool accepted = false;
746 PlatformMouseEvent mev(ev, 1);
747 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
748 if (mev.button() != NoButton)
749 accepted = frame->eventHandler()->handleMousePressEvent(mev);
750 ev->setAccepted(accepted);
751 }
752
mousePressEvent(QMouseEvent * ev)753 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
754 {
755 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
756 if (!frame->view())
757 return;
758
759 RefPtr<WebCore::Node> oldNode;
760 if (page->focusController()->focusedFrame()
761 && page->focusController()->focusedFrame()->document())
762 oldNode = page->focusController()->focusedFrame()->document()->focusedNode();
763
764 if (tripleClickTimer.isActive()
765 && (ev->pos() - tripleClick).manhattanLength()
766 < QApplication::startDragDistance()) {
767 mouseTripleClickEvent(ev);
768 return;
769 }
770
771 bool accepted = false;
772 PlatformMouseEvent mev(ev, 1);
773 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
774 if (mev.button() != NoButton)
775 accepted = frame->eventHandler()->handleMousePressEvent(mev);
776 ev->setAccepted(accepted);
777
778 RefPtr<WebCore::Node> newNode;
779 if (page->focusController()->focusedFrame()
780 && page->focusController()->focusedFrame()->document())
781 newNode = page->focusController()->focusedFrame()->document()->focusedNode();
782
783 if (newNode && oldNode != newNode)
784 clickCausedFocus = true;
785 }
786
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * ev)787 void QWebPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *ev)
788 {
789 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
790 if (!frame->view())
791 return;
792
793 bool accepted = false;
794 PlatformMouseEvent mev(ev, 2);
795 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
796 if (mev.button() != NoButton)
797 accepted = frame->eventHandler()->handleMousePressEvent(mev);
798 ev->setAccepted(accepted);
799
800 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
801 tripleClick = ev->pos().toPoint();
802 }
803
mouseDoubleClickEvent(QMouseEvent * ev)804 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
805 {
806 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
807 if (!frame->view())
808 return;
809
810 bool accepted = false;
811 PlatformMouseEvent mev(ev, 2);
812 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
813 if (mev.button() != NoButton)
814 accepted = frame->eventHandler()->handleMousePressEvent(mev);
815 ev->setAccepted(accepted);
816
817 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
818 tripleClick = ev->pos();
819 }
820
mouseTripleClickEvent(QGraphicsSceneMouseEvent * ev)821 void QWebPagePrivate::mouseTripleClickEvent(QGraphicsSceneMouseEvent *ev)
822 {
823 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
824 if (!frame->view())
825 return;
826
827 bool accepted = false;
828 PlatformMouseEvent mev(ev, 3);
829 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
830 if (mev.button() != NoButton)
831 accepted = frame->eventHandler()->handleMousePressEvent(mev);
832 ev->setAccepted(accepted);
833 }
834
mouseTripleClickEvent(QMouseEvent * ev)835 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
836 {
837 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
838 if (!frame->view())
839 return;
840
841 bool accepted = false;
842 PlatformMouseEvent mev(ev, 3);
843 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
844 if (mev.button() != NoButton)
845 accepted = frame->eventHandler()->handleMousePressEvent(mev);
846 ev->setAccepted(accepted);
847 }
848
handleClipboard(QEvent * ev,Qt::MouseButton button)849 void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
850 {
851 #ifndef QT_NO_CLIPBOARD
852 if (QApplication::clipboard()->supportsSelection()) {
853 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
854 Pasteboard::generalPasteboard()->setSelectionMode(true);
855 WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
856 if (button == Qt::LeftButton) {
857 if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
858 focusFrame->editor()->copy();
859 ev->setAccepted(true);
860 }
861 } else if (button == Qt::MidButton) {
862 if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
863 focusFrame->editor()->paste();
864 ev->setAccepted(true);
865 }
866 }
867 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
868 }
869 #endif
870 }
871
mouseReleaseEvent(QGraphicsSceneMouseEvent * ev)872 void QWebPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
873 {
874 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
875 if (!frame->view())
876 return;
877
878 bool accepted = false;
879 PlatformMouseEvent mev(ev, 0);
880 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
881 if (mev.button() != NoButton)
882 accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
883 ev->setAccepted(accepted);
884
885 handleClipboard(ev, ev->button());
886 handleSoftwareInputPanel(ev->button());
887 }
888
handleSoftwareInputPanel(Qt::MouseButton button)889 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button)
890 {
891 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
892 Frame* frame = page->focusController()->focusedFrame();
893 if (!frame)
894 return;
895
896 if (client && client->inputMethodEnabled()
897 && frame->document()->focusedNode()
898 && button == Qt::LeftButton && qApp->autoSipEnabled()) {
899 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
900 client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
901 if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
902 QEvent event(QEvent::RequestSoftwareInputPanel);
903 QApplication::sendEvent(client->ownerWidget(), &event);
904 }
905 }
906
907 clickCausedFocus = false;
908 #endif
909 }
910
mouseReleaseEvent(QMouseEvent * ev)911 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
912 {
913 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
914 if (!frame->view())
915 return;
916
917 bool accepted = false;
918 PlatformMouseEvent mev(ev, 0);
919 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
920 if (mev.button() != NoButton)
921 accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
922 ev->setAccepted(accepted);
923
924 handleClipboard(ev, ev->button());
925 handleSoftwareInputPanel(ev->button());
926 }
927
928 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(const QPoint & globalPos)929 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
930 {
931 QMenu *menu = q->createStandardContextMenu();
932 if (menu) {
933 menu->exec(globalPos);
934 delete menu;
935 }
936 }
937 #endif // QT_NO_CONTEXTMENU
938
939 /*!
940 \since 4.5
941 This function creates the standard context menu which is shown when
942 the user clicks on the web page with the right mouse button. It is
943 called from the default contextMenuEvent() handler. The popup menu's
944 ownership is transferred to the caller.
945 */
createStandardContextMenu()946 QMenu *QWebPage::createStandardContextMenu()
947 {
948 #ifndef QT_NO_CONTEXTMENU
949 QMenu *menu = d->currentContextMenu;
950 d->currentContextMenu = 0;
951 return menu;
952 #else
953 return 0;
954 #endif
955 }
956
957 #ifndef QT_NO_WHEELEVENT
wheelEvent(QGraphicsSceneWheelEvent * ev)958 void QWebPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev)
959 {
960 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
961 if (!frame->view())
962 return;
963
964 WebCore::PlatformWheelEvent pev(ev);
965 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
966 ev->setAccepted(accepted);
967 }
968
wheelEvent(QWheelEvent * ev)969 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
970 {
971 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
972 if (!frame->view())
973 return;
974
975 WebCore::PlatformWheelEvent pev(ev);
976 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
977 ev->setAccepted(accepted);
978 }
979 #endif // QT_NO_WHEELEVENT
980
981 #ifndef QT_NO_SHORTCUT
editorActionForKeyEvent(QKeyEvent * event)982 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
983 {
984 static struct {
985 QKeySequence::StandardKey standardKey;
986 QWebPage::WebAction action;
987 } editorActions[] = {
988 { QKeySequence::Cut, QWebPage::Cut },
989 { QKeySequence::Copy, QWebPage::Copy },
990 { QKeySequence::Paste, QWebPage::Paste },
991 { QKeySequence::Undo, QWebPage::Undo },
992 { QKeySequence::Redo, QWebPage::Redo },
993 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
994 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
995 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
996 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
997 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
998 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
999 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
1000 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
1001 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
1002 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
1003 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
1004 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
1005 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
1006 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
1007 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
1008 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
1009 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
1010 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
1011 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
1012 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
1013 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
1014 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
1015 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
1016 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
1017 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
1018 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
1019 #if QT_VERSION >= 0x040500
1020 { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
1021 { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
1022 #endif
1023 { QKeySequence::SelectAll, QWebPage::SelectAll },
1024 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
1025 };
1026
1027 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
1028 if (event == editorActions[i].standardKey)
1029 return editorActions[i].action;
1030
1031 return QWebPage::NoWebAction;
1032 }
1033 #endif // QT_NO_SHORTCUT
1034
keyPressEvent(QKeyEvent * ev)1035 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
1036 {
1037 bool handled = false;
1038 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1039 // we forward the key event to WebCore first to handle potential DOM
1040 // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
1041 // to trigger editor commands via triggerAction().
1042 if (!handled)
1043 handled = frame->eventHandler()->keyEvent(ev);
1044 if (!handled) {
1045 handled = true;
1046 QFont defaultFont;
1047 if (q->view())
1048 defaultFont = q->view()->font();
1049 QFontMetrics fm(defaultFont);
1050 if (!handleScrolling(ev, frame)) {
1051 switch (ev->key()) {
1052 case Qt::Key_Back:
1053 q->triggerAction(QWebPage::Back);
1054 break;
1055 case Qt::Key_Forward:
1056 q->triggerAction(QWebPage::Forward);
1057 break;
1058 case Qt::Key_Stop:
1059 q->triggerAction(QWebPage::Stop);
1060 break;
1061 case Qt::Key_Refresh:
1062 q->triggerAction(QWebPage::Reload);
1063 break;
1064 case Qt::Key_Backspace:
1065 if (ev->modifiers() == Qt::ShiftModifier)
1066 q->triggerAction(QWebPage::Forward);
1067 else
1068 q->triggerAction(QWebPage::Back);
1069 break;
1070 default:
1071 handled = false;
1072 break;
1073 }
1074 }
1075 }
1076
1077 ev->setAccepted(handled);
1078 }
1079
keyReleaseEvent(QKeyEvent * ev)1080 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
1081 {
1082 if (ev->isAutoRepeat()) {
1083 ev->setAccepted(true);
1084 return;
1085 }
1086
1087 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1088 bool handled = frame->eventHandler()->keyEvent(ev);
1089 ev->setAccepted(handled);
1090 }
1091
focusInEvent(QFocusEvent *)1092 void QWebPagePrivate::focusInEvent(QFocusEvent*)
1093 {
1094 FocusController *focusController = page->focusController();
1095 focusController->setActive(true);
1096 focusController->setFocused(true);
1097 if (!focusController->focusedFrame())
1098 focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
1099 }
1100
focusOutEvent(QFocusEvent *)1101 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
1102 {
1103 // only set the focused frame inactive so that we stop painting the caret
1104 // and the focus frame. But don't tell the focus controller so that upon
1105 // focusInEvent() we can re-activate the frame.
1106 FocusController *focusController = page->focusController();
1107 // Call setFocused first so that window.onblur doesn't get called twice
1108 focusController->setFocused(false);
1109 focusController->setActive(false);
1110 }
1111
dragEnterEvent(QGraphicsSceneDragDropEvent * ev)1112 void QWebPagePrivate::dragEnterEvent(QGraphicsSceneDragDropEvent* ev)
1113 {
1114 #ifndef QT_NO_DRAGANDDROP
1115 DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1116 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1117 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1118 ev->setDropAction(action);
1119 if (action != Qt::IgnoreAction)
1120 ev->accept();
1121 #endif
1122 }
1123
dragEnterEvent(QDragEnterEvent * ev)1124 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent* ev)
1125 {
1126 #ifndef QT_NO_DRAGANDDROP
1127 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1128 dropActionToDragOp(ev->possibleActions()));
1129 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1130 ev->setDropAction(action);
1131 // We must accept this event in order to receive the drag move events that are sent
1132 // while the drag and drop action is in progress.
1133 ev->accept();
1134 #endif
1135 }
1136
dragLeaveEvent(QGraphicsSceneDragDropEvent * ev)1137 void QWebPagePrivate::dragLeaveEvent(QGraphicsSceneDragDropEvent* ev)
1138 {
1139 #ifndef QT_NO_DRAGANDDROP
1140 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1141 page->dragController()->dragExited(&dragData);
1142 ev->accept();
1143 #endif
1144 }
1145
dragLeaveEvent(QDragLeaveEvent * ev)1146 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent* ev)
1147 {
1148 #ifndef QT_NO_DRAGANDDROP
1149 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1150 page->dragController()->dragExited(&dragData);
1151 ev->accept();
1152 #endif
1153 }
1154
dragMoveEvent(QGraphicsSceneDragDropEvent * ev)1155 void QWebPagePrivate::dragMoveEvent(QGraphicsSceneDragDropEvent* ev)
1156 {
1157 #ifndef QT_NO_DRAGANDDROP
1158 DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1159 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1160 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1161 ev->setDropAction(action);
1162 if (action != Qt::IgnoreAction)
1163 ev->accept();
1164 #endif
1165 }
1166
dragMoveEvent(QDragMoveEvent * ev)1167 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent* ev)
1168 {
1169 #ifndef QT_NO_DRAGANDDROP
1170 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1171 dropActionToDragOp(ev->possibleActions()));
1172 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1173 m_lastDropAction = action;
1174 ev->setDropAction(action);
1175 // We must accept this event in order to receive the drag move events that are sent
1176 // while the drag and drop action is in progress.
1177 ev->accept();
1178 #endif
1179 }
1180
dropEvent(QGraphicsSceneDragDropEvent * ev)1181 void QWebPagePrivate::dropEvent(QGraphicsSceneDragDropEvent* ev)
1182 {
1183 #ifndef QT_NO_DRAGANDDROP
1184 DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1185 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1186 if (page->dragController()->performDrag(&dragData))
1187 ev->accept();
1188 #endif
1189 }
1190
dropEvent(QDropEvent * ev)1191 void QWebPagePrivate::dropEvent(QDropEvent* ev)
1192 {
1193 #ifndef QT_NO_DRAGANDDROP
1194 // Overwrite the defaults set by QDragManager::defaultAction()
1195 ev->setDropAction(m_lastDropAction);
1196 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1197 dropActionToDragOp(Qt::DropAction(ev->dropAction())));
1198 if (page->dragController()->performDrag(&dragData))
1199 ev->accept();
1200 #endif
1201 }
1202
leaveEvent(QEvent *)1203 void QWebPagePrivate::leaveEvent(QEvent*)
1204 {
1205 // Fake a mouse move event just outside of the widget, since all
1206 // the interesting mouse-out behavior like invalidating scrollbars
1207 // is handled by the WebKit event handler's mouseMoved function.
1208 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1209 mouseMoveEvent(&fakeEvent);
1210 }
1211
1212 /*!
1213 \property QWebPage::palette
1214 \brief the page's palette
1215
1216 The base brush of the palette is used to draw the background of the main frame.
1217
1218 By default, this property contains the application's default palette.
1219 */
setPalette(const QPalette & pal)1220 void QWebPage::setPalette(const QPalette &pal)
1221 {
1222 d->palette = pal;
1223 if (!d->mainFrame || !d->mainFrame->d->frame->view())
1224 return;
1225
1226 QBrush brush = pal.brush(QPalette::Base);
1227 QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1228 QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1229 }
1230
palette() const1231 QPalette QWebPage::palette() const
1232 {
1233 return d->palette;
1234 }
1235
inputMethodEvent(QInputMethodEvent * ev)1236 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1237 {
1238 WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1239 WebCore::Editor *editor = frame->editor();
1240
1241 if (!editor->canEdit()) {
1242 ev->ignore();
1243 return;
1244 }
1245
1246 RenderObject* renderer = 0;
1247 RenderTextControl* renderTextControl = 0;
1248
1249 if (frame->selection()->rootEditableElement())
1250 renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1251
1252 if (renderer && renderer->isTextControl())
1253 renderTextControl = toRenderTextControl(renderer);
1254
1255 Vector<CompositionUnderline> underlines;
1256
1257 for (int i = 0; i < ev->attributes().size(); ++i) {
1258 const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1259 switch (a.type) {
1260 case QInputMethodEvent::TextFormat: {
1261 QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1262 QColor qcolor = textCharFormat.underlineColor();
1263 underlines.append(CompositionUnderline(a.start, a.length, Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1264 break;
1265 }
1266 case QInputMethodEvent::Cursor: {
1267 frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1268 if (a.length > 0) {
1269 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1270 if (caretRenderer) {
1271 QColor qcolor = a.value.value<QColor>();
1272 caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1273 }
1274 }
1275 break;
1276 }
1277 #if QT_VERSION >= 0x040600
1278 case QInputMethodEvent::Selection: {
1279 if (renderTextControl) {
1280 renderTextControl->setSelectionStart(a.start);
1281 renderTextControl->setSelectionEnd(a.start + a.length);
1282 }
1283 break;
1284 }
1285 #endif
1286 }
1287 }
1288
1289 if (!ev->commitString().isEmpty())
1290 editor->confirmComposition(ev->commitString());
1291 else if (!ev->preeditString().isEmpty()) {
1292 QString preedit = ev->preeditString();
1293 editor->setComposition(preedit, underlines, preedit.length(), 0);
1294 }
1295 ev->accept();
1296 }
1297
shortcutOverrideEvent(QKeyEvent * event)1298 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1299 {
1300 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1301 WebCore::Editor* editor = frame->editor();
1302 if (editor->canEdit()) {
1303 if (event->modifiers() == Qt::NoModifier
1304 || event->modifiers() == Qt::ShiftModifier
1305 || event->modifiers() == Qt::KeypadModifier) {
1306 if (event->key() < Qt::Key_Escape) {
1307 event->accept();
1308 } else {
1309 switch (event->key()) {
1310 case Qt::Key_Return:
1311 case Qt::Key_Enter:
1312 case Qt::Key_Delete:
1313 case Qt::Key_Home:
1314 case Qt::Key_End:
1315 case Qt::Key_Backspace:
1316 case Qt::Key_Left:
1317 case Qt::Key_Right:
1318 case Qt::Key_Up:
1319 case Qt::Key_Down:
1320 case Qt::Key_Tab:
1321 event->accept();
1322 default:
1323 break;
1324 }
1325 }
1326 }
1327 #ifndef QT_NO_SHORTCUT
1328 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1329 event->accept();
1330 #endif
1331 }
1332 }
1333
handleScrolling(QKeyEvent * ev,Frame * frame)1334 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1335 {
1336 ScrollDirection direction;
1337 ScrollGranularity granularity;
1338
1339 #ifndef QT_NO_SHORTCUT
1340 if (ev == QKeySequence::MoveToNextPage
1341 || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1342 granularity = ScrollByPage;
1343 direction = ScrollDown;
1344 } else if (ev == QKeySequence::MoveToPreviousPage
1345 || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1346 granularity = ScrollByPage;
1347 direction = ScrollUp;
1348 } else
1349 #endif // QT_NO_SHORTCUT
1350 if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1351 || ev->key() == Qt::Key_Home) {
1352 granularity = ScrollByDocument;
1353 direction = ScrollUp;
1354 } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1355 || ev->key() == Qt::Key_End) {
1356 granularity = ScrollByDocument;
1357 direction = ScrollDown;
1358 } else {
1359 switch (ev->key()) {
1360 case Qt::Key_Up:
1361 granularity = ScrollByLine;
1362 direction = ScrollUp;
1363 break;
1364 case Qt::Key_Down:
1365 granularity = ScrollByLine;
1366 direction = ScrollDown;
1367 break;
1368 case Qt::Key_Left:
1369 granularity = ScrollByLine;
1370 direction = ScrollLeft;
1371 break;
1372 case Qt::Key_Right:
1373 granularity = ScrollByLine;
1374 direction = ScrollRight;
1375 break;
1376 default:
1377 return false;
1378 }
1379 }
1380
1381 return frame->eventHandler()->scrollRecursively(direction, granularity);
1382 }
1383
1384 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
touchEvent(QTouchEvent * event)1385 void QWebPagePrivate::touchEvent(QTouchEvent* event)
1386 {
1387 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
1388 if (!frame->view())
1389 return;
1390
1391 bool accepted = frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1392 event->setAccepted(accepted);
1393 }
1394 #endif
1395
1396 /*!
1397 This method is used by the input method to query a set of properties of the page
1398 to be able to support complex input method operations as support for surrounding
1399 text and reconversions.
1400
1401 \a property specifies which property is queried.
1402
1403 \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1404 */
inputMethodQuery(Qt::InputMethodQuery property) const1405 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1406 {
1407 Frame* frame = d->page->focusController()->focusedFrame();
1408 if (!frame)
1409 return QVariant();
1410
1411 WebCore::Editor* editor = frame->editor();
1412
1413 RenderObject* renderer = 0;
1414 RenderTextControl* renderTextControl = 0;
1415
1416 if (frame->selection()->rootEditableElement())
1417 renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1418
1419 if (renderer && renderer->isTextControl())
1420 renderTextControl = toRenderTextControl(renderer);
1421
1422 switch (property) {
1423 case Qt::ImMicroFocus: {
1424 WebCore::FrameView* view = frame->view();
1425 if (view && view->needsLayout()) {
1426 // We can't access absoluteCaretBounds() while the view needs to layout.
1427 return QVariant();
1428 }
1429 return QVariant(frame->selection()->absoluteCaretBounds());
1430 }
1431 case Qt::ImFont: {
1432 if (renderTextControl) {
1433 RenderStyle* renderStyle = renderTextControl->style();
1434 return QVariant(QFont(renderStyle->font().font()));
1435 }
1436 return QVariant(QFont());
1437 }
1438 case Qt::ImCursorPosition: {
1439 if (renderTextControl) {
1440 if (editor->hasComposition()) {
1441 RefPtr<Range> range = editor->compositionRange();
1442 return QVariant(renderTextControl->selectionEnd() - TextIterator::rangeLength(range.get()));
1443 }
1444 return QVariant(renderTextControl->selectionEnd());
1445 }
1446 return QVariant();
1447 }
1448 case Qt::ImSurroundingText: {
1449 if (renderTextControl) {
1450 QString text = renderTextControl->text();
1451 RefPtr<Range> range = editor->compositionRange();
1452 if (range) {
1453 text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1454 }
1455 return QVariant(text);
1456 }
1457 return QVariant();
1458 }
1459 case Qt::ImCurrentSelection: {
1460 if (renderTextControl) {
1461 int start = renderTextControl->selectionStart();
1462 int end = renderTextControl->selectionEnd();
1463 if (end > start)
1464 return QVariant(QString(renderTextControl->text()).mid(start,end-start));
1465 }
1466 return QVariant();
1467
1468 }
1469 #if QT_VERSION >= 0x040600
1470 case Qt::ImAnchorPosition: {
1471 if (renderTextControl) {
1472 if (editor->hasComposition()) {
1473 RefPtr<Range> range = editor->compositionRange();
1474 return QVariant(renderTextControl->selectionStart() - TextIterator::rangeLength(range.get()));
1475 }
1476 return QVariant(renderTextControl->selectionStart());
1477 }
1478 return QVariant();
1479 }
1480 case Qt::ImMaximumTextLength: {
1481 if (frame->selection()->isContentEditable()) {
1482 if (frame->document() && frame->document()->focusedNode()) {
1483 if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1484 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1485 return QVariant(inputElement->maxLength());
1486 }
1487 }
1488 return QVariant(InputElement::s_maximumLength);
1489 }
1490 return QVariant(0);
1491 }
1492 #endif
1493 default:
1494 return QVariant();
1495 }
1496 }
1497
1498 /*!
1499 \internal
1500 */
setInspector(QWebInspector * insp)1501 void QWebPagePrivate::setInspector(QWebInspector* insp)
1502 {
1503 if (inspector)
1504 inspector->d->setFrontend(0);
1505
1506 if (inspectorIsInternalOnly) {
1507 QWebInspector* inspToDelete = inspector;
1508 inspector = 0;
1509 inspectorIsInternalOnly = false;
1510 delete inspToDelete; // Delete after to prevent infinite recursion
1511 }
1512
1513 inspector = insp;
1514
1515 // Give inspector frontend web view if previously created
1516 if (inspector && inspectorFrontend)
1517 inspector->d->setFrontend(inspectorFrontend);
1518 }
1519
1520 /*!
1521 \internal
1522 Returns the inspector and creates it if it wasn't created yet.
1523 The instance created here will not be available through QWebPage's API.
1524 */
getOrCreateInspector()1525 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1526 {
1527 #if ENABLE(INSPECTOR)
1528 if (!inspector) {
1529 QWebInspector* insp = new QWebInspector;
1530 insp->setPage(q);
1531 inspectorIsInternalOnly = true;
1532
1533 Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1534 }
1535 #endif
1536 return inspector;
1537 }
1538
1539 /*! \internal */
inspectorController()1540 InspectorController* QWebPagePrivate::inspectorController()
1541 {
1542 #if ENABLE(INSPECTOR)
1543 return page->inspectorController();
1544 #else
1545 return 0;
1546 #endif
1547 }
1548
1549
1550 /*!
1551 \enum QWebPage::FindFlag
1552
1553 This enum describes the options available to QWebPage's findText() function. The options
1554 can be OR-ed together from the following list:
1555
1556 \value FindBackward Searches backwards instead of forwards.
1557 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1558 changes the behaviour to a case sensitive find operation.
1559 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1560 was reached and the text was not found.
1561 \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1562 */
1563
1564 /*!
1565 \enum QWebPage::LinkDelegationPolicy
1566
1567 This enum defines the delegation policies a webpage can have when activating links and emitting
1568 the linkClicked() signal.
1569
1570 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1571 \value DelegateExternalLinks When activating links that point to documents not stored on the
1572 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1573 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1574 */
1575
1576 /*!
1577 \enum QWebPage::NavigationType
1578
1579 This enum describes the types of navigation available when browsing through hyperlinked
1580 documents.
1581
1582 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1583 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1584 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1585 \value NavigationTypeReload The user activated the reload action.
1586 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1587 \value NavigationTypeOther A navigation to another document using a method not listed above.
1588 */
1589
1590 /*!
1591 \enum QWebPage::WebAction
1592
1593 This enum describes the types of action which can be performed on the web page.
1594
1595 Actions only have an effect when they are applicable. The availability of
1596 actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1597 action returned by \l{QWebPage::}{action()}.
1598
1599 One method of enabling the text editing, cursor movement, and text selection actions
1600 is by setting \l contentEditable to true.
1601
1602 \value NoWebAction No action is triggered.
1603 \value OpenLink Open the current link.
1604 \value OpenLinkInNewWindow Open the current link in a new window.
1605 \value OpenFrameInNewWindow Replicate the current frame in a new window.
1606 \value DownloadLinkToDisk Download the current link to the disk.
1607 \value CopyLinkToClipboard Copy the current link to the clipboard.
1608 \value OpenImageInNewWindow Open the highlighted image in a new window.
1609 \value DownloadImageToDisk Download the highlighted image to the disk.
1610 \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1611 \value Back Navigate back in the history of navigated links.
1612 \value Forward Navigate forward in the history of navigated links.
1613 \value Stop Stop loading the current page.
1614 \value Reload Reload the current page.
1615 \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1616 \value Cut Cut the content currently selected into the clipboard.
1617 \value Copy Copy the content currently selected into the clipboard.
1618 \value Paste Paste content from the clipboard.
1619 \value Undo Undo the last editing action.
1620 \value Redo Redo the last editing action.
1621 \value MoveToNextChar Move the cursor to the next character.
1622 \value MoveToPreviousChar Move the cursor to the previous character.
1623 \value MoveToNextWord Move the cursor to the next word.
1624 \value MoveToPreviousWord Move the cursor to the previous word.
1625 \value MoveToNextLine Move the cursor to the next line.
1626 \value MoveToPreviousLine Move the cursor to the previous line.
1627 \value MoveToStartOfLine Move the cursor to the start of the line.
1628 \value MoveToEndOfLine Move the cursor to the end of the line.
1629 \value MoveToStartOfBlock Move the cursor to the start of the block.
1630 \value MoveToEndOfBlock Move the cursor to the end of the block.
1631 \value MoveToStartOfDocument Move the cursor to the start of the document.
1632 \value MoveToEndOfDocument Move the cursor to the end of the document.
1633 \value SelectNextChar Select to the next character.
1634 \value SelectPreviousChar Select to the previous character.
1635 \value SelectNextWord Select to the next word.
1636 \value SelectPreviousWord Select to the previous word.
1637 \value SelectNextLine Select to the next line.
1638 \value SelectPreviousLine Select to the previous line.
1639 \value SelectStartOfLine Select to the start of the line.
1640 \value SelectEndOfLine Select to the end of the line.
1641 \value SelectStartOfBlock Select to the start of the block.
1642 \value SelectEndOfBlock Select to the end of the block.
1643 \value SelectStartOfDocument Select to the start of the document.
1644 \value SelectEndOfDocument Select to the end of the document.
1645 \value DeleteStartOfWord Delete to the start of the word.
1646 \value DeleteEndOfWord Delete to the end of the word.
1647 \value SetTextDirectionDefault Set the text direction to the default direction.
1648 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1649 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1650 \value ToggleBold Toggle the formatting between bold and normal weight.
1651 \value ToggleItalic Toggle the formatting between italic and normal style.
1652 \value ToggleUnderline Toggle underlining.
1653 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1654 \value InsertParagraphSeparator Insert a new paragraph.
1655 \value InsertLineSeparator Insert a new line.
1656 \value SelectAll Selects all content.
1657 \value PasteAndMatchStyle Paste content from the clipboard with current style.
1658 \value RemoveFormat Removes formatting and style.
1659 \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1660 \value ToggleSubscript Toggle the formatting between subscript and baseline.
1661 \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1662 \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1663 \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1664 \value Indent Increases the indentation of the currently selected format block by one increment.
1665 \value Outdent Decreases the indentation of the currently selected format block by one increment.
1666 \value AlignCenter Applies center alignment to content.
1667 \value AlignJustified Applies full justification to content.
1668 \value AlignLeft Applies left justification to content.
1669 \value AlignRight Applies right justification to content.
1670
1671
1672 \omitvalue WebActionCount
1673
1674 */
1675
1676 /*!
1677 \enum QWebPage::WebWindowType
1678
1679 \value WebBrowserWindow The window is a regular web browser window.
1680 \value WebModalDialog The window acts as modal dialog.
1681 */
1682
1683 /*!
1684 \class QWebPage
1685 \since 4.4
1686 \brief The QWebPage class provides an object to view and edit web documents.
1687
1688 \inmodule QtWebKit
1689
1690 QWebPage holds a main frame responsible for web content, settings, the history
1691 of navigated links and actions. This class can be used, together with QWebFrame,
1692 to provide functionality like QWebView in a widget-less environment.
1693
1694 QWebPage's API is very similar to QWebView, as you are still provided with
1695 common functions like action() (known as \l{QWebView::}{pageAction()} in
1696 QWebView), triggerAction(), findText() and settings(). More QWebView-like
1697 functions can be found in the main frame of QWebPage, obtained via
1698 QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1699 unctions for QWebPage can be accessed using QWebFrame.
1700
1701 The loadStarted() signal is emitted when the page begins to load.The
1702 loadProgress() signal, on the other hand, is emitted whenever an element
1703 of the web page completes loading, such as an embedded image, a script,
1704 etc. Finally, the loadFinished() signal is emitted when the page has
1705 loaded completely. Its argument, either true or false, indicates whether
1706 or not the load operation succeeded.
1707
1708 \section1 Using QWebPage in a Widget-less Environment
1709
1710 Before you begin painting a QWebPage object, you need to set the size of
1711 the viewport by calling setViewportSize(). Then, you invoke the main
1712 frame's render function (QWebFrame::render()). An example of this
1713 is shown in the code snippet below.
1714
1715 Suppose we have a \c Thumbnail class as follows:
1716
1717 \snippet webkitsnippets/webpage/main.cpp 0
1718
1719 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1720 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1721 \c render().
1722
1723 \snippet webkitsnippets/webpage/main.cpp 1
1724
1725 The \c render() function shows how we can paint a thumbnail using a
1726 QWebPage object.
1727
1728 \snippet webkitsnippets/webpage/main.cpp 2
1729
1730 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1731 then we instantiate a QImage object, \c image, with the same size as our
1732 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1733 as a parameter to \c painter. Next, we render the contents of the main
1734 frame and its subframes into \c painter. Finally, we save the scaled image.
1735
1736 \sa QWebFrame
1737 */
1738
1739 /*!
1740 Constructs an empty QWebPage with parent \a parent.
1741 */
QWebPage(QObject * parent)1742 QWebPage::QWebPage(QObject *parent)
1743 : QObject(parent)
1744 , d(new QWebPagePrivate(this))
1745 {
1746 setView(qobject_cast<QWidget *>(parent));
1747
1748 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1749 #ifndef NDEBUG
1750 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1751 #endif
1752 }
1753
1754 /*!
1755 Destroys the web page.
1756 */
~QWebPage()1757 QWebPage::~QWebPage()
1758 {
1759 d->createMainFrame();
1760 FrameLoader *loader = d->mainFrame->d->frame->loader();
1761 if (loader)
1762 loader->detachFromParent();
1763 if (d->inspector) {
1764 // Since we have to delete an internal inspector,
1765 // call setInspector(0) directly to prevent potential crashes
1766 if (d->inspectorIsInternalOnly)
1767 d->setInspector(0);
1768 else
1769 d->inspector->setPage(0);
1770 }
1771 delete d;
1772 }
1773
1774 /*!
1775 Returns the main frame of the page.
1776
1777 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1778 want to explicitly render a web page into a given painter.
1779
1780 \sa currentFrame()
1781 */
mainFrame() const1782 QWebFrame *QWebPage::mainFrame() const
1783 {
1784 d->createMainFrame();
1785 return d->mainFrame;
1786 }
1787
1788 /*!
1789 Returns the frame currently active.
1790
1791 \sa mainFrame(), frameCreated()
1792 */
currentFrame() const1793 QWebFrame *QWebPage::currentFrame() const
1794 {
1795 d->createMainFrame();
1796 return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1797 }
1798
1799
1800 /*!
1801 \since 4.6
1802
1803 Returns the frame at the given point \a pos.
1804
1805 \sa mainFrame(), currentFrame()
1806 */
frameAt(const QPoint & pos) const1807 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1808 {
1809 QWebFrame* webFrame = mainFrame();
1810 if (!webFrame->geometry().contains(pos))
1811 return 0;
1812 QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1813 return hitTestResult.frame();
1814 }
1815
1816 /*!
1817 Returns a pointer to the view's history of navigated web pages.
1818 */
history() const1819 QWebHistory *QWebPage::history() const
1820 {
1821 d->createMainFrame();
1822 return &d->history;
1823 }
1824
1825 /*!
1826 Sets the \a view that is associated with the web page.
1827
1828 \sa view()
1829 */
setView(QWidget * view)1830 void QWebPage::setView(QWidget *view)
1831 {
1832 if (this->view() != view) {
1833 d->view = view;
1834 if (!view) {
1835 delete d->client;
1836 d->client = 0;
1837 } else {
1838 if (!d->client)
1839 d->client = new QWebPageWidgetClient(view);
1840 else
1841 static_cast<QWebPageWidgetClient*>(d->client)->view = view;
1842 }
1843 setViewportSize(view ? view->size() : QSize(0, 0));
1844 }
1845 }
1846
1847 /*!
1848 Returns the view widget that is associated with the web page.
1849
1850 \sa setView()
1851 */
view() const1852 QWidget *QWebPage::view() const
1853 {
1854 #if QT_VERSION < 0x040600
1855 return d->view;
1856 #else
1857 return d->view.data();
1858 #endif
1859 }
1860
1861 /*!
1862 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1863
1864 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1865
1866 The default implementation prints nothing.
1867 */
javaScriptConsoleMessage(const QString & message,int lineNumber,const QString & sourceID)1868 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1869 {
1870 Q_UNUSED(message)
1871 Q_UNUSED(lineNumber)
1872 Q_UNUSED(sourceID)
1873 }
1874
1875 /*!
1876 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1877 the message \a msg.
1878
1879 The default implementation shows the message, \a msg, with QMessageBox::information.
1880 */
javaScriptAlert(QWebFrame * frame,const QString & msg)1881 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1882 {
1883 Q_UNUSED(frame)
1884 #ifndef QT_NO_MESSAGEBOX
1885 QMessageBox::information(view(), tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
1886 #endif
1887 }
1888
1889 /*!
1890 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1891 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1892
1893 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1894 */
javaScriptConfirm(QWebFrame * frame,const QString & msg)1895 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1896 {
1897 Q_UNUSED(frame)
1898 #ifdef QT_NO_MESSAGEBOX
1899 return true;
1900 #else
1901 return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
1902 #endif
1903 }
1904
1905 /*!
1906 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1907 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1908
1909 If the prompt was cancelled by the user the implementation should return false; otherwise the
1910 result should be written to \a result and true should be returned. If the prompt was not cancelled by the
1911 user, the implementation should return true and the result string must not be null.
1912
1913 The default implementation uses QInputDialog::getText.
1914 */
javaScriptPrompt(QWebFrame * frame,const QString & msg,const QString & defaultValue,QString * result)1915 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1916 {
1917 Q_UNUSED(frame)
1918 bool ok = false;
1919 #ifndef QT_NO_INPUTDIALOG
1920 QString x = QInputDialog::getText(view(), tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
1921 if (ok && result)
1922 *result = x;
1923 #endif
1924 return ok;
1925 }
1926
1927 /*!
1928 \fn bool QWebPage::shouldInterruptJavaScript()
1929 \since 4.6
1930 This function is called when a JavaScript program is running for a long period of time.
1931
1932 If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1933
1934 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1935
1936 \warning Because of binary compatibility constraints, this function is not virtual. If you want to
1937 provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
1938 slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
1939 */
shouldInterruptJavaScript()1940 bool QWebPage::shouldInterruptJavaScript()
1941 {
1942 #ifdef QT_NO_MESSAGEBOX
1943 return false;
1944 #else
1945 return QMessageBox::Yes == QMessageBox::information(view(), 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);
1946 #endif
1947 }
1948
1949 /*!
1950 This function is called whenever WebKit wants to create a new window of the given \a type, for
1951 example when a JavaScript program requests to open a document in a new window.
1952
1953 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1954
1955 If the view associated with the web page is a QWebView object, then the default implementation forwards
1956 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1957
1958 If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
1959
1960 \sa acceptNavigationRequest()
1961 */
createWindow(WebWindowType type)1962 QWebPage *QWebPage::createWindow(WebWindowType type)
1963 {
1964 QWebView *webView = qobject_cast<QWebView *>(view());
1965 if (webView) {
1966 QWebView *newView = webView->createWindow(type);
1967 if (newView)
1968 return newView->page();
1969 }
1970 return 0;
1971 }
1972
1973 /*!
1974 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1975 The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1976 child elements to configure the embeddable object.
1977 */
createPlugin(const QString & classid,const QUrl & url,const QStringList & paramNames,const QStringList & paramValues)1978 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues)
1979 {
1980 Q_UNUSED(classid)
1981 Q_UNUSED(url)
1982 Q_UNUSED(paramNames)
1983 Q_UNUSED(paramValues)
1984 return 0;
1985 }
1986
frameLoadRequest(const QUrl & url,WebCore::Frame * frame)1987 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1988 {
1989 WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1990 return WebCore::FrameLoadRequest(rr);
1991 }
1992
openNewWindow(const QUrl & url,WebCore::Frame * frame)1993 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1994 {
1995 if (Page* oldPage = frame->page()) {
1996 WindowFeatures features;
1997 if (Page* newPage = oldPage->chrome()->createWindow(frame,
1998 frameLoadRequest(url, frame), features))
1999 newPage->chrome()->show();
2000 }
2001 }
2002
2003 /*!
2004 This function can be called to trigger the specified \a action.
2005 It is also called by QtWebKit if the user triggers the action, for example
2006 through a context menu item.
2007
2008 If \a action is a checkable action then \a checked specified whether the action
2009 is toggled or not.
2010
2011 \sa action()
2012 */
triggerAction(WebAction action,bool)2013 void QWebPage::triggerAction(WebAction action, bool)
2014 {
2015 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2016 if (!frame)
2017 return;
2018 WebCore::Editor *editor = frame->editor();
2019 const char *command = 0;
2020
2021 switch (action) {
2022 case OpenLink:
2023 if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2024 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2025 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2026 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2027 /*FormState*/ 0, SendReferrer);
2028 break;
2029 }
2030 // fall through
2031 case OpenLinkInNewWindow:
2032 openNewWindow(d->hitTestResult.linkUrl(), frame);
2033 break;
2034 case OpenFrameInNewWindow: {
2035 KURL url = frame->loader()->documentLoader()->unreachableURL();
2036 if (url.isEmpty())
2037 url = frame->loader()->documentLoader()->url();
2038 openNewWindow(url, frame);
2039 break;
2040 }
2041 case CopyLinkToClipboard: {
2042 #if defined(Q_WS_X11)
2043 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2044 Pasteboard::generalPasteboard()->setSelectionMode(true);
2045 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2046 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2047 #endif
2048 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2049 break;
2050 }
2051 case OpenImageInNewWindow:
2052 openNewWindow(d->hitTestResult.imageUrl(), frame);
2053 break;
2054 case DownloadImageToDisk:
2055 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2056 break;
2057 case DownloadLinkToDisk:
2058 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2059 break;
2060 #ifndef QT_NO_CLIPBOARD
2061 case CopyImageToClipboard:
2062 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2063 break;
2064 #endif
2065 case Back:
2066 d->page->goBack();
2067 break;
2068 case Forward:
2069 d->page->goForward();
2070 break;
2071 case Stop:
2072 mainFrame()->d->frame->loader()->stopForUserCancel();
2073 break;
2074 case Reload:
2075 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2076 break;
2077 case ReloadAndBypassCache:
2078 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2079 break;
2080 case SetTextDirectionDefault:
2081 editor->setBaseWritingDirection(NaturalWritingDirection);
2082 break;
2083 case SetTextDirectionLeftToRight:
2084 editor->setBaseWritingDirection(LeftToRightWritingDirection);
2085 break;
2086 case SetTextDirectionRightToLeft:
2087 editor->setBaseWritingDirection(RightToLeftWritingDirection);
2088 break;
2089 case InspectElement: {
2090 #if ENABLE(INSPECTOR)
2091 if (!d->hitTestResult.isNull()) {
2092 d->getOrCreateInspector(); // Make sure the inspector is created
2093 d->inspector->show(); // The inspector is expected to be shown on inspection
2094 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2095 }
2096 #endif
2097 break;
2098 }
2099 default:
2100 command = QWebPagePrivate::editorCommandForWebActions(action);
2101 break;
2102 }
2103
2104 if (command)
2105 editor->command(command).execute();
2106 }
2107
viewportSize() const2108 QSize QWebPage::viewportSize() const
2109 {
2110 if (d->mainFrame && d->mainFrame->d->frame->view())
2111 return d->mainFrame->d->frame->view()->frameRect().size();
2112
2113 return d->viewportSize;
2114 }
2115
2116 /*!
2117 \property QWebPage::viewportSize
2118 \brief the size of the viewport
2119
2120 The size affects for example the visibility of scrollbars
2121 if the document is larger than the viewport.
2122
2123 By default, for a newly-created Web page, this property contains a size with
2124 zero width and height.
2125 */
setViewportSize(const QSize & size) const2126 void QWebPage::setViewportSize(const QSize &size) const
2127 {
2128 d->viewportSize = size;
2129
2130 QWebFrame *frame = mainFrame();
2131 if (frame->d->frame && frame->d->frame->view()) {
2132 WebCore::FrameView* view = frame->d->frame->view();
2133 view->setFrameRect(QRect(QPoint(0, 0), size));
2134 view->forceLayout();
2135 view->adjustViewSize();
2136 }
2137 }
2138
preferredContentsSize() const2139 QSize QWebPage::preferredContentsSize() const
2140 {
2141 QWebFrame* frame = d->mainFrame;
2142 if (frame) {
2143 WebCore::FrameView* view = frame->d->frame->view();
2144 if (view && view->useFixedLayout())
2145 return d->mainFrame->d->frame->view()->fixedLayoutSize();
2146 }
2147
2148 return d->fixedLayoutSize;
2149 }
2150
2151 /*!
2152 \property QWebPage::preferredContentsSize
2153 \since 4.6
2154 \brief the size of the fixed layout
2155
2156 The size affects the layout of the page in the viewport. If set to a fixed size of
2157 1024x768 for example then webkit will layout the page as if the viewport were that size
2158 rather than something different.
2159 */
setPreferredContentsSize(const QSize & size) const2160 void QWebPage::setPreferredContentsSize(const QSize &size) const
2161 {
2162 d->fixedLayoutSize = size;
2163
2164 QWebFrame *frame = mainFrame();
2165 if (frame->d->frame && frame->d->frame->view()) {
2166 WebCore::FrameView* view = frame->d->frame->view();
2167
2168 if (size.isValid()) {
2169 view->setUseFixedLayout(true);
2170 view->setFixedLayoutSize(size);
2171 view->forceLayout();
2172 } else if (view->useFixedLayout()) {
2173 view->setUseFixedLayout(false);
2174 view->forceLayout();
2175 }
2176 }
2177 }
2178
2179 /*!
2180 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2181
2182 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2183 the specified navigation type \a type.
2184
2185 If \a frame is a null pointer then navigation to a new window is requested. If the request is
2186 accepted createWindow() will be called.
2187
2188 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2189 to let QWebPage handle the navigation itself.
2190
2191 \sa createWindow()
2192 */
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)2193 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2194 {
2195 Q_UNUSED(frame)
2196 if (type == NavigationTypeLinkClicked) {
2197 switch (d->linkPolicy) {
2198 case DontDelegateLinks:
2199 return true;
2200
2201 case DelegateExternalLinks:
2202 if (WebCore::SecurityOrigin::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2203 return true;
2204 emit linkClicked(request.url());
2205 return false;
2206
2207 case DelegateAllLinks:
2208 emit linkClicked(request.url());
2209 return false;
2210 }
2211 }
2212 return true;
2213 }
2214
2215 /*!
2216 \property QWebPage::selectedText
2217 \brief the text currently selected
2218
2219 By default, this property contains an empty string.
2220
2221 \sa selectionChanged()
2222 */
selectedText() const2223 QString QWebPage::selectedText() const
2224 {
2225 d->createMainFrame();
2226 return d->page->focusController()->focusedOrMainFrame()->selectedText();
2227 }
2228
2229 /*!
2230 Returns a QAction for the specified WebAction \a action.
2231
2232 The action is owned by the QWebPage but you can customize the look by
2233 changing its properties.
2234
2235 QWebPage also takes care of implementing the action, so that upon
2236 triggering the corresponding action is performed on the page.
2237
2238 \sa triggerAction()
2239 */
action(WebAction action) const2240 QAction *QWebPage::action(WebAction action) const
2241 {
2242 if (action == QWebPage::NoWebAction) return 0;
2243 if (d->actions[action])
2244 return d->actions[action];
2245
2246 QString text;
2247 QIcon icon;
2248 QStyle *style = view() ? view()->style() : qApp->style();
2249 bool checkable = false;
2250
2251 switch (action) {
2252 case OpenLink:
2253 text = contextMenuItemTagOpenLink();
2254 break;
2255 case OpenLinkInNewWindow:
2256 text = contextMenuItemTagOpenLinkInNewWindow();
2257 break;
2258 case OpenFrameInNewWindow:
2259 text = contextMenuItemTagOpenFrameInNewWindow();
2260 break;
2261
2262 case DownloadLinkToDisk:
2263 text = contextMenuItemTagDownloadLinkToDisk();
2264 break;
2265 case CopyLinkToClipboard:
2266 text = contextMenuItemTagCopyLinkToClipboard();
2267 break;
2268
2269 case OpenImageInNewWindow:
2270 text = contextMenuItemTagOpenImageInNewWindow();
2271 break;
2272 case DownloadImageToDisk:
2273 text = contextMenuItemTagDownloadImageToDisk();
2274 break;
2275 case CopyImageToClipboard:
2276 text = contextMenuItemTagCopyImageToClipboard();
2277 break;
2278
2279 case Back:
2280 text = contextMenuItemTagGoBack();
2281 icon = style->standardIcon(QStyle::SP_ArrowBack);
2282 break;
2283 case Forward:
2284 text = contextMenuItemTagGoForward();
2285 icon = style->standardIcon(QStyle::SP_ArrowForward);
2286 break;
2287 case Stop:
2288 text = contextMenuItemTagStop();
2289 icon = style->standardIcon(QStyle::SP_BrowserStop);
2290 break;
2291 case Reload:
2292 text = contextMenuItemTagReload();
2293 icon = style->standardIcon(QStyle::SP_BrowserReload);
2294 break;
2295
2296 case Cut:
2297 text = contextMenuItemTagCut();
2298 break;
2299 case Copy:
2300 text = contextMenuItemTagCopy();
2301 break;
2302 case Paste:
2303 text = contextMenuItemTagPaste();
2304 break;
2305 #ifndef QT_NO_UNDOSTACK
2306 case Undo: {
2307 QAction *a = undoStack()->createUndoAction(d->q);
2308 d->actions[action] = a;
2309 return a;
2310 }
2311 case Redo: {
2312 QAction *a = undoStack()->createRedoAction(d->q);
2313 d->actions[action] = a;
2314 return a;
2315 }
2316 #endif // QT_NO_UNDOSTACK
2317 case MoveToNextChar:
2318 text = tr("Move the cursor to the next character");
2319 break;
2320 case MoveToPreviousChar:
2321 text = tr("Move the cursor to the previous character");
2322 break;
2323 case MoveToNextWord:
2324 text = tr("Move the cursor to the next word");
2325 break;
2326 case MoveToPreviousWord:
2327 text = tr("Move the cursor to the previous word");
2328 break;
2329 case MoveToNextLine:
2330 text = tr("Move the cursor to the next line");
2331 break;
2332 case MoveToPreviousLine:
2333 text = tr("Move the cursor to the previous line");
2334 break;
2335 case MoveToStartOfLine:
2336 text = tr("Move the cursor to the start of the line");
2337 break;
2338 case MoveToEndOfLine:
2339 text = tr("Move the cursor to the end of the line");
2340 break;
2341 case MoveToStartOfBlock:
2342 text = tr("Move the cursor to the start of the block");
2343 break;
2344 case MoveToEndOfBlock:
2345 text = tr("Move the cursor to the end of the block");
2346 break;
2347 case MoveToStartOfDocument:
2348 text = tr("Move the cursor to the start of the document");
2349 break;
2350 case MoveToEndOfDocument:
2351 text = tr("Move the cursor to the end of the document");
2352 break;
2353 case SelectAll:
2354 text = tr("Select all");
2355 break;
2356 case SelectNextChar:
2357 text = tr("Select to the next character");
2358 break;
2359 case SelectPreviousChar:
2360 text = tr("Select to the previous character");
2361 break;
2362 case SelectNextWord:
2363 text = tr("Select to the next word");
2364 break;
2365 case SelectPreviousWord:
2366 text = tr("Select to the previous word");
2367 break;
2368 case SelectNextLine:
2369 text = tr("Select to the next line");
2370 break;
2371 case SelectPreviousLine:
2372 text = tr("Select to the previous line");
2373 break;
2374 case SelectStartOfLine:
2375 text = tr("Select to the start of the line");
2376 break;
2377 case SelectEndOfLine:
2378 text = tr("Select to the end of the line");
2379 break;
2380 case SelectStartOfBlock:
2381 text = tr("Select to the start of the block");
2382 break;
2383 case SelectEndOfBlock:
2384 text = tr("Select to the end of the block");
2385 break;
2386 case SelectStartOfDocument:
2387 text = tr("Select to the start of the document");
2388 break;
2389 case SelectEndOfDocument:
2390 text = tr("Select to the end of the document");
2391 break;
2392 case DeleteStartOfWord:
2393 text = tr("Delete to the start of the word");
2394 break;
2395 case DeleteEndOfWord:
2396 text = tr("Delete to the end of the word");
2397 break;
2398
2399 case SetTextDirectionDefault:
2400 text = contextMenuItemTagDefaultDirection();
2401 break;
2402 case SetTextDirectionLeftToRight:
2403 text = contextMenuItemTagLeftToRight();
2404 checkable = true;
2405 break;
2406 case SetTextDirectionRightToLeft:
2407 text = contextMenuItemTagRightToLeft();
2408 checkable = true;
2409 break;
2410
2411 case ToggleBold:
2412 text = contextMenuItemTagBold();
2413 checkable = true;
2414 break;
2415 case ToggleItalic:
2416 text = contextMenuItemTagItalic();
2417 checkable = true;
2418 break;
2419 case ToggleUnderline:
2420 text = contextMenuItemTagUnderline();
2421 checkable = true;
2422 break;
2423
2424 case InspectElement:
2425 text = contextMenuItemTagInspectElement();
2426 break;
2427
2428 case InsertParagraphSeparator:
2429 text = tr("Insert a new paragraph");
2430 break;
2431 case InsertLineSeparator:
2432 text = tr("Insert a new line");
2433 break;
2434
2435 case PasteAndMatchStyle:
2436 text = tr("Paste and Match Style");
2437 break;
2438 case RemoveFormat:
2439 text = tr("Remove formatting");
2440 break;
2441
2442 case ToggleStrikethrough:
2443 text = tr("Strikethrough");
2444 checkable = true;
2445 break;
2446 case ToggleSubscript:
2447 text = tr("Subscript");
2448 checkable = true;
2449 break;
2450 case ToggleSuperscript:
2451 text = tr("Superscript");
2452 checkable = true;
2453 break;
2454 case InsertUnorderedList:
2455 text = tr("Insert Bulleted List");
2456 checkable = true;
2457 break;
2458 case InsertOrderedList:
2459 text = tr("Insert Numbered List");
2460 checkable = true;
2461 break;
2462 case Indent:
2463 text = tr("Indent");
2464 break;
2465 case Outdent:
2466 text = tr("Outdent");
2467 break;
2468 case AlignCenter:
2469 text = tr("Center");
2470 break;
2471 case AlignJustified:
2472 text = tr("Justify");
2473 break;
2474 case AlignLeft:
2475 text = tr("Align Left");
2476 break;
2477 case AlignRight:
2478 text = tr("Align Right");
2479 break;
2480
2481 case NoWebAction:
2482 return 0;
2483 }
2484
2485 if (text.isEmpty())
2486 return 0;
2487
2488 QAction *a = new QAction(d->q);
2489 a->setText(text);
2490 a->setData(action);
2491 a->setCheckable(checkable);
2492 a->setIcon(icon);
2493
2494 connect(a, SIGNAL(triggered(bool)),
2495 this, SLOT(_q_webActionTriggered(bool)));
2496
2497 d->actions[action] = a;
2498 d->updateAction(action);
2499 return a;
2500 }
2501
2502 /*!
2503 \property QWebPage::modified
2504 \brief whether the page contains unsubmitted form data
2505
2506 By default, this property is false.
2507 */
isModified() const2508 bool QWebPage::isModified() const
2509 {
2510 #ifdef QT_NO_UNDOSTACK
2511 return false;
2512 #else
2513 if (!d->undoStack)
2514 return false;
2515 return d->undoStack->canUndo();
2516 #endif // QT_NO_UNDOSTACK
2517 }
2518
2519 #ifndef QT_NO_UNDOSTACK
2520 /*!
2521 Returns a pointer to the undo stack used for editable content.
2522 */
undoStack() const2523 QUndoStack *QWebPage::undoStack() const
2524 {
2525 if (!d->undoStack)
2526 d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2527
2528 return d->undoStack;
2529 }
2530 #endif // QT_NO_UNDOSTACK
2531
2532 /*! \reimp
2533 */
event(QEvent * ev)2534 bool QWebPage::event(QEvent *ev)
2535 {
2536 switch (ev->type()) {
2537 case QEvent::Timer:
2538 d->timerEvent(static_cast<QTimerEvent*>(ev));
2539 break;
2540 case QEvent::MouseMove:
2541 d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2542 break;
2543 case QEvent::GraphicsSceneMouseMove:
2544 d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2545 break;
2546 case QEvent::MouseButtonPress:
2547 d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2548 break;
2549 case QEvent::GraphicsSceneMousePress:
2550 d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2551 break;
2552 case QEvent::MouseButtonDblClick:
2553 d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2554 break;
2555 case QEvent::GraphicsSceneMouseDoubleClick:
2556 d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2557 break;
2558 case QEvent::MouseButtonRelease:
2559 d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2560 break;
2561 case QEvent::GraphicsSceneMouseRelease:
2562 d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2563 break;
2564 #ifndef QT_NO_CONTEXTMENU
2565 case QEvent::ContextMenu:
2566 d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
2567 break;
2568 case QEvent::GraphicsSceneContextMenu:
2569 d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
2570 break;
2571 #endif
2572 #ifndef QT_NO_WHEELEVENT
2573 case QEvent::Wheel:
2574 d->wheelEvent(static_cast<QWheelEvent*>(ev));
2575 break;
2576 case QEvent::GraphicsSceneWheel:
2577 d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
2578 break;
2579 #endif
2580 case QEvent::KeyPress:
2581 d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2582 break;
2583 case QEvent::KeyRelease:
2584 d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2585 break;
2586 case QEvent::FocusIn:
2587 d->focusInEvent(static_cast<QFocusEvent*>(ev));
2588 break;
2589 case QEvent::FocusOut:
2590 d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2591 break;
2592 #ifndef QT_NO_DRAGANDDROP
2593 case QEvent::DragEnter:
2594 d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2595 break;
2596 case QEvent::GraphicsSceneDragEnter:
2597 d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2598 break;
2599 case QEvent::DragLeave:
2600 d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
2601 break;
2602 case QEvent::GraphicsSceneDragLeave:
2603 d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2604 break;
2605 case QEvent::DragMove:
2606 d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2607 break;
2608 case QEvent::GraphicsSceneDragMove:
2609 d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2610 break;
2611 case QEvent::Drop:
2612 d->dropEvent(static_cast<QDropEvent*>(ev));
2613 break;
2614 case QEvent::GraphicsSceneDrop:
2615 d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2616 break;
2617 #endif
2618 case QEvent::InputMethod:
2619 d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2620 case QEvent::ShortcutOverride:
2621 d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2622 break;
2623 case QEvent::Leave:
2624 d->leaveEvent(ev);
2625 break;
2626 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
2627 case QEvent::TouchBegin:
2628 case QEvent::TouchUpdate:
2629 case QEvent::TouchEnd:
2630 d->touchEvent(static_cast<QTouchEvent*>(ev));
2631 break;
2632 #endif
2633 default:
2634 return QObject::event(ev);
2635 }
2636
2637 return true;
2638 }
2639
2640 /*!
2641 Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
2642 if \a next is true; otherwise the previous element is focused.
2643
2644 Returns true if it can find a new focusable element, or false if it can't.
2645 */
focusNextPrevChild(bool next)2646 bool QWebPage::focusNextPrevChild(bool next)
2647 {
2648 QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2649 d->keyPressEvent(&ev);
2650 bool hasFocusedNode = false;
2651 Frame *frame = d->page->focusController()->focusedFrame();
2652 if (frame) {
2653 Document *document = frame->document();
2654 hasFocusedNode = document && document->focusedNode();
2655 }
2656 //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
2657 return hasFocusedNode;
2658 }
2659
2660 /*!
2661 \property QWebPage::contentEditable
2662 \brief whether the content in this QWebPage is editable or not
2663 \since 4.5
2664
2665 If this property is enabled the contents of the page can be edited by the user through a visible
2666 cursor. If disabled (the default) only HTML elements in the web page with their
2667 \c{contenteditable} attribute set are editable.
2668 */
setContentEditable(bool editable)2669 void QWebPage::setContentEditable(bool editable)
2670 {
2671 if (d->editable != editable) {
2672 d->editable = editable;
2673 d->page->setTabKeyCyclesThroughElements(!editable);
2674 if (d->mainFrame) {
2675 WebCore::Frame* frame = d->mainFrame->d->frame;
2676 if (editable) {
2677 frame->applyEditingStyleToBodyElement();
2678 // FIXME: mac port calls this if there is no selectedDOMRange
2679 //frame->setSelectionFromNone();
2680 } else
2681 frame->removeEditingStyleFromBodyElement();
2682 }
2683
2684 d->updateEditorActions();
2685 }
2686 }
2687
isContentEditable() const2688 bool QWebPage::isContentEditable() const
2689 {
2690 return d->editable;
2691 }
2692
2693 /*!
2694 \property QWebPage::forwardUnsupportedContent
2695 \brief whether QWebPage should forward unsupported content
2696
2697 If enabled, the unsupportedContent() signal is emitted with a network reply that
2698 can be used to read the content.
2699
2700 If disabled, the download of such content is aborted immediately.
2701
2702 By default unsupported content is not forwarded.
2703 */
2704
setForwardUnsupportedContent(bool forward)2705 void QWebPage::setForwardUnsupportedContent(bool forward)
2706 {
2707 d->forwardUnsupportedContent = forward;
2708 }
2709
forwardUnsupportedContent() const2710 bool QWebPage::forwardUnsupportedContent() const
2711 {
2712 return d->forwardUnsupportedContent;
2713 }
2714
2715 /*!
2716 \property QWebPage::linkDelegationPolicy
2717 \brief how QWebPage should delegate the handling of links through the
2718 linkClicked() signal
2719
2720 The default is to delegate no links.
2721 */
2722
setLinkDelegationPolicy(LinkDelegationPolicy policy)2723 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2724 {
2725 d->linkPolicy = policy;
2726 }
2727
linkDelegationPolicy() const2728 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2729 {
2730 return d->linkPolicy;
2731 }
2732
2733 #ifndef QT_NO_CONTEXTMENU
2734 /*!
2735 Filters the context menu event, \a event, through handlers for scrollbars and
2736 custom event handlers in the web page. Returns true if the event was handled;
2737 otherwise false.
2738
2739 A web page may swallow a context menu event through a custom event handler, allowing for context
2740 menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2741 Maps}, for example.
2742 */
swallowContextMenuEvent(QContextMenuEvent * event)2743 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2744 {
2745 d->page->contextMenuController()->clearContextMenu();
2746
2747 if (QWebFrame* webFrame = frameAt(event->pos())) {
2748 Frame* frame = QWebFramePrivate::core(webFrame);
2749 if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
2750 return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
2751 }
2752
2753 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2754 focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
2755 ContextMenu *menu = d->page->contextMenuController()->contextMenu();
2756 // If the website defines its own handler then sendContextMenuEvent takes care of
2757 // calling/showing it and the context menu pointer will be zero. This is the case
2758 // on maps.google.com for example.
2759
2760 return !menu;
2761 }
2762 #endif // QT_NO_CONTEXTMENU
2763
2764 /*!
2765 Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2766 element the CopyImageToClipboard action is enabled.
2767 */
updatePositionDependentActions(const QPoint & pos)2768 void QWebPage::updatePositionDependentActions(const QPoint &pos)
2769 {
2770 // First we disable all actions, but keep track of which ones were originally enabled.
2771 QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2772 for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
2773 QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
2774 if (QAction *a = this->action(action)) {
2775 originallyEnabledWebActions.setBit(action, a->isEnabled());
2776 a->setEnabled(false);
2777 }
2778 }
2779
2780 d->createMainFrame();
2781 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2782 HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
2783
2784 if (result.scrollbar())
2785 d->hitTestResult = QWebHitTestResult();
2786 else
2787 d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
2788 WebCore::ContextMenu menu(result);
2789 menu.populate();
2790
2791 #if ENABLE(INSPECTOR)
2792 if (d->page->inspectorController()->enabled())
2793 menu.addInspectElementItem();
2794 #endif
2795
2796 QBitArray visitedWebActions(QWebPage::WebActionCount);
2797
2798 #ifndef QT_NO_CONTEXTMENU
2799 delete d->currentContextMenu;
2800
2801 // Then we let createContextMenu() enable the actions that are put into the menu
2802 d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
2803 #endif // QT_NO_CONTEXTMENU
2804
2805 // Finally, we restore the original enablement for the actions that were not put into the menu.
2806 originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2807 for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2808 if (originallyEnabledWebActions.at(i)) {
2809 if (QAction *a = this->action(QWebPage::WebAction(i)))
2810 a->setEnabled(true);
2811 }
2812 }
2813
2814 // This whole process ensures that any actions put into to the context menu has the right
2815 // enablement, while also keeping the correct enablement for actions that were left out of
2816 // the menu.
2817
2818 }
2819
2820
2821
2822 /*!
2823 \enum QWebPage::Extension
2824
2825 This enum describes the types of extensions that the page can support. Before using these extensions, you
2826 should verify that the extension is supported by calling supportsExtension().
2827
2828 \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2829 This extension is invoked when the web content requests one or more file names, for example
2830 as a result of the user clicking on a "file upload" button in a HTML form where multiple
2831 file selection is allowed.
2832
2833 \omitvalue ErrorPageExtension (introduced in Qt 4.6)
2834 */
2835
2836 /*!
2837 \enum QWebPage::ErrorDomain
2838 \since 4.6
2839 \internal
2840
2841 \value QtNetwork
2842 \value Http
2843 \value WebKit
2844 */
2845
2846 /*!
2847 \class QWebPage::ExtensionOption
2848 \since 4.4
2849 \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2850
2851 \inmodule QtWebKit
2852
2853 \sa QWebPage::extension()
2854 */
2855
2856 /*!
2857 \class QWebPage::ErrorPageExtensionOption
2858 \since 4.6
2859 \brief The ErrorPageExtensionOption class describes the option
2860 for the error page extension.
2861
2862 \inmodule QtWebKit
2863
2864 The ErrorPageExtensionOption class holds the \a url for which an error occoured as well as
2865 the associated \a frame.
2866
2867 The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
2868
2869 \sa QWebPage::ErrorPageExtensionReturn
2870 */
2871
2872 /*!
2873 \class QWebPage::ErrorPageExtensionReturn
2874 \since 4.6
2875 \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
2876 frame for which the error occured.
2877
2878 \inmodule QtWebKit
2879
2880 The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
2881 optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
2882 is assumed to be UTF-8 if not indicated otherwise.
2883
2884 The error page is stored in the \a content byte array, as HTML content. In order to convert a
2885 QString to a byte array, the QString::toUtf8() method can be used.
2886
2887 External objects such as stylesheets or images referenced in the HTML are located relative to
2888 \a baseUrl.
2889
2890 \sa QWebPage::ErrorPageExtensionOption, QString::toUtf8()
2891 */
2892
2893 /*!
2894 \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
2895
2896 Constructs a new error page object.
2897 */
2898
2899 /*!
2900 \class QWebPage::ChooseMultipleFilesExtensionOption
2901 \since 4.5
2902 \brief The ChooseMultipleFilesExtensionOption class describes the option
2903 for the multiple files selection extension.
2904
2905 \inmodule QtWebKit
2906
2907 The ChooseMultipleFilesExtensionOption class holds the frame originating the request
2908 and the suggested filenames which might be provided.
2909
2910 \sa QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
2911 */
2912
2913 /*!
2914 \class QWebPage::ChooseMultipleFilesExtensionReturn
2915 \since 4.5
2916 \brief The ChooseMultipleFilesExtensionReturn describes the return value
2917 for the multiple files selection extension.
2918
2919 \inmodule QtWebKit
2920
2921 The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
2922 when the extension is invoked.
2923
2924 \sa QWebPage::ChooseMultipleFilesExtensionOption
2925 */
2926
2927 /*!
2928 This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
2929 argument is provided as input to the extension; the output results can be stored in \a output.
2930
2931 The behavior of this function is determined by \a extension.
2932
2933 You can call supportsExtension() to check if an extension is supported by the page.
2934
2935 Returns true if the extension was called successfully; otherwise returns false.
2936
2937 \sa supportsExtension(), Extension
2938 */
extension(Extension extension,const ExtensionOption * option,ExtensionReturn * output)2939 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
2940 {
2941 #ifndef QT_NO_FILEDIALOG
2942 if (extension == ChooseMultipleFilesExtension) {
2943 // FIXME: do not ignore suggestedFiles
2944 QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
2945 QStringList names = QFileDialog::getOpenFileNames(view(), QString::null);
2946 static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
2947 return true;
2948 }
2949 #endif
2950
2951 return false;
2952 }
2953
2954 /*!
2955 This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2956
2957 \sa extension()
2958 */
supportsExtension(Extension extension) const2959 bool QWebPage::supportsExtension(Extension extension) const
2960 {
2961 #ifndef QT_NO_FILEDIALOG
2962 return extension == ChooseMultipleFilesExtension;
2963 #else
2964 Q_UNUSED(extension);
2965 return false;
2966 #endif
2967 }
2968
2969 /*!
2970 Finds the specified string, \a subString, in the page, using the given \a options.
2971
2972 If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
2973 that exist in the page. All subsequent calls will extend the highlight, rather than
2974 replace it, with occurrences of the new string.
2975
2976 If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
2977 and all subsequent calls will replace the current occurrence with the next one.
2978
2979 To clear the selection, just pass an empty string.
2980
2981 Returns true if \a subString was found; otherwise returns false.
2982 */
findText(const QString & subString,FindFlags options)2983 bool QWebPage::findText(const QString &subString, FindFlags options)
2984 {
2985 ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
2986 if (options & FindCaseSensitively)
2987 caseSensitivity = ::TextCaseSensitive;
2988
2989 if (options & HighlightAllOccurrences) {
2990 if (subString.isEmpty()) {
2991 d->page->unmarkAllTextMatches();
2992 return true;
2993 } else
2994 return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
2995 } else {
2996 ::FindDirection direction = ::FindDirectionForward;
2997 if (options & FindBackward)
2998 direction = ::FindDirectionBackward;
2999
3000 const bool shouldWrap = options & FindWrapsAroundDocument;
3001
3002 return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3003 }
3004 }
3005
3006 /*!
3007 Returns a pointer to the page's settings object.
3008
3009 \sa QWebSettings::globalSettings()
3010 */
settings() const3011 QWebSettings *QWebPage::settings() const
3012 {
3013 return d->settings;
3014 }
3015
3016 /*!
3017 This function is called when the web content requests a file name, for example
3018 as a result of the user clicking on a "file upload" button in a HTML form.
3019
3020 A suggested filename may be provided in \a suggestedFile. The frame originating the
3021 request is provided as \a parentFrame.
3022 */
chooseFile(QWebFrame * parentFrame,const QString & suggestedFile)3023 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3024 {
3025 Q_UNUSED(parentFrame)
3026 #ifndef QT_NO_FILEDIALOG
3027 return QFileDialog::getOpenFileName(view(), QString::null, suggestedFile);
3028 #else
3029 return QString::null;
3030 #endif
3031 }
3032
3033 /*!
3034 Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3035 QWebPage.
3036
3037 \note It is currently not supported to change the network access manager after the
3038 QWebPage has used it. The results of doing this are undefined.
3039
3040 \sa networkAccessManager()
3041 */
setNetworkAccessManager(QNetworkAccessManager * manager)3042 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3043 {
3044 if (manager == d->networkManager)
3045 return;
3046 if (d->networkManager && d->networkManager->parent() == this)
3047 delete d->networkManager;
3048 d->networkManager = manager;
3049 }
3050
3051 /*!
3052 Returns the QNetworkAccessManager that is responsible for serving network
3053 requests for this QWebPage.
3054
3055 \sa setNetworkAccessManager()
3056 */
networkAccessManager() const3057 QNetworkAccessManager *QWebPage::networkAccessManager() const
3058 {
3059 if (!d->networkManager) {
3060 QWebPage *that = const_cast<QWebPage *>(this);
3061 that->d->networkManager = new QNetworkAccessManager(that);
3062 }
3063 return d->networkManager;
3064 }
3065
3066 /*!
3067 Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3068 QWebPage.
3069
3070 Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3071
3072 \sa pluginFactory()
3073 */
setPluginFactory(QWebPluginFactory * factory)3074 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3075 {
3076 d->pluginFactory = factory;
3077 }
3078
3079 /*!
3080 Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3081 this QWebPage. If no plugin factory is installed a null pointer is returned.
3082
3083 \sa setPluginFactory()
3084 */
pluginFactory() const3085 QWebPluginFactory *QWebPage::pluginFactory() const
3086 {
3087 return d->pluginFactory;
3088 }
3089
3090 /*!
3091 This function is called when a user agent for HTTP requests is needed. You can reimplement this
3092 function to dynamically return different user agents for different URLs, based on the \a url parameter.
3093
3094 The default implementation returns the following value:
3095
3096 "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3097
3098 In this string the following values are replaced at run-time:
3099 \list
3100 \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
3101 \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
3102 \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage,
3103 then a default constructed QLocale is used instead.
3104 \o %WebKitVersion% is the version of WebKit the application was compiled against.
3105 \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3106 \endlist
3107 */
userAgentForUrl(const QUrl & url) const3108 QString QWebPage::userAgentForUrl(const QUrl& url) const
3109 {
3110 Q_UNUSED(url)
3111 QString ua = QLatin1String("Mozilla/5.0 ("
3112
3113 // Platform
3114 #ifdef Q_WS_MAC
3115 "Macintosh"
3116 #elif defined Q_WS_QWS
3117 "QtEmbedded"
3118 #elif defined Q_WS_WIN
3119 "Windows"
3120 #elif defined Q_WS_X11
3121 "X11"
3122 #elif defined Q_OS_SYMBIAN
3123 "SymbianOS"
3124 #else
3125 "Unknown"
3126 #endif
3127 // Placeholder for Platform Version
3128 "%1; "
3129
3130 // Placeholder for security strength (N or U)
3131 "%2; "
3132
3133 // Subplatform"
3134 #ifdef Q_OS_AIX
3135 "AIX"
3136 #elif defined Q_OS_WIN32
3137 "%3"
3138 #elif defined Q_OS_DARWIN
3139 #ifdef __i386__ || __x86_64__
3140 "Intel Mac OS X"
3141 #else
3142 "PPC Mac OS X"
3143 #endif
3144
3145 #elif defined Q_OS_BSDI
3146 "BSD"
3147 #elif defined Q_OS_BSD4
3148 "BSD Four"
3149 #elif defined Q_OS_CYGWIN
3150 "Cygwin"
3151 #elif defined Q_OS_DGUX
3152 "DG/UX"
3153 #elif defined Q_OS_DYNIX
3154 "DYNIX/ptx"
3155 #elif defined Q_OS_FREEBSD
3156 "FreeBSD"
3157 #elif defined Q_OS_HPUX
3158 "HP-UX"
3159 #elif defined Q_OS_HURD
3160 "GNU Hurd"
3161 #elif defined Q_OS_IRIX
3162 "SGI Irix"
3163 #elif defined Q_OS_LINUX
3164 "Linux"
3165 #elif defined Q_OS_LYNX
3166 "LynxOS"
3167 #elif defined Q_OS_NETBSD
3168 "NetBSD"
3169 #elif defined Q_OS_OS2
3170 "OS/2"
3171 #elif defined Q_OS_OPENBSD
3172 "OpenBSD"
3173 #elif defined Q_OS_OS2EMX
3174 "OS/2"
3175 #elif defined Q_OS_OSF
3176 "HP Tru64 UNIX"
3177 #elif defined Q_OS_QNX6
3178 "QNX RTP Six"
3179 #elif defined Q_OS_QNX
3180 "QNX"
3181 #elif defined Q_OS_RELIANT
3182 "Reliant UNIX"
3183 #elif defined Q_OS_SCO
3184 "SCO OpenServer"
3185 #elif defined Q_OS_SOLARIS
3186 "Sun Solaris"
3187 #elif defined Q_OS_ULTRIX
3188 "DEC Ultrix"
3189 #elif defined Q_WS_S60
3190 "Series60"
3191 #elif defined Q_OS_UNIX
3192 "UNIX BSD/SYSV system"
3193 #elif defined Q_OS_UNIXWARE
3194 "UnixWare Seven, Open UNIX Eight"
3195 #else
3196 "Unknown"
3197 #endif
3198 // Placeholder for SubPlatform Version
3199 "%4; ");
3200
3201 // Platform Version
3202 QString osVer;
3203 #ifdef Q_OS_SYMBIAN
3204 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3205 switch (symbianVersion) {
3206 case QSysInfo::SV_9_2:
3207 osVer = "/9.2";
3208 break;
3209 case QSysInfo::SV_9_3:
3210 osVer = "/9.3";
3211 break;
3212 case QSysInfo::SV_9_4:
3213 osVer = "/9.4";
3214 break;
3215 default:
3216 osVer = "Unknown";
3217 }
3218 #endif
3219 ua = ua.arg(osVer);
3220
3221 QChar securityStrength(QLatin1Char('N'));
3222 #if !defined(QT_NO_OPENSSL)
3223 // we could check QSslSocket::supportsSsl() here, but this makes
3224 // OpenSSL, certificates etc being loaded in all cases were QWebPage
3225 // is used. This loading is not needed for non-https.
3226 securityStrength = QLatin1Char('U');
3227 // this may lead to a false positive: We indicate SSL since it is
3228 // compiled in even though supportsSsl() might return false
3229 #endif
3230 ua = ua.arg(securityStrength);
3231
3232 #if defined Q_OS_WIN32
3233 QString ver;
3234 switch (QSysInfo::WindowsVersion) {
3235 case QSysInfo::WV_32s:
3236 ver = "Windows 3.1";
3237 break;
3238 case QSysInfo::WV_95:
3239 ver = "Windows 95";
3240 break;
3241 case QSysInfo::WV_98:
3242 ver = "Windows 98";
3243 break;
3244 case QSysInfo::WV_Me:
3245 ver = "Windows 98; Win 9x 4.90";
3246 break;
3247 case QSysInfo::WV_NT:
3248 ver = "WinNT4.0";
3249 break;
3250 case QSysInfo::WV_2000:
3251 ver = "Windows NT 5.0";
3252 break;
3253 case QSysInfo::WV_XP:
3254 ver = "Windows NT 5.1";
3255 break;
3256 case QSysInfo::WV_2003:
3257 ver = "Windows NT 5.2";
3258 break;
3259 case QSysInfo::WV_VISTA:
3260 ver = "Windows NT 6.0";
3261 break;
3262 #if QT_VERSION > 0x040500
3263 case QSysInfo::WV_WINDOWS7:
3264 ver = "Windows NT 6.1";
3265 break;
3266 #endif
3267 case QSysInfo::WV_CE:
3268 ver = "Windows CE";
3269 break;
3270 case QSysInfo::WV_CENET:
3271 ver = "Windows CE .NET";
3272 break;
3273 case QSysInfo::WV_CE_5:
3274 ver = "Windows CE 5.x";
3275 break;
3276 case QSysInfo::WV_CE_6:
3277 ver = "Windows CE 6.x";
3278 break;
3279 }
3280 ua = QString(ua).arg(ver);
3281 #endif
3282
3283 // SubPlatform Version
3284 QString subPlatformVer;
3285 #ifdef Q_OS_SYMBIAN
3286 QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3287 switch (s60Version) {
3288 case QSysInfo::SV_S60_3_1:
3289 subPlatformVer = "/3.1";
3290 break;
3291 case QSysInfo::SV_S60_3_2:
3292 subPlatformVer = "/3.2";
3293 break;
3294 case QSysInfo::SV_S60_5_0:
3295 subPlatformVer = "/5.0";
3296 break;
3297 default:
3298 subPlatformVer = " Unknown";
3299 }
3300 #endif
3301 ua = ua.arg(subPlatformVer);
3302
3303 // Language
3304 QLocale locale;
3305 if (view())
3306 locale = view()->locale();
3307 QString name = locale.name();
3308 name[2] = QLatin1Char('-');
3309 ua.append(name);
3310 ua.append(QLatin1String(") "));
3311
3312 // webkit/qt version
3313 ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) "))
3314 .arg(QString(qWebKitVersion())));
3315
3316 // Application name/version
3317 QString appName = QCoreApplication::applicationName();
3318 if (!appName.isEmpty()) {
3319 ua.append(appName);
3320 QString appVer = QCoreApplication::applicationVersion();
3321 if (!appVer.isEmpty())
3322 ua.append(QLatin1Char('/') + appVer);
3323 } else {
3324 // Qt version
3325 ua.append(QLatin1String("Qt/"));
3326 ua.append(QLatin1String(qVersion()));
3327 }
3328
3329 ua.append(QString(QLatin1String(" Safari/%1"))
3330 .arg(qWebKitVersion()));
3331
3332 return ua;
3333 }
3334
3335
_q_onLoadProgressChanged(int)3336 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3337 {
3338 m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3339 m_bytesReceived = page->progress()->totalBytesReceived();
3340 }
3341
3342
3343 /*!
3344 Returns the total number of bytes that were received from the network to render the current page,
3345 including extra content such as embedded images.
3346
3347 \sa bytesReceived()
3348 */
totalBytes() const3349 quint64 QWebPage::totalBytes() const
3350 {
3351 return d->m_totalBytes;
3352 }
3353
3354
3355 /*!
3356 Returns the number of bytes that were received from the network to render the current page.
3357
3358 \sa totalBytes()
3359 */
bytesReceived() const3360 quint64 QWebPage::bytesReceived() const
3361 {
3362 return d->m_bytesReceived;
3363 }
3364
3365 /*!
3366 \fn void QWebPage::loadStarted()
3367
3368 This signal is emitted when a new load of the page is started.
3369
3370 \sa loadFinished()
3371 */
3372
3373 /*!
3374 \fn void QWebPage::loadProgress(int progress)
3375
3376 This signal is emitted when the global progress status changes.
3377 The current value is provided by \a progress and scales from 0 to 100,
3378 which is the default range of QProgressBar.
3379 It accumulates changes from all the child frames.
3380
3381 \sa bytesReceived()
3382 */
3383
3384 /*!
3385 \fn void QWebPage::loadFinished(bool ok)
3386
3387 This signal is emitted when a load of the page is finished.
3388 \a ok will indicate whether the load was successful or any error occurred.
3389
3390 \sa loadStarted()
3391 */
3392
3393 /*!
3394 \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3395
3396 This signal is emitted when the mouse hovers over a link.
3397
3398 \a link contains the link url.
3399 \a title is the link element's title, if it is specified in the markup.
3400 \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3401
3402 When the mouse leaves the link element the signal is emitted with empty parameters.
3403
3404 \sa linkClicked()
3405 */
3406
3407 /*!
3408 \fn void QWebPage::statusBarMessage(const QString& text)
3409
3410 This signal is emitted when the statusbar \a text is changed by the page.
3411 */
3412
3413 /*!
3414 \fn void QWebPage::frameCreated(QWebFrame *frame)
3415
3416 This signal is emitted whenever the page creates a new \a frame.
3417 */
3418
3419 /*!
3420 \fn void QWebPage::selectionChanged()
3421
3422 This signal is emitted whenever the selection changes.
3423
3424 \sa selectedText()
3425 */
3426
3427 /*!
3428 \fn void QWebPage::contentsChanged()
3429 \since 4.5
3430
3431 This signal is emitted whenever the text in form elements changes
3432 as well as other editable content.
3433
3434 \sa contentEditable, QWebFrame::toHtml(), QWebFrame::toPlainText()
3435 */
3436
3437 /*!
3438 \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3439
3440 This signal is emitted whenever the document wants to change the position and size of the
3441 page to \a geom. This can happen for example through JavaScript.
3442 */
3443
3444 /*!
3445 \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3446
3447 This signal is emitted whenever this QWebPage should be updated and no view was set.
3448 \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3449 the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3450 \a dirtyRect as the second parameter.
3451
3452 \sa mainFrame()
3453 \sa view()
3454 */
3455
3456 /*!
3457 \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3458
3459 This signal is emitted whenever the content given by \a rectToScroll needs
3460 to be scrolled \a dx and \a dy downwards and no view was set.
3461
3462 \sa view()
3463 */
3464
3465 /*!
3466 \fn void QWebPage::windowCloseRequested()
3467
3468 This signal is emitted whenever the page requests the web browser window to be closed,
3469 for example through the JavaScript \c{window.close()} call.
3470 */
3471
3472 /*!
3473 \fn void QWebPage::printRequested(QWebFrame *frame)
3474
3475 This signal is emitted whenever the page requests the web browser to print \a frame,
3476 for example through the JavaScript \c{window.print()} call.
3477
3478 \sa QWebFrame::print(), QPrintPreviewDialog
3479 */
3480
3481 /*!
3482 \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3483
3484 This signal is emitted when WebKit cannot handle a link the user navigated to.
3485
3486 At signal emission time the meta-data of the QNetworkReply \a reply is available.
3487
3488 \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3489
3490 \sa downloadRequested()
3491 */
3492
3493 /*!
3494 \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3495
3496 This signal is emitted when the user decides to download a link. The url of
3497 the link as well as additional meta-information is contained in \a request.
3498
3499 \sa unsupportedContent()
3500 */
3501
3502 /*!
3503 \fn void QWebPage::microFocusChanged()
3504
3505 This signal is emitted when for example the position of the cursor in an editable form
3506 element changes. It is used inform input methods about the new on-screen position where
3507 the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
3508 slot.
3509 */
3510
3511 /*!
3512 \fn void QWebPage::linkClicked(const QUrl &url)
3513
3514 This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3515 property is set to delegate the link handling for the specified \a url.
3516
3517 By default no links are delegated and are handled by QWebPage instead.
3518
3519 \sa linkHovered()
3520 */
3521
3522 /*!
3523 \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3524
3525 This signal is emitted whenever the visibility of the toolbar in a web browser
3526 window that hosts QWebPage should be changed to \a visible.
3527 */
3528
3529 /*!
3530 \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3531
3532 This signal is emitted whenever the visibility of the statusbar in a web browser
3533 window that hosts QWebPage should be changed to \a visible.
3534 */
3535
3536 /*!
3537 \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3538
3539 This signal is emitted whenever the visibility of the menubar in a web browser
3540 window that hosts QWebPage should be changed to \a visible.
3541 */
3542
3543 /*!
3544 \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3545 \since 4.5
3546
3547 This signal is emitted whenever the web site shown in \a frame is asking to store data
3548 to the database \a databaseName and the quota allocated to that web site is exceeded.
3549 */
3550
3551 /*!
3552 \since 4.5
3553 \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3554
3555 This signal is emitted shortly before the history of navigated pages
3556 in \a frame is changed, for example when navigating back in the history.
3557
3558 The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3559 the change.
3560
3561 A potential use-case for this signal is to store custom data in
3562 the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3563 */
3564
3565 /*!
3566 \since 4.5
3567 \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3568
3569 This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3570 */
3571
3572 /*!
3573 \fn QWebPagePrivate* QWebPage::handle() const
3574 \internal
3575 */
3576
3577 #include "moc_qwebpage.cpp"
3578