1 /************************************************************************
2 * file name         : arbitrary_value_inspector.h
3 * ----------------- :
4 * creation time     : 2017/11/30
5 * author            : Victor Zarubkin
6 * email             : v.s.zarubkin@gmail.com
7 * ----------------- :
8 * description       : The file contains declaration of .
9 * ----------------- :
10 * change log        : * 2017/11/30 Victor Zarubkin: initial commit.
11 *                   :
12 *                   : *
13 * ----------------- :
14 * license           : Lightweight profiler library for c++
15 *                   : Copyright(C) 2016-2017  Sergey Yagovtsev, Victor Zarubkin
16 *                   :
17 *                   : Licensed under either of
18 *                   :     * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
19 *                   :     * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
20 *                   : at your option.
21 *                   :
22 *                   : The MIT License
23 *                   :
24 *                   : Permission is hereby granted, free of charge, to any person obtaining a copy
25 *                   : of this software and associated documentation files (the "Software"), to deal
26 *                   : in the Software without restriction, including without limitation the rights
27 *                   : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28 *                   : of the Software, and to permit persons to whom the Software is furnished
29 *                   : to do so, subject to the following conditions:
30 *                   :
31 *                   : The above copyright notice and this permission notice shall be included in all
32 *                   : copies or substantial portions of the Software.
33 *                   :
34 *                   : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
35 *                   : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 *                   : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
37 *                   : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
38 *                   : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
39 *                   : USE OR OTHER DEALINGS IN THE SOFTWARE.
40 *                   :
41 *                   : The Apache License, Version 2.0 (the "License")
42 *                   :
43 *                   : You may not use this file except in compliance with the License.
44 *                   : You may obtain a copy of the License at
45 *                   :
46 *                   : http://www.apache.org/licenses/LICENSE-2.0
47 *                   :
48 *                   : Unless required by applicable law or agreed to in writing, software
49 *                   : distributed under the License is distributed on an "AS IS" BASIS,
50 *                   : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51 *                   : See the License for the specific language governing permissions and
52 *                   : limitations under the License.
53 ************************************************************************/
54 
55 #ifndef EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H
56 #define EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H
57 
58 #include <QWidget>
59 #include <QTreeWidget>
60 #include <QTreeWidgetItem>
61 #include <QGraphicsItem>
62 #include <QGraphicsView>
63 #include <QTimer>
64 #include <QPointF>
65 #include <QList>
66 #include <easy/serialized_block.h>
67 #include <easy/reader.h>
68 #include <easy/utility.h>
69 #include <unordered_map>
70 #include <vector>
71 #include <string>
72 #include <thread>
73 #include <atomic>
74 #include <memory>
75 
76 //////////////////////////////////////////////////////////////////////////
77 
78 using Points = std::vector<QPointF>;
79 using ArbitraryValues = std::vector<const profiler::ArbitraryValue*>;
80 using ArbitraryValuesMap = std::unordered_map<profiler::thread_id_t, ArbitraryValues, estd::hash<profiler::thread_id_t> >;
81 
82 class ArbitraryValuesCollection EASY_FINAL
83 {
84 public:
85 
86     enum JobStatus : uint8_t { Idle = 0, Ready, InProgress };
87     enum JobType : uint8_t { None = 0, ValuesJob = 1 << 0, PointsJob = 1 << 1 };
88 
89 private:
90 
91     using This = ArbitraryValuesCollection;
92 
93     ArbitraryValuesMap          m_values;
94     Points                      m_points;
95     std::thread        m_collectorThread;
96     profiler::timestamp_t    m_beginTime;
97     qreal                     m_minValue;
98     qreal                     m_maxValue;
99     std::atomic<uint8_t>        m_status;
100     std::atomic_bool        m_bInterrupt;
101     uint8_t                    m_jobType;
102 
103 public:
104 
105     explicit ArbitraryValuesCollection();
106     ~ArbitraryValuesCollection();
107 
108     const ArbitraryValuesMap& valuesMap() const;
109     const Points& points() const;
110     JobStatus status() const;
111     size_t size() const;
112 
113     qreal minValue() const;
114     qreal maxValue() const;
115 
116     void collectValues(profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName);
117     void collectValues(profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName, profiler::timestamp_t _beginTime);
118     bool calculatePoints(profiler::timestamp_t _beginTime);
119     void interrupt();
120 
121 private:
122 
123     void setStatus(JobStatus _status);
124     void collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId);
125     void collectByName(profiler::thread_id_t _threadId, const std::string _valueName);
126     bool collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::vin_t _valueId, bool _calculatePoints);
127     bool collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot, const std::string& _valueName, bool _calculatePoints);
128 
129     QPointF point(const profiler::ArbitraryValue& _value) const;
130 
131 }; // end of class ArbitraryValuesCollection.
132 
133 enum class ChartType : uint8_t
134 {
135     Line = 0,
136     Points
137 };
138 
139 struct EasyCollectionPaintData EASY_FINAL
140 {
141     const ArbitraryValuesCollection* ptr;
142     QRgb                           color;
143     ChartType                  chartType;
144     bool                        selected;
145 };
146 
147 using Collections = std::vector<EasyCollectionPaintData>;
148 
149 //////////////////////////////////////////////////////////////////////////
150 
151 class EasyArbitraryValuesChartItem : public QGraphicsItem
152 {
153     using Parent = QGraphicsItem;
154     using This = EasyArbitraryValuesChartItem;
155 
156     Collections m_collections;
157     QRectF     m_boundingRect;
158 
159 public:
160 
161     explicit EasyArbitraryValuesChartItem();
162     ~EasyArbitraryValuesChartItem() override;
163 
164     void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
165 
166     QRectF boundingRect() const override;
167     void setBoundingRect(const QRectF& _rect);
168     void setBoundingRect(qreal _left, qreal _top, qreal _width, qreal _height);
169 
170     void update(Collections _collections);
171     void update(const ArbitraryValuesCollection* _selected);
172 
173 }; // end of class EasyArbitraryValuesChartItem.
174 
175 class EasyGraphicsChart : public QGraphicsView
176 {
177     Q_OBJECT
178 
179 private:
180 
181     using Parent = QGraphicsView;
182     using This = EasyGraphicsChart;
183 
184     EasyArbitraryValuesChartItem* m_chartItem;
185     qreal               m_left;
186     qreal              m_right;
187     qreal             m_offset;
188     qreal             m_xscale;
189     qreal m_visibleRegionWidth;
190     bool           m_bBindMode;
191 
192 public:
193 
194     explicit EasyGraphicsChart(QWidget* _parent = nullptr);
195     ~EasyGraphicsChart() override;
196 
197     void resizeEvent(QResizeEvent* _event) override;
198 
199     void clear();
200 
201     bool bindMode() const;
202     qreal xscale() const;
203 
204     qreal left() const;
205     qreal right() const;
206     qreal range() const;
207     qreal offset() const;
208     qreal region() const;
209 
210     void setOffset(qreal _offset);
211     void setRange(qreal _left, qreal _right);
212     void setRegion(qreal _visibleRegionWidth);
213 
214     void update(Collections _collections);
215     void update(const ArbitraryValuesCollection* _selected);
216 
217 private slots:
218 
219     void onSceneSizeChanged();
220     void onWindowSizeChanged(qreal _width, qreal _height);
221 
222 }; // end of class EasyGraphicsChart.
223 
224 //////////////////////////////////////////////////////////////////////////
225 
226 class EasyArbitraryTreeWidgetItem : public QTreeWidgetItem
227 {
228     using Parent = QTreeWidgetItem;
229     using This = EasyArbitraryTreeWidgetItem;
230     using CollectionPtr = std::unique_ptr<ArbitraryValuesCollection>;
231 
232     CollectionPtr   m_collection;
233     profiler::vin_t        m_vin;
234     profiler::color_t    m_color;
235     int              m_widthHint;
236 
237 public:
238 
239     explicit EasyArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, profiler::color_t _color, profiler::vin_t _vin = 0);
240     ~EasyArbitraryTreeWidgetItem() override;
241 
242     QVariant data(int _column, int _role) const override;
243 
244     void setWidthHint(int _width);
245 
246     const ArbitraryValuesCollection* collection() const;
247     void collectValues(profiler::thread_id_t _threadId);
248     void interrupt();
249 
250     profiler::color_t color() const;
251 
252 }; // end of class EasyArbitraryTreeWidgetItem.
253 
254 //////////////////////////////////////////////////////////////////////////
255 
256 class EasyArbitraryValuesWidget : public QWidget
257 {
258     Q_OBJECT
259 
260     using Parent = QWidget;
261     using This = EasyArbitraryValuesWidget;
262 
263     QTimer                  m_timer;
264     QTimer       m_collectionsTimer;
265     QList<EasyArbitraryTreeWidgetItem*> m_checkedItems;
266     QTreeWidget*       m_treeWidget;
267     EasyGraphicsChart*      m_chart;
268 
269 public:
270 
271     explicit EasyArbitraryValuesWidget(QWidget* _parent = nullptr);
272     ~EasyArbitraryValuesWidget() override;
273 
274     void clear();
275 
276 public slots:
277 
278     void rebuild();
279 
280 private slots:
281 
282     void onSelectedThreadChanged(profiler::thread_id_t _id);
283     void onSelectedBlockChanged(uint32_t _block_index);
284     void onSelectedBlockIdChanged(profiler::block_id_t _id);
285     void onItemDoubleClicked(QTreeWidgetItem* _item, int _column);
286     void onItemChanged(QTreeWidgetItem* _item, int _column);
287     void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*);
288     void onCollectionsTimeout();
289 
290 private:
291 
292     void buildTree(profiler::thread_id_t _threadId, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId);
293     QTreeWidgetItem* buildTreeForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId);
294 
295 }; // end of class EasyArbitraryValuesWidget.
296 
297 //////////////////////////////////////////////////////////////////////////
298 
299 #endif // EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H
300