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