diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 17b894647ed..4ec8c71ed0a 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -112,18 +112,24 @@ qint64 QmlProfilerTraceTime::duration() const void QmlProfilerTraceTime::clear() { - m_startTime = -1; - m_endTime = -1; + setStartTime(-1); + setEndTime(-1); } void QmlProfilerTraceTime::setStartTime(qint64 time) { - m_startTime = time; + if (time != m_startTime) { + m_startTime = time; + emit startTimeChanged(time); + } } void QmlProfilerTraceTime::setEndTime(qint64 time) { - m_endTime = time; + if (time != m_endTime) { + m_endTime = time; + emit endTimeChanged(time); + } } diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h index c9e2047cead..1be9abd973f 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -84,6 +84,10 @@ public: qint64 endTime() const; qint64 duration() const; +signals: + void startTimeChanged(qint64); + void endTimeChanged(qint64); + public slots: void clear(); void setStartTime(qint64 time); diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index c8f6562704d..6d7fa6a5944 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -61,15 +61,88 @@ namespace QmlProfiler { namespace Internal { ///////////////////////////////////////////////////////// +ZoomControl::ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent) : + QObject(parent), m_startTime(traceTime->startTime()), m_endTime(traceTime->endTime()), + m_windowStart(traceTime->startTime()), m_windowEnd(traceTime->endTime()), + m_traceTime(traceTime), m_windowLocked(false) +{ + connect(traceTime, SIGNAL(startTimeChanged(qint64)), this, SLOT(rebuildWindow())); + connect(traceTime, SIGNAL(endTimeChanged(qint64)), this, SLOT(rebuildWindow())); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(moveWindow())); +} + void ZoomControl::setRange(qint64 startTime, qint64 endTime) { if (m_startTime != startTime || m_endTime != endTime) { + m_timer.stop(); m_startTime = startTime; m_endTime = endTime; + rebuildWindow(); emit rangeChanged(); } } +void ZoomControl::rebuildWindow() +{ + qint64 minDuration = 1; // qMax needs equal data types, so literal 1 won't do + qint64 shownDuration = qMax(duration(), minDuration); + + qint64 oldWindowStart = m_windowStart; + qint64 oldWindowEnd = m_windowEnd; + if (m_traceTime->duration() / shownDuration < MAX_ZOOM_FACTOR) { + m_windowStart = m_traceTime->startTime(); + m_windowEnd = m_traceTime->endTime(); + } else if (windowLength() / shownDuration > MAX_ZOOM_FACTOR || + windowLength() / shownDuration * 2 < MAX_ZOOM_FACTOR) { + qint64 keep = shownDuration * MAX_ZOOM_FACTOR / 2 - shownDuration; + m_windowStart = m_startTime - keep; + if (m_windowStart < m_traceTime->startTime()) { + keep += m_traceTime->startTime() - m_windowStart; + m_windowStart = m_traceTime->startTime(); + } + + m_windowEnd = m_endTime + keep; + if (m_windowEnd > m_traceTime->endTime()) { + m_windowStart = qMax(m_traceTime->startTime(), + m_windowStart - m_windowEnd - m_traceTime->endTime()); + m_windowEnd = m_traceTime->endTime(); + } + } else { + m_timer.start(500); + } + if (oldWindowStart != m_windowStart || oldWindowEnd != m_windowEnd) + emit windowChanged(); +} + +void ZoomControl::moveWindow() +{ + if (m_windowLocked) + return; + m_timer.stop(); + + qint64 offset = (m_endTime - m_windowEnd + m_startTime - m_windowStart) / 2; + if (offset == 0 || (offset < 0 && m_windowStart == m_traceTime->startTime()) || + (offset > 0 && m_windowEnd == m_traceTime->endTime())) { + return; + } else if (offset > duration()) { + offset = (offset + duration()) / 2; + } else if (offset < -duration()) { + offset = (offset - duration()) / 2; + } + m_windowStart += offset; + if (m_windowStart < m_traceTime->startTime()) { + m_windowEnd += m_traceTime->startTime() - m_windowStart; + m_windowStart = m_traceTime->startTime(); + } + m_windowEnd += offset; + if (m_windowEnd > m_traceTime->endTime()) { + m_windowStart -= m_windowEnd - m_traceTime->endTime(); + m_windowEnd = m_traceTime->endTime(); + } + emit windowChanged(); + m_timer.start(100); +} + ///////////////////////////////////////////////////////// class QmlProfilerTraceView::QmlProfilerTraceViewPrivate { @@ -108,7 +181,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT { setObjectName(QLatin1String("QML Profiler")); - d->m_zoomControl = new ZoomControl(this); + d->m_zoomControl = new ZoomControl(modelManager->traceTime(), this); connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange())); QVBoxLayout *groupLayout = new QVBoxLayout; @@ -396,6 +469,18 @@ void QmlProfilerTraceView::resizeEvent(QResizeEvent *event) emit resized(); } +void QmlProfilerTraceView::mousePressEvent(QMouseEvent *event) +{ + d->m_zoomControl->setWindowLocked(true); + QWidget::mousePressEvent(event); +} + +void QmlProfilerTraceView::mouseReleaseEvent(QMouseEvent *event) +{ + d->m_zoomControl->setWindowLocked(false); + QWidget::mouseReleaseEvent(event); +} + //////////////////////////////////////////////////////////////// // Context menu void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.h b/src/plugins/qmlprofiler/qmlprofilertraceview.h index d6c0210c547..2203e643474 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.h +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.h @@ -30,8 +30,10 @@ #ifndef QMLPROFILERTRACEVIEW_H #define QMLPROFILERTRACEVIEW_H +#include "qmlprofilermodelmanager.h" #include #include +#include namespace Analyzer { class IAnalyzerTool; } @@ -47,19 +49,38 @@ class QmlProfilerViewManager; class ZoomControl : public QObject { Q_OBJECT public: - ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {} + static const qint64 MAX_ZOOM_FACTOR = 1 << 12; + + ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent = 0); ~ZoomControl(){} Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime); - Q_INVOKABLE qint64 startTime() { return m_startTime; } - Q_INVOKABLE qint64 endTime() { return m_endTime; } + Q_INVOKABLE qint64 startTime() const { return m_startTime; } + Q_INVOKABLE qint64 endTime() const { return m_endTime; } + Q_INVOKABLE qint64 duration() const { return m_endTime - m_startTime; } + + Q_INVOKABLE qint64 windowStart() const { return m_windowStart; } + Q_INVOKABLE qint64 windowEnd() const { return m_windowEnd; } + Q_INVOKABLE qint64 windowLength() const { return m_windowEnd - m_windowStart; } + void setWindowLocked(bool lock) { m_windowLocked = lock; } signals: void rangeChanged(); + void windowChanged(); + +private slots: + void rebuildWindow(); + void moveWindow(); private: qint64 m_startTime; qint64 m_endTime; + qint64 m_windowStart; + qint64 m_windowEnd; + + const QmlProfilerTraceTime *m_traceTime; + QTimer m_timer; + bool m_windowLocked; }; class QmlProfilerTraceView : public QWidget @@ -97,6 +118,8 @@ private slots: protected: virtual void resizeEvent(QResizeEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); private slots: void setZoomSliderEnabled(bool enabled);