qwebframe.cpp 28.6 KB
Newer Older
1 2
/*
    Copyright (C) 2007 Trolltech ASA
3
    Copyright (C) 2007 Staikos Computing Services Inc.
4 5 6 7 8 9 10 11 12 13 14 15 16

    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
ddkilzer's avatar
ddkilzer committed
17 18
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
19
*/
20

21
#include "config.h"
22 23 24 25 26
#include "qwebframe.h"
#include "qwebpage.h"
#include "qwebpage_p.h"
#include "qwebframe_p.h"

hausmann@webkit.org's avatar
hausmann@webkit.org committed
27
#include "DocumentLoader.h"
28
#include "FocusController.h"
29
#include "FrameLoaderClientQt.h"
mjs's avatar
mjs committed
30
#include "Frame.h"
staikos's avatar
staikos committed
31
#include "FrameTree.h"
32
#include "FrameView.h"
33
#include "IconDatabase.h"
34
#include "Page.h"
lars's avatar
lars committed
35
#include "ResourceRequest.h"
36
#include "RenderView.h"
37
#include "SelectionController.h"
38
#include "PlatformScrollBar.h"
39
#include "PrintContext.h"
40
#include "SubstituteData.h"
41 42 43 44 45

#include "markup.h"
#include "RenderTreeAsText.h"
#include "Element.h"
#include "Document.h"
46
#include "DragData.h"
47
#include "RenderView.h"
48 49 50 51 52 53
#include "GraphicsContext.h"
#include "PlatformScrollBar.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
54

hausmann@webkit.org's avatar
hausmann@webkit.org committed
55 56
#include "runtime.h"
#include "runtime_root.h"
weinig@apple.com's avatar
weinig@apple.com committed
57
#include "JSDOMWindow.h"
hausmann@webkit.org's avatar
hausmann@webkit.org committed
58
#include "qt_instance.h"
staikos's avatar
staikos committed
59 60
#include "kjs_proxy.h"
#include "kjs_binding.h"
61 62
#include "ExecState.h"
#include "object.h"
63
#include "qt_runtime.h"
64

lars's avatar
lars committed
65
#include "wtf/HashMap.h"
66

67
#include <qdebug.h>
68
#include <qevent.h>
69
#include <qfileinfo.h>
70
#include <qpainter.h>
71 72
#if QT_VERSION >= 0x040400
#include <qnetworkrequest.h>
73 74
#else
#include "qwebnetworkinterface.h"
75
#endif
76
#include <qregion.h>
77
#include <qprinter.h>
78

79 80
using namespace WebCore;

81 82 83 84 85
// from text/qfont.cpp
QT_BEGIN_NAMESPACE
extern Q_GUI_EXPORT int qt_defaultDpi();
QT_END_NAMESPACE

86
void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData)
87 88
{
    q = qframe;
89

90 91 92 93
    allowsScrolling = frameData->allowsScrolling;
    marginWidth = frameData->marginWidth;
    marginHeight = frameData->marginHeight;

94
    frameLoaderClient = new FrameLoaderClientQt();
95
    frame = new Frame(webcorePage, frameData->ownerElement, frameLoaderClient);
96
    frameLoaderClient->setFrame(qframe, frame);
mjs's avatar
mjs committed
97
    frame->init();
98 99
}

100 101
WebCore::PlatformScrollbar *QWebFramePrivate::horizontalScrollBar() const
{
102 103 104
    if (!frame->view())
        return 0;
    return frame->view()->horizontalScrollBar();
105
}
106

107 108
WebCore::PlatformScrollbar *QWebFramePrivate::verticalScrollBar() const
{
109 110 111
    if (!frame->view())
        return 0;
    return frame->view()->verticalScrollBar();
112 113
}

114 115 116 117 118 119 120 121 122 123 124 125 126
void QWebFramePrivate::updateBackground()
{
    WebCore::FrameView *view = frame->view();
    if (!view)
        return;
    QBrush brush = page->palette().brush(QPalette::Background);
    if (brush.style() == Qt::SolidPattern) {
        view->setBaseBackgroundColor(brush.color());
        if (!brush.color().alpha())
            view->setTransparent(true);
    }
}

