1 /************************************************************************
2  *
3  * Copyright 2011 Jakob Leben (jakob.leben@gmail.com)
4  *
5  * This file is part of SuperCollider Qt GUI.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  ************************************************************************/
21 
22 #pragma once
23 
24 #include "../QcCallback.hpp"
25 #include <QWebEngineView>
26 #include <QWebEnginePage>
27 #include <QWebEngineCallback>
28 #include <QPointer>
29 #include <QUrl>
30 #include <QException>
31 
32 const static int kWebEngineTimeout = 10000;
33 
34 Q_DECLARE_METATYPE(QUrl)
35 
36 namespace QtCollider {
37 
38 class WebPage;
39 
40 class WebView : public QWebEngineView {
41     Q_OBJECT
42 
43 public:
44     Q_INVOKABLE void setFontFamily(int genericFontFamily, const QString& fontFamily);
45     Q_INVOKABLE void triggerPageAction(int action, bool checked);
46     Q_INVOKABLE QAction* pageAction(QWebEnginePage::WebAction) const;
47 
48     // QWebEnginePage forwards
49     Q_INVOKABLE void setHtml(const QString& html, const QString& baseUrl);
50     Q_INVOKABLE void setContent(const QVector<int>& data, const QString& mimeType, const QString& baseUrl);
51     Q_INVOKABLE void toHtml(QcCallback* cb) const;
52     Q_INVOKABLE void toPlainText(QcCallback* cb) const;
53     Q_INVOKABLE void runJavaScript(const QString& script, QcCallback* cb);
54     Q_INVOKABLE void setWebAttribute(int attr, bool on);
55     Q_INVOKABLE bool testWebAttribute(int attr);
56     Q_INVOKABLE void resetWebAttribute(int attr);
57     Q_INVOKABLE void navigate(const QString& url);
58 
59 public Q_SLOTS:
60     void findText(const QString& searchText, bool reversed, QcCallback* cb);
61 
62 Q_SIGNALS:
63     void linkActivated(const QString&, int, bool);
64     void jsConsoleMsg(const QString&, int, const QString&);
65     void reloadTriggered(const QString&);
66     void interpret(const QString& code);
67 
68     // QWebEnginePage forwards
69     void linkHovered(const QString& url);
70     void geometryChangeRequested(const QRect& geom);
71     void windowCloseRequested();
72     void navigationRequested(const QUrl&, int, bool);
73 
74     void renderProcessTerminated(int terminationStatus, int exitCode);
75 
76     void scrollPositionChanged(const QPointF& position);
77     void contentsSizeChanged(const QSizeF& size);
78     void audioMutedChanged(bool muted);
79     void recentlyAudibleChanged(bool recentlyAudible);
80 
81 public:
82     WebView(QWidget* parent = 0);
83 
84     Q_PROPERTY(qreal zoom READ zoomFactor WRITE setZoomFactor);
85     Q_PROPERTY(bool hasSelection READ hasSelection);
86     Q_PROPERTY(QString selectedText READ selectedText);
87     Q_PROPERTY(QString title READ title);
88 
89     Q_PROPERTY(bool overrideNavigation READ overrideNavigation WRITE setOverrideNavigation);
90     bool overrideNavigation() const;
91     void setOverrideNavigation(bool b);
92 
93     Q_PROPERTY(QString url READ url WRITE setUrl);
94     QString url() const;
95     void setUrl(const QString&);
96 
97     Q_PROPERTY(bool delegateReload READ delegateReload WRITE setDelegateReload);
98     bool delegateReload() const;
99     void setDelegateReload(bool);
100 
101     Q_PROPERTY(bool enterInterpretsSelection READ interpretSelection WRITE setInterpretSelection);
102     bool interpretSelection() const { return _interpretSelection; }
103     void setInterpretSelection(bool b) { _interpretSelection = b; }
104 
105     Q_PROPERTY(bool editable READ editable WRITE setEditable);
106     bool editable() const { return _editable; }
107     void setEditable(bool b) {
108         _editable = b;
109         updateEditable(true);
110     }
111 
112     // QWebEnginePage properties
113     Q_PROPERTY(QString requestedUrl READ requestedUrl)
114     QString requestedUrl() const { return page() ? page()->requestedUrl().toString() : QString(); }
115 
116     Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
117     QColor backgroundColor() const { return page() ? page()->backgroundColor() : QColor(); }
118     void setBackgroundColor(QColor c) {
119         if (page())
120             page()->setBackgroundColor(c);
121     }
122 
123     Q_PROPERTY(QSizeF contentsSize READ contentsSize)
124     QSizeF contentsSize() const { return page() ? page()->contentsSize() : QSizeF(0, 0); }
125 
126     Q_PROPERTY(QPointF scrollPosition READ scrollPosition)
127     QPointF scrollPosition() const { return page() ? page()->scrollPosition() : QPointF(0, 0); }
128 
129     Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted)
130     bool isAudioMuted() const { return page() ? page()->isAudioMuted() : false; }
131     void setAudioMuted(bool m) {
132         if (page())
133             page()->setAudioMuted(m);
134     }
135 
136     Q_PROPERTY(bool recentlyAudible READ recentlyAudible)
137     bool recentlyAudible() const { return page() ? page()->recentlyAudible() : false; }
138 
139     inline static QUrl urlFromString(const QString& str) { return QUrl::fromUserInput(str); }
140 
141 protected:
142     virtual void keyPressEvent(QKeyEvent*);
143     virtual void contextMenuEvent(QContextMenuEvent*);
144 
145 public Q_SLOTS:
146     void onPageReload();
147     void onRenderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus, int);
148     void onLinkClicked(const QUrl&, QWebEnginePage::NavigationType, bool);
149     void updateEditable(bool);
150 
151 private:
152     void connectPage(QtCollider::WebPage* page);
153 
154     bool _interpretSelection;
155     bool _editable;
156 };
157 
158 } // namespace QtCollider
159