Qt 5.6 | Qt WebEngine | WebEngine Widgets Simple Browser Example | webview.cpp Example File

Qt 5.6.3 Reference Documentation

# webview.cpp Example File

webenginewidgets/simplebrowser/webview.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: http://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** You may use this file under the terms of the BSD license as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #include "browser.h"
      #include "browserwindow.h"
      #include "tabwidget.h"
      #include "webpage.h"
      #include "webpopupwindow.h"
      #include "webview.h"
      #include <QContextMenuEvent>
      #include <QDebug>
      #include <QMenu>
      #include <QMessageBox>
      #include <QNetworkReply>
      #include <QTimer>

      WebView::WebView(QWidget *parent)
          : QWebEngineView(parent)
          , m_loadProgress(0)
      {
          connect(this, &QWebEngineView::loadProgress, [this](int progress) {
              m_loadProgress = progress;
          });
          connect(this, &QWebEngineView::loadFinished, [this](bool success) {
              if (!success) {
                  qWarning() << "Could not load page: " << url();
                  m_loadProgress = 0;
              }
          });
          connect(this, &QWebEngineView::iconUrlChanged, this, &WebView::handleIconUrlChanged);
          connect(this, &QWebEngineView::renderProcessTerminated,
                  [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) {
              QString status;
              switch (termStatus) {
              case QWebEnginePage::NormalTerminationStatus:
                  status = tr("Render process normal exit");
                  break;
              case QWebEnginePage::AbnormalTerminationStatus:
                  status = tr("Render process abnormal exit");
                  break;
              case QWebEnginePage::CrashedTerminationStatus:
                  status = tr("Render process crashed");
                  break;
              case QWebEnginePage::KilledTerminationStatus:
                  status = tr("Render process killed");
                  break;
              }
              QMessageBox::critical(window(), status, tr("Render process exited with code: %1").arg(statusCode));
              QTimer::singleShot(0, [this] { reload(); });
          });
      }

      void WebView::setPage(WebPage *page)
      {
          createWebActionTrigger(page,QWebEnginePage::Forward);
          createWebActionTrigger(page,QWebEnginePage::Back);
          createWebActionTrigger(page,QWebEnginePage::Reload);
          createWebActionTrigger(page,QWebEnginePage::Stop);
          QWebEngineView::setPage(page);
      }

      QIcon WebView::icon() const
      {
          if (!m_icon.isNull())
              return m_icon;
          return QIcon(QLatin1String(":defaulticon.png"));
      }

      int WebView::loadProgress() const
      {
          return m_loadProgress;
      }

      void WebView::createWebActionTrigger(QWebEnginePage *page, QWebEnginePage::WebAction webAction)
      {
          QAction *action = page->action(webAction);
          connect(action, &QAction::changed, [this, action, webAction]{
              emit webActionEnabledChanged(webAction, action->isEnabled());
          });
      }

      bool WebView::isWebActionEnabled(QWebEnginePage::WebAction webAction) const
      {
          return page()->action(webAction)->isEnabled();
      }

      QNetworkAccessManager &WebView::networkAccessManager()
      {
          static QNetworkAccessManager networkAccessManager;
          return networkAccessManager;
      }

      QWebEngineView *WebView::createWindow(QWebEnginePage::WebWindowType type)
      {
          switch (type) {
          case QWebEnginePage::WebBrowserTab: {
              BrowserWindow *mainWindow = qobject_cast<BrowserWindow*>(window());
              return mainWindow->tabWidget()->createTab();
          }
          case QWebEnginePage::WebBrowserWindow: {
              BrowserWindow *mainWindow = new BrowserWindow();
              Browser::instance().addWindow(mainWindow);
              return mainWindow->currentTab();
          }
          case QWebEnginePage::WebDialog: {
              WebPopupWindow *popup = new WebPopupWindow(page()->profile());
              return popup->view();
          }
          }
          return nullptr;
      }

      void WebView::contextMenuEvent(QContextMenuEvent *event)
      {
          QMenu *menu = page()->createStandardContextMenu();
          const QList<QAction*> actions = menu->actions();
          auto it = std::find(actions.cbegin(), actions.cend(), page()->action(QWebEnginePage::OpenLinkInThisWindow));
          if (it != actions.cend()) {
              (*it)->setText(tr("Open Link in This Tab"));
              ++it;
              QAction *before(it == actions.cend() ? nullptr : *it);
              menu->insertAction(before, page()->action(QWebEnginePage::OpenLinkInNewWindow));
              menu->insertAction(before, page()->action(QWebEnginePage::OpenLinkInNewTab));
          }
          connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
          menu->popup(event->globalPos());
      }

      void WebView::handleIconUrlChanged(const QUrl &url)
      {
          QNetworkRequest iconRequest(url);
      #ifndef QT_NO_OPENSSL
          QSslConfiguration conf = iconRequest.sslConfiguration();
          conf.setPeerVerifyMode(QSslSocket::VerifyNone);
          iconRequest.setSslConfiguration(conf);
      #endif
          QNetworkReply *iconReply = networkAccessManager().get(iconRequest);
          iconReply->setParent(this);
          connect(iconReply, &QNetworkReply::finished, this, &WebView::handleIconLoaded);
      }

      void WebView::handleIconLoaded()
      {
          QNetworkReply *iconReply = qobject_cast<QNetworkReply*>(sender());
          if (iconReply && iconReply->error() == QNetworkReply::NoError) {
              QByteArray data = iconReply->readAll();
              QPixmap pixmap;
              pixmap.loadFromData(data);
              m_icon.addPixmap(pixmap);
              iconReply->deleteLater();
          } else {
              m_icon = QIcon(QStringLiteral(":defaulticon.png"));
          }
          emit iconChanged(m_icon);
      }