mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 00:31:02 +08:00
Release 2.0 further work. Intermediate commit.
This commit is contained in:
parent
9cd1f62fce
commit
694497b5ca
@ -141,6 +141,7 @@ set(INCLUDE_FILES
|
|||||||
${EASY_INCLUDE_DIR}/easy_socket.h
|
${EASY_INCLUDE_DIR}/easy_socket.h
|
||||||
${EASY_INCLUDE_DIR}/profiler.h
|
${EASY_INCLUDE_DIR}/profiler.h
|
||||||
${EASY_INCLUDE_DIR}/reader.h
|
${EASY_INCLUDE_DIR}/reader.h
|
||||||
|
${EASY_INCLUDE_DIR}/utility.h
|
||||||
${EASY_INCLUDE_DIR}/serialized_block.h
|
${EASY_INCLUDE_DIR}/serialized_block.h
|
||||||
${EASY_INCLUDE_DIR}/details/arbitrary_value_aux.h
|
${EASY_INCLUDE_DIR}/details/arbitrary_value_aux.h
|
||||||
${EASY_INCLUDE_DIR}/details/arbitrary_value_public_types.h
|
${EASY_INCLUDE_DIR}/details/arbitrary_value_public_types.h
|
||||||
|
@ -126,13 +126,13 @@
|
|||||||
//extern ProfileManager& MANAGER;
|
//extern ProfileManager& MANAGER;
|
||||||
#define MANAGER ProfileManager::instance()
|
#define MANAGER ProfileManager::instance()
|
||||||
|
|
||||||
extern const ::profiler::color_t EASY_COLOR_INTERNAL_EVENT;
|
extern const profiler::color_t EASY_COLOR_INTERNAL_EVENT;
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
::std::atomic<uint64_t> TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL);
|
std::atomic<uint64_t> TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL);
|
||||||
char KERNEL_LOGGER[] = KERNEL_LOGGER_NAME;
|
char KERNEL_LOGGER[] = KERNEL_LOGGER_NAME;
|
||||||
#else
|
#else
|
||||||
::std::atomic_uint64_t TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL);
|
std::atomic_uint64_t TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,7 +171,7 @@ namespace profiler {
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ProcessInfo {
|
struct ProcessInfo {
|
||||||
std::string name;
|
::std::string name;
|
||||||
processid_t id = 0;
|
processid_t id = 0;
|
||||||
int8_t valid = 0;
|
int8_t valid = 0;
|
||||||
};
|
};
|
||||||
@ -205,12 +205,12 @@ namespace profiler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ::std::unordered_map<decltype(CSwitch::NewThreadId), ProcessInfo*, do_not_calc_hash> thread_process_info_map;
|
using thread_process_info_map = ::std::unordered_map<decltype(CSwitch::NewThreadId), ProcessInfo*, do_not_calc_hash>;
|
||||||
typedef ::std::unordered_map<processid_t, ProcessInfo, do_not_calc_hash> process_info_map;
|
using process_info_map = ::std::unordered_map<processid_t, ProcessInfo, do_not_calc_hash>;
|
||||||
|
|
||||||
// Using static is safe because processTraceEvent() is called from one thread
|
// Using static is safe because processTraceEvent() is called from one thread
|
||||||
process_info_map PROCESS_INFO_TABLE;
|
process_info_map PROCESS_INFO_TABLE;
|
||||||
thread_process_info_map THREAD_PROCESS_INFO_TABLE = ([](){ thread_process_info_map initial; initial[0U] = nullptr; return ::std::move(initial); })();
|
thread_process_info_map THREAD_PROCESS_INFO_TABLE = ([] { thread_process_info_map initial; initial[0U] = nullptr; return ::std::move(initial); })();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -23,7 +23,13 @@ namespace estd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T> struct hash EASY_FINAL : public ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))> {
|
template <class T> struct hash EASY_FINAL : public ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))> {
|
||||||
using ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))>::operator();
|
using Parent = ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))>;
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1910
|
||||||
|
// TODO: Try to compile "using Parent::operator();" in MSVC 2017
|
||||||
|
size_t operator () (typename Parent::type value) const { return Parent::operator () (value); }
|
||||||
|
#else
|
||||||
|
using Parent::operator();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T> struct hash<T*> EASY_FINAL {
|
template <class T> struct hash<T*> EASY_FINAL {
|
||||||
|
@ -484,8 +484,8 @@ extern "C" {
|
|||||||
|
|
||||||
int64_t file_cpu_frequency = 0LL;
|
int64_t file_cpu_frequency = 0LL;
|
||||||
inFile.read((char*)&file_cpu_frequency, sizeof(int64_t));
|
inFile.read((char*)&file_cpu_frequency, sizeof(int64_t));
|
||||||
uint64_t cpu_frequency = file_cpu_frequency;
|
const uint64_t cpu_frequency = file_cpu_frequency;
|
||||||
const double conversion_factor = static_cast<double>(TIME_FACTOR) / static_cast<double>(cpu_frequency);
|
const double conversion_factor = (cpu_frequency != 0 ? static_cast<double>(TIME_FACTOR) / static_cast<double>(cpu_frequency) : 1.);
|
||||||
|
|
||||||
::profiler::timestamp_t begin_time = 0ULL;
|
::profiler::timestamp_t begin_time = 0ULL;
|
||||||
::profiler::timestamp_t end_time = 0ULL;
|
::profiler::timestamp_t end_time = 0ULL;
|
||||||
@ -749,7 +749,7 @@ extern "C" {
|
|||||||
/**/
|
/**/
|
||||||
EASY_BLOCK("Find children", ::profiler::colors::Blue);
|
EASY_BLOCK("Find children", ::profiler::colors::Blue);
|
||||||
auto rlower1 = ++root.children.rbegin();
|
auto rlower1 = ++root.children.rbegin();
|
||||||
for (; rlower1 != root.children.rend() && !(mt0 > blocks[*rlower1].node->begin()); ++rlower1);
|
for (; rlower1 != root.children.rend() && mt0 <= blocks[*rlower1].node->begin(); ++rlower1);
|
||||||
auto lower = rlower1.base();
|
auto lower = rlower1.base();
|
||||||
::std::move(lower, root.children.end(), ::std::back_inserter(tree.children));
|
::std::move(lower, root.children.end(), ::std::back_inserter(tree.children));
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ if (Qt5Widgets_FOUND)
|
|||||||
globals.h
|
globals.h
|
||||||
globals.cpp
|
globals.cpp
|
||||||
globals_qobjects.cpp
|
globals_qobjects.cpp
|
||||||
|
graphics_image_item.h
|
||||||
|
graphics_image_item.cpp
|
||||||
|
graphics_slider_area.h
|
||||||
|
graphics_slider_area.cpp
|
||||||
main_window.h
|
main_window.h
|
||||||
main_window.cpp
|
main_window.cpp
|
||||||
tree_widget_item.h
|
tree_widget_item.h
|
||||||
|
@ -881,7 +881,7 @@ void EasyGraphicsView::mousePressEvent(QMouseEvent* _event)
|
|||||||
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
|
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
|
||||||
m_chronometerItem->setLeftRight(mouseX, mouseX);
|
m_chronometerItem->setLeftRight(mouseX, mouseX);
|
||||||
m_chronometerItem->hide();
|
m_chronometerItem->hide();
|
||||||
m_pScrollbar->hideChrono();
|
m_pScrollbar->hideSelectionIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,7 +932,7 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
|
|||||||
if (m_chronometerItem->isVisible() && m_chronometerItem->width() < 1e-6)
|
if (m_chronometerItem->isVisible() && m_chronometerItem->width() < 1e-6)
|
||||||
{
|
{
|
||||||
m_chronometerItem->hide();
|
m_chronometerItem->hide();
|
||||||
m_pScrollbar->hideChrono();
|
m_pScrollbar->hideSelectionIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_selectedBlocks.empty())
|
if (!m_selectedBlocks.empty())
|
||||||
@ -1144,11 +1144,11 @@ void EasyGraphicsView::mouseMoveEvent(QMouseEvent* _event)
|
|||||||
if (m_mouseButtons & Qt::RightButton)
|
if (m_mouseButtons & Qt::RightButton)
|
||||||
{
|
{
|
||||||
bool showItem = moveChrono(m_chronometerItem, x);
|
bool showItem = moveChrono(m_chronometerItem, x);
|
||||||
m_pScrollbar->setChronoPos(m_chronometerItem->left(), m_chronometerItem->right());
|
m_pScrollbar->setSelectionPos(m_chronometerItem->left(), m_chronometerItem->right());
|
||||||
|
|
||||||
if (showItem)
|
if (showItem)
|
||||||
{
|
{
|
||||||
m_pScrollbar->showChrono();
|
m_pScrollbar->showSelectionIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
needUpdate = true;
|
needUpdate = true;
|
||||||
@ -2006,7 +2006,7 @@ void EasyGraphicsView::onRefreshRequired()
|
|||||||
|
|
||||||
EasyGraphicsViewWidget::EasyGraphicsViewWidget(QWidget* _parent)
|
EasyGraphicsViewWidget::EasyGraphicsViewWidget(QWidget* _parent)
|
||||||
: QWidget(_parent)
|
: QWidget(_parent)
|
||||||
, m_scrollbar(new EasyGraphicsScrollbar(this))
|
, m_scrollbar(new EasyGraphicsScrollbar(true, 85 + (QFontMetrics(font()).height() << 1), this))
|
||||||
, m_view(new EasyGraphicsView(this))
|
, m_view(new EasyGraphicsView(this))
|
||||||
, m_threadNamesWidget(new EasyThreadNamesWidget(m_view, m_scrollbar->height(), this))
|
, m_threadNamesWidget(new EasyThreadNamesWidget(m_view, m_scrollbar->height(), this))
|
||||||
{
|
{
|
||||||
|
@ -77,8 +77,8 @@ class EasyTreeWidget : public QTreeWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
typedef QTreeWidget Parent;
|
using Parent = QTreeWidget;
|
||||||
typedef EasyTreeWidget This;
|
using This = EasyTreeWidget;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -100,9 +100,10 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
explicit EasyTreeWidget(QWidget* _parent = nullptr);
|
explicit EasyTreeWidget(QWidget* _parent = nullptr);
|
||||||
virtual ~EasyTreeWidget();
|
~EasyTreeWidget() override;
|
||||||
|
|
||||||
void contextMenuEvent(QContextMenuEvent* _event) override;
|
void contextMenuEvent(QContextMenuEvent* _event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent*) override {}
|
||||||
|
|
||||||
void clearSilent(bool _global = false);
|
void clearSilent(bool _global = false);
|
||||||
int findNext(const QString& _str, Qt::MatchFlags _flags);
|
int findNext(const QString& _str, Qt::MatchFlags _flags);
|
||||||
@ -167,8 +168,8 @@ class EasyHierarchyWidget : public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
typedef QWidget Parent;
|
using Parent = QWidget;
|
||||||
typedef EasyHierarchyWidget This;
|
using This = EasyHierarchyWidget;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -183,9 +184,11 @@ public:
|
|||||||
// Public virtual methods
|
// Public virtual methods
|
||||||
|
|
||||||
explicit EasyHierarchyWidget(QWidget* _parent = nullptr);
|
explicit EasyHierarchyWidget(QWidget* _parent = nullptr);
|
||||||
virtual ~EasyHierarchyWidget();
|
~EasyHierarchyWidget() override;
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent* _event) override;
|
void keyPressEvent(QKeyEvent* _event) override;
|
||||||
void contextMenuEvent(QContextMenuEvent* _event) override;
|
void contextMenuEvent(QContextMenuEvent* _event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent*) override {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@
|
|||||||
|
|
||||||
class EasyFPSGraphicsItem : public QGraphicsItem
|
class EasyFPSGraphicsItem : public QGraphicsItem
|
||||||
{
|
{
|
||||||
typedef QGraphicsItem Parent;
|
using Parent = QGraphicsItem;
|
||||||
typedef EasyFPSGraphicsItem This;
|
using This = EasyFPSGraphicsItem;
|
||||||
typedef std::deque<std::pair<uint32_t, uint32_t> > FrameTimes;
|
using FrameTimes = std::deque<std::pair<uint32_t, uint32_t> >;
|
||||||
|
|
||||||
std::vector<QPointF> m_points1, m_points2;
|
std::vector<QPointF> m_points1, m_points2;
|
||||||
FrameTimes m_frames;
|
FrameTimes m_frames;
|
||||||
@ -78,10 +78,10 @@ class EasyFPSGraphicsItem : public QGraphicsItem
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
explicit EasyFPSGraphicsItem();
|
explicit EasyFPSGraphicsItem();
|
||||||
virtual ~EasyFPSGraphicsItem();
|
~EasyFPSGraphicsItem() override;
|
||||||
|
|
||||||
QRectF boundingRect() const override;
|
QRectF boundingRect() const override;
|
||||||
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
|
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) override;
|
||||||
|
|
||||||
void setBoundingRect(const QRectF& _boundingRect);
|
void setBoundingRect(const QRectF& _boundingRect);
|
||||||
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
|
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
|
||||||
@ -99,20 +99,21 @@ class EasyFrameRateViewer : public QGraphicsView
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef QGraphicsView Parent;
|
using Parent = QGraphicsView;
|
||||||
typedef EasyFrameRateViewer This;
|
using This = EasyFrameRateViewer;
|
||||||
|
|
||||||
EasyFPSGraphicsItem* m_fpsItem;
|
EasyFPSGraphicsItem* m_fpsItem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit EasyFrameRateViewer(QWidget* _parent = nullptr);
|
explicit EasyFrameRateViewer(QWidget* _parent = nullptr);
|
||||||
virtual ~EasyFrameRateViewer();
|
~EasyFrameRateViewer() override;
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* _event) override;
|
void resizeEvent(QResizeEvent* _event) override;
|
||||||
void hideEvent(QHideEvent* _event) override;
|
void hideEvent(QHideEvent* _event) override;
|
||||||
void showEvent(QShowEvent* _event) override;
|
void showEvent(QShowEvent* _event) override;
|
||||||
void contextMenuEvent(QContextMenuEvent* _event) override;
|
void contextMenuEvent(QContextMenuEvent* _event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent*) override {}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -58,88 +58,16 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <QGraphicsView>
|
|
||||||
#include <QGraphicsRectItem>
|
|
||||||
#include <QAction>
|
|
||||||
#include <QPolygonF>
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include "easy_qtimer.h"
|
#include "easy_qtimer.h"
|
||||||
#include "common_types.h"
|
#include "graphics_slider_area.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO: use profiler_core/spin_lock.h
|
class GraphicsHistogramItem : public GraphicsImageItem
|
||||||
|
|
||||||
#define EASY_GUI_USE_CRITICAL_SECTION // Use CRITICAL_SECTION instead of std::atomic_flag
|
|
||||||
#if defined(_WIN32) && defined(EASY_GUI_USE_CRITICAL_SECTION)
|
|
||||||
namespace profiler_gui {
|
|
||||||
// std::atomic_flag on Windows works slower than critical section, so we will use it instead of std::atomic_flag...
|
|
||||||
// By the way, Windows critical sections are slower than std::atomic_flag on Unix.
|
|
||||||
class spin_lock { void* m_lock; public:
|
|
||||||
void lock();
|
|
||||||
void unlock();
|
|
||||||
spin_lock();
|
|
||||||
~spin_lock();
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
namespace profiler_gui {
|
|
||||||
// std::atomic_flag on Unix works fine and very fast (almost instant!)
|
|
||||||
class spin_lock {
|
|
||||||
::std::atomic_flag m_lock; public:
|
|
||||||
|
|
||||||
void lock() {
|
|
||||||
while (m_lock.test_and_set(::std::memory_order_acquire));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock() {
|
|
||||||
m_lock.clear(::std::memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock() {
|
|
||||||
m_lock.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // END of namespace profiler_gui.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class EasyGraphicsSliderItem : public QGraphicsRectItem
|
|
||||||
{
|
{
|
||||||
typedef QGraphicsRectItem Parent;
|
using Parent = GraphicsImageItem;
|
||||||
typedef EasyGraphicsSliderItem This;
|
using This = GraphicsHistogramItem;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
QPolygonF m_indicator;
|
|
||||||
qreal m_halfwidth;
|
|
||||||
bool m_bMain;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit EasyGraphicsSliderItem(bool _main);
|
|
||||||
virtual ~EasyGraphicsSliderItem();
|
|
||||||
|
|
||||||
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
|
|
||||||
|
|
||||||
qreal width() const;
|
|
||||||
qreal halfwidth() const;
|
|
||||||
|
|
||||||
void setWidth(qreal _width);
|
|
||||||
void setHalfwidth(qreal _halfwidth);
|
|
||||||
|
|
||||||
void setColor(QRgb _color);
|
|
||||||
void setColor(const QColor& _color);
|
|
||||||
|
|
||||||
}; // END of class EasyGraphicsSliderItem.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class EasyHistogramItem : public QGraphicsItem
|
|
||||||
{
|
|
||||||
typedef QGraphicsItem Parent;
|
|
||||||
typedef EasyHistogramItem This;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -147,193 +75,108 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QRectF m_boundingRect;
|
qreal m_workerTopDuration;
|
||||||
qreal m_topDuration;
|
qreal m_workerBottomDuration;
|
||||||
qreal m_bottomDuration;
|
profiler::timestamp_t m_blockTotalDuraion;
|
||||||
qreal m_maxDuration;
|
QString m_topDurationStr;
|
||||||
qreal m_minDuration;
|
QString m_bottomDurationStr;
|
||||||
qreal m_mouseY;
|
QString m_threadName;
|
||||||
qreal m_imageOrigin;
|
QString m_blockName;
|
||||||
qreal m_imageScale;
|
profiler::BlocksTree::children_t m_selectedBlocks;
|
||||||
qreal m_imageOriginUpdate;
|
profiler::timestamp_t m_threadDuration;
|
||||||
qreal m_imageScaleUpdate;
|
profiler::timestamp_t m_threadProfiledTime;
|
||||||
qreal m_workerImageOrigin;
|
profiler::timestamp_t m_threadWaitTime;
|
||||||
qreal m_workerImageScale;
|
const profiler_gui::EasyItems* m_pSource;
|
||||||
qreal m_workerTopDuration;
|
const profiler::BlocksTreeRoot* m_pProfilerThread;
|
||||||
qreal m_workerBottomDuration;
|
profiler::thread_id_t m_threadId;
|
||||||
::profiler::timestamp_t m_blockTotalDuraion;
|
profiler::block_index_t m_blockId;
|
||||||
QString m_topDurationStr;
|
profiler_gui::TimeUnits m_timeUnits;
|
||||||
QString m_bottomDurationStr;
|
HistRegime m_regime;
|
||||||
QString m_threadName;
|
|
||||||
QString m_blockName;
|
|
||||||
::profiler::BlocksTree::children_t m_selectedBlocks;
|
|
||||||
QImage m_mainImage;
|
|
||||||
EasyQTimer m_timer;
|
|
||||||
EasyQTimer m_boundaryTimer;
|
|
||||||
::std::thread m_workerThread;
|
|
||||||
::profiler::timestamp_t m_threadDuration;
|
|
||||||
::profiler::timestamp_t m_threadProfiledTime;
|
|
||||||
::profiler::timestamp_t m_threadWaitTime;
|
|
||||||
const ::profiler_gui::EasyItems* m_pSource;
|
|
||||||
QImage* m_workerImage;
|
|
||||||
const ::profiler::BlocksTreeRoot* m_pProfilerThread;
|
|
||||||
::profiler::thread_id_t m_threadId;
|
|
||||||
::profiler::block_index_t m_blockId;
|
|
||||||
int m_timeouts;
|
|
||||||
::profiler_gui::TimeUnits m_timeUnits;
|
|
||||||
HistRegime m_regime;
|
|
||||||
bool m_bPermitImageUpdate; ///< Is false when m_workerThread is parsing input dataset (when setSource(_block_id) is called)
|
|
||||||
::profiler_gui::spin_lock m_spin;
|
|
||||||
::std::atomic_bool m_bReady;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit EasyHistogramItem();
|
explicit GraphicsHistogramItem();
|
||||||
virtual ~EasyHistogramItem();
|
~GraphicsHistogramItem() override;
|
||||||
|
|
||||||
// Public virtual methods
|
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) override;
|
||||||
|
|
||||||
QRectF boundingRect() const override;
|
bool updateImage() override;
|
||||||
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
|
void onImageUpdated() override;
|
||||||
|
|
||||||
|
bool pickTopValue() override;
|
||||||
|
bool increaseTopValue() override;
|
||||||
|
bool decreaseTopValue() override;
|
||||||
|
|
||||||
|
bool pickBottomValue() override;
|
||||||
|
bool increaseBottomValue() override;
|
||||||
|
bool decreaseBottomValue() override;
|
||||||
|
|
||||||
|
void onModeChanged() override;
|
||||||
|
void onValueChanged() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Public non-virtual methods
|
// Public non-virtual methods
|
||||||
|
|
||||||
::profiler::thread_id_t threadId() const;
|
profiler::thread_id_t threadId() const;
|
||||||
|
|
||||||
void setBoundingRect(const QRectF& _rect);
|
void setSource(profiler::thread_id_t _thread_id, const profiler_gui::EasyItems* _items);
|
||||||
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
|
void setSource(profiler::thread_id_t _thread_id, profiler::block_id_t _block_id);
|
||||||
|
|
||||||
void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items);
|
|
||||||
void setSource(::profiler::thread_id_t _thread_id, ::profiler::block_id_t _block_id);
|
|
||||||
void rebuildSource(HistRegime _regime);
|
void rebuildSource(HistRegime _regime);
|
||||||
void rebuildSource();
|
void rebuildSource();
|
||||||
void validateName();
|
void validateName();
|
||||||
void updateImage();
|
|
||||||
void cancelImageUpdate();
|
|
||||||
|
|
||||||
void pickTopBoundary(qreal _y);
|
|
||||||
void increaseTopBoundary();
|
|
||||||
void decreaseTopBoundary();
|
|
||||||
|
|
||||||
void pickBottomBoundary(qreal _y);
|
|
||||||
void increaseBottomBoundary();
|
|
||||||
void decreaseBottomBoundary();
|
|
||||||
|
|
||||||
void setMouseY(qreal _mouseY);
|
|
||||||
void pickFrameTime(qreal _y) const;
|
void pickFrameTime(qreal _y) const;
|
||||||
|
|
||||||
void onValueChanged();
|
|
||||||
void onModeChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void paintBusyIndicator(QPainter* _painter, qreal _current_scale);
|
|
||||||
void paintMouseIndicator(QPainter* _painter, qreal _top, qreal _bottom, qreal _width, qreal _height, qreal _top_width, qreal _mouse_y, qreal _delta_time, int _font_h);
|
void paintMouseIndicator(QPainter* _painter, qreal _top, qreal _bottom, qreal _width, qreal _height, qreal _top_width, qreal _mouse_y, qreal _delta_time, int _font_h);
|
||||||
void paintByPtr(QPainter* _painter);
|
void paintByPtr(QPainter* _painter);
|
||||||
void paintById(QPainter* _painter);
|
void paintById(QPainter* _painter);
|
||||||
void onTimeout();
|
|
||||||
void updateImage(QRectF _boundingRect, HistRegime _regime, qreal _current_scale,
|
|
||||||
qreal _minimum, qreal _maximum, qreal _range,
|
|
||||||
qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, bool _bindMode,
|
|
||||||
float _frame_time, ::profiler::timestamp_t _begin_time, qreal _origin, bool _autoAdjustHist);
|
|
||||||
|
|
||||||
}; // END of class EasyHistogramItem.
|
void updateImageAsync(QRectF _boundingRect, HistRegime _regime, qreal _current_scale,
|
||||||
|
qreal _minimum, qreal _maximum, qreal _range,
|
||||||
|
qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, bool _bindMode,
|
||||||
|
float _frame_time, profiler::timestamp_t _begin_time, bool _autoAdjustHist);
|
||||||
|
|
||||||
|
}; // END of class GraphicsHistogramItem.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class EasyGraphicsScrollbar : public QGraphicsView
|
class EasyGraphicsScrollbar : public GraphicsSliderArea
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef QGraphicsView Parent;
|
using Parent = GraphicsSliderArea;
|
||||||
typedef EasyGraphicsScrollbar This;
|
using This = EasyGraphicsScrollbar;
|
||||||
|
|
||||||
qreal m_minimumValue;
|
GraphicsHistogramItem* m_histogramItem = nullptr;
|
||||||
qreal m_maximumValue;
|
|
||||||
qreal m_value;
|
|
||||||
qreal m_windowScale;
|
|
||||||
QPoint m_mousePressPos;
|
|
||||||
Qt::MouseButtons m_mouseButtons;
|
|
||||||
EasyGraphicsSliderItem* m_slider;
|
|
||||||
EasyGraphicsSliderItem* m_chronometerIndicator;
|
|
||||||
EasyHistogramItem* m_histogramItem;
|
|
||||||
int m_defaultFontHeight;
|
|
||||||
bool m_bScrolling;
|
|
||||||
bool m_bBindMode;
|
|
||||||
bool m_bLocked;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit EasyGraphicsScrollbar(QWidget* _parent = nullptr);
|
explicit EasyGraphicsScrollbar(bool _fixedHeight, int _height, QWidget* _parent = nullptr);
|
||||||
virtual ~EasyGraphicsScrollbar();
|
~EasyGraphicsScrollbar() override;
|
||||||
|
|
||||||
// Public virtual methods
|
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
void mousePressEvent(QMouseEvent* _event) override;
|
void mousePressEvent(QMouseEvent* _event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent* _event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent* _event) override;
|
|
||||||
void wheelEvent(QWheelEvent* _event) override;
|
|
||||||
void resizeEvent(QResizeEvent* _event) override;
|
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent*) override {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Public non-virtual methods
|
// Public non-virtual methods
|
||||||
|
|
||||||
void clear();
|
profiler::thread_id_t hystThread() const;
|
||||||
|
|
||||||
bool bindMode() const;
|
void setHistogramSource(profiler::thread_id_t _thread_id, const profiler_gui::EasyItems* _items);
|
||||||
qreal getWindowScale() const;
|
void setHistogramSource(profiler::thread_id_t _thread_id, profiler::block_id_t _block_id);
|
||||||
::profiler::thread_id_t hystThread() const;
|
void setHistogramSource(profiler::thread_id_t _thread_id, const profiler_gui::EasyItems& _items) {
|
||||||
|
|
||||||
qreal minimum() const;
|
|
||||||
qreal maximum() const;
|
|
||||||
qreal range() const;
|
|
||||||
qreal value() const;
|
|
||||||
qreal sliderWidth() const;
|
|
||||||
qreal sliderHalfWidth() const;
|
|
||||||
int defaultFontHeight() const;
|
|
||||||
|
|
||||||
void setValue(qreal _value);
|
|
||||||
void setRange(qreal _minValue, qreal _maxValue);
|
|
||||||
void setSliderWidth(qreal _width);
|
|
||||||
void setChronoPos(qreal _left, qreal _right);
|
|
||||||
void showChrono();
|
|
||||||
void hideChrono();
|
|
||||||
|
|
||||||
void setHistogramSource(::profiler::thread_id_t _thread_id, const::profiler_gui::EasyItems* _items);
|
|
||||||
void setHistogramSource(::profiler::thread_id_t _thread_id, ::profiler::block_id_t _block_id);
|
|
||||||
|
|
||||||
inline void setHistogramSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems& _items)
|
|
||||||
{
|
|
||||||
setHistogramSource(_thread_id, &_items);
|
setHistogramSource(_thread_id, &_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lock()
|
|
||||||
{
|
|
||||||
m_bLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void unlock()
|
|
||||||
{
|
|
||||||
m_bLocked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void rangeChanged();
|
|
||||||
void valueChanged(qreal _value);
|
|
||||||
void wheeled(qreal _mouseX, int _wheelDelta);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void onThreadViewChanged();
|
void onThreadViewChanged();
|
||||||
void onWindowWidthChange(qreal _width);
|
|
||||||
|
|
||||||
}; // END of class EasyGraphicsScrollbar.
|
}; // END of class EasyGraphicsScrollbar.
|
||||||
|
|
||||||
|
@ -60,15 +60,15 @@
|
|||||||
EasyQTimer::EasyQTimer()
|
EasyQTimer::EasyQTimer()
|
||||||
: QObject()
|
: QObject()
|
||||||
{
|
{
|
||||||
connect(&m_timer, &QTimer::timeout, [this](){ m_handler(); });
|
connect(&m_timer, &QTimer::timeout, [this] { m_handler(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
EasyQTimer::EasyQTimer(::std::function<void()>&& _handler, bool _isSignleShot)
|
EasyQTimer::EasyQTimer(::std::function<void()>&& handler, bool signleShot)
|
||||||
: QObject()
|
: QObject()
|
||||||
, m_handler(::std::forward<::std::function<void()>&&>(_handler))
|
, m_handler(::std::forward<::std::function<void()>&&>(handler))
|
||||||
{
|
{
|
||||||
m_timer.setSingleShot(_isSignleShot);
|
m_timer.setSingleShot(signleShot);
|
||||||
connect(&m_timer, &QTimer::timeout, [this](){ m_handler(); });
|
connect(&m_timer, &QTimer::timeout, [this] { m_handler(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
EasyQTimer::~EasyQTimer()
|
EasyQTimer::~EasyQTimer()
|
||||||
@ -76,9 +76,47 @@ EasyQTimer::~EasyQTimer()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EasyQTimer::setHandler(::std::function<void()>&& _handler)
|
void EasyQTimer::setHandler(::std::function<void()>&& handler)
|
||||||
{
|
{
|
||||||
m_handler = _handler;
|
m_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EasyQTimer::setSignleShot(bool singleShot)
|
||||||
|
{
|
||||||
|
m_timer.setSingleShot(singleShot);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EasyQTimer::isSingleShot() const
|
||||||
|
{
|
||||||
|
return m_timer.isSingleShot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EasyQTimer::setInterval(int msec)
|
||||||
|
{
|
||||||
|
m_timer.setInterval(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EasyQTimer::start(int msec)
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
m_timer.start(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EasyQTimer::start()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
m_timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EasyQTimer::stop()
|
||||||
|
{
|
||||||
|
if (m_timer.isActive())
|
||||||
|
m_timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EasyQTimer::isActive() const
|
||||||
|
{
|
||||||
|
return m_timer.isActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -72,15 +72,20 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
EasyQTimer();
|
explicit EasyQTimer();
|
||||||
EasyQTimer(::std::function<void()>&& _handler, bool _isSignleShot = false);
|
explicit EasyQTimer(::std::function<void()>&& handler, bool signleShot = false);
|
||||||
virtual ~EasyQTimer();
|
~EasyQTimer() override;
|
||||||
|
|
||||||
void setHandler(::std::function<void()>&& _handler);
|
void setHandler(::std::function<void()>&& _handler);
|
||||||
|
|
||||||
inline void start(int msec) { m_timer.start(msec); }
|
void setSignleShot(bool singleShot);
|
||||||
inline void stop() { if (m_timer.isActive()) m_timer.stop(); }
|
bool isSingleShot() const;
|
||||||
inline bool isActive() const { return m_timer.isActive(); }
|
|
||||||
|
void setInterval(int msec);
|
||||||
|
void start(int msec);
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
bool isActive() const;
|
||||||
|
|
||||||
}; // END of class EasyQTimer.
|
}; // END of class EasyQTimer.
|
||||||
|
|
||||||
|
331
profiler_gui/graphics_image_item.cpp
Normal file
331
profiler_gui/graphics_image_item.cpp
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QPainter>
|
||||||
|
#include "graphics_image_item.h"
|
||||||
|
#include "graphics_slider_area.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
EASY_CONSTEXPR int TimerInterval = 40;
|
||||||
|
EASY_CONSTEXPR int BoundaryTimerInterval = 100;
|
||||||
|
|
||||||
|
GraphicsImageItem::GraphicsImageItem() : Parent(nullptr)
|
||||||
|
, m_boundaryTimer([this] { updateImage(); }, true)
|
||||||
|
, m_workerImage(nullptr)
|
||||||
|
, m_imageOrigin(0)
|
||||||
|
, m_imageScale(1)
|
||||||
|
, m_imageOriginUpdate(0)
|
||||||
|
, m_imageScaleUpdate(1)
|
||||||
|
, m_workerImageOrigin(0)
|
||||||
|
, m_workerImageScale(1)
|
||||||
|
, m_topValue(0)
|
||||||
|
, m_bottomValue(0)
|
||||||
|
, m_maxValue(0)
|
||||||
|
, m_minValue(0)
|
||||||
|
, m_timer(::std::bind(&This::onTimeout, this))
|
||||||
|
, m_bPermitImageUpdate(true)
|
||||||
|
{
|
||||||
|
m_bReady = ATOMIC_VAR_INIT(false);
|
||||||
|
m_boundaryTimer.setInterval(BoundaryTimerInterval);
|
||||||
|
m_timer.setInterval(TimerInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsImageItem::~GraphicsImageItem()
|
||||||
|
{
|
||||||
|
cancelAnyJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsImageItem::boundingRect() const
|
||||||
|
{
|
||||||
|
return m_boundingRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setBoundingRect(const QRectF& _rect)
|
||||||
|
{
|
||||||
|
m_boundingRect = _rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
|
||||||
|
{
|
||||||
|
m_boundingRect.setRect(x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setMousePos(const QPointF& pos)
|
||||||
|
{
|
||||||
|
m_mousePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setMousePos(qreal x, qreal y)
|
||||||
|
{
|
||||||
|
m_mousePos.setX(x);
|
||||||
|
m_mousePos.setY(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::updateImage()
|
||||||
|
{
|
||||||
|
if (!cancelImageUpdate())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
setReady(false);
|
||||||
|
startTimer();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GraphicsImageItem::onValueChanged()
|
||||||
|
{
|
||||||
|
const auto widget = qobject_cast<const GraphicsSliderArea*>(scene()->parent());
|
||||||
|
if (widget == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!widget->bindMode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_boundaryTimer.stop();
|
||||||
|
|
||||||
|
const auto sliderWidth_inv = 1.0 / widget->sliderWidth();
|
||||||
|
const auto k = widget->range() * sliderWidth_inv;
|
||||||
|
|
||||||
|
const auto deltaScale = m_imageScaleUpdate < k ? (k / m_imageScaleUpdate) : (m_imageScaleUpdate / k);
|
||||||
|
if (deltaScale > 4)
|
||||||
|
{
|
||||||
|
updateImage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto deltaOffset = (widget->value() - m_imageOriginUpdate) * sliderWidth_inv;
|
||||||
|
if (deltaOffset < 1.5 || deltaOffset > 4.5)
|
||||||
|
{
|
||||||
|
updateImage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_boundaryTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::onModeChanged()
|
||||||
|
{
|
||||||
|
if (!isImageUpdatePermitted())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_boundaryTimer.stop();
|
||||||
|
updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::onImageUpdated()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::cancelImageUpdate()
|
||||||
|
{
|
||||||
|
if (!isImageUpdatePermitted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cancelAnyJob();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::pickTopValue()
|
||||||
|
{
|
||||||
|
const auto y = m_mousePos.y();
|
||||||
|
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
|
||||||
|
{
|
||||||
|
m_topValue = m_bottomValue + (m_topValue - m_bottomValue) * (m_boundingRect.bottom() - y) / m_boundingRect.height();
|
||||||
|
m_boundaryTimer.stop();
|
||||||
|
updateImage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::increaseTopValue()
|
||||||
|
{
|
||||||
|
if (isImageUpdatePermitted() && m_topValue < m_maxValue)
|
||||||
|
{
|
||||||
|
auto step = 0.05 * (m_maxValue - m_bottomValue);
|
||||||
|
if (m_topValue < (m_bottomValue + 1.25 * step))
|
||||||
|
step = 0.1 * (m_topValue - m_bottomValue);
|
||||||
|
m_topValue = std::min(m_maxValue, m_topValue + step);
|
||||||
|
m_boundaryTimer.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::decreaseTopValue()
|
||||||
|
{
|
||||||
|
if (isImageUpdatePermitted() && m_topValue > m_bottomValue)
|
||||||
|
{
|
||||||
|
auto step = 0.05 * (m_maxValue - m_bottomValue);
|
||||||
|
if (m_topValue < (m_bottomValue + 1.25 * step))
|
||||||
|
step = std::max(0.1 * (m_topValue - m_bottomValue), 0.3);
|
||||||
|
|
||||||
|
if (m_topValue > (m_bottomValue + 1.25 * step))
|
||||||
|
{
|
||||||
|
m_topValue = std::max(m_bottomValue + step, m_topValue - step);
|
||||||
|
m_boundaryTimer.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::pickBottomValue()
|
||||||
|
{
|
||||||
|
const auto y = m_mousePos.y();
|
||||||
|
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
|
||||||
|
{
|
||||||
|
m_bottomValue = m_bottomValue + (m_topValue - m_bottomValue) * (m_boundingRect.bottom() - y) / m_boundingRect.height();
|
||||||
|
m_boundaryTimer.stop();
|
||||||
|
updateImage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::increaseBottomValue()
|
||||||
|
{
|
||||||
|
if (isImageUpdatePermitted() && m_bottomValue < m_topValue)
|
||||||
|
{
|
||||||
|
auto step = 0.05 * (m_topValue - m_minValue);
|
||||||
|
if (m_bottomValue > (m_topValue - 1.25 * step))
|
||||||
|
step = 0.1 * (m_topValue - m_bottomValue);
|
||||||
|
|
||||||
|
if (m_bottomValue < (m_topValue - 1.25 * step))
|
||||||
|
{
|
||||||
|
m_bottomValue = std::min(m_topValue - step, m_bottomValue + step);
|
||||||
|
m_boundaryTimer.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::decreaseBottomValue()
|
||||||
|
{
|
||||||
|
if (isImageUpdatePermitted() && m_bottomValue > m_minValue)
|
||||||
|
{
|
||||||
|
auto step = 0.05 * (m_topValue - m_minValue);
|
||||||
|
if (m_bottomValue > (m_topValue - 1.25 * step))
|
||||||
|
step = std::max(0.1 * (m_topValue - m_bottomValue), 0.3);
|
||||||
|
m_bottomValue = std::max(m_minValue, m_bottomValue - step);
|
||||||
|
m_boundaryTimer.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::paintImage(QPainter* _painter)
|
||||||
|
{
|
||||||
|
_painter->setPen(Qt::NoPen);
|
||||||
|
_painter->drawImage(0, m_boundingRect.top(), m_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight,
|
||||||
|
qreal _visibleRegionLeft, qreal _visibleRegionWidth)
|
||||||
|
{
|
||||||
|
const auto dscale = (_sceneRight - _sceneLeft) / (_visibleRegionWidth * m_imageScale);
|
||||||
|
|
||||||
|
_painter->setPen(Qt::NoPen);
|
||||||
|
_painter->setTransform(QTransform::fromScale(dscale, 1), true);
|
||||||
|
_painter->drawImage(QPointF {(_sceneLeft + m_imageOrigin - _visibleRegionLeft) * _scale * m_imageScale, m_boundingRect.top()}, m_image);
|
||||||
|
_painter->setTransform(QTransform::fromScale(1. / dscale, 1), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::onTimeout()
|
||||||
|
{
|
||||||
|
if (!isVisible())
|
||||||
|
{
|
||||||
|
stopTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReady())
|
||||||
|
{
|
||||||
|
stopTimer();
|
||||||
|
|
||||||
|
if (!isImageUpdatePermitted())
|
||||||
|
{
|
||||||
|
// Worker thread have finished parsing input data (when setSource(_block_id) was called)
|
||||||
|
setImageUpdatePermitted(true); // From now we can update an image
|
||||||
|
updateImage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Image updated
|
||||||
|
|
||||||
|
if (m_workerThread.joinable())
|
||||||
|
m_workerThread.join();
|
||||||
|
|
||||||
|
m_workerImage->swap(m_image);
|
||||||
|
delete m_workerImage;
|
||||||
|
m_workerImage = nullptr;
|
||||||
|
|
||||||
|
m_imageOriginUpdate = m_imageOrigin = m_workerImageOrigin;
|
||||||
|
m_imageScaleUpdate = m_imageScale = m_workerImageScale;
|
||||||
|
|
||||||
|
onImageUpdated();
|
||||||
|
scene()->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setImageUpdatePermitted(bool _permit)
|
||||||
|
{
|
||||||
|
m_bPermitImageUpdate = _permit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::isImageUpdatePermitted() const
|
||||||
|
{
|
||||||
|
return m_bPermitImageUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::cancelAnyJob()
|
||||||
|
{
|
||||||
|
setReady(true);
|
||||||
|
if (m_workerThread.joinable())
|
||||||
|
m_workerThread.join();
|
||||||
|
//setReady(false);
|
||||||
|
|
||||||
|
delete m_workerImage;
|
||||||
|
m_workerImage = nullptr;
|
||||||
|
|
||||||
|
m_imageOriginUpdate = m_imageOrigin;
|
||||||
|
m_imageScaleUpdate = m_imageScale;
|
||||||
|
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::resetTopBottomValues()
|
||||||
|
{
|
||||||
|
m_topValue = m_maxValue;
|
||||||
|
m_bottomValue = m_minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsImageItem::isReady() const
|
||||||
|
{
|
||||||
|
return m_bReady.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::setReady(bool _ready)
|
||||||
|
{
|
||||||
|
m_bReady.store(_ready, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::startTimer()
|
||||||
|
{
|
||||||
|
m_timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsImageItem::stopTimer()
|
||||||
|
{
|
||||||
|
m_timer.stop();
|
||||||
|
}
|
96
profiler_gui/graphics_image_item.h
Normal file
96
profiler_gui/graphics_image_item.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#ifndef EASY_PROFILER_GRAPHICS_IMAGE_ITEM_H
|
||||||
|
#define EASY_PROFILER_GRAPHICS_IMAGE_ITEM_H
|
||||||
|
|
||||||
|
#include <QGraphicsItem>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include "easy_qtimer.h"
|
||||||
|
|
||||||
|
class GraphicsImageItem : public QGraphicsItem
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
using Parent = QGraphicsItem;
|
||||||
|
using This = GraphicsImageItem;
|
||||||
|
|
||||||
|
QRectF m_boundingRect;
|
||||||
|
QImage m_image;
|
||||||
|
EasyQTimer m_boundaryTimer;
|
||||||
|
std::thread m_workerThread;
|
||||||
|
QPointF m_mousePos;
|
||||||
|
QImage* m_workerImage;
|
||||||
|
qreal m_imageOrigin;
|
||||||
|
qreal m_imageScale;
|
||||||
|
qreal m_imageOriginUpdate;
|
||||||
|
qreal m_imageScaleUpdate;
|
||||||
|
qreal m_workerImageOrigin;
|
||||||
|
qreal m_workerImageScale;
|
||||||
|
qreal m_topValue;
|
||||||
|
qreal m_bottomValue;
|
||||||
|
qreal m_maxValue;
|
||||||
|
qreal m_minValue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
EasyQTimer m_timer;
|
||||||
|
std::atomic_bool m_bReady;
|
||||||
|
bool m_bPermitImageUpdate; ///< Is false when m_workerThread is parsing input dataset (when setSource(_block_id) is called)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit GraphicsImageItem();
|
||||||
|
~GraphicsImageItem() override;
|
||||||
|
|
||||||
|
QRectF boundingRect() const override;
|
||||||
|
|
||||||
|
virtual bool pickTopValue();
|
||||||
|
virtual bool increaseTopValue();
|
||||||
|
virtual bool decreaseTopValue();
|
||||||
|
|
||||||
|
virtual bool pickBottomValue();
|
||||||
|
virtual bool increaseBottomValue();
|
||||||
|
virtual bool decreaseBottomValue();
|
||||||
|
|
||||||
|
virtual bool updateImage();
|
||||||
|
virtual void onModeChanged();
|
||||||
|
virtual void onValueChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void onImageUpdated();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void setMousePos(const QPointF& pos);
|
||||||
|
void setMousePos(qreal x, qreal y);
|
||||||
|
void setBoundingRect(const QRectF& _rect);
|
||||||
|
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
|
||||||
|
bool cancelImageUpdate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void paintImage(QPainter* _painter);
|
||||||
|
void paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight,
|
||||||
|
qreal _visibleRegionLeft, qreal _visibleRegionWidth);
|
||||||
|
|
||||||
|
void setImageUpdatePermitted(bool _permit);
|
||||||
|
bool isImageUpdatePermitted() const;
|
||||||
|
|
||||||
|
void cancelAnyJob();
|
||||||
|
void resetTopBottomValues();
|
||||||
|
|
||||||
|
bool isReady() const;
|
||||||
|
void setReady(bool _ready);
|
||||||
|
|
||||||
|
void startTimer();
|
||||||
|
void stopTimer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void onTimeout();
|
||||||
|
|
||||||
|
}; // end of class GraphicsImageItem.
|
||||||
|
|
||||||
|
#endif //EASY_PROFILER_GRAPHICS_IMAGE_ITEM_H
|
521
profiler_gui/graphics_slider_area.cpp
Normal file
521
profiler_gui/graphics_slider_area.cpp
Normal file
@ -0,0 +1,521 @@
|
|||||||
|
/**
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QWheelEvent>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <easy/utility.h>
|
||||||
|
#include "graphics_slider_area.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GraphicsSliderItem::GraphicsSliderItem(int _size, bool _main)
|
||||||
|
: Parent()
|
||||||
|
, m_halfwidth(0.5)
|
||||||
|
, m_bMain(_main)
|
||||||
|
{
|
||||||
|
const int sizeHalf = 1 + (_size >> 1);
|
||||||
|
|
||||||
|
if (_main)
|
||||||
|
_size = -_size;
|
||||||
|
|
||||||
|
m_indicator.reserve(3);
|
||||||
|
m_indicator.push_back(QPointF(0, 0));
|
||||||
|
m_indicator.push_back(QPointF(-sizeHalf, _size));
|
||||||
|
m_indicator.push_back(QPointF(sizeHalf, _size));
|
||||||
|
|
||||||
|
setBrush(Qt::SolidPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsSliderItem::~GraphicsSliderItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* /* _option */, QWidget* /* _widget */)
|
||||||
|
{
|
||||||
|
const auto view = static_cast<const GraphicsSliderArea*>(scene()->parent());
|
||||||
|
if (view->bindMode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto currentScale = view->getWindowScale();
|
||||||
|
const qreal w = width() * currentScale;
|
||||||
|
|
||||||
|
const auto br = rect();
|
||||||
|
const QRectF r(br.left() * currentScale, br.top() + view->margin(), w, br.height() - view->margins() - 1);
|
||||||
|
const auto r_right = r.right();
|
||||||
|
const auto r_bottom = r.bottom();
|
||||||
|
const auto b = brush();
|
||||||
|
|
||||||
|
_painter->save();
|
||||||
|
_painter->setTransform(QTransform::fromScale(1.0 / currentScale, 1), true);
|
||||||
|
_painter->setBrush(b);
|
||||||
|
|
||||||
|
if (w > 1)
|
||||||
|
{
|
||||||
|
_painter->setPen(Qt::NoPen);
|
||||||
|
_painter->drawRect(r);
|
||||||
|
|
||||||
|
// Draw left and right borders
|
||||||
|
if (m_bMain) _painter->setCompositionMode(QPainter::CompositionMode_Exclusion);
|
||||||
|
_painter->setPen(QColor::fromRgba(0xe0000000 | b.color().rgb()));
|
||||||
|
_painter->drawLine(QPointF(r.left(), r.top()), QPointF(r.left(), r_bottom));
|
||||||
|
_painter->drawLine(QPointF(r_right, r.top()), QPointF(r_right, r_bottom));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_bMain) _painter->setCompositionMode(QPainter::CompositionMode_Exclusion);
|
||||||
|
_painter->setPen(QColor::fromRgba(0xe0000000 | b.color().rgb()));
|
||||||
|
_painter->drawLine(QPointF(r.left(), r.top()), QPointF(r.left(), r_bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw triangle indicators for small slider
|
||||||
|
if (m_bMain)
|
||||||
|
_painter->setTransform(QTransform::fromTranslate(r.left() + w * 0.5, br.top() + view->margin()), true);
|
||||||
|
else
|
||||||
|
_painter->setTransform(QTransform::fromTranslate(r.left() + w * 0.5, br.bottom() - view->margin() - 1), true);
|
||||||
|
|
||||||
|
_painter->setPen(b.color().rgb());
|
||||||
|
_painter->drawPolygon(m_indicator);
|
||||||
|
|
||||||
|
_painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderItem::width() const
|
||||||
|
{
|
||||||
|
return m_halfwidth * 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderItem::halfwidth() const
|
||||||
|
{
|
||||||
|
return m_halfwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderItem::setWidth(qreal _width)
|
||||||
|
{
|
||||||
|
const auto sceneRect = scene()->sceneRect();
|
||||||
|
|
||||||
|
m_halfwidth = _width * 0.5;
|
||||||
|
setRect(-m_halfwidth, sceneRect.top(), _width, sceneRect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderItem::setHalfwidth(qreal _halfwidth)
|
||||||
|
{
|
||||||
|
const auto sceneRect = scene()->sceneRect();
|
||||||
|
|
||||||
|
m_halfwidth = _halfwidth;
|
||||||
|
setRect(-m_halfwidth, sceneRect.top(), width(), sceneRect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderItem::setColor(QRgb _color)
|
||||||
|
{
|
||||||
|
setColor(QColor::fromRgba(_color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderItem::setColor(const QColor& _color)
|
||||||
|
{
|
||||||
|
auto b = brush();
|
||||||
|
b.setColor(_color);
|
||||||
|
setBrush(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GraphicsSliderArea::GraphicsSliderArea(QWidget* _parent)
|
||||||
|
: Parent(_parent)
|
||||||
|
, m_minimumValue(0)
|
||||||
|
, m_maximumValue(500)
|
||||||
|
, m_value(10)
|
||||||
|
, m_windowScale(1)
|
||||||
|
, m_mouseButtons(Qt::NoButton)
|
||||||
|
, m_slider(nullptr)
|
||||||
|
, m_selectionIndicator(nullptr)
|
||||||
|
, m_histogramItem(nullptr)
|
||||||
|
, m_fontHeight(0)
|
||||||
|
, m_bScrolling(false)
|
||||||
|
, m_bBindMode(false)
|
||||||
|
, m_bLocked(false)
|
||||||
|
{
|
||||||
|
setCacheMode(QGraphicsView::CacheNone);
|
||||||
|
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||||
|
//setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
|
||||||
|
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
|
setOptimizationFlag(QGraphicsView::DontSavePainterState, true);
|
||||||
|
|
||||||
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
|
setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
setScene(new QGraphicsScene(this));
|
||||||
|
|
||||||
|
m_fontHeight = QFontMetrics(font()).height();
|
||||||
|
|
||||||
|
EASY_CONSTEXPR int SceneHeight = 500;
|
||||||
|
scene()->setSceneRect(0, -(SceneHeight >> 1), 500, SceneHeight);
|
||||||
|
|
||||||
|
m_histogramItem = new GraphicsHistogramItem();
|
||||||
|
scene()->addItem(m_histogramItem);
|
||||||
|
|
||||||
|
m_histogramItem->setPos(0, 0);
|
||||||
|
m_histogramItem->setBoundingRect(0, scene()->sceneRect().top() + margin(), scene()->width(), SceneHeight - margins() - 1);
|
||||||
|
m_histogramItem->hide();
|
||||||
|
|
||||||
|
m_selectionIndicator = new GraphicsSliderItem(6, false);
|
||||||
|
scene()->addItem(m_selectionIndicator);
|
||||||
|
|
||||||
|
m_selectionIndicator->setPos(0, 0);
|
||||||
|
m_selectionIndicator->setColor(0x40000000 | profiler_gui::CHRONOMETER_COLOR.rgba());
|
||||||
|
m_selectionIndicator->hide();
|
||||||
|
|
||||||
|
m_slider = new GraphicsSliderItem(6, true);
|
||||||
|
scene()->addItem(m_slider);
|
||||||
|
|
||||||
|
m_slider->setPos(0, 0);
|
||||||
|
m_slider->setColor(0x40c0c0c0);
|
||||||
|
m_slider->hide();
|
||||||
|
|
||||||
|
connect(&EASY_GLOBALS.events, &profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, this, &This::onThreadViewChanged);
|
||||||
|
connect(&EASY_GLOBALS.events, &profiler_gui::EasyGlobalSignals::hexThreadIdChanged, this, &This::onThreadViewChanged);
|
||||||
|
|
||||||
|
centerOn(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsSliderArea::~GraphicsSliderArea()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GraphicsSliderArea::clear()
|
||||||
|
{
|
||||||
|
m_selectionIndicator->hide();
|
||||||
|
setRange(0, 100);
|
||||||
|
setSliderWidth(2);
|
||||||
|
setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool GraphicsSliderArea::bindMode() const
|
||||||
|
{
|
||||||
|
return m_bBindMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::getWindowScale() const
|
||||||
|
{
|
||||||
|
return m_windowScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::minimum() const
|
||||||
|
{
|
||||||
|
return m_minimumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::maximum() const
|
||||||
|
{
|
||||||
|
return m_maximumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::range() const
|
||||||
|
{
|
||||||
|
return m_maximumValue - m_minimumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::value() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::sliderWidth() const
|
||||||
|
{
|
||||||
|
return m_slider->width();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GraphicsSliderArea::sliderHalfWidth() const
|
||||||
|
{
|
||||||
|
return m_slider->halfwidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsSliderArea::fontHeight() const
|
||||||
|
{
|
||||||
|
return m_fontHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsSliderArea::margin() const
|
||||||
|
{
|
||||||
|
return m_fontHeight + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsSliderArea::margins() const
|
||||||
|
{
|
||||||
|
return margin() << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GraphicsSliderArea::setValue(qreal _value)
|
||||||
|
{
|
||||||
|
using estd::clamp;
|
||||||
|
m_value = clamp(m_minimumValue, _value, std::max(m_minimumValue, m_maximumValue - m_slider->width()));
|
||||||
|
m_slider->setX(m_value + m_slider->halfwidth());
|
||||||
|
emit valueChanged(m_value);
|
||||||
|
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
m_imageItem->onValueChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::setRange(qreal _minValue, qreal _maxValue)
|
||||||
|
{
|
||||||
|
const auto oldRange = range();
|
||||||
|
const auto oldValue = oldRange < 1e-3 ? 0.0 : m_value / oldRange;
|
||||||
|
|
||||||
|
m_minimumValue = _minValue;
|
||||||
|
m_maximumValue = _maxValue;
|
||||||
|
const auto range = this->range();
|
||||||
|
|
||||||
|
const auto sceneRect = scene()->sceneRect();
|
||||||
|
scene()->setSceneRect(_minValue, sceneRect.top(), range, sceneRect.height());
|
||||||
|
|
||||||
|
const auto histogramRect = m_imageItem->boundingRect();
|
||||||
|
m_imageItem->cancelImageUpdate();
|
||||||
|
m_imageItem->setBoundingRect(_minValue, histogramRect.top(), range, histogramRect.height());
|
||||||
|
|
||||||
|
emit rangeChanged();
|
||||||
|
|
||||||
|
setValue(_minValue + oldValue * range);
|
||||||
|
|
||||||
|
onWindowWidthChange(width());
|
||||||
|
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
m_imageItem->updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::setSliderWidth(qreal _width)
|
||||||
|
{
|
||||||
|
m_slider->setWidth(_width);
|
||||||
|
setValue(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GraphicsSliderArea::setSelectionPos(qreal _left, qreal _right)
|
||||||
|
{
|
||||||
|
m_selectionIndicator->setWidth(_right - _left);
|
||||||
|
m_selectionIndicator->setX(_left + m_selectionIndicator->halfwidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::showSelectionIndicator()
|
||||||
|
{
|
||||||
|
if (!m_selectionIndicator->isVisible())
|
||||||
|
{
|
||||||
|
m_selectionIndicator->show();
|
||||||
|
scene()->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::hideSelectionIndicator()
|
||||||
|
{
|
||||||
|
if (m_selectionIndicator->isVisible())
|
||||||
|
{
|
||||||
|
m_selectionIndicator->hide();
|
||||||
|
scene()->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GraphicsSliderArea::mousePressEvent(QMouseEvent* _event)
|
||||||
|
{
|
||||||
|
_event->accept();
|
||||||
|
|
||||||
|
m_mouseButtons = _event->buttons();
|
||||||
|
|
||||||
|
if (m_mouseButtons & Qt::LeftButton)
|
||||||
|
{
|
||||||
|
if (_event->modifiers() & Qt::ControlModifier)
|
||||||
|
{
|
||||||
|
m_imageItem->pickBottomValue();
|
||||||
|
}
|
||||||
|
else if (_event->modifiers() & Qt::ShiftModifier)
|
||||||
|
{
|
||||||
|
m_imageItem->pickTopValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bScrolling = true;
|
||||||
|
m_mousePressPos = _event->pos();
|
||||||
|
if (!m_bBindMode)
|
||||||
|
setValue(mapToScene(m_mousePressPos).x() - m_minimumValue - m_slider->halfwidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mouseButtons & Qt::RightButton)
|
||||||
|
{
|
||||||
|
if (!_event->modifiers())
|
||||||
|
{
|
||||||
|
m_bBindMode = !m_bBindMode;
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
m_imageItem->onModeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parent::mousePressEvent(_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::mouseReleaseEvent(QMouseEvent* _event)
|
||||||
|
{
|
||||||
|
m_mouseButtons = _event->buttons();
|
||||||
|
m_bScrolling = false;
|
||||||
|
_event->accept();
|
||||||
|
//Parent::mouseReleaseEvent(_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::mouseMoveEvent(QMouseEvent* _event)
|
||||||
|
{
|
||||||
|
const auto pos = _event->pos();
|
||||||
|
|
||||||
|
if (m_mouseButtons & Qt::LeftButton)
|
||||||
|
{
|
||||||
|
const auto delta = pos - m_mousePressPos;
|
||||||
|
m_mousePressPos = pos;
|
||||||
|
|
||||||
|
if (m_bScrolling)
|
||||||
|
{
|
||||||
|
auto realScale = m_windowScale;
|
||||||
|
if (bindMode())
|
||||||
|
realScale *= -range() / sliderWidth();
|
||||||
|
setValue(m_value + delta.x() / realScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_imageItem->setMousePos(mapToScene(pos));
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
scene()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::wheelEvent(QWheelEvent* _event)
|
||||||
|
{
|
||||||
|
_event->accept();
|
||||||
|
|
||||||
|
if (_event->modifiers() & Qt::ShiftModifier)
|
||||||
|
{
|
||||||
|
// Shift + mouse wheel will change histogram top boundary
|
||||||
|
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
{
|
||||||
|
if (_event->delta() > 0)
|
||||||
|
m_imageItem->increaseTopValue();
|
||||||
|
else
|
||||||
|
m_imageItem->decreaseTopValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_event->modifiers() & Qt::ControlModifier)
|
||||||
|
{
|
||||||
|
// Ctrl + mouse wheel will change histogram bottom boundary
|
||||||
|
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
{
|
||||||
|
if (_event->delta() > 0)
|
||||||
|
m_imageItem->increaseBottomValue();
|
||||||
|
else
|
||||||
|
m_imageItem->decreaseBottomValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bindMode())
|
||||||
|
{
|
||||||
|
const auto w = m_slider->halfwidth() * (_event->delta() < 0 ? profiler_gui::SCALING_COEFFICIENT : profiler_gui::SCALING_COEFFICIENT_INV);
|
||||||
|
setValue(mapToScene(_event->pos()).x() - m_minimumValue - w);
|
||||||
|
emit wheeled(w * m_windowScale, _event->delta());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto x = (mapToScene(_event->pos()).x() - m_minimumValue) * m_windowScale;
|
||||||
|
emit wheeled(x, _event->delta());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSliderArea::resizeEvent(QResizeEvent* _event)
|
||||||
|
{
|
||||||
|
const int h = _event->size().height();
|
||||||
|
if (_event->oldSize().height() != h)
|
||||||
|
{
|
||||||
|
const int sceneHeight = h - 2;
|
||||||
|
scene()->setSceneRect(0, -(sceneHeight >> 1), 500, sceneHeight);
|
||||||
|
|
||||||
|
const auto br = m_imageItem->boundingRect();
|
||||||
|
m_imageItem->setBoundingRect(br.left(), scene()->sceneRect().top() + margin(), br.width(), sceneHeight - margins() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onWindowWidthChange(_event->size().width());
|
||||||
|
if (m_imageItem->isVisible())
|
||||||
|
m_imageItem->updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GraphicsSliderArea::onWindowWidthChange(qreal _width)
|
||||||
|
{
|
||||||
|
const auto oldScale = m_windowScale;
|
||||||
|
const auto scrollingRange = range();
|
||||||
|
|
||||||
|
if (scrollingRange < 1e-3)
|
||||||
|
{
|
||||||
|
m_windowScale = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_windowScale = _width / scrollingRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale(m_windowScale / oldScale, 1);
|
||||||
|
}
|
173
profiler_gui/graphics_slider_area.h
Normal file
173
profiler_gui/graphics_slider_area.h
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/**
|
||||||
|
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_GRAPHICS_SLIDER_AREA_H
|
||||||
|
#define EASY_PROFILER_GRAPHICS_SLIDER_AREA_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QGraphicsRectItem>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QPolygonF>
|
||||||
|
#include "common_types.h"
|
||||||
|
#include "graphics_image_item.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class GraphicsSliderItem : public QGraphicsRectItem
|
||||||
|
{
|
||||||
|
using Parent = QGraphicsRectItem;
|
||||||
|
using This = GraphicsSliderItem;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QPolygonF m_indicator;
|
||||||
|
qreal m_halfwidth;
|
||||||
|
bool m_bMain;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit GraphicsSliderItem(int _size, bool _main);
|
||||||
|
~GraphicsSliderItem() override;
|
||||||
|
|
||||||
|
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) override;
|
||||||
|
|
||||||
|
qreal width() const;
|
||||||
|
qreal halfwidth() const;
|
||||||
|
|
||||||
|
void setWidth(qreal _width);
|
||||||
|
void setHalfwidth(qreal _halfwidth);
|
||||||
|
|
||||||
|
void setColor(QRgb _color);
|
||||||
|
void setColor(const QColor& _color);
|
||||||
|
|
||||||
|
}; // END of class GraphicsSliderItem.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class GraphicsSliderArea : public QGraphicsView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Parent = QGraphicsView;
|
||||||
|
using This = GraphicsSliderArea;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
qreal m_minimumValue;
|
||||||
|
qreal m_maximumValue;
|
||||||
|
qreal m_value;
|
||||||
|
qreal m_windowScale;
|
||||||
|
QPoint m_mousePressPos;
|
||||||
|
Qt::MouseButtons m_mouseButtons;
|
||||||
|
GraphicsSliderItem* m_slider;
|
||||||
|
GraphicsSliderItem* m_selectionIndicator;
|
||||||
|
GraphicsHistogramItem* m_histogramItem;
|
||||||
|
GraphicsImageItem* m_imageItem;
|
||||||
|
int m_fontHeight;
|
||||||
|
bool m_bScrolling;
|
||||||
|
bool m_bBindMode;
|
||||||
|
bool m_bLocked;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit GraphicsSliderArea(QWidget* _parent = nullptr);
|
||||||
|
~GraphicsSliderArea() override;
|
||||||
|
|
||||||
|
// Public virtual methods
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* _event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* _event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent* _event) override;
|
||||||
|
void wheelEvent(QWheelEvent* _event) override;
|
||||||
|
void resizeEvent(QResizeEvent* _event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent*) override {}
|
||||||
|
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Public non-virtual methods
|
||||||
|
|
||||||
|
bool bindMode() const;
|
||||||
|
qreal getWindowScale() const;
|
||||||
|
|
||||||
|
qreal minimum() const;
|
||||||
|
qreal maximum() const;
|
||||||
|
qreal range() const;
|
||||||
|
qreal value() const;
|
||||||
|
qreal sliderWidth() const;
|
||||||
|
qreal sliderHalfWidth() const;
|
||||||
|
int fontHeight() const;
|
||||||
|
int margin() const;
|
||||||
|
int margins() const;
|
||||||
|
|
||||||
|
void setValue(qreal _value);
|
||||||
|
void setRange(qreal _minValue, qreal _maxValue);
|
||||||
|
void setSliderWidth(qreal _width);
|
||||||
|
void setSelectionPos(qreal _left, qreal _right);
|
||||||
|
void showSelectionIndicator();
|
||||||
|
void hideSelectionIndicator();
|
||||||
|
|
||||||
|
inline void lock() {
|
||||||
|
m_bLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void unlock() {
|
||||||
|
m_bLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void rangeChanged();
|
||||||
|
void valueChanged(qreal _value);
|
||||||
|
void wheeled(qreal _mouseX, int _wheelDelta);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
|
||||||
|
void onWindowWidthChange(qreal _width);
|
||||||
|
|
||||||
|
}; // END of class GraphicsSliderArea.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif //EASY_PROFILER_GRAPHICS_SLIDER_AREA_H
|
Loading…
x
Reference in New Issue
Block a user