127 128 129 130 131 132
/*!
    \class QWebFrame
    \since 4.4
    \brief The QWebFrame class represents a frame in a web page.

    QWebFrame represents a frame inside a web page. Each QWebPage
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    object contains at least one frame, the main frame, obtained using
    QWebPage::mainFrame(). Additional frames will be created for HTML
    \c{<frame>} or \c{<iframe>} elements.

    A frame can be loaded using load() or setUrl(). Alternatively, if you have
    the HTML content readily available, you can use setHtml() instead.

    The page() function returns a pointer to the web page object. See
    \l{Elements of QWebView} for an explanation of how web
    frames are related to a web page and web view.

    The title of an HTML frame can be accessed with the title() property.
    Additionally, a frame may also specify an icon, which can be accessed
    using the icon() property. If the title or the icon changes, the
    corresponding titleChanged() and iconChanged() signals will be emitted.
    The textSizeMultiplier() property can be used to change the overall size
    of the text displayed in the frame.
150 151

    QWebFrame objects are created and controlled by the web page. You
152
    can connect to the web page's \l{QWebPage::}{frameCreated()} signal
153 154 155 156 157 158 159 160 161
    to be notified when a new frame is created.

    The hitTestContent() function can be used to programmatically examine the
    contents of a frame.

    A QWebFrame can be printed onto a QPrinter using the print() function.
    This function is marked as a slot and can be conveniently connected to
    \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()}
    signal.
162 163 164 165

    \sa QWebPage
*/

lars's avatar
lars committed
166
QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
167
    : QObject(parent)
168 169
    , d(new QWebFramePrivate)
{
170 171
    d->page = parent;
    d->init(this, parent->d->page, frameData);
172

lars's avatar
lars committed
173 174 175 176
    if (!frameData->url.isEmpty()) {
        ResourceRequest request(frameData->url, frameData->referrer);
        d->frame->loader()->load(request, frameData->name);
    }
177 178
}

lars's avatar
lars committed
179
QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
180
    : QObject(parent)
181 182
    , d(new QWebFramePrivate)
{
183 184
    d->page = parent->d->page;
    d->init(this, parent->d->page->d->page, frameData);
185 186 187 188
}

QWebFrame::~QWebFrame()
{
189 190
    if (d->frame && d->frame->loader() && d->frame->loader()->client())
        static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0;
191

lars's avatar
lars committed
192
    delete d;
193 194
}

195
/*!
196 197 198 199 200 201
    Make \a object available under \a name from within the frame's JavaScript
    context. The \a object will be inserted as a child of the frame's window
    object.

    Qt properties will be exposed as JavaScript properties and slots as
    JavaScript methods.
202

203 204 205
    If you want to ensure that your QObjects remain accessible after loading a
    new URL, you should add them in a slot connected to the
    javaScriptWindowObjectCleared() signal.
206
*/
207
void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object)
208
{
209
      KJS::JSLock lock;
210
      JSDOMWindow *window = toJSDOMWindow(d->frame);
211 212 213 214 215 216
      KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
      if (!window) {
          qDebug() << "Warning: couldn't get window object";
          return;
      }

217 218
      KJS::ExecState* exec = window->globalExec();

219
      KJS::JSObject *runtimeObject =
220
        KJS::Bindings::Instance::createRuntimeObject(exec, KJS::Bindings::QtInstance::create(object, root));
221

222
      window->put(exec, KJS::Identifier((const UChar *) name.constData(), name.length()), runtimeObject);
223 224
}

225
/*!
226
    Returns the frame's content, converted to HTML.
227 228

    \sa setHtml(), toPlainText()
229
*/
230
QString QWebFrame::toHtml() const
231
{
232 233
    if (!d->frame->document())
        return QString();
234 235 236
    return createMarkup(d->frame->document());
}

