Add options to change analytics settings after initial prompt

* We are also more explicit in code about disabling the analytics when
  the opt-out is selected.
This commit is contained in:
baldurk
2018-02-05 13:50:22 +00:00
parent 18786451df
commit 2b64d6dfa7
6 changed files with 286 additions and 146 deletions
+56 -33
View File
@@ -73,6 +73,7 @@ namespace
enum class AnalyticsState
{
Nothing,
Disabled,
PromptFirstTime,
SubmitReport,
};
@@ -177,25 +178,25 @@ void saveTo(QVariantMap &parent, const QString &name, const T &el, bool reportin
}
// add a macro to either document, load, or save, depending on our state.
#define ANALYTIC_SERIALISE(varname) \
if(type == AnalyticsSerialiseType::Documenting) \
{ \
QString var = lit(#varname); \
int idx = var.indexOf(QLatin1Char('.')); \
if(idx >= 0) \
var = var.mid(idx + 1); \
doc += lit("<b>%1 (%2)</b>: %3<br>") \
.arg(var) \
.arg(QString::fromUtf8(TypeName<decltype(Analytics::db->varname)>())) \
.arg(docs.varname); \
} \
else if(type == AnalyticsSerialiseType::Loading) \
{ \
loadFrom(values, lit(#varname), Analytics::db->varname); \
} \
else \
{ \
saveTo(values, lit(#varname), Analytics::db->varname, reporting); \
#define ANALYTIC_SERIALISE(varname) \
if(type == AnalyticsSerialiseType::Documenting) \
{ \
QString var = lit(#varname); \
int idx = var.indexOf(QLatin1Char('.')); \
if(idx >= 0) \
var = var.mid(idx + 1); \
doc += lit("<b>%1 (%2)</b>: %3<br>") \
.arg(var) \
.arg(QString::fromUtf8(TypeName<decltype(serdb.varname)>())) \
.arg(docs.varname); \
} \
else if(type == AnalyticsSerialiseType::Loading) \
{ \
loadFrom(values, lit(#varname), serdb.varname); \
} \
else \
{ \
saveTo(values, lit(#varname), serdb.varname, reporting); \
}
// only used during documenting
@@ -309,13 +310,10 @@ static struct AnalyticsDocumentation
} DOCUMENT_ANALYTIC_SECTION(CaptureFeatures, "Capture API Usage");
} docs;
void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
void AnalyticsSerialise(Analytics &serdb, QVariantMap &values, AnalyticsSerialiseType type)
{
bool reporting = type == AnalyticsSerialiseType::Reporting;
if(!Analytics::db)
return;
static_assert(sizeof(Analytics) == 147, "Sizeof Analytics has changed - update serialisation.");
QString doc;
@@ -425,7 +423,8 @@ void AnalyticsSerialise(QVariantMap &values, AnalyticsSerialiseType type)
ANALYTIC_SERIALISE(CaptureFeatures.D3D12Bundle);
}
values[lit("doc")] = doc;
if(type == AnalyticsSerialiseType::Documenting)
values[lit("doc")] = doc;
}
}; // anonymous namespace
@@ -434,21 +433,35 @@ Analytics *Analytics::db = NULL;
void Analytics::Save()
{
if(analyticsSaveLocation.isEmpty())
if(analyticsSaveLocation.isEmpty() || analyticsState == AnalyticsState::Disabled ||
Analytics::db == NULL)
return;
QVariantMap values;
// call to the serialise function to save into the 'values' map
AnalyticsSerialise(values, AnalyticsSerialiseType::Saving);
AnalyticsSerialise(*Analytics::db, values, AnalyticsSerialiseType::Saving);
QFile f(analyticsSaveLocation);
if(f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
SaveToJSON(values, f, analyticsJSONMagic, analyticsJSONVersion);
}
void Analytics::Disable()
{
// do not save any values
Analytics::db = NULL;
analyticsSaveLocation = QString();
analyticsState = AnalyticsState::Disabled;
}
void Analytics::Load()
{
// refuse to load if we were previously disabled, just in case this function is called somehow. We
// require a full restart with the analytics enabled for it to start collecting.
if(analyticsState == AnalyticsState::Disabled)
return;
// allocate space for the Analytics singleton
Analytics::db = &actualDB;
@@ -467,7 +480,7 @@ void Analytics::Load()
bool success = LoadFromJSON(values, f, analyticsJSONMagic, analyticsJSONVersion);
if(success)
AnalyticsSerialise(values, AnalyticsSerialiseType::Loading);
AnalyticsSerialise(*Analytics::db, values, AnalyticsSerialiseType::Loading);
}
}
@@ -491,9 +504,10 @@ void Analytics::Load()
void Analytics::DocumentReport()
{
QVariantMap dummy;
AnalyticsSerialise(dummy, AnalyticsSerialiseType::Documenting);
QString reportText = dummy[lit("doc")].toString();
Analytics dummyDB;
QVariantMap dummyMap;
AnalyticsSerialise(dummyDB, dummyMap, AnalyticsSerialiseType::Documenting);
QString reportText = dummyMap[lit("doc")].toString();
{
QDialog dialog;
@@ -523,20 +537,25 @@ void Analytics::DocumentReport()
void Analytics::Prompt(ICaptureContext &ctx, PersistantConfig &config)
{
if(analyticsState == AnalyticsState::PromptFirstTime)
if(analyticsState == AnalyticsState::Disabled)
{
// do nothing, we're disabled
return;
}
else if(analyticsState == AnalyticsState::PromptFirstTime)
{
QWidget *mainWindow = ctx.GetMainWindow()->Widget();
AnalyticsPromptDialog prompt(config, mainWindow);
RDDialog::show(&prompt);
}
else if(analyticsState == AnalyticsState::SubmitReport)
else if(analyticsState == AnalyticsState::SubmitReport && Analytics::db != NULL)
{
QWidget *mainWindow = ctx.GetMainWindow()->Widget();
QVariantMap values;
AnalyticsSerialise(values, AnalyticsSerialiseType::Reporting);
AnalyticsSerialise(*Analytics::db, values, AnalyticsSerialiseType::Reporting);
QBuffer buf;
buf.open(QBuffer::WriteOnly);
@@ -586,6 +605,10 @@ void Load()
{
}
void Disable()
{
}
void Prompt(ICaptureContext &ctx, PersistantConfig &config)
{
}
+4
View File
@@ -112,6 +112,9 @@ struct Analytics
{
// utility function - loads the analytics from disk and initialise the Analytics::db member.
static void Load();
// utility function - explicitly disables the analytics and sets it into a black-hole mode that
// does nothing.
static void Disable();
// utility function - performs any UI-level prompting, such as asking the user if they want to
// opt-out, or manually vetting a report for uploading.
static void Prompt(ICaptureContext &ctx, PersistantConfig &config);
@@ -307,6 +310,7 @@ struct ICaptureContext;
namespace Analytics
{
void Disable();
void Load();
void Prompt(ICaptureContext &ctx, PersistantConfig &config);
void DocumentReport();
+3 -1
View File
@@ -290,7 +290,9 @@ int main(int argc, char *argv[])
.arg(configFilename));
}
if(!config.Analytics_TotalOptOut)
if(config.Analytics_TotalOptOut)
Analytics::Disable();
else
Analytics::Load();
bool isDarkTheme = IsDarkTheme();
@@ -167,6 +167,37 @@ SettingsDialog::SettingsDialog(ICaptureContext &ctx, QWidget *parent)
ui->AlwaysReplayLocally->setChecked(m_Ctx.Config().AlwaysReplayLocally);
#if RENDERDOC_ANALYTICS_ENABLE
if(m_Ctx.Config().Analytics_TotalOptOut)
{
ui->analyticsAutoSubmit->setChecked(false);
ui->analyticsManualCheck->setChecked(false);
ui->analyticsOptOut->setChecked(true);
// once we've started with analytics disabled, only a restart can re-enable them.
ui->analyticsAutoSubmit->setText(ui->analyticsAutoSubmit->text() + tr(" (Requires Restart)"));
ui->analyticsManualCheck->setText(ui->analyticsManualCheck->text() + tr(" (Requires Restart)"));
}
else if(m_Ctx.Config().Analytics_ManualCheck)
{
ui->analyticsAutoSubmit->setChecked(false);
ui->analyticsManualCheck->setChecked(true);
ui->analyticsOptOut->setChecked(false);
}
else
{
ui->analyticsAutoSubmit->setChecked(true);
ui->analyticsManualCheck->setChecked(false);
ui->analyticsOptOut->setChecked(false);
}
#else
ui->analyticsDescribeLabel->setText(tr("Analytics was disabled at compile time."));
ui->analyticsAutoSubmit->setEnabled(false);
ui->analyticsManualCheck->setEnabled(false);
ui->analyticsOptOut->setEnabled(false);
#endif
ui->AllowGlobalHook->setChecked(m_Ctx.Config().AllowGlobalHook);
ui->EventBrowser_TimeUnit->setCurrentIndex((int)m_Ctx.Config().EventBrowser_TimeUnit);
@@ -319,6 +350,47 @@ void SettingsDialog::on_AlwaysReplayLocally_toggled(bool checked)
m_Ctx.Config().Save();
}
void SettingsDialog::on_analyticsAutoSubmit_toggled(bool checked)
{
if(checked)
{
m_Ctx.Config().Analytics_ManualCheck = false;
m_Ctx.Config().Analytics_TotalOptOut = false;
m_Ctx.Config().Save();
}
}
void SettingsDialog::on_analyticsManualCheck_toggled(bool checked)
{
if(checked)
{
m_Ctx.Config().Analytics_ManualCheck = true;
m_Ctx.Config().Analytics_TotalOptOut = false;
m_Ctx.Config().Save();
}
}
void SettingsDialog::on_analyticsOptOut_toggled(bool checked)
{
if(checked)
{
m_Ctx.Config().Analytics_ManualCheck = false;
m_Ctx.Config().Analytics_TotalOptOut = true;
// immediately disable the analytics collection and ensure it can't send any reports.
Analytics::Disable();
m_Ctx.Config().Save();
}
}
void SettingsDialog::on_analyticsDescribeLabel_linkActivated(const QString &link)
{
Analytics::DocumentReport();
}
// core
void SettingsDialog::on_chooseSearchPaths_clicked()
{
@@ -60,6 +60,9 @@ private slots:
void on_CheckUpdate_AllowChecks_toggled(bool checked);
void on_Font_PreferMonospaced_toggled(bool checked);
void on_AlwaysReplayLocally_toggled(bool checked);
void on_analyticsAutoSubmit_toggled(bool checked);
void on_analyticsManualCheck_toggled(bool checked);
void on_analyticsOptOut_toggled(bool checked);
// core
void on_chooseSearchPaths_clicked();
@@ -100,6 +103,8 @@ private slots:
// manual slots
void formatter_valueChanged(int value);
void on_analyticsDescribeLabel_linkActivated(const QString &link);
private:
Ui::SettingsDialog *ui;
+146 -112
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>614</width>
<height>470</height>
<width>561</width>
<height>519</height>
</rect>
</property>
<property name="windowTitle">
@@ -73,7 +73,7 @@
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>6</number>
<number>0</number>
</property>
<property name="documentMode">
<bool>true</bool>
@@ -82,7 +82,7 @@
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
@@ -101,108 +101,6 @@
<string>General</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="toolTip">
<string>Any numbers larger than this exponent will be displayed in scientific notation.
e.g. 1000 * 10 = 1e4</string>
</property>
<property name="text">
<string>Positive exponential cutoff value</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_9">
<property name="toolTip">
<string>Wherever possible a monospaced font will be used instead of the default font</string>
</property>
<property name="text">
<string>Prefer monospaced fonts in UI (restart required)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="Formatter_MinFigures">
<property name="toolTip">
<string>Decimals will display at least this many digits.
e.g. a value of 2 means 0 will display as 0.00, 0.5 as 0.50</string>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="toolTip">
<string>Changes the default directory for the save dialog when saving capture files.
Defaults to blank, which follows system default behaviour.</string>
</property>
<property name="text">
<string>Default save directory for captures</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="toolTip">
<string>Any numbers smaller than this exponent will be displayed in scientific notation.
E.g. a value of 3 means 0.005 / 10 = 5E-4</string>
</property>
<property name="text">
<string>Negative exponential cutoff value</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Decimals will display at least this many digits.
e.g. a value of 2 means 0 will display as 0.00, 0.5 as 0.50</string>
</property>
<property name="text">
<string>Minimum decimal places on float values</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="globalHookLabel">
<property name="toolTip">
<string>Enables functionality on the capture application window that will insert RenderDoc automatically
into all new processes created - then inject into the target (matching) executable.
Useful for capturing programs indirectly that can't easily be launched directly by RenderDoc
Since this is a global system hook it must be used carefully and only when necessary!</string>
</property>
<property name="text">
<string>Allow global process hooking - be careful!</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="toolTip">
<string>No more significant figures than this will be displayed on floats.
e.g. a value of 5 means 0.123456789 will display as 0.12345</string>
</property>
<property name="text">
<string>Maximum significant figures on decimals</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_8">
<property name="toolTip">
<string>Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions.</string>
</property>
<property name="text">
<string>Allow periodic anonymous update checks</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="toolTip">
@@ -231,12 +129,6 @@ E.g. a value of 3 means 0.005 / 10 = 5E-4</string>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>216</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
@@ -394,6 +286,148 @@ This option overrides that and will always replay locally if the local context i
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="toolTip">
<string>Any numbers larger than this exponent will be displayed in scientific notation.
e.g. 1000 * 10 = 1e4</string>
</property>
<property name="text">
<string>Positive exponential cutoff value</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_9">
<property name="toolTip">
<string>Wherever possible a monospaced font will be used instead of the default font</string>
</property>
<property name="text">
<string>Prefer monospaced fonts in UI (restart required)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="Formatter_MinFigures">
<property name="toolTip">
<string>Decimals will display at least this many digits.
e.g. a value of 2 means 0 will display as 0.00, 0.5 as 0.50</string>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="toolTip">
<string>Changes the default directory for the save dialog when saving capture files.
Defaults to blank, which follows system default behaviour.</string>
</property>
<property name="text">
<string>Default save directory for captures</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="toolTip">
<string>Any numbers smaller than this exponent will be displayed in scientific notation.
E.g. a value of 3 means 0.005 / 10 = 5E-4</string>
</property>
<property name="text">
<string>Negative exponential cutoff value</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Decimals will display at least this many digits.
e.g. a value of 2 means 0 will display as 0.00, 0.5 as 0.50</string>
</property>
<property name="text">
<string>Minimum decimal places on float values</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="globalHookLabel">
<property name="toolTip">
<string>Enables functionality on the capture application window that will insert RenderDoc automatically
into all new processes created - then inject into the target (matching) executable.
Useful for capturing programs indirectly that can't easily be launched directly by RenderDoc
Since this is a global system hook it must be used carefully and only when necessary!</string>
</property>
<property name="text">
<string>Allow global process hooking - be careful!</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="toolTip">
<string>No more significant figures than this will be displayed on floats.
e.g. a value of 5 means 0.123456789 will display as 0.12345</string>
</property>
<property name="text">
<string>Maximum significant figures on decimals</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_8">
<property name="toolTip">
<string>Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions.</string>
</property>
<property name="text">
<string>Allow periodic anonymous update checks</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>Anonymous Analytics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="analyticsDescribeLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;#analyticsDescribe&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Click here&lt;/span&gt;&lt;/a&gt; to see currently reported data.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="analyticsAutoSubmit">
<property name="text">
<string>Gather anonymous low-detail statistics and submit automatically.</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="analyticsManualCheck">
<property name="text">
<string>Gather anonymous low-detail statistics, but manually verify before submitting.</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="analyticsOptOut">
<property name="text">
<string>Do not gather or submit any statistics.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>