easy_graphics_scrollbar.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /************************************************************************
  2. * file name : easy_graphics_scrollbar.h
  3. * ----------------- :
  4. * creation time : 2016/07/04
  5. * author : Victor Zarubkin
  6. * email : [email protected]
  7. * ----------------- :
  8. * description : This file contains declaration of
  9. * ----------------- :
  10. * change log : * 2016/07/04 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. #ifndef EASY__GRAPHICS_SCROLLBAR__H
  55. #define EASY__GRAPHICS_SCROLLBAR__H
  56. #include <stdlib.h>
  57. #include <thread>
  58. #include <atomic>
  59. #include <QGraphicsView>
  60. #include <QGraphicsRectItem>
  61. #include <QAction>
  62. #include <QPolygonF>
  63. #include <QImage>
  64. #include "easy_qtimer.h"
  65. #include "common_types.h"
  66. //////////////////////////////////////////////////////////////////////////
  67. // TODO: use profiler_core/spin_lock.h
  68. #define EASY_GUI_USE_CRITICAL_SECTION // Use CRITICAL_SECTION instead of std::atomic_flag
  69. #if defined(_WIN32) && defined(EASY_GUI_USE_CRITICAL_SECTION)
  70. namespace profiler_gui {
  71. // std::atomic_flag on Windows works slower than critical section, so we will use it instead of std::atomic_flag...
  72. // By the way, Windows critical sections are slower than std::atomic_flag on Unix.
  73. class spin_lock { void* m_lock; public:
  74. void lock();
  75. void unlock();
  76. spin_lock();
  77. ~spin_lock();
  78. };
  79. #else
  80. namespace profiler_gui {
  81. // std::atomic_flag on Unix works fine and very fast (almost instant!)
  82. class spin_lock {
  83. ::std::atomic_flag m_lock; public:
  84. void lock() {
  85. while (m_lock.test_and_set(::std::memory_order_acquire));
  86. }
  87. void unlock() {
  88. m_lock.clear(::std::memory_order_release);
  89. }
  90. spin_lock() {
  91. m_lock.clear();
  92. }
  93. };
  94. #endif
  95. } // END of namespace profiler_gui.
  96. //////////////////////////////////////////////////////////////////////////
  97. class EasyGraphicsSliderItem : public QGraphicsRectItem
  98. {
  99. typedef QGraphicsRectItem Parent;
  100. typedef EasyGraphicsSliderItem This;
  101. private:
  102. QPolygonF m_indicator;
  103. qreal m_halfwidth;
  104. bool m_bMain;
  105. public:
  106. explicit EasyGraphicsSliderItem(bool _main);
  107. virtual ~EasyGraphicsSliderItem();
  108. void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
  109. qreal width() const;
  110. qreal halfwidth() const;
  111. void setWidth(qreal _width);
  112. void setHalfwidth(qreal _halfwidth);
  113. void setColor(QRgb _color);
  114. void setColor(const QColor& _color);
  115. }; // END of class EasyGraphicsSliderItem.
  116. //////////////////////////////////////////////////////////////////////////
  117. class EasyHistogramItem : public QGraphicsItem
  118. {
  119. typedef QGraphicsItem Parent;
  120. typedef EasyHistogramItem This;
  121. public:
  122. enum HistRegime : uint8_t { Hist_Pointer, Hist_Id };
  123. private:
  124. QRectF m_boundingRect;
  125. qreal m_topDuration;
  126. qreal m_bottomDuration;
  127. qreal m_maxDuration;
  128. qreal m_minDuration;
  129. qreal m_mouseY;
  130. qreal m_imageOrigin;
  131. qreal m_imageScale;
  132. qreal m_imageOriginUpdate;
  133. qreal m_imageScaleUpdate;
  134. qreal m_workerImageOrigin;
  135. qreal m_workerImageScale;
  136. qreal m_workerTopDuration;
  137. qreal m_workerBottomDuration;
  138. ::profiler::timestamp_t m_blockTotalDuraion;
  139. QString m_topDurationStr;
  140. QString m_bottomDurationStr;
  141. QString m_threadName;
  142. QString m_blockName;
  143. ::profiler::BlocksTree::children_t m_selectedBlocks;
  144. QImage m_mainImage;
  145. EasyQTimer m_timer;
  146. EasyQTimer m_boundaryTimer;
  147. ::std::thread m_workerThread;
  148. ::profiler::timestamp_t m_threadDuration;
  149. ::profiler::timestamp_t m_threadProfiledTime;
  150. ::profiler::timestamp_t m_threadWaitTime;
  151. const ::profiler_gui::EasyItems* m_pSource;
  152. QImage* m_workerImage;
  153. const ::profiler::BlocksTreeRoot* m_pProfilerThread;
  154. ::profiler::thread_id_t m_threadId;
  155. ::profiler::block_index_t m_blockId;
  156. int m_timeouts;
  157. ::profiler_gui::TimeUnits m_timeUnits;
  158. HistRegime m_regime;
  159. bool m_bPermitImageUpdate; ///< Is false when m_workerThread is parsing input dataset (when setSource(_block_id) is called)
  160. ::profiler_gui::spin_lock m_spin;
  161. ::std::atomic_bool m_bReady;
  162. public:
  163. explicit EasyHistogramItem();
  164. virtual ~EasyHistogramItem();
  165. // Public virtual methods
  166. QRectF boundingRect() const override;
  167. void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
  168. public:
  169. // Public non-virtual methods
  170. ::profiler::thread_id_t threadId() const;
  171. void setBoundingRect(const QRectF& _rect);
  172. void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
  173. void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items);
  174. void setSource(::profiler::thread_id_t _thread_id, ::profiler::block_id_t _block_id);
  175. void rebuildSource(HistRegime _regime);
  176. void rebuildSource();
  177. void validateName();
  178. void updateImage();
  179. void cancelImageUpdate();
  180. void pickTopBoundary(qreal _y);
  181. void increaseTopBoundary();
  182. void decreaseTopBoundary();
  183. void pickBottomBoundary(qreal _y);
  184. void increaseBottomBoundary();
  185. void decreaseBottomBoundary();
  186. void setMouseY(qreal _mouseY);
  187. void pickFrameTime(qreal _y) const;
  188. void onValueChanged();
  189. void onModeChanged();
  190. private:
  191. void paintBusyIndicator(QPainter* _painter, qreal _current_scale);
  192. void paintMouseIndicator(QPainter* _painter, qreal _top, qreal _bottom, qreal _width, qreal _height, qreal _top_width, qreal _mouse_y, qreal _delta_time, int _font_h);
  193. void paintByPtr(QPainter* _painter);
  194. void paintById(QPainter* _painter);
  195. void onTimeout();
  196. void updateImage(QRectF _boundingRect, HistRegime _regime, qreal _current_scale,
  197. qreal _minimum, qreal _maximum, qreal _range,
  198. qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, bool _bindMode,
  199. float _frame_time, ::profiler::timestamp_t _begin_time, qreal _origin, bool _autoAdjustHist);
  200. }; // END of class EasyHistogramItem.
  201. //////////////////////////////////////////////////////////////////////////
  202. class EasyGraphicsScrollbar : public QGraphicsView
  203. {
  204. Q_OBJECT
  205. private:
  206. typedef QGraphicsView Parent;
  207. typedef EasyGraphicsScrollbar This;
  208. qreal m_minimumValue;
  209. qreal m_maximumValue;
  210. qreal m_value;
  211. qreal m_windowScale;
  212. QPoint m_mousePressPos;
  213. Qt::MouseButtons m_mouseButtons;
  214. EasyGraphicsSliderItem* m_slider;
  215. EasyGraphicsSliderItem* m_chronometerIndicator;
  216. EasyHistogramItem* m_histogramItem;
  217. int m_defaultFontHeight;
  218. bool m_bScrolling;
  219. bool m_bBindMode;
  220. bool m_bLocked;
  221. public:
  222. explicit EasyGraphicsScrollbar(QWidget* _parent = nullptr);
  223. virtual ~EasyGraphicsScrollbar();
  224. // Public virtual methods
  225. void mousePressEvent(QMouseEvent* _event) override;
  226. void mouseReleaseEvent(QMouseEvent* _event) override;
  227. void mouseMoveEvent(QMouseEvent* _event) override;
  228. void wheelEvent(QWheelEvent* _event) override;
  229. void resizeEvent(QResizeEvent* _event) override;
  230. void dragEnterEvent(QDragEnterEvent*) override {}
  231. public:
  232. // Public non-virtual methods
  233. void clear();
  234. bool bindMode() const;
  235. qreal getWindowScale() const;
  236. ::profiler::thread_id_t hystThread() const;
  237. qreal minimum() const;
  238. qreal maximum() const;
  239. qreal range() const;
  240. qreal value() const;
  241. qreal sliderWidth() const;
  242. qreal sliderHalfWidth() const;
  243. int defaultFontHeight() const;
  244. void setValue(qreal _value);
  245. void setRange(qreal _minValue, qreal _maxValue);
  246. void setSliderWidth(qreal _width);
  247. void setChronoPos(qreal _left, qreal _right);
  248. void showChrono();
  249. void hideChrono();
  250. void setHistogramSource(::profiler::thread_id_t _thread_id, const::profiler_gui::EasyItems* _items);
  251. void setHistogramSource(::profiler::thread_id_t _thread_id, ::profiler::block_id_t _block_id);
  252. inline void setHistogramSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems& _items)
  253. {
  254. setHistogramSource(_thread_id, &_items);
  255. }
  256. inline void lock()
  257. {
  258. m_bLocked = true;
  259. }
  260. inline void unlock()
  261. {
  262. m_bLocked = false;
  263. }
  264. signals:
  265. void rangeChanged();
  266. void valueChanged(qreal _value);
  267. void wheeled(qreal _mouseX, int _wheelDelta);
  268. private slots:
  269. void onThreadViewChanged();
  270. void onWindowWidthChange(qreal _width);
  271. }; // END of class EasyGraphicsScrollbar.
  272. //////////////////////////////////////////////////////////////////////////
  273. #endif // EASY__GRAPHICS_SCROLLBAR__H