30 #include <kblog/gdata.h>
31 #include <kblog/blogger1.h>
32 #include <kblog/metaweblog.h>
33 #include <kblog/movabletype.h>
34 #include <kblog/wordpressbuggy.h>
36 #include <kmessagebox.h>
38 #include <kio/jobclasses.h>
41 #include <QTableWidget>
43 #include <QTextDocument>
46 class AddEditBlog::Private
54 mFetchProfileIdTimer(0),
59 Ui::AddEditBlogBase ui;
64 QTimer* mFetchProfileIdTimer;
65 QTimer* mFetchBlogIdTimer;
66 QTimer* mFetchAPITimer;
72 :
KDialog( parent, flags ), d(new Private)
76 d->ui.setupUi( d->mainW );
77 setMainWidget( d->mainW );
80 d->mFetchAPITimer = d->mFetchBlogIdTimer = d->mFetchProfileIdTimer = 0;
82 connect( d->ui.txtId, SIGNAL(textChanged(QString)),
this, SLOT(
enableOkButton(QString)) );
83 connect( d->ui.txtUrl, SIGNAL(textChanged(QString)),
this, SLOT(
enableAutoConfBtn()) );
84 connect( d->ui.txtUser, SIGNAL(textChanged(QString)),
this, SLOT(
enableAutoConfBtn()) );
85 connect( d->ui.txtPass, SIGNAL(textChanged(QString)),
this, SLOT(
enableAutoConfBtn()) );
86 connect( d->ui.btnAutoConf, SIGNAL(clicked()),
this, SLOT(
autoConfigure()) );
87 connect( d->ui.btnFetch, SIGNAL(clicked()),
this, SLOT(
fetchBlogId()) );
88 connect( d->ui.comboApi, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
slotComboApiChanged(
int)) );
89 connect( d->ui.txtUrl, SIGNAL(returnPressed()),
this, SLOT(
slotReturnPressed()) );
90 connect( d->ui.txtUser, SIGNAL(returnPressed()),
this, SLOT(
slotReturnPressed()) );
91 connect( d->ui.txtPass, SIGNAL(returnPressed()),
this, SLOT(
slotReturnPressed()) );
95 setWindowTitle( i18n(
"Edit blog settings" ) );
96 enableButtonOk(
true );
97 d->ui.btnFetch->setEnabled(
true );
98 d->ui.btnAutoConf->setEnabled(
true );
101 d->ui.txtUrl->setText( d->bBlog->url().url() );
102 d->ui.txtUser->setText( d->bBlog->username() );
103 d->ui.txtPass->setText( d->bBlog->password() );
104 d->ui.txtId->setText( d->bBlog->blogid() );
105 QString title = d->bBlog->title();
106 title = title.replace(QLatin1String(
"&"), QLatin1String(
"&"));
107 d->ui.txtTitle->setText( title );
108 d->ui.comboApi->setCurrentIndex( d->bBlog->api() );
109 d->ui.comboDir->setCurrentIndex( d->bBlog->direction() );
110 d->ui.txtTitle->setEnabled(
true);
112 setWindowTitle( i18n(
"Add a new blog" ) );
114 d->bBlog->setBlogId( QString() );
115 enableButtonOk(
false );
116 d->ui.txtTitle->setEnabled(
false);
120 d->ui.txtUrl->setFocus();
125 if ( d->ui.txtUrl->text().isEmpty() || d->ui.txtUser->text().isEmpty() || d->ui.txtPass->text().isEmpty() ) {
126 d->ui.btnAutoConf->setEnabled(
false );
127 d->ui.btnFetch->setEnabled(
false );
129 d->ui.btnAutoConf->setEnabled(
true );
130 d->ui.btnFetch->setEnabled(
true );
137 if ( d->ui.txtUrl->text().isEmpty() || d->ui.txtUser->text().isEmpty() || d->ui.txtPass->text().isEmpty() ) {
138 kDebug() <<
"Username, Password or Url doesn't set!";
139 KMessageBox::sorry(
this, i18n(
"You have to set the username, password and URL of your blog or website." ),
140 i18n(
"Incomplete fields" ) );
143 showWaitWidget( i18n(
"Trying to guess blog and API type...") );
146 if ( d->ui.txtUrl->text().contains( QLatin1String(
"xmlrpc.php"), Qt::CaseInsensitive ) ) {
147 d->ui.comboApi->setCurrentIndex( 3 );
151 if ( d->ui.txtUrl->text().contains( QLatin1String(
"blogspot"), Qt::CaseInsensitive ) ) {
152 d->ui.comboApi->setCurrentIndex( 4 );
156 if ( d->ui.txtUrl->text().contains( QLatin1String(
"wordpress"), Qt::CaseInsensitive ) ) {
157 d->ui.comboApi->setCurrentIndex( 3 );
159 textUrl = d->ui.txtUrl->text();
160 while (textUrl.endsWith(QLatin1Char(
'/'))) {
161 textUrl.remove(textUrl.length()-1, 1);
163 d->ui.txtUrl->setText( textUrl + QLatin1String(
"/xmlrpc.php") );
167 if ( d->ui.txtUrl->text().contains( QLatin1String(
"livejournal"), Qt::CaseInsensitive ) ) {
168 d->ui.comboApi->setCurrentIndex( 0 );
169 d->tmpBlogUrl = d->ui.txtUrl->text();
170 d->ui.txtUrl->setText( QLatin1String(
"http://www.livejournal.com/interface/blogger/") );
171 d->ui.txtId->setText( d->ui.txtUser->text() );
172 d->ui.txtTitle->setText( d->ui.txtUser->text() );
176 kDebug() <<
"Trying to guess API type by Homepage contents";
177 KIO::StoredTransferJob *httpGetJob = KIO::storedGet( d->ui.txtUrl->text() , KIO::NoReload, KIO::HideProgressInfo );
178 connect( httpGetJob, SIGNAL(result(KJob*)),
this, SLOT(
gotHtml(KJob*)) );
179 d->mFetchAPITimer =
new QTimer(
this );
180 d->mFetchAPITimer->setSingleShot(
true );
182 d->mFetchAPITimer->start(
TIMEOUT );
189 if ( job->error() ) {
190 kDebug() <<
"Auto configuration failed! Error: " << job->errorString();
192 KMessageBox::sorry(
this, i18n(
"Auto configuration failed. You have to set Blog API on Advanced tab manually."));
195 QString httpData( QString::fromUtf8(static_cast<KIO::StoredTransferJob*>( job )->data() ) );
198 QRegExp rxGData( QString::fromLatin1(
"content='blogger' name='generator'" ) );
199 if ( rxGData.indexIn( httpData ) != -1 ) {
200 kDebug() <<
"content='blogger' name='generator' matched";
201 d->mFetchAPITimer->deleteLater();
202 d->ui.comboApi->setCurrentIndex( 4 );
203 QRegExp rxBlogId( QString::fromLatin1(
"BlogID=(\\d+)" ) );
204 d->ui.txtId->setText( rxBlogId.cap( 1 ) );
209 QRegExp rxLiveJournal( QString::fromLatin1(
"rel=\"openid.server\" href=\"http://www.livejournal.com/openid/server.bml\"" ) );
210 if ( rxLiveJournal.indexIn( httpData ) != -1 ) {
211 kDebug() <<
" rel=\"openid.server\" href=\"http://www.livejournal.com/openid/server.bml\" matched";
212 d->mFetchAPITimer->deleteLater();
213 d->ui.comboApi->setCurrentIndex( 0 );
214 d->ui.txtUrl->setText( QLatin1String(
"http://www.liverjournal.com/interface/blogger/") );
215 d->ui.txtId->setText( d->ui.txtUser->text() );
221 QRegExp rxWordpress( QString::fromLatin1(
"name=\"generator\" content=\"WordPress" ) );
222 if ( rxWordpress.indexIn( httpData ) != -1 ) {
223 kDebug() <<
"name=\"generator\" content=\"WordPress matched";
224 d->mFetchAPITimer->deleteLater();
225 d->ui.comboApi->setCurrentIndex( 3 );
227 textUrl = d->ui.txtUrl->text();
228 while (textUrl.endsWith(QLatin1Char(
'/'))) {
229 textUrl.remove(textUrl.length()-1, 1);
231 d->ui.txtUrl->setText( textUrl + QLatin1String(
"/xmlrpc.php") );
237 textUrl = d->ui.txtUrl->text();
238 while (textUrl.endsWith(QLatin1Char(
'/'))) {
239 textUrl.remove(textUrl.length()-1, 1);
241 KIO::StoredTransferJob *testXmlRpcJob = KIO::storedGet( QString::fromLatin1(
"%1/xmlrpc.php").arg(textUrl),
242 KIO::NoReload, KIO::HideProgressInfo );
244 connect( testXmlRpcJob, SIGNAL(result(KJob*)),
this, SLOT(
gotXmlRpcTest(KJob*)) );
250 d->mFetchAPITimer->deleteLater();
253 if ( job->error() ) {
254 kDebug() <<
"Auto configuration failed! Error: " << job->errorString();
256 KMessageBox::sorry(
this, i18n(
"Auto configuration failed. You have to set Blog API on Advanced tab manually."));
259 KMessageBox::information(
this, i18n(
"The program could not guess the API of your blog, "
260 "but has found an XMLRPC interface and is trying to use it.\n"
261 "The MovableType API is assumed for now; choose another API if you know the server supports it."));
262 d->ui.comboApi->setCurrentIndex( 2 );
263 QString textUrl = d->ui.txtUrl->text();
264 while (textUrl.endsWith(QLatin1Char(
'/'))) {
265 textUrl.remove(textUrl.length()-1, 1);
267 d->ui.txtUrl->setText( textUrl + QLatin1String(
"/xmlrpc.php") );
273 switch ( d->ui.comboApi->currentIndex() ) {
279 KBlog::Blogger1 *blog =
new KBlog::Blogger1( KUrl( d->ui.txtUrl->text() ),
this );
281 blog->setUsername( d->ui.txtUser->text() );
282 blog->setPassword( d->ui.txtPass->text() );
283 connect( blog , SIGNAL(listedBlogs(QList<QMap<QString,QString> >)),
285 d->mFetchBlogIdTimer =
new QTimer(
this );
286 d->mFetchBlogIdTimer->setSingleShot(
true );
288 d->mFetchBlogIdTimer->start(
TIMEOUT );
294 KBlog::GData* blog =
new KBlog::GData( d->ui.txtUrl->text() , this );
296 blog->setUsername( d->ui.txtUser->text() );
297 blog->setPassword( d->ui.txtPass->text() );
300 blog->fetchProfileId();
301 d->mFetchProfileIdTimer =
new QTimer(
this );
302 d->mFetchProfileIdTimer->setSingleShot(
true );
304 d->mFetchProfileIdTimer->start(
TIMEOUT );
308 kDebug()<<
"Unknown API";
312 connect( d->mBlog, SIGNAL(error(KBlog::Blog::ErrorType,QString)),
314 d->ui.txtId->setText( i18n(
"Please wait..." ) );
315 d->ui.txtId->setEnabled(
false );
316 showWaitWidget( i18n(
"Fetching Blog Id..." ) );
322 if ( d->mFetchBlogIdTimer ) {
323 d->mFetchBlogIdTimer->stop();
325 if( d->mFetchProfileIdTimer ) {
326 d->mFetchProfileIdTimer->stop();
328 d->ui.txtId->setText( QString() );
329 d->ui.txtId->setEnabled(
true );
331 KMessageBox::error(
this, i18n(
"Fetching the blog id timed out. Check your Internet connection,"
332 "and your homepage URL, username or password.\nNote that the URL has to contain \"http://\"\n"
333 "If you are using a self-hosted Wordpress blog, you have to enable Remote Publishing in its configuration." ) );
339 d->mFetchAPITimer->deleteLater();
340 d->mFetchAPITimer = 0;
342 d->ui.txtId->setEnabled(
true );
343 d->ui.txtId->setText( QString() );
344 KMessageBox::sorry(
this, i18n(
"The API guess function has failed, "
345 "please check your Internet connection. Otherwise, you have to set the API type manually on the Advanced tab." ),
346 i18n(
"Auto Configuration Failed" ) );
351 kDebug() <<
" ErrorType: " << type;
352 d->ui.txtId->setEnabled(
true );
353 d->ui.txtId->setText( QString() );
355 KMessageBox::detailedError(
this, i18n(
"Fetching BlogID Failed.\nPlease check your Internet connection." ), errorMsg );
360 if( d->mFetchBlogIdTimer ) {
361 d->mFetchBlogIdTimer->deleteLater();
362 d->mFetchBlogIdTimer = 0;
365 QString blogId, blogName, blogUrl, apiUrl;
366 const int listCount(list.count());
367 if ( listCount > 1 ) {
368 kDebug() <<
"User has more than ONE blog!";
370 QTableWidget *blogsList =
new QTableWidget(blogsDialog);
371 blogsList->setSelectionBehavior(QAbstractItemView::SelectRows);
372 QList< QMap<QString,QString> >::const_iterator it = list.constBegin();
373 QList< QMap<QString,QString> >::const_iterator endIt = list.constEnd();
375 blogsList->setColumnCount(4);
377 headers<<i18n(
"Title")<<i18n(
"Url");
379 blogsList->setHorizontalHeaderLabels(headers);
380 blogsList->setColumnHidden(2,
true);
381 blogsList->setColumnHidden(3,
true);
382 for(;it != endIt; ++it){
383 kDebug()<<it->value(QLatin1String(
"title"));
384 blogsList->insertRow(i);
385 blogsList->setCellWidget(i, 0,
new QLabel( it->value(QLatin1String(
"title"))) );
386 blogsList->setCellWidget(i, 1,
new QLabel( it->value(QLatin1String(
"url"))) );
387 blogsList->setCellWidget(i, 2,
new QLabel( it->value(QLatin1String(
"id"))) );
388 blogsList->setCellWidget(i, 3,
new QLabel( it->value(QLatin1String(
"apiUrl"))) );
391 blogsDialog->setMainWidget(blogsList);
392 blogsDialog->setWindowTitle( i18n(
"Which blog?") );
393 if( blogsDialog->exec() ) {
394 int row = blogsList->currentRow();
399 blogId = qobject_cast<QLabel*>( blogsList->cellWidget(row, 2) )->text();
400 blogName = qobject_cast<QLabel*>( blogsList->cellWidget(row, 0) )->text();
401 blogUrl = qobject_cast<QLabel*>( blogsList->cellWidget(row, 1) )->text();
402 apiUrl = qobject_cast<QLabel*>( blogsList->cellWidget(row, 3) )->text();
408 }
else if (listCount > 0) {
409 blogId = list.constBegin()->value(QLatin1String(
"id"));
410 blogName = list.constBegin()->value(QLatin1String(
"title"));
411 blogUrl = list.constBegin()->value(QLatin1String(
"url"));
412 apiUrl = list.constBegin()->value(QLatin1String(
"apiUrl"));
414 KMessageBox::sorry(
this, i18n(
"Sorry, No blog found with the specified account info."));
417 d->ui.txtId->setText( blogId );
418 d->ui.txtTitle->setText( blogName );
419 d->ui.txtId->setEnabled(
true );
420 d->ui.btnFetch->setEnabled(
true );
421 d->ui.btnAutoConf->setEnabled(
true );
423 if( !apiUrl.isEmpty() ){
424 d->ui.txtUrl->setText( apiUrl );
426 apiUrl = d->ui.txtUrl->text();
428 if( !blogUrl.isEmpty() ) {
429 d->bBlog->setBlogUrl( blogUrl );
431 if(d->tmpBlogUrl.isEmpty())
432 d->bBlog->setBlogUrl( apiUrl );
434 d->bBlog->setBlogUrl( d->tmpBlogUrl );
437 d->bBlog->setUrl( QUrl( apiUrl ) );
438 d->bBlog->setUsername( d->ui.txtUser->text() );
439 d->bBlog->setPassword( d->ui.txtPass->text() );
440 d->bBlog->setBlogId( blogId );
441 d->bBlog->setTitle( blogName );
448 d->mFetchProfileIdTimer->deleteLater();
449 d->mFetchProfileIdTimer = 0;
450 KBlog::GData* blog =
static_cast<KBlog::GData*
>( d->mBlog );
451 connect( blog, SIGNAL(listedBlogs(QList<QMap<QString,QString> >)),
453 connect( blog, SIGNAL(error(KBlog::Blog::ErrorType,QString)),
455 d->mFetchBlogIdTimer =
new QTimer(
this );
456 d->mFetchBlogIdTimer->setSingleShot(
true );
458 d->mFetchBlogIdTimer->start(
TIMEOUT );
464 const bool check = !txt.isEmpty();
465 enableButtonOk( check );
466 d->ui.txtTitle->setEnabled( check );
472 if(isButtonEnabled(KDialog::Ok)){
473 setButtonFocus(KDialog::Ok);
475 if(d->mainW->currentIndex()==0){
476 if(d->ui.btnAutoConf->isEnabled()){
493 const QString yesStyle = QLatin1String(
"QLabel{color: green;}");
494 const QString yesText = i18nc(
"Supported feature or Not",
"Yes" );
495 const QString noStyle = QLatin1String(
"QLabel{color: red;}");
496 const QString noText = i18nc(
"Supported feature or Not",
"No, API does not support it" );
497 const QString notYetText = i18nc(
"Supported feature or Not",
"No, Blogilo does not yet support it" );
499 d->ui.featureCreatePost->setText( yesText );
500 d->ui.featureCreatePost->setStyleSheet( yesStyle );
501 d->ui.featureRemovePost->setText( yesText );
502 d->ui.featureRemovePost->setStyleSheet( yesStyle );
503 d->ui.featurRecentPosts->setText( yesText );
504 d->ui.featurRecentPosts->setStyleSheet( yesStyle );
506 d->ui.featureCreateCategory->setStyleSheet( noStyle );
510 d->ui.featureUploadMedia->setText( noText );
511 d->ui.featureUploadMedia->setStyleSheet( noStyle );
512 d->ui.featureCategories->setText( noText );
513 d->ui.featureCategories->setStyleSheet( noStyle );
514 d->ui.featureMultipagedPosts->setText( noText );
515 d->ui.featureMultipagedPosts->setStyleSheet( noStyle );
516 d->ui.featureCreateCategory->setText( noText );
517 d->ui.featureTags->setText( noText );
518 d->ui.featureTags->setStyleSheet( noStyle );
521 d->ui.featureUploadMedia->setText( yesText );
522 d->ui.featureUploadMedia->setStyleSheet( yesStyle );
523 d->ui.featureCategories->setText( noText );
524 d->ui.featureCategories->setStyleSheet( noStyle );
525 d->ui.featureMultipagedPosts->setText( noText );
526 d->ui.featureMultipagedPosts->setStyleSheet( noStyle );
527 d->ui.featureCreateCategory->setText( noText );
528 d->ui.featureTags->setText( noText );
529 d->ui.featureTags->setStyleSheet( noStyle );
532 d->ui.featureUploadMedia->setText( yesText );
533 d->ui.featureUploadMedia->setStyleSheet( yesStyle );
534 d->ui.featureCategories->setText( yesText );
535 d->ui.featureCategories->setStyleSheet( yesStyle );
536 d->ui.featureMultipagedPosts->setText( yesText );
537 d->ui.featureMultipagedPosts->setStyleSheet( yesStyle );
538 d->ui.featureCreateCategory->setText( noText );
539 d->ui.featureTags->setText( yesText );
540 d->ui.featureTags->setStyleSheet( yesStyle );
543 d->ui.featureUploadMedia->setText( yesText );
544 d->ui.featureUploadMedia->setStyleSheet( yesStyle );
545 d->ui.featureCategories->setText( yesText );
546 d->ui.featureCategories->setStyleSheet( yesStyle );
547 d->ui.featureMultipagedPosts->setText( yesText );
548 d->ui.featureMultipagedPosts->setStyleSheet( yesStyle );
549 d->ui.featureCreateCategory->setText( notYetText );
550 d->ui.featureTags->setText( yesText );
551 d->ui.featureTags->setStyleSheet( yesStyle );
554 d->ui.featureUploadMedia->setText( noText );
555 d->ui.featureUploadMedia->setStyleSheet( noStyle );
556 d->ui.featureCategories->setText( noText );
557 d->ui.featureCategories->setStyleSheet( noStyle );
558 d->ui.featureMultipagedPosts->setText( noText );
559 d->ui.featureMultipagedPosts->setStyleSheet( noStyle );
560 d->ui.featureCreateCategory->setText( noText );
561 d->ui.featureTags->setText( yesText );
562 d->ui.featureTags->setStyleSheet( yesStyle );
576 if ( button == KDialog::Ok ) {
577 if ( d->bBlog->blogid().isEmpty() && d->ui.txtId->text().isEmpty() ) {
578 KMessageBox::sorry(
this, i18n(
"Blog ID has not yet been retrieved.\n"
579 "You can fetch the blog ID by clicking on \"Auto Configure\" or the \"Fetch ID\" button; otherwise, you have "
580 "to insert your blog ID manually." )
585 d->bBlog->setDirection(( Qt::LayoutDirection )d->ui.comboDir->currentIndex() );
586 d->bBlog->setTitle( d->ui.txtTitle->text() );
587 d->bBlog->setPassword( d->ui.txtPass->text() );
588 d->bBlog->setUsername( d->ui.txtUser->text() );
589 d->bBlog->setBlogId( d->ui.txtId->text() );
590 d->bBlog->setUrl( KUrl( d->ui.txtUrl->text() ) );
591 if(d->bBlog->blogUrl().isEmpty())
592 d->bBlog->setBlogUrl(d->ui.txtUrl->text());
594 if ( d->isNewBlog ) {
596 d->bBlog->setId( blog_id );
597 if ( blog_id != -1 ) {
598 kDebug() <<
"Emitting sigBlogAdded() ...";
601 kDebug() <<
"Cannot add blog";
605 kDebug() <<
"Emitting sigBlogEdited() ...";
608 kDebug() <<
"Cannot edit blog with id " << d->bBlog->id();
613 KDialog::slotButtonClicked( button );
616 void AddEditBlog::showWaitWidget( QString text )
618 d->ui.btnAutoConf->setEnabled(
false );
619 d->ui.btnFetch->setEnabled(
false );
622 d->wait->setWindowModality( Qt::WindowModal );
623 d->wait->setBusyState();
625 d->wait->setText( text );
629 void AddEditBlog::hideWaitWidget()
631 d->ui.btnAutoConf->setEnabled(
true );
632 d->ui.btnFetch->setEnabled(
true );
634 d->wait->deleteLater();
638 #include "addeditblog.moc"
void slotComboApiChanged(int index)
void fetchedProfileId(const QString &)
void handleFetchError(KBlog::Blog::ErrorType type, const QString &errorMsg)
static DBMan * self()
Retrieve the instance of DataBase Manager.
BilboBlog * blog(int blog_id)
QString as Title, and int as blog_id.
void handleFetchIDTimeout()
void setSupportedFeatures(BilboBlog::ApiType api)
AddEditBlog(int blog_id, QWidget *parent=0, Qt::WindowFlags flags=0)
void gotXmlRpcTest(KJob *job)
void sigBlogEdited(const BilboBlog &)
int addBlog(const BilboBlog &blog)
END.
void enableOkButton(const QString &)
void handleFetchAPITimeout()
void fetchedBlogId(const QList< QMap< QString, QString > > &list)
void sigBlogAdded(const BilboBlog &)
virtual void slotButtonClicked(int button)