Search code examples
qtqtwebkitqwebview

QtWebKit: How can I detect a URL changed via the HTML5 history API


We're currently using QtWebKit to build an application, part of which displays the product catalogue page of our website. On that webpage we're using the jQuery.history plugin to keep track of sorting and filtering options without users needing to reloading the page.

When jQuery.history's pushState() function is called the URL provided is pushed to the history properly, but QWebView's urlChanged() signal (which we're listening for to update back/forward buttons and the address bar) isn't fired even though the current URL has changed. I can only assume this is because no link was clicked, nor was there a page reload so Qt doesn't think it needs to do anything URL-related.

Is there any way to detect a URL change made via the HTML5 history API in QtWebKit, or am I missing something obvious?


Solution

  • There is QWebPage::saveFrameStateRequested signal:

    This signal is emitted shortly before the history of navigated pages in frame is changed, for example when navigating back in the history.

    You can use it to track history changes:

    void MainWindow::saveFrameStateRequested(QWebFrame *frame, QWebHistoryItem *item) {
        // this slot is executed before the history is changed, 
        // so we need to wait a bit:
        QTimer::singleShot(100, this, SLOT(listHistoryItems()));
    }
    
    void MainWindow::listHistoryItems() {
        for (QWebHistoryItem historyItem: view->page()->history()->items()) {
            qDebug() << "item" << historyItem.url() << historyItem.title();
        }
    }
    
    void MainWindow::finishLoading(bool) {
        // (re)connect the signal to track history change,
        // maybe there is a better place to connect this signal
        // where disconnect won't be needed
        disconnect(view->page(), SIGNAL(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)),
                this, SLOT(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)));
    
        connect(view->page(), SIGNAL(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)),
                this, SLOT(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)));
    }
    

    The modified Fancy Browser example screenshot.