Start a user survey dialog

The idea is that a week after the user starts using Subsurface we ask them
if they would like to submit a survey response.

If you are running a development build, don't wait seven days.

This patch doesn't do anything with the user's selections, doesn't submit
anything to our server, etc. It's just a placeholder to tune what we
should ask, etc.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2014-06-13 10:56:46 -07:00
parent 64236388e4
commit cdd3b3d9cd
6 changed files with 320 additions and 5 deletions

View file

@ -24,7 +24,7 @@
#include <fcntl.h> #include <fcntl.h>
#include "divelistview.h" #include "divelistview.h"
#include "starwidget.h" #include "starwidget.h"
#include "ssrf-version.h"
#include "dive.h" #include "dive.h"
#include "display.h" #include "display.h"
#include "divelist.h" #include "divelist.h"
@ -47,6 +47,7 @@
#endif #endif
#include "divelogimportdialog.h" #include "divelogimportdialog.h"
#include "divelogexportdialog.h" #include "divelogexportdialog.h"
#include "usersurvey.h"
#ifndef NO_USERMANUAL #ifndef NO_USERMANUAL
#include "usermanual.h" #include "usermanual.h"
#endif #endif
@ -61,7 +62,8 @@ MainWindow::MainWindow() : QMainWindow(),
yearlyStatsModel(0), yearlyStatsModel(0),
state(VIEWALL), state(VIEWALL),
updateManager(0), updateManager(0),
fakeDiveId(0) fakeDiveId(0),
survey(0)
{ {
Q_ASSERT_X(m_Instance == NULL, "MainWindow", "MainWindow recreated!"); Q_ASSERT_X(m_Instance == NULL, "MainWindow", "MainWindow recreated!");
m_Instance = this; m_Instance = this;
@ -814,10 +816,31 @@ void MainWindow::readSettings()
default_dive_computer_device = getSetting(s, "dive_computer_device"); default_dive_computer_device = getSetting(s, "dive_computer_device");
s.endGroup(); s.endGroup();
loadRecentFiles(&s); loadRecentFiles(&s);
checkSurvey(&s);
} }
#undef TOOLBOX_PREF_BUTTON #undef TOOLBOX_PREF_BUTTON
void MainWindow::checkSurvey(QSettings *s)
{
s->beginGroup("UserSurvey");
if (!s->contains("FirstUse42")) {
QVariant value = QDate().currentDate();
s->setValue("FirstUse42", value);
} else {
// wait a week for production versions, but not at all for non-tagged builds
QString ver(VERSION_STRING);
int waitTime = ver.contains('-') ? -1 : 7;
QDate firstUse42 = s->value("FirstUse42").toDate();
if (firstUse42.daysTo(QDate().currentDate()) > waitTime && !s->contains("SurveyDone")) {
if (!survey)
survey = new UserSurvey(this);
survey->show();
}
}
s->endGroup();
}
void MainWindow::writeSettings() void MainWindow::writeSettings()
{ {
QSettings settings; QSettings settings;

View file

@ -79,6 +79,7 @@ public:
bool filesFromCommandLine() const; bool filesFromCommandLine() const;
void setPlanNotes(const char *notes); void setPlanNotes(const char *notes);
void printPlan(); void printPlan();
void checkSurvey(QSettings *s);
private private
slots: slots:
/* file menu action */ /* file menu action */
@ -184,6 +185,7 @@ private:
bool plannerStateClean(); bool plannerStateClean();
void createFakeDiveForAddAndPlan(); void createFakeDiveForAddAndPlan();
int fakeDiveId; int fakeDiveId;
QDialog *survey;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

53
qt-ui/usersurvey.cpp Normal file
View file

@ -0,0 +1,53 @@
#include <QShortcut>
#include <QMessageBox>
#include <QDebug>
#include <QSettings>
#include "usersurvey.h"
#include "ui_usersurvey.h"
#include "ssrf-version.h"
#include "helpers.h"
UserSurvey::UserSurvey(QWidget *parent) : QDialog(parent),
ui(new Ui::UserSurvey)
{
ui->setupUi(this);
// fill in the system data
}
UserSurvey::~UserSurvey()
{
delete ui;
}
void UserSurvey::on_buttonBox_accepted()
{
// now we need to collect the data and submit it
QSettings s;
s.beginGroup("UserSurvey");
s.setValue("SurveyDone", "submitted");
hide();
}
void UserSurvey::on_buttonBox_rejected()
{
QMessageBox response(this);
response.setText(tr("Should we ask you later?"));
response.addButton(tr("Don't ask me again"), QMessageBox::RejectRole);
response.addButton(tr("Ask Later"), QMessageBox::AcceptRole);
response.setWindowTitle(tr("Ask again?")); // Not displayed on MacOSX as described in Qt API
response.setIcon(QMessageBox::Question);
response.setWindowModality(Qt::WindowModal);
switch (response.exec()) {
case QDialog::Accepted:
// nothing to do here, we'll just ask again the next time they start
break;
case QDialog::Rejected:
QSettings s;
s.beginGroup("UserSurvey");
s.setValue("SurveyDone", "declined");
break;
}
hide();
}

25
qt-ui/usersurvey.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef USERSURVEY_H
#define USERSURVEY_H
#include <QDialog>
namespace Ui {
class UserSurvey;
}
class UserSurvey : public QDialog {
Q_OBJECT
public:
explicit UserSurvey(QWidget *parent = 0);
~UserSurvey();
private
slots:
void on_buttonBox_accepted();
void on_buttonBox_rejected();
private:
Ui::UserSurvey *ui;
};
#endif // USERSURVEY_H

209
qt-ui/usersurvey.ui Normal file
View file

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserSurvey</class>
<widget class="QDialog" name="UserSurvey">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>410</width>
<height>524</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>40</x>
<y>490</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Subsurface User Survey</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>371</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>We would love to learn more about our users, their preferences and their usage habits. Please take a minute to fill out this form and submit it to the Subsurface team. Please select all options that apply to you.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QCheckBox" name="recreational">
<property name="geometry">
<rect>
<x>10</x>
<y>140</y>
<width>151</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Recreational DIver</string>
</property>
</widget>
<widget class="QCheckBox" name="tech">
<property name="geometry">
<rect>
<x>160</x>
<y>140</y>
<width>151</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Tech Diver</string>
</property>
</widget>
<widget class="QCheckBox" name="planning">
<property name="geometry">
<rect>
<x>10</x>
<y>160</y>
<width>211</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Interested in dive planning</string>
</property>
</widget>
<widget class="QCheckBox" name="download">
<property name="geometry">
<rect>
<x>10</x>
<y>180</y>
<width>371</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>I am downloading dives from supported dive computer</string>
</property>
</widget>
<widget class="QCheckBox" name="import_2">
<property name="geometry">
<rect>
<x>10</x>
<y>200</y>
<width>371</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>I am importing dives from other software / sources</string>
</property>
</widget>
<widget class="QCheckBox" name="manual">
<property name="geometry">
<rect>
<x>10</x>
<y>220</y>
<width>371</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>I am manually entering dives</string>
</property>
</widget>
<widget class="QTextEdit" name="suggestions">
<property name="geometry">
<rect>
<x>10</x>
<y>270</y>
<width>371</width>
<height>101</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Suggestions and missing features&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QCheckBox" name="companion">
<property name="geometry">
<rect>
<x>10</x>
<y>240</y>
<width>381</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>I use the Android companion app to track dive locations</string>
</property>
</widget>
<widget class="QTextEdit" name="system">
<property name="geometry">
<rect>
<x>10</x>
<y>380</y>
<width>371</width>
<height>101</height>
</rect>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Filled with some preferences (language, units, etc) plus system data (OS detailed version)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</widget>
<tabstops>
<tabstop>recreational</tabstop>
<tabstop>tech</tabstop>
<tabstop>planning</tabstop>
<tabstop>download</tabstop>
<tabstop>import_2</tabstop>
<tabstop>manual</tabstop>
<tabstop>companion</tabstop>
<tabstop>suggestions</tabstop>
<tabstop>system</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -81,7 +81,8 @@ HEADERS = \
qt-ui/profile/divetooltipitem.h \ qt-ui/profile/divetooltipitem.h \
qt-ui/profile/ruleritem.h \ qt-ui/profile/ruleritem.h \
qt-ui/updatemanager.h \ qt-ui/updatemanager.h \
qt-ui/divelogexportdialog.h qt-ui/divelogexportdialog.h \
qt-ui/usersurvey.h
android: HEADERS -= \ android: HEADERS -= \
qt-ui/usermanual.h \ qt-ui/usermanual.h \
@ -158,7 +159,8 @@ SOURCES = \
qt-ui/profile/divetooltipitem.cpp \ qt-ui/profile/divetooltipitem.cpp \
qt-ui/profile/ruleritem.cpp \ qt-ui/profile/ruleritem.cpp \
qt-ui/updatemanager.cpp \ qt-ui/updatemanager.cpp \
qt-ui/divelogexportdialog.cpp qt-ui/divelogexportdialog.cpp \
qt-ui/usersurvey.cpp
android: SOURCES += android.cpp android: SOURCES += android.cpp
else: linux*: SOURCES += linux.c else: linux*: SOURCES += linux.c
@ -188,7 +190,8 @@ FORMS = \
qt-ui/divelogimportdialog.ui \ qt-ui/divelogimportdialog.ui \
qt-ui/usermanual.ui \ qt-ui/usermanual.ui \
qt-ui/divelogexportdialog.ui \ qt-ui/divelogexportdialog.ui \
qt-ui/plannerSettings.ui qt-ui/plannerSettings.ui \
qt-ui/usersurvey.ui
# Nether usermanual or printing is supported on android right now # Nether usermanual or printing is supported on android right now
android: FORMS -= qt-ui/usermanual.ui qt-ui/printoptions.ui android: FORMS -= qt-ui/usermanual.ui qt-ui/printoptions.ui