1 /************************************************************************ 2 * file name : blocks_graphics_view.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 GraphicsScene and GraphicsView and 9 * : it's auxiliary classes for displyaing easy_profiler blocks tree. 10 * ----------------- : 11 * change log : * 2016/06/26 Victor Zarubkin: moved sources from graphics_view.h 12 * : and renamed classes from My* to Prof*. 13 * : 14 * : * 2016/06/29 Victor Zarubkin: Highly optimized painting performance and memory consumption. 15 * : 16 * : * 2016/06/30 Victor Zarubkin: Replaced doubles with floats (in ProfBlockItem) for less memory consumption. 17 * : 18 * : * 2016/09/15 Victor Zarubkin: Moved sources of EasyGraphicsItem and EasyChronometerItem to separate files. 19 * : 20 * : * 21 * ----------------- : 22 * license : Lightweight profiler library for c++ 23 * : Copyright(C) 2016-2017 Sergey Yagovtsev, Victor Zarubkin 24 * : 25 * : Licensed under either of 26 * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) 27 * : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0) 28 * : at your option. 29 * : 30 * : The MIT License 31 * : 32 * : Permission is hereby granted, free of charge, to any person obtaining a copy 33 * : of this software and associated documentation files (the "Software"), to deal 34 * : in the Software without restriction, including without limitation the rights 35 * : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 36 * : of the Software, and to permit persons to whom the Software is furnished 37 * : to do so, subject to the following conditions: 38 * : 39 * : The above copyright notice and this permission notice shall be included in all 40 * : copies or substantial portions of the Software. 41 * : 42 * : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 43 * : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 44 * : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 45 * : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 46 * : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 47 * : USE OR OTHER DEALINGS IN THE SOFTWARE. 48 * : 49 * : The Apache License, Version 2.0 (the "License") 50 * : 51 * : You may not use this file except in compliance with the License. 52 * : You may obtain a copy of the License at 53 * : 54 * : http://www.apache.org/licenses/LICENSE-2.0 55 * : 56 * : Unless required by applicable law or agreed to in writing, software 57 * : distributed under the License is distributed on an "AS IS" BASIS, 58 * : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 59 * : See the License for the specific language governing permissions and 60 * : limitations under the License. 61 ************************************************************************/ 62 63 #ifndef EASY_GRAPHICS_VIEW_H 64 #define EASY_GRAPHICS_VIEW_H 65 66 #include <stdlib.h> 67 #include <unordered_set> 68 69 #include <QGraphicsView> 70 #include <QGraphicsItem> 71 #include <QPoint> 72 #include <QRectF> 73 #include <QTimer> 74 #include <QLabel> 75 76 #include <easy/reader.h> 77 78 #include "common_functions.h" 79 80 ////////////////////////////////////////////////////////////////////////// 81 ////////////////////////////////////////////////////////////////////////// 82 83 class QGraphicsProxyWidget; 84 class EasyGraphicsView; 85 class EasyGraphicsItem; 86 class EasyGraphicsScrollbar; 87 class EasyChronometerItem; 88 89 ////////////////////////////////////////////////////////////////////////// 90 91 #define EASY_QGRAPHICSITEM(ClassName) \ 92 class ClassName : public QGraphicsItem { \ 93 QRectF m_boundingRect; \ 94 public: \ 95 ClassName() : QGraphicsItem() {} \ 96 virtual ~ClassName() {} \ 97 void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override; \ 98 QRectF boundingRect() const override { return m_boundingRect; } \ 99 void setBoundingRect(qreal x, qreal y, qreal w, qreal h) { m_boundingRect.setRect(x, y, w, h); } \ 100 void setBoundingRect(const QRectF& _rect) { m_boundingRect = _rect; } \ 101 } 102 103 EASY_QGRAPHICSITEM(EasyBackgroundItem); 104 EASY_QGRAPHICSITEM(EasyTimelineIndicatorItem); 105 EASY_QGRAPHICSITEM(EasyThreadNameItem); 106 107 #undef EASY_QGRAPHICSITEM 108 109 ////////////////////////////////////////////////////////////////////////// 110 111 struct EasyBoldLabel : public QLabel { 112 EasyBoldLabel(const QString& _text, QWidget* _parent = nullptr); 113 virtual ~EasyBoldLabel(); 114 }; 115 116 ////////////////////////////////////////////////////////////////////////// 117 118 class EasyGraphicsView : public QGraphicsView 119 { 120 Q_OBJECT 121 122 private: 123 124 using Parent = QGraphicsView; 125 using This = EasyGraphicsView; 126 using Items = ::std::vector<EasyGraphicsItem*>; 127 //using Keys = ::std::unordered_set<int, ::estd::hash<int> >; 128 129 Items m_items; ///< Array of all EasyGraphicsItem items 130 //Keys m_keys; ///< Pressed keyboard keys 131 ::profiler_gui::TreeBlocks m_selectedBlocks; ///< Array of items which were selected by selection zone (EasyChronometerItem) 132 QTimer m_flickerTimer; ///< Timer for flicking behavior 133 QTimer m_idleTimer; ///< 134 QRectF m_visibleSceneRect; ///< Visible scene rectangle 135 ::profiler::timestamp_t m_beginTime; ///< Begin time of profiler session. Used to reduce values of all begin and end times of profiler blocks. 136 qreal m_sceneWidth; ///< 137 qreal m_scale; ///< Current scale 138 qreal m_offset; ///< Have to use manual offset for all scene content instead of using scrollbars because QScrollBar::value is 32-bit integer :( 139 qreal m_timelineStep; ///< 140 uint64_t m_idleTime; ///< 141 QPoint m_mousePressPos; ///< Last mouse global position (used by mousePressEvent and mouseMoveEvent) 142 QPoint m_mouseMovePath; ///< Mouse move path between press and release of any button 143 Qt::MouseButtons m_mouseButtons; ///< Pressed mouse buttons 144 EasyGraphicsScrollbar* m_pScrollbar; ///< Pointer to the graphics scrollbar widget 145 EasyChronometerItem* m_chronometerItem; ///< Pointer to the EasyChronometerItem which is displayed when you press right mouse button and move mouse left or right. This item is used to select blocks to display in tree widget. 146 EasyChronometerItem* m_chronometerItemAux; ///< Pointer to the EasyChronometerItem which is displayed when you double click left mouse button and move mouse left or right. This item is used only to measure time. 147 QGraphicsProxyWidget* m_popupWidget; ///< 148 int m_flickerSpeedX; ///< Current flicking speed x 149 int m_flickerSpeedY; ///< Current flicking speed y 150 int m_flickerCounterX; 151 int m_flickerCounterY; 152 bool m_bDoubleClick; ///< Is mouse buttons double clicked 153 bool m_bUpdatingRect; ///< Stub flag which is used to avoid excess calculations on some scene update (flicking, scaling and so on) 154 bool m_bEmpty; ///< Indicates whether scene is empty and has no items 155 156 public: 157 158 explicit EasyGraphicsView(QWidget* _parent = nullptr); 159 virtual ~EasyGraphicsView(); 160 161 // Public virtual methods 162 163 void wheelEvent(QWheelEvent* _event) override; 164 void mousePressEvent(QMouseEvent* _event) override; 165 void mouseDoubleClickEvent(QMouseEvent* _event) override; 166 void mouseReleaseEvent(QMouseEvent* _event) override; 167 void mouseMoveEvent(QMouseEvent* _event) override; 168 void keyPressEvent(QKeyEvent* _event) override; 169 void keyReleaseEvent(QKeyEvent* _event) override; 170 void resizeEvent(QResizeEvent* _event) override; 171 dragEnterEvent(QDragEnterEvent *)172 void dragEnterEvent(QDragEnterEvent*) override {} 173 174 public: 175 176 // Public non-virtual methods 177 178 qreal sceneWidth() const; 179 qreal chronoTime() const; 180 qreal chronoTimeAux() const; 181 182 void setScrollbar(EasyGraphicsScrollbar* _scrollbar); 183 void clear(); 184 185 void setTree(const ::profiler::thread_blocks_tree_t& _blocksTree); 186 187 const Items& getItems() const; 188 189 signals: 190 191 // Signals 192 193 void sceneUpdated(); 194 void treeChanged(); 195 void intervalChanged(const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _session_begin_time, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict); 196 197 private: 198 199 // Private non-virtual methods 200 201 void removePopup(bool _removeFromScene = false); 202 203 EasyChronometerItem* createChronometer(bool _main = true); 204 bool moveChrono(EasyChronometerItem* _chronometerItem, qreal _mouseX); 205 void initMode(); 206 int updateVisibleSceneRect(); 207 void updateTimelineStep(qreal _windowWidth); 208 void scaleTo(qreal _scale); 209 void scrollTo(const EasyGraphicsItem* _item); 210 void onWheel(qreal _mouseX, int _wheelDelta); 211 qreal setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, uint32_t& _maxDepthChild, qreal _y, short _level); 212 213 private slots: 214 215 // Private Slots 216 217 void repaintScene(); 218 void onGraphicsScrollbarWheel(qreal _mouseX, int _wheelDelta); 219 void onScrollbarValueChange(int); 220 void onGraphicsScrollbarValueChange(qreal); 221 void onFlickerTimeout(); 222 void onIdleTimeout(); 223 void onHierarchyFlagChange(bool _value); 224 void onSelectedThreadChange(::profiler::thread_id_t _id); 225 void onSelectedBlockChange(unsigned int _block_index); 226 void onRefreshRequired(); 227 void onThreadViewChanged(); 228 229 public: 230 231 // Public inline methods 232 scale()233 inline qreal scale() const 234 { 235 return m_scale; 236 } 237 offset()238 inline qreal offset() const 239 { 240 return m_offset; 241 } 242 visibleSceneRect()243 inline const QRectF& visibleSceneRect() const 244 { 245 return m_visibleSceneRect; 246 } 247 timelineStep()248 inline qreal timelineStep() const 249 { 250 return m_timelineStep; 251 } 252 time2position(const profiler::timestamp_t & _time)253 inline qreal time2position(const profiler::timestamp_t& _time) const 254 { 255 return PROF_MICROSECONDS(qreal(_time - m_beginTime)); 256 //return PROF_MILLISECONDS(qreal(_time - m_beginTime)); 257 } 258 position2time(qreal _pos)259 inline ::profiler::timestamp_t position2time(qreal _pos) const 260 { 261 return PROF_FROM_MICROSECONDS(_pos); 262 //return PROF_FROM_MILLISECONDS(_pos); 263 } 264 265 }; // END of class EasyGraphicsView. 266 267 ////////////////////////////////////////////////////////////////////////// 268 269 class EasyThreadNamesWidget : public QGraphicsView 270 { 271 Q_OBJECT 272 273 private: 274 275 typedef QGraphicsView Parent; 276 typedef EasyThreadNamesWidget This; 277 278 QTimer m_idleTimer; ///< 279 uint64_t m_idleTime; ///< 280 EasyGraphicsView* m_view; ///< 281 QGraphicsProxyWidget* m_popupWidget; ///< 282 int m_maxLength; ///< 283 const int m_additionalHeight; ///< 284 285 public: 286 287 explicit EasyThreadNamesWidget(EasyGraphicsView* _view, int _additionalHeight, QWidget* _parent = nullptr); 288 virtual ~EasyThreadNamesWidget(); 289 290 void mousePressEvent(QMouseEvent* _event) override; 291 void mouseDoubleClickEvent(QMouseEvent* _event) override; 292 void mouseReleaseEvent(QMouseEvent* _event) override; 293 void mouseMoveEvent(QMouseEvent* _event) override; 294 void keyPressEvent(QKeyEvent* _event) override; 295 void keyReleaseEvent(QKeyEvent* _event) override; 296 void wheelEvent(QWheelEvent* _event) override; 297 dragEnterEvent(QDragEnterEvent *)298 void dragEnterEvent(QDragEnterEvent*) override {} 299 300 void clear(); 301 view()302 const EasyGraphicsView* view() const 303 { 304 return m_view; 305 } 306 307 private: 308 309 void removePopup(bool _removeFromScene = false); 310 311 private slots: 312 313 void setVerticalScrollbarRange(int _minValue, int _maxValue); 314 void onTreeChange(); 315 void onIdleTimeout(); 316 void repaintScene(); 317 318 }; // END of class EasyThreadNamesWidget. 319 320 ////////////////////////////////////////////////////////////////////////// 321 322 class EasyGraphicsViewWidget : public QWidget 323 { 324 Q_OBJECT 325 326 private: 327 328 EasyGraphicsScrollbar* m_scrollbar; 329 EasyGraphicsView* m_view; 330 EasyThreadNamesWidget* m_threadNamesWidget; 331 332 public: 333 334 explicit EasyGraphicsViewWidget(QWidget* _parent = nullptr); 335 virtual ~EasyGraphicsViewWidget(); 336 337 EasyGraphicsView* view(); 338 void clear(); 339 340 private: 341 342 void initWidget(); 343 344 }; // END of class EasyGraphicsViewWidget. 345 346 ////////////////////////////////////////////////////////////////////////// 347 ////////////////////////////////////////////////////////////////////////// 348 349 #endif // EASY_GRAPHICS_VIEW_H 350