QmlDesigner: Collect events for telemetry plugin

For each action/event we want to track we
emit QmlDesignerPlugin::usageStatisticsNotifier() with an identifer.

This allows counting how many states, transitions, timelines were created
and we track every registered action.

More 'trace points' can be added later.

Change-Id: Ibb31e1b7e20d984a10697e05bb4417e7ad1b8980
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Thomas Hartmann
2020-11-11 17:33:35 +01:00
parent 093d5f5ab1
commit fb9fb01e34
10 changed files with 50 additions and 6 deletions

View File

@@ -29,6 +29,10 @@
#include "annotation.h" #include "annotation.h"
#include "qmlmodelnodeproxy.h" #include "qmlmodelnodeproxy.h"
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <QObject> #include <QObject>
@@ -175,6 +179,7 @@ void AnnotationEditor::removeFullAnnotation()
void AnnotationEditor::acceptedClicked() void AnnotationEditor::acceptedClicked()
{ {
if (m_dialog) { if (m_dialog) {
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_ANNOTATION_ADDED);
QString customId = m_dialog->customId(); QString customId = m_dialog->customId();
Annotation annotation = m_dialog->annotation(); Annotation annotation = m_dialog->annotation();

View File

@@ -343,7 +343,7 @@ public:
parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode(); parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode();
if (!ModelNode::isThisOrAncestorLocked(parentNode)) { if (!ModelNode::isThisOrAncestorLocked(parentNode)) {
ActionTemplate *selectionAction = new ActionTemplate(QString(), &ModelNodeOperations::select); ActionTemplate *selectionAction = new ActionTemplate("SELECTION", {}, &ModelNodeOperations::select);
selectionAction->setParent(menu()); selectionAction->setParent(menu());
selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select parent: %1")).arg( selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select parent: %1")).arg(
captionForModelNode(parentNode))); captionForModelNode(parentNode)));
@@ -363,7 +363,7 @@ public:
&& !ModelNode::isThisOrAncestorLocked(node)) { && !ModelNode::isThisOrAncestorLocked(node)) {
selectionContext().setTargetNode(node); selectionContext().setTargetNode(node);
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node)); QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node));
ActionTemplate *selectionAction = new ActionTemplate(what, &ModelNodeOperations::select); ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select);
SelectionContext nodeSelectionContext = selectionContext(); SelectionContext nodeSelectionContext = selectionContext();
nodeSelectionContext.setTargetNode(node); nodeSelectionContext.setTargetNode(node);
@@ -546,7 +546,7 @@ public:
for (const QmlFlowItemNode &node : QmlFlowViewNode(selectionContext().rootNode()).flowItems()) { for (const QmlFlowItemNode &node : QmlFlowViewNode(selectionContext().rootNode()).flowItems()) {
if (node != selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode()) { if (node != selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode()) {
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect: %1")).arg(captionForModelNode(node)); QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Connect: %1")).arg(captionForModelNode(node));
ActionTemplate *connectionAction = new ActionTemplate(what, &ModelNodeOperations::addTransition); ActionTemplate *connectionAction = new ActionTemplate("CONNECT", what, &ModelNodeOperations::addTransition);
SelectionContext nodeSelectionContext = selectionContext(); SelectionContext nodeSelectionContext = selectionContext();
nodeSelectionContext.setTargetNode(node); nodeSelectionContext.setTargetNode(node);

View File

@@ -29,6 +29,7 @@
#include "abstractaction.h" #include "abstractaction.h"
#include "abstractactiongroup.h" #include "abstractactiongroup.h"
#include "qmlitemnode.h" #include "qmlitemnode.h"
#include <qmldesignerplugin.h>
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
@@ -103,17 +104,19 @@ class ActionTemplate : public DefaultAction
{ {
public: public:
ActionTemplate(const QString &description, SelectionContextOperation action) ActionTemplate(const QByteArray &id, const QString &description, SelectionContextOperation action)
: DefaultAction(description), m_action(action) : DefaultAction(description), m_action(action), m_id(id)
{ } { }
void actionTriggered(bool b) override void actionTriggered(bool b) override
{ {
QmlDesignerPlugin::emitUsageStatisticsContextAction(QString::fromUtf8(m_id));
m_selectionContext.setToggled(b); m_selectionContext.setToggled(b);
m_action(m_selectionContext); m_action(m_selectionContext);
} }
SelectionContextOperation m_action; SelectionContextOperation m_action;
QByteArray m_id;
}; };
class ActionGroup : public AbstractActionGroup class ActionGroup : public AbstractActionGroup
@@ -202,7 +205,7 @@ public:
SelectionContextOperation selectionAction, SelectionContextOperation selectionAction,
SelectionContextPredicate enabled = &SelectionContextFunctors::always, SelectionContextPredicate enabled = &SelectionContextFunctors::always,
SelectionContextPredicate visibility = &SelectionContextFunctors::always) : SelectionContextPredicate visibility = &SelectionContextFunctors::always) :
AbstractAction(new ActionTemplate(description, selectionAction)), AbstractAction(new ActionTemplate(id, description, selectionAction)),
m_id(id), m_id(id),
m_category(category), m_category(category),
m_priority(priority), m_priority(priority),

