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