237
/*!
238
    Returns the content of this frame converted to plain text.
239 240

    \sa toHtml()
241
*/
242
QString QWebFrame::toPlainText() const
243
{
244 245
    if (d->frame->view() && d->frame->view()->layoutPending())
        d->frame->view()->layout();
zack's avatar
zack committed
246

247 248 249 250
    Element *documentElement = d->frame->document()->documentElement();
    return documentElement->innerText();
}

251
/*!
252 253
    Returns a dump of the rendering tree. This is mainly useful for debugging
    html.
254
*/
255 256
QString QWebFrame::renderTreeDump() const
{
257 258
    if (d->frame->view() && d->frame->view()->layoutPending())
        d->frame->view()->layout();
zack's avatar
zack committed
259

260
    return externalRepresentation(d->frame->contentRenderer());
261 262
}

263
/*!
264 265
    \property QWebFrame::title
    \brief the title of the frame as defined by the HTML &lt;title&gt; element
266 267

    \sa titleChanged()
268
*/
269

270 271 272
QString QWebFrame::title() const
{
    if (d->frame->document())
hausmann@webkit.org's avatar
hausmann@webkit.org committed
273
        return d->frame->loader()->documentLoader()->title();
274 275
    else return QString();
}
276

277 278 279 280 281 282 283 284
static inline QUrl ensureAbsoluteUrl(const QUrl &url)
{
    if (!url.isRelative())
        return url;

    return QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath());
}

285
/*!
286
    \property QWebFrame::url
287
    \brief the url of the frame currently viewed
288 289

    \sa urlChanged()
290
*/
291 292 293

void QWebFrame::setUrl(const QUrl &url)
{
294
    d->frame->loader()->begin(ensureAbsoluteUrl(url));
295
    d->frame->loader()->end();
296
    load(ensureAbsoluteUrl(url));
297 298
}

299 300
QUrl QWebFrame::url() const
{
301
    return d->frame->loader()->url();
302 303
}

304
/*!
305 306
    \property QWebFrame::icon
    \brief the icon associated with this frame
307

308
    \sa iconChanged(), QWebSettings::iconForUrl()
309
*/
310

311
QIcon QWebFrame::icon() const
312
{
313
    return QWebSettings::iconForUrl(d->frame->loader()->url());
314 315
}

316 317 318
/*!
  The name of this frame as defined by the parent frame.
*/
319
QString QWebFrame::frameName() const
320 321 322 323
{
    return d->frame->tree()->name();
}

324 325 326 327
/*!
  The web page that contains this frame.
*/
QWebPage *QWebFrame::page() const
328 329 330 331
{
    return d->page;
}

332
/*!
333 334 335
  Loads \a url into this frame.

  \note The view remains the same until enough data has arrived to display the new \a url.
336 337

  \sa setUrl(), setHtml(), setContent()
338
*/
339 340
void QWebFrame::load(const QUrl &url)
{
341
#if QT_VERSION < 0x040400
342
    load(QWebNetworkRequest(ensureAbsoluteUrl(url)));
343
#else
344
    load(QNetworkRequest(ensureAbsoluteUrl(url)));
345
#endif
346 347
}

348
#if QT_VERSION < 0x040400
349
/*!
350 351 352
  Loads a network request, \a req, into this frame.

  \note The view remains the same until enough data has arrived to display the new url.
353
*/
354 355 356 357 358
void QWebFrame::load(const QWebNetworkRequest &req)
{
    if (d->parentFrame())
        d->page->d->insideOpenCall = true;

359
    QUrl url = ensureAbsoluteUrl(req.url());
360 361 362
    QHttpRequestHeader httpHeader = req.httpHeader();
    QByteArray postData = req.postData();

363
    WebCore::ResourceRequest request(url);
364 365 366 367 368 369 370 371 372 373 374

    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);
    }

375 376
    if (!postData.isEmpty())
        request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size()));
377 378 379 380 381 382 383

    d->frame->loader()->load(request);

    if (d->parentFrame())
        d->page->d->insideOpenCall = false;
}

384 385
#else

386
/*!
387 388 389 390 391 392
  Loads a network request, \a req, into this frame, using the method specified in \a
  operation.

  \a body is optional and is only used for POST operations.

  \note The view remains the same until enough data has arrived to display the new \a url.
393 394

  \sa setUrl()
395
*/
396 397 398
void QWebFrame::load(const QNetworkRequest &req,
                     QNetworkAccessManager::Operation operation,
                     const QByteArray &body)