View File

@@ -572,6 +572,7 @@ void ItemLibraryWidget::addResources()
for (const AddResourceHandler &handler : handlers) { for (const AddResourceHandler &handler : handlers) {
QStringList fileNames = partitionedFileNames.values(category); QStringList fileNames = partitionedFileNames.values(category);
if (handler.category == category) { if (handler.category == category) {
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_RESOURCE_IMPORTED + category);
if (!handler.operation(fileNames, document->fileName().parentDir().toString())) if (!handler.operation(fileNames, document->fileName().parentDir().toString()))
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), tr("Could not add %1 to project.").arg(fileNames.join(" "))); Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), tr("Could not add %1 to project.").arg(fileNames.join(" ")));
break; break;

View File

@@ -40,6 +40,8 @@
#include <variantproperty.h> #include <variantproperty.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
#include <qmlstate.h> #include <qmlstate.h>
#include <annotationeditor/annotationeditor.h> #include <annotationeditor/annotationeditor.h>
@@ -182,6 +184,8 @@ void StatesEditorView::addState()
if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode())) if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode()))
return; return;
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
QStringList modelStateNames = rootStateGroup().names(); QStringList modelStateNames = rootStateGroup().names();
QString newStateName; QString newStateName;

View File

@@ -44,6 +44,7 @@
#include <rewritertransaction.h> #include <rewritertransaction.h>
#include <variantproperty.h> #include <variantproperty.h>
#include <viewmanager.h> #include <viewmanager.h>
#include <qmldesignerconstants.h>
#include <qmldesignericons.h> #include <qmldesignericons.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
@@ -304,6 +305,8 @@ const QmlTimeline TimelineView::addNewTimeline()
QTC_ASSERT(isAttached(), return QmlTimeline()); QTC_ASSERT(isAttached(), return QmlTimeline());
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TIMELINE_ADDED);
try { try {
ensureQtQuickTimelineImport(); ensureQtQuickTimelineImport();
} catch (const Exception &e) { } catch (const Exception &e) {

View File

@@ -40,6 +40,7 @@
#include <rewritertransaction.h> #include <rewritertransaction.h>
#include <variantproperty.h> #include <variantproperty.h>
#include <viewmanager.h> #include <viewmanager.h>
#include <qmldesignerconstants.h>
#include <qmldesignericons.h> #include <qmldesignericons.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
@@ -203,6 +204,8 @@ ModelNode TransitionEditorView::addNewTransition()
states = QmlVisualNode(root).states().allStates(); states = QmlVisualNode(root).states().allStates();
} }
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TRANSITION_ADDED);
if (states.isEmpty()) { if (states.isEmpty()) {
Core::AsynchronousMessageBox::warning(tr("No States Defined"), Core::AsynchronousMessageBox::warning(tr("No States Defined"),
tr("There are no states defined in this component.")); tr("There are no states defined in this component."));

View File

@@ -77,6 +77,13 @@ const char M_VIEW_WORKSPACES[] = "QmlDesigner.Menu.View.Workspaces";
const int MODELNODE_PREVIEW_IMAGE_DIMENSIONS = 150; const int MODELNODE_PREVIEW_IMAGE_DIMENSIONS = 150;
const char EVENT_TIMELINE_ADDED[] = "Timeline Added";
const char EVENT_TRANSITION_ADDED[] = "Transition Added";
const char EVENT_STATE_ADDED[] = "State Added";
const char EVENT_ANNOTATION_ADDED[] = "Annotation Added";
const char EVENT_RESOURCE_IMPORTED[] = "Resource Imported ";
const char EVENT_ACTION_EXECUTED[] = "Action Executed ";
namespace Internal { namespace Internal {
enum { debug = 0 }; enum { debug = 0 };
} }

View File

@@ -547,6 +547,17 @@ double QmlDesignerPlugin::formEditorDevicePixelRatio()
return topLevelWindows.constFirst()->screen()->devicePixelRatio(); return topLevelWindows.constFirst()->screen()->devicePixelRatio();
} }
void QmlDesignerPlugin::emitUsageStatistics(const QString &identifier)
{
QTC_ASSERT(instance(), return);
emit instance()->usageStatisticsNotifier(identifier);
}
void QmlDesignerPlugin::emitUsageStatisticsContextAction(const QString &identifier)
{
emitUsageStatistics(Constants::EVENT_ACTION_EXECUTED + identifier);
}
QmlDesignerPlugin *QmlDesignerPlugin::instance() QmlDesignerPlugin *QmlDesignerPlugin::instance()
{ {
return m_instance; return m_instance;

View File

@@ -82,6 +82,13 @@ public:
static double formEditorDevicePixelRatio(); static double formEditorDevicePixelRatio();
static void emitUsageStatistics(const QString &identifier);
static void emitUsageStatisticsContextAction(const QString &identifier);
signals:
void usageStatisticsNotifier(const QString &identifier);
private: // functions private: // functions
void integrateIntoQtCreator(QWidget *modeWidget); void integrateIntoQtCreator(QWidget *modeWidget);
void showDesigner(); void showDesigner();