webengine/osswebengine/WebKit/qt/Api/qwebpage.cpp
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/qt/Api/qwebpage.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,710 @@
+/*
+    Copyright (C) 2007 Trolltech ASA
+    Copyright (C) 2007 Staikos Computing Services Inc.
+    Copyright (C) 2007 Apple Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#include "qwebpage.h"
+#include "qwebframe.h"
+#include "qwebpage_p.h"
+#include "qwebframe_p.h"
+#include "qwebnetworkinterface.h"
+#include "qwebpagehistory.h"
+#include "qwebpagehistory_p.h"
+#include "qwebsettings.h"
+
+#include "Frame.h"
+#include "ChromeClientQt.h"
+#include "ContextMenuClientQt.h"
+#include "DragClientQt.h"
+#include "DragController.h"
+#include "DragData.h"
+#include "EditorClientQt.h"
+#include "Settings.h"
+#include "Page.h"
+#include "FrameLoader.h"
+#include "KURL.h"
+#include "Image.h"
+#include "IconDatabase.h"
+#include "InspectorClientQt.h"
+#include "FocusController.h"
+#include "Editor.h"
+#include "PlatformScrollBar.h"
+#include "PlatformKeyboardEvent.h"
+#include "ProgressTracker.h"
+
+#include <QDebug>
+#include <QDragEnterEvent>
+#include <QDragLeaveEvent>
+#include <QDragMoveEvent>
+#include <QDropEvent>
+#include <QFileDialog>
+#include <QHttpRequestHeader>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QNetworkProxy>
+#include <QUndoStack>
+#include <QUrl>
+#include <QPainter>
+
+using namespace WebCore;
+
+QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
+    : q(qq), modified(false)
+{
+    q->setMouseTracking(true);
+    q->setFocusPolicy(Qt::ClickFocus);
+    chromeClient = new ChromeClientQt(q);
+    contextMenuClient = new ContextMenuClientQt();
+    editorClient = new EditorClientQt(q);
+    page = new Page(chromeClient, contextMenuClient, editorClient,
+                    new DragClientQt(q), new InspectorClientQt());
+
+    undoStack = 0;
+    mainFrame = 0;
+    networkInterface = 0;
+    insideOpenCall = false;
+}
+
+QWebPagePrivate::~QWebPagePrivate()
+{
+    delete undoStack;
+    delete page;
+}
+
+QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
+{
+    if (insideOpenCall
+        && frame == mainFrame)
+        return QWebPage::AcceptNavigationRequest;
+    return q->navigationRequested(frame, request, type);
+}
+
+void QWebPagePrivate::createMainFrame()
+{
+    if (!mainFrame) {
+        QWebFrameData frameData;
+        frameData.ownerElement = 0;
+        frameData.allowsScrolling = true;
+        frameData.marginWidth = 0;
+        frameData.marginHeight = 0;
+        mainFrame = q->createFrame(0, &frameData);
+        QObject::connect(mainFrame, SIGNAL(titleChanged(const QString&)),
+                q, SIGNAL(titleChanged(const QString&)));
+        QObject::connect(mainFrame, SIGNAL(hoveringOverLink(const QString&, const QString&)),
+                q, SIGNAL(hoveringOverLink(const QString&, const QString&)));
+        
+        mainFrame->d->frameView->setFrameGeometry(q->geometry());
+    }
+}
+
+
+QWebPage::QWebPage(QWidget *parent)
+    : QWidget(parent)
+    , d(new QWebPagePrivate(this))
+{
+    setSettings(QWebSettings::global());
+    QPalette pal = palette();
+    pal.setBrush(QPalette::Background, Qt::white);
+
+    setAttribute(Qt::WA_OpaquePaintEvent);
+
+    setPalette(pal);
+    setAcceptDrops(true);
+    connect(this, SIGNAL(loadProgressChanged(int)), this, SLOT(onLoadProgressChanged(int)));
+}
+
+QWebPage::~QWebPage()
+{
+    FrameLoader *loader = d->mainFrame->d->frame->loader();
+    if (loader)
+        loader->detachFromParent();
+    delete d;
+}
+
+QWebFrame *QWebPage::createFrame(QWebFrame *parentFrame, QWebFrameData *frameData)
+{
+    if (parentFrame)
+        return new QWebFrame(parentFrame, frameData);
+    QWebFrame *f = new QWebFrame(this, frameData);
+    return f;
+}
+
+void QWebPage::open(const QUrl &url)
+{
+    open(QWebNetworkRequest(url));
+}
+
+void QWebPage::open(const QWebNetworkRequest &req)
+{
+    d->insideOpenCall = true;
+
+    QUrl url = req.url();
+    QHttpRequestHeader httpHeader = req.httpHeader();
+    QByteArray postData = req.postData();
+
+    WebCore::ResourceRequest request(KURL(url.toString()));
+
+    QString method = httpHeader.method();
+    if (!method.isEmpty())
+        request.setHTTPMethod(method);
+
+    QList<QPair<QString, QString> > values = httpHeader.values();
+    for (int i = 0; i < values.size(); ++i) {
+        const QPair<QString, QString> &val = values.at(i);
+        request.addHTTPHeaderField(val.first, val.second);
+    }
+
+    if (!postData.isEmpty()) {
+        WTF::RefPtr<WebCore::FormData> formData = new WebCore::FormData(postData.constData(), postData.size());
+        request.setHTTPBody(formData);
+    }
+
+    mainFrame()->d->frame->loader()->load(request);
+    d->insideOpenCall = false;
+}
+
+QUrl QWebPage::url() const
+{
+    return QUrl((QString)mainFrame()->d->frame->loader()->url().url());
+}
+
+QString QWebPage::title() const
+{
+    return mainFrame()->title();
+}
+
+QWebFrame *QWebPage::mainFrame() const
+{
+    d->createMainFrame();
+    return d->mainFrame;
+}
+
+QSize QWebPage::sizeHint() const
+{
+    return QSize(800, 600);
+}
+
+void QWebPage::stop()
+{
+    FrameLoader *f = mainFrame()->d->frame->loader();
+    f->stopForUserCancel();
+}
+
+QWebPageHistory QWebPage::history() const
+{
+    WebCore::BackForwardList *lst = d->page->backForwardList();
+    QWebPageHistoryPrivate *priv = new QWebPageHistoryPrivate(lst);
+    return QWebPageHistory(priv);
+}
+
+void QWebPage::goBack()
+{
+    d->page->goBack();
+}
+
+void QWebPage::goForward()
+{
+    d->page->goForward();
+}
+
+void QWebPage::goToHistoryItem(const QWebHistoryItem &item)
+{
+    d->page->goToItem(item.d->item, FrameLoadTypeIndexedBackForward);
+}
+
+void QWebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID)
+{
+}
+
+void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
+{
+    //FIXME frame pos...
+    QMessageBox::information(this, title(), msg, QMessageBox::Ok);
+}
+
+bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
+{
+    //FIXME frame pos...
+    return 0 == QMessageBox::information(this, title(), msg, QMessageBox::Yes, QMessageBox::No);
+}
+
+bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
+{
+    //FIXME frame pos...
+    bool ok = false;
+#ifndef QT_NO_INPUTDIALOG
+    QString x = QInputDialog::getText(this, title(), msg, QLineEdit::Normal, defaultValue, &ok);
+    if (ok && result) {
+        *result = x;
+    }
+#endif
+    return ok;
+}
+
+QWebPage *QWebPage::createWindow()
+{
+    return 0;
+}
+
+QWebPage *QWebPage::createModalDialog()
+{
+    return 0;
+}
+
+QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
+{
+    Q_UNUSED(classid)
+    Q_UNUSED(url)
+    Q_UNUSED(paramNames)
+    Q_UNUSED(paramValues)
+    return 0;
+}
+
+QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
+{
+    Q_UNUSED(request)
+    return AcceptNavigationRequest;
+}
+
+void QWebPage::setWindowGeometry(const QRect& geom)
+{
+    Q_UNUSED(geom)
+}
+
+bool QWebPage::canCut() const
+{
+    return d->page->focusController()->focusedOrMainFrame()->editor()->canCut();
+}
+
+bool QWebPage::canCopy() const
+{
+    return d->page->focusController()->focusedOrMainFrame()->editor()->canCopy();
+}
+
+bool QWebPage::canPaste() const
+{
+    return d->page->focusController()->focusedOrMainFrame()->editor()->canPaste();
+}
+
+void QWebPage::cut()
+{
+    d->page->focusController()->focusedOrMainFrame()->editor()->cut();
+}
+
+void QWebPage::copy()
+{
+    d->page->focusController()->focusedOrMainFrame()->editor()->copy();
+}
+
+void QWebPage::paste()
+{
+    d->page->focusController()->focusedOrMainFrame()->editor()->paste();
+}
+
+/*!
+  Returns true if the page contains unsubmitted form data.
+*/
+bool QWebPage::isModified() const
+{
+    return d->modified;
+}
+
+
+QUndoStack *QWebPage::undoStack()
+{
+    if (!d->undoStack)
+        d->undoStack = new QUndoStack(this);
+
+    return d->undoStack;
+}
+
+static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
+{
+    unsigned result = 0;
+    if (actions & Qt::CopyAction)
+        result |= DragOperationCopy;
+    if (actions & Qt::MoveAction)
+        result |= DragOperationMove;
+    if (actions & Qt::LinkAction)
+        result |= DragOperationLink;
+    return (DragOperation)result;    
+}
+
+static inline Qt::DropAction dragOpToDropAction(unsigned actions)
+{
+    Qt::DropAction result = Qt::IgnoreAction;
+    if (actions & DragOperationCopy)
+        result = Qt::CopyAction;
+    else if (actions & DragOperationMove)
+        result = Qt::MoveAction;
+    else if (actions & DragOperationLink)
+        result = Qt::LinkAction;
+    return result;    
+}
+
+void QWebPage::resizeEvent(QResizeEvent *e)
+{
+    QWidget::resizeEvent(e);
+    if (mainFrame()->d->frame && mainFrame()->d->frameView) {
+        mainFrame()->d->frameView->setFrameGeometry(rect());
+        mainFrame()->d->frame->forceLayout();
+        mainFrame()->d->frame->view()->adjustViewSize();
+    }
+}
+
+void QWebPage::paintEvent(QPaintEvent *ev)
+{
+#ifdef QWEBKIT_TIME_RENDERING
+    QTime time;
+    time.start();
+#endif
+
+    QPainter p(this);
+
+    QVector<QRect> vector = ev->region().rects();
+    if (!vector.isEmpty()) {
+        for (int i = 0; i < vector.size(); ++i) {
+            mainFrame()->render(&p, vector.at(i));
+        }
+    } else {
+        mainFrame()->render(&p, ev->rect());
+    }
+
+#ifdef    QWEBKIT_TIME_RENDERING
+    int elapsed = time.elapsed();
+    qDebug()<<"paint event on "<<ev->region()<<", took to render =  "<<elapsed;
+#endif
+}
+
+void QWebPage::mouseMoveEvent(QMouseEvent *ev)
+{
+    mainFrame()->mouseMoveEvent(ev);
+}
+
+void QWebPage::mousePressEvent(QMouseEvent *ev)
+{
+    mainFrame()->mousePressEvent(ev);
+}
+
+void QWebPage::mouseDoubleClickEvent(QMouseEvent *ev)
+{
+    mainFrame()->mouseDoubleClickEvent(ev);
+}
+
+void QWebPage::mouseReleaseEvent(QMouseEvent *ev)
+{
+    mainFrame()->mouseReleaseEvent(ev);
+}
+
+void QWebPage::wheelEvent(QWheelEvent *ev)
+{
+    mainFrame()->wheelEvent(ev);
+    if (!ev->isAccepted())
+        QWidget::wheelEvent(ev);
+}
+
+void QWebPage::keyPressEvent(QKeyEvent *ev)
+{
+    PlatformKeyboardEvent kevent(ev, false);
+
+    if (!mainFrame()->d->eventHandler)
+        return;
+
+    bool handled = mainFrame()->d->eventHandler->keyEvent(kevent);
+    if (handled) {
+    } else {
+        handled = true;
+        PlatformScrollbar *h, *v;
+        h = mainFrame()->d->horizontalScrollBar();
+        v = mainFrame()->d->verticalScrollBar();
+
+        if (ev == QKeySequence::MoveToNextPage) {
+            if (v)
+                v->setValue(v->value() + height());
+        } else if (ev == QKeySequence::MoveToPreviousPage) {
+            if (v)
+                v->setValue(v->value() - height());
+        } else {
+            switch (ev->key()) {
+                case Qt::Key_Up:
+                    if (v)
+                        v->setValue(v->value() - 10);
+                    break;
+                case Qt::Key_Down:
+                    if (v)
+                        v->setValue(v->value() + 10);
+                    break;
+                case Qt::Key_Left:
+                    if (h)
+                        h->setValue(h->value() - 10);
+                    break;
+                case Qt::Key_Right:
+                    if (h)
+                        h->setValue(h->value() + 10);
+                    break;
+                default:
+                    handled = false;
+                    break;
+            }
+        }
+    }
+
+    ev->setAccepted(handled);
+}
+
+void QWebPage::keyReleaseEvent(QKeyEvent *ev)
+{
+    if (ev->isAutoRepeat()) {
+        ev->setAccepted(true);
+        return;
+    }
+
+    PlatformKeyboardEvent kevent(ev, true);
+
+    if (!mainFrame()->d->eventHandler)
+        return;
+
+    bool handled = mainFrame()->d->eventHandler->keyEvent(kevent);
+    ev->setAccepted(handled);
+}
+
+void QWebPage::focusInEvent(QFocusEvent *ev)
+{
+    if (ev->reason() != Qt::PopupFocusReason) {
+        mainFrame()->d->frame->page()->focusController()->setFocusedFrame(mainFrame()->d->frame);
+        mainFrame()->d->frame->setIsActive(true);
+    }
+    QWidget::focusInEvent(ev);
+}
+
+void QWebPage::focusOutEvent(QFocusEvent *ev)
+{
+    QWidget::focusOutEvent(ev);
+    if (ev->reason() != Qt::PopupFocusReason) {
+        mainFrame()->d->frame->selectionController()->clear();
+        mainFrame()->d->frame->setIsActive(false);
+    }
+}
+
+bool QWebPage::focusNextPrevChild(bool next)
+{
+    Q_UNUSED(next)
+    return false;
+}
+
+void QWebPage::dragEnterEvent(QDragEnterEvent *ev)
+{
+#ifndef QT_NO_DRAGANDDROP
+    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), 
+                      dropActionToDragOp(ev->possibleActions()));
+    Qt::DropAction action = dragOpToDropAction(d->page->dragController()->dragEntered(&dragData));
+    ev->setDropAction(action);
+    ev->accept();
+#endif
+}
+
+void QWebPage::dragLeaveEvent(QDragLeaveEvent *ev)
+{
+#ifndef QT_NO_DRAGANDDROP
+    DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
+    d->page->dragController()->dragExited(&dragData);
+    ev->accept();
+#endif
+}
+
+void QWebPage::dragMoveEvent(QDragMoveEvent *ev)
+{
+#ifndef QT_NO_DRAGANDDROP
+    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), 
+                      dropActionToDragOp(ev->possibleActions()));
+    Qt::DropAction action = dragOpToDropAction(d->page->dragController()->dragUpdated(&dragData));
+    ev->setDropAction(action);
+    ev->accept();
+#endif
+}
+
+void QWebPage::dropEvent(QDropEvent *ev)
+{
+#ifndef QT_NO_DRAGANDDROP
+    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), 
+                      dropActionToDragOp(ev->possibleActions()));
+    Qt::DropAction action = dragOpToDropAction(d->page->dragController()->performDrag(&dragData));
+    ev->accept();
+#endif
+}
+
+void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
+{
+    d->networkInterface = interface;
+}
+
+QWebNetworkInterface *QWebPage::networkInterface() const
+{
+    if (d->networkInterface)
+        return d->networkInterface;
+    else
+        return QWebNetworkInterface::defaultInterface();
+}
+
+QPixmap QWebPage::icon() const
+{
+    Image* image = iconDatabase()->iconForPageURL(url().toString(), IntSize(16, 16));
+    if (!image || image->isNull()) {
+        image = iconDatabase()->defaultIcon(IntSize(16, 16));
+    }
+
+    if (!image) {
+        return QPixmap();
+    }
+
+    QPixmap *icon = image->getPixmap();
+    if (!icon) {
+        return QPixmap();
+    }
+    return *icon;
+}
+
+void QWebPage::setSettings(const QWebSettings &settings)
+{
+    WebCore::Settings *wSettings = d->page->settings();
+
+    wSettings->setStandardFontFamily(
+        settings.fontFamily(QWebSettings::StandardFont));
+    wSettings->setFixedFontFamily(
+        settings.fontFamily(QWebSettings::FixedFont));
+    wSettings->setSerifFontFamily(
+        settings.fontFamily(QWebSettings::SerifFont));
+    wSettings->setSansSerifFontFamily(
+        settings.fontFamily(QWebSettings::SansSerifFont));
+    wSettings->setCursiveFontFamily(
+        settings.fontFamily(QWebSettings::CursiveFont));
+    wSettings->setFantasyFontFamily(
+        settings.fontFamily(QWebSettings::FantasyFont));
+
+    wSettings->setMinimumFontSize(settings.minimumFontSize());
+    wSettings->setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
+    wSettings->setDefaultFontSize(settings.defaultFontSize());
+    wSettings->setDefaultFixedFontSize(settings.defaultFixedFontSize());
+
+    wSettings->setLoadsImagesAutomatically(
+        settings.testAttribute(QWebSettings::AutoLoadImages));
+    wSettings->setJavaScriptEnabled(
+        settings.testAttribute(QWebSettings::JavascriptEnabled));
+    wSettings->setJavaScriptCanOpenWindowsAutomatically(
+        settings.testAttribute(QWebSettings::JavascriptCanOpenWindows));
+    wSettings->setJavaEnabled(
+        settings.testAttribute(QWebSettings::JavaEnabled));
+    wSettings->setPluginsEnabled(
+        settings.testAttribute(QWebSettings::PluginsEnabled));
+    wSettings->setPrivateBrowsingEnabled(
+        settings.testAttribute(QWebSettings::PrivateBrowsingEnabled));
+
+    wSettings->setUserStyleSheetLocation(KURL(settings.userStyleSheetLocation()));
+
+    // ### should be configurable
+    wSettings->setDefaultTextEncodingName("iso-8859-1");
+}
+
+QWebSettings QWebPage::settings() const
+{
+    QWebSettings settings;
+    WebCore::Settings *wSettings = d->page->settings();
+
+    settings.setFontFamily(QWebSettings::StandardFont,
+                           wSettings->standardFontFamily());
+    settings.setFontFamily(QWebSettings::FixedFont,
+                           wSettings->fixedFontFamily());
+    settings.setFontFamily(QWebSettings::SerifFont,
+                           wSettings->serifFontFamily());
+    settings.setFontFamily(QWebSettings::SansSerifFont,
+                           wSettings->sansSerifFontFamily());
+    settings.setFontFamily(QWebSettings::CursiveFont,
+                           wSettings->cursiveFontFamily());
+    settings.setFontFamily(QWebSettings::FantasyFont,
+                           wSettings->fantasyFontFamily());
+
+    settings.setMinimumFontSize(wSettings->minimumFontSize());
+    settings.setMinimumLogicalFontSize(wSettings->minimumLogicalFontSize());
+    settings.setDefaultFontSize(wSettings->defaultFontSize());
+    settings.setDefaultFixedFontSize(wSettings->defaultFixedFontSize());
+
+    settings.setAttribute(QWebSettings::AutoLoadImages,
+                          wSettings->loadsImagesAutomatically());
+    settings.setAttribute(QWebSettings::JavascriptEnabled,
+                          wSettings->isJavaScriptEnabled());
+    settings.setAttribute(QWebSettings::JavascriptCanOpenWindows,
+                          wSettings->JavaScriptCanOpenWindowsAutomatically());
+    settings.setAttribute(QWebSettings::JavaEnabled,
+                          wSettings->isJavaEnabled());
+    settings.setAttribute(QWebSettings::PluginsEnabled,
+                          wSettings->arePluginsEnabled());
+    settings.setAttribute(QWebSettings::PrivateBrowsingEnabled,
+                          wSettings->privateBrowsingEnabled());
+
+    settings.setUserStyleSheetLocation(
+        wSettings->userStyleSheetLocation().url());
+
+    return settings;
+}
+
+QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& oldFile)
+{
+    //FIXME frame pos...
+#ifndef QT_NO_FILEDIALOG
+    return QFileDialog::getOpenFileName(this, QString::null, oldFile);
+#else
+    return QString::null;
+#endif
+}
+
+#ifndef QT_NO_NETWORKPROXY
+void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
+{
+    d->networkProxy = proxy;
+}
+
+QNetworkProxy QWebPage::networkProxy() const
+{
+    return d->networkProxy;
+}
+#endif
+
+QString QWebPage::userAgentStringForUrl(const QUrl& forUrl) const {
+    Q_UNUSED(forUrl)
+    return QLatin1String("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3 Qt");
+}
+
+
+void QWebPage::onLoadProgressChanged(int) {
+    d->m_totalBytes = d->page->progress()->totalPageAndResourceBytesToLoad();
+    d->m_bytesReceived = d->page->progress()->totalBytesReceived();
+}
+
+
+quint64 QWebPage::totalBytes() const {
+    return d->m_bytesReceived;
+}
+
+
+quint64 QWebPage::bytesReceived() const {
+    return d->m_totalBytes;
+}