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: Nick Dedekind <nick.dedekind@canonical.com>
19
#include "menucontentactivator.h"
21
// Essentially a QTimer wrapper
22
class ContentTimer : public UnityIndicators::AbstractTimer
26
ContentTimer(QObject *parent) : UnityIndicators::AbstractTimer(parent) {
27
m_timer.setSingleShot(false);
28
connect(&m_timer, &QTimer::timeout,
29
this, &UnityIndicators::AbstractTimer::timeout);
31
virtual int interval() const { return m_timer.interval(); }
32
virtual void setInterval(int msecs) { m_timer.setInterval(msecs); }
33
virtual void start() { m_timer.start(); UnityIndicators::AbstractTimer::start(); }
34
virtual void stop() { m_timer.stop(); UnityIndicators::AbstractTimer::stop(); }
39
class MenuContentActivatorPrivate : public QObject
43
MenuContentActivatorPrivate(MenuContentActivator* parent)
52
~MenuContentActivatorPrivate()
54
qDeleteAll(m_content);
58
int findNextInactiveDelta(bool* finished = NULL);
60
static int content_count(QQmlListProperty<MenuContentState> *prop);
61
static MenuContentState* content_at(QQmlListProperty<MenuContentState> *prop, int index);
67
UnityIndicators::AbstractTimer* m_timer;
68
QMap<int, MenuContentState*> m_content;
69
MenuContentActivator* q;
72
MenuContentActivator::MenuContentActivator(QObject* parent)
74
d(new MenuContentActivatorPrivate(this))
76
qRegisterMetaType<QQmlListProperty<MenuContentState> > ("QQmlListProperty<MenuContentState>");
78
setContentTimer(new ContentTimer(this));
79
d->m_timer->setInterval(75);
82
MenuContentActivator::~MenuContentActivator()
87
void MenuContentActivator::restart()
89
// when we start, make sure we have the base index in the list.
90
setMenuContentState(d->m_baseIndex, true);
93
// check if we've finished before starting the timer.
94
bool finished = false;
95
d->findNextInactiveDelta(&finished);
104
Q_EMIT runningChanged(true);
108
void MenuContentActivator::stop()
112
d->m_running = false;
113
Q_EMIT runningChanged(false);
117
void MenuContentActivator::clear()
119
qDeleteAll(d->m_content);
120
d->m_content.clear();
125
Q_EMIT contentChanged();
128
bool MenuContentActivator::isMenuContentActive(int index) const
130
if (d->m_content.contains(index))
131
return d->m_content[index]->isActive();
135
void MenuContentActivator::setRunning(bool running)
144
bool MenuContentActivator::isRunning() const
149
void MenuContentActivator::setBaseIndex(int index)
151
if (d->m_baseIndex != index) {
152
d->m_baseIndex = index;
158
Q_EMIT baseIndexChanged(index);
162
int MenuContentActivator::baseIndex() const
164
return d->m_baseIndex;
167
void MenuContentActivator::setCount(int count)
169
if (d->m_count != count) {
171
Q_EMIT countChanged(count);
179
int MenuContentActivator::count() const
184
void MenuContentActivator::setDelta(int delta)
186
if (d->m_delta != delta) {
188
Q_EMIT deltaChanged(d->m_delta);
192
int MenuContentActivator::delta() const
197
QQmlListProperty<MenuContentState> MenuContentActivator::content()
199
return QQmlListProperty<MenuContentState>(this,
201
MenuContentActivatorPrivate::content_count,
202
MenuContentActivatorPrivate::content_at);
205
void MenuContentActivator::onTimeout()
207
bool finished = false;
208
int tempDelta = d->findNextInactiveDelta(&finished);
210
setMenuContentState(d->m_baseIndex + tempDelta, true);
219
void MenuContentActivator::setContentTimer(UnityIndicators::AbstractTimer *timer)
222
bool timerWasRunning = false;
224
// can be null when called from the constructor
226
interval = d->m_timer->interval();
227
timerWasRunning = d->m_timer->isRunning();
228
if (d->m_timer->parent() == this) {
234
timer->setInterval(interval);
235
connect(timer, &UnityIndicators::AbstractTimer::timeout,
236
this, &MenuContentActivator::onTimeout);
237
if (timerWasRunning) {
242
void MenuContentActivator::setMenuContentState(int index, bool active)
244
if (d->m_content.contains(index)) {
245
d->m_content[index]->setActive(active);
247
d->m_content[index] = new MenuContentState(active);
248
Q_EMIT contentChanged();
252
int MenuContentActivatorPrivate::findNextInactiveDelta(bool* finished)
254
if (m_count == 0 || m_baseIndex >= m_count) {
255
if (finished) *finished = true;
259
int tmpDelta = m_delta;
260
bool topReached = false, bottomReached = false;
263
// prechecks for bottom and top limits.
264
if (tmpDelta > 0 && bottomReached) tmpDelta = -tmpDelta;
265
if (tmpDelta < 0 && topReached) tmpDelta = (-tmpDelta) + 1;
268
// negative of baseIndex
269
tmpDelta = -tmpDelta;
270
// reached the bottom?
271
if (m_baseIndex + tmpDelta < 0) {
272
bottomReached = true;
273
// if we've reached the top as well, then we know we're done.
275
if (finished) *finished = true;
281
// positive of baseIndex
282
tmpDelta = (-tmpDelta) + 1;
284
if (m_baseIndex + tmpDelta >= m_count) {
286
// if we've reached the bottom as well, then we know we're done.
288
if (finished) *finished = true;
295
if (q->isMenuContentActive(m_baseIndex + tmpDelta)) {
300
if (finished) *finished = false;
304
int MenuContentActivatorPrivate::content_count(QQmlListProperty<MenuContentState> *prop)
306
MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
307
// we'll create MenuContentState on demand.
311
MenuContentState* MenuContentActivatorPrivate::content_at(QQmlListProperty<MenuContentState> *prop, int index)
313
MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
314
MenuContentActivatorPrivate *d = p->d;
316
if (!d->m_content.contains(index)) {
317
MenuContentState* content = new MenuContentState(false);
318
d->m_content[index] = content;
319
Q_EMIT p->contentChanged();
323
return d->m_content[index];
326
MenuContentState::MenuContentState(bool active)
331
bool MenuContentState::isActive() const
336
void MenuContentState::setActive(bool active)
338
if (m_active != active) {
340
Q_EMIT activeChanged();
344
// Because we are defining a new QObject-based class (ContentTimer) here.
345
#include "menucontentactivator.moc"