2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2012-02-24 10:47:17 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-02-24 10:47:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2012-02-24 10:47:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-02-24 10:47:17 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2012-02-24 10:47:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2012-02-24 10:47:17 +01:00
|
|
|
|
|
|
|
|
#include "qmlprofilertraceview.h"
|
|
|
|
|
#include "qmlprofilertool.h"
|
|
|
|
|
#include "qmlprofilerstatemanager.h"
|
2013-08-08 13:28:08 +02:00
|
|
|
#include "qmlprofilermodelmanager.h"
|
2014-11-04 14:41:32 +01:00
|
|
|
#include "qmlprofilernotesmodel.h"
|
2014-12-05 17:33:21 +01:00
|
|
|
#include "qmlprofileranimationsmodel.h"
|
|
|
|
|
#include "qmlprofilerrangemodel.h"
|
|
|
|
|
#include "qmlprofilerplugin.h"
|
2012-02-24 10:47:17 +01:00
|
|
|
|
2016-04-26 10:21:00 +02:00
|
|
|
#include "inputeventsmodel.h"
|
|
|
|
|
#include "pixmapcachemodel.h"
|
|
|
|
|
#include "debugmessagesmodel.h"
|
|
|
|
|
#include "flamegraphview.h"
|
|
|
|
|
#include "memoryusagemodel.h"
|
|
|
|
|
#include "scenegraphtimelinemodel.h"
|
|
|
|
|
|
2013-08-08 13:28:08 +02:00
|
|
|
// Communication with the other views (limit events to range)
|
2012-02-24 10:47:17 +01:00
|
|
|
#include "qmlprofilerviewmanager.h"
|
2014-12-10 12:53:49 +01:00
|
|
|
|
|
|
|
|
#include "timeline/timelinezoomcontrol.h"
|
|
|
|
|
#include "timeline/timelinemodelaggregator.h"
|
|
|
|
|
#include "timeline/timelinerenderer.h"
|
|
|
|
|
#include "timeline/timelineoverviewrenderer.h"
|
2016-06-17 16:21:04 +02:00
|
|
|
#include "timeline/timelinetheme.h"
|
2016-12-19 11:29:40 +01:00
|
|
|
#include "timeline/timelineformattime.h"
|
2014-12-10 12:53:49 +01:00
|
|
|
|
2015-05-08 14:30:30 +02:00
|
|
|
#include <aggregation/aggregate.h>
|
2014-12-10 12:53:49 +01:00
|
|
|
// Needed for the load&save actions in the context menu
|
2016-02-26 14:14:49 +01:00
|
|
|
#include <debugger/analyzer/analyzermanager.h>
|
2015-05-08 14:30:30 +02:00
|
|
|
#include <coreplugin/findplaceholder.h>
|
2012-02-24 10:47:17 +01:00
|
|
|
#include <utils/styledbar.h>
|
2016-08-11 13:44:40 +02:00
|
|
|
#include <utils/algorithm.h>
|
2012-02-24 10:47:17 +01:00
|
|
|
|
2013-09-16 14:33:07 +02:00
|
|
|
#include <QQmlContext>
|
2012-02-24 10:47:17 +01:00
|
|
|
#include <QToolButton>
|
|
|
|
|
#include <QEvent>
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
#include <QGraphicsObject>
|
|
|
|
|
#include <QScrollBar>
|
|
|
|
|
#include <QSlider>
|
|
|
|
|
#include <QMenu>
|
2013-09-16 14:33:07 +02:00
|
|
|
#include <QQuickItem>
|
2015-02-05 12:26:06 +01:00
|
|
|
#include <QQuickWidget>
|
2014-02-21 18:34:05 +01:00
|
|
|
#include <QApplication>
|
2015-05-08 14:30:30 +02:00
|
|
|
#include <QTextCursor>
|
2012-02-24 10:47:17 +01:00
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
namespace QmlProfiler {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
class QmlProfilerTraceView::QmlProfilerTraceViewPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {}
|
|
|
|
|
QmlProfilerTraceView *q;
|
|
|
|
|
QmlProfilerViewManager *m_viewContainer;
|
2015-02-05 12:26:06 +01:00
|
|
|
QQuickWidget *m_mainView;
|
2013-08-08 13:28:08 +02:00
|
|
|
QmlProfilerModelManager *m_modelManager;
|
2016-08-11 13:44:40 +02:00
|
|
|
QVariantList m_suspendedModels;
|
2014-12-09 11:01:23 +01:00
|
|
|
Timeline::TimelineModelAggregator *m_modelProxy;
|
|
|
|
|
Timeline::TimelineZoomControl *m_zoomControl;
|
2012-02-24 10:47:17 +01:00
|
|
|
};
|
|
|
|
|
|
2016-01-04 17:20:13 +01:00
|
|
|
QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManager *container,
|
|
|
|
|
QmlProfilerModelManager *modelManager)
|
2012-02-24 10:47:17 +01:00
|
|
|
: QWidget(parent), d(new QmlProfilerTraceViewPrivate(this))
|
|
|
|
|
{
|
2016-12-14 13:50:20 +01:00
|
|
|
setWindowTitle(tr("Timeline"));
|
|
|
|
|
setObjectName("QmlProfiler.Timeline.Dock");
|
2012-02-24 10:47:17 +01:00
|
|
|
|
2014-12-09 11:01:23 +01:00
|
|
|
d->m_zoomControl = new Timeline::TimelineZoomControl(this);
|
2016-04-28 15:43:00 +02:00
|
|
|
connect(modelManager, &QmlProfilerModelManager::stateChanged, this, [modelManager, this]() {
|
2016-08-11 13:44:40 +02:00
|
|
|
switch (modelManager->state()) {
|
|
|
|
|
case QmlProfilerModelManager::Done: {
|
2016-04-28 15:43:00 +02:00
|
|
|
qint64 start = modelManager->traceTime()->startTime();
|
|
|
|
|
qint64 end = modelManager->traceTime()->endTime();
|
|
|
|
|
d->m_zoomControl->setTrace(start, end);
|
|
|
|
|
d->m_zoomControl->setRange(start, start + (end - start) / 10);
|
2016-08-11 13:44:40 +02:00
|
|
|
// Fall through
|
|
|
|
|
}
|
|
|
|
|
case QmlProfilerModelManager::Empty:
|
|
|
|
|
d->m_modelProxy->setModels(d->m_suspendedModels);
|
|
|
|
|
d->m_suspendedModels.clear();
|
|
|
|
|
break;
|
|
|
|
|
case QmlProfilerModelManager::ProcessingData:
|
|
|
|
|
break;
|
|
|
|
|
case QmlProfilerModelManager::ClearingData:
|
2016-04-28 15:43:00 +02:00
|
|
|
d->m_zoomControl->clear();
|
2016-08-11 13:44:40 +02:00
|
|
|
// Fall through
|
|
|
|
|
case QmlProfilerModelManager::AcquiringData:
|
|
|
|
|
// Temporarily remove the models, while we're changing them
|
|
|
|
|
d->m_suspendedModels = d->m_modelProxy->models();
|
|
|
|
|
d->m_modelProxy->setModels(QVariantList());
|
|
|
|
|
break;
|
2016-04-28 15:43:00 +02:00
|
|
|
}
|
2015-04-08 19:05:30 +02:00
|
|
|
});
|
2012-02-24 10:47:17 +01:00
|
|
|
|
|
|
|
|
QVBoxLayout *groupLayout = new QVBoxLayout;
|
|
|
|
|
groupLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
groupLayout->setSpacing(0);
|
|
|
|
|
|
2014-12-09 11:01:23 +01:00
|
|
|
qmlRegisterType<Timeline::TimelineRenderer>("TimelineRenderer", 1, 0, "TimelineRenderer");
|
2014-12-09 18:27:56 +01:00
|
|
|
qmlRegisterType<Timeline::TimelineOverviewRenderer>("TimelineOverviewRenderer", 1, 0,
|
|
|
|
|
"TimelineOverviewRenderer");
|
2014-12-09 11:01:23 +01:00
|
|
|
qmlRegisterType<Timeline::TimelineZoomControl>();
|
|
|
|
|
qmlRegisterType<Timeline::TimelineModel>();
|
|
|
|
|
qmlRegisterType<Timeline::TimelineNotesModel>();
|
2014-11-04 14:41:32 +01:00
|
|
|
|
2015-02-05 12:26:06 +01:00
|
|
|
d->m_mainView = new QQuickWidget(this);
|
|
|
|
|
d->m_mainView->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
|
|
|
|
d->m_mainView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
2015-05-08 14:30:30 +02:00
|
|
|
setFocusProxy(d->m_mainView);
|
|
|
|
|
|
|
|
|
|
Aggregation::Aggregate *agg = new Aggregation::Aggregate;
|
|
|
|
|
agg->add(d->m_mainView);
|
|
|
|
|
agg->add(new TraceViewFindSupport(this, modelManager));
|
2012-02-24 10:47:17 +01:00
|
|
|
|
2015-02-05 12:26:06 +01:00
|
|
|
groupLayout->addWidget(d->m_mainView);
|
2015-05-08 14:30:30 +02:00
|
|
|
groupLayout->addWidget(new Core::FindToolBarPlaceHolder(this));
|
2012-02-24 10:47:17 +01:00
|
|
|
setLayout(groupLayout);
|
|
|
|
|
|
|
|
|
|
d->m_viewContainer = container;
|
2014-12-09 11:01:23 +01:00
|
|
|
d->m_modelProxy = new Timeline::TimelineModelAggregator(modelManager->notesModel(), this);
|
2014-12-05 17:33:21 +01:00
|
|
|
d->m_modelManager = modelManager;
|
2014-12-09 10:35:01 +01:00
|
|
|
|
2016-11-23 16:47:04 +01:00
|
|
|
QVariantList models;
|
|
|
|
|
models.append(QVariant::fromValue(new PixmapCacheModel(modelManager, d->m_modelProxy)));
|
|
|
|
|
models.append(QVariant::fromValue(new SceneGraphTimelineModel(modelManager, d->m_modelProxy)));
|
|
|
|
|
models.append(QVariant::fromValue(new MemoryUsageModel(modelManager, d->m_modelProxy)));
|
|
|
|
|
models.append(QVariant::fromValue(new InputEventsModel(modelManager, d->m_modelProxy)));
|
|
|
|
|
models.append(QVariant::fromValue(new DebugMessagesModel(modelManager, d->m_modelProxy)));
|
|
|
|
|
models.append(QVariant::fromValue(new QmlProfilerAnimationsModel(modelManager,
|
|
|
|
|
d->m_modelProxy)));
|
|
|
|
|
for (int i = 0; i < MaximumRangeType; ++i) {
|
|
|
|
|
models.append(QVariant::fromValue(new QmlProfilerRangeModel(modelManager, (RangeType)i,
|
|
|
|
|
d->m_modelProxy)));
|
|
|
|
|
}
|
2016-05-25 18:23:26 +02:00
|
|
|
d->m_modelProxy->setModels(models);
|
2014-12-05 17:33:21 +01:00
|
|
|
|
2014-12-09 10:35:01 +01:00
|
|
|
// Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin
|
|
|
|
|
setMinimumHeight(170);
|
2012-02-24 10:47:17 +01:00
|
|
|
|
2016-06-17 16:21:04 +02:00
|
|
|
Timeline::TimelineTheme::setupTheme(d->m_mainView->engine());
|
2016-12-19 11:29:40 +01:00
|
|
|
Timeline::TimeFormatter::setupTimeFormatter();
|
2016-06-17 16:21:04 +02:00
|
|
|
|
2014-12-09 10:35:01 +01:00
|
|
|
d->m_mainView->rootContext()->setContextProperty(QLatin1String("timelineModelAggregator"),
|
|
|
|
|
d->m_modelProxy);
|
|
|
|
|
d->m_mainView->rootContext()->setContextProperty(QLatin1String("zoomControl"),
|
|
|
|
|
d->m_zoomControl);
|
2014-12-10 12:53:49 +01:00
|
|
|
d->m_mainView->setSource(QUrl(QLatin1String("qrc:/timeline/MainView.qml")));
|
2012-12-30 12:01:41 +01:00
|
|
|
|
2013-10-30 13:49:01 +01:00
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
2012-12-30 12:01:41 +01:00
|
|
|
connect(rootObject, SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-09 10:35:01 +01:00
|
|
|
QmlProfilerTraceView::~QmlProfilerTraceView()
|
|
|
|
|
{
|
|
|
|
|
delete d->m_mainView;
|
|
|
|
|
delete d;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 10:47:17 +01:00
|
|
|
bool QmlProfilerTraceView::hasValidSelection() const
|
|
|
|
|
{
|
2013-09-16 14:33:07 +02:00
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
2012-12-30 12:01:41 +01:00
|
|
|
if (rootObject)
|
|
|
|
|
return rootObject->property("selectionRangeReady").toBool();
|
2012-02-24 10:47:17 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qint64 QmlProfilerTraceView::selectionStart() const
|
|
|
|
|
{
|
2015-03-23 18:50:47 +01:00
|
|
|
return d->m_zoomControl->selectionStart();
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qint64 QmlProfilerTraceView::selectionEnd() const
|
|
|
|
|
{
|
2015-03-23 18:50:47 +01:00
|
|
|
return d->m_zoomControl->selectionEnd();
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-25 17:10:25 +01:00
|
|
|
void QmlProfilerTraceView::clear()
|
2012-02-24 10:47:17 +01:00
|
|
|
{
|
2014-03-25 17:10:25 +01:00
|
|
|
QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clear");
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-29 16:32:42 +02:00
|
|
|
void QmlProfilerTraceView::selectByTypeId(int typeId)
|
2012-02-24 10:47:17 +01:00
|
|
|
{
|
2013-09-16 14:33:07 +02:00
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
2014-06-12 13:08:08 +02:00
|
|
|
if (!rootObject)
|
|
|
|
|
return;
|
2014-10-28 12:56:53 +01:00
|
|
|
QMetaObject::invokeMethod(rootObject, "selectByTypeId", Q_ARG(QVariant,QVariant(typeId)));
|
2013-08-08 13:28:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-30 16:52:11 +01:00
|
|
|
void QmlProfilerTraceView::selectByEventIndex(int modelId, int eventIndex)
|
|
|
|
|
{
|
|
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
|
|
|
|
if (!rootObject)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const int modelIndex = d->m_modelProxy->modelIndexById(modelId);
|
|
|
|
|
QTC_ASSERT(modelIndex != -1, return);
|
|
|
|
|
QMetaObject::invokeMethod(rootObject, "selectByIndices",
|
|
|
|
|
Q_ARG(QVariant, QVariant(modelIndex)),
|
|
|
|
|
Q_ARG(QVariant, QVariant(eventIndex)));
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 10:47:17 +01:00
|
|
|
// Goto source location
|
|
|
|
|
void QmlProfilerTraceView::updateCursorPosition()
|
|
|
|
|
{
|
2013-09-16 14:33:07 +02:00
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
2014-09-29 16:24:34 +02:00
|
|
|
QString file = rootObject->property("fileName").toString();
|
|
|
|
|
if (!file.isEmpty())
|
|
|
|
|
emit gotoSourceLocation(file, rootObject->property("lineNumber").toInt(),
|
|
|
|
|
rootObject->property("columnNumber").toInt());
|
|
|
|
|
|
|
|
|
|
emit typeSelected(rootObject->property("typeId").toInt());
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-28 16:06:07 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 10:47:17 +01:00
|
|
|
void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)
|
2014-02-21 18:34:05 +01:00
|
|
|
{
|
|
|
|
|
showContextMenu(ev->globalPos());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlProfilerTraceView::showContextMenu(QPoint position)
|
2012-02-24 10:47:17 +01:00
|
|
|
{
|
|
|
|
|
QMenu menu;
|
|
|
|
|
QAction *viewAllAction = 0;
|
|
|
|
|
|
2016-01-04 17:20:13 +01:00
|
|
|
menu.addActions(QmlProfilerTool::profilerContextMenuActions());
|
2012-02-24 10:47:17 +01:00
|
|
|
menu.addSeparator();
|
2012-12-30 12:01:41 +01:00
|
|
|
|
2015-12-04 16:54:58 +01:00
|
|
|
QAction *getLocalStatsAction = menu.addAction(tr("Analyze Current Range"));
|
2012-02-24 10:47:17 +01:00
|
|
|
if (!d->m_viewContainer->hasValidSelection())
|
|
|
|
|
getLocalStatsAction->setEnabled(false);
|
2012-12-30 12:01:41 +01:00
|
|
|
|
2015-12-04 16:54:58 +01:00
|
|
|
QAction *getGlobalStatsAction = menu.addAction(tr("Analyze Full Range"));
|
2015-12-04 13:02:12 +01:00
|
|
|
if (!d->m_viewContainer->isEventsRestrictedToRange())
|
2012-02-24 10:47:17 +01:00
|
|
|
getGlobalStatsAction->setEnabled(false);
|
|
|
|
|
|
2014-10-30 14:57:49 +01:00
|
|
|
if (d->m_zoomControl->traceDuration() > 0) {
|
2012-02-24 10:47:17 +01:00
|
|
|
menu.addSeparator();
|
|
|
|
|
viewAllAction = menu.addAction(tr("Reset Zoom"));
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-21 18:34:05 +01:00
|
|
|
QAction *selectedAction = menu.exec(position);
|
2012-02-24 10:47:17 +01:00
|
|
|
|
|
|
|
|
if (selectedAction) {
|
|
|
|
|
if (selectedAction == viewAllAction) {
|
2014-10-14 16:44:45 +02:00
|
|
|
d->m_zoomControl->setRange(d->m_zoomControl->traceStart(),
|
|
|
|
|
d->m_zoomControl->traceEnd());
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
if (selectedAction == getLocalStatsAction) {
|
2015-12-04 13:02:12 +01:00
|
|
|
d->m_viewContainer->restrictEventsToRange(d->m_viewContainer->selectionStart(),
|
|
|
|
|
d->m_viewContainer->selectionEnd());
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
2013-11-11 22:20:47 +02:00
|
|
|
if (selectedAction == getGlobalStatsAction)
|
2015-12-04 13:02:12 +01:00
|
|
|
d->m_viewContainer->restrictEventsToRange(-1, -1);
|
2012-02-24 10:47:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-14 13:40:23 +01:00
|
|
|
bool QmlProfilerTraceView::isUsable() const
|
|
|
|
|
{
|
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
|
|
|
|
return d->m_mainView->quickWindow()->rendererInterface()->graphicsApi()
|
|
|
|
|
== QSGRendererInterface::OpenGL;
|
|
|
|
|
#else
|
|
|
|
|
return true;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-10 20:29:54 +01:00
|
|
|
void QmlProfilerTraceView::changeEvent(QEvent *e)
|
|
|
|
|
{
|
|
|
|
|
if (e->type() == QEvent::EnabledChange) {
|
|
|
|
|
QQuickItem *rootObject = d->m_mainView->rootObject();
|
|
|
|
|
rootObject->setProperty("enabled", isEnabled());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-08 14:30:30 +02:00
|
|
|
TraceViewFindSupport::TraceViewFindSupport(QmlProfilerTraceView *view,
|
|
|
|
|
QmlProfilerModelManager *manager)
|
|
|
|
|
: m_view(view), m_modelManager(manager)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TraceViewFindSupport::supportsReplace() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::FindFlags TraceViewFindSupport::supportedFindFlags() const
|
|
|
|
|
{
|
|
|
|
|
return Core::FindBackward | Core::FindCaseSensitively | Core::FindRegularExpression
|
|
|
|
|
| Core::FindWholeWords;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TraceViewFindSupport::resetIncrementalSearch()
|
|
|
|
|
{
|
|
|
|
|
m_incrementalStartPos = -1;
|
|
|
|
|
m_incrementalWrappedState = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TraceViewFindSupport::clearHighlights()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString TraceViewFindSupport::currentFindString() const
|
|
|
|
|
{
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString TraceViewFindSupport::completedFindString() const
|
|
|
|
|
{
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::IFindSupport::Result TraceViewFindSupport::findIncremental(const QString &txt,
|
|
|
|
|
Core::FindFlags findFlags)
|
|
|
|
|
{
|
|
|
|
|
if (m_incrementalStartPos < 0)
|
|
|
|
|
m_incrementalStartPos = qMax(m_currentPosition, 0);
|
|
|
|
|
bool wrapped = false;
|
|
|
|
|
bool found = find(txt, findFlags, m_incrementalStartPos, &wrapped);
|
|
|
|
|
if (wrapped != m_incrementalWrappedState && found) {
|
|
|
|
|
m_incrementalWrappedState = wrapped;
|
|
|
|
|
showWrapIndicator(m_view);
|
|
|
|
|
}
|
|
|
|
|
return found ? Core::IFindSupport::Found : Core::IFindSupport::NotFound;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::IFindSupport::Result TraceViewFindSupport::findStep(const QString &txt,
|
|
|
|
|
Core::FindFlags findFlags)
|
|
|
|
|
{
|
|
|
|
|
int start = (findFlags & Core::FindBackward) ? m_currentPosition : m_currentPosition + 1;
|
|
|
|
|
bool wrapped;
|
|
|
|
|
bool found = find(txt, findFlags, start, &wrapped);
|
|
|
|
|
if (wrapped)
|
|
|
|
|
showWrapIndicator(m_view);
|
|
|
|
|
if (found) {
|
|
|
|
|
m_incrementalStartPos = m_currentPosition;
|
|
|
|
|
m_incrementalWrappedState = false;
|
|
|
|
|
}
|
|
|
|
|
return found ? Core::IFindSupport::Found : Core::IFindSupport::NotFound;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "start" is the model index that is searched first in a forward search, i.e. as if the
|
|
|
|
|
// "cursor" were between start-1 and start
|
|
|
|
|
bool TraceViewFindSupport::find(const QString &txt, Core::FindFlags findFlags, int start,
|
|
|
|
|
bool *wrapped)
|
|
|
|
|
{
|
|
|
|
|
if (wrapped)
|
|
|
|
|
*wrapped = false;
|
|
|
|
|
if (!findOne(txt, findFlags, start)) {
|
|
|
|
|
int secondStart;
|
|
|
|
|
if (findFlags & Core::FindBackward)
|
|
|
|
|
secondStart = m_modelManager->notesModel()->count();
|
|
|
|
|
else
|
|
|
|
|
secondStart = 0;
|
|
|
|
|
if (!findOne(txt, findFlags, secondStart))
|
|
|
|
|
return false;
|
|
|
|
|
if (wrapped)
|
|
|
|
|
*wrapped = true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "start" is the model index that is searched first in a forward search, i.e. as if the
|
|
|
|
|
// "cursor" were between start-1 and start
|
|
|
|
|
bool TraceViewFindSupport::findOne(const QString &txt, Core::FindFlags findFlags, int start)
|
|
|
|
|
{
|
|
|
|
|
bool caseSensitiveSearch = (findFlags & Core::FindCaseSensitively);
|
|
|
|
|
QRegExp regexp(txt);
|
|
|
|
|
regexp.setPatternSyntax((findFlags & Core::FindRegularExpression) ? QRegExp::RegExp : QRegExp::FixedString);
|
|
|
|
|
regexp.setCaseSensitivity(caseSensitiveSearch ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
|
|
|
QTextDocument::FindFlags flags;
|
|
|
|
|
if (caseSensitiveSearch)
|
|
|
|
|
flags |= QTextDocument::FindCaseSensitively;
|
|
|
|
|
if (findFlags & Core::FindWholeWords)
|
|
|
|
|
flags |= QTextDocument::FindWholeWords;
|
|
|
|
|
bool forwardSearch = !(findFlags & Core::FindBackward);
|
|
|
|
|
int increment = forwardSearch ? +1 : -1;
|
|
|
|
|
int current = forwardSearch ? start : start - 1;
|
|
|
|
|
QmlProfilerNotesModel *model = m_modelManager->notesModel();
|
|
|
|
|
while (current >= 0 && current < model->count()) {
|
|
|
|
|
QTextDocument doc(model->text(current)); // for automatic handling of WholeWords option
|
|
|
|
|
if (!doc.find(regexp, 0, flags).isNull()) {
|
|
|
|
|
m_currentPosition = current;
|
|
|
|
|
m_view->selectByEventIndex(model->timelineModel(m_currentPosition),
|
|
|
|
|
model->timelineIndex(m_currentPosition));
|
2016-05-02 10:50:55 +02:00
|
|
|
QWidget *findBar = QApplication::focusWidget();
|
2015-11-11 11:47:12 +01:00
|
|
|
m_view->updateCursorPosition(); // open file/line that belongs to event
|
2016-05-02 10:50:55 +02:00
|
|
|
QTC_ASSERT(findBar, return true);
|
|
|
|
|
findBar->setFocus();
|
2015-05-08 14:30:30 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
current += increment;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 10:47:17 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace QmlProfiler
|