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