399 400 401 402
{
    if (d->parentFrame())
        d->page->d->insideOpenCall = true;

403
    QUrl url = ensureAbsoluteUrl(req.url());
404

405
    WebCore::ResourceRequest request(url);
406

407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
    switch (operation) {
        case QNetworkAccessManager::HeadOperation:
            request.setHTTPMethod("HEAD");
            break;
        case QNetworkAccessManager::GetOperation:
            request.setHTTPMethod("GET");
            break;
        case QNetworkAccessManager::PutOperation:
            request.setHTTPMethod("PUT");
            break;
        case QNetworkAccessManager::PostOperation:
            request.setHTTPMethod("POST");
            break;
        case QNetworkAccessManager::UnknownOperation:
            // eh?
            break;
    }
424 425 426 427 428 429 430

    QList<QByteArray> httpHeaders = req.rawHeaderList();
    for (int i = 0; i < httpHeaders.size(); ++i) {
        const QByteArray &headerName = httpHeaders.at(i);
        request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));
    }

431 432
    if (!body.isEmpty())
        request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));
433 434 435 436 437 438 439 440

    d->frame->loader()->load(request);

    if (d->parentFrame())
        d->page->d->insideOpenCall = false;
}
#endif

441 442 443
/*!
  Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative
  URLs in the document.
444 445 446 447 448

  When using this method WebKit assumes that external resources such as JavaScript programs or style
  sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external
  script can be specified through the charset attribute of the HTML script tag. It is also possible
  for the encoding to be specified by web server.
449 450

  \sa toHtml()
451
*/
452 453
void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl)
{
454
    KURL kurl(baseUrl);
455
    WebCore::ResourceRequest request(kurl);
456 457 458
    const QByteArray utf8 = html.toUtf8();
    WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length());
    WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-8"), kurl);
459 460 461
    d->frame->loader()->load(request, substituteData);
}

462
/*!
463 464 465 466 467
  Sets the content of this frame to the specified content \a data. If the \a mimeType argument
  is empty it is currently assumed that the content is HTML but in future versions we may introduce
  auto-detection.

  External objects referenced in the content are located relative to \a baseUrl.
468 469

  \sa toHtml()
470
*/
471 472
void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
{
473
    KURL kurl(baseUrl);
474
    WebCore::ResourceRequest request(kurl);
hausmann@webkit.org's avatar
hausmann@webkit.org committed
475
    WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length());
476 477 478 479 480 481 482
    QString actualMimeType = mimeType;
    if (actualMimeType.isEmpty())
        actualMimeType = QLatin1String("text/html");
    WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl);
    d->frame->loader()->load(request, substituteData);
}

483 484 485 486 487 488

/*!
  Returns the parent frame of this frame, or 0 if the frame is the web pages
  main frame.

  This is equivalent to qobject_cast<QWebFrame*>(frame->parent()).
489 490

  \sa childFrames()
491 492 493 494 495 496 497 498
*/
QWebFrame *QWebFrame::parentFrame() const
{
    return d->parentFrame();
}

/*!
  Returns a list of all frames that are direct children of this frame.
499 500

  \sa parentFrame()
501
*/
staikos's avatar
staikos committed
502 503 504 505 506 507
QList<QWebFrame*> QWebFrame::childFrames() const
{
    QList<QWebFrame*> rc;
    if (d->frame) {
        FrameTree *tree = d->frame->tree();
        for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
508 509 510 511
            FrameLoader *loader = child->loader();
            FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
            if (client)
                rc.append(client->webFrame());
staikos's avatar
staikos committed
512 513 514 515
        }

    }
    return rc;
lars's avatar
lars committed
516 517
}

518
/*!
519
    Returns the scrollbar policy for the scrollbar defined by \a orientation.
520
*/
521
Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const
lars's avatar
lars committed
522
{
523 524
    if (orientation == Qt::Horizontal)
        return d->horizontalScrollBarPolicy;
525
    return d->verticalScrollBarPolicy;
lars's avatar
lars committed
526 527
}

