on eefa5c8 help sign in
unity8/tests/mocks/libusermetrics/UserMetrics.cpp
494 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
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 findAndSetUsername(const QString &username);
93 void nextFakeData();
95 void generateFakeData();
97 void loadFakeData();
99 void loadUserMetricsData();
101 void finishSetFakeData();
103private:
104 Q_DECLARE_PUBLIC(UserMetrics)
105};
107class UserMetricsDataPrivate: QObject
109public:
110 explicit UserMetricsDataPrivate(UserMetricsData *parent);
112 UserMetricsDataPrivate(const QString &label,
113 const ColorTheme &firstColor,
114 const QVariantList &firstMonth,
115 const ColorTheme &secondColor,
116 const QVariantList &secondMonth, UserMetricsData *parent);
118 ~UserMetricsDataPrivate();
120 UserMetricsData * const q_ptr;
121 QString m_label;
122 ColorTheme m_firstColor;
123 QVariantList m_firstMonth;
124 ColorTheme m_secondColor;
125 QVariantList m_secondMonth;
126 int m_length;
128protected:
129 int calculateLength();
131private:
132 Q_DECLARE_PUBLIC(UserMetricsData)
133};
137UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
138 q_ptr(parent), m_label(""), m_firstColor(this), m_secondColor(this)
140 m_length = calculateLength();
143UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
144 const ColorTheme &firstColor, const QVariantList &firstMonth,
145 const ColorTheme &secondColor,
146 const QVariantList &secondMonth, UserMetricsData *parent) :
147 q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
148 firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
150 m_length = calculateLength();
151 m_firstColor = firstColor;
152 m_secondColor = secondColor;
155UserMetricsDataPrivate::~UserMetricsDataPrivate()
159int UserMetricsDataPrivate::calculateLength()
161 int day(m_firstMonth.size());
162 auto it = m_firstMonth.end(), end = m_firstMonth.begin();
163 while (it != end)
164 {
165 --it;
166 --day;
167 if (!it->isNull())
168 {
169 return day;
170 }
171 }
173 return -1;
176UserMetricsData::UserMetricsData(QObject *parent) :
177 QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
181UserMetricsData::UserMetricsData(const QString &label,
182 const ColorTheme &firstColor, const QVariantList &firstMonth,
183 const ColorTheme &secondColor,
184 const QVariantList &secondMonth, QObject* parent) :
185 QObject(parent), d_ptr(
186 new UserMetricsDataPrivate(label, firstColor, firstMonth,
187 secondColor, secondMonth, this))
191UserMetricsData::~UserMetricsData()
193 delete d_ptr;
196const QString & UserMetricsData::label() const
198 return d_ptr->m_label;
201const ColorTheme & UserMetricsData::firstColor() const
203 return d_ptr->m_firstColor;
206const QVariantList & UserMetricsData::firstMonth() const
208 return d_ptr->m_firstMonth;
211const ColorTheme & UserMetricsData::secondColor() const
213 return d_ptr->m_secondColor;
216const QVariantList & UserMetricsData::secondMonth() const
218 return d_ptr->m_secondMonth;
221int UserMetricsData::length() const
223 return d_ptr->m_length;
226UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
227 q_ptr(parent), m_firstColor(this), m_secondColor(this), m_currentDay(0)
229 m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
232UserMetricsPrivate::~UserMetricsPrivate()
236void UserMetricsPrivate::findAndSetUsername(const QString &username)
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 m_newData = *m_dataIndex;
249void UserMetricsPrivate::setUsername(const QString &username)
251 if (m_username == username && m_newData) {
252 return;
253 }
255 findAndSetUsername(username);
256 loadFakeData();
258 q_ptr->usernameChanged(m_username);
261void UserMetricsPrivate::generateFakeData()
263 std::default_random_engine generator;
264 std::normal_distribution<qreal> distribution(0.5, 0.2);
265 auto rand = std::bind(distribution, generator);
267 QVector<QColor> colours;
268 colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
269 colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
270 colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
272 colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
273 colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
274 colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
276 colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
277 colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
278 colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
280 colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
281 colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
282 colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
284 ColorTheme first(colours[0], colours[1], colours[2]);
285 ColorTheme second(colours[3], colours[4], colours[5]);
286 ColorTheme eighth(colours[6], colours[7], colours[8]);
287 ColorTheme ninth(colours[9], colours[10], colours[11]);
289 {
290 QVariantList firstMonth;
291 while (firstMonth.size() < 17)
292 firstMonth.push_back(QVariant(rand()));
293 while (firstMonth.size() < 31)
294 firstMonth.push_back(QVariant());
295 QVariantList secondMonth;
296 while (secondMonth.size() < 31)
297 secondMonth.push_back(QVariant(rand()));
298 QSharedPointer<UserMetricsData> data(
299 new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
300 ninth, secondMonth, this));
301 m_fakeData.insert("single", data);
302 m_fakeData.insert("has-pin", data);
303 }
305 {
306 QVariantList firstMonth;
307 while (firstMonth.size() < 17)
308 firstMonth.push_back(QVariant(rand()));
309 while (firstMonth.size() < 31)
310 firstMonth.push_back(QVariant());
311 QVariantList secondMonth;
312 while (secondMonth.size() < 31)
313 secondMonth.push_back(QVariant(rand()));
314 QSharedPointer<UserMetricsData> data(
315 new UserMetricsData("<b>33</b> messages today", second,
316 firstMonth, eighth, secondMonth, this));
317 m_fakeData.insert("single", data);
318 m_fakeData.insert("has-pin", data);
319 }
321 {
322 QVariantList firstMonth;
323 while (firstMonth.size() < 17)
324 firstMonth.push_back(QVariant(rand()));
325 firstMonth[8] = QVariant(1.0); // oversized 9th day, to test clipping
326 while (firstMonth.size() < 31)
327 firstMonth.push_back(QVariant());
328 QVariantList secondMonth;
329 while (secondMonth.size() < 31)
330 secondMonth.push_back(QVariant(rand()));
331 QSharedPointer<UserMetricsData> data(
332 new UserMetricsData("<b>19</b> minutes talk time", eighth,
333 firstMonth, second, secondMonth, this));
334 m_fakeData.insert("single", data);
335 m_fakeData.insert("has-pin", data);
336 // Also use same data for some tablet users
337 m_fakeData.insert("has-password", data);
338 m_fakeData.insert("no-password", data);
339 m_fakeData.insert("empty-name", data);
340 }
343void UserMetricsPrivate::loadFakeData()
346 bool oldLabelEmpty = m_label.isEmpty();
347 bool newLabelEmpty = m_newData->label().isEmpty();
349 if (oldLabelEmpty && !newLabelEmpty)
350 {
351 q_ptr->dataAboutToAppear();
352 finishSetFakeData();
353 } else if (!oldLabelEmpty && newLabelEmpty)
354 {
355 q_ptr->dataAboutToDisappear();
356 } else if (!oldLabelEmpty && !newLabelEmpty)
357 {
358 q_ptr->dataAboutToChange();
359 }
360 // we emit no signal if the data has stayed empty
363void UserMetricsPrivate::loadUserMetricsData()
365 m_label = m_newData->label();
366 m_firstColor = m_newData->firstColor();
367 m_firstMonth.setVariantList(m_newData->firstMonth());
368 m_secondColor = m_newData->secondColor();
369 m_secondMonth.setVariantList(m_newData->secondMonth());
370 m_currentDay = m_newData->length();
373void UserMetricsPrivate::finishSetFakeData()
375 bool oldLabelEmpty = m_label.isEmpty();
376 bool newLabelEmpty = m_newData->label().isEmpty();
377 bool currentDayChanged = m_currentDay != m_newData->length();
379 loadUserMetricsData();
381 q_ptr->labelChanged(m_label);
382 if (currentDayChanged)
383 {
384 q_ptr->currentDayChanged(m_currentDay);
385 }
387 if (oldLabelEmpty && !newLabelEmpty)
388 {
389 q_ptr->dataAppeared();
390 } else if (!oldLabelEmpty && newLabelEmpty)
391 {
392 q_ptr->dataDisappeared();
393 } else if (!oldLabelEmpty && !newLabelEmpty)
394 {
395 q_ptr->dataChanged();
396 }
397 // we emit no signal if the data has stayed empty
400void UserMetricsPrivate::nextFakeData()
402 ++m_dataIndex;
403 if (m_dataIndex == m_fakeData.constEnd() || m_dataIndex.key() != m_username)
404 {
405 m_dataIndex = m_fakeData.constFind(m_username);
406 if (m_dataIndex == m_fakeData.constEnd())
407 {
408 m_dataIndex = m_fakeData.constFind("");
409 }
410 }
412 m_newData = *m_dataIndex;
413 loadFakeData();
416UserMetrics::UserMetrics(QObject *parent) :
417 QObject(parent), d_ptr(new UserMetricsPrivate(this))
419 d_ptr->generateFakeData();
420 setUsername("");
422 connect(this, &UserMetrics::nextDataSource, this, &UserMetrics::nextDataSourceSlot, Qt::QueuedConnection);
423 connect(this, &UserMetrics::readyForDataChange, this, &UserMetrics::readyForDataChangeSlot, Qt::QueuedConnection);
426UserMetrics::~UserMetrics()
428 delete d_ptr;
431QString UserMetrics::label() const
433 return d_ptr->m_label;
436QString UserMetrics::username() const
438 return d_ptr->m_username;
441void UserMetrics::setUsername(const QString &username)
443 d_ptr->setUsername(username);
446ColorTheme *UserMetrics::firstColor() const
448 return &d_ptr->m_firstColor;
451ColorTheme *UserMetrics::secondColor() const
453 return &d_ptr->m_secondColor;
456QAbstractItemModel *UserMetrics::firstMonth() const
458 return &d_ptr->m_firstMonth;
461QAbstractItemModel *UserMetrics::secondMonth() const
463 return &d_ptr->m_secondMonth;
466int UserMetrics::currentDay() const
468 return d_ptr->m_currentDay;
471void UserMetrics::nextDataSourceSlot()
473 d_ptr->nextFakeData();
476void UserMetrics::readyForDataChangeSlot()
478 d_ptr->finishSetFakeData();
481void UserMetrics::reset()
483 d_ptr->findAndSetUsername("");
484 d_ptr->loadUserMetricsData();
487/**
488 * Factory methods
489 */
491UserMetrics * UserMetrics::getInstance()
493 return new UserMetrics();