on fb178ff help sign in
unity8/tests/mocks/libusermetrics/UserMetrics.cpp
474 lines 12 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Pete Woods <pete.woods@canonical.com>
17 */
19#include "UserMetrics.h"
20#include <qvariantlistmodel.h>
22#include <QtCore/QDir>
23#include <QtCore/QString>
24#include <QtGui/QIcon>
25#include <QMultiMap>
27#include <functional>
28#include <random>
30using namespace UserMetricsOutput;
32namespace UserMetricsOutput
34class UserMetricsDataPrivate;
35class UserMetricsPrivate;
37class Q_DECL_EXPORT UserMetricsData: public QObject
39public:
40 explicit UserMetricsData(QObject *parent);
42 UserMetricsData(const QString &label,
43 const ColorTheme &firstColor,
44 const QVariantList &firstMonth,
45 const ColorTheme &secondColor,
46 const QVariantList &secondMonth, QObject* parent);
48 ~UserMetricsData();
50protected:
51 UserMetricsDataPrivate * const d_ptr;
53public:
54 const QString & label() const;
55 const ColorTheme & firstColor() const;
56 const QVariantList & firstMonth() const;
57 const ColorTheme & secondColor() const;
58 const QVariantList & secondMonth() const;
59 int length() const;
61private:
62 Q_DECLARE_PRIVATE(UserMetricsData)
63};
65class UserMetricsPrivate: QObject
67public:
68 explicit UserMetricsPrivate(UserMetrics *parent);
70 ~UserMetricsPrivate();
72public:
73 typedef QSharedPointer<UserMetricsData> UserMetricsDataPtr;
74 typedef QMultiMap<QString, UserMetricsDataPtr> FakeDataMap;
76 UserMetrics * const q_ptr;
77 QString m_label;
78 ColorTheme m_firstColor;
79 QVariantListModel m_firstMonth;
80 ColorTheme m_secondColor;
81 QVariantListModel m_secondMonth;
82 int m_currentDay;
83 QString m_username;
84 FakeDataMap::const_iterator m_dataIndex;
85 UserMetricsDataPtr m_newData;
86 FakeDataMap m_fakeData;
88 void setUsername(const QString &username);
90protected:
91 void nextFakeData();
93 void generateFakeData();
95 void loadFakeData();
97 void finishSetFakeData();
99private:
100 Q_DECLARE_PUBLIC(UserMetrics)
101};
103class UserMetricsDataPrivate: QObject
105public:
106 explicit UserMetricsDataPrivate(UserMetricsData *parent);
108 UserMetricsDataPrivate(const QString &label,
109 const ColorTheme &firstColor,
110 const QVariantList &firstMonth,
111 const ColorTheme &secondColor,
112 const QVariantList &secondMonth, UserMetricsData *parent);
114 ~UserMetricsDataPrivate();
116 UserMetricsData * const q_ptr;
117 QString m_label;
118 ColorTheme m_firstColor;
119 QVariantList m_firstMonth;
120 ColorTheme m_secondColor;
121 QVariantList m_secondMonth;
122 int m_length;
124protected:
125 int calculateLength();
127private:
128 Q_DECLARE_PUBLIC(UserMetricsData)
129};
133UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
134 q_ptr(parent), m_firstColor(this), m_secondColor(this)
136 m_length = calculateLength();
139UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
140 const ColorTheme &firstColor, const QVariantList &firstMonth,
141 const ColorTheme &secondColor,
142 const QVariantList &secondMonth, UserMetricsData *parent) :
143 q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
144 firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
146 m_length = calculateLength();
147 m_firstColor = firstColor;
148 m_secondColor = secondColor;
151UserMetricsDataPrivate::~UserMetricsDataPrivate()
155int UserMetricsDataPrivate::calculateLength()
157 int day(m_firstMonth.size());
158 auto it = m_firstMonth.end(), end = m_firstMonth.begin();
159 while (it != end)
160 {
161 --it;
162 --day;
163 if (!it->isNull())
164 {
165 return day;
166 }
167 }
169 return -1;
172UserMetricsData::UserMetricsData(QObject *parent) :
173 QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
177UserMetricsData::UserMetricsData(const QString &label,
178 const ColorTheme &firstColor, const QVariantList &firstMonth,
179 const ColorTheme &secondColor,
180 const QVariantList &secondMonth, QObject* parent) :
181 QObject(parent), d_ptr(
182 new UserMetricsDataPrivate(label, firstColor, firstMonth,
183 secondColor, secondMonth, this))
187UserMetricsData::~UserMetricsData()
189 delete d_ptr;
192const QString & UserMetricsData::label() const
194 return d_ptr->m_label;
197const ColorTheme & UserMetricsData::firstColor() const
199 return d_ptr->m_firstColor;
202const QVariantList & UserMetricsData::firstMonth() const
204 return d_ptr->m_firstMonth;
207const ColorTheme & UserMetricsData::secondColor() const
209 return d_ptr->m_secondColor;
212const QVariantList & UserMetricsData::secondMonth() const
214 return d_ptr->m_secondMonth;
217int UserMetricsData::length() const
219 return d_ptr->m_length;
222UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
223 q_ptr(parent), m_firstColor(this), m_secondColor(this), m_currentDay(0)
225 m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
228UserMetricsPrivate::~UserMetricsPrivate()
232void UserMetricsPrivate::setUsername(const QString &username)
234 if (m_username == username && m_newData) {
235 return;
236 }
238 m_username = username;
240 m_dataIndex = m_fakeData.constFind(m_username);
241 if (m_dataIndex == m_fakeData.constEnd())
242 {
243 m_dataIndex = m_fakeData.constFind("");
244 }
246 loadFakeData();
248 q_ptr->usernameChanged(m_username);
251void UserMetricsPrivate::generateFakeData()
253 std::default_random_engine generator;
254 std::normal_distribution<qreal> distribution(0.5, 0.2);
255 auto rand = std::bind(distribution, generator);
257 QVector<QColor> colours;
258 colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
259 colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
260 colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
262 colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
263 colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
264 colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
266 colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
267 colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
268 colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
270 colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
271 colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
272 colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
274 ColorTheme first(colours[0], colours[1], colours[2]);
275 ColorTheme second(colours[3], colours[4], colours[5]);
276 ColorTheme eighth(colours[6], colours[7], colours[8]);
277 ColorTheme ninth(colours[9], colours[10], colours[11]);
279 {
280 QVariantList firstMonth;
281 while (firstMonth.size() < 17)
282 firstMonth.push_back(QVariant(rand()));
283 while (firstMonth.size() < 31)
284 firstMonth.push_back(QVariant());
285 QVariantList secondMonth;
286 while (secondMonth.size() < 31)
287 secondMonth.push_back(QVariant(rand()));
288 QSharedPointer<UserMetricsData> data(
289 new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
290 ninth, secondMonth, this));
291 m_fakeData.insert("single", data);
292 m_fakeData.insert("has-pin", data);
293 }
295 {
296 QVariantList firstMonth;
297 while (firstMonth.size() < 17)
298 firstMonth.push_back(QVariant(rand()));
299 while (firstMonth.size() < 31)
300 firstMonth.push_back(QVariant());
301 QVariantList secondMonth;
302 while (secondMonth.size() < 31)
303 secondMonth.push_back(QVariant(rand()));
304 QSharedPointer<UserMetricsData> data(
305 new UserMetricsData("<b>33</b> messages today", second,
306 firstMonth, eighth, secondMonth, this));
307 m_fakeData.insert("single", data);
308 m_fakeData.insert("has-pin", data);
309 }
311 {
312 QVariantList firstMonth;
313 while (firstMonth.size() < 17)
314 firstMonth.push_back(QVariant(rand()));
315 firstMonth[8] = QVariant(1.0); // oversized 9th day, to test clipping
316 while (firstMonth.size() < 31)
317 firstMonth.push_back(QVariant());
318 QVariantList secondMonth;
319 while (secondMonth.size() < 31)
320 secondMonth.push_back(QVariant(rand()));
321 QSharedPointer<UserMetricsData> data(
322 new UserMetricsData("<b>19</b> minutes talk time", eighth,
323 firstMonth, second, secondMonth, this));
324 m_fakeData.insert("single", data);
325 m_fakeData.insert("has-pin", data);
326 // Also use same data for some tablet users
327 m_fakeData.insert("has-password", data);
328 m_fakeData.insert("no-password", data);
329 m_fakeData.insert("empty-name", data);
330 }
333void UserMetricsPrivate::loadFakeData()
335 m_newData = *m_dataIndex;
337 bool oldLabelEmpty = m_label.isEmpty();
338 bool newLabelEmpty = m_newData->label().isEmpty();
340 if (oldLabelEmpty && !newLabelEmpty)
341 {
342 q_ptr->dataAboutToAppear();
343 finishSetFakeData();
344 } else if (!oldLabelEmpty && newLabelEmpty)
345 {
346 q_ptr->dataAboutToDisappear();
347 } else if (!oldLabelEmpty && !newLabelEmpty)
348 {
349 q_ptr->dataAboutToChange();
350 }
351 // we emit no signal if the data has stayed empty
354void UserMetricsPrivate::finishSetFakeData()
356 bool oldLabelEmpty = m_label.isEmpty();
357 bool newLabelEmpty = m_newData->label().isEmpty();
359 m_label = m_newData->label();
360 m_firstColor = m_newData->firstColor();
361 m_firstMonth.setVariantList(m_newData->firstMonth());
362 m_secondColor = m_newData->secondColor();
363 m_secondMonth.setVariantList(m_newData->secondMonth());
365 bool currentDayChanged = m_currentDay != m_newData->length();
366 m_currentDay = m_newData->length();
368 q_ptr->labelChanged(m_label);
369 if (currentDayChanged)
370 {
371 q_ptr->currentDayChanged(m_currentDay);
372 }
374 if (oldLabelEmpty && !newLabelEmpty)
375 {
376 q_ptr->dataAppeared();
377 } else if (!oldLabelEmpty && newLabelEmpty)
378 {
379 q_ptr->dataDisappeared();
380 } else if (!oldLabelEmpty && !newLabelEmpty)
381 {
382 q_ptr->dataChanged();
383 }
384 // we emit no signal if the data has stayed empty
387void UserMetricsPrivate::nextFakeData()
389 ++m_dataIndex;
390 if (m_dataIndex == m_fakeData.constEnd() || m_dataIndex.key() != m_username)
391 {
392 m_dataIndex = m_fakeData.constFind(m_username);
393 if (m_dataIndex == m_fakeData.constEnd())
394 {
395 m_dataIndex = m_fakeData.constFind("");
396 }
397 }
399 loadFakeData();
402UserMetrics::UserMetrics(QObject *parent) :
403 QObject(parent), d_ptr(new UserMetricsPrivate(this))
405 d_ptr->generateFakeData();
406 setUsername("");
408 connect(this, &UserMetrics::nextDataSource, this, &UserMetrics::nextDataSourceSlot, Qt::QueuedConnection);
409 connect(this, &UserMetrics::readyForDataChange, this, &UserMetrics::readyForDataChangeSlot, Qt::QueuedConnection);
412UserMetrics::~UserMetrics()
414 delete d_ptr;
417QString UserMetrics::label() const
419 return d_ptr->m_label;
422QString UserMetrics::username() const
424 return d_ptr->m_username;
427void UserMetrics::setUsername(const QString &username)
429 d_ptr->setUsername(username);
432ColorTheme *UserMetrics::firstColor() const
434 return &d_ptr->m_firstColor;
437ColorTheme *UserMetrics::secondColor() const
439 return &d_ptr->m_secondColor;
442QAbstractItemModel *UserMetrics::firstMonth() const
444 return &d_ptr->m_firstMonth;
447QAbstractItemModel *UserMetrics::secondMonth() const
449 return &d_ptr->m_secondMonth;
452int UserMetrics::currentDay() const
454 return d_ptr->m_currentDay;
457void UserMetrics::nextDataSourceSlot()
459 d_ptr->nextFakeData();
462void UserMetrics::readyForDataChangeSlot()
464 d_ptr->finishSetFakeData();
467/**
468 * Factory methods
469 */
471UserMetrics * UserMetrics::getInstance()
473 return new UserMetrics();