diff --git a/qrenderdoc/Code/Interface/Analytics.cpp b/qrenderdoc/Code/Interface/Analytics.cpp
index 00c96e678..56740a042 100644
--- a/qrenderdoc/Code/Interface/Analytics.cpp
+++ b/qrenderdoc/Code/Interface/Analytics.cpp
@@ -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("%1 (%2): %3
") \
- .arg(var) \
- .arg(QString::fromUtf8(TypeNamevarname)>())) \
- .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("%1 (%2): %3
") \
+ .arg(var) \
+ .arg(QString::fromUtf8(TypeName())) \
+ .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)
{
}
diff --git a/qrenderdoc/Code/Interface/Analytics.h b/qrenderdoc/Code/Interface/Analytics.h
index 5143fadc2..36d649646 100644
--- a/qrenderdoc/Code/Interface/Analytics.h
+++ b/qrenderdoc/Code/Interface/Analytics.h
@@ -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();
diff --git a/qrenderdoc/Code/qrenderdoc.cpp b/qrenderdoc/Code/qrenderdoc.cpp
index 6bf57c3b2..a5d957030 100644
--- a/qrenderdoc/Code/qrenderdoc.cpp
+++ b/qrenderdoc/Code/qrenderdoc.cpp
@@ -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();
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
index 83d4888d9..686eb0066 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp
@@ -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()
{
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.h b/qrenderdoc/Windows/Dialogs/SettingsDialog.h
index e167e7634..4919a02a6 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.h
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.h
@@ -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;
diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
index 91faba70a..8f5f98f7c 100644
--- a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
+++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui
@@ -6,8 +6,8 @@
0
0
- 614
- 470
+ 561
+ 519
@@ -73,7 +73,7 @@
QTabWidget::West
- 6
+ 0
true
@@ -82,7 +82,7 @@
General
-
+
0
@@ -101,108 +101,6 @@
General
- -
-
-
- Any numbers larger than this exponent will be displayed in scientific notation.
-e.g. 1000 * 10 = 1e4
-
-
- Positive exponential cutoff value
-
-
-
- -
-
-
- Wherever possible a monospaced font will be used instead of the default font
-
-
- Prefer monospaced fonts in UI (restart required)
-
-
-
- -
-
-
- 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
-
-
- 2
-
-
-
- -
-
-
- Changes the default directory for the save dialog when saving capture files.
-
-Defaults to blank, which follows system default behaviour.
-
-
- Default save directory for captures
-
-
-
- -
-
-
- Any numbers smaller than this exponent will be displayed in scientific notation.
-E.g. a value of 3 means 0.005 / 10 = 5E-4
-
-
- Negative exponential cutoff value
-
-
-
- -
-
-
- 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
-
-
- Minimum decimal places on float values
-
-
-
- -
-
-
- 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!
-
-
- Allow global process hooking - be careful!
-
-
-
- -
-
-
- 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
-
-
- Maximum significant figures on decimals
-
-
-
- -
-
-
- Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions.
-
-
- Allow periodic anonymous update checks
-
-
-
-
@@ -231,12 +129,6 @@ E.g. a value of 3 means 0.005 / 10 = 5E-4
Qt::Vertical
-
-
- 20
- 216
-
-
-
@@ -394,6 +286,148 @@ This option overrides that and will always replay locally if the local context i
+ -
+
+
+ Any numbers larger than this exponent will be displayed in scientific notation.
+e.g. 1000 * 10 = 1e4
+
+
+ Positive exponential cutoff value
+
+
+
+ -
+
+
+ Wherever possible a monospaced font will be used instead of the default font
+
+
+ Prefer monospaced fonts in UI (restart required)
+
+
+
+ -
+
+
+ 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
+
+
+ 2
+
+
+
+ -
+
+
+ Changes the default directory for the save dialog when saving capture files.
+
+Defaults to blank, which follows system default behaviour.
+
+
+ Default save directory for captures
+
+
+
+ -
+
+
+ Any numbers smaller than this exponent will be displayed in scientific notation.
+E.g. a value of 3 means 0.005 / 10 = 5E-4
+
+
+ Negative exponential cutoff value
+
+
+
+ -
+
+
+ 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
+
+
+ Minimum decimal places on float values
+
+
+
+ -
+
+
+ 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!
+
+
+ Allow global process hooking - be careful!
+
+
+
+ -
+
+
+ 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
+
+
+ Maximum significant figures on decimals
+
+
+
+ -
+
+
+ Allows RenderDoc to phone home to https://renderdoc.org to anonymously check for new versions.
+
+
+ Allow periodic anonymous update checks
+
+
+
+
+
+
+ -
+
+
+ Anonymous Analytics
+
+
+
-
+
+
+ <html><head/><body><p><a href="#analyticsDescribe"><span style=" text-decoration: underline; color:#0000ff;">Click here</span></a> to see currently reported data.</p></body></html>
+
+
+
+ -
+
+
+ Gather anonymous low-detail statistics and submit automatically.
+
+
+ true
+
+
+
+ -
+
+
+ Gather anonymous low-detail statistics, but manually verify before submitting.
+
+
+
+ -
+
+
+ Do not gather or submit any statistics.
+
+
+