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