2 Copyright (C) 2007 Trolltech ASA
3 Copyright (C) 2007 Staikos Computing Services Inc.
4 Copyright (C) 2007 Apple Inc.
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.
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.
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.
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 "qwebsettings.h"
33 #include "FrameTree.h"
34 #include "FrameLoaderClientQt.h"
35 #include "FrameView.h"
36 #include "ChromeClientQt.h"
37 #include "ContextMenu.h"
38 #include "ContextMenuClientQt.h"
39 #include "DocumentLoader.h"
40 #include "DragClientQt.h"
41 #include "DragController.h"
43 #include "EditorClientQt.h"
46 #include "Pasteboard.h"
47 #include "FrameLoader.h"
48 #include "FrameLoadRequest.h"
52 #include "InspectorClientQt.h"
53 #include "InspectorController.h"
54 #include "FocusController.h"
56 #include "PlatformScrollBar.h"
57 #include "PlatformKeyboardEvent.h"
58 #include "PlatformWheelEvent.h"
59 #include "ProgressTracker.h"
62 #include "HitTestResult.h"
63 #include "WindowFeatures.h"
64 #include "LocalizedStrings.h"
66 #include <QApplication>
67 #include <QBasicTimer>
70 #include <QDragEnterEvent>
71 #include <QDragLeaveEvent>
72 #include <QDragMoveEvent>
74 #include <QFileDialog>
75 #include <QHttpRequestHeader>
76 #include <QInputDialog>
77 #include <QMessageBox>
78 #include <QNetworkProxy>
85 #if QT_VERSION >= 0x040400
86 #include <QNetworkAccessManager>
87 #include <QNetworkRequest>
89 #include "qwebnetworkinterface.h"
92 using namespace WebCore;
94 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
95 static const char* editorCommandWebActions[] =
99 0, // OpenLinkInNewWindow,
100 0, // OpenFrameInNewWindow,
102 0, // DownloadLinkToDisk,
103 0, // CopyLinkToClipboard,
105 0, // OpenImageInNewWindow,
106 0, // DownloadImageToDisk,
107 0, // CopyImageToClipboard,
120 "MoveForward", // MoveToNextChar,
121 "MoveBackward", // MoveToPreviousChar,
122 "MoveWordForward", // MoveToNextWord,
123 "MoveWordBackward", // MoveToPreviousWord,
124 "MoveDown", // MoveToNextLine,
125 "MoveUp", // MoveToPreviousLine,
126 "MoveToBeginningOfLine", // MoveToStartOfLine,
127 "MoveToEndOfLine", // MoveToEndOfLine,
128 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
129 "MoveToEndOfParagraph", // MoveToEndOfBlock,
130 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
131 "MoveToEndOfDocument", // MoveToEndOfDocument,
132 "MoveForwardAndModifySelection", // SelectNextChar,
133 "MoveBackwardAndModifySelection", // SelectPreviousChar,
134 "MoveWordForwardAndModifySelection", // SelectNextWord,
135 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
136 "MoveDownAndModifySelection", // SelectNextLine,
137 "MoveUpAndModifySelection", // SelectPreviousLine,
138 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
139 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
140 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
141 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
142 "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
143 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
144 "DeleteWordBackward", // DeleteStartOfWord,
145 "DeleteWordForward", // DeleteEndOfWord,
147 0, // SetTextDirectionDefault,
148 0, // SetTextDirectionLeftToRight,
149 0, // SetTextDirectionRightToLeft,
151 "ToggleBold", // ToggleBold,
152 "ToggleItalic", // ToggleItalic,
153 "ToggleUnderline", // ToggleUnderline,
155 0, // InspectElement,
160 // Lookup the appropriate editor command to use for WebAction \a action
161 static const char* editorCommandForWebActions(QWebPage::WebAction action)
163 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
164 return editorCommandWebActions[action];
170 SetCursorEvent::SetCursorEvent(const QCursor& cursor)
171 : QEvent(static_cast<QEvent::Type>(EventType))
175 QCursor SetCursorEvent::cursor() const
181 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
182 #define WEBKIT_VERSION "527+"
184 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
187 if (actions & Qt::CopyAction)
188 result |= DragOperationCopy;
189 if (actions & Qt::MoveAction)
190 result |= DragOperationMove;
191 if (actions & Qt::LinkAction)
192 result |= DragOperationLink;
193 return (DragOperation)result;
196 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
198 Qt::DropAction result = Qt::IgnoreAction;
199 if (actions & DragOperationCopy)
200 result = Qt::CopyAction;
201 else if (actions & DragOperationMove)
202 result = Qt::MoveAction;
203 else if (actions & DragOperationLink)
204 result = Qt::LinkAction;
208 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
212 , viewportSize(QSize(0,0))
214 WebCore::InitializeLoggingChannelsIfNecessary();
216 chromeClient = new ChromeClientQt(q);
217 contextMenuClient = new ContextMenuClientQt();
218 editorClient = new EditorClientQt(q);
219 page = new Page(chromeClient, contextMenuClient, editorClient,
220 new DragClientQt(q), new InspectorClientQt(q));
222 // ### should be configurable
223 page->settings()->setDefaultTextEncodingName("iso-8859-1");
225 settings = new QWebSettings(page->settings());
229 #if QT_VERSION < 0x040400
230 networkInterface = 0;
235 insideOpenCall = false;
236 forwardUnsupportedContent = false;
238 linkPolicy = QWebPage::DontDelegateLinks;
239 currentContextMenu = 0;
241 history.d = new QWebHistoryPrivate(page->backForwardList());
242 memset(actions, 0, sizeof(actions));
245 QWebPagePrivate::~QWebPagePrivate()
247 delete currentContextMenu;
253 #if QT_VERSION < 0x040400
254 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
257 && frame == mainFrame)
259 return q->acceptNavigationRequest(frame, request, type);
262 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
265 && frame == mainFrame)
267 return q->acceptNavigationRequest(frame, request, type);
271 void QWebPagePrivate::createMainFrame()
274 QWebFrameData frameData;
275 frameData.ownerElement = 0;
276 frameData.allowsScrolling = true;
277 frameData.marginWidth = 0;
278 frameData.marginHeight = 0;
279 mainFrame = new QWebFrame(q, &frameData);
281 emit q->frameCreated(mainFrame);
285 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
288 case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
289 case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
290 case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
291 case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
292 case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
293 case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
294 case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
295 case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
296 case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
297 case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
298 case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
299 case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
300 case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
301 case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
302 case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
303 case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
304 case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
305 case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
306 case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
307 case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
308 case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
309 case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
312 return QWebPage::NoWebAction;
315 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
316 const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
318 QMenu* menu = new QMenu(view);
319 for (int i = 0; i < items->count(); ++i) {
320 const ContextMenuItem &item = items->at(i);
321 switch (item.type()) {
322 case WebCore::CheckableActionType: /* fall through */
323 case WebCore::ActionType: {
324 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
325 QAction *a = q->action(action);
327 ContextMenuItem it(item);
328 webcoreMenu->checkOrEnableIfNeeded(it);
329 PlatformMenuItemDescription desc = it.releasePlatformDescription();
330 a->setEnabled(desc.enabled);
331 a->setChecked(desc.checked);
332 a->setCheckable(item.type() == WebCore::CheckableActionType);
335 visitedWebActions->setBit(action);
339 case WebCore::SeparatorType:
340 menu->addSeparator();
342 case WebCore::SubmenuType: {
343 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
345 bool anyEnabledAction = false;
347 QList<QAction *> actions = subMenu->actions();
348 for (int i = 0; i < actions.count(); ++i) {
349 if (actions.at(i)->isVisible())
350 anyEnabledAction |= actions.at(i)->isEnabled();
353 // don't show sub-menus with just disabled actions
354 if (anyEnabledAction) {
355 subMenu->setTitle(item.title());
356 menu->addAction(subMenu->menuAction());
367 QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const
369 QWebFrame *frame = mainFrame;
372 QList<QWebFrame*> children = frame->childFrames();
373 for (int i = 0; i < children.size(); ++i) {
374 if (children.at(i)->geometry().contains(pos)) {
375 frame = children.at(i);
379 if (frame->geometry().contains(pos))
384 void QWebPagePrivate::_q_webActionTriggered(bool checked)
386 QAction *a = qobject_cast<QAction *>(q->sender());
389 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
390 q->triggerAction(action, checked);
393 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
395 QAction *a = actions[action];
396 if (!a || !mainFrame)
399 WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
400 WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
402 bool enabled = a->isEnabled();
403 bool checked = a->isChecked();
407 enabled = loader->canGoBackOrForward(-1);
409 case QWebPage::Forward:
410 enabled = loader->canGoBackOrForward(1);
413 enabled = loader->isLoading();
415 case QWebPage::Reload:
416 enabled = !loader->isLoading();
419 enabled = editor->canCut();
422 enabled = editor->canCopy();
424 case QWebPage::Paste:
425 enabled = editor->canPaste();
429 // those two are handled by QUndoStack
431 case QWebPage::ToggleBold:
432 case QWebPage::ToggleItalic:
433 case QWebPage::ToggleUnderline:
434 enabled = editor->canEditRichly();
436 checked = editor->command(editorCommandForWebActions(action)).state() != FalseTriState;
443 a->setEnabled(enabled);
445 if (a->isCheckable())
446 a->setChecked(checked);
449 void QWebPagePrivate::updateNavigationActions()
451 updateAction(QWebPage::Back);
452 updateAction(QWebPage::Forward);
453 updateAction(QWebPage::Stop);
454 updateAction(QWebPage::Reload);
457 void QWebPagePrivate::updateEditorActions()
459 updateAction(QWebPage::Cut);
460 updateAction(QWebPage::Copy);
461 updateAction(QWebPage::Paste);
462 updateAction(QWebPage::ToggleBold);
463 updateAction(QWebPage::ToggleItalic);
464 updateAction(QWebPage::ToggleUnderline);
467 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
469 int timerId = ev->timerId();
470 if (timerId == tripleClickTimer.timerId())
471 tripleClickTimer.stop();
473 q->QObject::timerEvent(ev);
476 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
478 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
482 bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
483 ev->setAccepted(accepted);
486 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
488 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
492 if (tripleClickTimer.isActive()
493 && (ev->pos() - tripleClick).manhattanLength()
494 < QApplication::startDragDistance()) {
495 mouseTripleClickEvent(ev);
499 bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1));
500 ev->setAccepted(accepted);
503 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
505 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
509 bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2));
510 ev->setAccepted(accepted);
512 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
513 tripleClick = ev->pos();
516 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
518 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
522 bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 3));
523 ev->setAccepted(accepted);
526 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
528 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
532 bool accepted = frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0));
533 ev->setAccepted(accepted);
535 #ifndef QT_NO_CLIPBOARD
536 if (QApplication::clipboard()->supportsSelection()) {
537 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
538 Pasteboard::generalPasteboard()->setSelectionMode(true);
539 WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
540 if (ev->button() == Qt::LeftButton) {
541 if(focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
542 focusFrame->editor()->copy();
543 ev->setAccepted(true);
545 } else if (ev->button() == Qt::MidButton) {
546 if(focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
547 focusFrame->editor()->paste();
548 ev->setAccepted(true);
551 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
556 void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev)
558 QMenu *menu = q->createStandardContextMenu();
560 menu->exec(ev->globalPos());
567 This function creates the standard context menu which is shown when
568 the user clicks on the web page with the right mouse button. It is
569 called from the default contextMenuEvent() handler. The popup menu's
570 ownership is transferred to the caller.
572 QMenu *QWebPage::createStandardContextMenu()
574 QMenu *menu = d->currentContextMenu;
575 d->currentContextMenu = 0;
579 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
581 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
585 WebCore::PlatformWheelEvent pev(ev);
586 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
587 ev->setAccepted(accepted);
590 static QWebPage::WebAction editorActionForKeyEvent(QKeyEvent* event)
593 QKeySequence::StandardKey standardKey;
594 QWebPage::WebAction action;
595 } editorActions[32] = {
596 { QKeySequence::Cut, QWebPage::Cut },
597 { QKeySequence::Copy, QWebPage::Copy },
598 { QKeySequence::Paste, QWebPage::Paste },
599 { QKeySequence::Undo, QWebPage::Undo },
600 { QKeySequence::Redo, QWebPage::Redo },
601 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
602 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
603 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
604 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
605 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
606 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
607 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
608 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
609 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
610 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
611 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
612 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
613 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
614 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
615 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
616 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
617 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
618 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
619 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
620 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
621 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
622 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
623 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
624 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
625 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
626 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
627 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
630 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
631 if (event == editorActions[i].standardKey)
632 return editorActions[i].action;
634 return QWebPage::NoWebAction;
637 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
639 bool handled = false;
640 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
641 WebCore::Editor* editor = frame->editor();
642 if (editor->canEdit()) {
643 QWebPage::WebAction action = editorActionForKeyEvent(ev);
644 if (action != QWebPage::NoWebAction) {
645 q->triggerAction(action);
649 if (ev == QKeySequence::Copy) {
650 q->triggerAction(QWebPage::Copy);
655 handled = frame->eventHandler()->keyEvent(ev);
660 defaultFont = view->font();
661 QFontMetrics fm(defaultFont);
662 int fontHeight = fm.height();
663 if (!handleScrolling(ev)) {
665 case Qt::Key_Backspace:
666 if (ev->modifiers() == Qt::ShiftModifier)
667 q->triggerAction(QWebPage::Forward);
669 q->triggerAction(QWebPage::Back);
677 ev->setAccepted(handled);
680 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
682 if (ev->isAutoRepeat()) {
683 ev->setAccepted(true);
687 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
688 bool handled = frame->eventHandler()->keyEvent(ev);
689 ev->setAccepted(handled);
692 void QWebPagePrivate::focusInEvent(QFocusEvent *ev)
694 if (ev->reason() == Qt::PopupFocusReason)
697 FocusController *focusController = page->focusController();
698 Frame *frame = focusController->focusedFrame();
699 focusController->setActive(true);
701 frame->selection()->setFocused(true);
703 focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
707 void QWebPagePrivate::focusOutEvent(QFocusEvent *ev)
709 if (ev->reason() == Qt::PopupFocusReason)
712 // only set the focused frame inactive so that we stop painting the caret
713 // and the focus frame. But don't tell the focus controller so that upon
714 // focusInEvent() we can re-activate the frame.
715 FocusController *focusController = page->focusController();
716 focusController->setActive(false);
717 Frame *frame = focusController->focusedFrame();
719 frame->selection()->setFocused(false);
723 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev)
725 #ifndef QT_NO_DRAGANDDROP
726 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
727 dropActionToDragOp(ev->possibleActions()));
728 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
729 ev->setDropAction(action);
734 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev)
736 #ifndef QT_NO_DRAGANDDROP
737 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
738 page->dragController()->dragExited(&dragData);
743 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev)
745 #ifndef QT_NO_DRAGANDDROP
746 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
747 dropActionToDragOp(ev->possibleActions()));
748 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
749 ev->setDropAction(action);
754 void QWebPagePrivate::dropEvent(QDropEvent *ev)
756 #ifndef QT_NO_DRAGANDDROP
757 DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
758 dropActionToDragOp(ev->possibleActions()));
759 Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData));
764 void QWebPagePrivate::leaveEvent(QEvent *ev)
766 // Fake a mouse move event just outside of the widget, since all
767 // the interesting mouse-out behavior like invalidating scrollbars
768 // is handled by the WebKit event handler's mouseMoved function.
769 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
770 mouseMoveEvent(&fakeEvent);
774 \property QWebPage::palette
775 \brief the page's palette
777 The background brush of the palette is used to draw the background of the main frame.
779 void QWebPage::setPalette(const QPalette &pal)
783 d->mainFrame->d->updateBackground();
786 QPalette QWebPage::palette() const
791 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
793 WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
794 WebCore::Editor *editor = frame->editor();
796 if (!editor->canEdit()) {
801 if (!ev->preeditString().isEmpty()) {
802 QString preedit = ev->preeditString();
803 // ### FIXME: use the provided QTextCharFormat (use color at least)
804 Vector<CompositionUnderline> underlines;
805 underlines.append(CompositionUnderline(0, preedit.length(), Color(0,0,0), false));
806 editor->setComposition(preedit, underlines, preedit.length(), 0);
807 } else if (!ev->commitString().isEmpty()) {
808 editor->confirmComposition(ev->commitString());
813 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
815 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
816 WebCore::Editor* editor = frame->editor();
817 if (editor->canEdit()) {
818 if (event->modifiers() == Qt::NoModifier
819 || event->modifiers() == Qt::ShiftModifier
820 || event->modifiers() == Qt::KeypadModifier) {
821 if (event->key() < Qt::Key_Escape) {
824 switch (event->key()) {
830 case Qt::Key_Backspace:
842 #ifndef QT_NO_SHORTCUT
843 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction) {
850 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev)
852 ScrollDirection direction;
853 ScrollGranularity granularity;
855 if (ev == QKeySequence::MoveToNextPage
856 || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
857 granularity = ScrollByPage;
858 direction = ScrollDown;
859 } else if (ev == QKeySequence::MoveToPreviousPage
860 || (ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier)) {
861 granularity = ScrollByPage;
862 direction = ScrollUp;
863 } else if (ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier
864 || ev->key() == Qt::Key_Home) {
865 granularity = ScrollByDocument;
866 direction = ScrollUp;
867 } else if (ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier
868 || ev->key() == Qt::Key_End) {
869 granularity = ScrollByDocument;
870 direction = ScrollDown;
874 granularity = ScrollByLine;
875 direction = ScrollUp;
878 granularity = ScrollByLine;
879 direction = ScrollDown;
882 granularity = ScrollByLine;
883 direction = ScrollLeft;
886 granularity = ScrollByLine;
887 direction = ScrollRight;
894 if (!mainFrame->d->frame->eventHandler()->scrollOverflow(direction, granularity))
895 mainFrame->d->frame->view()->scroll(direction, granularity);
901 This method is used by the input method to query a set of properties of the page
902 to be able to support complex input method operations as support for surrounding
903 text and reconversions.
905 \a property specifies which property is queried.
907 \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
909 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
912 case Qt::ImMicroFocus: {
913 Frame *frame = d->page->focusController()->focusedFrame();
915 return QVariant(frame->selection()->caretRect());
920 QWebView *webView = qobject_cast<QWebView *>(d->view);
922 return QVariant(webView->font());
925 case Qt::ImCursorPosition: {
926 Frame *frame = d->page->focusController()->focusedFrame();
928 Selection selection = frame->selection()->selection();
929 if (selection.isCaret()) {
930 return QVariant(selection.start().offset());
935 case Qt::ImSurroundingText: {
936 Frame *frame = d->page->focusController()->focusedFrame();
938 Document *document = frame->document();
939 if (document->focusedNode()) {
940 return QVariant(document->focusedNode()->nodeValue());
945 case Qt::ImCurrentSelection:
946 return QVariant(selectedText());
953 \enum QWebPage::FindFlag
955 This enum describes the options available to QWebPage's findText() function. The options
956 can be OR-ed together from the following list:
958 \value FindBackward Searches backwards instead of forwards.
959 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
960 changes the behaviour to a case sensitive find operation.
961 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
962 was reached and the text was not found.
966 \enum QWebPage::LinkDelegationPolicy
968 This enum defines the delegation policies a webpage can have when activating links and emitting
969 the linkClicked() signal.
971 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
972 \value DelegateExternalLinks When activating links that point to documents not stored on the
973 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
974 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
978 \enum QWebPage::NavigationType
980 This enum describes the types of navigation available when browsing through hyperlinked
983 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
984 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
985 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
986 \value NavigationTypeReload The user activated the reload action.
987 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
988 \value NavigationTypeOther A navigation to another document using a method not listed above.
992 \enum QWebPage::WebAction
994 \value NoWebAction No action is triggered.
995 \value OpenLink Open the current link.
996 \value OpenLinkInNewWindow Open the current link in a new window.
997 \value OpenFrameInNewWindow Replicate the current frame in a new window.
998 \value DownloadLinkToDisk Download the current link to the disk.
999 \value CopyLinkToClipboard Copy the current link to the clipboard.
1000 \value OpenImageInNewWindow Open the highlighted image in a new window.
1001 \value DownloadImageToDisk Download the highlighted image to the disk.
1002 \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1003 \value Back Navigate back in the history of navigated links.
1004 \value Forward Navigate forward in the history of navigated links.
1005 \value Stop Stop loading the current page.
1006 \value Reload Reload the current page.
1007 \value Cut Cut the content currently selected into the clipboard.
1008 \value Copy Copy the content currently selected into the clipboard.
1009 \value Paste Paste content from the clipboard.
1010 \value Undo Undo the last editing action.
1011 \value Redo Redo the last editing action.
1012 \value MoveToNextChar Move the cursor to the next character.
1013 \value MoveToPreviousChar Move the cursor to the previous character.
1014 \value MoveToNextWord Move the cursor to the next word.
1015 \value MoveToPreviousWord Move the cursor to the previous word.
1016 \value MoveToNextLine Move the cursor to the next line.
1017 \value MoveToPreviousLine Move the cursor to the previous line.
1018 \value MoveToStartOfLine Move the cursor to the start of the line.
1019 \value MoveToEndOfLine Move the cursor to the end of the line.
1020 \value MoveToStartOfBlock Move the cursor to the start of the block.
1021 \value MoveToEndOfBlock Move the cursor to the end of the block.
1022 \value MoveToStartOfDocument Move the cursor to the start of the document.
1023 \value MoveToEndOfDocument Move the cursor to the end of the document.
1024 \value SelectNextChar Select to the next character.
1025 \value SelectPreviousChar Select to the previous character.
1026 \value SelectNextWord Select to the next word.
1027 \value SelectPreviousWord Select to the previous word.
1028 \value SelectNextLine Select to the next line.
1029 \value SelectPreviousLine Select to the previous line.
1030 \value SelectStartOfLine Select to the start of the line.
1031 \value SelectEndOfLine Select to the end of the line.
1032 \value SelectStartOfBlock Select to the start of the block.
1033 \value SelectEndOfBlock Select to the end of the block.
1034 \value SelectStartOfDocument Select to the start of the document.
1035 \value SelectEndOfDocument Select to the end of the document.
1036 \value DeleteStartOfWord Delete to the start of the word.
1037 \value DeleteEndOfWord Delete to the end of the word.
1038 \value SetTextDirectionDefault Set the text direction to the default direction.
1039 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1040 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1041 \value ToggleBold Toggle the formatting between bold and normal weight.
1042 \value ToggleItalic Toggle the formatting between italic and normal style.
1043 \value ToggleUnderline Toggle underlining.
1044 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1045 \omitvalue WebActionCount
1050 \enum QWebPage::WebWindowType
1052 \value WebBrowserWindow The window is a regular web browser window.
1053 \value WebModalDialog The window acts as modal dialog.
1059 \brief The QWebPage class provides an object to view and edit web documents.
1061 QWebPage holds a main frame responsible for web content, settings, the history
1062 of navigated links and actions. This class can be used, together with QWebFrame,
1063 to provide functionality like QWebView in a widget-less environment.
1065 QWebPage's API is very similar to QWebView, as you are still provided with
1066 common functions like action() (known as \l{QWebView::}{pageAction()} in
1067 QWebView), triggerAction(), findText() and settings(). More QWebView-like
1068 functions can be found in the main frame of QWebPage, obtained via
1069 QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1070 unctions for QWebPage can be accessed using QWebFrame.
1072 The loadStarted() signal is emitted when the page begins to load.The
1073 loadProgress() signal, on the other hand, is emitted whenever an element
1074 of the web page completes loading, such as an embedded image, a script,
1075 etc. Finally, the loadFinished() signal is emitted when the page has
1076 loaded completely. Its argument, either true or false, indicates whether
1077 or not the load operation succeeded.
1079 \section1 Using QWebPage in a Widget-less Environment
1081 Before you begin painting a QWebPage object, you need to set the size of
1082 the viewport by calling setViewportSize(). Then, you invoke the main
1083 frame's render function (QWebFrame::render()). An example of this
1084 is shown in the code snippet below.
1086 Suppose we have a \c Thumbnail class as follows:
1088 \snippet doc/src/snippets/webkit/webpage/main.cpp 0
1090 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1091 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1094 \snippet doc/src/snippets/webkit/webpage/main.cpp 1
1096 The \c render() function shows how we can paint a thumbnail using a
1099 \snippet doc/src/snippets/webkit/webpage/main.cpp 2
1101 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1102 then we instantiate a QImage object, \c image, with the same size as our
1103 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1104 as a parameter to \c painter. Next, we render the contents of the main
1105 frame and its subframes into \c painter. Finally, we save the scaled image.
1111 Constructs an empty QWebView with parent \a parent.
1113 QWebPage::QWebPage(QObject *parent)
1115 , d(new QWebPagePrivate(this))
1117 setView(qobject_cast<QWidget *>(parent));
1119 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1123 Destroys the web page.
1125 QWebPage::~QWebPage()
1127 FrameLoader *loader = d->mainFrame->d->frame->loader();
1129 loader->detachFromParent();
1134 Returns the main frame of the page.
1136 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1137 want to explicitly render a web page into a given painter.
1141 QWebFrame *QWebPage::mainFrame() const
1143 d->createMainFrame();
1144 return d->mainFrame;
1148 Returns the frame currently active.
1150 \sa mainFrame(), frameCreated()
1152 QWebFrame *QWebPage::currentFrame() const
1154 return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1158 Returns a pointer to the view's history of navigated web pages.
1160 QWebHistory *QWebPage::history() const
1166 Sets the \a view that is associated with the web page.
1170 void QWebPage::setView(QWidget *view)
1173 setViewportSize(view ? view->size() : QSize(0, 0));
1177 Returns the view widget that is associated with the web page.
1181 QWidget *QWebPage::view() const
1187 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1189 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1191 The default implementation prints nothing.
1193 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1196 Q_UNUSED(lineNumber)
1201 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1204 The default implementation shows the message, \a msg, with QMessageBox::information.
1206 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1208 QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok);
1212 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1213 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1215 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1217 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1219 return QMessageBox::Yes == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No);
1223 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1224 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1226 If the prompt was cancelled by the user the implementation should return false; otherwise the
1227 result should be written to \a result and true should be returned.
1229 The default implementation uses QInputDialog::getText.
1231 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1234 #ifndef QT_NO_INPUTDIALOG
1235 QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok);
1244 This function is called whenever WebKit wants to create a new window of the given \a type, for
1245 example when a JavaScript program requests to open a document in a new window.
1247 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1249 If the view associated with the web page is a QWebView object, then the default implementation forwards
1250 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1252 \sa acceptNavigationRequest()
1254 QWebPage *QWebPage::createWindow(WebWindowType type)
1256 QWebView *webView = qobject_cast<QWebView *>(d->view);
1258 QWebView *newView = webView->createWindow(type);
1260 return newView->page();
1266 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1267 The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1268 child elements to configure the embeddable object.
1270 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues)
1274 Q_UNUSED(paramNames)
1275 Q_UNUSED(paramValues)
1279 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1281 WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1282 return WebCore::FrameLoadRequest(rr);
1285 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1287 if (Page* oldPage = frame->page()) {
1288 WindowFeatures features;
1289 if (Page* newPage = oldPage->chrome()->createWindow(frame,
1290 frameLoadRequest(url, frame), features))
1291 newPage->chrome()->show();
1296 This function can be called to trigger the specified \a action.
1297 It is also called by QtWebKit if the user triggers the action, for example
1298 through a context menu item.
1300 If \a action is a checkable action then \a checked specified whether the action
1305 void QWebPage::triggerAction(WebAction action, bool checked)
1307 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
1310 WebCore::Editor *editor = frame->editor();
1311 const char *command = 0;
1315 if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
1316 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
1317 targetFrame->d->frame->loader()->loadFrameRequestWithFormAndValues(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
1318 /*lockHistory*/ false, /*event*/ 0,
1319 /*HTMLFormElement*/ 0, /*formValues*/
1320 WTF::HashMap<String, String>());
1324 case OpenLinkInNewWindow:
1325 openNewWindow(d->hitTestResult.linkUrl(), frame);
1327 case OpenFrameInNewWindow: {
1328 KURL url = frame->loader()->documentLoader()->unreachableURL();
1330 url = frame->loader()->documentLoader()->url();
1331 openNewWindow(url, frame);
1334 case CopyLinkToClipboard:
1335 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
1337 case OpenImageInNewWindow:
1338 openNewWindow(d->hitTestResult.imageUrl(), frame);
1340 case DownloadImageToDisk:
1341 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
1343 case DownloadLinkToDisk:
1344 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
1346 #ifndef QT_NO_CLIPBOARD
1347 case CopyImageToClipboard:
1348 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1355 d->page->goForward();
1358 mainFrame()->d->frame->loader()->stopForUserCancel();
1361 mainFrame()->d->frame->loader()->reload();
1363 case SetTextDirectionDefault:
1364 editor->setBaseWritingDirection(NaturalWritingDirection);
1366 case SetTextDirectionLeftToRight:
1367 editor->setBaseWritingDirection(LeftToRightWritingDirection);
1369 case SetTextDirectionRightToLeft:
1370 editor->setBaseWritingDirection(RightToLeftWritingDirection);
1372 case InspectElement:
1373 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
1376 command = editorCommandForWebActions(action);
1381 editor->command(command).execute();
1384 QSize QWebPage::viewportSize() const
1386 if (d->mainFrame && d->mainFrame->d->frame->view())
1387 return d->mainFrame->d->frame->view()->frameGeometry().size();
1389 return d->viewportSize;
1393 \property QWebPage::viewportSize
1394 \brief the size of the viewport
1396 The size affects for example the visibility of scrollbars
1397 if the document is larger than the viewport.
1399 void QWebPage::setViewportSize(const QSize &size) const
1401 d->viewportSize = size;
1403 QWebFrame *frame = mainFrame();
1404 if (frame->d->frame && frame->d->frame->view()) {
1405 WebCore::FrameView* view = frame->d->frame->view();
1406 view->setFrameGeometry(QRect(QPoint(0, 0), size));
1407 frame->d->frame->forceLayout();
1408 view->adjustViewSize();
1414 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1416 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
1417 the specified navigation type \a type.
1419 If \a frame is a null pointer then navigation to a new window is requested. If the request is
1420 accepted createWindow() will be called.
1422 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
1423 to let QWebPage handle the navigation itself.
1427 #if QT_VERSION >= 0x040400
1428 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1430 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1433 if (type == NavigationTypeLinkClicked) {
1434 switch (d->linkPolicy) {
1435 case DontDelegateLinks:
1438 case DelegateExternalLinks:
1439 if (WebCore::FrameLoader::shouldTreatSchemeAsLocal(request.url().scheme()))
1441 emit linkClicked(request.url());
1444 case DelegateAllLinks:
1445 emit linkClicked(request.url());
1453 \property QWebPage::selectedText
1454 \brief the text currently selected
1456 \sa selectionChanged()
1458 QString QWebPage::selectedText() const
1460 return d->page->focusController()->focusedOrMainFrame()->selectedText();
1464 Returns a QAction for the specified WebAction \a action.
1466 The action is owned by the QWebPage but you can customize the look by
1467 changing its properties.
1469 QWebPage also takes care of implementing the action, so that upon
1470 triggering the corresponding action is performed on the page.
1474 QAction *QWebPage::action(WebAction action) const
1476 if (action == QWebPage::NoWebAction) return 0;
1477 if (d->actions[action])
1478 return d->actions[action];
1482 QStyle *style = view() ? view()->style() : qApp->style();
1483 bool checkable = false;
1487 text = contextMenuItemTagOpenLink();
1489 case OpenLinkInNewWindow:
1490 text = contextMenuItemTagOpenLinkInNewWindow();
1492 case OpenFrameInNewWindow:
1493 text = contextMenuItemTagOpenFrameInNewWindow();
1496 case DownloadLinkToDisk:
1497 text = contextMenuItemTagDownloadLinkToDisk();
1499 case CopyLinkToClipboard:
1500 text = contextMenuItemTagCopyLinkToClipboard();
1503 case OpenImageInNewWindow:
1504 text = contextMenuItemTagOpenImageInNewWindow();
1506 case DownloadImageToDisk:
1507 text = contextMenuItemTagDownloadImageToDisk();
1509 case CopyImageToClipboard:
1510 text = contextMenuItemTagCopyImageToClipboard();
1514 text = contextMenuItemTagGoBack();
1515 #if QT_VERSION >= 0x040400
1516 icon = style->standardIcon(QStyle::SP_ArrowBack);
1520 text = contextMenuItemTagGoForward();
1521 #if QT_VERSION >= 0x040400
1522 icon = style->standardIcon(QStyle::SP_ArrowForward);
1526 text = contextMenuItemTagStop();
1527 #if QT_VERSION >= 0x040400
1528 icon = style->standardIcon(QStyle::SP_BrowserStop);
1532 text = contextMenuItemTagReload();
1533 #if QT_VERSION >= 0x040400
1534 icon = style->standardIcon(QStyle::SP_BrowserReload);
1539 text = contextMenuItemTagCut();
1542 text = contextMenuItemTagCopy();
1545 text = contextMenuItemTagPaste();
1549 QAction *a = undoStack()->createUndoAction(d->q);
1550 d->actions[action] = a;
1554 QAction *a = undoStack()->createRedoAction(d->q);
1555 d->actions[action] = a;
1558 case MoveToNextChar:
1559 case MoveToPreviousChar:
1560 case MoveToNextWord:
1561 case MoveToPreviousWord:
1562 case MoveToNextLine:
1563 case MoveToPreviousLine:
1564 case MoveToStartOfLine:
1565 case MoveToEndOfLine:
1566 case MoveToStartOfBlock:
1567 case MoveToEndOfBlock:
1568 case MoveToStartOfDocument:
1569 case MoveToEndOfDocument:
1570 case SelectNextChar:
1571 case SelectPreviousChar:
1572 case SelectNextWord:
1573 case SelectPreviousWord:
1574 case SelectNextLine:
1575 case SelectPreviousLine:
1576 case SelectStartOfLine:
1577 case SelectEndOfLine:
1578 case SelectStartOfBlock:
1579 case SelectEndOfBlock:
1580 case SelectStartOfDocument:
1581 case SelectEndOfDocument:
1582 case DeleteStartOfWord:
1583 case DeleteEndOfWord:
1586 case SetTextDirectionDefault:
1587 text = contextMenuItemTagDefaultDirection();
1589 case SetTextDirectionLeftToRight:
1590 text = contextMenuItemTagLeftToRight();
1593 case SetTextDirectionRightToLeft:
1594 text = contextMenuItemTagRightToLeft();
1599 text = contextMenuItemTagBold();
1603 text = contextMenuItemTagItalic();
1606 case ToggleUnderline:
1607 text = contextMenuItemTagUnderline();
1611 case InspectElement:
1612 text = contextMenuItemTagInspectElement();
1622 QAction *a = new QAction(d->q);
1625 a->setCheckable(checkable);
1628 connect(a, SIGNAL(triggered(bool)),
1629 this, SLOT(_q_webActionTriggered(bool)));
1631 d->actions[action] = a;
1632 d->updateAction(action);
1637 \property QWebPage::modified
1638 \brief whether the page contains unsubmitted form data
1640 bool QWebPage::isModified() const
1646 Returns a pointer to the undo stack used for editable content.
1648 QUndoStack *QWebPage::undoStack() const
1651 d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
1653 return d->undoStack;
1658 bool QWebPage::event(QEvent *ev)
1660 switch (ev->type()) {
1662 d->timerEvent(static_cast<QTimerEvent*>(ev));
1664 case QEvent::MouseMove:
1665 d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
1667 case QEvent::MouseButtonPress:
1668 d->mousePressEvent(static_cast<QMouseEvent*>(ev));
1670 case QEvent::MouseButtonDblClick:
1671 d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
1673 case QEvent::MouseButtonRelease:
1674 d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
1676 case QEvent::ContextMenu:
1677 d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
1680 d->wheelEvent(static_cast<QWheelEvent*>(ev));
1682 case QEvent::KeyPress:
1683 d->keyPressEvent(static_cast<QKeyEvent*>(ev));
1685 case QEvent::KeyRelease:
1686 d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
1688 case QEvent::FocusIn:
1689 d->focusInEvent(static_cast<QFocusEvent*>(ev));
1691 case QEvent::FocusOut:
1692 d->focusOutEvent(static_cast<QFocusEvent*>(ev));
1694 #ifndef QT_NO_DRAGANDDROP
1695 case QEvent::DragEnter:
1696 d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
1698 case QEvent::DragLeave:
1699 d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
1701 case QEvent::DragMove:
1702 d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
1705 d->dropEvent(static_cast<QDropEvent*>(ev));
1708 case QEvent::InputMethod:
1709 d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
1710 case QEvent::ShortcutOverride:
1711 d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
1717 return QObject::event(ev);
1724 Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
1725 if \a next is true; otherwise the previous element is focused.
1727 Returns true if it can find a new focusable element, or false if it can't.
1729 bool QWebPage::focusNextPrevChild(bool next)
1731 QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
1732 d->keyPressEvent(&ev);
1733 bool hasFocusedNode = false;
1734 Frame *frame = d->page->focusController()->focusedFrame();
1736 Document *document = frame->document();
1737 hasFocusedNode = document && document->focusedNode();
1739 //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
1740 return hasFocusedNode;
1744 \property QWebPage::editable
1745 \brief whether the content in this QWebPage is editable or not
1748 If this property is enabled the contents of the page can be edited by the user through a visible
1749 cursor. If disabled (the default) only HTML elements in the web page with their
1750 \c{contenteditable} attribute set are editable.
1752 void QWebPage::setEditable(bool editable)
1754 if (d->editable != editable) {
1755 d->editable = editable;
1756 d->page->setTabKeyCyclesThroughElements(!editable);
1758 WebCore::Frame* frame = d->mainFrame->d->frame;
1760 frame->applyEditingStyleToBodyElement();
1761 // FIXME: mac port calls this if there is no selectedDOMRange
1762 //frame->setSelectionFromNone();
1764 frame->removeEditingStyleFromBodyElement();
1768 d->updateEditorActions();
1772 bool QWebPage::isEditable() const
1778 \property QWebPage::forwardUnsupportedContent
1779 \brief whether QWebPage should forward unsupported content through the
1780 unsupportedContent signal
1782 If disabled the download of such content is aborted immediately.
1784 By default unsupported content is not forwarded.
1787 void QWebPage::setForwardUnsupportedContent(bool forward)
1789 d->forwardUnsupportedContent = forward;
1792 bool QWebPage::forwardUnsupportedContent() const
1794 return d->forwardUnsupportedContent;
1798 \property QWebPage::linkDelegationPolicy
1799 \brief how QWebPage should delegate the handling of links through the
1800 linkClicked() signal
1802 The default is to delegate no links.
1805 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
1807 d->linkPolicy = policy;
1810 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
1812 return d->linkPolicy;
1816 Filters the context menu event, \a event, through handlers for scrollbars and
1817 custom event handlers in the web page. Returns true if the event was handled;
1820 A web page may swallow a context menu event through a custom event handler, allowing for context
1821 menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
1824 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
1826 d->page->contextMenuController()->clearContextMenu();
1828 if (QWebFrame* webFrame = d->frameAt(event->pos())) {
1829 Frame* frame = QWebFramePrivate::core(webFrame);
1830 if (PlatformScrollbar* scrollbar = frame->view()->scrollbarUnderMouse(PlatformMouseEvent(event, 1))) {
1831 return scrollbar->handleContextMenuEvent(PlatformMouseEvent(event, 1));
1835 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1836 focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
1837 ContextMenu *menu = d->page->contextMenuController()->contextMenu();
1838 // If the website defines its own handler then sendContextMenuEvent takes care of
1839 // calling/showing it and the context menu pointer will be zero. This is the case
1840 // on maps.google.com for example.
1846 Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
1847 element the CopyImageToClipboard action is enabled.
1849 void QWebPage::updatePositionDependentActions(const QPoint &pos)
1851 // First we disable all actions, but keep track of which ones were originally enabled.
1852 QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
1853 for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
1854 QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
1855 if (QAction *a = this->action(action)) {
1856 originallyEnabledWebActions.setBit(action, a->isEnabled());
1857 a->setEnabled(false);
1861 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1862 HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
1864 d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
1865 WebCore::ContextMenu menu(result);
1867 if (d->page->inspectorController()->enabled())
1868 menu.addInspectElementItem();
1870 delete d->currentContextMenu;
1872 // Then we let createContextMenu() enable the actions that are put into the menu
1873 QBitArray visitedWebActions(QWebPage::WebActionCount);
1874 d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
1876 // Finally, we restore the original enablement for the actions that were not put into the menu.
1877 originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
1878 for (int i = 0; i < QWebPage::WebActionCount; ++i) {
1879 if (originallyEnabledWebActions.at(i)) {
1880 if (QAction *a = this->action(QWebPage::WebAction(i))) {
1881 a->setEnabled(true);
1886 // This whole process ensures that any actions put into to the context menu has the right
1887 // enablement, while also keeping the correct enablement for actions that were left out of
1895 \enum QWebPage::Extension
1897 This enum describes the types of extensions that the page can support. Before using these extensions, you
1898 should verify that the extension is supported by calling supportsExtension().
1900 Currently there are no extensions.
1904 \class QWebPage::ExtensionOption
1906 \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
1908 \sa QWebPage::extension()
1912 \class QWebPage::ExtensionReturn
1914 \brief The ExtensionOption class provides an extended output argument to QWebPage's extension support.
1916 \sa QWebPage::extension()
1920 This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
1921 argument is provided as input to the extension; the output results can be stored in \a output.
1923 The behavior of this function is determined by \a extension.
1925 You can call supportsExtension() to check if an extension is supported by the page.
1927 By default, no extensions are supported, and this function returns false.
1929 \sa supportsExtension(), Extension
1931 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
1940 This virtual function returns true if the web page supports \a extension; otherwise false is returned.
1944 bool QWebPage::supportsExtension(Extension extension) const
1951 Finds the next occurrence of the string, \a subString, in the page, using the given \a options.
1952 Returns true of \a subString was found and selects the match visually; otherwise returns false.
1954 bool QWebPage::findText(const QString &subString, FindFlags options)
1956 ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
1957 if (options & FindCaseSensitively)
1958 caseSensitivity = ::TextCaseSensitive;
1960 ::FindDirection direction = ::FindDirectionForward;
1961 if (options & FindBackward)
1962 direction = ::FindDirectionBackward;
1964 const bool shouldWrap = options & FindWrapsAroundDocument;
1966 return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
1970 Returns a pointer to the page's settings object.
1972 \sa QWebSettings::globalSettings()
1974 QWebSettings *QWebPage::settings() const
1980 This function is called when the web content requests a file name, for example
1981 as a result of the user clicking on a "file upload" button in a HTML form.
1983 A suggested filename may be provided in \a suggestedFile. The frame originating the
1984 request is provided as \a parentFrame.
1986 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
1988 #ifndef QT_NO_FILEDIALOG
1989 return QFileDialog::getOpenFileName(d->view, QString::null, suggestedFile);
1991 return QString::null;
1995 #if QT_VERSION < 0x040400 && !defined qdoc
1997 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
1999 d->networkInterface = interface;
2002 QWebNetworkInterface *QWebPage::networkInterface() const
2004 if (d->networkInterface)
2005 return d->networkInterface;
2007 return QWebNetworkInterface::defaultInterface();
2010 #ifndef QT_NO_NETWORKPROXY
2011 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
2013 d->networkProxy = proxy;
2016 QNetworkProxy QWebPage::networkProxy() const
2018 return d->networkProxy;
2025 Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
2028 \sa networkAccessManager()
2030 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
2032 if (manager == d->networkManager)
2034 if (d->networkManager && d->networkManager->parent() == this)
2035 delete d->networkManager;
2036 d->networkManager = manager;
2040 Returns the QNetworkAccessManager that is responsible for serving network
2041 requests for this QWebPage.
2043 \sa setNetworkAccessManager()
2045 QNetworkAccessManager *QWebPage::networkAccessManager() const
2047 if (!d->networkManager) {
2048 QWebPage *that = const_cast<QWebPage *>(this);
2049 that->d->networkManager = new QNetworkAccessManager(that);
2051 return d->networkManager;
2057 Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
2060 Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
2064 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
2066 d->pluginFactory = factory;
2070 Returns the QWebPluginFactory that is responsible for creating plugins embedded into
2071 this QWebPage. If no plugin factory is installed a null pointer is returned.
2073 \sa setPluginFactory()
2075 QWebPluginFactory *QWebPage::pluginFactory() const
2077 return d->pluginFactory;
2081 This function is called when a user agent for HTTP requests is needed. You can re-implement this
2082 function to dynamically return different user agent's for different urls, based on the \a url parameter.
2084 The default implementation returns the following value:
2086 "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko, Safari/419.3) %AppVersion"
2088 In this string the following values are replaced at run-time:
2090 \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
2091 \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
2092 \o %Locale% is replaced with QLocale::name().
2093 \o %WebKitVersion% currently expands to 527+
2094 \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
2097 QString QWebPage::userAgentForUrl(const QUrl& url) const
2100 QString ua = QLatin1String("Mozilla/5.0 ("
2105 #elif defined Q_WS_QWS
2107 #elif defined Q_WS_WIN
2109 #elif defined Q_WS_X11
2116 // Placeholder for security strength (N or U)
2122 #elif defined Q_OS_WIN32
2124 #elif defined Q_OS_DARWIN
2125 #ifdef __i386__ || __x86_64__
2131 #elif defined Q_OS_BSDI
2133 #elif defined Q_OS_BSD4
2135 #elif defined Q_OS_CYGWIN
2137 #elif defined Q_OS_DGUX
2139 #elif defined Q_OS_DYNIX
2141 #elif defined Q_OS_FREEBSD
2143 #elif defined Q_OS_HPUX
2145 #elif defined Q_OS_HURD
2147 #elif defined Q_OS_IRIX
2149 #elif defined Q_OS_LINUX
2151 #elif defined Q_OS_LYNX
2153 #elif defined Q_OS_NETBSD
2155 #elif defined Q_OS_OS2
2157 #elif defined Q_OS_OPENBSD
2159 #elif defined Q_OS_OS2EMX
2161 #elif defined Q_OS_OSF
2163 #elif defined Q_OS_QNX6
2165 #elif defined Q_OS_QNX
2167 #elif defined Q_OS_RELIANT
2169 #elif defined Q_OS_SCO
2171 #elif defined Q_OS_SOLARIS
2173 #elif defined Q_OS_ULTRIX
2175 #elif defined Q_OS_UNIX
2176 "UNIX BSD/SYSV system"
2177 #elif defined Q_OS_UNIXWARE
2178 "UnixWare Seven, Open UNIX Eight"
2184 QChar securityStrength(QLatin1Char('N'));
2185 #if !defined(QT_NO_OPENSSL)
2186 if (QSslSocket::supportsSsl())
2187 securityStrength = QLatin1Char('U');
2189 ua = ua.arg(securityStrength);
2191 #if defined Q_OS_WIN32
2193 switch(QSysInfo::WindowsVersion) {
2194 case QSysInfo::WV_32s:
2195 ver = "Windows 3.1";
2197 case QSysInfo::WV_95:
2200 case QSysInfo::WV_98:
2203 case QSysInfo::WV_Me:
2204 ver = "Windows 98; Win 9x 4.90";
2206 case QSysInfo::WV_NT:
2209 case QSysInfo::WV_2000:
2210 ver = "Windows NT 5.0";
2212 case QSysInfo::WV_XP:
2213 ver = "Windows NT 5.1";
2215 case QSysInfo::WV_2003:
2216 ver = "Windows NT 5.2";
2218 case QSysInfo::WV_VISTA:
2219 ver = "Windows NT 6.0";
2221 case QSysInfo::WV_CE:
2224 case QSysInfo::WV_CENET:
2225 ver = "Windows CE .NET";
2227 case QSysInfo::WV_CE_5:
2228 ver = "Windows CE 5.x";
2230 case QSysInfo::WV_CE_6:
2231 ver = "Windows CE 6.x";
2234 ua = QString(ua).arg(ver);
2240 locale = d->view->locale();
2241 QString name = locale.name();
2242 name[2] = QLatin1Char('-');
2244 ua.append(QLatin1String(") "));
2246 // webkit/qt version
2247 ua.append(QLatin1String("AppleWebKit/" WEBKIT_VERSION " (KHTML, like Gecko, Safari/419.3) "));
2249 // Application name/version
2250 QString appName = QCoreApplication::applicationName();
2251 if (!appName.isEmpty()) {
2252 ua.append(QLatin1Char(' ') + appName);
2253 #if QT_VERSION >= 0x040400
2254 QString appVer = QCoreApplication::applicationVersion();
2255 if (!appVer.isEmpty())
2256 ua.append(QLatin1Char('/') + appVer);
2260 ua.append(QLatin1String("Qt/"));
2261 ua.append(QLatin1String(qVersion()));
2267 void QWebPagePrivate::_q_onLoadProgressChanged(int) {
2268 m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
2269 m_bytesReceived = page->progress()->totalBytesReceived();
2274 Returns the total number of bytes that were received from the network to render the current page,
2275 including extra content such as embedded images.
2279 quint64 QWebPage::totalBytes() const {
2280 return d->m_bytesReceived;
2285 Returns the number of bytes that were received from the network to render the current page.
2289 quint64 QWebPage::bytesReceived() const {
2290 return d->m_totalBytes;
2294 \fn void QWebPage::loadStarted()
2296 This signal is emitted when a new load of the page is started.
2302 \fn void QWebPage::loadProgress(int progress)
2304 This signal is emitted when the global progress status changes.
2305 The current value is provided by \a progress and scales from 0 to 100,
2306 which is the default range of QProgressBar.
2307 It accumulates changes from all the child frames.
2313 \fn void QWebPage::loadFinished(bool ok)
2315 This signal is emitted when a load of the page is finished.
2316 \a ok will indicate whether the load was successful or any error occurred.
2322 \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
2324 This signal is emitted when the mouse is hovering over a link.
2325 The first parameter is the \a link url, the second is the link \a title
2326 if any, and third \a textContent is the text content. Method is emitter with both
2327 empty parameters when the mouse isn't hovering over any link element.
2333 \fn void QWebPage::statusBarMessage(const QString& text)
2335 This signal is emitted when the statusbar \a text is changed by the page.
2339 \fn void QWebPage::frameCreated(QWebFrame *frame)
2341 This signal is emitted whenever the page creates a new \a frame.
2345 \fn void QWebPage::selectionChanged()
2347 This signal is emitted whenever the selection changes.
2353 \fn void QWebPage::geometryChangeRequested(const QRect& geom)
2355 This signal is emitted whenever the document wants to change the position and size of the
2356 page to \a geom. This can happen for example through JavaScript.
2360 \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
2362 This signal is emitted whenever this QWebPage should be updated and no view was set.
2363 \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
2364 the mainFrame() and call the render(QPainter*, const QRegion&) method with the
2365 \a dirtyRect as the second parameter.
2372 \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
2374 This signal is emitted whenever the content given by \a rectToScroll needs
2375 to be scrolled \a dx and \a dy downwards and no view was set.
2381 \fn void QWebPage::windowCloseRequested()
2383 This signal is emitted whenever the page requests the web browser window to be closed,
2384 for example through the JavaScript \c{window.close()} call.
2388 \fn void QWebPage::printRequested(QWebFrame *frame)
2390 This signal is emitted whenever the page requests the web browser to print \a frame,
2391 for example through the JavaScript \c{window.print()} call.
2393 \sa QWebFrame::print(), QPrintPreviewDialog
2397 \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
2399 This signals is emitted when webkit cannot handle a link the user navigated to.
2401 At signal emissions time the meta data of the QNetworkReply \a reply is available.
2403 \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
2405 \sa downloadRequested()
2409 \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
2411 This signal is emitted when the user decides to download a link. The url of
2412 the link as well as additional meta-information is contained in \a request.
2414 \sa unsupportedContent()
2418 \fn void QWebPage::microFocusChanged()
2420 This signal is emitted when for example the position of the cursor in an editable form
2421 element changes. It is used inform input methods about the new on-screen position where
2422 the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
2427 \fn void QWebPage::linkClicked(const QUrl &url)
2429 This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
2430 property is set to delegate the link handling for the specified \a url.
2432 By default no links are delegated and are handled by QWebPage instead.
2438 \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
2440 This signal is emitted whenever the visibility of the toolbar in a web browser
2441 window that hosts QWebPage should be changed to \a visible.
2445 \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
2447 This signal is emitted whenever the visibility of the statusbar in a web browser
2448 window that hosts QWebPage should be changed to \a visible.
2452 \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
2454 This signal is emitted whenever the visibility of the menubar in a web browser
2455 window that hosts QWebPage should be changed to \a visible.
2458 #include "moc_qwebpage.cpp"