528 529 530 531
/*!
    Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy.
*/
void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy)
lars's avatar
lars committed
532
{
533 534 535
    Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded);
    Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff);
    Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn);
536

537 538 539 540 541 542 543 544 545
    if (orientation == Qt::Horizontal) {
        d->horizontalScrollBarPolicy = policy;
        if (d->frame->view())
            d->frame->view()->setHScrollbarMode((ScrollbarMode)policy);
    } else {
        d->verticalScrollBarPolicy = policy;
        if (d->frame->view())
            d->frame->view()->setVScrollbarMode((ScrollbarMode)policy);
    }
546 547
}

548
/*!
549
  Sets the current \a value for the scrollbar with orientation \a orientation.
550

551
  The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum.
552 553

  Changing the value also updates the thumb position.
554 555

  \sa scrollBarMinimum(), scrollBarMaximum()
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
*/
void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value)
{
    PlatformScrollbar *sb;
    sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
    if (sb) {
        if (value < 0)
            value = 0;
        else if (value > scrollBarMaximum(orientation))
            value = scrollBarMaximum(orientation);
        sb->setValue(value);
    }
}

/*!
  Returns the current value for the scrollbar with orientation \a orientation, or 0
  if no scrollbar is found for \a orientation.
573 574

  \sa scrollBarMinimum(), scrollBarMaximum()
575 576 577 578 579 580 581 582 583 584 585 586 587 588
*/
int QWebFrame::scrollBarValue(Qt::Orientation orientation) const
{
    PlatformScrollbar *sb;
    sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
    if (sb) {
        return sb->value();
    }
    return 0;
}

/*!
  Returns the maximum value for the scrollbar with orientation \a orientation, or 0
  if no scrollbar is found for \a orientation.
589 590

  \sa scrollBarMinimum()
591 592 593 594 595
*/
int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const
{
    PlatformScrollbar *sb;
    sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
596 597
    if (sb)
        return sb->maximum();
598 599 600 601 602 603 604
    return 0;
}

/*!
  Returns the minimum value for the scrollbar with orientation \a orientation.

  The minimum value is always 0.
605 606

  \sa scrollBarMaximum()
607 608 609 610 611 612
*/
int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const
{
    return 0;
}

613 614
/*!
  Render the frame into \a painter clipping to \a clip.
615 616

  \sa print()
617 618
*/
void QWebFrame::render(QPainter *painter, const QRegion &clip)
619
{
620
    if (!d->frame->view() || !d->frame->contentRenderer())
621 622
        return;

623
    d->frame->view()->layoutIfNeededRecursive();
624 625

    GraphicsContext ctx(painter);
626
    QVector<QRect> vector = clip.rects();
627
    WebCore::FrameView* view = d->frame->view();
628
    for (int i = 0; i < vector.size(); ++i)
629
        view->paint(&ctx, vector.at(i));
630 631
}

632
/*!
633
  Render the frame into \a painter.
634
*/
635
void QWebFrame::render(QPainter *painter)
636
{
637
    if (!d->frame->view() || !d->frame->contentRenderer())
638
        return;
639

640 641 642 643 644
    d->frame->view()->layoutIfNeededRecursive();

    GraphicsContext ctx(painter);
    WebCore::FrameView* view = d->frame->view();
    view->paint(&ctx, view->frameGeometry());
645 646
}

647
/*!
648
  \property QWebFrame::textSizeMultiplier
649
  \brief the scaling factor for all text in the frame
650
*/
651 652

void QWebFrame::setTextSizeMultiplier(qreal factor)
653
{
654 655
    d->frame->setZoomFactor(factor, /*isTextOnly*/true);
}
656

657 658
qreal QWebFrame::textSizeMultiplier() const
{
659
    return d->frame->zoomFactor();
660 661
}

662
/*!
663
    Returns the position of the frame relative to it's parent frame.
664
*/
665 666
QPoint QWebFrame::pos() const
{
667 668 669 670
    if (!d->frame->view())
        return QPoint();

    return d->frame->view()->frameGeometry().topLeft();
671
}
672

