1 /*
2 Copyright (C) 2017 Volker Krause <vkrause@kde.org>
3
4 Permission is hereby granted, free of charge, to any person obtaining
5 a copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and/or sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions:
11
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "feedbackconfiguicontroller.h"
25 #include "abstractdatasource.h"
26
27 #include <QGuiApplication>
28 #include <QSet>
29 #include <QVector>
30
31 #include <algorithm>
32 #include <vector>
33
34 using namespace KUserFeedback;
35
36 namespace KUserFeedback {
37 class FeedbackConfigUiControllerPrivate {
38 public:
39 FeedbackConfigUiControllerPrivate();
40
41 Provider *provider;
42 std::vector<Provider::TelemetryMode> telemetryModeMap;
43 QString m_appName;
44 };
45 }
46
FeedbackConfigUiControllerPrivate()47 FeedbackConfigUiControllerPrivate::FeedbackConfigUiControllerPrivate() :
48 provider(nullptr),
49 m_appName(QGuiApplication::applicationDisplayName())
50 {
51 }
52
FeedbackConfigUiController(QObject * parent)53 FeedbackConfigUiController::FeedbackConfigUiController(QObject* parent)
54 : QObject(parent)
55 , d(new FeedbackConfigUiControllerPrivate)
56 {
57 }
58
~FeedbackConfigUiController()59 FeedbackConfigUiController::~FeedbackConfigUiController()
60 {
61 }
62
feedbackProvider() const63 Provider* FeedbackConfigUiController::feedbackProvider() const
64 {
65 return d->provider;
66 }
67
setFeedbackProvider(Provider * provider)68 void FeedbackConfigUiController::setFeedbackProvider(Provider* provider)
69 {
70 if (d->provider == provider)
71 return;
72 d->provider = provider;
73
74 d->telemetryModeMap.clear();
75 d->telemetryModeMap.reserve(5);
76 d->telemetryModeMap.push_back(Provider::NoTelemetry);
77 d->telemetryModeMap.push_back(Provider::BasicSystemInformation);
78 d->telemetryModeMap.push_back(Provider::BasicUsageStatistics);
79 d->telemetryModeMap.push_back(Provider::DetailedSystemInformation);
80 d->telemetryModeMap.push_back(Provider::DetailedUsageStatistics);
81
82 QSet<Provider::TelemetryMode> supportedModes;
83 supportedModes.reserve(d->telemetryModeMap.size());
84 supportedModes.insert(Provider::NoTelemetry);
85 foreach (const auto &src, provider->dataSources())
86 supportedModes.insert(src->telemetryMode());
87 for (auto it = d->telemetryModeMap.begin(); it != d->telemetryModeMap.end();) {
88 if (!supportedModes.contains(*it))
89 it = d->telemetryModeMap.erase(it);
90 else
91 ++it;
92 }
93
94 emit providerChanged();
95 }
96
telemetryModeCount() const97 int FeedbackConfigUiController::telemetryModeCount() const
98 {
99 return d->telemetryModeMap.size();
100 }
101
surveyModeCount() const102 int FeedbackConfigUiController::surveyModeCount() const
103 {
104 return 3;
105 }
106
telemetryIndexToMode(int index) const107 Provider::TelemetryMode FeedbackConfigUiController::telemetryIndexToMode(int index) const
108 {
109 if (index < 0 || index >= telemetryModeCount())
110 return Provider::NoTelemetry;
111 return d->telemetryModeMap[index];
112 }
113
telemetryModeToIndex(Provider::TelemetryMode mode) const114 int FeedbackConfigUiController::telemetryModeToIndex(Provider::TelemetryMode mode) const
115 {
116 const auto it = std::lower_bound(d->telemetryModeMap.begin(), d->telemetryModeMap.end(), mode);
117 if (it == d->telemetryModeMap.end())
118 return 0;
119 return std::distance(d->telemetryModeMap.begin(), it);
120 }
121
telemetryModeName(int telemetryIndex) const122 QString FeedbackConfigUiController::telemetryModeName(int telemetryIndex) const
123 {
124 return telemetryName(telemetryIndexToMode(telemetryIndex));
125 }
126
telemetryModeDescription(int telemetryIndex) const127 QString FeedbackConfigUiController::telemetryModeDescription(int telemetryIndex) const
128 {
129 return telemetryDescription(telemetryIndexToMode(telemetryIndex));
130 }
131
telemetryName(KUserFeedback::Provider::TelemetryMode mode) const132 QString FeedbackConfigUiController::telemetryName(KUserFeedback::Provider::TelemetryMode mode) const
133 {
134 switch (mode) {
135 case Provider::NoTelemetry:
136 return tr("Disabled");
137 case Provider::BasicSystemInformation:
138 return tr("Basic system information");
139 case Provider::BasicUsageStatistics:
140 return tr("Basic system information and usage statistics");
141 case Provider::DetailedSystemInformation:
142 return tr("Detailed system information and basic usage statistics");
143 case Provider::DetailedUsageStatistics:
144 return tr("Detailed system information and usage statistics");
145 }
146
147 return {};
148 }
149
telemetryDescription(KUserFeedback::Provider::TelemetryMode mode) const150 QString FeedbackConfigUiController::telemetryDescription(KUserFeedback::Provider::TelemetryMode mode) const
151 {
152 const auto name = applicationName();
153 if (name.isEmpty()) {
154 switch (mode) {
155 case Provider::NoTelemetry:
156 return tr(
157 "Don't share anything"
158 );
159 case Provider::BasicSystemInformation:
160 return tr(
161 "Share basic system information such as the version of the application and the operating system"
162 );
163 case Provider::BasicUsageStatistics:
164 return tr(
165 "Share basic system information and basic statistics on how often you use the application"
166 );
167 case Provider::DetailedSystemInformation:
168 return tr(
169 "Share basic statistics on how often you use the application, as well as more detailed information about your system"
170 );
171 case Provider::DetailedUsageStatistics:
172 return tr(
173 "Share detailed system information and statistics on how often individual features of the application are used."
174 );
175 }
176 } else {
177 switch (mode) {
178 case Provider::NoTelemetry:
179 return tr(
180 "Don't share anything"
181 );
182 case Provider::BasicSystemInformation:
183 return tr(
184 "Share basic system information such as the version of %1 and and the operating system"
185 ).arg(name);
186 case Provider::BasicUsageStatistics:
187 return tr(
188 "Share basic system information and basic statistics on how often you use %1"
189 ).arg(name);
190 case Provider::DetailedSystemInformation:
191 return tr(
192 "Share basic statistics on how often you use %1, as well as more detailed information about your system"
193 ).arg(name);
194 case Provider::DetailedUsageStatistics:
195 return tr(
196 "Share detailed system information and statistics on how often individual features of %1 are used."
197 ).arg(name);
198 }
199 }
200
201 return QString();
202 }
203
telemetryModeDetails(int telemetryIndex) const204 QString FeedbackConfigUiController::telemetryModeDetails(int telemetryIndex) const
205 {
206 if (telemetryIndex <= 0 || telemetryIndex >= telemetryModeCount())
207 return QString();
208
209 auto srcs = d->provider->dataSources();
210 std::stable_sort(srcs.begin(), srcs.end(), [](AbstractDataSource *lhs, AbstractDataSource *rhs) {
211 return lhs->telemetryMode() < rhs->telemetryMode();
212 });
213
214 auto detailsStr = QStringLiteral("<ul>");
215 foreach (const auto *src, srcs) {
216 if (telemetryIndex >= telemetryModeToIndex(src->telemetryMode()) && !src->description().isEmpty())
217 detailsStr += QStringLiteral("<li>") + src->description() + QStringLiteral("</li>");
218 }
219 return detailsStr + QStringLiteral("</ul>");
220 }
221
surveyIndexToInterval(int index) const222 int FeedbackConfigUiController::surveyIndexToInterval(int index) const
223 {
224 switch (index) {
225 case 0: return -1;
226 case 1: return 90;
227 case 2: return 0;
228 }
229 return -1;
230 }
231
surveyIntervalToIndex(int interval) const232 int FeedbackConfigUiController::surveyIntervalToIndex(int interval) const
233 {
234 if (interval < 0)
235 return 0;
236 else if (interval >= 90)
237 return 1;
238 else
239 return 2;
240 }
241
surveyModeDescription(int surveyIndex) const242 QString FeedbackConfigUiController::surveyModeDescription(int surveyIndex) const
243 {
244 const auto name = applicationName();
245 if (name.isEmpty()) {
246 switch (surveyIndex) {
247 case 0:
248 return tr(
249 "Don't participate in usability surveys"
250 );
251 case 1:
252 return tr(
253 "Participate in surveys about the application not more than four times a year"
254 );
255 case 2:
256 return tr(
257 "Participate in surveys about the application whenever one is available (they can be deferred or skipped)"
258 );
259 }
260 } else {
261 switch (surveyIndex) {
262 case 0:
263 return tr(
264 "Don't participate in usability surveys about %1"
265 ).arg(name);
266 case 1:
267 return tr(
268 "Participate in surveys about %1 not more than four times a year"
269 ).arg(name);
270 case 2:
271 return tr(
272 "Participate in surveys about %1 whenever one is available (they can be deferred or skipped)"
273 ).arg(name);
274 }
275 }
276
277 return QString();
278 }
279
applicationName() const280 QString FeedbackConfigUiController::applicationName() const
281 {
282 return d->m_appName;
283 }
284
setApplicationName(const QString & appName)285 void FeedbackConfigUiController::setApplicationName(const QString& appName)
286 {
287 if (appName == d->m_appName)
288 return;
289
290 d->m_appName = appName;
291 Q_EMIT applicationNameChanged(appName);
292 }
293