/************************************************************************ * file name : arbitrary_value_inspector.h * ----------------- : * creation time : 2017/11/30 * author : Victor Zarubkin * email : v.s.zarubkin@gmail.com * ----------------- : * description : The file contains declaration of . * ----------------- : * change log : * 2017/11/30 Victor Zarubkin: initial commit. * : * : * * ----------------- : * license : Lightweight profiler library for c++ * : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin * : * : Licensed under either of * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0) * : at your option. * : * : The MIT License * : * : Permission is hereby granted, free of charge, to any person obtaining a copy * : of this software and associated documentation files (the "Software"), to deal * : in the Software without restriction, including without limitation the rights * : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * : of the Software, and to permit persons to whom the Software is furnished * : to do so, subject to the following conditions: * : * : The above copyright notice and this permission notice shall be included in all * : copies or substantial portions of the Software. * : * : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * : USE OR OTHER DEALINGS IN THE SOFTWARE. * : * : The Apache License, Version 2.0 (the "License") * : * : You may not use this file except in compliance with the License. * : You may obtain a copy of the License at * : * : http://www.apache.org/licenses/LICENSE-2.0 * : * : Unless required by applicable law or agreed to in writing, software * : distributed under the License is distributed on an "AS IS" BASIS, * : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * : See the License for the specific language governing permissions and * : limitations under the License. ************************************************************************/ #ifndef EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H #define EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "graphics_slider_area.h" #include "thread_pool_task.h" ////////////////////////////////////////////////////////////////////////// using Points = std::vector; using ArbitraryValues = std::vector; using ArbitraryValuesMap = std::unordered_map >; using Durations = std::vector; using ComplexityValuesMap = std::map; enum class ChartType : uint8_t { Regular = 0, ///< Regular chart; X axis = time, Y axis = value Complexity ///< Complexity chart; X axis = value, Y axis = duration }; enum class ComplexityType : uint8_t { Constant = 0, ///< O(1) Logarithmic, ///< O(logN) Linear, ///< O(N) Quasilinear, ///< O(N*logN) Quadratic, ///< O(N^2) Cubic, ///< O(N^3) Exponential, ///< O(2^N) Factorial, ///< O(N!) }; enum class ChartPenStyle : uint8_t { Line = 0, Points }; class ArbitraryValuesCollection EASY_FINAL { public: enum JobStatus : uint8_t { Idle = 0, Ready, InProgress }; enum JobType : uint8_t { None = 0, ValuesJob = 1 << 0, PointsJob = 1 << 1 }; private: using This = ArbitraryValuesCollection; ArbitraryValuesMap m_values; ComplexityValuesMap m_complexityMap; Points m_points; ThreadPoolTask m_worker; profiler::timestamp_t m_beginTime; profiler::timestamp_t m_minDuration; profiler::timestamp_t m_maxDuration; qreal m_minValue; qreal m_maxValue; std::atomic m_status; std::atomic_bool m_bInterrupt; ChartType m_chartType; uint8_t m_jobType; public: explicit ArbitraryValuesCollection(); ~ArbitraryValuesCollection(); ChartType chartType() const; const ArbitraryValuesMap& valuesMap() const; const ComplexityValuesMap& complexityMap() const; const Points& points() const; JobStatus status() const; size_t size() const; profiler::timestamp_t minDuration() const; profiler::timestamp_t maxDuration() const; qreal minValue() const; qreal maxValue() const; void collectValues(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName, profiler::block_id_t _parentBlockId, bool _directParent); bool calculatePoints(profiler::timestamp_t _beginTime); void collectValuesAndPoints(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName, profiler::timestamp_t _beginTime, profiler::block_id_t _parentBlockId, bool _directParent); void interrupt(); private: void setStatus(JobStatus _status); void collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId, profiler::block_id_t _parentBlockId, bool _directParent); void collectByName(profiler::thread_id_t _threadId, const std::string _valueName, profiler::block_id_t _parentBlockId, bool _directParent); bool collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::vin_t _valueId, bool _calculatePoints, profiler::block_id_t _parentBlockId, bool _directParent); bool collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot, const std::string& _valueName, bool _calculatePoints, profiler::block_id_t _parentBlockId, bool _directParent); bool depthFirstSearch(const profiler::BlocksTreeRoot& _threadRoot, bool _calculatePoints , profiler::block_id_t _parentBlockId, bool _directParent, std::function _isSuitableValue); double addPoint(const profiler::ArbitraryValue& _value); QPointF point(const profiler::ArbitraryValue& _value) const; }; // end of class ArbitraryValuesCollection. struct CollectionPaintData EASY_FINAL { const ArbitraryValuesCollection* ptr; QRgb color; ChartPenStyle chartPenStyle; bool selected; }; using Collections = std::vector; ////////////////////////////////////////////////////////////////////////// class ArbitraryValuesChartItem : public GraphicsImageItem { using Parent = GraphicsImageItem; using This = ArbitraryValuesChartItem; Collections m_collections; qreal m_workerMaxValue; qreal m_workerMinValue; profiler::timestamp_t m_workerMaxDuration; profiler::timestamp_t m_workerMinDuration; profiler::timestamp_t m_maxDuration; profiler::timestamp_t m_minDuration; ChartType m_chartType; public: explicit ArbitraryValuesChartItem(); ~ArbitraryValuesChartItem() override; void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) override; bool updateImage() override; protected: void onImageUpdated() override; public: void clear(); void update(Collections _collections); void update(const ArbitraryValuesCollection* _selected); void setChartType(ChartType _chartType); ChartType chartType() const; private: void paintMouseIndicator(QPainter* _painter, qreal _top, qreal _bottom, qreal _width, qreal _height, int _font_h, qreal _visibleRegionLeft, qreal _visibleRegionWidth); void updateRegularImageAsync(QRectF _boundingRect, qreal _current_scale, qreal _minimum, qreal _maximum , qreal _range, qreal _value, qreal _width, bool _bindMode, profiler::timestamp_t _begin_time, bool _autoAdjust); void updateComplexityImageAsync(QRectF _boundingRect, qreal _current_scale, qreal _minimum, qreal _maximum , qreal _range, qreal _value, qreal _width, bool _bindMode, profiler::timestamp_t _begin_time, bool _autoAdjust); void drawGrid(QPainter& _painter, int _width, int _height) const; }; // end of class ArbitraryValuesChartItem. class GraphicsChart : public GraphicsSliderArea { Q_OBJECT private: using Parent = GraphicsSliderArea; using This = GraphicsChart; ArbitraryValuesChartItem* m_chartItem; qreal m_left; qreal m_right; qreal m_offset; qreal m_xscale; qreal m_visibleRegionWidth; bool m_bBindMode; public: explicit GraphicsChart(QWidget* _parent = nullptr); ~GraphicsChart() override; void clear() override; public: void cancelImageUpdate(); void update(Collections _collections); void update(const ArbitraryValuesCollection* _selected); void setChartType(ChartType _chartType); ChartType chartType() const; private slots: void onAutoAdjustChartChanged(); }; // end of class GraphicsChart. ////////////////////////////////////////////////////////////////////////// class ArbitraryTreeWidgetItem : public QTreeWidgetItem { using Parent = QTreeWidgetItem; using This = ArbitraryTreeWidgetItem; using CollectionPtr = std::unique_ptr; QFont m_font; CollectionPtr m_collection; profiler::vin_t m_vin; profiler::color_t m_color; int m_widthHint; public: explicit ArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, profiler::color_t _color, profiler::vin_t _vin = 0); ~ArbitraryTreeWidgetItem() override; QVariant data(int _column, int _role) const override; void setWidthHint(int _width); void setBold(bool _isBold); const ArbitraryValuesCollection* collection() const; ArbitraryValuesCollection* collection(); void collectValues(profiler::thread_id_t _threadId, ChartType _chartType); void interrupt(); profiler::color_t color() const; }; // end of class ArbitraryTreeWidgetItem. ////////////////////////////////////////////////////////////////////////// class ArbitraryValuesWidget : public QWidget { Q_OBJECT using Parent = QWidget; using This = ArbitraryValuesWidget; QTimer m_collectionsTimer; QList m_checkedItems; class QSplitter* m_splitter; QTreeWidget* m_treeWidget; GraphicsChart* m_chart; ArbitraryTreeWidgetItem* m_boldItem; public: explicit ArbitraryValuesWidget(QWidget* _parent = nullptr); ~ArbitraryValuesWidget() override; void contextMenuEvent(QContextMenuEvent*) override {} public slots: void clear(); void rebuild(); private slots: void onSelectedBlockChanged(uint32_t _block_index); void onSelectedBlockIdChanged(profiler::block_id_t _id); void onItemDoubleClicked(QTreeWidgetItem* _item, int _column); void onItemChanged(QTreeWidgetItem* _item, int _column); void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); void onCollectionsTimeout(); void onRegularChartTypeChecked(bool _checked); void onComplexityChartTypeChecked(bool _checked); private: void repaint(); void buildTree(profiler::thread_id_t _threadId, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId); QTreeWidgetItem* buildTreeForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::block_index_t _blockIndex, profiler::block_id_t _blockId); void loadSettings(); void saveSettings(); }; // end of class ArbitraryValuesWidget. ////////////////////////////////////////////////////////////////////////// #endif // EASY_PROFILER_GUI_ARBITRARY_VALUE_INSPECTOR_H