QmlProfiler: Keep an extra time window in ZoomControl

This window is dynamically sized so that no integer overflows can occur
when using it in the timeline view instead of the whole trace time.

Task-number: QTCREATORBUG-11879
Change-Id: Id86faaf614b5f833e47ce26bb859b63eb09e7547
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
Ulf Hermann
2014-03-28 16:06:07 +01:00
parent a0239e3e71
commit be1a94ef1f
4 changed files with 126 additions and 8 deletions

View File

@@ -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)