webview.cpp Example File | Qt WebKit Examples 5.9

Qt 5.9 | Qt WebKit Examples | Tab Browser | webview.cpp Example File

Qt 5.9.2 Reference Documentation

# webview.cpp Example File

webkitwidgets/browser/webview.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2015 The Qt Company Ltd.
      ** Contact: http://www.qt.io/licensing/
      **
      ** This file is part of the demonstration applications of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:LGPL21$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see http://www.qt.io/terms-conditions. For further
      ** information use the contact form at http://www.qt.io/contact-us.
      **
      ** GNU Lesser General Public License Usage
      ** Alternatively, this file may be used under the terms of the GNU Lesser
      ** General Public License version 2.1 or version 3 as published by the Free
      ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
      ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
      ** following information to ensure the GNU Lesser General Public License
      ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
      ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
      **
      ** As a special exception, The Qt Company gives you certain additional
      ** rights. These rights are described in The Qt Company LGPL Exception
      ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #include "browserapplication.h"
      #include "browsermainwindow.h"
      #include "cookiejar.h"
      #include "downloadmanager.h"
      #include "networkaccessmanager.h"
      #include "tabwidget.h"
      #include "webview.h"

      #include <QtGui/QClipboard>
      #include <QtWidgets/QMenu>
      #include <QtWidgets/QMessageBox>
      #include <QtGui/QMouseEvent>

      #include <QWebHitTestResult>

      #ifndef QT_NO_UITOOLS
      #include <QtUiTools/QUiLoader>
      #endif  //QT_NO_UITOOLS

      #include <QtCore/QDebug>
      #include <QtCore/QBuffer>

      WebPage::WebPage(QObject *parent)
          : QWebPage(parent)
          , m_keyboardModifiers(Qt::NoModifier)
          , m_pressedButtons(Qt::NoButton)
          , m_openInNewTab(false)
      {
          setNetworkAccessManager(BrowserApplication::networkAccessManager());
          connect(this, SIGNAL(unsupportedContent(QNetworkReply*)),
                  this, SLOT(handleUnsupportedContent(QNetworkReply*)));
      }

      BrowserMainWindow *WebPage::mainWindow()
      {
          QObject *w = this->parent();
          while (w) {
              if (BrowserMainWindow *mw = qobject_cast<BrowserMainWindow*>(w))
                  return mw;
              w = w->parent();
          }
          return BrowserApplication::instance()->mainWindow();
      }

      bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
      {
          // ctrl open in new tab
          // ctrl-shift open in new tab and select
          // ctrl-alt open in new window
          if (type == QWebPage::NavigationTypeLinkClicked
              && (m_keyboardModifiers & Qt::ControlModifier
                  || m_pressedButtons == Qt::MidButton)) {
              bool newWindow = (m_keyboardModifiers & Qt::AltModifier);
              WebView *webView;
              if (newWindow) {
                  BrowserApplication::instance()->newMainWindow();
                  BrowserMainWindow *newMainWindow = BrowserApplication::instance()->mainWindow();
                  webView = newMainWindow->currentTab();
                  newMainWindow->raise();
                  newMainWindow->activateWindow();
                  webView->setFocus();
              } else {
                  bool selectNewTab = (m_keyboardModifiers & Qt::ShiftModifier);
                  webView = mainWindow()->tabWidget()->newTab(selectNewTab);
              }
              webView->load(request);
              m_keyboardModifiers = Qt::NoModifier;
              m_pressedButtons = Qt::NoButton;
              return false;
          }
          if (frame == mainFrame()) {
              m_loadingUrl = request.url();
              emit loadingUrl(m_loadingUrl);
          }
          return QWebPage::acceptNavigationRequest(frame, request, type);
      }

      QWebPage *WebPage::createWindow(QWebPage::WebWindowType type)
      {
          Q_UNUSED(type);
          if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)
              m_openInNewTab = true;
          if (m_openInNewTab) {
              m_openInNewTab = false;
              return mainWindow()->tabWidget()->newTab()->page();
          }
          BrowserApplication::instance()->newMainWindow();
          BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow();
          return mainWindow->currentTab()->page();
      }

      #if !defined(QT_NO_UITOOLS)
      QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
      {
          Q_UNUSED(url);
          Q_UNUSED(paramNames);
          Q_UNUSED(paramValues);
          QUiLoader loader;
          return loader.createWidget(classId, view());
      }
      #endif // !defined(QT_NO_UITOOLS)

      void WebPage::handleUnsupportedContent(QNetworkReply *reply)
      {
          QString errorString = reply->errorString();

          if (m_loadingUrl != reply->url()) {
              // sub resource of this page
              qWarning() << "Resource" << reply->url().toEncoded() << "has unknown Content-Type, will be ignored.";
              reply->deleteLater();
              return;
          }

          if (reply->error() == QNetworkReply::NoError && !reply->header(QNetworkRequest::ContentTypeHeader).isValid()) {
              errorString = "Unknown Content-Type";
          }

          QFile file(QLatin1String(":/notfound.html"));
          bool isOpened = file.open(QIODevice::ReadOnly);
          Q_ASSERT(isOpened);
          Q_UNUSED(isOpened)

          QString title = tr("Error loading page: %1").arg(reply->url().toString());
          QString html = QString(QLatin1String(file.readAll()))
                              .arg(title)
                              .arg(errorString)
                              .arg(reply->url().toString());

          QBuffer imageBuffer;
          imageBuffer.open(QBuffer::ReadWrite);
          QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, view());
          QPixmap pixmap = icon.pixmap(QSize(32,32));
          if (pixmap.save(&imageBuffer, "PNG")) {
              html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"),
                           QString(QLatin1String(imageBuffer.buffer().toBase64())));
          }

          QList<QWebFrame*> frames;
          frames.append(mainFrame());
          while (!frames.isEmpty()) {
              QWebFrame *frame = frames.takeFirst();
              if (frame->url() == reply->url()) {
                  frame->setHtml(html, reply->url());
                  return;
              }
              QList<QWebFrame *> children = frame->childFrames();
              foreach(QWebFrame *frame, children)
                  frames.append(frame);
          }
          if (m_loadingUrl == reply->url()) {
              mainFrame()->setHtml(html, reply->url());
          }
      }

      WebView::WebView(QWidget* parent)
          : QWebView(parent)
          , m_progress(0)
          , m_page(new WebPage(this))
      {
          setPage(m_page);
          connect(page(), SIGNAL(statusBarMessage(QString)),
                  SLOT(setStatusBarText(QString)));
          connect(this, SIGNAL(loadProgress(int)),
                  this, SLOT(setProgress(int)));
          connect(this, SIGNAL(loadFinished(bool)),
                  this, SLOT(loadFinished()));
          connect(page(), SIGNAL(loadingUrl(QUrl)),
                  this, SIGNAL(urlChanged(QUrl)));
          connect(page(), SIGNAL(downloadRequested(QNetworkRequest)),
                  this, SLOT(downloadRequested(QNetworkRequest)));
          page()->setForwardUnsupportedContent(true);

      }

      void WebView::contextMenuEvent(QContextMenuEvent *event)
      {
          QWebHitTestResult r = page()->mainFrame()->hitTestContent(event->pos());
          if (!r.linkUrl().isEmpty()) {
              QMenu menu(this);
              menu.addAction(pageAction(QWebPage::OpenLinkInNewWindow));
              menu.addAction(tr("Open in New Tab"), this, SLOT(openLinkInNewTab()));
              menu.addSeparator();
              menu.addAction(pageAction(QWebPage::DownloadLinkToDisk));
              // Add link to bookmarks...
              menu.addSeparator();
              menu.addAction(pageAction(QWebPage::CopyLinkToClipboard));
              if (page()->settings()->testAttribute(QWebSettings::DeveloperExtrasEnabled))
                  menu.addAction(pageAction(QWebPage::InspectElement));
              menu.exec(mapToGlobal(event->pos()));
              return;
          }
          QWebView::contextMenuEvent(event);
      }

      void WebView::wheelEvent(QWheelEvent *event)
      {
          if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
              int numDegrees = event->delta() / 8;
              int numSteps = numDegrees / 15;
              setTextSizeMultiplier(textSizeMultiplier() + numSteps * 0.1);
              event->accept();
              return;
          }
          QWebView::wheelEvent(event);
      }

      void WebView::openLinkInNewTab()
      {
          m_page->m_openInNewTab = true;
          pageAction(QWebPage::OpenLinkInNewWindow)->trigger();
      }

      void WebView::setProgress(int progress)
      {
          m_progress = progress;
      }

      void WebView::loadFinished()
      {
          if (100 != m_progress) {
              qWarning() << "Received finished signal while progress is still:" << progress()
                         << "Url:" << url();
          }
          m_progress = 0;
      }

      void WebView::loadUrl(const QUrl &url)
      {
          m_initialUrl = url;
          load(url);
      }

      QString WebView::lastStatusBarText() const
      {
          return m_statusBarText;
      }

      QUrl WebView::url() const
      {
          QUrl url = QWebView::url();
          if (!url.isEmpty())
              return url;

          return m_initialUrl;
      }

      void WebView::mousePressEvent(QMouseEvent *event)
      {
          m_page->m_pressedButtons = event->buttons();
          m_page->m_keyboardModifiers = event->modifiers();
          QWebView::mousePressEvent(event);
      }

      void WebView::mouseReleaseEvent(QMouseEvent *event)
      {
          QWebView::mouseReleaseEvent(event);
      #ifndef QT_NO_CLIPBOARD
          if (!event->isAccepted() && (m_page->m_pressedButtons & Qt::MidButton)) {
              QUrl url(QApplication::clipboard()->text(QClipboard::Selection));
              if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) {
                  setUrl(url);
              }
          }
      #endif
      }

      void WebView::setStatusBarText(const QString &string)
      {
          m_statusBarText = string;
      }

      void WebView::downloadRequested(const QNetworkRequest &request)
      {
          BrowserApplication::downloadManager()->download(request);
      }