on xenial help sign in
Initial sequential menu activator
commitb644619d8dd70dacdb9a5ca45eb32a5d50b0ead4 authorNick Dedekind <nicholas.dedekind@gmail.com> dateWed 17 Jul 2013, 10:11 (13 years ago) parent9da9b67
13 files changed+820−10
Panel/Indicators.qml+4−1 Panel/MenuContent.qml+12−2 plugins/Unity/Indicators/CMakeLists.txt+1 plugins/Unity/Indicators/flatmenuproxymodel.cpp+13 plugins/Unity/Indicators/indicatorsmodel.cpp−1 plugins/Unity/Indicators/menucontentactivator.cpp+361 plugins/Unity/Indicators/menucontentactivator.h+118 plugins/Unity/Indicators/plugin.cpp+3 plugins/Unity/Indicators/qml/IndicatorPage.qml−6 tests/mocks/Unity/Indicators/CMakeLists.txt+1 tests/mocks/Unity/Indicators/fakeplugin.cpp+4 tests/plugins/Unity/Indicators/CMakeLists.txt+1 tests/plugins/Unity/Indicators/menucontentactivatortest.cpp+302
Panel/Indicators.qml+4−1
@@ -281,7 +281,10 @@ Showable {
281281 indicators.state = "initial"
282282 menuContent.hideAll()
283283 } else {
284− if (state == "initial") indicatorRow.setDefaultItem()
284+ if (state == "initial") {
285+ indicatorRow.setDefaultItem();
286+ menuContent.releaseContent();
287+ }
285288 }
286289 }
287290 }
Panel/MenuContent.qml+12−2
@@ -83,7 +83,7 @@ Rectangle {
8383
8484 delegate: Loader {
8585 clip: true
86− property bool contentActive: content.__contentActive
86+ property bool contentActive: content.__contentActive && menuActivator.content[index].active
8787
8888 onContentActiveChanged: {
8989 if (contentActive && item) {
@@ -196,6 +196,16 @@ Rectangle {
196196 id: contentReleaseTimer
197197
198198 interval: contentReleaseInterval
199− onTriggered: __contentActive = false
199+ onTriggered: {
200+ __contentActive = false;
201+ menuActivator.clear();
202+ }
203+ }
204+
205+ Indicators.MenuContentActivator {
206+ id: menuActivator
207+ running: content.__contentActive
208+ baseIndex: content.currentIndex
209+ count: indicatorsModel.count
200210 }
201211}
plugins/Unity/Indicators/CMakeLists.txt+1
@@ -23,6 +23,7 @@ set(IndicatorsQML_SOURCES
2323 indicators.h
2424 indicatorsmanager.cpp
2525 indicatorsmodel.cpp
26+ menucontentactivator.cpp
2627 plugin.cpp
2728)
2829add_definitions(-DUNITYINDICATORS_LIBRARY)
plugins/Unity/Indicators/flatmenuproxymodel.cpp+13
@@ -77,6 +77,19 @@ void FlatMenuProxyModel::setSourceModel(QAbstractItemModel *source)
7777 SIGNAL(modelReset()),
7878 SLOT(onModelReset()));
7979
80+ //Connection args
81+ connect(source,
82+ SIGNAL(busTypeChanged(DBusEnums::BusType)),
83+ SIGNAL(busTypeChanged()));
84+
85+ connect(source,
86+ SIGNAL(busNameChanged(const QString&)),
87+ SIGNAL(busNameChanged()));
88+
89+ connect(source,
90+ SIGNAL(objectPathChanged(const QString&)),
91+ SIGNAL(objectPathChanged()));
92+
8093 connect(source,
8194 SIGNAL(statusChanged(DBusEnums::ConnectionStatus)),
8295 SIGNAL(statusChanged()));
plugins/Unity/Indicators/indicatorsmodel.cpp−1
@@ -128,7 +128,6 @@ void IndicatorsModel::onIndicatorLoaded(const QString& indicator_name)
128128 QObject::connect(indicator.data(), SIGNAL(indicatorPropertiesChanged(const QVariant&)), this, SLOT(onIndicatorPropertiesChanged()));
129129
130130 beginInsertRows(QModelIndex(), pos, pos);
131−
132131 m_indicators.insert(pos, indicator);
133132 endInsertRows();
134133}
plugins/Unity/Indicators/menucontentactivator.cppnew file+361
@@ -0,0 +1,361 @@
1+/*
2+ * Copyright (C) 2012 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: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+ #include "menucontentactivator.h"
20+ #include <QDebug>
21+
22+// Essentially a QTimer wrapper
23+class ContentTimer : public UnityIndicators::AbstractTimer
24+{
25+ Q_OBJECT
26+public:
27+ ContentTimer(QObject *parent) : UnityIndicators::AbstractTimer(parent) {
28+ m_timer.setSingleShot(false);
29+ connect(&m_timer, &QTimer::timeout,
30+ this, &UnityIndicators::AbstractTimer::timeout);
31+ }
32+ virtual int interval() const { return m_timer.interval(); }
33+ virtual void setInterval(int msecs) { m_timer.setInterval(msecs); }
34+ virtual void start() { m_timer.start(); UnityIndicators::AbstractTimer::start(); }
35+ virtual void stop() { m_timer.stop(); UnityIndicators::AbstractTimer::stop(); }
36+private:
37+ QTimer m_timer;
38+};
39+
40+class MenuContentActivatorPrivate : public QObject
41+{
42+ Q_OBJECT
43+public:
44+ MenuContentActivatorPrivate(MenuContentActivator* parent)
45+ : m_running(false),
46+ m_baseIndex(0),
47+ m_delta(0),
48+ m_count(0),
49+ m_timer(NULL),
50+ q(parent)
51+ {}
52+
53+ ~MenuContentActivatorPrivate()
54+ {
55+ qDeleteAll(m_content);
56+ m_content.clear();
57+ }
58+
59+ int findNextInactiveDelta(bool* finished = NULL);
60+
61+ static int content_count(QQmlListProperty<MenuContentState> *prop);
62+ static MenuContentState* content_at(QQmlListProperty<MenuContentState> *prop, int index);
63+
64+ bool m_running;
65+ int m_baseIndex;
66+ int m_delta;
67+ int m_count;
68+ UnityIndicators::AbstractTimer* m_timer;
69+ QMap<int, MenuContentState*> m_content;
70+ MenuContentActivator* q;
71+};
72+
73+MenuContentActivator::MenuContentActivator(QObject* parent)
74+ : QObject(parent),
75+ d(new MenuContentActivatorPrivate(this))
76+{
77+ qRegisterMetaType<QQmlListProperty<MenuContentState> > ("QQmlListProperty<MenuContentState>");
78+
79+ setContentTimer(new ContentTimer(this));
80+ d->m_timer->setInterval(75);
81+}
82+
83+MenuContentActivator::~MenuContentActivator()
84+{
85+ delete d;
86+}
87+
88+void MenuContentActivator::restart()
89+{
90+ // when we start, make sure we have the base index in the list.
91+ setMenuContentState(d->m_baseIndex, true);
92+ setDelta(0);
93+
94+ // check if we've finished before starting the timer.
95+ bool finished = false;
96+ d->findNextInactiveDelta(&finished);
97+ if (!finished) {
98+ d->m_timer->start();
99+ }
100+ else {
101+ // stop the timer.
102+ d->m_timer->stop();
103+ }
104+
105+ if (!d->m_running) {
106+ d->m_running = true;
107+ Q_EMIT runningChanged(true);
108+ }
109+}
110+
111+void MenuContentActivator::stop()
112+{
113+ d->m_timer->stop();
114+ if (!d->m_running) {
115+ d->m_running = false;
116+ Q_EMIT runningChanged(false);
117+ }
118+}
119+
120+void MenuContentActivator::clear()
121+{
122+ qDeleteAll(d->m_content);
123+ d->m_content.clear();
124+
125+ setDelta(0);
126+ d->m_timer->stop();
127+
128+ Q_EMIT contentChanged();
129+}
130+
131+bool MenuContentActivator::isMenuContentActive(int index) const
132+{
133+ if (d->m_content.contains(index))
134+ return d->m_content[index]->active();
135+ return false;
136+}
137+
138+void MenuContentActivator::setRunning(bool running)
139+{
140+ if (running) {
141+ restart();
142+ }
143+ else {
144+ stop();
145+ }
146+}
147+
148+bool MenuContentActivator::running() const
149+{
150+ return d->m_running;
151+}
152+
153+void MenuContentActivator::setBaseIndex(int index)
154+{
155+ if (d->m_baseIndex != index) {
156+ d->m_baseIndex = index;
157+
158+ // if we've updated the base index, we need to
159+ bool finished = false;
160+ d->findNextInactiveDelta(&finished);
161+ if (running()) {
162+ if (!isMenuContentActive(d->m_baseIndex)) {
163+ setMenuContentState(d->m_baseIndex, true);
164+ }
165+ if (finished) {
166+ // stop the timer.
167+ d->m_timer->stop();
168+ }
169+ }
170+ setDelta(0);
171+ Q_EMIT baseIndexChanged(index);
172+ }
173+}
174+
175+int MenuContentActivator::baseIndex() const
176+{
177+ return d->m_baseIndex;
178+}
179+
180+void MenuContentActivator::setCount(int count)
181+{
182+ if (d->m_count != count) {
183+ d->m_count = count;
184+ Q_EMIT countChanged(count);
185+
186+ if (running()) {
187+ restart();
188+ }
189+ }
190+}
191+
192+int MenuContentActivator::count() const
193+{
194+ return d->m_count;
195+}
196+
197+void MenuContentActivator::setDelta(int delta)
198+{
199+ if (d->m_delta != delta) {
200+ d->m_delta = delta;
201+ Q_EMIT deltaChanged(d->m_delta);
202+ }
203+}
204+
205+int MenuContentActivator::delta() const
206+{
207+ return d->m_delta;
208+}
209+
210+QQmlListProperty<MenuContentState> MenuContentActivator::content()
211+{
212+ return QQmlListProperty<MenuContentState>(this,
213+ 0,
214+ MenuContentActivatorPrivate::content_count,
215+ MenuContentActivatorPrivate::content_at);
216+}
217+
218+void MenuContentActivator::onTimeout()
219+{
220+ bool finished = false;
221+ int tempDelta = d->findNextInactiveDelta(&finished);
222+ if (!finished) {
223+ setMenuContentState(d->m_baseIndex + tempDelta, true);
224+ setDelta(tempDelta);
225+ }
226+
227+ if (finished) {
228+ // just stop the timer.
229+ d->m_timer->stop();
230+ }
231+}
232+
233+void MenuContentActivator::setContentTimer(UnityIndicators::AbstractTimer *timer)
234+{
235+ int interval = 0;
236+ bool timerWasRunning = false;
237+
238+ // can be null when called from the constructor
239+ if (d->m_timer) {
240+ interval = d->m_timer->interval();
241+ timerWasRunning = d->m_timer->isRunning();
242+ if (d->m_timer->parent() == this) {
243+ delete d->m_timer;
244+ }
245+ }
246+
247+ d->m_timer = timer;
248+ timer->setInterval(interval);
249+ connect(timer, &UnityIndicators::AbstractTimer::timeout,
250+ this, &MenuContentActivator::onTimeout);
251+ if (timerWasRunning) {
252+ d->m_timer->start();
253+ }
254+}
255+
256+void MenuContentActivator::setMenuContentState(int index, bool active)
257+{
258+ if (d->m_content.contains(index)) {
259+ d->m_content[index]->setActive(active);
260+ }
261+ else {
262+ d->m_content[index] = new MenuContentState(active);
263+ Q_EMIT contentChanged();
264+ }
265+}
266+
267+int MenuContentActivatorPrivate::findNextInactiveDelta(bool* finished)
268+{
269+ if (m_count == 0 || m_baseIndex >= m_count) {
270+ if (finished) *finished = true;
271+ return 0;
272+ }
273+
274+ int tmpDelta = m_delta;
275+ bool topReached = false, bottomReached = false;
276+ while(true) {
277+
278+ // prechecks for bottom and top limits.
279+ if (tmpDelta > 0 && bottomReached) tmpDelta = -tmpDelta;
280+ if (tmpDelta < 0 && topReached) tmpDelta = (-tmpDelta) + 1;
281+
282+ if (tmpDelta > 0) {
283+ // negative of baseIndex
284+ tmpDelta = -tmpDelta;
285+ // reached the bottom?
286+ if (m_baseIndex + tmpDelta < 0) {
287+ bottomReached = true;
288+ // if we've reached the top as well, then we know we're done.
289+ if (topReached) {
290+ if (finished) *finished = true;
291+ return 0;
292+ }
293+ continue;
294+ }
295+ }
296+ else {
297+ // positive of baseIndex
298+ tmpDelta = (-tmpDelta) + 1;
299+ // reached the top?
300+ if (m_baseIndex + tmpDelta >= m_count) {
301+ topReached = true;
302+ // if we've reached the bottom as well, then we know we're done.
303+ if (bottomReached) {
304+ if (finished) *finished = true;
305+ return 0;
306+ }
307+ continue;
308+ }
309+ }
310+
311+ if (q->isMenuContentActive(m_baseIndex + tmpDelta)) {
312+ continue;
313+ }
314+ break;
315+ }
316+ if (finished) *finished = false;
317+ return tmpDelta;
318+}
319+
320+int MenuContentActivatorPrivate::content_count(QQmlListProperty<MenuContentState> *prop)
321+{
322+ MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
323+ // we'll create MenuContentState on demand.
324+ return p->count();
325+}
326+
327+MenuContentState* MenuContentActivatorPrivate::content_at(QQmlListProperty<MenuContentState> *prop, int index)
328+{
329+ MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
330+ MenuContentActivatorPrivate *d = p->d;
331+
332+ if (!d->m_content.contains(index)) {
333+ MenuContentState* content = new MenuContentState(false);
334+ d->m_content[index] = content;
335+ Q_EMIT p->contentChanged();
336+ return content;
337+ }
338+
339+ return d->m_content[index];
340+}
341+
342+MenuContentState::MenuContentState(bool active)
343+ : m_active(active)
344+{
345+}
346+
347+bool MenuContentState::active() const
348+{
349+ return m_active;
350+}
351+
352+void MenuContentState::setActive(bool active)
353+{
354+ if (m_active != active) {
355+ m_active = active;
356+ Q_EMIT activeChanged();
357+ }
358+}
359+
360+// Because we are defining a new QObject-based class (ContentTimer) here.
361+#include "menucontentactivator.moc"
plugins/Unity/Indicators/menucontentactivator.hnew file+118
@@ -0,0 +1,118 @@
1+/*
2+ * Copyright (C) 2012 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: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MENUCONTENTACTIVATOR_H
20+#define MENUCONTENTACTIVATOR_H
21+
22+#include "unityindicatorsglobal.h"
23+
24+#include <QObject>
25+#include <QTimer>
26+#include <QQmlListProperty>
27+
28+
29+namespace UnityIndicators {
30+/* Defines an interface for a Timer. */
31+class UNITYINDICATORS_EXPORT AbstractTimer : public QObject {
32+ Q_OBJECT
33+public:
34+ AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
35+ virtual int interval() const = 0;
36+ virtual void setInterval(int msecs) = 0;
37+ virtual void start() { m_isRunning = true; };
38+ virtual void stop() { m_isRunning = false; }
39+ bool isRunning() const { return m_isRunning; }
40+Q_SIGNALS:
41+ void timeout();
42+private:
43+ bool m_isRunning;
44+};
45+}
46+
47+/* Defines a object to express the active state of a menu. */
48+class UNITYINDICATORS_EXPORT MenuContentState : public QObject
49+{
50+ Q_OBJECT
51+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
52+public:
53+ MenuContentState(bool active);
54+
55+ bool active() const;
56+ void setActive(bool active);
57+
58+Q_SIGNALS:
59+ void activeChanged();
60+private:
61+ bool m_active;
62+};
63+
64+class MenuContentActivatorPrivate;
65+
66+class UNITYINDICATORS_EXPORT MenuContentActivator : public QObject
67+{
68+ Q_OBJECT
69+ Q_PROPERTY(int baseIndex READ baseIndex WRITE setBaseIndex NOTIFY baseIndexChanged)
70+ Q_PROPERTY(int delta READ delta NOTIFY deltaChanged)
71+ Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
72+ Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
73+ Q_PROPERTY(QQmlListProperty<MenuContentState> content READ content NOTIFY contentChanged DESIGNABLE false)
74+public:
75+ MenuContentActivator(QObject* parent = NULL);
76+ ~MenuContentActivator();
77+
78+ Q_INVOKABLE void restart();
79+ Q_INVOKABLE void stop();
80+ Q_INVOKABLE void clear();
81+ Q_INVOKABLE bool isMenuContentActive(int index) const;
82+
83+ void setRunning(bool running);
84+ bool running() const;
85+
86+ void setBaseIndex(int index);
87+ int baseIndex() const;
88+
89+ void setCount(int index);
90+ int count() const;
91+
92+ void setDelta(int index);
93+ int delta() const;
94+
95+ QQmlListProperty<MenuContentState> content();
96+
97+ // Replaces the existing Timer with the given one.
98+ //
99+ // Useful for providing a fake timer when testing.
100+ void setContentTimer(UnityIndicators::AbstractTimer *timer);
101+ void setMenuContentState(int index, bool active);
102+
103+Q_SIGNALS:
104+ void baseIndexChanged(int baseIndex);
105+ void deltaChanged(int delta);
106+ void runningChanged(bool running);
107+ void countChanged(int count);
108+ void contentChanged();
109+
110+private Q_SLOTS:
111+ void onTimeout();
112+
113+private:
114+ MenuContentActivatorPrivate* d;
115+ friend class MenuContentActivatorPrivate;
116+};
117+
118+#endif // MENUCONTENTACTIVATOR_H
plugins/Unity/Indicators/plugin.cpp+3
@@ -27,6 +27,7 @@
2727#include "indicatorsmanager.h"
2828#include "indicatorsmodel.h"
2929#include "indicators.h"
30+#include "menucontentactivator.h"
3031
3132void IndicatorsPlugin::registerTypes(const char *uri)
3233{
@@ -35,7 +36,9 @@ void IndicatorsPlugin::registerTypes(const char *uri)
3536 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
3637 qmlRegisterType<FlatMenuProxyModel>(uri, 0, 1, "FlatMenuProxyModel");
3738 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
39+ qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
3840
41+ qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
3942 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
4043 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
4144 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
plugins/Unity/Indicators/qml/IndicatorPage.qml−6
@@ -188,10 +188,4 @@ IndicatorBase {
188188 mainMenu.currentIndex = -1;
189189 mainMenu.positionViewAtBeginning();
190190 }
191−
192− Component.onCompleted: {
193− if ((busType != 0) && (busName != "") && (deviceMenuObjectPath != "")) {
194− start();
195− }
196− }
197191}
tests/mocks/Unity/Indicators/CMakeLists.txt+1
@@ -12,6 +12,7 @@ include_directories(
1212set(IndicatorsFakeQml_SOURCES
1313 fakeplugin.cpp
1414 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/indicators.h
15+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/menucontentactivator.cpp
1516)
1617
1718set(IndicatorsFakeQml_RESOURCES
tests/mocks/Unity/Indicators/fakeplugin.cpp+4
@@ -24,11 +24,15 @@
2424
2525// local
2626#include "indicators.h"
27+#include "menucontentactivator.h"
2728
2829void IndicatorsFakePlugin::registerTypes(const char * uri)
2930{
3031 Q_INIT_RESOURCE(indicators_fake);
3132
33+ qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
34+
35+ qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
3236 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
3337 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
3438 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
tests/plugins/Unity/Indicators/CMakeLists.txt+1
@@ -24,4 +24,5 @@ endmacro(run_tests)
2424run_tests(
2525 indicatorsmanagertest
2626 indicatorsmodeltest
27+ menucontentactivatortest
2728 )
tests/plugins/Unity/Indicators/menucontentactivatortest.cppnew file+302
@@ -0,0 +1,302 @@
1+/*
2+ * Copyright 2012 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Renato Araujo Oliveira Filho <renato@canonical.com>
18+ */
19+
20+#include "menucontentactivator.h"
21+#include "paths.h"
22+
23+#include <QtTest>
24+#include <QDebug>
25+
26+class FakeTimer : public UnityIndicators::AbstractTimer
27+{
28+ Q_OBJECT
29+public:
30+ FakeTimer(QObject *parent = 0)
31+ : UnityIndicators::AbstractTimer(parent)
32+ {}
33+
34+ virtual int interval() const { return m_duration; }
35+ virtual void setInterval(int msecs) { m_duration = msecs; }
36+
37+ void emitTimeout() {
38+ if (isRunning()) {
39+ Q_EMIT timeout();
40+ }
41+ }
42+private:
43+ int m_duration;
44+};
45+
46+
47+class MenuConentActivatorTest : public QObject
48+{
49+ Q_OBJECT
50+private Q_SLOTS:
51+ void init() // called right before each and every test function is executed
52+ {
53+ m_fakeTimeSource = new FakeTimer(this);
54+ m_deltas.clear();
55+ }
56+ void cleanup() // called right after each and every test function is executed
57+ {
58+ delete m_fakeTimeSource;
59+ m_fakeTimeSource = 0;
60+ }
61+
62+ /*
63+ * Test if a new plugin init function is called only once
64+ */
65+ void testContentActiveChange()
66+ {
67+ // Tests the ordering of activation
68+
69+ MenuContentActivator activator;
70+ activator.setContentTimer(m_fakeTimeSource);
71+ activator.setCount(10);
72+ activator.setBaseIndex(5);
73+ activator.restart();
74+
75+ QCOMPARE(activator.isMenuContentActive(4), false);
76+ QCOMPARE(activator.isMenuContentActive(5), true); // always active at base index.
77+ QCOMPARE(activator.isMenuContentActive(6), false);
78+
79+ m_fakeTimeSource->emitTimeout();
80+ QCOMPARE(activator.isMenuContentActive(4), false);
81+ QCOMPARE(activator.isMenuContentActive(5), true);
82+ QCOMPARE(activator.isMenuContentActive(6), true);
83+ QCOMPARE(activator.isMenuContentActive(7), false);
84+
85+ m_fakeTimeSource->emitTimeout();
86+ QCOMPARE(activator.isMenuContentActive(3), false);
87+ QCOMPARE(activator.isMenuContentActive(4), true);
88+ QCOMPARE(activator.isMenuContentActive(5), true);
89+ QCOMPARE(activator.isMenuContentActive(6), true);
90+ QCOMPARE(activator.isMenuContentActive(7), false);
91+
92+ m_fakeTimeSource->emitTimeout();
93+ QCOMPARE(activator.isMenuContentActive(3), false);
94+ QCOMPARE(activator.isMenuContentActive(4), true);
95+ QCOMPARE(activator.isMenuContentActive(5), true);
96+ QCOMPARE(activator.isMenuContentActive(6), true);
97+ QCOMPARE(activator.isMenuContentActive(7), true);
98+ QCOMPARE(activator.isMenuContentActive(8), false);
99+
100+ m_fakeTimeSource->emitTimeout();
101+ QCOMPARE(activator.isMenuContentActive(2), false);
102+ QCOMPARE(activator.isMenuContentActive(3), true);
103+ QCOMPARE(activator.isMenuContentActive(4), true);
104+ QCOMPARE(activator.isMenuContentActive(5), true);
105+ QCOMPARE(activator.isMenuContentActive(6), true);
106+ QCOMPARE(activator.isMenuContentActive(7), true);
107+ QCOMPARE(activator.isMenuContentActive(8), false);
108+
109+ m_fakeTimeSource->emitTimeout();
110+ QCOMPARE(activator.isMenuContentActive(2), false);
111+ QCOMPARE(activator.isMenuContentActive(3), true);
112+ QCOMPARE(activator.isMenuContentActive(4), true);
113+ QCOMPARE(activator.isMenuContentActive(5), true);
114+ QCOMPARE(activator.isMenuContentActive(6), true);
115+ QCOMPARE(activator.isMenuContentActive(7), true);
116+ QCOMPARE(activator.isMenuContentActive(8), true);
117+ QCOMPARE(activator.isMenuContentActive(9), false);
118+
119+ m_fakeTimeSource->emitTimeout();
120+ QCOMPARE(activator.isMenuContentActive(1), false);
121+ QCOMPARE(activator.isMenuContentActive(2), true);
122+ QCOMPARE(activator.isMenuContentActive(3), true);
123+ QCOMPARE(activator.isMenuContentActive(4), true);
124+ QCOMPARE(activator.isMenuContentActive(5), true);
125+ QCOMPARE(activator.isMenuContentActive(6), true);
126+ QCOMPARE(activator.isMenuContentActive(7), true);
127+ QCOMPARE(activator.isMenuContentActive(8), true);
128+ QCOMPARE(activator.isMenuContentActive(9), false);
129+
130+ m_fakeTimeSource->emitTimeout();
131+ QCOMPARE(activator.isMenuContentActive(1), false);
132+ QCOMPARE(activator.isMenuContentActive(2), true);
133+ QCOMPARE(activator.isMenuContentActive(3), true);
134+ QCOMPARE(activator.isMenuContentActive(4), true);
135+ QCOMPARE(activator.isMenuContentActive(5), true);
136+ QCOMPARE(activator.isMenuContentActive(6), true);
137+ QCOMPARE(activator.isMenuContentActive(7), true);
138+ QCOMPARE(activator.isMenuContentActive(8), true);
139+ QCOMPARE(activator.isMenuContentActive(9), true);
140+ QCOMPARE(activator.isMenuContentActive(10), false);
141+
142+ m_fakeTimeSource->emitTimeout();
143+ QCOMPARE(activator.isMenuContentActive(0), false);
144+ QCOMPARE(activator.isMenuContentActive(1), true);
145+ QCOMPARE(activator.isMenuContentActive(2), true);
146+ QCOMPARE(activator.isMenuContentActive(3), true);
147+ QCOMPARE(activator.isMenuContentActive(4), true);
148+ QCOMPARE(activator.isMenuContentActive(5), true);
149+ QCOMPARE(activator.isMenuContentActive(6), true);
150+ QCOMPARE(activator.isMenuContentActive(7), true);
151+ QCOMPARE(activator.isMenuContentActive(8), true);
152+ QCOMPARE(activator.isMenuContentActive(9), true);
153+ QCOMPARE(activator.isMenuContentActive(10), false);
154+
155+ m_fakeTimeSource->emitTimeout();
156+ QCOMPARE(activator.isMenuContentActive(-1), false);
157+ QCOMPARE(activator.isMenuContentActive(0), true);
158+ QCOMPARE(activator.isMenuContentActive(1), true);
159+ QCOMPARE(activator.isMenuContentActive(2), true);
160+ QCOMPARE(activator.isMenuContentActive(3), true);
161+ QCOMPARE(activator.isMenuContentActive(4), true);
162+ QCOMPARE(activator.isMenuContentActive(5), true);
163+ QCOMPARE(activator.isMenuContentActive(6), true);
164+ QCOMPARE(activator.isMenuContentActive(7), true);
165+ QCOMPARE(activator.isMenuContentActive(8), true);
166+ QCOMPARE(activator.isMenuContentActive(9), true);
167+ QCOMPARE(activator.isMenuContentActive(10), false);
168+ }
169+
170+ void testDelta()
171+ {
172+ // Tests the delta calculation for each timeout.
173+
174+ MenuContentActivator activator;
175+ activator.setContentTimer(m_fakeTimeSource);
176+ activator.setCount(9);
177+ activator.setBaseIndex(3);
178+
179+ connect(&activator, &MenuContentActivator::deltaChanged,
180+ this, &MenuConentActivatorTest::onDeltaChange);
181+ activator.restart();
182+
183+ QCOMPARE(m_deltas, QList<int>()); // empty
184+ QCOMPARE(getIndexList(&activator), QList<int>()); // empty
185+
186+ m_fakeTimeSource->emitTimeout();
187+ QCOMPARE(m_deltas, QList<int>() << 1);
188+ QCOMPARE(getIndexList(&activator), QList<int>() << 4);
189+
190+ m_fakeTimeSource->emitTimeout();
191+ QCOMPARE(m_deltas, QList<int>() << 1 << -1);
192+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2);
193+
194+ m_fakeTimeSource->emitTimeout();
195+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2);
196+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5);
197+
198+ m_fakeTimeSource->emitTimeout();
199+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2);
200+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1);
201+
202+ m_fakeTimeSource->emitTimeout();
203+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3);
204+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6);
205+
206+ m_fakeTimeSource->emitTimeout();
207+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3);
208+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0);
209+
210+ m_fakeTimeSource->emitTimeout();
211+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4);
212+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7);
213+
214+ m_fakeTimeSource->emitTimeout();
215+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4 << 5);
216+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7 << 8);
217+
218+ m_fakeTimeSource->emitTimeout();
219+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4 << 5);
220+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7 << 8);
221+ }
222+
223+ void testBaseIndexChange()
224+ {
225+ // Tests that changing the base index re-prioritizes the activation
226+ // around the base index.
227+ MenuContentActivator activator;
228+ activator.setContentTimer(m_fakeTimeSource);
229+ activator.setCount(12);
230+ activator.setBaseIndex(5);
231+ activator.restart();
232+
233+ m_fakeTimeSource->emitTimeout();
234+ m_fakeTimeSource->emitTimeout();
235+ QCOMPARE(activator.isMenuContentActive(3), false);
236+ QCOMPARE(activator.isMenuContentActive(4), true);
237+ QCOMPARE(activator.isMenuContentActive(5), true); // always active at base index.
238+ QCOMPARE(activator.isMenuContentActive(6), true);
239+ QCOMPARE(activator.isMenuContentActive(7), false);
240+
241+ activator.setBaseIndex(8);
242+ QCOMPARE(activator.isMenuContentActive(3), false);
243+ QCOMPARE(activator.isMenuContentActive(4), true);
244+ QCOMPARE(activator.isMenuContentActive(5), true);
245+ QCOMPARE(activator.isMenuContentActive(6), true);
246+ QCOMPARE(activator.isMenuContentActive(7), false);
247+ QCOMPARE(activator.isMenuContentActive(8), true);
248+ QCOMPARE(activator.isMenuContentActive(9), false);
249+
250+ m_fakeTimeSource->emitTimeout();
251+ QCOMPARE(activator.isMenuContentActive(3), false);
252+ QCOMPARE(activator.isMenuContentActive(4), true);
253+ QCOMPARE(activator.isMenuContentActive(5), true);
254+ QCOMPARE(activator.isMenuContentActive(6), true);
255+ QCOMPARE(activator.isMenuContentActive(7), false);
256+ QCOMPARE(activator.isMenuContentActive(8), true);
257+ QCOMPARE(activator.isMenuContentActive(9), true);
258+ QCOMPARE(activator.isMenuContentActive(10), false);
259+
260+ m_fakeTimeSource->emitTimeout();
261+ QCOMPARE(activator.isMenuContentActive(3), false);
262+ QCOMPARE(activator.isMenuContentActive(4), true);
263+ QCOMPARE(activator.isMenuContentActive(5), true);
264+ QCOMPARE(activator.isMenuContentActive(6), true);
265+ QCOMPARE(activator.isMenuContentActive(7), true);
266+ QCOMPARE(activator.isMenuContentActive(8), true);
267+ QCOMPARE(activator.isMenuContentActive(9), true);
268+ QCOMPARE(activator.isMenuContentActive(10), false);
269+
270+ m_fakeTimeSource->emitTimeout();
271+ QCOMPARE(activator.isMenuContentActive(3), false);
272+ QCOMPARE(activator.isMenuContentActive(4), true);
273+ QCOMPARE(activator.isMenuContentActive(5), true);
274+ QCOMPARE(activator.isMenuContentActive(6), true);
275+ QCOMPARE(activator.isMenuContentActive(7), true);
276+ QCOMPARE(activator.isMenuContentActive(8), true);
277+ QCOMPARE(activator.isMenuContentActive(9), true);
278+ QCOMPARE(activator.isMenuContentActive(10), true);
279+ QCOMPARE(activator.isMenuContentActive(11), false);
280+ }
281+
282+ void onDeltaChange(int delta)
283+ {
284+ m_deltas << delta;
285+ }
286+
287+private:
288+ QList<int> getIndexList(MenuContentActivator* activator)
289+ {
290+ QList<int> list;
291+ Q_FOREACH(int delta, m_deltas) {
292+ list << (activator->baseIndex() + delta);
293+ }
294+ return list;
295+ }
296+
297+ FakeTimer* m_fakeTimeSource;
298+ QList<int> m_deltas;
299+};
300+
301+QTEST_MAIN(MenuConentActivatorTest)
302+#include "menucontentactivatortest.moc"