Fix focus chain handling and cycling through focusable objects (links) using tab...
[WebKit-https.git] / WebKit / qt / Api / qwebview.cpp
1 /*
2     Copyright (C) 2007 Trolltech ASA
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 library 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 library; 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 #include "config.h"
21 #include "qwebview.h"
22 #include "qwebframe.h"
23 #include "qevent.h"
24 #include "qpainter.h"
25
26 class QWebViewPrivate
27 {
28 public:
29     QWebPage *page;
30 };
31
32 /*!
33     \class QWebView
34     \since 4.4
35     \brief The QWebView class provides a widget that is used to view and edit web documents.
36
37     QWebView is the main widget component of the QtWebKit web browsing module.
38 */
39
40 /*!
41     Constructs an empty QWebView with parent \a parent.
42 */
43 QWebView::QWebView(QWidget *parent)
44     : QWidget(parent)
45 {
46     d = new QWebViewPrivate;
47     d->page = 0;
48
49     QPalette pal = palette();
50     pal.setBrush(QPalette::Background, Qt::white);
51
52     setAttribute(Qt::WA_OpaquePaintEvent);
53
54     setPalette(pal);
55     setAcceptDrops(true);
56
57     setMouseTracking(true);
58     setFocusPolicy(Qt::WheelFocus);
59 }
60
61 /*!
62     Destructor.
63 */
64 QWebView::~QWebView()
65 {
66     if (d->page && d->page->parent() == this)
67         delete d->page;
68     delete d;
69 }
70
71 /*!
72     Returns a pointer to the underlying web page.
73
74     \sa setPage()
75 */
76 QWebPage *QWebView::page() const
77 {
78     if (!d->page) {
79         QWebView *that = const_cast<QWebView *>(this);
80         that->setPage(new QWebPage(that));
81     }
82     return d->page;
83 }
84
85 /*!
86     Makes \a page the new web page of the web view.
87
88     The parent QObject of the provided page remains the owner
89     of the object. If the current document is a child of the web
90     view, then it is deleted.
91
92     \sa page()
93 */
94 void QWebView::setPage(QWebPage *page)
95 {
96     if (d->page == page)
97         return;
98     if (d->page) {
99         if (d->page->parent() == this) {
100             delete d->page;
101         } else {
102             d->page->disconnect(this);
103         }
104     }
105     d->page = page;
106     if (d->page) {
107         d->page->setView(this);
108         // #### connect signals
109         QWebFrame *mainFrame = d->page->mainFrame();
110         connect(mainFrame, SIGNAL(loadStarted()),
111                 this, SIGNAL(loadStarted()));
112         connect(mainFrame, SIGNAL(loadFinished()),
113                 this, SIGNAL(loadFinished()));
114         connect(mainFrame, SIGNAL(titleChanged(const QString&)),
115                 this, SIGNAL(titleChanged(const QString&)));
116         connect(mainFrame, SIGNAL(iconLoaded()),
117                 this, SIGNAL(iconLoaded()));
118         connect(mainFrame, SIGNAL(urlChanged(const QUrl &)),
119                 this, SIGNAL(urlChanged(const QUrl &)));
120
121         connect(d->page, SIGNAL(loadProgressChanged(int)),
122                 this, SIGNAL(loadProgressChanged(int)));
123         connect(d->page, SIGNAL(statusBarTextChanged(const QString &)),
124                 this, SIGNAL(statusBarTextChanged(const QString &)));
125     }
126     update();
127 }
128
129 /*!
130     Downloads the specified \a url and displays it.
131 */
132 void QWebView::load(const QUrl &url)
133 {
134     page()->mainFrame()->load(url);
135 }
136
137 #if QT_VERSION < 0x040400
138 void QWebView::load(const QWebNetworkRequest &request)
139 #else
140 void QWebView::load(const QNetworkRequest &request,
141                     QNetworkAccessManager::Operation operation,
142                     const QByteArray &body)
143 #endif
144 {
145     page()->mainFrame()->load(request
146 #if QT_VERSION >= 0x040400
147                               , operation, body
148 #endif
149                              );
150 }
151
152 /*!
153     Sets the content of the web view to the specified \a html.
154
155     External objects referenced in the HTML document are located relative to \a baseUrl.
156 */
157 void QWebView::setHtml(const QString &html, const QUrl &baseUrl)
158 {
159     page()->mainFrame()->setHtml(html, baseUrl);
160 }
161
162 /*!
163     Sets the content of the web view to the specified \a html.
164
165     External objects referenced in the HTML document are located relative to \a baseUrl.
166 */
167 void QWebView::setHtml(const QByteArray &html, const QUrl &baseUrl)
168 {
169     page()->mainFrame()->setHtml(html, baseUrl);
170 }
171
172 /*!
173     Sets the content of the web view to the specified content \a data. If the \a mimeType argument
174     is empty it is assumed that the content is HTML.
175
176     External objects referenced in the HTML document are located relative to \a baseUrl.
177 */
178 void QWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
179 {
180     page()->mainFrame()->setContent(data, mimeType, baseUrl);
181 }
182
183 /*!
184     Returns a pointer to the view's history of navigated web pages.
185
186     It is equivalent to
187
188     \code
189     view->page()->history();
190     \endcode
191 */
192 QWebHistory *QWebView::history() const
193 {
194     return page()->history();
195 }
196
197 /*!
198     Returns a pointer to the view/page specific settings object.
199
200     It is equivalent to
201
202     \code
203     view->page()->settings();
204     \endcode
205 */
206 QWebSettings *QWebView::settings() const
207 {
208     return page()->settings();
209 }
210
211 /*!
212   \property QWebView::title
213   \brief the title of the web page currently viewed.
214 */
215 QString QWebView::title() const
216 {
217     if (d->page)
218         return d->page->mainFrame()->title();
219     return QString();
220 }
221
222 /*!
223     \property QWebView::url
224     \brief the url of the web page currently viewed.
225 */
226 QUrl QWebView::url() const
227 {
228     if (d->page)
229         return d->page->mainFrame()->url();
230     return QUrl();
231 }
232
233 /*!
234     \property QWebView::icon
235     \brief the icon associated with the web page currently viewed.
236 */
237 QPixmap QWebView::icon() const
238 {
239     if (d->page)
240         return d->page->mainFrame()->icon();
241     return QPixmap();
242 }
243
244 /*!
245     \property QWebView::selectedText
246     \brief the text currently selected.
247 */
248 QString QWebView::selectedText() const
249 {
250     if (d->page)
251         return d->page->selectedText();
252     return QString();
253 }
254
255 /*!
256     Returns a pointer to a QAction that encapsulates the specified web action \a action.
257 */
258 QAction *QWebView::action(QWebPage::WebAction action) const
259 {
260     return page()->action(action);
261 }
262
263 /*!
264     Triggers the specified \a action. If it is a checkable action the specified \a checked state is assumed.
265
266     The following example triggers the copy action and therefore copies any selected text to the clipboard.
267
268     \code
269     view->triggerAction(QWebPage::Copy);
270     \endcode
271 */
272 void QWebView::triggerAction(QWebPage::WebAction action, bool checked)
273 {
274     page()->triggerAction(action, checked);
275 }
276
277 /*!
278     \property QWebView::modified
279     \brief Indicates whether the document was modified by the user or not.
280
281     Parts of HTML documents can be editable for example through the \c{contenteditable} attribute on
282     HTML elements.
283 */
284 bool QWebView::isModified() const
285 {
286     if (d->page)
287         return d->page->isModified();
288     return false;
289 }
290
291 Qt::TextInteractionFlags QWebView::textInteractionFlags() const
292 {
293     // ### FIXME (add to page)
294     return Qt::TextInteractionFlags();
295 }
296
297 /*!
298     \property QWebView::textInteractionFlags
299
300     Specifies how the view should interact with user input.
301 */
302
303 void QWebView::setTextInteractionFlags(Qt::TextInteractionFlags flags)
304 {
305     Q_UNUSED(flags)
306     // ### FIXME (add to page)
307 }
308
309 /*!
310     \reimp
311 */
312 QSize QWebView::sizeHint() const
313 {
314     return QSize(800, 600); // ####...
315 }
316
317 /*!
318     Convenience slot that stops loading the document.
319
320     It is equivalent to
321
322     \code
323     view->page()->triggerAction(QWebPage::Stop);
324     \endcode
325 */
326 void QWebView::stop()
327 {
328     if (d->page)
329         d->page->triggerAction(QWebPage::Stop);
330 }
331
332 /*!
333     Convenience slot that loads the previous document in the list of
334     documents built by navigating links. Does nothing if there is no
335     previous document.
336
337     It is equivalent to
338
339     \code
340     view->page()->triggerAction(QWebPage::GoBack);
341     \endcode
342 */
343 void QWebView::backward()
344 {
345     if (d->page)
346         d->page->triggerAction(QWebPage::GoBack);
347 }
348
349 /*!
350     Convenience slot that loads the next document in the list of
351     documents built by navigating links. Does nothing if there is no
352     next document.
353
354     It is equivalent to
355
356     \code
357     view->page()->triggerAction(QWebPage::GoForward);
358     \endcode
359 */
360 void QWebView::forward()
361 {
362     if (d->page)
363         d->page->triggerAction(QWebPage::GoForward);
364 }
365
366 /*!
367     Reloads the current document.
368 */
369 void QWebView::reload()
370 {
371     if (d->page)
372         d->page->triggerAction(QWebPage::Reload);
373 }
374
375 /*! \reimp
376 */
377 void QWebView::resizeEvent(QResizeEvent *e)
378 {
379     if (d->page)
380         d->page->setViewportSize(e->size());
381 }
382
383 /*! \reimp
384 */
385 void QWebView::paintEvent(QPaintEvent *ev)
386 {
387     if (!d->page)
388         return;
389 #ifdef QWEBKIT_TIME_RENDERING
390     QTime time;
391     time.start();
392 #endif
393
394     QWebFrame *frame = d->page->mainFrame();
395     QPainter p(this);
396
397     frame->render(&p, ev->region());
398
399 #ifdef    QWEBKIT_TIME_RENDERING
400     int elapsed = time.elapsed();
401     qDebug()<<"paint event on "<<ev->region()<<", took to render =  "<<elapsed;
402 #endif
403 }
404
405 /*!
406     This function is called whenever WebKit wants to create a new window, for example as a result of
407     a JavaScript request to open a document in a new window.
408 */
409 QWebView *QWebView::createWindow()
410 {
411     return 0;
412 }
413
414 /*! \reimp
415 */
416 void QWebView::mouseMoveEvent(QMouseEvent* ev)
417 {
418     if (d->page)
419         d->page->event(ev);
420 }
421
422 /*! \reimp
423 */
424 void QWebView::mousePressEvent(QMouseEvent* ev)
425 {
426     if (d->page)
427         d->page->event(ev);
428 }
429
430 /*! \reimp
431 */
432 void QWebView::mouseDoubleClickEvent(QMouseEvent* ev)
433 {
434     if (d->page)
435         d->page->event(ev);
436 }
437
438 /*! \reimp
439 */
440 void QWebView::mouseReleaseEvent(QMouseEvent* ev)
441 {
442     if (d->page)
443         d->page->event(ev);
444 }
445
446 /*! \reimp
447 */
448 void QWebView::contextMenuEvent(QContextMenuEvent* ev)
449 {
450     if (d->page)
451         d->page->event(ev);
452 }
453
454 /*! \reimp
455 */
456 void QWebView::wheelEvent(QWheelEvent* ev)
457 {
458     if (d->page)
459         d->page->event(ev);
460
461     if (!ev->isAccepted())
462         return QWidget::wheelEvent(ev);
463 }
464
465 /*! \reimp
466 */
467 void QWebView::keyPressEvent(QKeyEvent* ev)
468 {
469     if (d->page)
470         d->page->event(ev);
471     if (!ev->isAccepted())
472         QWidget::keyPressEvent(ev);
473 }
474
475 /*! \reimp
476 */
477 void QWebView::keyReleaseEvent(QKeyEvent* ev)
478 {
479     if (d->page)
480         d->page->event(ev);
481     if (!ev->isAccepted())
482         QWidget::keyReleaseEvent(ev);
483 }
484
485 /*! \reimp
486 */
487 void QWebView::focusInEvent(QFocusEvent* ev)
488 {
489     if (d->page)
490         d->page->event(ev);
491     QWidget::focusInEvent(ev);
492 }
493
494 /*! \reimp
495 */
496 void QWebView::focusOutEvent(QFocusEvent* ev)
497 {
498     QWidget::focusOutEvent(ev);
499     if (d->page)
500         d->page->event(ev);
501 }
502
503 /*! \reimp
504 */
505 void QWebView::dragEnterEvent(QDragEnterEvent* ev)
506 {
507 #ifndef QT_NO_DRAGANDDROP
508     if (d->page)
509         d->page->event(ev);
510 #endif
511 }
512
513 /*! \reimp
514 */
515 void QWebView::dragLeaveEvent(QDragLeaveEvent* ev)
516 {
517 #ifndef QT_NO_DRAGANDDROP
518     if (d->page)
519         d->page->event(ev);
520 #endif
521 }
522
523 /*! \reimp
524 */
525 void QWebView::dragMoveEvent(QDragMoveEvent* ev)
526 {
527 #ifndef QT_NO_DRAGANDDROP
528     if (d->page)
529         d->page->event(ev);
530 #endif
531 }
532
533 /*! \reimp
534 */
535 void QWebView::dropEvent(QDropEvent* ev)
536 {
537 #ifndef QT_NO_DRAGANDDROP
538     if (d->page)
539         d->page->event(ev);
540 #endif
541 }
542
543 /*! \reimp
544 */
545 bool QWebView::focusNextPrevChild(bool next)
546 {
547     if (d->page && d->page->focusNextPrevChild(next))
548         return true;
549     return QWidget::focusNextPrevChild(next);
550 }
551
552 /*!
553   \fn void QWebView::titleChanged(const QString &title)
554
555   This signal is emitted whenever the \a title of the main frame changes.
556
557   \sa title()
558 */
559
560 /*!
561   \fn void QWebView::urlChanged(const QUrl &url)
562
563   This signal is emitted whenever the \a url of the main frame changes.
564
565   \sa url()
566 */
567
568 /*!
569     \fn void QWebView::statusBarTextChanged(const QString& text)
570
571     This signal is emitted when the statusbar \a text is changed by the page.
572 */
573
574 /*!
575     \fn void QWebView::iconLoaded()
576
577     This signal is emitted whenever the icon of the page is loaded or changes.
578 */
579
580 /*!
581     \fn void QWebView::loadStarted()
582
583     This signal is emitted when a new load of the frame is started.
584 */
585
586 /*!
587     \fn void QWebView::loadFinished()
588
589     This signal is emitted when a load of the frame is finished.
590 */
591
592 /*!
593     \fn void QWebView::selectionChanged()
594
595     This signal is emitted whenever the selection changes.
596 */
597
598 /*!
599     \fn void QWebView::loadProgressChanged(int progress)
600
601     This signal is emitted when the global progress status changes.
602     The current value is provided by \a progress in percent.
603     It accumulates changes from all the child frames.
604 */
605