673
/*!
674
    Return the geometry of the frame relative to it's parent frame.
675
*/
676 677
QRect QWebFrame::geometry() const
{
678 679 680
    if (!d->frame->view())
        return QRect();
    return d->frame->view()->frameGeometry();
681
}
682

683 684 685 686 687 688 689 690 691 692 693 694
/*!
    \property QWebFrame::contentsSize
    \brief the size of the contents in this frame
*/
QSize QWebFrame::contentsSize() const
{
    FrameView *view = d->frame->view();
    if (!view)
        return QSize();
    return QSize(view->contentsWidth(), view->contentsHeight());
}

695 696 697 698 699 700 701 702 703 704 705 706
/*!
    Performs a hit test on the frame contents at the given position \a pos and returns the hit test result.
*/
QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const
{
    if (!d->frame->view() || !d->frame->contentRenderer())
        return QWebHitTestResult();

    HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false);
    return QWebHitTestResult(new QWebHitTestResultPrivate(result));
}

707 708 709 710 711 712 713
/*! \reimp
*/
bool QWebFrame::event(QEvent *e)
{
    return QObject::event(e);
}

714
/*!
715 716 717
    Prints the frame to the given \a printer.

    \sa render()
718 719 720
*/
void QWebFrame::print(QPrinter *printer) const
{
721 722 723
    const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi();
    const qreal zoomFactorY = printer->logicalDpiY() / qt_defaultDpi();

724 725 726
    PrintContext printContext(d->frame);
    float pageHeight = 0;

727 728 729
    QRect qprinterRect = printer->pageRect();

    IntRect pageRect(0, 0,
730 731
                     int(qprinterRect.width() / zoomFactorX),
                     int(qprinterRect.height() / zoomFactorY));
732 733

    printContext.begin(pageRect.width());
734

735
    printContext.computePageRects(pageRect, /*headerHeight*/0, /*footerHeight*/0, /*userScaleFactor*/1.0, pageHeight);
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766

    int docCopies;
    int pageCopies;
    if (printer->collateCopies() == true){
        docCopies = 1;
        pageCopies = printer->numCopies();
    } else {
        docCopies = printer->numCopies();
        pageCopies = 1;
    }

    int fromPage = printer->fromPage();
    int toPage = printer->toPage();
    bool ascending = true;

    if (fromPage == 0 && toPage == 0) {
        fromPage = 1;
        toPage = printContext.pageCount();
    }
    // paranoia check
    fromPage = qMax(1, fromPage);
    toPage = qMin(printContext.pageCount(), toPage);

    if (printer->pageOrder() == QPrinter::LastPageFirst) {
        int tmp = fromPage;
        fromPage = toPage;
        toPage = tmp;
        ascending = false;
    }

    QPainter painter(printer);
767
    painter.scale(zoomFactorX, zoomFactorY);
768 769 770 771 772 773 774 775 776 777 778
    GraphicsContext ctx(&painter);

    for (int i = 0; i < docCopies; ++i) {
        int page = fromPage;
        while (true) {
            for (int j = 0; j < pageCopies; ++j) {
                if (printer->printerState() == QPrinter::Aborted
                    || printer->printerState() == QPrinter::Error) {
                    printContext.end();
                    return;
                }
779
                printContext.spoolPage(ctx, page - 1, pageRect.width());
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
                if (j < pageCopies - 1)
                    printer->newPage();
            }

            if (page == toPage)
                break;

            if (ascending)
                ++page;
            else
                --page;

            printer->newPage();
        }

        if ( i < docCopies - 1)
            printer->newPage();
    }

    printContext.end();
}

802
/*!
803 804 805
    Evaluate JavaScript defined by \a scriptSource using this frame as context.

    \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared()
806
*/
807
QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource)
808 809
{
    KJSProxy *proxy = d->frame->scriptProxy();
810
    QVariant rc;
811
    if (proxy) {
bdash's avatar
bdash committed
812
        KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource);
813
        if (v) {
814 815
            int distance = 0;
            rc = KJS::Bindings::convertValueToQVariant(proxy->globalObject()->globalExec(), v, QMetaType::Void, &distance);
816 817 818
        }
    }
    return rc;
