1 /*
2     SuperCollider Qt IDE
3     Copyright (c) 2012 Jakob Leben & Tim Blechmann
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 
21 #pragma once
22 
23 #include "util/docklet.hpp"
24 #include "QtCollider/widgets/web_page.hpp"
25 
26 #include <QWebEngineView>
27 #include <QLabel>
28 #include <QLineEdit>
29 #include <QBasicTimer>
30 #include <QTimerEvent>
31 #include <QList>
32 #include <QKeySequence>
33 
34 namespace ScIDE {
35 
36 namespace Settings {
37 class Manager;
38 }
39 
40 class HelpBrowserDocklet;
41 class HelpBrowserFindBox;
42 class HelpBrowser;
43 
44 class LoadProgressIndicator : public QLabel {
45     Q_OBJECT
46 public slots:
start(const QString & msg=tr ("Loading"))47     void start(const QString& msg = tr("Loading")) {
48         mMsg = msg;
49         mDotCount = 0;
50         mUpdateTimer.start(200, this);
51     }
stop()52     void stop() {
53         mUpdateTimer.stop();
54         clear();
55     }
56 
57 protected:
timerEvent(QTimerEvent * event)58     virtual void timerEvent(QTimerEvent* event) {
59         if (event->timerId() != mUpdateTimer.timerId())
60             return;
61 
62         ++mDotCount;
63         if (mDotCount > 6)
64             mDotCount = 1;
65 
66         QString string(mDotCount, '.');
67         string.prepend(mMsg);
68 
69         setText(string);
70     }
71 
72 private:
73     QBasicTimer mUpdateTimer;
74     QString mMsg;
75     int mDotCount;
76 };
77 
78 class HelpWebPage : public QtCollider::WebPage {
79     Q_OBJECT
80 
81 public:
82     HelpWebPage(HelpBrowser* browser);
83 
84 private:
85     HelpBrowser* mBrowser;
86 };
87 
88 class HelpBrowser : public QWidget {
89     Q_OBJECT
90 
91 public:
92     enum ActionRole {
93         GoHome,
94         DocClose,
95         ZoomIn,
96         ZoomOut,
97         ResetZoom,
98         Evaluate,
99 
100         ActionCount
101     };
102 
103     HelpBrowser(QWidget* parent = 0);
104 
sizeHint() const105     QSize sizeHint() const { return mSizeHint; }
minimumSizeHint() const106     QSize minimumSizeHint() const { return QSize(50, 50); }
107 
108     void gotoHelpFor(const QString&);
109     void gotoHelpForMethod(const QString& className, const QString& methodName);
loadProgressIndicator()110     QWidget* loadProgressIndicator() { return mLoadProgressIndicator; }
111 
url() const112     QUrl url() const { return mWebView->url(); }
113 
114     bool helpBrowserHasFocus() const;
115 
setServerPort(int serverPort)116     void setServerPort(int serverPort) { mServerPort = serverPort; };
117 
118 public slots:
119     void applySettings(Settings::Manager*);
120     void goHome();
121     void closeDocument();
122     void zoomIn();
123     void zoomOut();
124     void resetZoom();
125     void evaluateSelection(bool region = false);
126     void findText(const QString& text, bool backwards = false);
127     bool openDocumentation();
128     void openDefinition();
129     void openCommandLine();
130     void findReferences();
131     void onLinkClicked(const QUrl&, QWebEnginePage::NavigationType type, bool isMainFrame);
132     void onPageLoad();
133 
134 signals:
135     void urlChanged();
136 
137 private slots:
138     void onContextMenuRequest(const QPoint& pos);
139     void onReload();
140     void onScResponse(const QString& command, const QString& data);
141     void onJsConsoleMsg(const QString&, int, const QString&);
142 
143 private:
144     friend class HelpBrowserDocklet;
145 
146     void createActions();
147     bool eventFilter(QObject* object, QEvent* event);
148     void sendRequest(const QString& code);
149     QString symbolUnderCursor();
150 
151     QWebEngineView* mWebView;
152     LoadProgressIndicator* mLoadProgressIndicator;
153 
154     QSize mSizeHint;
155 
156     QAction* mActions[ActionCount];
157 
158     int mServerPort = 0; // if 0, server is not running
159 };
160 
161 class HelpBrowserFindBox : public QLineEdit {
162     Q_OBJECT
163 
164 public:
165     HelpBrowserFindBox(QWidget* parent = 0);
166 
167 signals:
168     void query(const QString& text, bool backwards = false);
169 
170 protected:
171     virtual bool event(QEvent* event);
172 };
173 
174 class HelpBrowserDocklet : public Docklet {
175     Q_OBJECT
176 
177 public:
178     explicit HelpBrowserDocklet(QWidget* parent = 0);
browser()179     HelpBrowser* browser() { return mHelpBrowser; }
180 
181 private slots:
onInterpreterStart()182     void onInterpreterStart() {
183         if (isVisible() && mHelpBrowser->url().isEmpty())
184             mHelpBrowser->goHome();
185     }
186 
187 private:
188     HelpBrowser* mHelpBrowser;
189     HelpBrowserFindBox* mFindBox;
190 };
191 
192 } // namespace ScIDE
193