diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index 6ea9fd36de1..c0a6846e057 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -254,8 +254,16 @@ Rectangle { height: 24 onZoomControlChanged: zoomSliderToolBar.visible = !zoomSliderToolBar.visible onFilterMenuChanged: filterMenu.visible = !filterMenu.visible - onJumpToNext: view.selectNext(); - onJumpToPrev: view.selectPrev(); + onJumpToNext: { + var next = qmlProfilerModelProxy.nextItem(view.selectedModel, view.selectedItem, + zoomControl.rangeStart); + view.selectFromEventIndex(next.model, next.item); + } + onJumpToPrev: { + var prev = qmlProfilerModelProxy.prevItem(view.selectedModel, view.selectedItem, + zoomControl.rangeEnd); + view.selectFromEventIndex(prev.model, prev.item); + } onRangeSelectChanged: selectionRangeMode = rangeButtonChecked(); onLockChanged: selectionLocked = !lockButtonChecked(); } diff --git a/src/plugins/qmlprofiler/timelinemodel.cpp b/src/plugins/qmlprofiler/timelinemodel.cpp index 00dc72ed104..c00f56c7509 100644 --- a/src/plugins/qmlprofiler/timelinemodel.cpp +++ b/src/plugins/qmlprofiler/timelinemodel.cpp @@ -275,7 +275,7 @@ int TimelineModel::typeId(int index) const int TimelineModel::firstIndex(qint64 startTime) const { Q_D(const TimelineModel); - int index = firstIndexNoParents(startTime); + int index = d->firstIndexNoParents(startTime); if (index == -1) return -1; int parent = d->ranges[index].parent; @@ -286,18 +286,17 @@ int TimelineModel::firstIndex(qint64 startTime) const Looks up the first range with an end time later than the specified \a startTime and returns its index. If no such range is found, it returns -1. */ -int TimelineModel::firstIndexNoParents(qint64 startTime) const +int TimelineModel::TimelineModelPrivate::firstIndexNoParents(qint64 startTime) const { - Q_D(const TimelineModel); // in the "endtime" list, find the first event that ends after startTime - if (d->endTimes.isEmpty()) + if (endTimes.isEmpty()) return -1; - if (d->endTimes.count() == 1 || d->endTimes.first().end > startTime) - return d->endTimes.first().startIndex; - if (d->endTimes.last().end <= startTime) + if (endTimes.count() == 1 || endTimes.first().end > startTime) + return endTimes.first().startIndex; + if (endTimes.last().end <= startTime) return -1; - return d->endTimes[d->lowerBound(d->endTimes, startTime) + 1].startIndex; + return endTimes[lowerBound(endTimes, startTime) + 1].startIndex; } /*! @@ -506,6 +505,80 @@ void TimelineModel::clear() emit hiddenChanged(); } +int TimelineModel::nextItemBySelectionId(int selectionId, qint64 time, int currentItem) const +{ + Q_D(const TimelineModel); + return d->nextItemById(TimelineModelPrivate::SelectionId, selectionId, time, currentItem); +} + +int TimelineModel::nextItemByTypeId(int typeId, qint64 time, int currentItem) const +{ + Q_D(const TimelineModel); + return d->nextItemById(TimelineModelPrivate::TypeId, typeId, time, currentItem); +} + +int TimelineModel::prevItemBySelectionId(int selectionId, qint64 time, int currentItem) const +{ + Q_D(const TimelineModel); + return d->prevItemById(TimelineModelPrivate::SelectionId, selectionId, time, currentItem); +} + +int TimelineModel::prevItemByTypeId(int typeId, qint64 time, int currentItem) const +{ + Q_D(const TimelineModel); + return d->prevItemById(TimelineModelPrivate::TypeId, typeId, time, currentItem); +} + +int TimelineModel::TimelineModelPrivate::nextItemById(IdType idType, int id, qint64 time, + int currentItem) const +{ + Q_Q(const TimelineModel); + if (ranges.empty()) + return -1; + + int ndx = -1; + if (currentItem == -1) + ndx = firstIndexNoParents(time); + else + ndx = currentItem + 1; + + if (ndx < 0 || ndx >= ranges.count()) + ndx = 0; + int startIndex = ndx; + do { + if ((idType == TypeId && q->typeId(ndx) == id) || + (idType == SelectionId && ranges[ndx].selectionId == id)) + return ndx; + ndx = (ndx + 1) % ranges.count(); + } while (ndx != startIndex); + return -1; +} + +int TimelineModel::TimelineModelPrivate::prevItemById(IdType idType, int id, qint64 time, + int currentItem) const +{ + Q_Q(const TimelineModel); + if (ranges.empty()) + return -1; + + int ndx = -1; + if (currentItem == -1) + ndx = firstIndexNoParents(time); + else + ndx = currentItem - 1; + if (ndx < 0) + ndx = ranges.count() - 1; + int startIndex = ndx; + do { + if ((idType == TypeId && q->typeId(ndx) == id) || + (idType == SelectionId && ranges[ndx].selectionId == id)) + return ndx; + if (--ndx < 0) + ndx = ranges.count()-1; + } while (ndx != startIndex); + return -1; +} + } #include "moc_timelinemodel.cpp" diff --git a/src/plugins/qmlprofiler/timelinemodel.h b/src/plugins/qmlprofiler/timelinemodel.h index 428473eab88..b1ca9e182f3 100644 --- a/src/plugins/qmlprofiler/timelinemodel.h +++ b/src/plugins/qmlprofiler/timelinemodel.h @@ -69,7 +69,6 @@ public: int selectionId(int index) const; int firstIndex(qint64 startTime) const; - int firstIndexNoParents(qint64 startTime) const; int lastIndex(qint64 endTime) const; bool expanded() const; @@ -95,6 +94,11 @@ public: virtual int rowMinValue(int rowNumber) const; virtual int rowMaxValue(int rowNumber) const; + Q_INVOKABLE int nextItemBySelectionId(int selectionId, qint64 time, int currentItem) const; + Q_INVOKABLE int nextItemByTypeId(int typeId, qint64 time, int currentItem) const; + Q_INVOKABLE int prevItemBySelectionId(int selectionId, qint64 time, int currentItem) const; + Q_INVOKABLE int prevItemByTypeId(int typeId, qint64 time, int currentItem) const; + static int defaultRowHeight(); signals: diff --git a/src/plugins/qmlprofiler/timelinemodel_p.h b/src/plugins/qmlprofiler/timelinemodel_p.h index dca047de51f..b1de496624a 100644 --- a/src/plugins/qmlprofiler/timelinemodel_p.h +++ b/src/plugins/qmlprofiler/timelinemodel_p.h @@ -39,6 +39,8 @@ class QMLPROFILER_EXPORT TimelineModel::TimelineModelPrivate { public: static const int DefaultRowHeight = 30; + enum IdType { SelectionId, TypeId }; + enum BoxColorProperties { SelectionIdHueMultiplier = 25, FractionHueMultiplier = 96, @@ -111,6 +113,9 @@ public: return fromIndex; } + int prevItemById(IdType idType, int id, qint64 time, int currentSelected) const; + int nextItemById(IdType idType, int id, qint64 time, int currentSelected) const; + QVector ranges; QVector endTimes; diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp index 92285084aa6..088bf269f68 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -214,11 +214,6 @@ int TimelineModelAggregator::firstIndex(int modelIndex, qint64 startTime) const return d->modelList[modelIndex]->firstIndex(startTime); } -int TimelineModelAggregator::firstIndexNoParents(int modelIndex, qint64 startTime) const -{ - return d->modelList[modelIndex]->firstIndexNoParents(startTime); -} - int TimelineModelAggregator::lastIndex(int modelIndex, qint64 endTime) const { return d->modelList[modelIndex]->lastIndex(endTime); @@ -376,5 +371,114 @@ int TimelineModelAggregator::modelCount() const return d->modelList.count(); } +QVariantMap TimelineModelAggregator::nextItem(int selectedModel, int selectedItem, + qint64 time) const +{ + if (selectedItem != -1) + time = model(selectedModel)->startTime(selectedItem); + + QVarLengthArray itemIndexes(modelCount()); + for (int i = 0; i < modelCount(); i++) { + const QmlProfilerTimelineModel *currentModel = model(i); + if (currentModel->count() > 0) { + if (selectedModel == i) { + itemIndexes[i] = (selectedItem + 1) % currentModel->count(); + } else { + if (currentModel->startTime(0) > time) + itemIndexes[i] = 0; + else + itemIndexes[i] = (currentModel->lastIndex(time) + 1) % currentModel->count(); + } + } else { + itemIndexes[i] = -1; + } + } + + int candidateModelIndex = -1; + qint64 candidateStartTime = std::numeric_limits::max(); + for (int i = 0; i < modelCount(); i++) { + if (itemIndexes[i] == -1) + continue; + qint64 newStartTime = model(i)->startTime(itemIndexes[i]); + if (newStartTime > time && newStartTime < candidateStartTime) { + candidateStartTime = newStartTime; + candidateModelIndex = i; + } + } + + int itemIndex; + if (candidateModelIndex != -1) { + itemIndex = itemIndexes[candidateModelIndex]; + } else { + itemIndex = -1; + candidateStartTime = std::numeric_limits::max(); + for (int i = 0; i < modelCount(); i++) { + const QmlProfilerTimelineModel *currentModel = model(i); + if (currentModel->count() > 0 && currentModel->startTime(0) < candidateStartTime) { + candidateModelIndex = i; + itemIndex = 0; + candidateStartTime = currentModel->startTime(0); + } + } + } + + QVariantMap ret; + ret.insert(QLatin1String("model"), candidateModelIndex); + ret.insert(QLatin1String("item"), itemIndex); + return ret; +} + +QVariantMap TimelineModelAggregator::prevItem(int selectedModel, int selectedItem, + qint64 time) const +{ + if (selectedItem != -1) + time = model(selectedModel)->startTime(selectedItem); + + QVarLengthArray itemIndexes(modelCount()); + for (int i = 0; i < modelCount(); i++) { + if (selectedModel == i) { + itemIndexes[i] = selectedItem - 1; + if (itemIndexes[i] < 0) + itemIndexes[i] = model(selectedModel)->count() -1; + } + else + itemIndexes[i] = model(i)->lastIndex(time); + } + + int candidateModelIndex = -1; + qint64 candidateStartTime = std::numeric_limits::min(); + for (int i = 0; i < modelCount(); i++) { + const QmlProfilerTimelineModel *currentModel = model(i); + if (itemIndexes[i] == -1 || itemIndexes[i] >= currentModel->count()) + continue; + qint64 newStartTime = currentModel->startTime(itemIndexes[i]); + if (newStartTime < time && newStartTime > candidateStartTime) { + candidateStartTime = newStartTime; + candidateModelIndex = i; + } + } + + int itemIndex = -1; + if (candidateModelIndex != -1) { + itemIndex = itemIndexes[candidateModelIndex]; + } else { + candidateStartTime = std::numeric_limits::min(); + for (int i = 0; i < modelCount(); i++) { + const QmlProfilerTimelineModel *currentModel = model(i); + if (currentModel->count() > 0 && + currentModel->startTime(currentModel->count() - 1) > candidateStartTime) { + candidateModelIndex = i; + itemIndex = currentModel->count() - 1; + candidateStartTime = currentModel->startTime(itemIndex); + } + } + } + + QVariantMap ret; + ret.insert(QLatin1String("model"), candidateModelIndex); + ret.insert(QLatin1String("item"), itemIndex); + return ret; +} + } // namespace Internal } // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.h b/src/plugins/qmlprofiler/timelinemodelaggregator.h index 6d594326104..82efb85d8e0 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.h @@ -78,7 +78,6 @@ public: Q_INVOKABLE int rowMaxValue(int modelIndex, int row) const; Q_INVOKABLE int firstIndex(int modelIndex, qint64 startTime) const; - Q_INVOKABLE int firstIndexNoParents(int modelIndex, qint64 startTime) const; Q_INVOKABLE int lastIndex(int modelIndex, qint64 endTime) const; Q_INVOKABLE int row(int modelIndex, int index) const; @@ -111,6 +110,9 @@ public: Q_INVOKABLE QVariantList notesByTypeId(int typeId) const; Q_INVOKABLE int noteCount() const; + Q_INVOKABLE QVariantMap nextItem(int selectedModel, int selectedItem, qint64 time) const; + Q_INVOKABLE QVariantMap prevItem(int selectedModel, int selectedItem, qint64 time) const; + signals: void dataAvailable(); void stateChanged(); diff --git a/src/plugins/qmlprofiler/timelinerenderer.cpp b/src/plugins/qmlprofiler/timelinerenderer.cpp index 64eb6feaff1..5be5eab7559 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.cpp +++ b/src/plugins/qmlprofiler/timelinerenderer.cpp @@ -567,178 +567,6 @@ int TimelineRenderer::getYPosition(int modelIndex, int index) const m_profilerModelProxy->row(modelIndex, index)); } -void TimelineRenderer::selectNext() -{ - if (m_profilerModelProxy->isEmpty()) - return; - - qint64 searchTime = m_zoomer->rangeStart(); - if (m_selectedItem != -1) - searchTime = m_profilerModelProxy->startTime(m_selectedModel, m_selectedItem); - - QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (m_profilerModelProxy->count(i) > 0) { - if (m_selectedModel == i) { - itemIndexes[i] = (m_selectedItem + 1) % m_profilerModelProxy->count(i); - } else { - if (m_profilerModelProxy->startTime(i, 0) > searchTime) - itemIndexes[i] = 0; - else - itemIndexes[i] = (m_profilerModelProxy->lastIndex(i, searchTime) + 1) % m_profilerModelProxy->count(i); - } - } else { - itemIndexes[i] = -1; - } - } - - int candidateModelIndex = -1; - qint64 candidateStartTime = m_zoomer->traceEnd(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (itemIndexes[i] == -1) - continue; - qint64 newStartTime = m_profilerModelProxy->startTime(i, itemIndexes[i]); - if (newStartTime > searchTime && newStartTime < candidateStartTime) { - candidateStartTime = newStartTime; - candidateModelIndex = i; - } - } - - int itemIndex; - if (candidateModelIndex != -1) { - itemIndex = itemIndexes[candidateModelIndex]; - } else { - // find the first index of them all (todo: the modelproxy should do this) - itemIndex = -1; - candidateStartTime = m_zoomer->traceEnd(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) - if (m_profilerModelProxy->count(i) > 0 && - m_profilerModelProxy->startTime(i,0) < candidateStartTime) { - candidateModelIndex = i; - itemIndex = 0; - candidateStartTime = m_profilerModelProxy->startTime(i,0); - } - } - - selectFromEventIndex(candidateModelIndex, itemIndex); -} - -void TimelineRenderer::selectPrev() -{ - if (m_profilerModelProxy->isEmpty()) - return; - - qint64 searchTime = m_zoomer->rangeEnd(); - if (m_selectedItem != -1) - searchTime = m_profilerModelProxy->startTime(m_selectedModel, m_selectedItem); - - QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (m_selectedModel == i) { - itemIndexes[i] = m_selectedItem - 1; - if (itemIndexes[i] < 0) - itemIndexes[i] = m_profilerModelProxy->count(m_selectedModel) -1; - } - else - itemIndexes[i] = m_profilerModelProxy->lastIndex(i, searchTime); - } - - int candidateModelIndex = -1; - qint64 candidateStartTime = m_zoomer->traceStart(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (itemIndexes[i] == -1 - || itemIndexes[i] >= m_profilerModelProxy->count(i)) - continue; - qint64 newStartTime = m_profilerModelProxy->startTime(i, itemIndexes[i]); - if (newStartTime < searchTime && newStartTime > candidateStartTime) { - candidateStartTime = newStartTime; - candidateModelIndex = i; - } - } - - int itemIndex = -1; - if (candidateModelIndex != -1) { - itemIndex = itemIndexes[candidateModelIndex]; - } else { - // find the last index of them all (todo: the modelproxy should do this) - candidateModelIndex = 0; - candidateStartTime = m_zoomer->traceStart(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) - if (m_profilerModelProxy->count(i) > 0 && - m_profilerModelProxy->startTime(i,m_profilerModelProxy->count(i)-1) > candidateStartTime) { - candidateModelIndex = i; - itemIndex = m_profilerModelProxy->count(candidateModelIndex) - 1; - candidateStartTime = m_profilerModelProxy->startTime(i,m_profilerModelProxy->count(i)-1); - } - } - - selectFromEventIndex(candidateModelIndex, itemIndex); -} - -int TimelineRenderer::nextItemFromSelectionId(int modelIndex, int selectionId) const -{ - return nextItemFromId(modelIndex, SelectionId, selectionId); -} - -int TimelineRenderer::nextItemFromTypeId(int modelIndex, int typeId) const -{ - return nextItemFromId(modelIndex, TypeId, typeId); -} - -int TimelineRenderer::prevItemFromSelectionId(int modelIndex, int selectionId) const -{ - return prevItemFromId(modelIndex, SelectionId, selectionId); -} - -int TimelineRenderer::prevItemFromTypeId(int modelIndex, int typeId) const -{ - return prevItemFromId(modelIndex, TypeId, typeId); -} - -int TimelineRenderer::nextItemFromId(int modelIndex, IdType idType, int id) const -{ - int modelCount = m_profilerModelProxy->count(modelIndex); - if (modelCount == 0) - return -1; - - int ndx = -1; - if (m_selectedItem == -1 || modelIndex != m_selectedModel) - ndx = m_profilerModelProxy->firstIndexNoParents(modelIndex, m_zoomer->rangeStart()); - else - ndx = m_selectedItem + 1; - - if (ndx < 0 || ndx >= modelCount) - ndx = 0; - int startIndex = ndx; - do { - if ((idType == TypeId && m_profilerModelProxy->typeId(modelIndex, ndx) == id) || - (idType == SelectionId && m_profilerModelProxy->selectionId(modelIndex, ndx) == id)) - return ndx; - ndx = (ndx + 1) % modelCount; - } while (ndx != startIndex); - return -1; -} - -int TimelineRenderer::prevItemFromId(int modelIndex, IdType idType, int id) const -{ - int ndx = -1; - if (m_selectedItem == -1 || modelIndex != m_selectedModel) - ndx = m_profilerModelProxy->firstIndexNoParents(modelIndex, m_zoomer->rangeStart()); - else - ndx = m_selectedItem - 1; - if (ndx < 0) - ndx = m_profilerModelProxy->count(modelIndex) - 1; - int startIndex = ndx; - do { - if ((idType == TypeId && m_profilerModelProxy->typeId(modelIndex, ndx) == id) || - (idType == SelectionId && m_profilerModelProxy->selectionId(modelIndex, ndx) == id)) - return ndx; - if (--ndx < 0) - ndx = m_profilerModelProxy->count(modelIndex)-1; - } while (ndx != startIndex); - return -1; -} - void TimelineRenderer::selectFromEventIndex(int modelIndex, int eventIndex) { if (modelIndex != m_selectedModel || eventIndex != m_selectedItem) { @@ -748,12 +576,14 @@ void TimelineRenderer::selectFromEventIndex(int modelIndex, int eventIndex) } } -void TimelineRenderer::selectNextFromSelectionId(int modelIndex, int typeId) +void TimelineRenderer::selectNextFromSelectionId(int modelIndex, int selectionId) { - selectFromEventIndex(modelIndex, nextItemFromSelectionId(modelIndex, typeId)); + selectFromEventIndex(modelIndex, m_profilerModelProxy->model(modelIndex)->nextItemBySelectionId( + selectionId, m_zoomer->rangeStart(), m_selectedItem)); } -void TimelineRenderer::selectPrevFromSelectionId(int modelIndex, int typeId) +void TimelineRenderer::selectPrevFromSelectionId(int modelIndex, int selectionId) { - selectFromEventIndex(modelIndex, prevItemFromSelectionId(modelIndex, typeId)); + selectFromEventIndex(modelIndex, m_profilerModelProxy->model(modelIndex)->prevItemBySelectionId( + selectionId, m_zoomer->rangeStart(), m_selectedItem)); } diff --git a/src/plugins/qmlprofiler/timelinerenderer.h b/src/plugins/qmlprofiler/timelinerenderer.h index b3b76446b1f..c8fe232ee57 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.h +++ b/src/plugins/qmlprofiler/timelinerenderer.h @@ -86,12 +86,6 @@ public: Q_INVOKABLE int getYPosition(int modelIndex, int index) const; - Q_INVOKABLE void selectNext(); - Q_INVOKABLE void selectPrev(); - Q_INVOKABLE int nextItemFromSelectionId(int modelIndex, int selectionId) const; - Q_INVOKABLE int nextItemFromTypeId(int modelIndex, int typeId) const; - Q_INVOKABLE int prevItemFromSelectionId(int modelIndex, int selectionId) const; - Q_INVOKABLE int prevItemFromTypeId(int modelIndex, int typeId) const; Q_INVOKABLE void selectFromEventIndex(int modelIndex, int index); Q_INVOKABLE void selectNextFromSelectionId(int modelIndex, int selectionId); Q_INVOKABLE void selectPrevFromSelectionId(int modelIndex, int selectionId); @@ -203,8 +197,6 @@ private: bool m_selectionLocked; int m_startDragArea; int m_endDragArea; - int nextItemFromId(int modelIndex, IdType idType, int id) const; - int prevItemFromId(int modelIndex, IdType idType, int id) const; }; } // namespace Internal