move the timer experiment out for 4.1 at least
svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=797015
This commit is contained in:
parent
ae33eeddda
commit
b8e3eed0dc
@ -47,7 +47,6 @@ set(plasma_LIB_SRCS
|
||||
svg.cpp
|
||||
svgpanel.cpp
|
||||
theme.cpp
|
||||
timer.cpp
|
||||
toolbox.cpp
|
||||
paneltoolbox.cpp
|
||||
desktoptoolbox.cpp
|
||||
@ -117,7 +116,6 @@ set(plasma_LIB_INCLUDES
|
||||
svg.h
|
||||
svgpanel.h
|
||||
theme.h
|
||||
timer.h
|
||||
uiloader.h
|
||||
view.h
|
||||
delegate.h)
|
||||
|
@ -17,7 +17,3 @@ set(appletbrowser_SRCS appletbrowser.cpp)
|
||||
kde4_add_executable(plasmaappletbrowser ${appletbrowser_SRCS})
|
||||
target_link_libraries(plasmaappletbrowser ${KDE4_KDEUI_LIBS} plasma)
|
||||
|
||||
set(sharedtimertest_SRCS sharedtimertest.cpp)
|
||||
kde4_add_executable(sharedtimertest ${sharedtimertest_SRCS})
|
||||
target_link_libraries(sharedtimertest ${KDE4_KDEUI_LIBS} plasma)
|
||||
|
||||
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Aaron J. Seigo
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "sharedtimertest.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KAboutData>
|
||||
#include <KApplication>
|
||||
#include <KCmdLineArgs>
|
||||
#include <KComponentData>
|
||||
#include <KConfig>
|
||||
#include <KDebug>
|
||||
|
||||
#include "plasma/timer.h"
|
||||
|
||||
static const char description[] = I18N_NOOP("Applet browser dialog");
|
||||
static const char version[] = "1.0";
|
||||
|
||||
Tester::Tester(int rounds)
|
||||
: QObject(0),
|
||||
m_count(0),
|
||||
m_round(0),
|
||||
m_targetRounds(rounds)
|
||||
{
|
||||
Plasma::Timer *t50 = new Plasma::Timer(this);
|
||||
connect(t50, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t50->start(50);
|
||||
|
||||
Plasma::Timer *t70 = new Plasma::Timer(this);
|
||||
connect(t70, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t70->start(70);
|
||||
|
||||
Plasma::Timer *t210 = new Plasma::Timer(this);
|
||||
connect(t210, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t210->start(210);
|
||||
|
||||
Plasma::Timer *t500 = new Plasma::Timer(this);
|
||||
connect(t500, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t500->start(500);
|
||||
// QObject::connect(t, SIGNAL(timeout()), &app, SLOT(quit()));
|
||||
|
||||
Plasma::Timer *t1000 = new Plasma::Timer(this);
|
||||
t1000->start(1000);
|
||||
delete t1000;
|
||||
|
||||
Plasma::Timer *t95 = new Plasma::Timer(this);
|
||||
connect(t95, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t95->start(95);
|
||||
|
||||
Plasma::Timer *t200 = new Plasma::Timer(this);
|
||||
connect(t200, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
t200->start(200);
|
||||
|
||||
|
||||
m_order << t50 << t70 << t95
|
||||
<< t50 << t70 << t95
|
||||
<< t200 << t210
|
||||
<< t50 << t70 << t95
|
||||
<< t50 << t70 << t95
|
||||
<< t200 << t210
|
||||
<< t50 << t70
|
||||
<< t500;
|
||||
|
||||
}
|
||||
|
||||
void Tester::timeout()
|
||||
{
|
||||
Plasma::Timer *t = qobject_cast<Plasma::Timer*>(sender());
|
||||
if (m_order[m_count] != t) {
|
||||
kFatal() << "round" << m_round << "call" << m_count << "expected"
|
||||
<< m_order[m_count]->interval() << "but got" << t->interval();
|
||||
}
|
||||
|
||||
//kDebug() << "round" << m_round << "call" << m_count << "got" << t->interval();
|
||||
++m_count;
|
||||
|
||||
if (m_count == m_order.count()) {
|
||||
m_count = 0;
|
||||
++m_round;
|
||||
//kDebug() << "starting round" << m_round;
|
||||
}
|
||||
|
||||
if (m_round == m_targetRounds) {
|
||||
qApp->quit();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
KAboutData aboutData("sharedtimertest", 0, ki18n("Plasma Shared Timer Test"),
|
||||
version, ki18n( description ), KAboutData::License_GPL,
|
||||
ki18n("(C) 2008, Aaron Seigo"));
|
||||
aboutData.addAuthor(ki18n("Aaron Seigo"), ki18n("Original author"), "aseigo@kde.org");
|
||||
KCmdLineArgs::init(argc, argv, &aboutData);
|
||||
KApplication app;
|
||||
|
||||
Tester t(2);
|
||||
//QTimer::singleShot(2000, &app, SLOT(quit()));
|
||||
|
||||
QTime elapsed;
|
||||
elapsed.start();
|
||||
|
||||
int rv = app.exec();
|
||||
|
||||
int totalTime = elapsed.elapsed();
|
||||
kDebug() << "successful run, took" << totalTime;
|
||||
return rv;
|
||||
}
|
||||
|
||||
#include "sharedtimertest.moc"
|
||||
|
427
timer.cpp
427
timer.cpp
@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "timer.h"
|
||||
#include "sharedtimer_p.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QTimerEvent>
|
||||
|
||||
#include <KDE/KDebug>
|
||||
#include <KDE/KGlobal>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class Timer::Private
|
||||
{
|
||||
public:
|
||||
Private()
|
||||
: interval(0),
|
||||
active(false),
|
||||
singleShot(false)
|
||||
{
|
||||
}
|
||||
|
||||
int interval;
|
||||
bool active;
|
||||
bool singleShot;
|
||||
};
|
||||
|
||||
Timer::Timer(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new Private)
|
||||
{
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
{
|
||||
TimerDrive::self()->unregisterTimer(this, d->interval);
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Timer::setInterval(int msec)
|
||||
{
|
||||
if (d->active) {
|
||||
// unregister with the new time
|
||||
TimerDrive::self()->unregisterTimer(this, d->interval);
|
||||
}
|
||||
|
||||
d->interval = msec;
|
||||
|
||||
if (d->active) {
|
||||
// register with the new time
|
||||
TimerDrive::self()->registerTimer(this, d->interval);
|
||||
}
|
||||
}
|
||||
|
||||
int Timer::interval() const
|
||||
{
|
||||
return d->interval;
|
||||
}
|
||||
|
||||
void Timer::setSingleShot(bool singleShot)
|
||||
{
|
||||
d->singleShot = singleShot;
|
||||
}
|
||||
|
||||
bool Timer::isSingleShot() const
|
||||
{
|
||||
return d->singleShot;
|
||||
}
|
||||
|
||||
bool Timer::isActive() const
|
||||
{
|
||||
return d->active;
|
||||
}
|
||||
|
||||
void Timer::start(int msec)
|
||||
{
|
||||
if (d->interval != msec) {
|
||||
setInterval(msec);
|
||||
}
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void Timer::start()
|
||||
{
|
||||
if (d->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->active = true;
|
||||
TimerDrive::self()->registerTimer(this, d->interval);
|
||||
}
|
||||
|
||||
void Timer::stop()
|
||||
{
|
||||
TimerDrive::self()->unregisterTimer(this, d->interval);
|
||||
d->active = false;
|
||||
}
|
||||
|
||||
void Timer::activate() const
|
||||
{
|
||||
emit timeout();
|
||||
|
||||
if (d->singleShot) {
|
||||
TimerDrive::self()->unregisterTimer(this, d->interval);
|
||||
d->active = false;
|
||||
}
|
||||
}
|
||||
|
||||
class TimerBundle
|
||||
{
|
||||
public:
|
||||
TimerBundle()
|
||||
: multiple(-1),
|
||||
currentCount(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void setMultiple(int msec, int nextMsec)
|
||||
{
|
||||
if (nextMsec > 0) {
|
||||
currentCount = multiple = nextMsec / msec;
|
||||
} else {
|
||||
currentCount = multiple = -1;
|
||||
}
|
||||
//kDebug() << "setting msec of" << msec << "with" << nextMsec << multiple;
|
||||
}
|
||||
|
||||
int multiple;
|
||||
int currentCount;
|
||||
QList<const Timer*> timers;
|
||||
};
|
||||
|
||||
class TimerDrive::Private
|
||||
{
|
||||
public:
|
||||
Private()
|
||||
: interval(0),
|
||||
timerId(-1)
|
||||
{
|
||||
}
|
||||
|
||||
// msec -> TimerBundle
|
||||
QMap<int, TimerBundle> bundles;
|
||||
int interval;
|
||||
int timerId;
|
||||
};
|
||||
|
||||
class TimerDriveSingleton
|
||||
{
|
||||
public:
|
||||
TimerDrive self;
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(TimerDriveSingleton, privateTimerDriveSelf)
|
||||
|
||||
TimerDrive* TimerDrive::self()
|
||||
{
|
||||
return &privateTimerDriveSelf->self;
|
||||
}
|
||||
|
||||
TimerDrive::TimerDrive(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new Private)
|
||||
{
|
||||
}
|
||||
|
||||
TimerDrive::~TimerDrive()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TimerDrive::registerTimer(const Timer *t, int msec)
|
||||
{
|
||||
kDebug() << "registering" << t << "for" << msec;
|
||||
QMap<int, TimerBundle>::iterator it = d->bundles.find(msec);
|
||||
|
||||
if (it == d->bundles.end()) {
|
||||
kDebug( ) << "creating a new bundle";
|
||||
it = d->bundles.insert(msec, TimerBundle());
|
||||
|
||||
if (it != d->bundles.begin()) {
|
||||
QMap<int, TimerBundle>::iterator prev = it - 1;
|
||||
prev.value().setMultiple(prev.key(), msec);
|
||||
}
|
||||
|
||||
QMap<int, TimerBundle>::iterator next = it + 1;
|
||||
if (next != d->bundles.end()) {
|
||||
it.value().setMultiple(msec, next.key());
|
||||
}
|
||||
|
||||
if (d->bundles.count() == 1) {
|
||||
kDebug() << "kickstarting the timer";
|
||||
d->interval = msec;
|
||||
|
||||
if (d->timerId != -1) {
|
||||
// this should never happen, but better safe than sorry?
|
||||
killTimer(d->timerId);
|
||||
}
|
||||
|
||||
d->timerId = startTimer(msec);
|
||||
} else if (d->timerId != -1) {
|
||||
//TODO: figure out if we're injecting an item between the two current timers
|
||||
}
|
||||
} else {
|
||||
// prevent multiple inclusions
|
||||
foreach (const Timer *existingTimer, it.value().timers) {
|
||||
if (t == existingTimer) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kDebug() << "appending our timer";
|
||||
it.value().timers.append(t);
|
||||
}
|
||||
|
||||
void TimerDrive::unregisterTimer(const Timer *t, int msec)
|
||||
{
|
||||
kDebug() << "unregistering" << t << "for" << msec;
|
||||
// hash of intervals to timer ids
|
||||
QMap<int, TimerBundle>::iterator it = d->bundles.find(msec);
|
||||
if (it != d->bundles.end()) {
|
||||
TimerBundle &bundle = it.value();
|
||||
bundle.timers.removeAll(t);
|
||||
|
||||
if (bundle.timers.count() == 0) {
|
||||
kDebug() << "no more timers, removing this bundle";
|
||||
if (it != d->bundles.begin()) {
|
||||
// update the previous entries multiple
|
||||
kDebug() << "reseting previous interval";
|
||||
int nextMsec = 0;
|
||||
if (it != d->bundles.end()) {
|
||||
QMap<int, TimerBundle>::iterator next = it + 1;
|
||||
if (next != d->bundles.end()) {
|
||||
nextMsec = next.key();
|
||||
}
|
||||
}
|
||||
|
||||
QMap<int, TimerBundle>::iterator prev = it - 1;
|
||||
if (prev != d->bundles.end()) {
|
||||
prev.value().setMultiple(prev.key(), nextMsec);
|
||||
}
|
||||
}
|
||||
|
||||
d->bundles.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->bundles.count() == 0) {
|
||||
if (d->timerId != -1) {
|
||||
killTimer(d->timerId);
|
||||
d->timerId = -1;
|
||||
}
|
||||
} else if (d->timerId != -1) {
|
||||
//TODO: figure out if we were going to call this guy next, and if so,
|
||||
// repair the timings
|
||||
}
|
||||
}
|
||||
|
||||
void TimerDrive::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
int id = event->timerId();
|
||||
if (d->timerId != -1) {
|
||||
killTimer(d->timerId);
|
||||
}
|
||||
|
||||
QMap<int, TimerBundle>::iterator it = d->bundles.begin();
|
||||
QMap<int, TimerBundle>::iterator begin = d->bundles.begin();
|
||||
QMap<int, TimerBundle>::iterator end = d->bundles.end();
|
||||
|
||||
if (it == end) {
|
||||
return;
|
||||
}
|
||||
|
||||
kDebug() << id << d->timerId << "got interval of" << d->interval;
|
||||
int effectiveInterval = d->interval;
|
||||
|
||||
while (it != end) {
|
||||
int msec = it.key();
|
||||
TimerBundle &bundle = it.value();
|
||||
if (msec <= effectiveInterval && bundle.currentCount != 0) {
|
||||
kDebug() << " +++ activating" << msec << bundle.currentCount << effectiveInterval;
|
||||
foreach (const Timer *t, bundle.timers) {
|
||||
t->activate();
|
||||
}
|
||||
|
||||
if (bundle.currentCount >= 0) {
|
||||
--bundle.currentCount;
|
||||
}
|
||||
|
||||
if (bundle.currentCount >= 0) {
|
||||
// we haven't reached our multiple, so don't go further.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//kDebug() << " --- skipping" << msec << bundle.currentCount << effectiveInterval;
|
||||
bundle.currentCount = bundle.multiple;
|
||||
}
|
||||
|
||||
effectiveInterval = msec * bundle.multiple + d->interval;
|
||||
++it;
|
||||
}
|
||||
|
||||
d->interval = 0;
|
||||
int intervalAdjustment = 0;
|
||||
|
||||
if (it == end) {
|
||||
d->interval = begin.key();
|
||||
} else {
|
||||
int currentCount = it.value().currentCount;
|
||||
int prevMsec = it.key() * it.value().multiple;
|
||||
|
||||
if (++it == end) {
|
||||
//kDebug() << " end of the line";
|
||||
d->interval = begin.key();
|
||||
// take into consideration time spent in the last moments prior to reset.
|
||||
if (--it != begin) {
|
||||
int prevInterval = it.key();
|
||||
while (--it != begin) {
|
||||
int gap = prevInterval - it.key();
|
||||
if (gap + intervalAdjustment > d->interval) {
|
||||
break;
|
||||
}
|
||||
|
||||
intervalAdjustment += gap;
|
||||
prevInterval = it.key();
|
||||
}
|
||||
}
|
||||
|
||||
// ensure all our current counts are reset
|
||||
while (begin != end) {
|
||||
begin.value().currentCount = begin.value().multiple;
|
||||
++begin;
|
||||
}
|
||||
} else {
|
||||
// calculate hop to the next value
|
||||
int interval = it.key() - prevMsec;
|
||||
if (currentCount != 0) {
|
||||
// start at the beginning, because we have to take another lap
|
||||
// before continuing on to the next item
|
||||
//kDebug() << " reseting";
|
||||
d->interval = begin.key();
|
||||
|
||||
// take into consideration time spent in the last moments prior to reset.
|
||||
if (--it != begin) {
|
||||
int prevInterval = it.key();
|
||||
while (--it != begin) {
|
||||
int gap = prevInterval - it.key();
|
||||
if (gap + intervalAdjustment > d->interval) {
|
||||
break;
|
||||
}
|
||||
|
||||
intervalAdjustment += gap;
|
||||
prevInterval = it.key();
|
||||
}
|
||||
}
|
||||
} else if (interval > begin.key()) {
|
||||
// start at the beginning, because our next interval is longer
|
||||
// than some of our earlier timers
|
||||
//kDebug() << " looping back";
|
||||
d->interval = begin.key();
|
||||
while (begin != it) {
|
||||
if (begin.key() < interval) {
|
||||
begin.value().currentCount = begin.value().multiple;
|
||||
} else {
|
||||
begin.value().currentCount = 0;
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
} else if (it.value().currentCount == 0) {
|
||||
// in this branch, we've looped back once due to the next step
|
||||
// interval being larger than our beginning interval
|
||||
//kDebug() << " loop back detected";
|
||||
while (begin != it) {
|
||||
begin.value().currentCount = 0;
|
||||
++begin;
|
||||
}
|
||||
|
||||
while (it.value().currentCount == 0) {
|
||||
interval = it.key() * it.value().multiple;
|
||||
++it;
|
||||
}
|
||||
|
||||
d->interval = it.key() - interval;
|
||||
} else {
|
||||
// short hop to the next entry
|
||||
//kDebug() << " short hop to the next stop";
|
||||
d->interval = interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (d->interval) {
|
||||
d->timerId = startTimer(d->interval - intervalAdjustment);
|
||||
kDebug() << " starting interval of" << d->interval
|
||||
<< " (really" << d->interval - intervalAdjustment << ")" << d->timerId;
|
||||
} else {
|
||||
d->timerId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include "timer.moc"
|
||||
#include "sharedtimer_p.moc"
|
||||
|
60
timer.h
60
timer.h
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_TIMER_H
|
||||
#define PLASMA_TIMER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class PLASMA_EXPORT Timer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Timer(QObject *parent = 0);
|
||||
~Timer();
|
||||
int interval() const;
|
||||
bool isActive() const;
|
||||
bool isSingleShot() const;
|
||||
void setInterval(int msec);
|
||||
void setSingleShot(bool singleShot);
|
||||
void activate() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void start(int msec);
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
Q_SIGNALS:
|
||||
void timeout() const;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private * const d;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user