[Marble-commits] KDE/kdeedu/marble/src
Bastian Holst
bastianholst at gmx.de
Thu Aug 13 16:27:03 CEST 2009
SVN commit 1010843 by bholst:
Marble Weather Plugin speedup by sourcing complex tasks out into a thread.
M +3 -0 lib/AbstractDataPluginItem.h
M +1 -0 lib/AbstractDataPluginModel.cpp
M +90 -1 plugins/render/weather/BBCParser.cpp
M +28 -2 plugins/render/weather/BBCParser.h
M +3 -23 plugins/render/weather/BBCWeatherItem.cpp
M +33 -11 plugins/render/weather/BBCWeatherService.cpp
M +11 -0 plugins/render/weather/BBCWeatherService.h
M +28 -4 plugins/render/weather/StationListParser.cpp
M +15 -2 plugins/render/weather/StationListParser.h
M +3 -0 plugins/render/weather/WeatherItem.cpp
--- trunk/KDE/kdeedu/marble/src/lib/AbstractDataPluginItem.h #1010842:1010843
@@ -81,6 +81,9 @@
virtual bool isGeoProjected();
virtual bool operator<( const AbstractDataPluginItem *other ) const = 0;
+
+ Q_SIGNALS:
+ void updated();
private:
AbstractDataPluginItemPrivate * const d;
--- trunk/KDE/kdeedu/marble/src/lib/AbstractDataPluginModel.cpp #1010842:1010843
@@ -303,6 +303,7 @@
d->m_itemSet.insert( i, item );
connect( item, SIGNAL( destroyed( QObject* ) ), this, SLOT( removeItem( QObject* ) ) );
+ connect( item, SIGNAL( updated() ), this, SIGNAL( itemsUpdated() ) );
if ( item->initialized() ) {
emit itemsUpdated();
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/BBCParser.cpp #1010842:1010843
@@ -14,11 +14,14 @@
// Marble
#include "global.h"
#include "WeatherData.h"
+#include "BBCWeatherItem.h"
// Qt
#include <QtCore/QByteArray>
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QMutexLocker>
#include <QtCore/QRegExp>
using namespace Marble;
@@ -36,11 +39,93 @@
QHash<QString, int> BBCParser::monthNames
= QHash<QString, int>();
+const int WAIT_ATTEMPTS = 20;
+const int WAIT_TIME = 100;
+
BBCParser::BBCParser()
+ : QThread(),
+ m_end( false )
{
BBCParser::setupHashes();
}
+BBCParser::~BBCParser()
+{
+ m_schedule.clear();
+ if ( isRunning() ) {
+ m_end = true;
+ wait( 1000 );
+ }
+}
+
+BBCParser *BBCParser::instance()
+{
+ static BBCParser parser;
+ return &parser;
+}
+
+void BBCParser::scheduleRead( const QString& path,
+ BBCWeatherItem *item,
+ const QString& type )
+{
+ ScheduleEntry entry;
+ entry.path = path;
+ entry.item = item;
+ entry.type = type;
+
+ m_schedule.push( entry );
+
+ QMutexLocker locker( &m_runStateMutex );
+ if ( !isRunning() ) {
+ start( QThread::IdlePriority );
+ }
+}
+
+void BBCParser::run()
+{
+ int waitAttempts = WAIT_ATTEMPTS;
+ while( 1 ) {
+ m_runStateMutex.lock();
+ if ( m_schedule.isEmpty() ) {
+ waitAttempts--;
+ if ( !waitAttempts || m_end ) {
+ break;
+ }
+ else {
+ m_runStateMutex.unlock();
+ msleep( WAIT_TIME );
+ }
+ }
+ else {
+ m_runStateMutex.unlock();
+ ScheduleEntry entry = m_schedule.pop();
+
+ QFile file( entry.path );
+ if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
+ return;
+ }
+
+ QList<WeatherData> data = read( &file );
+
+ if( !data.isEmpty() && !entry.item.isNull() ) {
+ if ( entry.type == "bbcobservation" ) {
+ entry.item->setCurrentWeather( data.at( 0 ) );
+ }
+ else if ( entry.type == "bbcforecast" ) {
+ entry.item->addForecastWeather( data );
+ }
+
+ emit parsedFile();
+ }
+
+ waitAttempts = WAIT_ATTEMPTS;
+ }
+ }
+
+ m_runStateMutex.unlock();
+}
+
+
QList<WeatherData> BBCParser::read( QIODevice *device )
{
m_list.clear();
@@ -381,7 +466,7 @@
{
return;
}
-
+
dayConditions["sunny"] = WeatherData::ClearDay;
dayConditions["clear"] = WeatherData::ClearDay;
dayConditions["clear sky"] = WeatherData::ClearDay;
@@ -396,6 +481,7 @@
dayConditions["fog"] = WeatherData::Mist;
dayConditions["foggy"] = WeatherData::Mist;
dayConditions["dense fog"] = WeatherData::Mist;
+ dayConditions["Thick Fog"] = WeatherData::Mist;
dayConditions["tropical storm"] = WeatherData::Thunderstorm;
dayConditions["hazy"] = WeatherData::Mist;
dayConditions["light shower"] = WeatherData::LightShowersDay;
@@ -443,6 +529,7 @@
nightConditions["fog"] = WeatherData::Mist;
nightConditions["foggy"] = WeatherData::Mist;
nightConditions["dense fog"] = WeatherData::Mist;
+ nightConditions["Thick Fog"] = WeatherData::Mist;
nightConditions["tropical storm"] = WeatherData::Thunderstorm;
nightConditions["hazy"] = WeatherData::Mist;
nightConditions["light shower"] = WeatherData::LightShowersNight;
@@ -522,3 +609,5 @@
monthNames["Nov"] = 11;
monthNames["Dec"] = 12;
}
+
+#include "BBCParser.moc"
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/BBCParser.h #1010842:1010843
@@ -17,6 +17,10 @@
// Qt
#include <QtCore/QHash>
#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include <QtCore/QPointer>
+#include <QtCore/QStack>
+#include <QtCore/QThread>
#include <QtCore/QXmlStreamReader>
class QByteArray;
@@ -25,14 +29,33 @@
namespace Marble
{
-class BBCParser : public QXmlStreamReader
+class BBCWeatherItem;
+
+struct ScheduleEntry {
+ QString path;
+ QPointer<BBCWeatherItem> item;
+ QString type;
+};
+
+class BBCParser : public QThread, public QXmlStreamReader
{
+ Q_OBJECT;
public:
BBCParser();
+ ~BBCParser();
+ static BBCParser *instance();
+ void scheduleRead( const QString& path, BBCWeatherItem *item, const QString& type );
+
+protected:
+ void run();
+
+Q_SIGNALS:
+ void parsedFile();
+
+private:
QList<WeatherData> read( QIODevice *device );
-private:
void readUnknownElement();
void readBBC();
void readChannel();
@@ -44,6 +67,9 @@
void setupHashes();
QList<WeatherData> m_list;
+ QStack<ScheduleEntry> m_schedule;
+ QMutex m_runStateMutex;
+ bool m_end;
static QHash<QString, WeatherData::WeatherCondition> dayConditions;
static QHash<QString, WeatherData::WeatherCondition> nightConditions;
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/BBCWeatherItem.cpp #1010842:1010843
@@ -18,6 +18,7 @@
// Qt
#include <QtCore/QDebug>
#include <QtCore/QFile>
+#include <QtCore/QTime>
#include <QtCore/QUrl>
using namespace Marble;
@@ -57,30 +58,9 @@
void BBCWeatherItem::addDownloadedFile( const QString& url, const QString& type )
{
- if( type == "bbcobservation" ) {
- QFile file( url );
- if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
- return;
- }
-
- BBCParser parser;
- QList<WeatherData> data = parser.read( &file );
- if( !data.isEmpty() ) {
- setCurrentWeather( data.at( 0 ) );
- }
+ if( type == "bbcobservation" || type == "bbcforecast" ) {
+ BBCParser::instance()->scheduleRead( url, this, type );
}
- else if ( type == "bbcforecast" ) {
- QFile file( url );
-
- if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
- return;
- }
-
- BBCParser parser;
- QList<WeatherData> data = parser.read( &file );
-
- addForecastWeather( data );
- }
}
quint32 BBCWeatherItem::bbcId() const
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/BBCWeatherService.cpp #1010842:1010843
@@ -31,7 +31,12 @@
using namespace Marble;
BBCWeatherService::BBCWeatherService( QObject *parent )
- : AbstractWeatherService( parent )
+ : AbstractWeatherService( parent ),
+ m_parsingStarted( false ),
+ m_parser( 0 ),
+ m_scheduledBox(),
+ m_scheduledNumber( 0 ),
+ m_scheduledFacade( 0 )
{
}
@@ -45,10 +50,17 @@
{
Q_UNUSED( facade );
- if ( m_items.isEmpty() ) {
+ if ( !m_parsingStarted ) {
setupList();
}
-
+
+ if ( m_items.isEmpty() ) {
+ m_scheduledBox = box;
+ m_scheduledNumber = number;
+ m_scheduledFacade = facade;
+ return;
+ }
+
qint32 fetched = 0;
QList<BBCWeatherItem *>::iterator it = m_items.begin();
@@ -63,18 +75,28 @@
}
}
-void BBCWeatherService::setupList()
+void BBCWeatherService::fetchStationList()
{
- QTime time;
- QFile file( MarbleDirs::path( "weather/bbc-stations.xml" ) );
+ m_items = m_parser->stationList();
+ delete m_parser;
+ m_parser = 0;
- if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
- return;
+ if ( m_scheduledNumber
+ && !m_scheduledBox.isNull()
+ && m_scheduledFacade ) {
+ getAdditionalItems( m_scheduledBox, m_scheduledFacade, m_scheduledNumber );
}
+}
- StationListParser parser( this );
- m_items = parser.read( &file );
- qDebug() << "Parsed station list in " << time.elapsed() << " ms and found " << m_items.size() << "items";
+void BBCWeatherService::setupList()
+{
+ m_parsingStarted = true;
+
+ m_parser = new StationListParser( this );
+ m_parser->setPath( MarbleDirs::path( "weather/bbc-stations.xml" ) );
+ connect( m_parser, SIGNAL( parsedStationList() ),
+ this, SLOT( fetchStationList() ) );
+ m_parser->start( QThread::IdlePriority );
}
#include "BBCWeatherService.moc"
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/BBCWeatherService.h #1010842:1010843
@@ -13,10 +13,13 @@
#include "AbstractWeatherService.h"
+#include "GeoDataLatLonAltBox.h"
+
namespace Marble
{
class BBCWeatherItem;
+class StationListParser;
class BBCWeatherService : public AbstractWeatherService
{
@@ -31,10 +34,18 @@
MarbleDataFacade *facade,
qint32 number = 10 );
+ private Q_SLOTS:
+ void fetchStationList();
+
private:
void setupList();
QList<BBCWeatherItem*> m_items;
+ bool m_parsingStarted;
+ StationListParser *m_parser;
+ GeoDataLatLonAltBox m_scheduledBox;
+ qint32 m_scheduledNumber;
+ MarbleDataFacade *m_scheduledFacade;
};
} // namespace Marble
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/StationListParser.cpp #1010842:1010843
@@ -18,6 +18,7 @@
// Qt
#include <QtCore/QDebug>
+#include <QtCore/QFile>
#include <QtCore/QString>
using namespace Marble;
@@ -34,14 +35,14 @@
}
StationListParser::StationListParser( QObject *parent )
- : m_parent( parent )
+ : QThread( parent ),
+ QXmlStreamReader()
{
}
-QList<BBCWeatherItem*> StationListParser::read( QIODevice *device )
+void StationListParser::read()
{
m_list.clear();
- setDevice( device );
while ( !atEnd() ) {
readNext();
@@ -53,10 +54,31 @@
raiseError( "The file is not an valid file." );
}
}
+}
+QList<BBCWeatherItem *> StationListParser::stationList() const
+{
return m_list;
}
+void StationListParser::setPath( QString path )
+{
+ m_path = path;
+}
+
+void StationListParser::run()
+{
+ QFile file( m_path );
+
+ if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
+ return;
+ }
+
+ setDevice( &file );
+ read();
+ emit parsedStationList();
+}
+
void StationListParser::readUnknownElement()
{
Q_ASSERT( isStartElement() );
@@ -97,7 +119,7 @@
Q_ASSERT( isStartElement()
&& name() == "Station" );
- BBCWeatherItem *item = new BBCWeatherItem( m_parent );
+ BBCWeatherItem *item = new BBCWeatherItem();
while ( !atEnd() ) {
readNext();
@@ -179,3 +201,5 @@
}
}
}
+
+#include "StationListParser.moc"
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/StationListParser.h #1010842:1010843
@@ -15,6 +15,7 @@
#include <QtCore/QHash>
#include <QtCore/QStringList>
#include <QtCore/QList>
+#include <QtCore/QThread>
#include <QtCore/QXmlStreamReader>
class QString;
@@ -24,13 +25,24 @@
class BBCWeatherItem;
-class StationListParser : public QXmlStreamReader
+class StationListParser : public QThread, public QXmlStreamReader
{
+ Q_OBJECT
public:
StationListParser( QObject *parent );
- QList<BBCWeatherItem *> read( QIODevice *device );
+ void read();
+ QList<BBCWeatherItem *> stationList() const;
+
+ void setPath( QString path );
+
+Q_SIGNALS:
+ void parsedStationList();
+
+protected:
+ void run();
+
private:
void readUnknownElement();
void readStationList();
@@ -38,6 +50,7 @@
QString readCharacters();
void readPoint( BBCWeatherItem *item );
+ QString m_path;
QList<BBCWeatherItem *> m_list;
QObject *m_parent;
};
--- trunk/KDE/kdeedu/marble/src/plugins/render/weather/WeatherItem.cpp #1010842:1010843
@@ -347,6 +347,7 @@
d->m_currentWeather = weather;
d->updateToolTip();
d->updateLabels();
+ emit updated();
}
QMap<QDate, WeatherData> WeatherItem::forecastWeather() const
@@ -359,6 +360,7 @@
d->m_forecastWeather = forecasts;
d->updateToolTip();
+ emit updated();
}
void WeatherItem::addForecastWeather( const QList<WeatherData>& forecasts )
@@ -389,6 +391,7 @@
}
d->updateToolTip();
+ emit updated();
}
quint8 WeatherItem::priority() const
More information about the Marble-commits
mailing list