forked from qt-creator/qt-creator
QmlProfiler: Apply d-pointer pattern to TimelineRenderer
TimelineRenderer will be a public class in the timeline library. We don't want to expose its private members. Change-Id: Ib82ab8b30f702293d1d8b5d101b7dd0e3380194c Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
@@ -86,7 +86,8 @@ HEADERS += \
|
|||||||
timelinerenderpass.h \
|
timelinerenderpass.h \
|
||||||
timelinerenderstate.h \
|
timelinerenderstate.h \
|
||||||
timelinenotesmodel.h \
|
timelinenotesmodel.h \
|
||||||
timelinenotesmodel_p.h
|
timelinenotesmodel_p.h \
|
||||||
|
timelinerenderer_p.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
qml/qmlprofiler.qrc
|
qml/qmlprofiler.qrc
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ QtcPlugin {
|
|||||||
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
|
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
|
||||||
"timelinenotesmodel.cpp", "timelinenotesmodel.h", "timelinenotesmodel_p.h",
|
"timelinenotesmodel.cpp", "timelinenotesmodel.h", "timelinenotesmodel_p.h",
|
||||||
"timelinenotesrenderpass.cpp", "timelinenotesrenderpass.h",
|
"timelinenotesrenderpass.cpp", "timelinenotesrenderpass.h",
|
||||||
"timelinerenderer.cpp", "timelinerenderer.h",
|
"timelinerenderer.cpp", "timelinerenderer.h", "timelinerenderer_p.h",
|
||||||
"timelinerenderpass.cpp", "timelinerenderpass.h",
|
"timelinerenderpass.cpp", "timelinerenderpass.h",
|
||||||
"timelinerenderstate.cpp", "timelinerenderstate.h",
|
"timelinerenderstate.cpp", "timelinerenderstate.h",
|
||||||
"timelineselectionrenderpass.cpp", "timelineselectionrenderpass.h",
|
"timelineselectionrenderpass.cpp", "timelineselectionrenderpass.h",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "timelinerenderer.h"
|
#include "timelinerenderer_p.h"
|
||||||
#include "timelinerenderpass.h"
|
#include "timelinerenderpass.h"
|
||||||
#include "qmlprofilernotesmodel.h"
|
#include "qmlprofilernotesmodel.h"
|
||||||
#include "timelineitemsrenderpass.h"
|
#include "timelineitemsrenderpass.h"
|
||||||
@@ -50,113 +50,159 @@
|
|||||||
|
|
||||||
namespace Timeline {
|
namespace Timeline {
|
||||||
|
|
||||||
|
TimelineRenderer::TimelineRendererPrivate::TimelineRendererPrivate(TimelineRenderer *q) :
|
||||||
|
model(0), zoomer(0), notes(0), selectedItem(-1), selectionLocked(true), modelDirty(false),
|
||||||
|
rowHeightsDirty(false), rowCountsDirty(false), lastState(0), q_ptr(q)
|
||||||
|
{
|
||||||
|
resetCurrentSelection();
|
||||||
|
}
|
||||||
|
|
||||||
TimelineRenderer::TimelineRenderer(QQuickItem *parent) :
|
TimelineRenderer::TimelineRenderer(QQuickItem *parent) :
|
||||||
QQuickItem(parent), m_model(0), m_zoomer(0), m_notes(0),
|
QQuickItem(parent), d_ptr(new TimelineRendererPrivate(this))
|
||||||
m_selectedItem(-1), m_selectionLocked(true), m_modelDirty(false),
|
|
||||||
m_rowHeightsDirty(false), m_rowCountsDirty(false), m_lastState(0)
|
|
||||||
{
|
{
|
||||||
setFlag(QQuickItem::ItemHasContents);
|
setFlag(QQuickItem::ItemHasContents);
|
||||||
resetCurrentSelection();
|
|
||||||
setAcceptedMouseButtons(Qt::LeftButton);
|
setAcceptedMouseButtons(Qt::LeftButton);
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setModel(TimelineModel *model)
|
bool TimelineRenderer::selectionLocked() const
|
||||||
{
|
{
|
||||||
if (m_model == model)
|
Q_D(const TimelineRenderer);
|
||||||
return;
|
return d->selectionLocked;
|
||||||
|
|
||||||
if (m_model) {
|
|
||||||
disconnect(m_model, SIGNAL(expandedChanged()), this, SLOT(update()));
|
|
||||||
disconnect(m_model, SIGNAL(hiddenChanged()), this, SLOT(update()));
|
|
||||||
disconnect(m_model, SIGNAL(expandedRowHeightChanged(int,int)),
|
|
||||||
this, SLOT(setRowHeightsDirty()));
|
|
||||||
disconnect(m_model, SIGNAL(emptyChanged()), this, SLOT(setModelDirty()));
|
|
||||||
disconnect(m_model, SIGNAL(expandedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
|
||||||
disconnect(m_model, SIGNAL(collapsedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_model = model;
|
int TimelineRenderer::selectedItem() const
|
||||||
if (m_model) {
|
{
|
||||||
connect(m_model, SIGNAL(expandedChanged()), this, SLOT(update()));
|
Q_D(const TimelineRenderer);
|
||||||
connect(m_model, SIGNAL(hiddenChanged()), this, SLOT(update()));
|
return d->selectedItem;
|
||||||
connect(m_model, SIGNAL(expandedRowHeightChanged(int,int)),
|
}
|
||||||
|
|
||||||
|
TimelineModel *TimelineRenderer::model() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineRenderer::setModel(TimelineModel *model)
|
||||||
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
|
if (d->model == model)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d->model) {
|
||||||
|
disconnect(d->model, SIGNAL(expandedChanged()), this, SLOT(update()));
|
||||||
|
disconnect(d->model, SIGNAL(hiddenChanged()), this, SLOT(update()));
|
||||||
|
disconnect(d->model, SIGNAL(expandedRowHeightChanged(int,int)),
|
||||||
this, SLOT(setRowHeightsDirty()));
|
this, SLOT(setRowHeightsDirty()));
|
||||||
connect(m_model, SIGNAL(emptyChanged()), this, SLOT(setModelDirty()));
|
disconnect(d->model, SIGNAL(emptyChanged()), this, SLOT(setModelDirty()));
|
||||||
connect(m_model, SIGNAL(expandedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
disconnect(d->model, SIGNAL(expandedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
||||||
connect(m_model, SIGNAL(collapsedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
disconnect(d->model, SIGNAL(collapsedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
||||||
m_renderPasses = model->supportedRenderPasses();
|
}
|
||||||
|
|
||||||
|
d->model = model;
|
||||||
|
if (d->model) {
|
||||||
|
connect(d->model, SIGNAL(expandedChanged()), this, SLOT(update()));
|
||||||
|
connect(d->model, SIGNAL(hiddenChanged()), this, SLOT(update()));
|
||||||
|
connect(d->model, SIGNAL(expandedRowHeightChanged(int,int)),
|
||||||
|
this, SLOT(setRowHeightsDirty()));
|
||||||
|
connect(d->model, SIGNAL(emptyChanged()), this, SLOT(setModelDirty()));
|
||||||
|
connect(d->model, SIGNAL(expandedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
||||||
|
connect(d->model, SIGNAL(collapsedRowCountChanged()), this, SLOT(setRowCountsDirty()));
|
||||||
|
d->renderPasses = d->model->supportedRenderPasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
setModelDirty();
|
setModelDirty();
|
||||||
setRowHeightsDirty();
|
setRowHeightsDirty();
|
||||||
setRowCountsDirty();
|
setRowCountsDirty();
|
||||||
emit modelChanged(m_model);
|
emit modelChanged(d->model);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineZoomControl *TimelineRenderer::zoomer() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->zoomer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setZoomer(TimelineZoomControl *zoomer)
|
void TimelineRenderer::setZoomer(TimelineZoomControl *zoomer)
|
||||||
{
|
{
|
||||||
if (zoomer != m_zoomer) {
|
Q_D(TimelineRenderer);
|
||||||
if (m_zoomer != 0)
|
if (zoomer != d->zoomer) {
|
||||||
disconnect(m_zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
|
if (d->zoomer != 0)
|
||||||
m_zoomer = zoomer;
|
disconnect(d->zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
|
||||||
if (m_zoomer != 0)
|
d->zoomer = zoomer;
|
||||||
connect(m_zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
|
if (d->zoomer != 0)
|
||||||
|
connect(d->zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
|
||||||
emit zoomerChanged(zoomer);
|
emit zoomerChanged(zoomer);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelineNotesModel *TimelineRenderer::notes() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->notes;
|
||||||
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setNotes(TimelineNotesModel *notes)
|
void TimelineRenderer::setNotes(TimelineNotesModel *notes)
|
||||||
{
|
{
|
||||||
if (m_notes == notes)
|
Q_D(TimelineRenderer);
|
||||||
|
if (d->notes == notes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_notes)
|
if (d->notes)
|
||||||
disconnect(m_notes, &TimelineNotesModel::changed,
|
disconnect(d->notes, &TimelineNotesModel::changed,
|
||||||
this, &TimelineRenderer::setNotesDirty);
|
this, &TimelineRenderer::setNotesDirty);
|
||||||
|
|
||||||
m_notes = notes;
|
d->notes = notes;
|
||||||
if (m_notes)
|
if (d->notes)
|
||||||
connect(m_notes, &TimelineNotesModel::changed,
|
connect(d->notes, &TimelineNotesModel::changed,
|
||||||
this, &TimelineRenderer::setNotesDirty);
|
this, &TimelineRenderer::setNotesDirty);
|
||||||
|
|
||||||
emit notesChanged(m_notes);
|
emit notesChanged(d->notes);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimelineRenderer::modelDirty() const
|
bool TimelineRenderer::modelDirty() const
|
||||||
{
|
{
|
||||||
return m_modelDirty;
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->modelDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimelineRenderer::notesDirty() const
|
bool TimelineRenderer::notesDirty() const
|
||||||
{
|
{
|
||||||
return m_notesDirty;
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->notesDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimelineRenderer::rowHeightsDirty() const
|
bool TimelineRenderer::rowHeightsDirty() const
|
||||||
{
|
{
|
||||||
return m_rowHeightsDirty;
|
Q_D(const TimelineRenderer);
|
||||||
|
return d->rowHeightsDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::resetCurrentSelection()
|
bool TimelineRenderer::rowCountsDirty() const
|
||||||
{
|
{
|
||||||
m_currentSelection.startTime = -1;
|
Q_D(const TimelineRenderer);
|
||||||
m_currentSelection.endTime = -1;
|
return d->rowCountsDirty;
|
||||||
m_currentSelection.row = -1;
|
|
||||||
m_currentSelection.eventIndex = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineRenderState *TimelineRenderer::findRenderState()
|
void TimelineRenderer::TimelineRendererPrivate::resetCurrentSelection()
|
||||||
|
{
|
||||||
|
currentSelection.startTime = -1;
|
||||||
|
currentSelection.endTime = -1;
|
||||||
|
currentSelection.row = -1;
|
||||||
|
currentSelection.eventIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineRenderState *TimelineRenderer::TimelineRendererPrivate::findRenderState()
|
||||||
{
|
{
|
||||||
int newLevel = 0;
|
int newLevel = 0;
|
||||||
int newOffset = 0;
|
int newOffset = 0;
|
||||||
int level;
|
int level;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
qint64 newStart = m_zoomer->traceStart();
|
qint64 newStart = zoomer->traceStart();
|
||||||
qint64 newEnd = m_zoomer->traceEnd();
|
qint64 newEnd = zoomer->traceEnd();
|
||||||
qint64 start;
|
qint64 start;
|
||||||
qint64 end;
|
qint64 end;
|
||||||
do {
|
do {
|
||||||
@@ -166,60 +212,61 @@ TimelineRenderState *TimelineRenderer::findRenderState()
|
|||||||
end = newEnd;
|
end = newEnd;
|
||||||
|
|
||||||
newLevel = level + 1;
|
newLevel = level + 1;
|
||||||
qint64 range = m_zoomer->traceDuration() >> newLevel;
|
qint64 range = zoomer->traceDuration() >> newLevel;
|
||||||
newOffset = (m_zoomer->windowStart() - m_zoomer->traceStart() + range / 2) / range;
|
newOffset = (zoomer->windowStart() - zoomer->traceStart() + range / 2) / range;
|
||||||
newStart = m_zoomer->traceStart() + newOffset * range - range / 2;
|
newStart = zoomer->traceStart() + newOffset * range - range / 2;
|
||||||
newEnd = newStart + range;
|
newEnd = newStart + range;
|
||||||
} while (newStart < m_zoomer->windowStart() && newEnd > m_zoomer->windowEnd());
|
} while (newStart < zoomer->windowStart() && newEnd > zoomer->windowEnd());
|
||||||
|
|
||||||
|
|
||||||
if (m_renderStates.length() <= level)
|
if (renderStates.length() <= level)
|
||||||
m_renderStates.resize(level + 1);
|
renderStates.resize(level + 1);
|
||||||
if (m_renderStates[level].length() <= offset)
|
if (renderStates[level].length() <= offset)
|
||||||
m_renderStates[level].resize(offset + 1);
|
renderStates[level].resize(offset + 1);
|
||||||
TimelineRenderState *state = m_renderStates[level][offset];
|
TimelineRenderState *state = renderStates[level][offset];
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
state = new TimelineRenderState(start, end, 1.0 / static_cast<qreal>(SafeFloatMax),
|
state = new TimelineRenderState(start, end, 1.0 / static_cast<qreal>(SafeFloatMax),
|
||||||
m_renderPasses.size());
|
renderPasses.size());
|
||||||
m_renderStates[level][offset] = state;
|
renderStates[level][offset] = state;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node,
|
QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node, UpdatePaintNodeData *updatePaintNodeData)
|
||||||
UpdatePaintNodeData *updatePaintNodeData)
|
|
||||||
{
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
Q_UNUSED(updatePaintNodeData)
|
Q_UNUSED(updatePaintNodeData)
|
||||||
|
|
||||||
if (!m_model || m_model->hidden() || m_model->isEmpty() || m_zoomer->windowDuration() <= 0) {
|
if (!d->model || d->model->hidden() || d->model->isEmpty() ||
|
||||||
|
d->zoomer->windowDuration() <= 0) {
|
||||||
delete node;
|
delete node;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (node == 0) {
|
} else if (node == 0) {
|
||||||
node = new QSGTransformNode;
|
node = new QSGTransformNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal spacing = width() / m_zoomer->windowDuration();
|
qreal spacing = width() / d->zoomer->windowDuration();
|
||||||
|
|
||||||
if (m_modelDirty || m_rowCountsDirty) {
|
if (d->modelDirty || d->rowCountsDirty) {
|
||||||
node->removeAllChildNodes();
|
node->removeAllChildNodes();
|
||||||
foreach (QVector<TimelineRenderState *> stateVector, m_renderStates)
|
foreach (QVector<TimelineRenderState *> stateVector, d->renderStates)
|
||||||
qDeleteAll(stateVector);
|
qDeleteAll(stateVector);
|
||||||
m_renderStates.clear();
|
d->renderStates.clear();
|
||||||
m_lastState = 0;
|
d->lastState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineRenderState *state = findRenderState();
|
TimelineRenderState *state = d->findRenderState();
|
||||||
|
|
||||||
int lastIndex = m_model->lastIndex(m_zoomer->windowEnd());
|
int lastIndex = d->model->lastIndex(d->zoomer->windowEnd());
|
||||||
int firstIndex = m_model->firstIndex(m_zoomer->windowStart());
|
int firstIndex = d->model->firstIndex(d->zoomer->windowStart());
|
||||||
|
|
||||||
for (int i = 0; i < m_renderPasses.length(); ++i)
|
for (int i = 0; i < d->renderPasses.length(); ++i)
|
||||||
state->setPassState(i, m_renderPasses[i]->update(this, state, state->passState(i),
|
state->setPassState(i, d->renderPasses[i]->update(this, state, state->passState(i),
|
||||||
firstIndex, lastIndex + 1,
|
firstIndex, lastIndex + 1,
|
||||||
state != m_lastState, spacing));
|
state != d->lastState, spacing));
|
||||||
|
|
||||||
if (state->isEmpty()) { // new state
|
if (state->isEmpty()) { // new state
|
||||||
for (int pass = 0; pass < m_renderPasses.length(); ++pass) {
|
for (int pass = 0; pass < d->renderPasses.length(); ++pass) {
|
||||||
const TimelineRenderPass::State *passState = state->passState(pass);
|
const TimelineRenderPass::State *passState = state->passState(pass);
|
||||||
if (!passState)
|
if (!passState)
|
||||||
continue;
|
continue;
|
||||||
@@ -230,9 +277,9 @@ QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
for (int i = 0; i < m_model->expandedRowCount(); ++i) {
|
for (int i = 0; i < d->model->expandedRowCount(); ++i) {
|
||||||
QSGTransformNode *rowNode = new QSGTransformNode;
|
QSGTransformNode *rowNode = new QSGTransformNode;
|
||||||
for (int pass = 0; pass < m_renderPasses.length(); ++pass) {
|
for (int pass = 0; pass < d->renderPasses.length(); ++pass) {
|
||||||
const TimelineRenderPass::State *passState = state->passState(pass);
|
const TimelineRenderPass::State *passState = state->passState(pass);
|
||||||
if (passState && passState->expandedRows.length() > row) {
|
if (passState && passState->expandedRows.length() > row) {
|
||||||
QSGNode *rowChildNode = passState->expandedRows[row];
|
QSGNode *rowChildNode = passState->expandedRows[row];
|
||||||
@@ -244,12 +291,12 @@ QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node,
|
|||||||
++row;
|
++row;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int row = 0; row < m_model->collapsedRowCount(); ++row) {
|
for (int row = 0; row < d->model->collapsedRowCount(); ++row) {
|
||||||
QSGTransformNode *rowNode = new QSGTransformNode;
|
QSGTransformNode *rowNode = new QSGTransformNode;
|
||||||
QMatrix4x4 matrix;
|
QMatrix4x4 matrix;
|
||||||
matrix.translate(0, row * TimelineModel::defaultRowHeight(), 0);
|
matrix.translate(0, row * TimelineModel::defaultRowHeight(), 0);
|
||||||
rowNode->setMatrix(matrix);
|
rowNode->setMatrix(matrix);
|
||||||
for (int pass = 0; pass < m_renderPasses.length(); ++pass) {
|
for (int pass = 0; pass < d->renderPasses.length(); ++pass) {
|
||||||
const TimelineRenderPass::State *passState = state->passState(pass);
|
const TimelineRenderPass::State *passState = state->passState(pass);
|
||||||
if (passState && passState->collapsedRows.length() > row) {
|
if (passState && passState->collapsedRows.length() > row) {
|
||||||
QSGNode *rowChildNode = passState->collapsedRows[row];
|
QSGNode *rowChildNode = passState->collapsedRows[row];
|
||||||
@@ -261,12 +308,12 @@ QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_rowHeightsDirty || state != m_lastState) {
|
if (d->rowHeightsDirty || state != d->lastState) {
|
||||||
int row = 0;
|
int row = 0;
|
||||||
qreal offset = 0;
|
qreal offset = 0;
|
||||||
for (QSGNode *rowNode = state->expandedRowRoot()->firstChild(); rowNode != 0;
|
for (QSGNode *rowNode = state->expandedRowRoot()->firstChild(); rowNode != 0;
|
||||||
rowNode = rowNode->nextSibling()) {
|
rowNode = rowNode->nextSibling()) {
|
||||||
qreal rowHeight = m_model->expandedRowHeight(row++);
|
qreal rowHeight = d->model->expandedRowHeight(row++);
|
||||||
QMatrix4x4 matrix;
|
QMatrix4x4 matrix;
|
||||||
matrix.translate(0, offset, 0);
|
matrix.translate(0, offset, 0);
|
||||||
matrix.scale(1, rowHeight / TimelineModel::defaultRowHeight(), 1);
|
matrix.scale(1, rowHeight / TimelineModel::defaultRowHeight(), 1);
|
||||||
@@ -275,18 +322,18 @@ QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_modelDirty = false;
|
d->modelDirty = false;
|
||||||
m_notesDirty = false;
|
d->notesDirty = false;
|
||||||
m_rowCountsDirty = false;
|
d->rowCountsDirty = false;
|
||||||
m_rowHeightsDirty = false;
|
d->rowHeightsDirty = false;
|
||||||
m_lastState = state;
|
d->lastState = state;
|
||||||
|
|
||||||
QSGNode *rowNode = m_model->expanded() ? state->expandedRowRoot() : state->collapsedRowRoot();
|
QSGNode *rowNode = d->model->expanded() ? state->expandedRowRoot() : state->collapsedRowRoot();
|
||||||
QSGNode *overlayNode = m_model->expanded() ? state->expandedOverlayRoot() :
|
QSGNode *overlayNode = d->model->expanded() ? state->expandedOverlayRoot() :
|
||||||
state->collapsedOverlayRoot();
|
state->collapsedOverlayRoot();
|
||||||
|
|
||||||
QMatrix4x4 matrix;
|
QMatrix4x4 matrix;
|
||||||
matrix.translate((state->start() - m_zoomer->windowStart()) * spacing, 0, 0);
|
matrix.translate((state->start() - d->zoomer->windowStart()) * spacing, 0, 0);
|
||||||
matrix.scale(spacing / state->scale(), 1, 1);
|
matrix.scale(spacing / state->scale(), 1, 1);
|
||||||
|
|
||||||
QSGTransformNode *transform = static_cast<QSGTransformNode *>(node);
|
QSGTransformNode *transform = static_cast<QSGTransformNode *>(node);
|
||||||
@@ -305,14 +352,14 @@ void TimelineRenderer::mousePressEvent(QMouseEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimelineRenderer::rowFromPosition(int y)
|
int TimelineRenderer::TimelineRendererPrivate::rowFromPosition(int y) const
|
||||||
{
|
{
|
||||||
if (!m_model->expanded())
|
if (!model->expanded())
|
||||||
return y / TimelineModel::defaultRowHeight();
|
return y / TimelineModel::defaultRowHeight();
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (int row = 0; row < m_model->expandedRowCount(); ++row) {
|
for (int row = 0; row < model->expandedRowCount(); ++row) {
|
||||||
y -= m_model->expandedRowHeight(row);
|
y -= model->expandedRowHeight(row);
|
||||||
if (y <= 0) return ret;
|
if (y <= 0) return ret;
|
||||||
++ret;
|
++ret;
|
||||||
}
|
}
|
||||||
@@ -322,9 +369,10 @@ int TimelineRenderer::rowFromPosition(int y)
|
|||||||
|
|
||||||
void TimelineRenderer::mouseReleaseEvent(QMouseEvent *event)
|
void TimelineRenderer::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
if (!m_model->isEmpty())
|
if (!d->model->isEmpty())
|
||||||
manageClicked();
|
d->manageClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::mouseMoveEvent(QMouseEvent *event)
|
void TimelineRenderer::mouseMoveEvent(QMouseEvent *event)
|
||||||
@@ -332,131 +380,161 @@ void TimelineRenderer::mouseMoveEvent(QMouseEvent *event)
|
|||||||
event->setAccepted(false);
|
event->setAccepted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TimelineRenderer::hoverMoveEvent(QHoverEvent *event)
|
void TimelineRenderer::hoverMoveEvent(QHoverEvent *event)
|
||||||
{
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
manageHovered(event->pos().x(), event->pos().y());
|
d->manageHovered(event->pos().x(), event->pos().y());
|
||||||
if (m_currentSelection.eventIndex == -1)
|
if (d->currentSelection.eventIndex == -1)
|
||||||
event->setAccepted(false);
|
event->setAccepted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::manageClicked()
|
void TimelineRenderer::TimelineRendererPrivate::manageClicked()
|
||||||
{
|
{
|
||||||
if (m_currentSelection.eventIndex != -1) {
|
Q_Q(TimelineRenderer);
|
||||||
if (m_currentSelection.eventIndex == m_selectedItem)
|
if (currentSelection.eventIndex != -1) {
|
||||||
setSelectionLocked(!m_selectionLocked);
|
if (currentSelection.eventIndex == selectedItem)
|
||||||
|
q->setSelectionLocked(!selectionLocked);
|
||||||
else
|
else
|
||||||
setSelectionLocked(true);
|
q->setSelectionLocked(true);
|
||||||
|
|
||||||
// itemPressed() will trigger an update of the events and JavaScript views. Make sure the
|
// itemPressed() will trigger an update of the events and JavaScript views. Make sure the
|
||||||
// correct event is already selected when that happens, to prevent confusion.
|
// correct event is already selected when that happens, to prevent confusion.
|
||||||
setSelectedItem(m_currentSelection.eventIndex);
|
q->setSelectedItem(currentSelection.eventIndex);
|
||||||
emit itemPressed(m_currentSelection.eventIndex);
|
emit q->itemPressed(currentSelection.eventIndex);
|
||||||
} else {
|
} else {
|
||||||
setSelectionLocked(false);
|
q->setSelectionLocked(false);
|
||||||
setSelectedItem(-1);
|
q->setSelectedItem(-1);
|
||||||
emit itemPressed(-1);
|
emit q->itemPressed(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::manageHovered(int mouseX, int mouseY)
|
void TimelineRenderer::TimelineRendererPrivate::manageHovered(int mouseX, int mouseY)
|
||||||
{
|
{
|
||||||
qint64 duration = m_zoomer->windowDuration();
|
Q_Q(TimelineRenderer);
|
||||||
|
qint64 duration = zoomer->windowDuration();
|
||||||
if (duration <= 0)
|
if (duration <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Make the "selected" area 3 pixels wide by adding/subtracting 1 to catch very narrow events.
|
// Make the "selected" area 3 pixels wide by adding/subtracting 1 to catch very narrow events.
|
||||||
qint64 startTime = (mouseX - 1) * duration / width() + m_zoomer->windowStart();
|
qint64 startTime = (mouseX - 1) * duration / q->width() + zoomer->windowStart();
|
||||||
qint64 endTime = (mouseX + 1) * duration / width() + m_zoomer->windowStart();
|
qint64 endTime = (mouseX + 1) * duration / q->width() + zoomer->windowStart();
|
||||||
qint64 exactTime = (startTime + endTime) / 2;
|
qint64 exactTime = (startTime + endTime) / 2;
|
||||||
int row = rowFromPosition(mouseY);
|
int row = rowFromPosition(mouseY);
|
||||||
|
|
||||||
// already covered? Only recheck selectionLocked and make sure m_selectedItem is correct.
|
// already covered? Only recheck selectionLocked and make sure d->selectedItem is correct.
|
||||||
if (m_currentSelection.eventIndex != -1 &&
|
if (currentSelection.eventIndex != -1 &&
|
||||||
exactTime >= m_currentSelection.startTime &&
|
exactTime >= currentSelection.startTime &&
|
||||||
exactTime < m_currentSelection.endTime &&
|
exactTime < currentSelection.endTime &&
|
||||||
row == m_currentSelection.row) {
|
row == currentSelection.row) {
|
||||||
if (!m_selectionLocked)
|
if (!selectionLocked)
|
||||||
setSelectedItem(m_currentSelection.eventIndex);
|
q->setSelectedItem(currentSelection.eventIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find if there's items in the time range
|
// find if there's items in the time range
|
||||||
int eventFrom = m_model->firstIndex(startTime);
|
int eventFrom = model->firstIndex(startTime);
|
||||||
int eventTo = m_model->lastIndex(endTime);
|
int eventTo = model->lastIndex(endTime);
|
||||||
|
|
||||||
m_currentSelection.eventIndex = -1;
|
currentSelection.eventIndex = -1;
|
||||||
if (eventFrom == -1 || eventTo < eventFrom || eventTo >= m_model->count())
|
if (eventFrom == -1 || eventTo < eventFrom || eventTo >= model->count())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// find if we are in the right column
|
// find if we are in the right column
|
||||||
qint64 bestOffset = std::numeric_limits<qint64>::max();
|
qint64 bestOffset = std::numeric_limits<qint64>::max();
|
||||||
for (int i=eventTo; i>=eventFrom; --i) {
|
for (int i=eventTo; i>=eventFrom; --i) {
|
||||||
if ( m_model->row(i) == row) {
|
if (model->row(i) == row) {
|
||||||
// There can be small events that don't reach the cursor position after large events
|
// There can be small events that don't reach the cursor position after large events
|
||||||
// that do but are in a different row.
|
// that do but are in a different row.
|
||||||
qint64 itemEnd = m_model->endTime(i);
|
qint64 itemEnd = model->endTime(i);
|
||||||
if (itemEnd < startTime)
|
if (itemEnd < startTime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
qint64 itemStart = m_model->startTime(i);
|
qint64 itemStart = model->startTime(i);
|
||||||
|
|
||||||
qint64 offset = qAbs(itemEnd - exactTime) + qAbs(itemStart - exactTime);
|
qint64 offset = qAbs(itemEnd - exactTime) + qAbs(itemStart - exactTime);
|
||||||
if (offset < bestOffset) {
|
if (offset < bestOffset) {
|
||||||
// match
|
// match
|
||||||
m_currentSelection.eventIndex = i;
|
currentSelection.eventIndex = i;
|
||||||
m_currentSelection.startTime = itemStart;
|
currentSelection.startTime = itemStart;
|
||||||
m_currentSelection.endTime = itemEnd;
|
currentSelection.endTime = itemEnd;
|
||||||
m_currentSelection.row = row;
|
currentSelection.row = row;
|
||||||
bestOffset = offset;
|
bestOffset = offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_selectionLocked && m_currentSelection.eventIndex != -1)
|
if (!selectionLocked && currentSelection.eventIndex != -1)
|
||||||
setSelectedItem(m_currentSelection.eventIndex);
|
q->setSelectedItem(currentSelection.eventIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::clearData()
|
void TimelineRenderer::clearData()
|
||||||
{
|
{
|
||||||
resetCurrentSelection();
|
Q_D(TimelineRenderer);
|
||||||
|
d->resetCurrentSelection();
|
||||||
setSelectedItem(-1);
|
setSelectedItem(-1);
|
||||||
setSelectionLocked(true);
|
setSelectionLocked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TimelineRenderer::setSelectedItem(int itemIndex)
|
||||||
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
|
if (d->selectedItem != itemIndex) {
|
||||||
|
d->selectedItem = itemIndex;
|
||||||
|
update();
|
||||||
|
emit selectedItemChanged(itemIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineRenderer::setSelectionLocked(bool locked)
|
||||||
|
{
|
||||||
|
Q_D(TimelineRenderer);
|
||||||
|
if (d->selectionLocked != locked) {
|
||||||
|
d->selectionLocked = locked;
|
||||||
|
update();
|
||||||
|
emit selectionLockedChanged(locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TimelineRenderer::selectNextFromSelectionId(int selectionId)
|
void TimelineRenderer::selectNextFromSelectionId(int selectionId)
|
||||||
{
|
{
|
||||||
setSelectedItem(m_model->nextItemBySelectionId(selectionId, m_zoomer->rangeStart(),
|
Q_D(TimelineRenderer);
|
||||||
m_selectedItem));
|
setSelectedItem(d->model->nextItemBySelectionId(selectionId, d->zoomer->rangeStart(),
|
||||||
|
d->selectedItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::selectPrevFromSelectionId(int selectionId)
|
void TimelineRenderer::selectPrevFromSelectionId(int selectionId)
|
||||||
{
|
{
|
||||||
setSelectedItem(m_model->prevItemBySelectionId(selectionId, m_zoomer->rangeStart(),
|
Q_D(TimelineRenderer);
|
||||||
m_selectedItem));
|
setSelectedItem(d->model->prevItemBySelectionId(selectionId, d->zoomer->rangeStart(),
|
||||||
|
d->selectedItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setModelDirty()
|
void TimelineRenderer::setModelDirty()
|
||||||
{
|
{
|
||||||
m_modelDirty = true;
|
Q_D(TimelineRenderer);
|
||||||
|
d->modelDirty = true;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setRowHeightsDirty()
|
void TimelineRenderer::setRowHeightsDirty()
|
||||||
{
|
{
|
||||||
m_rowHeightsDirty = true;
|
Q_D(TimelineRenderer);
|
||||||
|
d->rowHeightsDirty = true;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setNotesDirty()
|
void TimelineRenderer::setNotesDirty()
|
||||||
{
|
{
|
||||||
m_notesDirty = true;
|
Q_D(TimelineRenderer);
|
||||||
|
d->notesDirty = true;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineRenderer::setRowCountsDirty()
|
void TimelineRenderer::setRowCountsDirty()
|
||||||
{
|
{
|
||||||
m_rowCountsDirty = true;
|
Q_D(TimelineRenderer);
|
||||||
|
d->rowCountsDirty = true;
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Timeline
|
} // namespace Timeline
|
||||||
|
|||||||
@@ -56,28 +56,22 @@ public:
|
|||||||
|
|
||||||
explicit TimelineRenderer(QQuickItem *parent = 0);
|
explicit TimelineRenderer(QQuickItem *parent = 0);
|
||||||
|
|
||||||
bool selectionLocked() const
|
bool selectionLocked() const;
|
||||||
{
|
int selectedItem() const;
|
||||||
return m_selectionLocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
int selectedItem() const
|
TimelineModel *model() const;
|
||||||
{
|
|
||||||
return m_selectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimelineModel *model() const { return m_model; }
|
|
||||||
void setModel(TimelineModel *model);
|
void setModel(TimelineModel *model);
|
||||||
|
|
||||||
TimelineZoomControl *zoomer() const { return m_zoomer; }
|
TimelineZoomControl *zoomer() const;
|
||||||
void setZoomer(TimelineZoomControl *zoomer);
|
void setZoomer(TimelineZoomControl *zoomer);
|
||||||
|
|
||||||
TimelineNotesModel *notes() const { return m_notes; }
|
TimelineNotesModel *notes() const;
|
||||||
void setNotes(TimelineNotesModel *notes);
|
void setNotes(TimelineNotesModel *notes);
|
||||||
|
|
||||||
bool modelDirty() const;
|
bool modelDirty() const;
|
||||||
bool notesDirty() const;
|
bool notesDirty() const;
|
||||||
bool rowHeightsDirty() const;
|
bool rowHeightsDirty() const;
|
||||||
|
bool rowCountsDirty() const;
|
||||||
|
|
||||||
Q_INVOKABLE void selectNextFromSelectionId(int selectionId);
|
Q_INVOKABLE void selectNextFromSelectionId(int selectionId);
|
||||||
Q_INVOKABLE void selectPrevFromSelectionId(int selectionId);
|
Q_INVOKABLE void selectPrevFromSelectionId(int selectionId);
|
||||||
@@ -97,25 +91,9 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void clearData();
|
void clearData();
|
||||||
|
|
||||||
void setSelectedItem(int itemIndex)
|
void setSelectedItem(int itemIndex);
|
||||||
{
|
void setSelectionLocked(bool locked);
|
||||||
if (m_selectedItem != itemIndex) {
|
|
||||||
m_selectedItem = itemIndex;
|
|
||||||
update();
|
|
||||||
emit selectedItemChanged(itemIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSelectionLocked(bool locked)
|
|
||||||
{
|
|
||||||
if (m_selectionLocked != locked) {
|
|
||||||
m_selectionLocked = locked;
|
|
||||||
update();
|
|
||||||
emit selectionLockedChanged(locked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void setModelDirty();
|
void setModelDirty();
|
||||||
void setRowHeightsDirty();
|
void setRowHeightsDirty();
|
||||||
void setNotesDirty();
|
void setNotesDirty();
|
||||||
@@ -129,38 +107,9 @@ protected:
|
|||||||
virtual void hoverMoveEvent(QHoverEvent *event);
|
virtual void hoverMoveEvent(QHoverEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int rowFromPosition(int y);
|
class TimelineRendererPrivate;
|
||||||
|
TimelineRendererPrivate *d_ptr;
|
||||||
void manageClicked();
|
Q_DECLARE_PRIVATE(TimelineRenderer)
|
||||||
void manageHovered(int mouseX, int mouseY);
|
|
||||||
|
|
||||||
static const int SafeFloatMax = 1 << 12;
|
|
||||||
|
|
||||||
void resetCurrentSelection();
|
|
||||||
|
|
||||||
TimelineRenderState *findRenderState();
|
|
||||||
|
|
||||||
TimelineModel *m_model;
|
|
||||||
TimelineZoomControl *m_zoomer;
|
|
||||||
TimelineNotesModel *m_notes;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
qint64 startTime;
|
|
||||||
qint64 endTime;
|
|
||||||
int row;
|
|
||||||
int eventIndex;
|
|
||||||
} m_currentSelection;
|
|
||||||
|
|
||||||
int m_selectedItem;
|
|
||||||
bool m_selectionLocked;
|
|
||||||
bool m_modelDirty;
|
|
||||||
bool m_rowHeightsDirty;
|
|
||||||
bool m_notesDirty;
|
|
||||||
bool m_rowCountsDirty;
|
|
||||||
|
|
||||||
QList<const TimelineRenderPass *> m_renderPasses;
|
|
||||||
QVector<QVector<TimelineRenderState *> > m_renderStates;
|
|
||||||
TimelineRenderState *m_lastState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Timeline
|
} // namespace Timeline
|
||||||
|
|||||||
83
src/plugins/qmlprofiler/timelinerenderer_p.h
Normal file
83
src/plugins/qmlprofiler/timelinerenderer_p.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://www.qt.io/licensing. For further information
|
||||||
|
** use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TIMELINERENDERER_P_H
|
||||||
|
#define TIMELINERENDERER_P_H
|
||||||
|
|
||||||
|
#include "timelinerenderer.h"
|
||||||
|
|
||||||
|
namespace Timeline {
|
||||||
|
|
||||||
|
class TimelineRenderer::TimelineRendererPrivate {
|
||||||
|
public:
|
||||||
|
TimelineRendererPrivate(TimelineRenderer *q);
|
||||||
|
|
||||||
|
int rowFromPosition(int y) const;
|
||||||
|
|
||||||
|
void manageClicked();
|
||||||
|
void manageHovered(int mouseX, int mouseY);
|
||||||
|
|
||||||
|
static const int SafeFloatMax = 1 << 12;
|
||||||
|
|
||||||
|
void resetCurrentSelection();
|
||||||
|
|
||||||
|
TimelineRenderState *findRenderState();
|
||||||
|
|
||||||
|
TimelineModel *model;
|
||||||
|
TimelineZoomControl *zoomer;
|
||||||
|
TimelineNotesModel *notes;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
qint64 startTime;
|
||||||
|
qint64 endTime;
|
||||||
|
int row;
|
||||||
|
int eventIndex;
|
||||||
|
} currentSelection;
|
||||||
|
|
||||||
|
int selectedItem;
|
||||||
|
bool selectionLocked;
|
||||||
|
bool modelDirty;
|
||||||
|
bool rowHeightsDirty;
|
||||||
|
bool notesDirty;
|
||||||
|
bool rowCountsDirty;
|
||||||
|
|
||||||
|
QList<const TimelineRenderPass *> renderPasses;
|
||||||
|
QVector<QVector<TimelineRenderState *> > renderStates;
|
||||||
|
TimelineRenderState *lastState;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TimelineRenderer *q_ptr;
|
||||||
|
Q_DECLARE_PUBLIC(TimelineRenderer)
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Timeline
|
||||||
|
|
||||||
|
#endif // TIMELINERENDERER_P_H
|
||||||
|
|
||||||
Reference in New Issue
Block a user