Browse Source

add WebKit support

Sonnix 6 years ago
parent
commit
3a3ad1ef84
15 changed files with 610 additions and 26 deletions
  1. 15 0
      Qqsp.pro
  2. 3 0
      callbacks_gui.cpp
  3. 35 11
      mainwindow.cpp
  4. 5 2
      mainwindow.h
  5. 71 0
      qspnetworkaccessmanager.cpp
  6. 39 0
      qspnetworkaccessmanager.h
  7. 101 0
      qspreply.cpp
  8. 35 0
      qspreply.h
  9. 5 5
      qsptextbox.cpp
  10. 4 4
      qsptextbox.h
  11. 8 2
      qspwebbox.cpp
  12. 6 0
      qspwebbox.h
  13. 215 0
      qspwebbox_webkit.cpp
  14. 64 0
      qspwebbox_webkit.h
  15. 4 2
      qspwebengineurlschemehandler.cpp

+ 15 - 0
Qqsp.pro

@@ -148,6 +148,7 @@ CONFIG += enable-webbox
 
 enable-webbox {
   DEFINES += _WEBBOX
+  DEFINES += _WEBBOX_COMMON
   QT += webengine webenginewidgets
   SOURCES += qspwebbox.cpp \
     qspwebengineurlrequestinterceptor.cpp \
@@ -159,6 +160,20 @@ enable-webbox {
     qspexecwebengineurlschemehandler.h
 }
 
+#CONFIG += enable-webbox-webkit
+
+enable-webbox-webkit {
+  DEFINES += _WEBBOX_WEBKIT
+  DEFINES += _WEBBOX_COMMON
+  QT += webkitwidgets
+  SOURCES += qspwebbox_webkit.cpp \
+    qspnetworkaccessmanager.cpp \
+    qspreply.cpp
+  HEADERS += qspwebbox_webkit.h \
+    qspnetworkaccessmanager.h \
+    qspreply.h
+}
+
 unix:!macx {
     CONFIG += disable-nativedialog
 }

+ 3 - 0
callbacks_gui.cpp

@@ -16,6 +16,9 @@
 #ifdef _WEBBOX
 #include "qspwebbox.h"
 #endif
+#ifdef _WEBBOX_WEBKIT
+#include "qspwebbox_webkit.h"
+#endif
 
 QString QSPCallBacks::m_gamePath;
 MainWindow *QSPCallBacks::m_frame;

+ 35 - 11
mainwindow.cpp

@@ -394,7 +394,7 @@ void MainWindow::SetOverallVolume(float new_volume)
 void MainWindow::SetDisableVideo(bool isDisableVideo)
 {
     disableVideo = isDisableVideo;
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     _mainDescTextBox->SetDisableVideo(disableVideo);
     _descTextBox->SetDisableVideo(disableVideo);
 #endif
@@ -403,7 +403,7 @@ void MainWindow::SetDisableVideo(bool isDisableVideo)
 void MainWindow::SetVideoFix(bool isFix)
 {
     m_videoFix = isFix;
-#ifdef _WEBBOX
+#ifdef _WEBBOX_COMMON
     _mainDescTextBox->SetVideoFix(m_videoFix);
     _descTextBox->SetVideoFix(m_videoFix);
 #endif
@@ -667,12 +667,24 @@ void MainWindow::CreateMenuBar()
 void MainWindow::CreateDockWindows()
 {
     // "Main desc" widget
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     _mainDescTextBox = new QspTextBox(this);
     connect(_mainDescTextBox, SIGNAL(anchorClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
-#else
+#endif
+#ifdef _WEBBOX
     _mainDescTextBox = new QspWebBox(this);
-    _mainDescTextBox->page()->load(QUrl("qsp:"));
+    connect(_mainDescTextBox, SIGNAL(qspLinkClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
+    _mainDescTextBox->page()->load(QUrl("qsp:/"));
+#endif
+#ifdef _WEBBOX_WEBKIT
+    _mainDescTextBox = new QspWebBox(this);
+    connect(_mainDescTextBox, SIGNAL(linkClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
+    _mainDescTextBox->load(QUrl("qsp:/"));
+    {
+        QEventLoop loop;
+        connect(_mainDescTextBox,SIGNAL(loadFinished(bool)),&loop,SLOT(quit()));
+        loop.exec();
+    }
 #endif
     _mainDescTextBox->setObjectName(QStringLiteral("_mainDescTextBox"));
     _mainDescWidget = new QDockWidget(tr("Main desc"), this);
@@ -709,12 +721,24 @@ void MainWindow::CreateDockWindows()
     _descWidget = new QDockWidget(tr("Additional desc"), this);
     _descWidget->setObjectName(QStringLiteral("_descWidget"));
     addDockWidget(Qt::BottomDockWidgetArea, _descWidget, Qt::Horizontal);
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     _descTextBox = new QspTextBox(this);
     connect(_descTextBox, SIGNAL(anchorClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
-#else
+#endif
+#ifdef _WEBBOX
     _descTextBox = new QspWebBox(this);
-    _mainDescTextBox->page()->load(QUrl("qsp:"));
+    connect(_descTextBox, SIGNAL(qspLinkClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
+    _mainDescTextBox->page()->load(QUrl("qsp:/"));
+#endif
+#ifdef _WEBBOX_WEBKIT
+    _descTextBox = new QspWebBox(this);
+    connect(_descTextBox, SIGNAL(linkClicked(QUrl)), this, SLOT(OnLinkClicked(QUrl)));
+    _descTextBox->load(QUrl("qsp:/"));
+    {
+        QEventLoop loop;
+        connect(_descTextBox,SIGNAL(loadFinished(bool)),&loop,SLOT(quit()));
+        loop.exec();
+    }
 #endif
     _descTextBox->setObjectName(QStringLiteral("_descTextBox"));
     _descWidget->setWidget(_descTextBox);
@@ -826,7 +850,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
     if(event->key() == Qt::Key_Escape)
         if(isFullScreen())
             showNormal();
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     _descTextBox->keyPressEvent(event);
     _mainDescTextBox->keyPressEvent(event);
 #endif
@@ -1151,13 +1175,13 @@ void MainWindow::OnLinkClicked(const QUrl &url)
     {
         QObject* obj = sender();
         if (obj == _mainDescTextBox)
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
             _mainDescTextBox->setSource(url);
 #else
             _mainDescTextBox->setUrl(url);
 #endif
         else
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
             _descTextBox->setSource(url);
 #else
             _descTextBox->setUrl(url);

+ 5 - 2
mainwindow.h

@@ -29,6 +29,9 @@
 #include "qspwebengineurlrequestinterceptor.h"
 #include "qspwebengineurlschemehandler.h"
 #endif
+#ifdef _WEBBOX_WEBKIT
+#include "qspwebbox_webkit.h"
+#endif
 
 #include <qsp_default.h>
 
@@ -60,7 +63,7 @@ public:
 
     // Accessors
     QTimer *GetTimer() const { return m_timer; }
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     QspTextBox *GetDesc() const { return _mainDescTextBox; }
     QspTextBox *GetVars() const { return _descTextBox; }
 #else
@@ -148,7 +151,7 @@ private:
     QMenu*			_gameMenu; // was wxMenu *m_gameMenu;
     QMenu*			_settingsMenu; // was wxMenu *m_settingsMenu;
     QMenu*			_showHideMenu; //Show / Hide submenu
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     QspTextBox*		_mainDescTextBox; //m_desc
     QspTextBox*		_descTextBox; //m_vars ID_VARSDESC
 #else

+ 71 - 0
qspnetworkaccessmanager.cpp

@@ -0,0 +1,71 @@
+#include "qspnetworkaccessmanager.h"
+#include "qspreply.h"
+
+QspNetworkAccessManager::QspNetworkAccessManager(QNetworkAccessManager *oldManager, QObject *parent) : QNetworkAccessManager(parent)
+{
+    //setCache(oldManager->cache());
+    setCookieJar(oldManager->cookieJar());
+    //setProxy(oldManager->proxy());
+    //setProxyFactory(oldManager->proxyFactory());
+}
+
+QspNetworkAccessManager::~QspNetworkAccessManager()
+{
+
+}
+
+void QspNetworkAccessManager::SetPlainText(const QString &text)
+{
+    m_isUseHtml = false;
+    m_text= text;
+}
+
+void QspNetworkAccessManager::SetHtml(const QString &text)
+{
+    m_isUseHtml = true;
+    m_text =text;
+}
+
+void QspNetworkAccessManager::SetGamePath(const QString &path)
+{
+    m_path = path;
+}
+
+void QspNetworkAccessManager::SetLinkColor(const QColor &color)
+{
+    m_linkColor = color;
+}
+
+void QspNetworkAccessManager::SetBackgroundColor(const QColor &color)
+{
+    m_backColor = color;
+}
+
+void QspNetworkAccessManager::SetForegroundColor(const QColor &color)
+{
+    m_fontColor = color;
+}
+
+void QspNetworkAccessManager::SetBackgroundImage(const QString &path)
+{
+    m_bmpBg = path;
+}
+
+void QspNetworkAccessManager::SetTextFont(const QFont &new_font)
+{
+    m_font = new_font;
+}
+
+QNetworkReply *QspNetworkAccessManager::createRequest(
+    QNetworkAccessManager::Operation operation, const QNetworkRequest &request,
+    QIODevice *device)
+{
+    if (request.url().scheme() == "http" || request.url().scheme() == "https")
+        return QNetworkAccessManager::createRequest(operation, request, device);
+
+    if (operation == GetOperation)
+        // Handle qsp:// URLs separately by creating custom QNetworkReply objects.
+        return new QspReply(request.url(), m_text, m_isUseHtml, m_path, m_linkColor, m_backColor, m_fontColor, m_bmpBg, m_font);
+    else
+        return QNetworkAccessManager::createRequest(operation, request, device);
+}

+ 39 - 0
qspnetworkaccessmanager.h

@@ -0,0 +1,39 @@
+#ifndef QSPNETWORKACCESSMANAGER_H
+#define QSPNETWORKACCESSMANAGER_H
+
+#include <QNetworkAccessManager>
+#include <QString>
+#include <QColor>
+#include <QFont>
+
+class QspNetworkAccessManager : public QNetworkAccessManager
+{
+    Q_OBJECT
+
+public:
+    QspNetworkAccessManager(QNetworkAccessManager *oldManager, QObject *parent = 0);
+    ~QspNetworkAccessManager();
+    void SetPlainText(const QString& text);
+    void SetHtml(const QString& text);
+    void SetGamePath(const QString &path);
+    void SetLinkColor(const QColor &color);
+    void SetBackgroundColor(const QColor& color);
+    void SetForegroundColor(const QColor& color);
+    void SetBackgroundImage(const QString &path);
+    void SetTextFont(const QFont& new_font);
+
+protected:
+    QNetworkReply *createRequest(Operation operation, const QNetworkRequest &request, QIODevice *device);
+
+private:
+    QString  m_text;
+    QString m_path;
+    QString m_bmpBg;
+    QColor m_linkColor;
+    QColor m_backColor;
+    QColor m_fontColor;
+    QFont m_font;
+    bool m_isUseHtml = true;
+};
+
+#endif // QSPNETWORKACCESSMANAGER_H

+ 101 - 0
qspreply.cpp

@@ -0,0 +1,101 @@
+#include "qspreply.h"
+
+#include <QTimer>
+#include <QMimeDatabase>
+#include <QMimeType>
+#include <QFile>
+
+#include "comtools.h"
+
+QspReply::QspReply(const QUrl &url, const QString &_text, bool _isUseHtml, const QString &_path, const QColor &_linkColor, const QColor &_backColor, const QColor &_fontColor, const QString &_bmpBg, const QFont &_font)
+{
+    offset = 0;
+    m_text = _text;
+    m_path = _path;
+    m_bmpBg = _bmpBg;
+    m_linkColor = _linkColor;
+    m_backColor = _backColor;
+    m_fontColor = _fontColor;
+    m_font = _font;
+    m_isUseHtml = _isUseHtml;
+
+    setUrl(url);
+
+    QString url_str = QByteArray::fromPercentEncoding(url.toString().toUtf8());
+
+    if(url_str.compare("qsp:" , Qt::CaseInsensitive) == 0 || url_str.compare("qsp:/" , Qt::CaseInsensitive) == 0)
+    {
+        QString replystr;
+        replystr.append("<html>\n<head>\n<meta charset=\"UTF-8\">\n<style>\nbody {\n");
+        if(m_backColor.isValid())
+            replystr.append(QString("background-color: %1;\n").arg(m_backColor.name()));
+        if(m_fontColor.isValid())
+            replystr.append(QString("color: %1;\n").arg(m_fontColor.name()));
+        replystr.append(QString("font-family: %1;\n").arg(m_font.family()));
+        replystr.append(QString("font-size: %1pt;\n").arg(m_font.pointSize()));
+        if(!m_bmpBg.isEmpty())
+            replystr.append(QString("background: url(%1) no-repeat center center fixed;\nbackground-size: cover;\n").arg(m_bmpBg));
+        if(m_linkColor.isValid())
+            replystr.append(QString("}\na:link {\ncolor: %1;\n").arg(m_linkColor.name()));
+        replystr.append("}\n</style></head>\n<body>\n");
+        replystr.append(m_text);
+        replystr.append("</body>\n</html>");
+
+        open(ReadOnly | Unbuffered);
+        if(m_isUseHtml)
+        {
+            content = replystr.toUtf8();
+            setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/html"));
+        }
+        else
+        {
+            setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain; charset=utf-8"));
+            content = m_text.toUtf8();
+        }
+    }
+    else
+    {
+        open(ReadOnly | Unbuffered);
+        QString path = QSPTools::GetCaseInsensitiveFilePath(m_path, url_str.mid(5));
+        QMimeDatabase db;
+        QMimeType type = db.mimeTypeForFile(m_path + path);
+        QFile file( m_path + path );
+        if(file.open(QIODevice::ReadOnly))
+        {
+            content = file.readAll();
+            setHeader(QNetworkRequest::ContentTypeHeader, QVariant(type.name().toUtf8()));
+        }
+        file.close();
+    }
+    setHeader(QNetworkRequest::ContentLengthHeader, QVariant(content.size()));
+    QTimer::singleShot(0, this, SLOT(readyRead()));
+    QTimer::singleShot(0, this, SLOT(finished()));
+    //emit readyRead();
+    //emit finished();
+}
+
+void QspReply::abort()
+{
+
+}
+
+qint64 QspReply::bytesAvailable() const
+{
+    return content.size() - offset + QIODevice::bytesAvailable();
+}
+
+bool QspReply::isSequential() const
+{
+    return true;
+}
+
+qint64 QspReply::readData(char *data, qint64 maxSize)
+{
+    if (offset < content.size()) {
+        qint64 number = qMin(maxSize, content.size() - offset);
+        memcpy(data, content.constData() + offset, number);
+        offset += number;
+        return number;
+    } else
+        return -1;
+}

+ 35 - 0
qspreply.h

@@ -0,0 +1,35 @@
+#ifndef QSPREPLY_H
+#define QSPREPLY_H
+
+#include <QNetworkReply>
+#include <QString>
+#include <QColor>
+#include <QFont>
+
+class QspReply : public QNetworkReply
+{
+    Q_OBJECT
+
+public:
+    QspReply(const QUrl &url, const QString  &_text, bool _isUseHtml, const QString &_path, const QColor &_linkColor, const QColor &_backColor, const QColor &_fontColor, const QString &_bmpBg, const QFont &_font);
+    void abort();
+    qint64 bytesAvailable() const;
+    bool isSequential() const;
+
+protected:
+    qint64 readData(char *data, qint64 maxSize);
+
+    QByteArray content;
+    qint64 offset;
+
+    QString  m_text;
+    QString m_path;
+    QString m_bmpBg;
+    QColor m_linkColor;
+    QColor m_backColor;
+    QColor m_fontColor;
+    QFont m_font;
+    bool m_isUseHtml = true;
+};
+
+#endif // QSPREPLY_H

+ 5 - 5
qsptextbox.cpp

@@ -24,7 +24,7 @@ QspTextBox::QspTextBox(QWidget *parent) : QTextBrowser(parent)
     //m_backColor = QColor(224, 224, 224);
     m_font = font();
     setOpenLinks(false);
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(resizeAnimations()) );
     connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(resizeAnimations()) );
 #endif
@@ -38,7 +38,7 @@ QspTextBox::QspTextBox(QWidget *parent) : QTextBrowser(parent)
 
 QspTextBox::~QspTextBox()
 {
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     clearManualResources();
 #endif
 }
@@ -84,7 +84,7 @@ void QspTextBox::SetText(const QString& text, bool isScroll)
 {
     if (m_text != text)
     {
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
         clearManualResources();
 #endif
         if (isScroll)
@@ -94,7 +94,7 @@ void QspTextBox::SetText(const QString& text, bool isScroll)
         }
         m_text = text;
         RefreshUI(isScroll);
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
         resizeAnimations();
 #endif
     }
@@ -199,7 +199,7 @@ void QspTextBox::keyPressEvent(QKeyEvent *event)
     QTextBrowser::keyPressEvent(event);
 }
 
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
 void QspTextBox::SetBackgroundImage(const QImage& bmpBg)
 {
     m_bmpBg = bmpBg;

+ 4 - 4
qsptextbox.h

@@ -59,7 +59,7 @@ public:
     void SetShowPlainText(bool isPlain);
     void SetDisableVideo(bool isDisableVideo) { disableVideo = isDisableVideo; }
     void keyPressEvent(QKeyEvent *event);
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     void SetBackgroundImage(const QImage& bmpBg);
     void LoadBackImage(const QString& fileName);
 #endif
@@ -67,7 +67,7 @@ public:
 private:
     // Internal methods
     void wheelEvent(QWheelEvent *e);
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     void CalcImageSize();
     void paintEvent(QPaintEvent *e);
     QVariant loadResource(int type, const QUrl &name);
@@ -89,7 +89,7 @@ private:
     QColor m_fontColor;
     bool showPlainText;
     bool disableVideo;
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
     QImage m_bmpBg;
     QImage m_bmpRealBg;
     QMap<QString, animation_gif> animations_gif;
@@ -97,7 +97,7 @@ private:
     QMutex mutex;
 #endif
 
-#ifndef _WEBBOX
+#ifndef _WEBBOX_COMMON
 private slots:
     void repaintAnimation();
     void resizeAnimations();

+ 8 - 2
qspwebbox.cpp

@@ -33,11 +33,12 @@ QspWebBox::QspWebBox(QWidget *parent) : QWebEngineView(parent)
     //QspWebEngineUrlRequestInterceptor *qwuri = new QspWebEngineUrlRequestInterceptor(this);
     //profile->setRequestInterceptor(qwuri);
     qweush = new QspWebEngineUrlSchemeHandler(this);
-    profile->installUrlSchemeHandler(QByteArray("qsp"),qweush);
+    profile->installUrlSchemeHandler(QByteArray("qsp"), qweush);
     QspExecWebEngineUrlSchemeHandler *qeweush = new QspExecWebEngineUrlSchemeHandler(this);
-    profile->installUrlSchemeHandler(QByteArray("exec"),qeweush);
+    profile->installUrlSchemeHandler(QByteArray("exec"), qeweush);
     QWebEnginePage * page = new QWebEnginePage(profile, this);
     setPage(page);
+    connect(qeweush, SIGNAL(qspLinkClicked(QUrl)), this, SLOT(OnQspLinkClicked(QUrl)));
 }
 
 QspWebBox::~QspWebBox()
@@ -227,3 +228,8 @@ void QspWebBox::SetVideoFix(bool isFix)
 {
     m_videoFix = isFix;
 }
+
+void QspWebBox::OnQspLinkClicked(QUrl url)
+{
+    emit qspLinkClicked(url);
+}

+ 6 - 0
qspwebbox.h

@@ -59,6 +59,12 @@ private:
     bool showPlainText;
     bool m_videoFix;
     QspWebEngineUrlSchemeHandler *qweush;
+
+signals:
+    void qspLinkClicked(QUrl url);
+
+private slots:
+    void OnQspLinkClicked(QUrl url);
 };
 
 #endif // QSPWEBBOX_H

+ 215 - 0
qspwebbox_webkit.cpp

@@ -0,0 +1,215 @@
+#include "qspwebbox_webkit.h"
+
+#include <QFileInfo>
+#include <QPalette>
+#include <QAbstractScrollArea>
+#include <QScrollBar>
+#include <QPainter>
+#include <QWebSettings>
+#include <QEventLoop>
+
+#include "comtools.h"
+
+QspWebBox::QspWebBox(QWidget *parent) : QWebView(parent)
+{
+    settings()->setDefaultTextEncoding("utf-8");
+    setFocusPolicy(Qt::NoFocus);
+    //setFrameStyle(QFrame::NoFrame);
+    //setFrameShadow(QFrame::Plain);
+    setContextMenuPolicy( Qt::NoContextMenu );
+    setContentsMargins(0,0,0,0);
+    m_isUseHtml = false;
+    showPlainText = false;
+    m_videoFix = true;
+    m_font = font();
+    //setOpenLinks(false);
+    page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
+    QNetworkAccessManager *oldManager = page()->networkAccessManager();
+    qspManager = new QspNetworkAccessManager(oldManager, this);
+    page()->setNetworkAccessManager(qspManager);
+    page()->setForwardUnsupportedContent(true);
+    load(QUrl("qsp:/"));
+}
+
+QspWebBox::~QspWebBox()
+{
+
+}
+
+void QspWebBox::SetIsHtml(bool isHtml)
+{
+    if (m_isUseHtml != isHtml)
+    {
+        m_isUseHtml = isHtml;
+        RefreshUI();
+    }
+}
+
+void QspWebBox::RefreshUI(bool isScroll)
+{
+    QString color(QSPTools::GetHexColor(GetForegroundColor()));
+    QString str = m_text;
+    QString text;
+//    if(m_isUseHtml)
+//    {
+//        if(str.endsWith("\r"))
+//            str.chop(1);
+//        if(str.endsWith("\n"))
+//            str.chop(1);
+//        str = str.replace("\r", "").replace("\n", "<br>").replace("<video ", "<img ", Qt::CaseInsensitive);
+//        text = str.replace("</center><br>", "</center>", Qt::CaseInsensitive).replace("</table><br>", "</table>", Qt::CaseInsensitive);
+//    }
+//    else
+//    {
+//        text = str;
+//    }
+
+    if(m_videoFix)
+    {
+        int copypos = 0;
+        int startIndex = str.indexOf("<video", 0, Qt::CaseInsensitive);
+        while (startIndex >= 0)
+        {
+            int endIndex = str.indexOf(">", startIndex, Qt::CaseInsensitive);
+            if(endIndex < 0)
+                break;
+            endIndex = endIndex + 1;
+            text.append(str.mid(copypos, startIndex + 6 - copypos));
+            if(!str.mid(startIndex, endIndex - startIndex).contains("autoplay", Qt::CaseInsensitive))
+                text.append(" autoplay");
+            if(!str.mid(startIndex, endIndex - startIndex).contains("loop", Qt::CaseInsensitive))
+                text.append(" loop");
+            text.append(str.mid(startIndex + 6, endIndex - startIndex - 6));
+            copypos = endIndex;
+            int cloaseTegPos = str.indexOf("</video>", 0, Qt::CaseInsensitive);
+            if(cloaseTegPos == -1)
+                text.append("</video>");
+            else
+            {
+                int nextV = str.indexOf("<video", endIndex, Qt::CaseInsensitive);
+                if(nextV == -1)
+                    text.append("</video>");
+                else
+                {
+                    if(cloaseTegPos > nextV)
+                        text.append("</video>");
+                }
+            }
+            startIndex = str.indexOf("<video", endIndex, Qt::CaseInsensitive);
+        }
+        text.append(str.mid(copypos));
+    }
+    else
+        text = str;
+
+    text = QSPTools::HtmlizeWhitespaces(m_isUseHtml ? text : QSPTools::ProceedAsPlain(text));
+    if(showPlainText)
+        qspManager->SetPlainText(text);
+    else
+        qspManager->SetHtml(text);
+    QString url_str = QByteArray::fromPercentEncoding(url().toString().toUtf8());
+    if(url_str.compare("qsp:" , Qt::CaseInsensitive) != 0 || url_str.compare("qsp:/" , Qt::CaseInsensitive) != 0)
+    {
+        QEventLoop loop;
+        connect(this, SIGNAL(loadFinished(bool)), &loop, SLOT(quit()));
+        load(QUrl("qsp:/"));
+        loop.exec();
+    }
+    triggerPageAction(QWebPage::ReloadAndBypassCache);
+}
+
+void QspWebBox::LoadBackImage(const QString& fileName)
+{
+    qspManager->SetBackgroundImage(fileName);
+    QFileInfo file(m_path + fileName);
+    QString path(file.absoluteFilePath());
+}
+
+void QspWebBox::SetText(const QString& text, bool isScroll)
+{
+    if (m_text != text)
+    {
+        if (isScroll)
+        {
+            if (m_text.isEmpty() || !text.startsWith(m_text))
+                isScroll = false;
+        }
+        m_text = text;
+        RefreshUI(isScroll);
+    }
+}
+
+void QspWebBox::SetTextFont(const QFont& new_font)
+{
+    if (m_font != new_font)
+    {
+        m_font = new_font;
+        qspManager->SetTextFont(new_font);
+    }
+}
+
+bool QspWebBox::SetLinkColor(const QColor &color)
+{
+    if(m_linkColor != color)
+    {
+        m_linkColor = color;
+        qspManager->SetLinkColor(color);
+        RefreshUI();
+        return true;
+    }
+    return false;
+}
+
+void QspWebBox::SetGamePath(const QString &path)
+{
+    m_path = path;
+    qspManager->SetGamePath(path);
+}
+
+//Returns the background color of the window.
+QColor QspWebBox::GetBackgroundColor()
+{
+    return m_backColor;
+}
+
+//The meaning of foreground colour varies according to the window class; it may be the text colour or other colour, or it may not be used at all. Additionally, not all native controls support changing their foreground colour so this method may change their colour only partially or even not at all.
+QColor QspWebBox::GetForegroundColor()
+{
+    return m_fontColor;
+}
+
+//Returns true if the color was really changed, false if it was already set to this color and nothing was done.
+bool QspWebBox::SetBackgroundColor(const QColor &color)
+{
+    if(m_backColor != color)
+    {
+        m_backColor = color;
+        qspManager->SetBackgroundColor(color);
+        RefreshUI();
+        return true;
+    }
+    return false;
+}
+
+bool QspWebBox::SetForegroundColor(const QColor &color)
+{
+    if(m_fontColor != color)
+    {
+        m_fontColor = color;
+        qspManager->SetForegroundColor(color);
+        RefreshUI();
+        return true;
+    }
+    return false;
+}
+
+void QspWebBox::SetShowPlainText(bool isPlain)
+{
+    showPlainText = isPlain;
+    RefreshUI();
+}
+
+void QspWebBox::SetVideoFix(bool isFix)
+{
+    m_videoFix = isFix;
+}

+ 64 - 0
qspwebbox_webkit.h

@@ -0,0 +1,64 @@
+#ifndef QSPWEBBOX_H
+#define QSPWEBBOX_H
+
+#include <QWidget>
+#include <QWebView>
+#include <QString>
+#include <QFont>
+#include <QColor>
+#include <QVariant>
+#include <QUrl>
+
+#include "qspnetworkaccessmanager.h"
+
+namespace Ui {
+class QspWebBox;
+}
+
+class QspWebBox : public QWebView
+{
+    Q_OBJECT
+
+public:
+    explicit QspWebBox(QWidget *parent = 0);
+    ~QspWebBox();
+
+    // Methods
+    void RefreshUI(bool isScroll = false);
+    void LoadBackImage(const QString& fileName);
+
+    // Accessors
+    void SetIsHtml(bool isHtml);
+    void SetText(const QString& text, bool isScroll = false);
+    void SetTextFont(const QFont& new_font);
+    QFont GetTextFont() const { return m_font; }
+    QString GetText() const { return m_text; }
+    bool SetLinkColor(const QColor &color);
+    QColor GetLinkColor() { return m_linkColor; }
+    void SetGamePath(const QString& path);
+    QColor GetBackgroundColor();
+    QColor GetForegroundColor(); //text color
+    bool SetBackgroundColor(const QColor& color);
+    bool SetForegroundColor(const QColor& color);
+    void SetShowPlainText(bool isPlain);
+    void SetVideoFix(bool isFix);
+
+private:
+    // Fields
+    bool m_isUseHtml;
+    QString m_outFormat;
+    QString m_path;
+    QString m_imagePath;
+    QFont m_font;
+    QString m_text;
+    int m_posX;
+    int m_posY;
+    QColor m_linkColor;
+    QColor m_backColor;
+    QColor m_fontColor;
+    bool showPlainText;
+    bool m_videoFix;
+    QspNetworkAccessManager *qspManager;
+};
+
+#endif // QSPWEBBOX_H

+ 4 - 2
qspwebengineurlschemehandler.cpp

@@ -58,8 +58,10 @@ void QspWebEngineUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *reque
         QMimeDatabase db;
         QMimeType type = db.mimeTypeForFile(m_path + path);
         QFile file( m_path + path );
-        file.open(QIODevice::ReadOnly);
-        buffer->write(file.readAll());
+        if(file.open(QIODevice::ReadOnly))
+        {
+            buffer->write(file.readAll());
+        }
         buffer->close();
         file.close();
         request->reply(type.name().toUtf8(), buffer);