@@ -0,0 +1,465 @@
2+ * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
16+ * Author: Pete Woods <pete.woods@canonical.com>
19+#include "UserMetrics.h"
20+#include "plugins/Utils/qvariantlistmodel.h"
22+#include <QtCore/QDir>
23+#include <QtCore/QString>
24+#include <QtGui/QIcon>
27+using namespace UserMetricsOutput;
29+namespace UserMetricsOutput
31+class UserMetricsDataPrivate;
32+class UserMetricsPrivate;
34+class Q_DECL_EXPORT UserMetricsData: public QObject
37+ explicit UserMetricsData(QObject *parent);
39+ UserMetricsData(const QString &label,
40+ const ColorTheme &firstColor,
41+ const QVariantList &firstMonth,
42+ const ColorTheme &secondColor,
43+ const QVariantList &secondMonth, QObject* parent);
48+ UserMetricsDataPrivate * const d_ptr;
51+ const QString & label() const;
52+ const ColorTheme & firstColor() const;
53+ const QVariantList & firstMonth() const;
54+ const ColorTheme & secondColor() const;
55+ const QVariantList & secondMonth() const;
59+ Q_DECLARE_PRIVATE(UserMetricsData)
62+class UserMetricsPrivate: QObject
65+ explicit UserMetricsPrivate(UserMetrics *parent);
67+ ~UserMetricsPrivate();
70+ typedef QSharedPointer<UserMetricsData> UserMetricsDataPtr;
71+ typedef QMultiMap<QString, UserMetricsDataPtr> FakeDataMap;
73+ UserMetrics * const q_ptr;
75+ ColorTheme m_firstColor;
76+ QVariantListModel m_firstMonth;
77+ ColorTheme m_secondColor;
78+ QVariantListModel m_secondMonth;
81+ FakeDataMap::const_iterator m_dataIndex;
82+ UserMetricsDataPtr m_newData;
83+ FakeDataMap m_fakeData;
85+ void setUsername(const QString &username);
90+ void generateFakeData();
94+ void finishSetFakeData();
97+ Q_DECLARE_PUBLIC(UserMetrics)
100+class UserMetricsDataPrivate: QObject
103+ explicit UserMetricsDataPrivate(UserMetricsData *parent);
105+ UserMetricsDataPrivate(const QString &label,
106+ const ColorTheme &firstColor,
107+ const QVariantList &firstMonth,
108+ const ColorTheme &secondColor,
109+ const QVariantList &secondMonth, UserMetricsData *parent);
111+ ~UserMetricsDataPrivate();
113+ UserMetricsData * const q_ptr;
115+ ColorTheme m_firstColor;
116+ QVariantList m_firstMonth;
117+ ColorTheme m_secondColor;
118+ QVariantList m_secondMonth;
122+ int calculateLength();
125+ Q_DECLARE_PUBLIC(UserMetricsData)
130+UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
131+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
133+ m_length = calculateLength();
136+UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
137+ const ColorTheme &firstColor, const QVariantList &firstMonth,
138+ const ColorTheme &secondColor,
139+ const QVariantList &secondMonth, UserMetricsData *parent) :
140+ q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
141+ firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
143+ m_length = calculateLength();
144+ m_firstColor = firstColor;
145+ m_secondColor = secondColor;
148+UserMetricsDataPrivate::~UserMetricsDataPrivate()
152+int UserMetricsDataPrivate::calculateLength()
154+ int day(m_firstMonth.size());
155+ auto it = m_firstMonth.end(), end = m_firstMonth.begin();
169+UserMetricsData::UserMetricsData(QObject *parent) :
170+ QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
174+UserMetricsData::UserMetricsData(const QString &label,
175+ const ColorTheme &firstColor, const QVariantList &firstMonth,
176+ const ColorTheme &secondColor,
177+ const QVariantList &secondMonth, QObject* parent) :
178+ QObject(parent), d_ptr(
179+ new UserMetricsDataPrivate(label, firstColor, firstMonth,
180+ secondColor, secondMonth, this))
184+UserMetricsData::~UserMetricsData()
189+const QString & UserMetricsData::label() const
191+ return d_ptr->m_label;
194+const ColorTheme & UserMetricsData::firstColor() const
196+ return d_ptr->m_firstColor;
199+const QVariantList & UserMetricsData::firstMonth() const
201+ return d_ptr->m_firstMonth;
204+const ColorTheme & UserMetricsData::secondColor() const
206+ return d_ptr->m_secondColor;
209+const QVariantList & UserMetricsData::secondMonth() const
211+ return d_ptr->m_secondMonth;
214+int UserMetricsData::length() const
216+ return d_ptr->m_length;
219+UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
220+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
222+ m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
225+UserMetricsPrivate::~UserMetricsPrivate()
229+void UserMetricsPrivate::setUsername(const QString &username)
231+ if (m_username == username) {
235+ m_username = username;
237+ m_dataIndex = m_fakeData.constFind(m_username);
238+ if (m_dataIndex == m_fakeData.end())
240+ m_dataIndex = m_fakeData.constFind("");
245+ q_ptr->usernameChanged(m_username);
248+void UserMetricsPrivate::generateFakeData()
250+ std::default_random_engine generator;
251+ std::normal_distribution<qreal> distribution(0.5, 0.2);
252+ auto rand = std::bind(distribution, generator);
254+ QVector<QColor> colours;
255+ colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
256+ colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
257+ colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
259+ colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
260+ colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
261+ colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
263+ colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
264+ colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
265+ colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
267+ colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
268+ colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
269+ colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
271+ ColorTheme first(colours[0], colours[1], colours[2]);
272+ ColorTheme second(colours[3], colours[4], colours[5]);
273+ ColorTheme eighth(colours[6], colours[7], colours[8]);
274+ ColorTheme ninth(colours[9], colours[10], colours[11]);
277+ QVariantList firstMonth;
278+ while (firstMonth.size() < 17)
279+ firstMonth.push_back(QVariant(rand()));
280+ while (firstMonth.size() < 31)
281+ firstMonth.push_back(QVariant());
282+ QVariantList secondMonth;
283+ while (secondMonth.size() < 31)
284+ secondMonth.push_back(QVariant(rand()));
285+ QSharedPointer<UserMetricsData> data(
286+ new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
287+ ninth, secondMonth, this));
288+ m_fakeData.insert("single", data);
292+ QVariantList firstMonth;
293+ while (firstMonth.size() < 17)
294+ firstMonth.push_back(QVariant(rand()));
295+ while (firstMonth.size() < 31)
296+ firstMonth.push_back(QVariant());
297+ QVariantList secondMonth;
298+ while (secondMonth.size() < 31)
299+ secondMonth.push_back(QVariant(rand()));
300+ QSharedPointer<UserMetricsData> data(
301+ new UserMetricsData("<b>33</b> messages today", second,
302+ firstMonth, eighth, secondMonth, this));
303+ m_fakeData.insert("single", data);
307+ QVariantList firstMonth;
308+ while (firstMonth.size() < 17)
309+ firstMonth.push_back(QVariant(rand()));
310+ while (firstMonth.size() < 31)
311+ firstMonth.push_back(QVariant());
312+ QVariantList secondMonth;
313+ while (secondMonth.size() < 31)
314+ secondMonth.push_back(QVariant(rand()));
315+ QSharedPointer<UserMetricsData> data(
316+ new UserMetricsData("<b>19</b> minutes talk time", eighth,
317+ firstMonth, second, secondMonth, this));
318+ m_fakeData.insert("single", data);
319+ // Also use same data for some tablet users
320+ m_fakeData.insert("has-password", data);
321+ m_fakeData.insert("no-password", data);
322+ m_fakeData.insert("empty-name", data);
326+void UserMetricsPrivate::loadFakeData()
328+ m_newData = *m_dataIndex;
330+ bool oldLabelEmpty = m_label.isEmpty();
331+ bool newLabelEmpty = m_newData->label().isEmpty();
333+ if (oldLabelEmpty && !newLabelEmpty)
335+ q_ptr->dataAboutToAppear();
336+ finishSetFakeData();
337+ } else if (!oldLabelEmpty && newLabelEmpty)
339+ q_ptr->dataAboutToDisappear();
340+ } else if (!oldLabelEmpty && !newLabelEmpty)
342+ q_ptr->dataAboutToChange();
344+ // we emit no signal if the data has stayed empty
347+void UserMetricsPrivate::finishSetFakeData()
349+ bool oldLabelEmpty = m_label.isEmpty();
350+ bool newLabelEmpty = m_newData->label().isEmpty();
352+ m_label = m_newData->label();
353+ m_firstColor = m_newData->firstColor();
354+ m_firstMonth.setVariantList(m_newData->firstMonth());
355+ m_secondColor = m_newData->secondColor();
356+ m_secondMonth.setVariantList(m_newData->secondMonth());
358+ bool currentDayChanged = m_currentDay != m_newData->length();
359+ m_currentDay = m_newData->length();
361+ q_ptr->labelChanged(m_label);
362+ if (currentDayChanged)
364+ q_ptr->currentDayChanged(m_currentDay);
367+ if (oldLabelEmpty && !newLabelEmpty)
369+ q_ptr->dataAppeared();
370+ } else if (!oldLabelEmpty && newLabelEmpty)
372+ q_ptr->dataDisappeared();
373+ } else if (!oldLabelEmpty && !newLabelEmpty)
375+ q_ptr->dataChanged();
377+ // we emit no signal if the data has stayed empty
380+void UserMetricsPrivate::nextFakeData()
383+ if (m_dataIndex == m_fakeData.end() || m_dataIndex.key() != m_username)
385+ m_dataIndex = m_fakeData.constFind(m_username);
391+UserMetrics::UserMetrics(QObject *parent) :
392+ QObject(parent), d_ptr(new UserMetricsPrivate(this))
394+ d_ptr->generateFakeData();
397+ connect(this, SIGNAL(nextDataSource()), this, SLOT(nextDataSourceSlot()),
398+ Qt::QueuedConnection);
399+ connect(this, SIGNAL(readyForDataChange()), this,
400+ SLOT(readyForDataChangeSlot()), Qt::QueuedConnection);
403+UserMetrics::~UserMetrics()
408+QString UserMetrics::label() const
410+ return d_ptr->m_label;
413+QString UserMetrics::username() const
415+ return d_ptr->m_username;
418+void UserMetrics::setUsername(const QString &username)
420+ d_ptr->setUsername(username);
423+ColorTheme *UserMetrics::firstColor() const
425+ return &d_ptr->m_firstColor;
428+ColorTheme *UserMetrics::secondColor() const
430+ return &d_ptr->m_secondColor;
433+QAbstractItemModel *UserMetrics::firstMonth() const
435+ return &d_ptr->m_firstMonth;
438+QAbstractItemModel *UserMetrics::secondMonth() const
440+ return &d_ptr->m_secondMonth;
443+int UserMetrics::currentDay() const
445+ return d_ptr->m_currentDay;
448+void UserMetrics::nextDataSourceSlot()
450+ d_ptr->nextFakeData();
453+void UserMetrics::readyForDataChangeSlot()
455+ d_ptr->finishSetFakeData();
462+UserMetrics * UserMetrics::getInstance()
464+ return new UserMetrics();