26 #include <KIO/Scheduler>
28 #include <QDomDocument>
30 class PicofthedayFactory :
public DecorationFactory
40 KConfig _config( QLatin1String(
"korganizerrc" ));
41 KConfigGroup config( &_config,
"Picture of the Day Plugin" );
42 mThumbSize = config.readEntry(
"InitialThumbnailSize", QSize( 120, 60 ) );
57 return i18n(
"<qt>This plugin provides the Wikipedia "
58 "<i>Picture of the Day</i>.</qt>" );
63 Element::List elements;
66 elements.append( element );
74 const QSize &initialThumbSize )
75 :
StoredElement( id ), mDate( date ), mThumbSize( initialThumbSize ),
76 mFirstStepCompleted( false ),
77 mSecondStepCompleted( false ),
78 mFirstStepJob( 0 ), mSecondStepJob( 0 ), mThirdStepJob( 0 )
80 setShortText( i18n(
"Loading..." ) );
81 setLongText( i18n(
"<qt>Loading <i>Picture of the Day</i>...</qt>" ) );
83 mTimer =
new QTimer(
this );
84 mTimer->setSingleShot(
true );
93 if ( !mFirstStepCompleted && !mFirstStepJob ) {
94 KUrl url = KUrl( QLatin1String(
"http://en.wikipedia.org/w/index.php?title=Template:POTD/") +
95 mDate.toString( Qt::ISODate ) + QLatin1String(
"&action=raw") );
98 mFirstStepJob = KIO::storedGet( url, KIO::NoReload, KIO::HideProgressInfo );
99 KIO::Scheduler::setJobPriority( mFirstStepJob, 1 );
101 connect( mFirstStepJob, SIGNAL(result(
KJob*)),
102 this, SLOT(step1Result(
KJob*)) );
112 void POTDElement::step1Result(
KJob *job )
114 if ( job->error() ) {
115 kWarning() <<
"POTD:" << mDate <<
": could not get POTD file name:" << job->errorString();
116 kDebug() <<
"POTD:" << mDate <<
": file name:" << mFileName;
117 kDebug() <<
"POTD:" << mDate <<
": full-size image:" << mFullSizeImageUrl.url();
118 kDebug() <<
"POTD:" << mDate <<
": thumbnail:" << mThumbUrl.url();
119 mFirstStepCompleted =
false;
124 KIO::StoredTransferJob *
const transferJob =
static_cast<KIO::StoredTransferJob*
>( job );
125 const QStringList lines =
126 QString::fromUtf8( transferJob->data().data(), transferJob->data().size() ).split( QLatin1Char(
'\n') );
128 Q_FOREACH(
const QString &line, lines ) {
129 if ( line.startsWith( QLatin1String(
"|image=") ) ) {
134 mFileName = mFileName.remove( QLatin1String(
"|image=") ).replace( QLatin1Char(
' '), QLatin1Char(
'_') );
136 Q_FOREACH(
const QString &line, lines ) {
137 if ( line.startsWith( QLatin1String(
"|texttitle=") ) ) {
142 mDescription = mDescription.remove( QLatin1String(
"|texttitle=") );
143 if ( !mDescription.isEmpty() ) {
144 mLongText = mDescription;
146 mLongText = mFileName;
148 mLongText = i18n(
"Wikipedia POTD: %1", mLongText );
151 kDebug() <<
"FILENAME=" << mFileName;
152 kDebug() <<
"DESCRIPTION=" << mDescription;
154 mFirstStepCompleted =
true;
162 if ( !mSecondStepCompleted && !mSecondStepJob ) {
163 mUrl = KUrl( QLatin1String(
"http://en.wikipedia.org/wiki/File:") + mFileName );
167 mShortText = i18n(
"Picture Page" );
170 mSecondStepJob = KIO::storedGet( mUrl, KIO::NoReload, KIO::HideProgressInfo );
171 KIO::Scheduler::setJobPriority( mSecondStepJob, 1 );
173 connect( mSecondStepJob, SIGNAL(result(
KJob*)),
174 this, SLOT(step2Result(
KJob*)) );
183 void POTDElement::step2Result(
KJob *job )
185 if ( job->error() ) {
186 kWarning() <<
"POTD:" << mDate <<
": could not get POTD image page:" << job->errorString();
187 kDebug() <<
"POTD:" << mDate <<
": file name:" << mFileName;
188 kDebug() <<
"POTD:" << mDate <<
": full-size image:" << mFullSizeImageUrl.url();
189 kDebug() <<
"POTD:" << mDate <<
": thumbnail:" << mThumbUrl.url();
190 mSecondStepCompleted =
false;
196 KIO::StoredTransferJob *
const transferJob =
static_cast<KIO::StoredTransferJob*
>( job );
198 QDomDocument imgPage;
199 if ( !imgPage.setContent( QString::fromUtf8( transferJob->data().data(),
200 transferJob->data().size() ) ) ) {
201 kWarning() <<
"POTD:" << mDate <<
": Wikipedia returned an invalid XML page for image"
207 QDomNodeList links = imgPage.elementsByTagName( QLatin1String(
"a") );
208 for ( uint i=0; i<links.length(); ++i ) {
209 QString href = links.item(i).attributes().namedItem( QLatin1String(
"href") ).nodeValue();
210 if ( href.startsWith(
211 QLatin1String(
"//upload.wikimedia.org/wikipedia/commons/" ) ) ) {
212 mFullSizeImageUrl = href;
219 QDomNodeList images = imgPage.elementsByTagName( QLatin1String(
"img") );
220 for ( uint i=0; i<links.length(); ++i ) {
221 QDomNamedNodeMap attr = images.item( i ).attributes();
222 QString src = attr.namedItem( QLatin1String(
"src") ).nodeValue();
224 if ( src.startsWith(
thumbnailUrl( mFullSizeImageUrl ).url() ) ) {
225 if ( ( attr.namedItem( QLatin1String(
"height") ).nodeValue().toInt() != 0 ) &&
226 ( attr.namedItem( QLatin1String(
"width") ).nodeValue().toInt() != 0 ) ) {
227 mHWRatio = attr.namedItem( QLatin1String(
"height") ).nodeValue().toFloat() /
228 attr.namedItem( QLatin1String(
"width") ).nodeValue().toFloat();
234 kDebug() <<
"POTD:" << mDate <<
": h/w ratio:" << mHWRatio;
235 kDebug() <<
"POTD:" << mDate <<
": got POTD image page source:" << mFullSizeImageUrl;
237 if ( !mFullSizeImageUrl.isEmpty() ) {
238 mSecondStepCompleted =
true;
246 QString thumbUrl = fullSizeUrl.url();
248 thumbUrl.replace( QRegExp( QLatin1String(
"//upload.wikimedia.org/wikipedia/commons/(.*)/([^/]*)") ),
249 QLatin1String(
"//upload.wikimedia.org/wikipedia/commons/thumb/\\1/\\2/") +
250 QString::number( width ) + QLatin1String(
"px-\\2") );
253 thumbUrl.replace( QRegExp( QLatin1String(
"//upload.wikimedia.org/wikipedia/commons/(.*)/([^/]*)") ),
254 QLatin1String(
"//upload.wikimedia.org/wikipedia/commons/thumb/\\1/\\2") );
256 thumbUrl.replace( QRegExp( QLatin1String(
"^file:////") ), QLatin1String(
"http://") );
257 return KUrl( thumbUrl );
263 if ( mThirdStepJob ) {
264 mThirdStepJob->kill();
268 int thumbWidth = mThumbSize.width();
269 int thumbHeight =
static_cast<int>( thumbWidth * mHWRatio );
270 if ( mThumbSize.height() < thumbHeight ) {
275 thumbWidth /= ( thumbHeight / mThumbSize.height() );
276 thumbHeight =
static_cast<int>( thumbWidth * mHWRatio );
278 mDlThumbSize = QSize( thumbWidth, thumbHeight );
279 kDebug() <<
"POTD:" << mDate <<
": will download thumbnail of size" << mDlThumbSize;
281 QUrl::fromPercentEncoding(
282 thumbnailUrl( mFullSizeImageUrl, thumbWidth ).url().toLatin1() );
284 kDebug() <<
"POTD:" << mDate <<
": got POTD thumbnail URL:" << thumbUrl;
285 mThumbUrl = thumbUrl;
287 mThirdStepJob = KIO::storedGet( thumbUrl, KIO::NoReload, KIO::HideProgressInfo );
288 kDebug() <<
"POTD:" << mDate <<
": get" << thumbUrl;
289 KIO::Scheduler::setJobPriority( mThirdStepJob, 1 );
291 connect( mThirdStepJob, SIGNAL(result(
KJob*)),
292 this, SLOT(step3Result(
KJob*)) );
299 void POTDElement::step3Result(
KJob *job )
301 if ( job != mThirdStepJob ) {
306 if ( job->error() ) {
307 kWarning() <<
"POTD:" << mDate <<
": could not get POTD:" << job->errorString();
308 kDebug() <<
"POTD:" << mDate <<
": file name:" << mFileName;
309 kDebug() <<
"POTD:" << mDate <<
": full-size image:" << mFullSizeImageUrl.url();
310 kDebug() <<
"POTD:" << mDate <<
": thumbnail:" << mThumbUrl.url();
315 KIO::StoredTransferJob*
const transferJob =
static_cast<KIO::StoredTransferJob*
>( job );
316 if ( mPixmap.loadFromData( transferJob->data() ) ) {
317 kDebug() <<
"POTD:" << mDate <<
": got POTD.";
318 emit
gotNewPixmap( mPixmap.scaled( mThumbSize, Qt::KeepAspectRatio,
319 Qt::SmoothTransformation ) );
325 if ( ( mThumbSize.width() < size.width() ) || ( mThumbSize.height() < size.height() ) ) {
326 kDebug() <<
"POTD:" << mDate <<
": called for a new pixmap size ("
327 << size <<
"instead of" << mThumbSize <<
", stored pixmap:"
328 << mPixmap.size() <<
")";
331 if ( !mFirstStepCompleted ) {
333 }
else if ( ( mDlThumbSize.width() < size.width() ) &&
334 ( mDlThumbSize.height() < size.height() ) ) {
335 if ( mThirdStepJob ) {
341 }
else if ( mFirstStepJob || mSecondStepJob ) {
348 disconnect( mTimer, SIGNAL(timeout()),
350 connect( mTimer, SIGNAL(timeout()),
352 mTimer->setSingleShot(
true );
353 mTimer->start( 1000 );
361 if ( mPixmap.isNull() ) {
364 return mPixmap.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
372 #include "picoftheday.moc"
POTDElement(const QString &id, const QDate &date, const QSize &initialThumbSize)
void step1StartDownload()
First step of three in the download process.
void step1Success() const
void configure(QWidget *parent)
void gotNewShortText(const QString &) const
void step3GetThumbnail()
Third step of three in the downloading process.
void gotNewPixmap(const QPixmap &) const
void gotNewUrl(const KUrl &) const
void step2GetImagePage()
Second step of three in the download process.
QPixmap newPixmap(const QSize &size)
void gotNewLongText(const QString &) const
K_EXPORT_PLUGIN(KOrganizerFactory(createAboutData())) KOrganizerPart
void setThumbnailSize(const QSize &size)
void step2Success() const
KUrl thumbnailUrl(const KUrl &fullSizeUrl, const int width=0) const
Returns the thumbnail URL for a given width corresponding to a full-size image URL.
void step3Success() const
Element::List createDayElements(const QDate &)