819 820
}

821 822
WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
{
823
    return webFrame->d->frame;
824 825 826 827 828 829
}

QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
{
    return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
}
830 831 832


/*!
833
    \fn void QWebFrame::javaScriptWindowObjectCleared()
834

835 836
    This signal is emitted whenever the global window object of the JavaScript
    environment is cleared, e.g., before starting a new load.
837

838 839 840 841
    If you intend to add QObjects to a QWebFrame using
    addToJavaScriptWindowObject(), you should add them in a slot connected
    to this signal. This ensures that your objects remain accessible when
    loading new URLs.
842 843 844
*/

/*!
845 846
    \fn void QWebFrame::provisionalLoad()
    \internal
847 848 849
*/

/*!
850
    \fn void QWebFrame::titleChanged(const QString &title)
851

852 853
    This signal is emitted whenever the title of the frame changes.
    The \a title string specifies the new title.
854

855
    \sa title()
856 857
*/

858
/*!
859
    \fn void QWebFrame::urlChanged(const QUrl &url)
860

861
    This signal is emitted when the \a url of the frame changes.
862

863
    \sa url()
864 865
*/

866
/*!
867 868 869 870
    \fn void QWebFrame::initialLayoutCompleted()

    This signal is emitted when the frame is laid out the first time.
    This is the first time you will see contents displayed on the frame.
871

872
    \note A frame can be laid out multiple times.
873
*/
874

875
/*!
876
  \fn void QWebFrame::iconChanged()
877

878 879
  This signal is emitted when the icon ("favicon") associated with the frame
  has been loaded.
880 881

  \sa icon()
882
*/
883 884 885 886

/*!
    \class QWebHitTestResult
    \since 4.4
887 888
    \brief The QWebHitTestResult class provides information about the web
    page content after a hit test.
889

890 891
    QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide
    information about the content of the web page at the specified position.
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
*/

/*!
    \internal
*/
QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv)
    : d(priv)
{
}

QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest)
    : isContentEditable(false)
    , isContentSelected(false)
{
    if (!hitTest.innerNode())
        return;
    pos = hitTest.point();
    title = hitTest.title();
    linkText = hitTest.textContent();
    linkUrl = hitTest.absoluteLinkURL();
    linkTitle = hitTest.titleDisplayString();
    alternateText = hitTest.altDisplayString();
    imageUrl = hitTest.absoluteImageURL();
    innerNonSharedNode = hitTest.innerNonSharedNode();
    WebCore::Image *img = hitTest.image();
    if (img) {
        QPixmap *pix = img->getPixmap();
        if (pix)
            pixmap = *pix;
    }
    WebCore::Frame *wframe = hitTest.targetFrame();
    if (wframe)
        linkTargetFrame = QWebFramePrivate::kit(wframe);

    isContentEditable = hitTest.isContentEditable();
    isContentSelected = hitTest.isSelected();

    if (innerNonSharedNode && innerNonSharedNode->document()
        && innerNonSharedNode->document()->frame())
        frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame());
}

/*!
    Constructs a null hit test result.
*/
QWebHitTestResult::QWebHitTestResult()
    : d(0)
{
}

/*!
    Constructs a hit test result from \a other.
*/
QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other)
    : d(0)
{
    if (other.d)
        d = new QWebHitTestResultPrivate(*other.d);
}

/*!
    Assigns the \a other hit test result to this.
*/
QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other)
{
    if (this != &other) {
        if (other.d) {
            if (!d)
                d = new QWebHitTestResultPrivate;
            *d = *other.d;
        } else {
            delete d;
            d = 0;
        }
    }
    return *this;
}

/*!
    Destructor.
*/
QWebHitTestResult::~QWebHitTestResult()
{
    delete d;
}

/*!
    Returns true if the hit test result is null; otherwise returns false.
*/
bool QWebHitTestResult::isNull() const
{
983
    return !d;
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000