on 19bfe13 help sign in
unity8/tests/mocks/libusermetrics/UserMetrics.cpp
499 lines 13 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
39 Q_OBJECT
40public:
41 explicit UserMetricsData(QObject *parent);
43 UserMetricsData(const QString &label,
44 const ColorTheme &firstColor,
45 const QVariantList &firstMonth,
46 const ColorTheme &secondColor,
47 const QVariantList &secondMonth, QObject* parent);
49 ~UserMetricsData();
51protected:
52 UserMetricsDataPrivate * const d_ptr;
54public:
55 const QString & label() const;
56 const ColorTheme & firstColor() const;
57 const QVariantList & firstMonth() const;
58 const ColorTheme & secondColor() const;
59 const QVariantList & secondMonth() const;
60 int length() const;
62private:
63 Q_DECLARE_PRIVATE(UserMetricsData)
64};
66class UserMetricsPrivate: QObject
68 Q_OBJECT
69public:
70 explicit UserMetricsPrivate(UserMetrics *parent);
72 ~UserMetricsPrivate();
74public:
75 typedef QSharedPointer<UserMetricsData> UserMetricsDataPtr;
76 typedef QMultiMap<QString, UserMetricsDataPtr> FakeDataMap;
78 UserMetrics * const q_ptr;
79 QString m_label;
80 ColorTheme m_firstColor;
81 QVariantListModel m_firstMonth;
82 ColorTheme m_secondColor;
83 QVariantListModel m_secondMonth;
84 int m_currentDay;
85 QString m_username;
86 FakeDataMap::const_iterator m_dataIndex;
87 UserMetricsDataPtr m_newData;
88 FakeDataMap m_fakeData;
90 void setUsername(const QString &username);
92protected:
93 void findAndSetUsername(const QString &username);
95 void nextFakeData();
97 void generateFakeData();
99 void loadFakeData();
101 void loadUserMetricsData();
103 void finishSetFakeData();
105private:
106 Q_DECLARE_PUBLIC(UserMetrics)
107};
109class UserMetricsDataPrivate: QObject
111 Q_OBJECT
112public:
113 explicit UserMetricsDataPrivate(UserMetricsData *parent);
115 UserMetricsDataPrivate(const QString &label,
116 const ColorTheme &firstColor,
117 const QVariantList &firstMonth,
118 const ColorTheme &secondColor,
119 const QVariantList &secondMonth, UserMetricsData *parent);
121 ~UserMetricsDataPrivate();
123 UserMetricsData * const q_ptr;
124 QString m_label;
125 ColorTheme m_firstColor;
126 QVariantList m_firstMonth;
127 ColorTheme m_secondColor;
128 QVariantList m_secondMonth;
129 int m_length;
131protected:
132 int calculateLength();
134private:
135 Q_DECLARE_PUBLIC(UserMetricsData)
136};
140UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
141 q_ptr(parent), m_label(""), m_firstColor(this), m_secondColor(this)
143 m_length = calculateLength();
146UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
147 const ColorTheme &firstColor, const QVariantList &firstMonth,
148 const ColorTheme &secondColor,
149 const QVariantList &secondMonth, UserMetricsData *parent) :
150 q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
151 firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
153 m_length = calculateLength();
154 m_firstColor = firstColor;
155 m_secondColor = secondColor;
158UserMetricsDataPrivate::~UserMetricsDataPrivate()
162int UserMetricsDataPrivate::calculateLength()
164 int day(m_firstMonth.size());
165 auto it = m_firstMonth.end(), end = m_firstMonth.begin();
166 while (it != end)
167 {
168 --it;
169 --day;
170 if (!it->isNull())
171 {
172 return day;
173 }
174 }
176 return -1;
179UserMetricsData::UserMetricsData(QObject *parent) :
180 QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
184UserMetricsData::UserMetricsData(const QString &label,
185 const ColorTheme &firstColor, const QVariantList &firstMonth,
186 const ColorTheme &secondColor,
187 const QVariantList &secondMonth, QObject* parent) :
188 QObject(parent), d_ptr(
189 new UserMetricsDataPrivate(label, firstColor, firstMonth,
190 secondColor, secondMonth, this))
194UserMetricsData::~UserMetricsData()
196 delete d_ptr;
199const QString & UserMetricsData::label() const
201 return d_ptr->m_label;
204const ColorTheme & UserMetricsData::firstColor() const
206 return d_ptr->m_firstColor;
209const QVariantList & UserMetricsData::firstMonth() const
211 return d_ptr->m_firstMonth;
214const ColorTheme & UserMetricsData::secondColor() const
216 return d_ptr->m_secondColor;
219const QVariantList & UserMetricsData::secondMonth() const
221 return d_ptr->m_secondMonth;
224int UserMetricsData::length() const
226 return d_ptr->m_length;
229UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
230 q_ptr(parent), m_firstColor(this), m_secondColor(this), m_currentDay(0)
232 m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
235UserMetricsPrivate::~UserMetricsPrivate()
239void UserMetricsPrivate::findAndSetUsername(const QString &username)
241 m_username = username;
243 m_dataIndex = m_fakeData.constFind(m_username);
244 if (m_dataIndex == m_fakeData.constEnd())
245 {
246 m_dataIndex = m_fakeData.constFind("");
247 }
249 m_newData = *m_dataIndex;
252void UserMetricsPrivate::setUsername(const QString &username)
254 if (m_username == username && m_newData) {
255 return;
256 }
258 findAndSetUsername(username);
259 loadFakeData();
261 q_ptr->usernameChanged(m_username);
264void UserMetricsPrivate::generateFakeData()
266 std::default_random_engine generator;
267 std::normal_distribution<qreal> distribution(0.5, 0.2);
268 auto rand = std::bind(distribution, generator);
270 QVector<QColor> colours;
271 colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
272 colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
273 colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
275 colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
276 colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
277 colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
279 colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
280 colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
281 colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
283 colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
284 colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
285 colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
287 ColorTheme first(colours[0], colours[1], colours[2]);
288 ColorTheme second(colours[3], colours[4], colours[5]);
289 ColorTheme eighth(colours[6], colours[7], colours[8]);
290 ColorTheme ninth(colours[9], colours[10], colours[11]);
292 {
293 QVariantList firstMonth;
294 while (firstMonth.size() < 17)
295 firstMonth.push_back(QVariant(rand()));
296 while (firstMonth.size() < 31)
297 firstMonth.push_back(QVariant());
298 QVariantList secondMonth;
299 while (secondMonth.size() < 31)
300 secondMonth.push_back(QVariant(rand()));
301 QSharedPointer<UserMetricsData> data(
302 new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
303 ninth, secondMonth, this));
304 m_fakeData.insert("single", data);
305 m_fakeData.insert("has-pin", data);
306 }
308 {
309 QVariantList firstMonth;
310 while (firstMonth.size() < 17)
311 firstMonth.push_back(QVariant(rand()));
312 while (firstMonth.size() < 31)
313 firstMonth.push_back(QVariant());
314 QVariantList secondMonth;
315 while (secondMonth.size() < 31)
316 secondMonth.push_back(QVariant(rand()));
317 QSharedPointer<UserMetricsData> data(
318 new UserMetricsData("<b>33</b> messages today", second,
319 firstMonth, eighth, secondMonth, this));
320 m_fakeData.insert("single", data);
321 m_fakeData.insert("has-pin", data);
322 }
324 {
325 QVariantList firstMonth;
326 while (firstMonth.size() < 17)
327 firstMonth.push_back(QVariant(rand()));
328 firstMonth[8] = QVariant(1.0); // oversized 9th day, to test clipping
329 while (firstMonth.size() < 31)
330 firstMonth.push_back(QVariant());
331 QVariantList secondMonth;
332 while (secondMonth.size() < 31)
333 secondMonth.push_back(QVariant(rand()));
334 QSharedPointer<UserMetricsData> data(
335 new UserMetricsData("<b>19</b> minutes talk time", eighth,
336 firstMonth, second, secondMonth, this));
337 m_fakeData.insert("single", data);
338 m_fakeData.insert("has-pin", data);
339 // Also use same data for some tablet users
340 m_fakeData.insert("has-password", data);
341 m_fakeData.insert("no-password", data);
342 m_fakeData.insert("empty-name", data);
343 }
346void UserMetricsPrivate::loadFakeData()
349 bool oldLabelEmpty = m_label.isEmpty();
350 bool newLabelEmpty = m_newData->label().isEmpty();
352 if (oldLabelEmpty && !newLabelEmpty)
353 {
354 q_ptr->dataAboutToAppear();
355 finishSetFakeData();
356 } else if (!oldLabelEmpty && newLabelEmpty)
357 {
358 q_ptr->dataAboutToDisappear();
359 } else if (!oldLabelEmpty && !newLabelEmpty)
360 {
361 q_ptr->dataAboutToChange();
362 }
363 // we emit no signal if the data has stayed empty
366void UserMetricsPrivate::loadUserMetricsData()
368 m_label = m_newData->label();
369 m_firstColor = m_newData->firstColor();
370 m_firstMonth.setVariantList(m_newData->firstMonth());
371 m_secondColor = m_newData->secondColor();
372 m_secondMonth.setVariantList(m_newData->secondMonth());
373 m_currentDay = m_newData->length();
376void UserMetricsPrivate::finishSetFakeData()
378 bool oldLabelEmpty = m_label.isEmpty();
379 bool newLabelEmpty = m_newData->label().isEmpty();
380 bool currentDayChanged = m_currentDay != m_newData->length();
382 loadUserMetricsData();
384 q_ptr->labelChanged(m_label);
385 if (currentDayChanged)
386 {
387 q_ptr->currentDayChanged(m_currentDay);
388 }
390 if (oldLabelEmpty && !newLabelEmpty)
391 {
392 q_ptr->dataAppeared();
393 } else if (!oldLabelEmpty && newLabelEmpty)
394 {
395 q_ptr->dataDisappeared();
396 } else if (!oldLabelEmpty && !newLabelEmpty)
397 {
398 q_ptr->dataChanged();
399 }
400 // we emit no signal if the data has stayed empty
403void UserMetricsPrivate::nextFakeData()
405 ++m_dataIndex;
406 if (m_dataIndex == m_fakeData.constEnd() || m_dataIndex.key() != m_username)
407 {
408 m_dataIndex = m_fakeData.constFind(m_username);
409 if (m_dataIndex == m_fakeData.constEnd())
410 {
411 m_dataIndex = m_fakeData.constFind("");
412 }
413 }
415 m_newData = *m_dataIndex;
416 loadFakeData();
419UserMetrics::UserMetrics(QObject *parent) :
420 QObject(parent), d_ptr(new UserMetricsPrivate(this))
422 d_ptr->generateFakeData();
423 setUsername("");
425 connect(this, &UserMetrics::nextDataSource, this, &UserMetrics::nextDataSourceSlot, Qt::QueuedConnection);
426 connect(this, &UserMetrics::readyForDataChange, this, &UserMetrics::readyForDataChangeSlot, Qt::QueuedConnection);
429UserMetrics::~UserMetrics()
431 delete d_ptr;
434QString UserMetrics::label() const
436 return d_ptr->m_label;
439QString UserMetrics::username() const
441 return d_ptr->m_username;
444void UserMetrics::setUsername(const QString &username)
446 d_ptr->setUsername(username);
449ColorTheme *UserMetrics::firstColor() const
451 return &d_ptr->m_firstColor;
454ColorTheme *UserMetrics::secondColor() const
456 return &d_ptr->m_secondColor;
459QAbstractItemModel *UserMetrics::firstMonth() const
461 return &d_ptr->m_firstMonth;
464QAbstractItemModel *UserMetrics::secondMonth() const
466 return &d_ptr->m_secondMonth;
469int UserMetrics::currentDay() const
471 return d_ptr->m_currentDay;
474void UserMetrics::nextDataSourceSlot()
476 d_ptr->nextFakeData();
479void UserMetrics::readyForDataChangeSlot()
481 d_ptr->finishSetFakeData();
484void UserMetrics::reset()
486 d_ptr->findAndSetUsername("");
487 d_ptr->loadUserMetricsData();
490/**
491 * Factory methods
492 */
494UserMetrics * UserMetrics::getInstance()
496 return new UserMetrics();
499#include "UserMetrics.moc"