diff --git a/src/plugins/qmlprofiler/debugmessagesmodel.cpp b/src/plugins/qmlprofiler/debugmessagesmodel.cpp
index 2aa79c00609cfec1b7dde80b6bdb881ff8146962..ef100f19b0147ffc9da0763173f0361147452f78 100644
--- a/src/plugins/qmlprofiler/debugmessagesmodel.cpp
+++ b/src/plugins/qmlprofiler/debugmessagesmodel.cpp
@@ -76,10 +76,10 @@ QVariantMap DebugMessagesModel::details(int index) const
     const QmlEventType &type = modelManager()->qmlModel()->eventTypes()[m_data[index].typeId];
 
     QVariantMap result;
-    result.insert(QLatin1String("displayName"), messageType(type.detailType));
+    result.insert(QLatin1String("displayName"), messageType(type.detailType()));
     result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index)));
     result.insert(tr("Message"), m_data[index].text);
-    result.insert(tr("Location"), type.displayName);
+    result.insert(tr("Location"), type.displayName());
     return result;
 }
 
@@ -96,9 +96,9 @@ int DebugMessagesModel::collapsedRow(int index) const
 
 void DebugMessagesModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
-    m_data.insert(insert(event.timestamp(), 0, type.detailType),
+    m_data.insert(insert(event.timestamp(), 0, type.detailType()),
                   MessageData(event.string(), event.typeIndex()));
-    if (type.detailType > m_maximumMsgType)
+    if (type.detailType() > m_maximumMsgType)
         m_maximumMsgType = event.typeIndex();
 }
 
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp
index 46313337baacaecd7a886441d9477401eec0da38..3d40df22f182359a85396f71c28fcf4d0e01706d 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.cpp
+++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp
@@ -168,14 +168,14 @@ QVariant FlameGraphModel::lookup(const FlameGraphData &stats, int role) const
         const QmlEventType &type = typeList[stats.typeIndex];
 
         switch (role) {
-        case FilenameRole: return type.location.filename();
-        case LineRole: return type.location.line();
-        case ColumnRole: return type.location.column();
-        case TypeRole: return nameForType(type.rangeType);
-        case RangeTypeRole: return type.rangeType;
-        case DetailsRole: return type.data.isEmpty() ?
-                        FlameGraphModel::tr("Source code not available") : type.data;
-        case LocationRole: return type.displayName;
+        case FilenameRole: return type.location().filename();
+        case LineRole: return type.location().line();
+        case ColumnRole: return type.location().column();
+        case TypeRole: return nameForType(type.rangeType());
+        case RangeTypeRole: return type.rangeType();
+        case DetailsRole: return type.data().isEmpty() ?
+                        FlameGraphModel::tr("Source code not available") : type.data();
+        case LocationRole: return type.displayName();
         default: return QVariant();
         }
     } else {
diff --git a/src/plugins/qmlprofiler/inputeventsmodel.cpp b/src/plugins/qmlprofiler/inputeventsmodel.cpp
index 17114a1a967410f90d68d190fd5a11afccbaba56..a7827ee3aade3070992e548479b1d3b2ba21404f 100644
--- a/src/plugins/qmlprofiler/inputeventsmodel.cpp
+++ b/src/plugins/qmlprofiler/inputeventsmodel.cpp
@@ -142,11 +142,11 @@ int InputEventsModel::collapsedRow(int index) const
 
 void InputEventsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
-    m_data.insert(insert(event.timestamp(), 0, type.detailType),
+    m_data.insert(insert(event.timestamp(), 0, type.detailType()),
                   InputEvent(static_cast<InputEventType>(event.number<qint32>(0)),
                              event.number<qint32>(1), event.number<qint32>(2)));
 
-    if (type.detailType == Mouse) {
+    if (type.detailType() == Mouse) {
         if (m_mouseTypeId == -1)
             m_mouseTypeId = event.typeIndex();
     } else if (m_keyTypeId == -1) {
@@ -170,7 +170,7 @@ void InputEventsModel::clear()
 bool InputEventsModel::accepted(const QmlEventType &type) const
 {
     return QmlProfilerTimelineModel::accepted(type) &&
-            (type.detailType == Mouse || type.detailType == Key);
+            (type.detailType() == Mouse || type.detailType() == Key);
 }
 
 InputEventsModel::InputEvent::InputEvent(InputEventType type, int a, int b) :
diff --git a/src/plugins/qmlprofiler/memoryusagemodel.cpp b/src/plugins/qmlprofiler/memoryusagemodel.cpp
index b7f85e1684ade5c358962fe2b723b793fe3cf7ee..d07b40df2fbe19209aef0ecc6c8e6e85ea296bee 100644
--- a/src/plugins/qmlprofiler/memoryusagemodel.cpp
+++ b/src/plugins/qmlprofiler/memoryusagemodel.cpp
@@ -122,19 +122,19 @@ QVariantMap MemoryUsageModel::details(int index) const
     result.insert(tr("Type"), memoryTypeName);
 
     result.insert(tr("Location"),
-                  modelManager()->qmlModel()->eventTypes().at(ev->typeId).displayName);
+                  modelManager()->qmlModel()->eventTypes().at(ev->typeId).displayName());
     return result;
 }
 
 bool MemoryUsageModel::accepted(const QmlEventType &type) const
 {
-    return QmlProfilerTimelineModel::accepted(type) || type.rangeType != MaximumRangeType;
+    return QmlProfilerTimelineModel::accepted(type) || type.rangeType() != MaximumRangeType;
 }
 
 void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
-    if (type.message != MemoryAllocation) {
-        if (type.rangeType != MaximumRangeType) {
+    if (type.message() != MemoryAllocation) {
+        if (type.rangeType() != MaximumRangeType) {
             if (event.rangeStage() == RangeStart)
                 m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp()));
             else if (event.rangeStage() == RangeEnd)
@@ -164,7 +164,7 @@ void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type
         }
     };
 
-    if (type.detailType == SmallItem || type.detailType == LargeItem) {
+    if (type.detailType() == SmallItem || type.detailType() == LargeItem) {
         if (canContinue(ContinueUsage)) {
             m_data[m_currentUsageIndex].update(event.number<qint64>(0));
             m_currentUsage = m_data[m_currentUsageIndex].size;
@@ -186,9 +186,9 @@ void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type
         }
     }
 
-    if (type.detailType == HeapPage || type.detailType == LargeItem) {
+    if (type.detailType() == HeapPage || type.detailType() == LargeItem) {
         if (canContinue(ContinueAllocation)
-                && type.detailType == selectionId(m_currentJSHeapIndex)) {
+                && type.detailType() == selectionId(m_currentJSHeapIndex)) {
             m_data[m_currentJSHeapIndex].update(event.number<qint64>(0));
             m_currentSize = m_data[m_currentJSHeapIndex].size;
         } else {
@@ -204,7 +204,7 @@ void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type
             if (m_currentJSHeapIndex != -1)
                 insertEnd(m_currentJSHeapIndex,
                           event.timestamp() - startTime(m_currentJSHeapIndex) - 1);
-            m_currentJSHeapIndex = insertStart(event.timestamp(), type.detailType);
+            m_currentJSHeapIndex = insertStart(event.timestamp(), type.detailType());
             m_data.insert(m_currentJSHeapIndex, allocation);
             m_continuation = m_continuation | ContinueAllocation;
         }
diff --git a/src/plugins/qmlprofiler/pixmapcachemodel.cpp b/src/plugins/qmlprofiler/pixmapcachemodel.cpp
index 09aeb2c9112b0a99aadf3dfb74f3d005173ec159..d497c1996a6b006c2019cace1b7eacf9ea580539 100644
--- a/src/plugins/qmlprofiler/pixmapcachemodel.cpp
+++ b/src/plugins/qmlprofiler/pixmapcachemodel.cpp
@@ -163,13 +163,13 @@ QVariantMap PixmapCacheModel::details(int index) const
 void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
     PixmapCacheItem newEvent;
-    const PixmapEventType pixmapType = static_cast<PixmapEventType>(type.detailType);
+    const PixmapEventType pixmapType = static_cast<PixmapEventType>(type.detailType());
     newEvent.pixmapEventType = pixmapType;
     qint64 pixmapStartTime = event.timestamp();
 
     newEvent.urlIndex = -1;
     for (auto i = m_pixmaps.cend(), begin = m_pixmaps.cbegin(); i != begin;) {
-        if ((--i)->url == type.location.filename()) {
+        if ((--i)->url == type.location().filename()) {
             newEvent.urlIndex = i - m_pixmaps.cbegin();
             break;
         }
@@ -178,7 +178,7 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type
     newEvent.sizeIndex = -1;
     if (newEvent.urlIndex == -1) {
         newEvent.urlIndex = m_pixmaps.count();
-        m_pixmaps << Pixmap(type.location.filename());
+        m_pixmaps << Pixmap(type.location().filename());
     }
 
     Pixmap &pixmap = m_pixmaps[newEvent.urlIndex];
diff --git a/src/plugins/qmlprofiler/qmleventtype.cpp b/src/plugins/qmlprofiler/qmleventtype.cpp
index 3d32b1343f1eb8cf4667e69ddadc651759de5c30..0649379f857440d65b5f24035c13eb5f652acb05 100644
--- a/src/plugins/qmlprofiler/qmleventtype.cpp
+++ b/src/plugins/qmlprofiler/qmleventtype.cpp
@@ -32,18 +32,45 @@ QDataStream &operator>>(QDataStream &stream, QmlEventType &type)
 {
     quint8 message;
     quint8 rangeType;
-    stream >> type.displayName >> type.data >> type.location >> message >> rangeType
-           >> type.detailType;
-    type.message = static_cast<Message>(message);
-    type.rangeType = static_cast<RangeType>(rangeType);
+    stream >> type.m_displayName >> type.m_data >> type.m_location >> message >> rangeType
+           >> type.m_detailType;
+    type.m_message = static_cast<Message>(message);
+    type.m_rangeType = static_cast<RangeType>(rangeType);
     return stream;
 }
 
 QDataStream &operator<<(QDataStream &stream, const QmlEventType &type)
 {
-    return stream << type.displayName << type.data << type.location
-                  << static_cast<quint8>(type.message) << static_cast<quint8>(type.rangeType)
-                  << type.detailType;
+    return stream << type.m_displayName << type.m_data << type.m_location
+                  << static_cast<quint8>(type.m_message) << static_cast<quint8>(type.m_rangeType)
+                  << type.m_detailType;
+}
+
+ProfileFeature QmlEventType::feature() const
+{
+    switch (m_message) {
+    case Event: {
+        switch (m_detailType) {
+        case Mouse:
+        case Key:
+            return ProfileInputEvents;
+        case AnimationFrame:
+            return ProfileAnimations;
+        default:
+            return MaximumProfileFeature;
+        }
+    }
+    case PixmapCacheEvent:
+        return ProfilePixmapCache;
+    case SceneGraphFrame:
+        return ProfileSceneGraph;
+    case MemoryAllocation:
+        return ProfileMemory;
+    case DebugMessage:
+        return ProfileDebugMessages;
+    default:
+        return featureFromRangeType(m_rangeType);
+    }
 }
 
 
diff --git a/src/plugins/qmlprofiler/qmleventtype.h b/src/plugins/qmlprofiler/qmleventtype.h
index da22f83121f7660c81e9a0e93f96f7eabd656170..f4a0a4c8ed1022c15f606ea2a5a4059d007bcc9d 100644
--- a/src/plugins/qmlprofiler/qmleventtype.h
+++ b/src/plugins/qmlprofiler/qmleventtype.h
@@ -31,48 +31,37 @@
 
 namespace QmlProfiler {
 
-struct QmlEventType {
-    QmlEventType(const QString &displayName = QString(),
-                 const QmlEventLocation &location = QmlEventLocation(),
-                 Message message = MaximumMessage, RangeType rangeType = MaximumRangeType,
-                 int detailType = -1, const QString &data = QString()) :
-        displayName(displayName), data(data), location(location), message(message),
-        rangeType(rangeType), detailType(detailType)
+class QmlEventType {
+public:
+    QmlEventType(Message message = MaximumMessage, RangeType rangeType = MaximumRangeType,
+                 int detailType = -1, const QmlEventLocation &location = QmlEventLocation(),
+                 const QString &data = QString(), const QString displayName = QString()) :
+        m_displayName(displayName), m_data(data), m_location(location), m_message(message),
+        m_rangeType(rangeType), m_detailType(detailType)
     {}
 
-    QString displayName;
-    QString data;
-    QmlEventLocation location;
-    Message message;
-    RangeType rangeType;
-    int detailType; // can be EventType, BindingType, PixmapEventType or SceneGraphFrameType
+    void setDisplayName(const QString &displayName) { m_displayName = displayName; }
+    void setData(const QString &data) { m_data = data; }
+    void setLocation(const QmlEventLocation &location) { m_location = location; }
 
-    ProfileFeature feature() const
-    {
-        switch (message) {
-        case Event: {
-            switch (detailType) {
-            case Mouse:
-            case Key:
-                return ProfileInputEvents;
-            case AnimationFrame:
-                return ProfileAnimations;
-            default:
-                return MaximumProfileFeature;
-            }
-        }
-        case PixmapCacheEvent:
-            return ProfilePixmapCache;
-        case SceneGraphFrame:
-            return ProfileSceneGraph;
-        case MemoryAllocation:
-            return ProfileMemory;
-        case DebugMessage:
-            return ProfileDebugMessages;
-        default:
-            return featureFromRangeType(rangeType);
-        }
-    }
+    ProfileFeature feature() const;
+    QString displayName() const { return m_displayName; }
+    QString data() const { return m_data; }
+    QmlEventLocation location() const { return m_location; }
+    Message message() const { return m_message; }
+    RangeType rangeType() const { return m_rangeType; }
+    int detailType() const { return m_detailType; }
+
+private:
+    friend QDataStream &operator>>(QDataStream &stream, QmlEventType &type);
+    friend QDataStream &operator<<(QDataStream &stream, const QmlEventType &type);
+
+    QString m_displayName;
+    QString m_data;
+    QmlEventLocation m_location;
+    Message m_message;
+    RangeType m_rangeType;
+    int m_detailType; // can be EventType, BindingType, PixmapEventType or SceneGraphFrameType
 };
 
 QDataStream &operator>>(QDataStream &stream, QmlEventType &type);
diff --git a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
index d464d6953fa3f800ec3753b671f0e737d06c1228..e8fb41dd59a4f098f3f038e16d48a9fc5410f997 100644
--- a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
@@ -57,7 +57,7 @@ void QmlProfilerAnimationsModel::clear()
 
 bool QmlProfilerAnimationsModel::accepted(const QmlEventType &event) const
 {
-    return QmlProfilerTimelineModel::accepted(event) && event.detailType == AnimationFrame;
+    return QmlProfilerTimelineModel::accepted(event) && event.detailType() == AnimationFrame;
 }
 
 void QmlProfilerAnimationsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
index aca2b606a65f4b76892628e95d06798a9026a0b0..c5908924926b1577bfcf1748711225de31365c5f 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
@@ -57,24 +57,23 @@ public:
 
 QString getDisplayName(const QmlEventType &event)
 {
-    if (event.location.filename().isEmpty()) {
+    if (event.location().filename().isEmpty()) {
         return QmlProfilerDataModel::tr("<bytecode>");
     } else {
-        const QString filePath = QUrl(event.location.filename()).path();
+        const QString filePath = QUrl(event.location().filename()).path();
         return filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') +
-                QString::number(event.location.line());
+                QString::number(event.location().line());
     }
 }
 
 QString getInitialDetails(const QmlEventType &event)
 {
-    QString details;
+    QString details = event.data();
     // generate details string
-    if (!event.data.isEmpty()) {
-        details = event.data;
+    if (!details.isEmpty()) {
         details = details.replace(QLatin1Char('\n'),QLatin1Char(' ')).simplified();
         if (details.isEmpty()) {
-            if (event.rangeType == Javascript)
+            if (event.rangeType() == Javascript)
                 details = QmlProfilerDataModel::tr("anonymous function");
         } else {
             QRegExp rewrite(QLatin1String("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)"));
@@ -85,7 +84,7 @@ QString getInitialDetails(const QmlEventType &event)
                     details.startsWith(QLatin1String("qrc:/")))
                 details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1);
         }
-    } else if (event.rangeType == Painting) {
+    } else if (event.rangeType() == Painting) {
         // QtQuick1 animations always run in GUI thread.
         details = QmlProfilerDataModel::tr("GUI Thread");
     }
@@ -174,18 +173,18 @@ bool QmlProfilerDataModel::isEmpty() const
 void QmlProfilerDataModel::QmlProfilerDataModelPrivate::rewriteType(int typeIndex)
 {
     QmlEventType &type = eventTypes[typeIndex];
-    type.displayName = getDisplayName(type);
-    type.data = getInitialDetails(type);
+    type.setDisplayName(getDisplayName(type));
+    type.setData(getInitialDetails(type));
 
     // Only bindings and signal handlers need rewriting
-    if (type.rangeType != Binding && type.rangeType != HandlingSignal)
+    if (type.rangeType() != Binding && type.rangeType() != HandlingSignal)
         return;
 
     // There is no point in looking for invalid locations
-    if (!type.location.isValid())
+    if (!type.location().isValid())
         return;
 
-    detailsRewriter->requestDetailsForLocation(typeIndex, type.location);
+    detailsRewriter->requestDetailsForLocation(typeIndex, type.location());
 }
 
 void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
@@ -205,7 +204,7 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
         const QmlEventType &type = d->eventTypes[event.typeIndex()];
         if (rangeStart != -1 && rangeEnd != -1) {
             if (event.timestamp() < rangeStart) {
-                if (type.rangeType != MaximumRangeType) {
+                if (type.rangeType() != MaximumRangeType) {
                     if (event.rangeStage() == RangeStart)
                         stack.push(event);
                     else if (event.rangeStage() == RangeEnd)
@@ -213,7 +212,7 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
                 }
                 continue;
             } else if (event.timestamp() > rangeEnd) {
-                if (type.rangeType != MaximumRangeType) {
+                if (type.rangeType() != MaximumRangeType) {
                     if (event.rangeStage() == RangeEnd) {
                         if (stack.isEmpty()) {
                             QmlEvent endEvent(event);
@@ -251,7 +250,7 @@ void QmlProfilerDataModel::detailsChanged(int requestId, const QString &newStrin
 {
     Q_D(QmlProfilerDataModel);
     QTC_ASSERT(requestId < d->eventTypes.count(), return);
-    d->eventTypes[requestId].data = newString;
+    d->eventTypes[requestId].setData(newString);
 }
 
 } // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
index 085dd49fde5aac797dbda1ccfafe37fac91d9eeb..f52c46f7dcac54aab624faa02c6f98eb89111323 100644
--- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
@@ -193,8 +193,8 @@ QVariantList QmlProfilerRangeModel::labels() const
     for (int i = 1; i < expandedRowCount(); i++) { // Ignore the -1 for the first row
         QVariantMap element;
         int typeId = m_expandedRowTypes[i];
-        element.insert(QLatin1String("displayName"), QVariant(types[typeId].displayName));
-        element.insert(QLatin1String("description"), QVariant(types[typeId].data));
+        element.insert(QLatin1String("displayName"), QVariant(types[typeId].displayName()));
+        element.insert(QLatin1String("description"), QVariant(types[typeId].data()));
         element.insert(QLatin1String("id"), QVariant(typeId));
         result << element;
     }
@@ -212,8 +212,8 @@ QVariantMap QmlProfilerRangeModel::details(int index) const
                   tr(QmlProfilerModelManager::featureName(mainFeature())));
     result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index)));
 
-    result.insert(tr("Details"), types[id].data);
-    result.insert(tr("Location"), types[id].displayName);
+    result.insert(tr("Details"), types[id].data());
+    result.insert(tr("Location"), types[id].displayName());
     return result;
 }
 
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
index a1262e4b095040786081d1e535ae27bbe6acb7b9..c2e1b92e5f774f5abc04bf0f14af0c8721c70d2f 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
@@ -207,7 +207,7 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
 
 void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
-    if (!d->acceptedTypes.contains(type.rangeType))
+    if (!d->acceptedTypes.contains(type.rangeType()))
         return;
 
     switch (event.rangeStage()) {
@@ -215,7 +215,7 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
         // binding loop detection: check whether event is already in stack
         for (int ii = 1; ii < d->callStack.size(); ++ii) {
             if (d->callStack.at(ii).typeIndex() == event.typeIndex()
-                    && type.rangeType != Javascript) {
+                    && type.rangeType() != Javascript) {
                 d->eventsInBindingLoop.insert(event.typeIndex());
                 break;
             }
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
index 671f3103b713e3a9092ca817a5c8a505d1749fd2..113199af508dc71b124ed6f7f73b21bc44781532 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
@@ -53,15 +53,11 @@ struct Colors {
 };
 
 struct RootEventType : public QmlEventType {
-    RootEventType()
+    RootEventType() : QmlEventType(MaximumMessage, MaximumRangeType, -1,
+                                   QmlEventLocation("<program>", 1, 1),
+                                   QmlProfilerStatisticsMainView::tr("Main Program"),
+                                   QmlProfilerStatisticsMainView::tr("<program>"))
     {
-        QString rootEventName = QmlProfilerStatisticsMainView::tr("<program>");
-        displayName = rootEventName;
-        location = QmlEventLocation(rootEventName, 1, 1);
-        message = MaximumMessage;
-        rangeType = MaximumRangeType;
-        detailType = -1;
-        data = QmlProfilerStatisticsMainView::tr("Main Program");
     }
 };
 
@@ -571,11 +567,11 @@ void QmlProfilerStatisticsMainView::parseModel()
         QList<QStandardItem *> newRow;
 
         if (d->m_fieldShown[Name])
-            newRow << new StatisticsViewItem(event.displayName.isEmpty() ? tr("<bytecode>") :
-                                                                       event.displayName);
+            newRow << new StatisticsViewItem(event.displayName().isEmpty() ? tr("<bytecode>") :
+                                                                             event.displayName());
 
         if (d->m_fieldShown[Type]) {
-            QString typeString = QmlProfilerStatisticsMainView::nameForType(event.rangeType);
+            QString typeString = QmlProfilerStatisticsMainView::nameForType(event.rangeType());
             newRow << new StatisticsViewItem(typeString);
             newRow.last()->setData(QVariant(typeString));
         }
@@ -628,9 +624,9 @@ void QmlProfilerStatisticsMainView::parseModel()
         }
 
         if (d->m_fieldShown[Details]) {
-            newRow << new StatisticsViewItem(event.data.isEmpty() ?
-                                                 tr("Source code not available") : event.data);
-            newRow.last()->setData(QVariant(event.data));
+            newRow << new StatisticsViewItem(event.data().isEmpty() ?
+                                                 tr("Source code not available") : event.data());
+            newRow.last()->setData(event.data());
         }
 
 
@@ -642,9 +638,10 @@ void QmlProfilerStatisticsMainView::parseModel()
 
             // metadata
             newRow.at(0)->setData(typeIndex, TypeIdRole);
-            newRow.at(0)->setData(event.location.filename(), FilenameRole);
-            newRow.at(0)->setData(event.location.line(), LineRole);
-            newRow.at(0)->setData(event.location.column(), ColumnRole);
+            const QmlEventLocation location(event.location());
+            newRow.at(0)->setData(location.filename(), FilenameRole);
+            newRow.at(0)->setData(location.line(), LineRole);
+            newRow.at(0)->setData(location.column(), ColumnRole);
 
             // append
             parentItem->appendRow(newRow);
@@ -859,23 +856,24 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
         // ToDo: here we were going to search for the data in the other model
         // maybe we should store the data in this model and get it here
         // no indirections at this level of abstraction!
-        newRow << new StatisticsViewItem(type.displayName.isEmpty() ? tr("<bytecode>") :
-                                                                  type.displayName);
+        newRow << new StatisticsViewItem(type.displayName().isEmpty() ? tr("<bytecode>") :
+                                                                        type.displayName());
         newRow << new StatisticsViewItem(QmlProfilerStatisticsMainView::nameForType(
-                                             type.rangeType));
+                                             type.rangeType()));
         newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(event.duration));
         newRow << new StatisticsViewItem(QString::number(event.calls));
-        newRow << new StatisticsViewItem(type.data.isEmpty() ? tr("Source code not available") :
-                                                           type.data);
+        newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available") :
+                                                                 type.data());
 
         newRow.at(0)->setData(typeIndex, TypeIdRole);
-        newRow.at(0)->setData(type.location.filename(), FilenameRole);
-        newRow.at(0)->setData(type.location.line(), LineRole);
-        newRow.at(0)->setData(type.location.column(), ColumnRole);
-        newRow.at(1)->setData(QmlProfilerStatisticsMainView::nameForType(type.rangeType));
+        const QmlEventLocation location(type.location());
+        newRow.at(0)->setData(location.filename(), FilenameRole);
+        newRow.at(0)->setData(location.line(), LineRole);
+        newRow.at(0)->setData(location.column(), ColumnRole);
+        newRow.at(1)->setData(QmlProfilerStatisticsMainView::nameForType(type.rangeType()));
         newRow.at(2)->setData(event.duration);
         newRow.at(3)->setData(event.calls);
-        newRow.at(4)->setData(type.data);
+        newRow.at(4)->setData(type.data());
 
         if (event.isBindingLoop) {
             foreach (QStandardItem *item, newRow) {
diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
index 464c5ca514e801dc2f506eb35d7a0d0dab7279a6..181ca3b90db520f13252e31b480dae55a9681948 100644
--- a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
@@ -57,9 +57,9 @@ ProfileFeature QmlProfilerTimelineModel::mainFeature() const
     return m_mainFeature;
 }
 
-bool QmlProfilerTimelineModel::accepted(const QmlEventType &event) const
+bool QmlProfilerTimelineModel::accepted(const QmlEventType &type) const
 {
-    return (event.rangeType == m_rangeType && event.message == m_message);
+    return (type.rangeType() == m_rangeType && type.message() == m_message);
 }
 
 bool QmlProfilerTimelineModel::handlesTypeId(int typeIndex) const
@@ -129,7 +129,7 @@ QVariantMap QmlProfilerTimelineModel::locationFromTypeId(int index) const
     if (id >= types.length())
         return result;
 
-    const QmlEventLocation &location = types.at(id).location;
+    QmlEventLocation location = types.at(id).location();
 
     result.insert(QStringLiteral("file"), location.filename());
     result.insert(QStringLiteral("line"), location.line());
diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
index c5097e86292ebfa0dea5c0c9b78f97e53117edd7..7fd590dbd3ce1a6b01fe7203b1ff36baf4ba3af6 100644
--- a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
@@ -48,7 +48,7 @@ public:
     Message message() const;
     ProfileFeature mainFeature() const;
 
-    virtual bool accepted(const QmlEventType &event) const;
+    virtual bool accepted(const QmlEventType &type) const;
     bool handlesTypeId(int typeId) const;
     Q_INVOKABLE virtual int bindingLoopDest(int index) const;
     QVariantMap locationFromTypeId(int index) const;
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
index 16f17da5444f285d8102938015b0b26ae448b754..8b3af29d8e59bed3cc6aa696932a4231c8b54322 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
@@ -36,19 +36,18 @@ namespace QmlProfiler {
 
 inline static uint qHash(const QmlEventType &type)
 {
-    return qHash(type.location.filename()) ^
-            ((type.location.line() & 0xfff) |             // 12 bits of line number
-            ((type.message << 12) & 0xf000) |             // 4 bits of message
-            ((type.location.column() << 16) & 0xff0000) | // 8 bits of column
-            ((type.rangeType << 24) & 0xf000000) |        // 4 bits of rangeType
-            ((type.detailType << 28) & 0xf0000000));      // 4 bits of detailType
+    return qHash(type.location().filename()) ^
+            ((type.location().line() & 0xfff) |             // 12 bits of line number
+            ((type.message() << 12) & 0xf000) |             // 4 bits of message
+            ((type.location().column() << 16) & 0xff0000) | // 8 bits of column
+            ((type.rangeType() << 24) & 0xf000000) |        // 4 bits of rangeType
+            ((type.detailType() << 28) & 0xf0000000));      // 4 bits of detailType
 }
 
-inline static bool operator==(const QmlEventType &type1,
-                              const QmlEventType &type2)
+inline static bool operator==(const QmlEventType &type1, const QmlEventType &type2)
 {
-    return type1.message == type2.message && type1.rangeType == type2.rangeType &&
-            type1.detailType == type2.detailType && type1.location == type2.location;
+    return type1.message() == type2.message() && type1.rangeType() == type2.rangeType() &&
+            type1.detailType() == type2.detailType() && type1.location() == type2.location();
 }
 
 class QmlProfilerTraceClientPrivate {
@@ -136,8 +135,8 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
     // all ranges are perfectly nested. This is why we can defer the type resolution until either
     // the range ends or a child range starts. With only the information in RangeStart we wouldn't
     // be able to uniquely identify the event type.
-    Message rangeStage = currentEvent.type.rangeType == MaximumRangeType ?
-                currentEvent.type.message : currentEvent.event.rangeStage();
+    Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ?
+                currentEvent.type.message() : currentEvent.event.rangeStage();
     switch (rangeStage) {
     case RangeStart:
         resolveStackTop();
@@ -152,10 +151,10 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
         break;
     }
     case RangeData:
-        rangesInProgress.top().type.data = currentEvent.type.data;
+        rangesInProgress.top().type.setData(currentEvent.type.data());
         break;
     case RangeLocation:
-        rangesInProgress.top().type.location = currentEvent.type.location;
+        rangesInProgress.top().type.setLocation(currentEvent.type.location());
         break;
     default: {
         int typeIndex = resolveType(currentEvent);
@@ -249,12 +248,8 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features)
             d->currentEvent.event.setTimestamp(context.timestamp);
             d->currentEvent.event.setTypeIndex(-1);
             d->currentEvent.event.setString(text);
-            d->currentEvent.type.location = QmlEventLocation(context.file, context.line, 1);
-            d->currentEvent.type.displayName.clear();
-            d->currentEvent.type.data.clear();
-            d->currentEvent.type.message = DebugMessage;
-            d->currentEvent.type.rangeType = MaximumRangeType;
-            d->currentEvent.type.detailType = type;
+            d->currentEvent.type = QmlEventType(DebugMessage, MaximumRangeType, type,
+                                                QmlEventLocation(context.file, context.line, 1));
             d->currentEvent.serverTypeId = 0;
             d->processCurrentEvent();
         });
@@ -301,17 +296,17 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
     stream >> d->currentEvent;
 
     d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
-    if (d->currentEvent.type.message == Complete) {
+    if (d->currentEvent.type.message() == Complete) {
         emit complete(d->maximumTime);
         setRecordingFromServer(false);
-    } else if (d->currentEvent.type.message == Event
-               && d->currentEvent.type.detailType == StartTrace) {
+    } else if (d->currentEvent.type.message() == Event
+               && d->currentEvent.type.detailType() == StartTrace) {
         if (!d->recording)
             setRecordingFromServer(true);
         emit traceStarted(d->currentEvent.event.timestamp(),
                           d->currentEvent.event.numbers<QList<int>, qint32>());
-    } else if (d->currentEvent.type.message == Event
-               && d->currentEvent.type.detailType == EndTrace) {
+    } else if (d->currentEvent.type.message() == Event
+               && d->currentEvent.type.detailType() == EndTrace) {
         emit traceFinished(d->currentEvent.event.timestamp(),
                            d->currentEvent.event.numbers<QList<int>, qint32>());
     } else if (d->updateFeatures(d->currentEvent.type.feature())) {
diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
index 534c74c04bbd971ca99e9590049c27e36c8897ce..3b8ea4ff8cf97f95d8418a2f2b97e75bb8729b61 100644
--- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
@@ -290,19 +290,23 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
     QTC_ASSERT(stream.name() == _("eventData"), return);
 
     int typeIndex = -1;
-    QmlEventType type = {
-            QString(), // displayname
-            QmlEventLocation(),
-            MaximumMessage,
-            Painting, // type
-            QmlBinding,  // bindingType, set for backwards compatibility
-            QString(), // details
-    };
-    const QmlEventType defaultEvent = type;
 
+    QPair<Message, RangeType> messageAndRange(MaximumMessage, MaximumRangeType);
+    int detailType = -1;
+    QString displayName;
+    QString data;
     QString filename;
     int line = 0, column = 0;
 
+    auto clearType = [&](){
+        messageAndRange = QPair<Message, RangeType>(MaximumMessage, MaximumRangeType);
+        detailType = -1;
+        displayName.clear();
+        data.clear();
+        filename.clear();
+        line = column = 0;
+    };
+
     while (!stream.atEnd() && !stream.hasError()) {
         if (isCanceled())
             return;
@@ -314,7 +318,7 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
         case QXmlStreamReader::StartElement: {
             if (elementName == _("event")) {
                 updateProgress(stream.device());
-                type = defaultEvent;
+                clearType();
 
                 const QXmlStreamAttributes attributes = stream.attributes();
                 if (attributes.hasAttribute(_("index"))) {
@@ -333,14 +337,12 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
             const QString readData = stream.text().toString();
 
             if (elementName == _("displayname")) {
-                type.displayName = readData;
+                displayName = readData;
                 break;
             }
 
             if (elementName == _("type")) {
-                QPair<Message, RangeType> enums = qmlTypeAsEnum(readData);
-                type.message = enums.first;
-                type.rangeType = enums.second;
+                messageAndRange = qmlTypeAsEnum(readData);
                 break;
             }
 
@@ -360,20 +362,19 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
             }
 
             if (elementName == _("details")) {
-                type.data = readData;
+                data = readData;
                 break;
             }
 
             if (elementName == _("animationFrame")) {
-                type.detailType = readData.toInt();
+                detailType = readData.toInt();
                 // new animation frames used to be saved as ranges of range type Painting with
                 // binding type 4 (which was called "AnimationFrame" to make everything even more
                 // confusing), even though they clearly aren't ranges. Convert that to something
                 // sane here.
-                if (type.detailType == 4) {
-                    type.message = Event;
-                    type.rangeType = MaximumRangeType;
-                    type.detailType = AnimationFrame;
+                if (detailType == 4) {
+                    messageAndRange = QPair<Message, RangeType>(Event, MaximumRangeType);
+                    detailType = AnimationFrame;
                 }
             }
 
@@ -384,7 +385,7 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
                     elementName == _("mouseEvent") ||
                     elementName == _("keyEvent") ||
                     elementName == _("level")) {
-                type.detailType = readData.toInt();
+                detailType = readData.toInt();
                 break;
             }
 
@@ -395,9 +396,8 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream)
                 if (typeIndex >= 0) {
                     if (typeIndex >= m_eventTypes.size())
                         m_eventTypes.resize(typeIndex + 1);
-                    type.location = QmlEventLocation(filename, line, column);
-                    filename.clear();
-                    line = column = 0;
+                    QmlEventType type(messageAndRange.first, messageAndRange.second, detailType,
+                                      QmlEventLocation(filename, line, column), data, displayName);
                     m_eventTypes[typeIndex] = type;
                     ProfileFeature feature = type.feature();
                     if (feature != MaximumProfileFeature)
@@ -624,41 +624,42 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device)
 
         stream.writeStartElement(_("event"));
         stream.writeAttribute(_("index"), QString::number(typeIndex));
-        stream.writeTextElement(_("displayname"), type.displayName);
-        stream.writeTextElement(_("type"), qmlTypeAsString(type.message, type.rangeType));
-        if (!type.location.filename().isEmpty()) {
-            stream.writeTextElement(_("filename"), type.location.filename());
-            stream.writeTextElement(_("line"), QString::number(type.location.line()));
-            stream.writeTextElement(_("column"), QString::number(type.location.column()));
+        stream.writeTextElement(_("displayname"), type.displayName());
+        stream.writeTextElement(_("type"), qmlTypeAsString(type.message(), type.rangeType()));
+        const QmlEventLocation location(type.location());
+        if (!location.filename().isEmpty()) {
+            stream.writeTextElement(_("filename"), location.filename());
+            stream.writeTextElement(_("line"), QString::number(location.line()));
+            stream.writeTextElement(_("column"), QString::number(location.column()));
         }
 
-        if (!type.data.isEmpty())
-            stream.writeTextElement(_("details"), type.data);
+        if (!type.data().isEmpty())
+            stream.writeTextElement(_("details"), type.data());
 
-        if (type.rangeType == Binding) {
-            stream.writeTextElement(_("bindingType"), QString::number(type.detailType));
-        } else if (type.message == Event) {
-            switch (type.detailType) {
+        if (type.rangeType() == Binding) {
+            stream.writeTextElement(_("bindingType"), QString::number(type.detailType()));
+        } else if (type.message() == Event) {
+            switch (type.detailType()) {
             case AnimationFrame:
-                stream.writeTextElement(_("animationFrame"), QString::number(type.detailType));
+                stream.writeTextElement(_("animationFrame"), QString::number(type.detailType()));
                 break;
             case Key:
-                stream.writeTextElement(_("keyEvent"), QString::number(type.detailType));
+                stream.writeTextElement(_("keyEvent"), QString::number(type.detailType()));
                 break;
             case Mouse:
-                stream.writeTextElement(_("mouseEvent"), QString::number(type.detailType));
+                stream.writeTextElement(_("mouseEvent"), QString::number(type.detailType()));
                 break;
             default:
                 break;
             }
-        } else if (type.message == PixmapCacheEvent) {
-            stream.writeTextElement(_("cacheEventType"), QString::number(type.detailType));
-        } else if (type.message == SceneGraphFrame) {
-            stream.writeTextElement(_("sgEventType"), QString::number(type.detailType));
-        } else if (type.message == MemoryAllocation) {
-            stream.writeTextElement(_("memoryEventType"), QString::number(type.detailType));
-        } else if (type.message == DebugMessage) {
-            stream.writeTextElement(_("level"), QString::number(type.detailType));
+        } else if (type.message() == PixmapCacheEvent) {
+            stream.writeTextElement(_("cacheEventType"), QString::number(type.detailType()));
+        } else if (type.message() == SceneGraphFrame) {
+            stream.writeTextElement(_("sgEventType"), QString::number(type.detailType()));
+        } else if (type.message() == MemoryAllocation) {
+            stream.writeTextElement(_("memoryEventType"), QString::number(type.detailType()));
+        } else if (type.message() == DebugMessage) {
+            stream.writeTextElement(_("level"), QString::number(type.detailType()));
         }
         stream.writeEndElement();
         incrementProgress();
@@ -673,13 +674,13 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device)
         if (isCanceled())
             return;
 
-        if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeStart) {
+        if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeStart) {
             stack.push(event);
             return;
         }
 
         stream.writeStartElement(_("range"));
-        if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeEnd) {
+        if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeEnd) {
             QmlEvent start = stack.pop();
             stream.writeAttribute(_("startTime"), QString::number(start.timestamp()));
             stream.writeAttribute(_("duration"),
@@ -690,14 +691,14 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device)
 
         stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex()));
 
-        if (type.message == Event) {
-            if (type.detailType == AnimationFrame) {
+        if (type.message() == Event) {
+            if (type.detailType() == AnimationFrame) {
                 // special: animation event
                 stream.writeAttribute(_("framerate"), QString::number(event.number<qint32>(0)));
                 stream.writeAttribute(_("animationcount"),
                                       QString::number(event.number<qint32>(1)));
                 stream.writeAttribute(_("thread"), QString::number(event.number<qint32>(2)));
-            } else if (type.detailType == Key || type.detailType == Mouse) {
+            } else if (type.detailType() == Key || type.detailType() == Mouse) {
                 // special: input event
                 stream.writeAttribute(_("type"), QString::number(event.number<qint32>(0)));
                 stream.writeAttribute(_("data1"), QString::number(event.number<qint32>(1)));
@@ -706,18 +707,18 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device)
         }
 
         // special: pixmap cache event
-        if (type.message == PixmapCacheEvent) {
-            if (type.detailType == PixmapSizeKnown) {
+        if (type.message() == PixmapCacheEvent) {
+            if (type.detailType() == PixmapSizeKnown) {
                 stream.writeAttribute(_("width"), QString::number(event.number<qint32>(0)));
                 stream.writeAttribute(_("height"), QString::number(event.number<qint32>(1)));
             }
 
-            if (type.detailType == PixmapReferenceCountChanged ||
-                    type.detailType == PixmapCacheCountChanged)
+            if (type.detailType() == PixmapReferenceCountChanged
+                    || type.detailType() == PixmapCacheCountChanged)
                 stream.writeAttribute(_("refCount"), QString::number(event.number<qint32>(2)));
         }
 
-        if (type.message == SceneGraphFrame) {
+        if (type.message() == SceneGraphFrame) {
             // special: scenegraph frame events
             for (int i = 0; i < 5; ++i) {
                 qint64 number = event.number<qint64>(i);
@@ -729,10 +730,10 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device)
         }
 
         // special: memory allocation event
-        if (type.message == MemoryAllocation)
+        if (type.message() == MemoryAllocation)
             stream.writeAttribute(_("amount"), QString::number(event.number<qint64>(0)));
 
-        if (type.message == DebugMessage)
+        if (type.message() == DebugMessage)
             stream.writeAttribute(_("text"), event.string());
 
         stream.writeEndElement();
diff --git a/src/plugins/qmlprofiler/qmltypedevent.cpp b/src/plugins/qmlprofiler/qmltypedevent.cpp
index bf4e421c5889fdb016ceefd2c596a8194d3543ef..e5007345b5fad4ce4333d63d6729a82a9125d6bc 100644
--- a/src/plugins/qmlprofiler/qmltypedevent.cpp
+++ b/src/plugins/qmlprofiler/qmltypedevent.cpp
@@ -46,16 +46,11 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
 
     event.event.setTimestamp(time);
     event.event.setTypeIndex(-1);
-    event.type.displayName.clear();
-    event.type.data.clear();
-    event.type.location.clear();
     event.serverTypeId = 0;
 
     switch (messageType) {
     case Event: {
-        event.type.detailType = subtype;
-        event.type.rangeType = MaximumRangeType;
-        event.type.message = static_cast<Message>(messageType);
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
         switch (subtype) {
         case StartTrace:
         case EndTrace: {
@@ -99,9 +94,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
         break;
     }
     case Complete: {
-        event.type.message = static_cast<Message>(messageType);
-        event.type.rangeType = MaximumRangeType;
-        event.type.detailType = subtype;
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
         break;
     }
     case SceneGraphFrame: {
@@ -113,9 +106,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
             params.push_back(param);
         }
 
-        event.type.message = static_cast<Message>(messageType);
-        event.type.rangeType = MaximumRangeType;
-        event.type.detailType = subtype;
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
         event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params);
         break;
     }
@@ -123,7 +114,6 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
         qint32 width = 0, height = 0, refcount = 0;
         QString filename;
         stream >> filename;
-        event.type.location = QmlEventLocation(filename, 0, 0);
         if (subtype == PixmapReferenceCountChanged || subtype == PixmapCacheCountChanged) {
             stream >> refcount;
         } else if (subtype == PixmapSizeKnown) {
@@ -131,9 +121,8 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
             refcount = 1;
         }
 
-        event.type.message = static_cast<Message>(messageType);
-        event.type.rangeType = MaximumRangeType;
-        event.type.detailType = subtype;
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype,
+                                  QmlEventLocation(filename, 0, 0));
         event.event.setNumbers<qint32>({width, height, refcount});
         break;
     }
@@ -141,9 +130,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
         qint64 delta;
         stream >> delta;
 
-        event.type.message = static_cast<Message>(messageType);
-        event.type.rangeType = MaximumRangeType;
-        event.type.detailType = subtype;
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
         event.event.setNumbers<qint64>({delta});
         break;
     }
@@ -156,19 +143,16 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
             // otherwise it's the old binding type of 4 bytes
         }
 
-        event.type.message = MaximumMessage;
-        event.type.rangeType = rangeType;
+        event.type = QmlEventType(MaximumMessage, rangeType, -1);
         event.event.setRangeStage(RangeStart);
-        event.type.detailType = -1;
         break;
     }
     case RangeData: {
-        stream >> event.type.data;
+        QString data;
+        stream >> data;
 
-        event.type.message = MaximumMessage;
-        event.type.rangeType = rangeType;
+        event.type = QmlEventType(MaximumMessage, rangeType, -1, QmlEventLocation(), data);
         event.event.setRangeStage(RangeData);
-        event.type.detailType = -1;
         if (!stream.atEnd())
             stream >> event.serverTypeId;
         break;
@@ -185,24 +169,18 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
                 stream >> event.serverTypeId;
         }
 
-        event.type.location = QmlEventLocation(filename, line, column);
-        event.type.message = MaximumMessage;
-        event.type.rangeType = rangeType;
+        event.type = QmlEventType(MaximumMessage, rangeType, -1,
+                                  QmlEventLocation(filename, line, column));
         event.event.setRangeStage(RangeLocation);
-        event.type.detailType = -1;
         break;
     }
     case RangeEnd: {
-        event.type.message = MaximumMessage;
-        event.type.rangeType = rangeType;
+        event.type = QmlEventType(MaximumMessage, rangeType, -1);
         event.event.setRangeStage(RangeEnd);
-        event.type.detailType = -1;
         break;
     }
     default:
-        event.type.message = static_cast<Message>(messageType);
-        event.type.rangeType = MaximumRangeType;
-        event.type.detailType = subtype;
+        event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
         break;
     }
 
diff --git a/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp
index 01f67dd8c21b9a5e2253f602a0a61e3b879efac2..d9836301758c5867ada55b9d8d2d60ffa9edff78 100644
--- a/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp
+++ b/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp
@@ -134,7 +134,7 @@ QVariantMap SceneGraphTimelineModel::details(int index) const
 void SceneGraphTimelineModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
 {
     // combine the data of several eventtypes into two rows
-    switch ((SceneGraphFrameType)type.detailType) {
+    switch ((SceneGraphFrameType)type.detailType()) {
     case SceneGraphRendererFrame: {
         // Breakdown of render times. We repeat "render" here as "net" render time. It would
         // look incomplete if that was left out as the printf profiler lists it, too, and people
diff --git a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp
index f75a3ecb59ec7d34777c73b1a26aae8e5a8ebcad..c48d8a5219052ff28555bdff58c6175ce95c6664 100644
--- a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp
@@ -38,19 +38,13 @@ void DebugMessagesModelTest::initTestCase()
 {
     manager.startAcquiring();
     QmlEvent event;
-    QmlEventType type;
-
     event.setTypeIndex(-1);
-    type.displayName.clear();
-    type.data.clear();
-    type.message = DebugMessage;
-    type.rangeType = MaximumRangeType;
 
     for (int i = 0; i < 10; ++i) {
         event.setTimestamp(i);
         event.setString(QString::fromLatin1("message %1").arg(i));
-        type.location = QmlEventLocation("somefile.js", i, 10 - i);
-        type.detailType = i % (QtMsgType::QtInfoMsg + 1);
+        QmlEventType type(DebugMessage, MaximumRangeType, i % (QtMsgType::QtInfoMsg + 1),
+                          QmlEventLocation("somefile.js", i, 10 - i));
         event.setTypeIndex(manager.qmlModel()->addEventType(type));
         manager.qmlModel()->addEvent(event);
     }
diff --git a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
index 1ee2e643730ae5ae8d4688fc08b8bb5a3656dae7..78bbfee830b601814c513e2ae55f25d9af011587 100644
--- a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
@@ -45,23 +45,17 @@ void FlameGraphModelTest::generateData(QmlProfilerModelManager *manager)
 
     manager->startAcquiring();
     QmlEvent event;
-    QmlEventType type;
 
     event.setTypeIndex(-1);
-    type.displayName.clear();
-    type.data = QLatin1String("funcfunc");
-    type.rangeType = MaximumRangeType;
-    type.detailType = -1;
-    type.message = MaximumMessage;
-
     QStack<int> typeIndices;
 
     int i = 0;
     while (i < 10) {
         int typeIndex = -1;
         if (i < 5) {
-            type.location = QmlEventLocation("somefile.js", i, 20 - i);
-            type.rangeType = static_cast<RangeType>(static_cast<int>(Javascript) - i);
+            QmlEventType type(MaximumMessage,
+                              static_cast<RangeType>(static_cast<int>(Javascript) - i),
+                              -1, QmlEventLocation("somefile.js", i, 20 - i), QString("funcfunc"));
             typeIndex = manager->qmlModel()->addEventType(type);
         } else {
             typeIndex = typeIndices[i - 5];
diff --git a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
index 10a3241b1ad4badb188571b3df365d46ab696996..f0212b66a363b76f9ab1ba83dc158868ce2a5619 100644
--- a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
@@ -33,14 +33,8 @@ namespace Internal {
 InputEventsModelTest::InputEventsModelTest(QObject *parent) :
     QObject(parent), manager(nullptr), model(&manager)
 {
-    QmlEventType type;
-    type.message = Event;
-    type.rangeType = MaximumRangeType;
-    type.detailType = Key;
-    keyTypeId = manager.qmlModel()->addEventType(type);
-
-    type.detailType = Mouse;
-    mouseTypeId = manager.qmlModel()->addEventType(type);
+    keyTypeId = manager.qmlModel()->addEventType(QmlEventType(Event, MaximumRangeType, Key));
+    mouseTypeId = manager.qmlModel()->addEventType(QmlEventType(Event, MaximumRangeType, Mouse));
 }
 
 void InputEventsModelTest::initTestCase()
@@ -63,16 +57,11 @@ void InputEventsModelTest::initTestCase()
 
 void InputEventsModelTest::testAccepted()
 {
-    QmlEventType type;
-    QVERIFY(!model.accepted(type));
-    type.message = Event;
-    QVERIFY(!model.accepted(type));
-    type.rangeType = MaximumRangeType;
-    QVERIFY(!model.accepted(type));
-    type.detailType = Key;
-    QVERIFY(model.accepted(type));
-    type.detailType = Mouse;
-    QVERIFY(model.accepted(type));
+    QVERIFY(!model.accepted(QmlEventType()));
+    QVERIFY(!model.accepted(QmlEventType(Event)));
+    QVERIFY(!model.accepted(QmlEventType(Event, MaximumRangeType)));
+    QVERIFY(model.accepted(QmlEventType(Event, MaximumRangeType, Key)));
+    QVERIFY(model.accepted(QmlEventType(Event, MaximumRangeType, Mouse)));
 }
 
 void InputEventsModelTest::testTypeId()
diff --git a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp
index 9666c3e6e1669f31bf04ae8c5ddcbd5da27814aa..274f3a9c011e39604cba6841079a5599ebe198c4 100644
--- a/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/memoryusagemodel_test.cpp
@@ -39,16 +39,13 @@ void MemoryUsageModelTest::initTestCase()
     manager.startAcquiring();
     qint64 timestamp = 0;
 
-    QmlEventType type;
-    type.message = MemoryAllocation;
-    type.rangeType = MaximumRangeType;
 
-    type.detailType = HeapPage;
-    heapPageTypeId = manager.qmlModel()->addEventType(type);
-    type.detailType = SmallItem;
-    smallItemTypeId = manager.qmlModel()->addEventType(type);
-    type.detailType = LargeItem;
-    largeItemTypeId = manager.qmlModel()->addEventType(type);
+    heapPageTypeId = manager.qmlModel()->addEventType(
+                QmlEventType(MemoryAllocation, MaximumRangeType, HeapPage));
+    smallItemTypeId = manager.qmlModel()->addEventType(
+                QmlEventType(MemoryAllocation, MaximumRangeType, SmallItem));
+    largeItemTypeId = manager.qmlModel()->addEventType(
+                QmlEventType(MemoryAllocation, MaximumRangeType, LargeItem));
 
     auto addMemoryEvents = [&]() {
         QmlEvent event;
@@ -75,12 +72,10 @@ void MemoryUsageModelTest::initTestCase()
     };
 
     addMemoryEvents();
-    QmlEventType rangeType;
-    rangeType.message = MaximumMessage;
-    rangeType.rangeType = Javascript;
-    rangeType.data = QString("funcfunc");
-    rangeType.location = QmlEventLocation(QString("somefile.js"), 10, 20);
-    rangeTypeId = manager.qmlModel()->addEventType(rangeType);
+    rangeTypeId = manager.qmlModel()->addEventType(
+                QmlEventType(MaximumMessage, Javascript, -1,
+                             QmlEventLocation(QString("somefile.js"), 10, 20),
+                             QString("funcfunc")));
 
     QmlEvent event;
     event.setRangeStage(RangeStart);
@@ -229,16 +224,10 @@ void MemoryUsageModelTest::testRelativeHeight()
 
 void MemoryUsageModelTest::testAccepted()
 {
-    QmlEventType type;
-    QVERIFY(!model.accepted(type));
-    type.detailType = HeapPage;
-    QVERIFY(!model.accepted(type));
-    type.message = MemoryAllocation;
-    QVERIFY(model.accepted(type));
-
-    type.message = MaximumMessage;
-    type.rangeType = Javascript;
-    QVERIFY(model.accepted(type));
+    QVERIFY(!model.accepted(QmlEventType()));
+    QVERIFY(!model.accepted(QmlEventType(MaximumMessage, MaximumRangeType, HeapPage)));
+    QVERIFY(model.accepted(QmlEventType(MemoryAllocation, MaximumRangeType, HeapPage)));
+    QVERIFY(model.accepted(QmlEventType(MaximumMessage, Javascript)));
 }
 
 void MemoryUsageModelTest::cleanupTestCase()
diff --git a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
index 8aa692a0d426a18eb1b8b168919f5b46d6231195..8332904f8766e67c9d13c3cf5cbf354b1318d638 100644
--- a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
@@ -39,14 +39,10 @@ void PixmapCacheModelTest::initTestCase()
     manager.startAcquiring();
     manager.traceTime()->setTime(1, 300);
 
-    QmlEventType type;
-    type.message = PixmapCacheEvent;
-    type.rangeType = MaximumRangeType;
-    type.location = QmlEventLocation("dings.png", -1, -1);
-
     for (int i = 0; i < MaximumPixmapEventType; ++i) {
-        type.detailType = i;
-        eventTypeIndices[i] = manager.qmlModel()->addEventType(type);
+        eventTypeIndices[i] = manager.qmlModel()->addEventType(
+                    QmlEventType(PixmapCacheEvent, MaximumRangeType, i,
+                                 QmlEventLocation("dings.png", 0, 0)));
     }
 
     // random data, should still result in consistent model.
@@ -58,10 +54,10 @@ void PixmapCacheModelTest::initTestCase()
         manager.qmlModel()->addEvent(event);
     }
 
-    type.location = QmlEventLocation("blah.png", -1, -1);
     for (int i = 0; i < MaximumPixmapEventType; ++i) {
-        type.detailType = i;
-        eventTypeIndices[i + MaximumPixmapEventType] = manager.qmlModel()->addEventType(type);
+        eventTypeIndices[i + MaximumPixmapEventType] = manager.qmlModel()->addEventType(
+                    QmlEventType(PixmapCacheEvent, MaximumRangeType, i,
+                                 QmlEventLocation("blah.png", 0, 0)));
     }
 
 
@@ -285,7 +281,7 @@ void PixmapCacheModelTest::testColor()
                 QCOMPARE(model.color(i), row1Color);
         } else {
             const QmlEventType &type = manager.qmlModel()->eventTypes()[model.typeId(i)];
-            QColor &pixmapColor = (type.location.filename() == QString("blah.png")) ?
+            QColor &pixmapColor = (type.location().filename() == QString("blah.png")) ?
                         blahColor : dingsColor;
             if (!pixmapColor.isValid())
                 pixmapColor = model.color(i);