Home | History | Annotate | Download | only in Api
      1 /*
      2     Copyright (C) 2008 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 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 "qwebhistory.h"
     22 #include "qwebhistory_p.h"
     23 #include "qwebframe_p.h"
     24 
     25 #include "PlatformString.h"
     26 #include "Image.h"
     27 #include "KURL.h"
     28 #include "Page.h"
     29 #include "PageGroup.h"
     30 
     31 #include <QSharedData>
     32 #include <QDebug>
     33 
     34 enum {
     35     InitialHistoryVersion = 1,
     36     DefaultHistoryVersion = InitialHistoryVersion
     37 };
     38 
     39 /*!
     40   \class QWebHistoryItem
     41   \since 4.4
     42   \brief The QWebHistoryItem class represents one item in the history of a QWebPage
     43 
     44   \inmodule QtWebKit
     45 
     46   Each QWebHistoryItem instance represents an entry in the history stack of a Web page,
     47   containing information about the page, its location, and when it was last visited.
     48 
     49   The following table shows the properties of the page held by the history item, and
     50   the functions used to access them.
     51 
     52   \table
     53   \header \o Function      \o Description
     54   \row    \o title()       \o The page title.
     55   \row    \o url()         \o The location of the page.
     56   \row    \o originalUrl() \o The URL used to access the page.
     57   \row    \o lastVisited() \o The date and time of the user's last visit to the page.
     58   \row    \o icon()        \o The icon associated with the page that was provided by the server.
     59   \row    \o userData()    \o The user specific data that was stored with the history item.
     60   \endtable
     61 
     62   \note QWebHistoryItem objects are value based, but \e{explicitly shared}. Changing
     63   a QWebHistoryItem instance by calling setUserData() will change all copies of that
     64   instance.
     65 
     66   \sa QWebHistory, QWebPage::history(), QWebHistoryInterface
     67 */
     68 
     69 /*!
     70   Constructs a history item from \a other. The new item and \a other
     71   will share their data, and modifying either this item or \a other will
     72   modify both instances.
     73 */
     74 QWebHistoryItem::QWebHistoryItem(const QWebHistoryItem &other)
     75     : d(other.d)
     76 {
     77 }
     78 
     79 /*!
     80   Assigns the \a other history item to this. This item and \a other
     81   will share their data, and modifying either this item or \a other will
     82   modify both instances.
     83 */
     84 QWebHistoryItem &QWebHistoryItem::operator=(const QWebHistoryItem &other)
     85 {
     86     d = other.d;
     87     return *this;
     88 }
     89 
     90 /*!
     91   Destroys the history item.
     92 */
     93 QWebHistoryItem::~QWebHistoryItem()
     94 {
     95 }
     96 
     97 /*!
     98  Returns the original URL associated with the history item.
     99 
    100  \sa url()
    101 */
    102 QUrl QWebHistoryItem::originalUrl() const
    103 {
    104     if (d->item)
    105         return QUrl(d->item->originalURL().string());
    106     return QUrl();
    107 }
    108 
    109 
    110 /*!
    111  Returns the URL associated with the history item.
    112 
    113  \sa originalUrl(), title(), lastVisited()
    114 */
    115 QUrl QWebHistoryItem::url() const
    116 {
    117     if (d->item)
    118         return QUrl(d->item->url().string());
    119     return QUrl();
    120 }
    121 
    122 
    123 /*!
    124  Returns the title of the page associated with the history item.
    125 
    126  \sa icon(), url(), lastVisited()
    127 */
    128 QString QWebHistoryItem::title() const
    129 {
    130     if (d->item)
    131         return d->item->title();
    132     return QString();
    133 }
    134 
    135 
    136 /*!
    137  Returns the date and time that the page associated with the item was last visited.
    138 
    139  \sa title(), icon(), url()
    140 */
    141 QDateTime QWebHistoryItem::lastVisited() const
    142 {
    143     //FIXME : this will be wrong unless we correctly set lastVisitedTime ourselves
    144     if (d->item)
    145         return QDateTime::fromTime_t((uint)d->item->lastVisitedTime());
    146     return QDateTime();
    147 }
    148 
    149 
    150 /*!
    151  Returns the icon associated with the history item.
    152 
    153  \sa title(), url(), lastVisited()
    154 */
    155 QIcon QWebHistoryItem::icon() const
    156 {
    157     if (d->item)
    158         return *d->item->icon()->nativeImageForCurrentFrame();
    159     return QIcon();
    160 }
    161 
    162 /*!
    163   \since 4.5
    164   Returns the user specific data that was stored with the history item.
    165 
    166   \sa setUserData()
    167 */
    168 QVariant QWebHistoryItem::userData() const
    169 {
    170     if (d->item)
    171         return d->item->userData();
    172     return QVariant();
    173 }
    174 
    175 /*!
    176   \since 4.5
    177 
    178  Stores user specific data \a userData with the history item.
    179 
    180  \note All copies of this item will be modified.
    181 
    182  \sa userData()
    183 */
    184 void QWebHistoryItem::setUserData(const QVariant& userData)
    185 {
    186     if (d->item)
    187         d->item->setUserData(userData);
    188 }
    189 
    190 /*!*
    191   \internal
    192 */
    193 QWebHistoryItem::QWebHistoryItem(QWebHistoryItemPrivate *priv)
    194 {
    195     d = priv;
    196 }
    197 
    198 /*!
    199     \since 4.5
    200     Returns whether this is a valid history item.
    201 */
    202 bool QWebHistoryItem::isValid() const
    203 {
    204     return d->item;
    205 }
    206 
    207 /*!
    208   \class QWebHistory
    209   \since 4.4
    210   \brief The QWebHistory class represents the history of a QWebPage
    211 
    212   \inmodule QtWebKit
    213 
    214   Each QWebPage instance contains a history of visited pages that can be accessed
    215   by QWebPage::history(). QWebHistory represents this history and makes it possible
    216   to navigate it.
    217 
    218   The history uses the concept of a \e{current item}, dividing the pages visited
    219   into those that can be visited by navigating \e back and \e forward using the
    220   back() and forward() functions. The current item can be obtained by calling
    221   currentItem(), and an arbitrary item in the history can be made the current
    222   item by passing it to goToItem().
    223 
    224   A list of items describing the pages that can be visited by going back can be
    225   obtained by calling the backItems() function; similarly, items describing the
    226   pages ahead of the current page can be obtained with the forwardItems() function.
    227   The total list of items is obtained with the items() function.
    228 
    229   Just as with containers, functions are available to examine the history in terms
    230   of a list. Arbitrary items in the history can be obtained with itemAt(), the total
    231   number of items is given by count(), and the history can be cleared with the
    232   clear() function.
    233 
    234   QWebHistory's state can be saved to a QDataStream using the >> operator and loaded
    235   by using the << operator.
    236 
    237   \sa QWebHistoryItem, QWebHistoryInterface, QWebPage
    238 */
    239 
    240 
    241 QWebHistory::QWebHistory()
    242     : d(0)
    243 {
    244 }
    245 
    246 QWebHistory::~QWebHistory()
    247 {
    248     delete d;
    249 }
    250 
    251 /*!
    252   Clears the history.
    253 
    254   \sa count(), items()
    255 */
    256 void QWebHistory::clear()
    257 {
    258     //shortcut to private BackForwardList
    259     WebCore::BackForwardList* lst = d->lst;
    260 
    261     //clear visited links
    262     WebCore::Page* page = lst->page();
    263     if (page && page->groupPtr())
    264         page->groupPtr()->removeVisitedLinks();
    265 
    266     //if count() == 0 then just return
    267     if (!lst->entries().size())
    268         return;
    269 
    270     RefPtr<WebCore::HistoryItem> current = lst->currentItem();
    271     int capacity = lst->capacity();
    272     lst->setCapacity(0);
    273 
    274     lst->setCapacity(capacity);   //revert capacity
    275     lst->addItem(current.get());  //insert old current item
    276     lst->goToItem(current.get()); //and set it as current again
    277 
    278     d->page()->updateNavigationActions();
    279 }
    280 
    281 /*!
    282   Returns a list of all items currently in the history.
    283 
    284   \sa count(), clear()
    285 */
    286 QList<QWebHistoryItem> QWebHistory::items() const
    287 {
    288     const WebCore::HistoryItemVector &items = d->lst->entries();
    289 
    290     QList<QWebHistoryItem> ret;
    291     for (unsigned i = 0; i < items.size(); ++i) {
    292         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    293         ret.append(QWebHistoryItem(priv));
    294     }
    295     return ret;
    296 }
    297 
    298 /*!
    299   Returns the list of items in the backwards history list.
    300   At most \a maxItems entries are returned.
    301 
    302   \sa forwardItems()
    303 */
    304 QList<QWebHistoryItem> QWebHistory::backItems(int maxItems) const
    305 {
    306     WebCore::HistoryItemVector items(maxItems);
    307     d->lst->backListWithLimit(maxItems, items);
    308 
    309     QList<QWebHistoryItem> ret;
    310     for (unsigned i = 0; i < items.size(); ++i) {
    311         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    312         ret.append(QWebHistoryItem(priv));
    313     }
    314     return ret;
    315 }
    316 
    317 /*!
    318   Returns the list of items in the forward history list.
    319   At most \a maxItems entries are returned.
    320 
    321   \sa backItems()
    322 */
    323 QList<QWebHistoryItem> QWebHistory::forwardItems(int maxItems) const
    324 {
    325     WebCore::HistoryItemVector items(maxItems);
    326     d->lst->forwardListWithLimit(maxItems, items);
    327 
    328     QList<QWebHistoryItem> ret;
    329     for (unsigned i = 0; i < items.size(); ++i) {
    330         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    331         ret.append(QWebHistoryItem(priv));
    332     }
    333     return ret;
    334 }
    335 
    336 /*!
    337   Returns true if there is an item preceding the current item in the history;
    338   otherwise returns false.
    339 
    340   \sa canGoForward()
    341 */
    342 bool QWebHistory::canGoBack() const
    343 {
    344     return d->lst->backListCount() > 0;
    345 }
    346 
    347 /*!
    348   Returns true if we have an item to go forward to; otherwise returns false.
    349 
    350   \sa canGoBack()
    351 */
    352 bool QWebHistory::canGoForward() const
    353 {
    354     return d->lst->forwardListCount() > 0;
    355 }
    356 
    357 /*!
    358   Set the current item to be the previous item in the history and goes to the
    359   corresponding page; i.e., goes back one history item.
    360 
    361   \sa forward(), goToItem()
    362 */
    363 void QWebHistory::back()
    364 {
    365     if (canGoBack()) {
    366         d->lst->goBack();
    367         WebCore::Page* page = d->lst->page();
    368         page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward);
    369     }
    370 }
    371 
    372 /*!
    373   Sets the current item to be the next item in the history and goes to the
    374   corresponding page; i.e., goes forward one history item.
    375 
    376   \sa back(), goToItem()
    377 */
    378 void QWebHistory::forward()
    379 {
    380     if (canGoForward()) {
    381         d->lst->goForward();
    382         WebCore::Page* page = d->lst->page();
    383         page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward);
    384     }
    385 }
    386 
    387 /*!
    388   Sets the current item to be the specified \a item in the history and goes to the page.
    389 
    390   \sa back(), forward()
    391 */
    392 void QWebHistory::goToItem(const QWebHistoryItem &item)
    393 {
    394     d->lst->goToItem(item.d->item);
    395     WebCore::Page* page = d->lst->page();
    396     page->goToItem(currentItem().d->item, WebCore::FrameLoadTypeIndexedBackForward);
    397 }
    398 
    399 /*!
    400   Returns the item before the current item in the history.
    401 */
    402 QWebHistoryItem QWebHistory::backItem() const
    403 {
    404     WebCore::HistoryItem *i = d->lst->backItem();
    405     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    406     return QWebHistoryItem(priv);
    407 }
    408 
    409 /*!
    410   Returns the current item in the history.
    411 */
    412 QWebHistoryItem QWebHistory::currentItem() const
    413 {
    414     WebCore::HistoryItem *i = d->lst->currentItem();
    415     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    416     return QWebHistoryItem(priv);
    417 }
    418 
    419 /*!
    420   Returns the item after the current item in the history.
    421 */
    422 QWebHistoryItem QWebHistory::forwardItem() const
    423 {
    424     WebCore::HistoryItem *i = d->lst->forwardItem();
    425     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    426     return QWebHistoryItem(priv);
    427 }
    428 
    429 /*!
    430   \since 4.5
    431   Returns the index of the current item in history.
    432 */
    433 int QWebHistory::currentItemIndex() const
    434 {
    435     return d->lst->backListCount();
    436 }
    437 
    438 /*!
    439   Returns the item at index \a i in the history.
    440 */
    441 QWebHistoryItem QWebHistory::itemAt(int i) const
    442 {
    443     QWebHistoryItemPrivate *priv;
    444     if (i < 0 || i >= count())
    445         priv = new QWebHistoryItemPrivate(0);
    446     else {
    447         WebCore::HistoryItem *item = d->lst->entries()[i].get();
    448         priv = new QWebHistoryItemPrivate(item);
    449     }
    450     return QWebHistoryItem(priv);
    451 }
    452 
    453 /*!
    454     Returns the total number of items in the history.
    455 */
    456 int QWebHistory::count() const
    457 {
    458     return d->lst->entries().size();
    459 }
    460 
    461 /*!
    462   \since 4.5
    463   Returns the maximum number of items in the history.
    464 
    465   \sa setMaximumItemCount()
    466 */
    467 int QWebHistory::maximumItemCount() const
    468 {
    469     return d->lst->capacity();
    470 }
    471 
    472 /*!
    473   \since 4.5
    474   Sets the maximum number of items in the history to \a count.
    475 
    476   \sa maximumItemCount()
    477 */
    478 void QWebHistory::setMaximumItemCount(int count)
    479 {
    480     d->lst->setCapacity(count);
    481 }
    482 
    483 /*!
    484   \since 4.6
    485   \fn QDataStream& operator<<(QDataStream& stream, const QWebHistory& history)
    486   \relates QWebHistory
    487 
    488   \brief The operator<< function streams a history into a data stream.
    489 
    490   It saves the \a history into the specified \a stream.
    491 */
    492 
    493 QDataStream& operator<<(QDataStream& target, const QWebHistory& history)
    494 {
    495     QWebHistoryPrivate* d = history.d;
    496 
    497     int version = DefaultHistoryVersion;
    498 
    499     target << version;
    500     target << history.count() << history.currentItemIndex();
    501 
    502     const WebCore::HistoryItemVector &items = d->lst->entries();
    503     for (unsigned i = 0; i < items.size(); i++)
    504         items[i].get()->saveState(target, version);
    505 
    506     return target;
    507 }
    508 
    509 /*!
    510   \fn QDataStream& operator>>(QDataStream& stream, QWebHistory& history)
    511   \relates QWebHistory
    512   \since 4.6
    513 
    514   \brief The operator>> function loads a history from a data stream.
    515 
    516   Loads a QWebHistory from the specified \a stream into the given \a history.
    517 */
    518 
    519 QDataStream& operator>>(QDataStream& source, QWebHistory& history)
    520 {
    521     QWebHistoryPrivate* d = history.d;
    522 
    523     int version;
    524 
    525     source >> version;
    526 
    527     if (version == 1) {
    528         int count;
    529         int currentIndex;
    530         source >> count >> currentIndex;
    531 
    532         history.clear();
    533         // only if there are elements
    534         if (count) {
    535             // after clear() is new clear HistoryItem (at the end we had to remove it)
    536             WebCore::HistoryItem* nullItem = d->lst->currentItem();
    537             for (int i = 0; i < count; i++) {
    538                 WTF::PassRefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
    539                 item->restoreState(source, version);
    540                 d->lst->addItem(item);
    541             }
    542             d->lst->removeItem(nullItem);
    543             history.goToItem(history.itemAt(currentIndex));
    544         }
    545     }
    546 
    547     d->page()->updateNavigationActions();
    548 
    549     return source;
    550 }
    551 
    552 QWebPagePrivate* QWebHistoryPrivate::page()
    553 {
    554     return QWebFramePrivate::kit(lst->page()->mainFrame())->page()->handle();
    555 }
    556