1 /************************************************************************
2 * file name         : main_window.h
3 * ----------------- :
4 * creation time     : 2016/06/26
5 * author            : Victor Zarubkin
6 * email             : v.s.zarubkin@gmail.com
7 * ----------------- :
8 * description       : The file contains declaration of MainWindow for easy_profiler GUI.
9 * ----------------- :
10 * change log        : * 2016/06/26 Victor Zarubkin: initial commit.
11 *                   : *
12 * ----------------- :
13 * license           : Lightweight profiler library for c++
14 *                   : Copyright(C) 2016-2017  Sergey Yagovtsev, Victor Zarubkin
15 *                   :
16 *                   : Licensed under either of
17 *                   :     * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
18 *                   :     * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
19 *                   : at your option.
20 *                   :
21 *                   : The MIT License
22 *                   :
23 *                   : Permission is hereby granted, free of charge, to any person obtaining a copy
24 *                   : of this software and associated documentation files (the "Software"), to deal
25 *                   : in the Software without restriction, including without limitation the rights
26 *                   : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
27 *                   : of the Software, and to permit persons to whom the Software is furnished
28 *                   : to do so, subject to the following conditions:
29 *                   :
30 *                   : The above copyright notice and this permission notice shall be included in all
31 *                   : copies or substantial portions of the Software.
32 *                   :
33 *                   : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
34 *                   : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 *                   : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
36 *                   : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
37 *                   : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
38 *                   : USE OR OTHER DEALINGS IN THE SOFTWARE.
39 *                   :
40 *                   : The Apache License, Version 2.0 (the "License")
41 *                   :
42 *                   : You may not use this file except in compliance with the License.
43 *                   : You may obtain a copy of the License at
44 *                   :
45 *                   : http://www.apache.org/licenses/LICENSE-2.0
46 *                   :
47 *                   : Unless required by applicable law or agreed to in writing, software
48 *                   : distributed under the License is distributed on an "AS IS" BASIS,
49 *                   : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50 *                   : See the License for the specific language governing permissions and
51 *                   : limitations under the License.
52 ************************************************************************/
53 
54 #ifndef EASY_PROFILER_GUI__MAIN_WINDOW__H
55 #define EASY_PROFILER_GUI__MAIN_WINDOW__H
56 
57 #include <string>
58 #include <thread>
59 #include <atomic>
60 #include <sstream>
61 
62 #include <QMainWindow>
63 #include <QDockWidget>
64 #include <QTimer>
65 #include <QStringList>
66 
67 #include <easy/easy_socket.h>
68 #include <easy/reader.h>
69 
70 #ifdef max
71 #undef max
72 #endif
73 
74 #ifdef min
75 #undef min
76 #endif
77 
78 //////////////////////////////////////////////////////////////////////////
79 
80 #define EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW 0
81 
82 namespace profiler { namespace net { struct EasyProfilerStatus; } }
83 
84 //////////////////////////////////////////////////////////////////////////
85 
86 class EasyFileReader Q_DECL_FINAL
87 {
88     ::profiler::SerializedData      m_serializedBlocks; ///<
89     ::profiler::SerializedData m_serializedDescriptors; ///<
90     ::profiler::descriptors_list_t       m_descriptors; ///<
91     ::profiler::blocks_t                      m_blocks; ///<
92     ::profiler::thread_blocks_tree_t      m_blocksTree; ///<
93     ::std::stringstream                       m_stream; ///<
94     ::std::stringstream                 m_errorMessage; ///<
95     QString                                 m_filename; ///<
96     uint32_t             m_descriptorsNumberInFile = 0; ///<
97     uint32_t                             m_version = 0; ///<
98     ::std::thread                             m_thread; ///<
99     ::std::atomic_bool                         m_bDone; ///<
100     ::std::atomic<int>                      m_progress; ///<
101     ::std::atomic<unsigned int>                 m_size; ///<
102     bool                              m_isFile = false; ///<
103 
104 public:
105 
106     EasyFileReader();
107     ~EasyFileReader();
108 
109     const bool isFile() const;
110     bool done() const;
111     int progress() const;
112     unsigned int size() const;
113     const QString& filename() const;
114 
115     void load(const QString& _filename);
116     void load(::std::stringstream& _stream);
117     void interrupt();
118     void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
119              ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
120              uint32_t& _descriptorsNumberInFile, uint32_t& _version, QString& _filename);
121 
122     QString getError();
123 
124 }; // END of class EasyFileReader.
125 
126 //////////////////////////////////////////////////////////////////////////
127 
128 enum EasyListenerRegime : uint8_t
129 {
130     LISTENER_IDLE = 0,
131     LISTENER_CAPTURE,
132     LISTENER_CAPTURE_RECEIVE,
133     LISTENER_DESCRIBE
134 };
135 
136 class EasySocketListener Q_DECL_FINAL
137 {
138     EasySocket            m_easySocket; ///<
139     ::std::string            m_address; ///<
140     ::std::stringstream m_receivedData; ///<
141     ::std::thread             m_thread; ///<
142     uint64_t            m_receivedSize; ///<
143     uint16_t                    m_port; ///<
144     ::std::atomic<uint32_t> m_frameMax; ///<
145     ::std::atomic<uint32_t> m_frameAvg; ///<
146     ::std::atomic_bool    m_bInterrupt; ///<
147     ::std::atomic_bool    m_bConnected; ///<
148     ::std::atomic_bool  m_bStopReceive; ///<
149     ::std::atomic_bool m_bCaptureReady; ///<
150     ::std::atomic_bool m_bFrameTimeReady; ///<
151     EasyListenerRegime        m_regime; ///<
152 
153 public:
154 
155     EasySocketListener();
156     ~EasySocketListener();
157 
158     bool connected() const;
159     bool captured() const;
160     EasyListenerRegime regime() const;
161     uint64_t size() const;
162     const ::std::string& address() const;
163     uint16_t port() const;
164 
165     ::std::stringstream& data();
166     void clearData();
167 
168     void disconnect();
169     void closeSocket();
170     bool connect(const char* _ipaddress, uint16_t _port, ::profiler::net::EasyProfilerStatus& _reply, bool _disconnectFirst = false);
171     bool reconnect(const char* _ipaddress, uint16_t _port, ::profiler::net::EasyProfilerStatus& _reply);
172 
173     bool startCapture();
174     void stopCapture();
175     void finalizeCapture();
176     void requestBlocksDescription();
177 
178     bool frameTime(uint32_t& _maxTime, uint32_t& _avgTime);
179     bool requestFrameTime();
180 
181     template <class T>
send(const T & _message)182     inline void send(const T& _message)
183     {
184         m_easySocket.send(&_message, sizeof(T));
185     }
186 
187 private:
188 
189     void listenCapture();
190     void listenDescription();
191     void listenFrameTime();
192 
193 }; // END of class EasySocketListener.
194 
195 //////////////////////////////////////////////////////////////////////////
196 
197 class EasyDockWidget : public QDockWidget
198 {
199     Q_OBJECT
200 public:
201     explicit EasyDockWidget(const QString& title, QWidget* parent = nullptr);
202     ~EasyDockWidget() override;
203 };
204 
205 class EasyMainWindow : public QMainWindow
206 {
207     Q_OBJECT
208 
209 protected:
210 
211     typedef EasyMainWindow This;
212     typedef QMainWindow  Parent;
213 
214     QStringList                            m_lastFiles;
215     QString                                    m_theme;
216     QString                              m_lastAddress;
217     QDockWidget*                          m_treeWidget = nullptr;
218     QDockWidget*                        m_graphicsView = nullptr;
219     QDockWidget*                           m_fpsViewer = nullptr;
220 
221 #if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
222     QDockWidget*                      m_descTreeWidget = nullptr;
223 #endif
224 
225     class QProgressDialog*                  m_progress = nullptr;
226     class QDialog*                    m_descTreeDialog = nullptr;
227     class EasyDescWidget*             m_dialogDescTree = nullptr;
228     class QMessageBox*                m_listenerDialog = nullptr;
229     QTimer                               m_readerTimer;
230     QTimer                             m_listenerTimer;
231     QTimer                           m_fpsRequestTimer;
232     ::profiler::SerializedData      m_serializedBlocks;
233     ::profiler::SerializedData m_serializedDescriptors;
234     EasyFileReader                            m_reader;
235     EasySocketListener                      m_listener;
236 
237     class QLineEdit* m_addressEdit = nullptr;
238     class QLineEdit* m_portEdit = nullptr;
239     class QLineEdit* m_frameTimeEdit = nullptr;
240 
241     class QMenu*   m_loadActionMenu = nullptr;
242     class QAction* m_saveAction = nullptr;
243     class QAction* m_deleteAction = nullptr;
244 
245     class QAction* m_captureAction = nullptr;
246     class QAction* m_connectAction = nullptr;
247     class QAction* m_eventTracingEnableAction = nullptr;
248     class QAction* m_eventTracingPriorityAction = nullptr;
249 
250     uint32_t m_descriptorsNumberInFile = 0;
251     uint16_t m_lastPort = 0;
252     bool m_bNetworkFileRegime = false;
253     bool m_bOpenedCacheFile = false;
254 
255 public:
256 
257     explicit EasyMainWindow();
258     ~EasyMainWindow() override;
259 
260     // Public virtual methods
261 
262     void closeEvent(QCloseEvent* close_event) override;
263     void dragEnterEvent(QDragEnterEvent* drag_event) override;
264     void dragMoveEvent(QDragMoveEvent* drag_event) override;
265     void dragLeaveEvent(QDragLeaveEvent* drag_event) override;
266     void dropEvent(QDropEvent* drop_event) override;
267 
268 protected slots:
269 
270     void onThemeChange(bool);
271     void onOpenFileClicked(bool);
272     void onSaveFileClicked(bool);
273     void onDeleteClicked(bool);
274     void onExitClicked(bool);
275     void onEncodingChanged(bool);
276     void onChronoTextPosChanged(bool);
277     void onUnitsChanged(bool);
278     void onEnableDisableStatistics(bool);
279     void onCollapseItemsAfterCloseChanged(bool);
280     void onAllItemsExpandedByDefaultChange(bool);
281     void onBindExpandStatusChange(bool);
282     void onHierarchyFlagChange(bool);
283     void onExpandAllClicked(bool);
284     void onCollapseAllClicked(bool);
285     void onSpacingChange(int _value);
286     void onMinSizeChange(int _value);
287     void onNarrowSizeChange(int _value);
288     void onFpsIntervalChange(int _value);
289     void onFpsHistoryChange(int _value);
290     void onFpsMonitorLineWidthChange(int _value);
291     void onFileReaderTimeout();
292     void onFrameTimeRequestTimeout();
293     void onListenerTimerTimeout();
294     void onFileReaderCancel();
295     void onEditBlocksClicked(bool);
296     void onDescTreeDialogClose(int);
297     void onListenerDialogClose(int);
298     void onCaptureClicked(bool);
299     void onGetBlockDescriptionsClicked(bool);
300     void onConnectClicked(bool);
301     void onEventTracingPriorityChange(bool _checked);
302     void onEventTracingEnableChange(bool _checked);
303     void onFrameTimeEditFinish();
304     void onFrameTimeChanged();
305 
306     void onBlockStatusChange(::profiler::block_id_t _id, ::profiler::EasyBlockStatus _status);
307 
308     void checkFrameTimeReady();
309 
310 private:
311 
312     // Private non-virtual methods
313 
314     void clear();
315 
316     void refreshDiagram();
317 
318     void addFileToList(const QString& filename);
319     void loadFile(const QString& filename);
320     void readStream(::std::stringstream& data);
321 
322     void loadSettings();
323     void loadGeometry();
324     void saveSettingsAndGeometry();
325 
326     void setDisconnected(bool _showMessage = true);
327 
328     void destroyProgressDialog();
329     void createProgressDialog(const QString& text);
330 
331 }; // END of class EasyMainWindow.
332 
333 //////////////////////////////////////////////////////////////////////////
334 
335 #endif // EASY_PROFILER_GUI__MAIN_WINDOW__H
336