1/*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this program; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include "config.h"
22#include "qwkpage.h"
23#include "qwkpage_p.h"
24
25#include "qwkpreferences_p.h"
26
27#include "ChunkedUpdateDrawingAreaProxy.h"
28#include "ClientImpl.h"
29#include "qgraphicswkview.h"
30#include "qwkcontext.h"
31#include "qwkcontext_p.h"
32#include "qwkhistory.h"
33#include "qwkhistory_p.h"
34#include "FindIndicator.h"
35#include "LocalizedStrings.h"
36#include "NativeWebKeyboardEvent.h"
37#include "NativeWebMouseEvent.h"
38#include "NotImplemented.h"
39#include "TiledDrawingAreaProxy.h"
40#include "WebContext.h"
41#include "WebContextMenuProxyQt.h"
42#include "WebEventFactoryQt.h"
43#include "WebPopupMenuProxyQt.h"
44#include "WKStringQt.h"
45#include "WKURLQt.h"
46#include "ViewportArguments.h"
47#include <QAction>
48#include <QApplication>
49#include <QGraphicsSceneMouseEvent>
50#include <QStyle>
51#include <QTouchEvent>
52#include <QtDebug>
53#include <WebCore/Cursor.h>
54#include <WebCore/FloatRect.h>
55#include <WebCore/NotImplemented.h>
56#include <WebKit2/WKFrame.h>
57#include <WebKit2/WKPageGroup.h>
58#include <WebKit2/WKRetainPtr.h>
59
60using namespace WebKit;
61using namespace WebCore;
62
63static WebCore::ContextMenuAction contextMenuActionForWebAction(QWKPage::WebAction action)
64{
65    switch (action) {
66    case QWKPage::OpenLink:
67        return WebCore::ContextMenuItemTagOpenLink;
68    case QWKPage::OpenLinkInNewWindow:
69        return WebCore::ContextMenuItemTagOpenLinkInNewWindow;
70    case QWKPage::CopyLinkToClipboard:
71        return WebCore::ContextMenuItemTagCopyLinkToClipboard;
72    case QWKPage::OpenImageInNewWindow:
73        return WebCore::ContextMenuItemTagOpenImageInNewWindow;
74    case QWKPage::Cut:
75        return WebCore::ContextMenuItemTagCut;
76    case QWKPage::Copy:
77        return WebCore::ContextMenuItemTagCopy;
78    case QWKPage::Paste:
79        return WebCore::ContextMenuItemTagPaste;
80    case QWKPage::SelectAll:
81        return WebCore::ContextMenuItemTagSelectAll;
82    default:
83        ASSERT(false);
84        break;
85    }
86    return WebCore::ContextMenuItemTagNoAction;
87}
88
89QWKPagePrivate::QWKPagePrivate(QWKPage* qq, QWKContext* c)
90    : q(qq)
91    , view(0)
92    , context(c)
93    , preferences(0)
94    , createNewPageFn(0)
95    , backingStoreType(QGraphicsWKView::Simple)
96    , isConnectedToEngine(true)
97{
98    memset(actions, 0, sizeof(actions));
99    page = context->d->context->createWebPage(this, 0);
100    history = QWKHistoryPrivate::createHistory(page->backForwardList());
101}
102
103QWKPagePrivate::~QWKPagePrivate()
104{
105    page->close();
106    delete history;
107}
108
109void QWKPagePrivate::init(QGraphicsItem* view, QGraphicsWKView::BackingStoreType backingStoreType)
110{
111    this->view = view;
112    this->backingStoreType = backingStoreType;
113    page->initializeWebPage();
114}
115
116void QWKPagePrivate::setCursor(const WebCore::Cursor& cursor)
117{
118#ifndef QT_NO_CURSOR
119    emit q->cursorChanged(*cursor.platformCursor());
120#endif
121}
122
123void QWKPagePrivate::setViewportArguments(const ViewportArguments& args)
124{
125    viewportArguments = args;
126    emit q->viewportChangeRequested();
127}
128
129PassOwnPtr<DrawingAreaProxy> QWKPagePrivate::createDrawingAreaProxy()
130{
131    // FIXME: We should avoid this cast by decoupling the view from the page.
132    QGraphicsWKView* wkView = static_cast<QGraphicsWKView*>(view);
133
134#if ENABLE(TILED_BACKING_STORE)
135    if (backingStoreType == QGraphicsWKView::Tiled)
136        return TiledDrawingAreaProxy::create(wkView, page.get());
137#endif
138    return ChunkedUpdateDrawingAreaProxy::create(wkView, page.get());
139}
140
141void QWKPagePrivate::setViewNeedsDisplay(const WebCore::IntRect& rect)
142{
143    view->update(QRect(rect));
144}
145
146void QWKPagePrivate::displayView()
147{
148    // FIXME: Implement.
149}
150
151void QWKPagePrivate::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
152{
153    // FIXME: Implement.
154}
155
156WebCore::IntSize QWKPagePrivate::viewSize()
157{
158    // FIXME: Implement.
159    return WebCore::IntSize();
160}
161
162bool QWKPagePrivate::isViewWindowActive()
163{
164    return view && view->isActive();
165}
166
167bool QWKPagePrivate::isViewFocused()
168{
169    return view && view->hasFocus();
170}
171
172bool QWKPagePrivate::isViewVisible()
173{
174    return view && view->isVisible();
175}
176
177bool QWKPagePrivate::isViewInWindow()
178{
179    // FIXME: Implement.
180    return true;
181}
182
183void QWKPagePrivate::enterAcceleratedCompositingMode(const LayerTreeContext&)
184{
185    // FIXME: Implement.
186}
187
188void QWKPagePrivate::exitAcceleratedCompositingMode()
189{
190    // FIXME: Implement.
191}
192
193void QWKPagePrivate::pageDidRequestScroll(const IntPoint& point)
194{
195    emit q->scrollRequested(point.x(), point.y());
196}
197
198void QWKPagePrivate::didChangeContentsSize(const IntSize& newSize)
199{
200    emit q->contentsSizeChanged(QSize(newSize));
201}
202
203void QWKPagePrivate::toolTipChanged(const String&, const String& newTooltip)
204{
205    emit q->toolTipChanged(QString(newTooltip));
206}
207
208void QWKPagePrivate::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo)
209{
210}
211
212void QWKPagePrivate::clearAllEditCommands()
213{
214}
215
216bool QWKPagePrivate::canUndoRedo(WebPageProxy::UndoOrRedo)
217{
218    return false;
219}
220
221void QWKPagePrivate::executeUndoRedo(WebPageProxy::UndoOrRedo)
222{
223}
224
225FloatRect QWKPagePrivate::convertToDeviceSpace(const FloatRect& rect)
226{
227    return rect;
228}
229
230IntRect QWKPagePrivate::windowToScreen(const IntRect& rect)
231{
232    return rect;
233}
234
235FloatRect QWKPagePrivate::convertToUserSpace(const FloatRect& rect)
236{
237    return rect;
238}
239
240void QWKPagePrivate::selectionChanged(bool, bool, bool, bool)
241{
242}
243
244void QWKPagePrivate::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
245{
246}
247
248PassRefPtr<WebPopupMenuProxy> QWKPagePrivate::createPopupMenuProxy(WebPageProxy*)
249{
250    return WebPopupMenuProxyQt::create();
251}
252
253PassRefPtr<WebContextMenuProxy> QWKPagePrivate::createContextMenuProxy(WebPageProxy*)
254{
255    return WebContextMenuProxyQt::create(q);
256}
257
258void QWKPagePrivate::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut)
259{
260}
261
262void QWKPagePrivate::didCommitLoadForMainFrame(bool useCustomRepresentation)
263{
264}
265
266void QWKPagePrivate::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
267{
268}
269
270void QWKPagePrivate::flashBackingStoreUpdates(const Vector<IntRect>&)
271{
272    notImplemented();
273}
274
275void QWKPagePrivate::paint(QPainter* painter, QRect area)
276{
277    if (page->isValid() && page->drawingArea())
278        page->drawingArea()->paint(IntRect(area), painter);
279    else
280        painter->fillRect(area, Qt::white);
281}
282
283void QWKPagePrivate::keyPressEvent(QKeyEvent* ev)
284{
285    page->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
286}
287
288void QWKPagePrivate::keyReleaseEvent(QKeyEvent* ev)
289{
290    page->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
291}
292
293void QWKPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
294{
295    // For some reason mouse press results in mouse hover (which is
296    // converted to mouse move for WebKit). We ignore these hover
297    // events by comparing lastPos with newPos.
298    // NOTE: lastPos from the event always comes empty, so we work
299    // around that here.
300    static QPointF lastPos = QPointF();
301    if (lastPos == ev->pos())
302        return;
303    lastPos = ev->pos();
304
305    page->handleMouseEvent(NativeWebMouseEvent(ev, 0));
306}
307
308void QWKPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev)
309{
310    if (tripleClickTimer.isActive() && (ev->pos() - tripleClick).manhattanLength() < QApplication::startDragDistance()) {
311        page->handleMouseEvent(NativeWebMouseEvent(ev, 3));
312        return;
313    }
314
315    page->handleMouseEvent(NativeWebMouseEvent(ev, 1));
316}
317
318void QWKPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
319{
320    page->handleMouseEvent(NativeWebMouseEvent(ev, 0));
321}
322
323void QWKPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev)
324{
325    page->handleMouseEvent(NativeWebMouseEvent(ev, 2));
326
327    tripleClickTimer.start(QApplication::doubleClickInterval(), q);
328    tripleClick = ev->pos().toPoint();
329}
330
331void QWKPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev)
332{
333    WebWheelEvent wheelEvent = WebEventFactory::createWebWheelEvent(ev);
334    page->handleWheelEvent(wheelEvent);
335}
336
337void QWKPagePrivate::updateAction(QWKPage::WebAction action)
338{
339#ifdef QT_NO_ACTION
340    Q_UNUSED(action)
341#else
342    QAction* a = actions[action];
343    if (!a)
344        return;
345
346    RefPtr<WebKit::WebFrameProxy> mainFrame = page->mainFrame();
347    if (!mainFrame)
348        return;
349
350    bool enabled = a->isEnabled();
351    bool checked = a->isChecked();
352
353    switch (action) {
354    case QWKPage::Back:
355        enabled = page->canGoBack();
356        break;
357    case QWKPage::Forward:
358        enabled = page->canGoForward();
359        break;
360    case QWKPage::Stop:
361        enabled = !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
362        break;
363    case QWKPage::Reload:
364        enabled = (WebFrameProxy::LoadStateFinished == mainFrame->loadState());
365        break;
366    default:
367        break;
368    }
369
370    a->setEnabled(enabled);
371
372    if (a->isCheckable())
373        a->setChecked(checked);
374#endif // QT_NO_ACTION
375}
376
377void QWKPagePrivate::updateNavigationActions()
378{
379    updateAction(QWKPage::Back);
380    updateAction(QWKPage::Forward);
381    updateAction(QWKPage::Stop);
382    updateAction(QWKPage::Reload);
383}
384
385#ifndef QT_NO_ACTION
386void QWKPagePrivate::_q_webActionTriggered(bool checked)
387{
388    QAction* a = qobject_cast<QAction*>(q->sender());
389    if (!a)
390        return;
391    QWKPage::WebAction action = static_cast<QWKPage::WebAction>(a->data().toInt());
392    q->triggerAction(action, checked);
393}
394#endif // QT_NO_ACTION
395
396void QWKPagePrivate::touchEvent(QTouchEvent* event)
397{
398#if ENABLE(TOUCH_EVENTS)
399    WebTouchEvent touchEvent = WebEventFactory::createWebTouchEvent(event);
400    page->handleTouchEvent(touchEvent);
401#else
402    event->ignore();
403#endif
404}
405
406void QWKPagePrivate::didRelaunchProcess()
407{
408    QGraphicsWKView* wkView = static_cast<QGraphicsWKView*>(view);
409    if (wkView)
410        q->setViewportSize(wkView->size().toSize());
411
412    isConnectedToEngine = true;
413    emit q->engineConnectionChanged(true);
414}
415
416void QWKPagePrivate::processDidCrash()
417{
418    isConnectedToEngine = false;
419    emit q->engineConnectionChanged(false);
420}
421
422QWKPage::QWKPage(QWKContext* context)
423    : d(new QWKPagePrivate(this, context))
424{
425    WKPageLoaderClient loadClient = {
426        0,      /* version */
427        this,   /* clientInfo */
428        qt_wk_didStartProvisionalLoadForFrame,
429        qt_wk_didReceiveServerRedirectForProvisionalLoadForFrame,
430        qt_wk_didFailProvisionalLoadWithErrorForFrame,
431        qt_wk_didCommitLoadForFrame,
432        qt_wk_didFinishDocumentLoadForFrame,
433        qt_wk_didFinishLoadForFrame,
434        qt_wk_didFailLoadWithErrorForFrame,
435        0, /* didSameDocumentNavigationForFrame */
436        qt_wk_didReceiveTitleForFrame,
437        qt_wk_didFirstLayoutForFrame,
438        qt_wk_didFirstVisuallyNonEmptyLayoutForFrame,
439        qt_wk_didRemoveFrameFromHierarchy,
440        0, /* didDisplayInsecureContentForFrame */
441        0, /* didRunInsecureContentForFrame */
442        0, /* canAuthenticateAgainstProtectionSpaceInFrame */
443        0, /* didReceiveAuthenticationChallengeInFrame */
444        qt_wk_didStartProgress,
445        qt_wk_didChangeProgress,
446        qt_wk_didFinishProgress,
447        qt_wk_didBecomeUnresponsive,
448        qt_wk_didBecomeResponsive,
449        0,  /* processDidCrash */
450        0,  /* didChangeBackForwardList */
451        0   /* shouldGoToBackForwardListItem */
452    };
453    WKPageSetPageLoaderClient(pageRef(), &loadClient);
454
455    WKPageUIClient uiClient = {
456        0,      /* version */
457        this,   /* clientInfo */
458        qt_wk_createNewPage,
459        qt_wk_showPage,
460        qt_wk_close,
461        qt_wk_takeFocus,
462        0,  /* focus */
463        0,  /* unfocus */
464        qt_wk_runJavaScriptAlert,
465        0,  /* runJavaScriptConfirm */
466        0,  /* runJavaScriptPrompt */
467        qt_wk_setStatusText,
468        0,  /* mouseDidMoveOverElement */
469        0,  /* missingPluginButtonClicked */
470        0,  /* didNotHandleKeyEvent */
471        0,  /* toolbarsAreVisible */
472        0,  /* setToolbarsAreVisible */
473        0,  /* menuBarIsVisible */
474        0,  /* setMenuBarIsVisible */
475        0,  /* statusBarIsVisible */
476        0,  /* setStatusBarIsVisible */
477        0,  /* isResizable */
478        0,  /* setIsResizable */
479        0,  /* getWindowFrame */
480        0,  /* setWindowFrame */
481        0,  /* runBeforeUnloadConfirmPanel */
482        0,  /* didDraw */
483        0,  /* pageDidScroll */
484        0,  /* exceededDatabaseQuota */
485        0,  /* runOpenPanel */
486        0,  /* decidePolicyForGeolocationPermissionRequest */
487        0,  /* headerHeight */
488        0,  /* footerHeight */
489        0,  /* drawHeader */
490        0,  /* drawFooter */
491        0,  /* printFrame */
492        0,  /* runModal */
493        0,   /* didCompleteRubberBandForMainFrame */
494        0    /* saveDataToFileInDownloadsFolder */
495    };
496    WKPageSetPageUIClient(pageRef(), &uiClient);
497}
498
499QWKPage::~QWKPage()
500{
501    delete d;
502}
503
504QWKPage::ViewportAttributes::ViewportAttributes()
505    : d(0)
506    , m_initialScaleFactor(-1.0)
507    , m_minimumScaleFactor(-1.0)
508    , m_maximumScaleFactor(-1.0)
509    , m_devicePixelRatio(-1.0)
510    , m_isUserScalable(true)
511    , m_isValid(false)
512{
513
514}
515
516QWKPage::ViewportAttributes::ViewportAttributes(const QWKPage::ViewportAttributes& other)
517    : d(other.d)
518    , m_initialScaleFactor(other.m_initialScaleFactor)
519    , m_minimumScaleFactor(other.m_minimumScaleFactor)
520    , m_maximumScaleFactor(other.m_maximumScaleFactor)
521    , m_devicePixelRatio(other.m_devicePixelRatio)
522    , m_isUserScalable(other.m_isUserScalable)
523    , m_isValid(other.m_isValid)
524    , m_size(other.m_size)
525{
526
527}
528
529QWKPage::ViewportAttributes::~ViewportAttributes()
530{
531
532}
533
534QWKPage::ViewportAttributes& QWKPage::ViewportAttributes::operator=(const QWKPage::ViewportAttributes& other)
535{
536    if (this != &other) {
537        d = other.d;
538        m_initialScaleFactor = other.m_initialScaleFactor;
539        m_minimumScaleFactor = other.m_minimumScaleFactor;
540        m_maximumScaleFactor = other.m_maximumScaleFactor;
541        m_devicePixelRatio = other.m_devicePixelRatio;
542        m_isUserScalable = other.m_isUserScalable;
543        m_isValid = other.m_isValid;
544        m_size = other.m_size;
545    }
546
547    return *this;
548}
549
550QWKPage::ViewportAttributes QWKPage::viewportAttributesForSize(const QSize& availableSize) const
551{
552    static int desktopWidth = 980;
553    static int deviceDPI = 160;
554
555    ViewportAttributes result;
556
557     if (availableSize.isEmpty())
558         return result; // Returns an invalid instance.
559
560    // FIXME: Add a way to get these data via the platform plugin and fall back
561    // to the size of the view.
562    int deviceWidth = 480;
563    int deviceHeight = 864;
564
565    WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments, desktopWidth, deviceWidth, deviceHeight, deviceDPI, availableSize);
566
567    result.m_isValid = true;
568    result.m_size = conf.layoutSize;
569    result.m_initialScaleFactor = conf.initialScale;
570    result.m_minimumScaleFactor = conf.minimumScale;
571    result.m_maximumScaleFactor = conf.maximumScale;
572    result.m_devicePixelRatio = conf.devicePixelRatio;
573    result.m_isUserScalable = static_cast<bool>(conf.userScalable);
574
575    return result;
576}
577
578void QWKPage::setActualVisibleContentsRect(const QRect& rect) const
579{
580#if ENABLE(TILED_BACKING_STORE)
581    d->page->setActualVisibleContentRect(rect);
582#endif
583}
584
585void QWKPage::timerEvent(QTimerEvent* ev)
586{
587    int timerId = ev->timerId();
588    if (timerId == d->tripleClickTimer.timerId())
589        d->tripleClickTimer.stop();
590    else
591        QObject::timerEvent(ev);
592}
593
594WKPageRef QWKPage::pageRef() const
595{
596    return toAPI(d->page.get());
597}
598
599QWKContext* QWKPage::context() const
600{
601    return d->context;
602}
603
604QWKPreferences* QWKPage::preferences() const
605{
606    if (!d->preferences) {
607        WKPageGroupRef pageGroupRef = WKPageGetPageGroup(pageRef());
608        d->preferences = QWKPreferencesPrivate::createPreferences(pageGroupRef);
609    }
610
611    return d->preferences;
612}
613
614void QWKPage::setCreateNewPageFunction(CreateNewPageFn function)
615{
616    d->createNewPageFn = function;
617}
618
619void QWKPage::setCustomUserAgent(const QString& userAgent)
620{
621    WKRetainPtr<WKStringRef> wkUserAgent(WKStringCreateWithQString(userAgent));
622    WKPageSetCustomUserAgent(pageRef(), wkUserAgent.get());
623}
624
625QString QWKPage::customUserAgent() const
626{
627    return WKStringCopyQString(WKPageCopyCustomUserAgent(pageRef()));
628}
629
630void QWKPage::load(const QUrl& url)
631{
632    WKRetainPtr<WKURLRef> wkurl(WKURLCreateWithQUrl(url));
633    WKPageLoadURL(pageRef(), wkurl.get());
634}
635
636void QWKPage::setUrl(const QUrl& url)
637{
638    load(url);
639}
640
641QUrl QWKPage::url() const
642{
643    WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef());
644    if (!frame)
645        return QUrl();
646    return WKURLCopyQUrl(WKFrameCopyURL(frame.get()));
647}
648
649QString QWKPage::title() const
650{
651    return WKStringCopyQString(WKPageCopyTitle(pageRef()));
652}
653
654void QWKPage::setViewportSize(const QSize& size)
655{
656    if (d->page->drawingArea())
657        d->page->drawingArea()->setSize(IntSize(size), IntSize());
658}
659
660qreal QWKPage::textZoomFactor() const
661{
662    return WKPageGetTextZoomFactor(pageRef());
663}
664
665void QWKPage::setTextZoomFactor(qreal zoomFactor)
666{
667    WKPageSetTextZoomFactor(pageRef(), zoomFactor);
668}
669
670qreal QWKPage::pageZoomFactor() const
671{
672    return WKPageGetPageZoomFactor(pageRef());
673}
674
675void QWKPage::setPageZoomFactor(qreal zoomFactor)
676{
677    WKPageSetPageZoomFactor(pageRef(), zoomFactor);
678}
679
680void QWKPage::setPageAndTextZoomFactors(qreal pageZoomFactor, qreal textZoomFactor)
681{
682    WKPageSetPageAndTextZoomFactors(pageRef(), pageZoomFactor, textZoomFactor);
683}
684
685QWKHistory* QWKPage::history() const
686{
687    return d->history;
688}
689
690void QWKPage::setResizesToContentsUsingLayoutSize(const QSize& targetLayoutSize)
691{
692#if ENABLE(TILED_BACKING_STORE)
693    d->page->setResizesToContentsUsingLayoutSize(targetLayoutSize);
694#endif
695}
696
697#ifndef QT_NO_ACTION
698void QWKPage::triggerAction(WebAction webAction, bool)
699{
700    switch (webAction) {
701    case Back:
702        d->page->goBack();
703        return;
704    case Forward:
705        d->page->goForward();
706        return;
707    case Stop:
708        d->page->stopLoading();
709        return;
710    case Reload:
711        d->page->reload(/* reloadFromOrigin */ true);
712        return;
713    default:
714        break;
715    }
716
717    QAction* qtAction = action(webAction);
718    WebKit::WebContextMenuItemData menuItemData(ActionType, contextMenuActionForWebAction(webAction), qtAction->text(), qtAction->isEnabled(), qtAction->isChecked());
719    d->page->contextMenuItemSelected(menuItemData);
720}
721#endif // QT_NO_ACTION
722
723#ifndef QT_NO_ACTION
724QAction* QWKPage::action(WebAction action) const
725{
726    if (action == QWKPage::NoWebAction || action >= WebActionCount)
727        return 0;
728
729    if (d->actions[action])
730        return d->actions[action];
731
732    QString text;
733    QIcon icon;
734    QStyle* style = qobject_cast<QApplication*>(QCoreApplication::instance())->style();
735    bool checkable = false;
736
737    switch (action) {
738    case OpenLink:
739        text = contextMenuItemTagOpenLink();
740        break;
741    case OpenLinkInNewWindow:
742        text = contextMenuItemTagOpenLinkInNewWindow();
743        break;
744    case CopyLinkToClipboard:
745        text = contextMenuItemTagCopyLinkToClipboard();
746        break;
747    case OpenImageInNewWindow:
748        text = contextMenuItemTagOpenImageInNewWindow();
749        break;
750    case Back:
751        text = contextMenuItemTagGoBack();
752        icon = style->standardIcon(QStyle::SP_ArrowBack);
753        break;
754    case Forward:
755        text = contextMenuItemTagGoForward();
756        icon = style->standardIcon(QStyle::SP_ArrowForward);
757        break;
758    case Stop:
759        text = contextMenuItemTagStop();
760        icon = style->standardIcon(QStyle::SP_BrowserStop);
761        break;
762    case Reload:
763        text = contextMenuItemTagReload();
764        icon = style->standardIcon(QStyle::SP_BrowserReload);
765        break;
766    case Cut:
767        text = contextMenuItemTagCut();
768        break;
769    case Copy:
770        text = contextMenuItemTagCopy();
771        break;
772    case Paste:
773        text = contextMenuItemTagPaste();
774        break;
775    case SelectAll:
776        text = contextMenuItemTagSelectAll();
777        break;
778    default:
779        return 0;
780        break;
781    }
782
783    if (text.isEmpty())
784        return 0;
785
786    QAction* a = new QAction(d->q);
787    a->setText(text);
788    a->setData(action);
789    a->setCheckable(checkable);
790    a->setIcon(icon);
791
792    connect(a, SIGNAL(triggered(bool)), this, SLOT(_q_webActionTriggered(bool)));
793
794    d->actions[action] = a;
795    d->updateAction(action);
796    return a;
797}
798#endif // QT_NO_ACTION
799
800void QWKPage::findZoomableAreaForPoint(const QPoint& point)
801{
802    d->page->findZoomableAreaForPoint(point);
803}
804
805void QWKPagePrivate::didFindZoomableArea(const IntRect& area)
806{
807    emit q->zoomableAreaFound(QRect(area));
808}
809
810bool QWKPage::isConnectedToEngine() const
811{
812    return d->isConnectedToEngine;
813}
814
815#include "moc_qwkpage.cpp"
816