Logo Search packages:      
Sourcecode: kblogger-kde4 version File versions  Download package

composer.cpp

/***************************************************************************

   Copyright (C) 2005-2007 by Christian Weilbach <christian_weilbach@web.de>
   Copyright (C) 2007 Antonio Aloisio <gnuton@gnuton.org>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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 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 "composer.h"

#include <QCheckBox>
#include <QRegExp>
#include <QLabel>
#include <QLayout>
#include <QFileInfo>
#include <QValidator>
#include <Q3CString>
#include <QPixmap>
#include <QListWidget>
#include <QFile>

#include <klineedit.h>
#include <klocale.h>
#include <ktextedit.h>
#include <kcombobox.h>
#include <kpushbutton.h>
#include <kdatetimewidget.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include "kbloggerconfig.h"
#include "backend.h"
//#include "backendmanager.h" //FIXME KBloggerPost
#include "kbloggerpost.h"
#include "postslist.h"
#include "composereditor.h"
#include "itemsmanager.h"
#include "kbloggerblog.h"
#include "blogchooser.h"
#include "visualeditor.h"

#define MAGIC_KEY 0xA1B2C3D4
#define VERSION 001
#define DIR_TO_SAVE_CATEGORIES "categories/"

namespace KBlogger
{

Composer::Composer ( KBloggerPost* post, QWidget* parent):
        QDialog(parent)
{
    kDebug();
    mPostToModify = post;
    initialize();
    loadPostSlot (post);
    connect ( buttonBox, SIGNAL( accepted() ), this, SLOT( enqueueSlot() ) );
    connect ( buttonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
}

Composer::Composer (const QString& blogname, QWidget* parent):
        QDialog(parent)
{
    kDebug();
    mPostToModify = 0;
    initialize();
    setBlogname(blogname);
    timeStampKDateTime->setDateTime ( QDateTime::currentDateTime() );
    connect ( buttonBox, SIGNAL( accepted() ), this, SLOT( enqueueSlot() ) );
    connect ( buttonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
}


Composer::~Composer()
{
    kDebug();
    //TODO Stop 'Fetch Categories' if it's running!
}

void Composer::setBlogname(const QString& blogname)
{
    kDebug();
    if ( blogname.isEmpty() ) return;
    for ( int i = 0; mBlogChooser->blogCombo->count(); ++i ) {
        if ( blogname == mBlogChooser->blogCombo->itemText(i) ) {
            mBlogChooser->blogCombo->setCurrentIndex(i);
            break;
        }
    }
}

QString Composer::blogname()
{
    kDebug();
    if ( !mBlogChooser->blogCombo->currentIndex() )
        return QString();
    else
        return mBlogChooser->blogCombo->currentText();
}

void Composer::initialize ()
{
    kDebug();
    setupUi( this );
    mBackend = Backend::self();
    mItemsManager = ItemsManager::self();

    setAttribute( Qt::WA_DeleteOnClose ); //Destroy on close

    //Add Blog Chooser
    mBlogChooser = new BlogChooser( blogGroupBox );
    blogGroupBox->layout()->addWidget( mBlogChooser );

    //Add Editor: NOTE Editor require BlogChooser!
    mEditor = new ComposerEditor(this, editorFrame);
    editorFrame->layout()->addWidget(mEditor);

    //Connections
    connect ( refreshCategoriesButton, SIGNAL( clicked() ),
              this, SLOT( slotRefreshCateroriesFromServer() ) );
    connect ( mBlogChooser->blogCombo, SIGNAL( currentIndexChanged(const QString& ) ),
              this, SLOT( updateBlogOptions(const QString& ) ) );
    connect( CategoryComboBox, SIGNAL( currentIndexChanged(const QString& ) ),
             this , SLOT( hideFirstCategory( const QString&)));

}

void Composer::loadPostSlot ( KBloggerPost* post )
{
    kDebug();
    if (!post) return;

    //MODIFY POST
    TitleLineEdit->setText ( post->title() );
    //  CategoryComboBox->setItemText(-1, post.category() );
    mEditor->visualTextEditor->setHtml (
        mEditor->htmlToRichtext(post->content() ));

    kDebug() << "Post content" << endl
    << post->content() << endl;
    timeStampKDateTime->setDateTime ( post->creationDateTime().dateTime () );
    setBlogname ( post->getBlogName() );

    commentCheckBox->setChecked( post->isCommentAllowed() );
    trackbackCheckBox->setChecked( post->isTrackBackAllowed());
}

bool Composer::loadCategories(const QString& blogname)
{
    kDebug();

    //blogname test
    if (blogname.isEmpty()) {
        kError() << "blogname is empty" << endl;
        return false;
    }

    //Setting up filename
    QString filename;
    filename = DIR_TO_SAVE_CATEGORIES + blogname;
    if (filename.isEmpty()) {
        kDebug() << "\tfilename is empty" << endl;
        return false;
    }
    QString fileToOpen = KStandardDirs::locateLocal("appdata", filename , true);
    kDebug() << "opening file: " << fileToOpen << endl;
    if (fileToOpen.isEmpty()) {
        return false;
    }
    QFile file( fileToOpen );
    file.open(QIODevice::ReadOnly);
    QDataStream in(&file);

    // Read and check the header
    quint32 magic;
    in >> magic;
    if (magic != MAGIC_KEY) {
        kDebug() << "BAD MAGIC KEY, Trying to retrieve categories from " << blogname << endl;
        return false;
    }

    // Read the version
    qint32 version;
    in >> version;
    if (version != VERSION) {
        kDebug() << "BAD VERSION" << endl;
        getCategories(blogname);
        return false;
    }

    //Read the number of categories
    qint32 categoriesNumber = -1;
    in >> categoriesNumber;

    if ( categoriesNumber == -1 ) {
        //file is empty
        file.close();
        return false;
    } else {
        //Read data
        QString name, description, htmlUrl, rssUrl;
        QListWidgetItem *categoriesListItem;
        for (int i = 0; i < categoriesNumber; ++i) {
            in >> name;
            in >> description;
            in >> htmlUrl;
            in >> rssUrl;
            categoriesListItem = new QListWidgetItem(name, categoriesList);
            categoriesListItem->setCheckState(Qt::Unchecked);

            CategoryComboBox->insertItem (0, name );
        }

        mBackend->showStatusBarMessage(i18n("Loaded %1 categories...", categoriesNumber));
        file.close();
    }
    return true;
}

void Composer::getCategories(const QString& blogname)
{
    kDebug();
    mBackend->showStatusBarMessage(i18n("Fetching List of Categories..."));
    connect (mBackend,
             SIGNAL(categoryInfoRetrieved( const QList<QMap<QString, QString> >&)),
             this,
             SLOT(slotCategoryInfoRetrieved( const QList<QMap<QString, QString> >&)));
    mBackend->listCategories(blogname, this);
}

void Composer::slotRefreshCateroriesFromServer()
{
    kDebug();
    updateBlogOptions(mBlogChooser->blogCombo->currentText(), true);
}

void Composer::hideFirstCategory( const QString& categoryToHide )
{
    kDebug();
    QListWidgetItem *category;
    for (int row = 0; row < categoriesList->count(); ++row) {
        category = categoriesList->item(row);
        if ( categoryToHide == category->text() ) {
            category->setHidden(true);
            category->setCheckState(Qt::Unchecked);
        } else {
            category->setHidden(false);
        }
    }
}

void Composer::saveCategories(const QString& blogname, const QList< QMap<QString, QString> >* categories)
{
    kDebug();

    //blogname test
    if (blogname.isEmpty()) {
        kError() << "blogname is empty" << endl;
        return;
    }

    //Setting up filename
    QString filename;
    filename = DIR_TO_SAVE_CATEGORIES + blogname;
    if (filename.isEmpty()) {
        kDebug() << "\tfilename is empty" << endl;
        return;
    }
    QString fileToSave = KStandardDirs::locateLocal("appdata", filename , true);
    kDebug() << "\tsaving file: " << fileToSave << endl;

    //
    //TODO qApp->processEvents(QEventLoop::ExcludeUserInputEvents);

    //Open file to write and setting up Datastream
    QFile file( fileToSave );
    file.open(QIODevice::WriteOnly);
    QDataStream out(&file);   // we will serialize the data into the file

    // Write the header
    out << (quint32)MAGIC_KEY; //"magic number"
    out << (qint32)VERSION; //binary file version

    out.setVersion(QDataStream::Qt_4_0);

    //write the number of categories that will be stored;
    out << categories->count();

    //write categories data;
    const QMap<QString, QString> *category;
    for ( int i = 0; i < categories->count(); ++i) {
        category = &(categories->at(i));
        if (!category) {
            kError() << "category is NULL" << endl;
            break;
        }
        out << category->value("name");
        out << category->value("description"); //TODO UNUSED
        out << category->value("htmlUrl"); //TODO UNUSED
        out <<  category->value("rssUrl"); //TODO UNUSED
    }
    file.close();
}

void Composer::enqueueSlot()
{
    kDebug();

    //TEST - No Post Content
    if ( mEditor->visualTextEditor->toPlainText().isEmpty() ) {
        close();
        return;
    }

    //TEST - Blog doesn't selected
    if ( !mBlogChooser->blogCombo->currentIndex() ) {
        KMessageBox::information(this, i18n("Please select a blog first"));
        return;
    }

    //TEST - Post Title is Empty
    if ( !TitleLineEdit->isHidden() && TitleLineEdit->text().isEmpty() ) {
        KMessageBox::sorry ( this, i18n ( "Please fill the Title field." ) );
        return;
    }

    //Give a title to Untitled post (Needed by Blogger v.1 API)
    if (TitleLineEdit->isReadOnly()) { //Blogger v.1 fix
        QString title = i18n("Untitled post of %1",
                             KDateTime::currentUtcDateTime().toString()) ;
        TitleLineEdit->setText(title);
    }


    mBackend->showStatusBarMessage(i18n("Post enqueued in the Local Draft."));

    //Post content contains HTML code of HtmlEditor.
    mEditor->syncEditors(1); // 1 = HtmlEditor

    QStringList categories;
    categories << CategoryComboBox->currentText();
    for ( int i = 0; i < categoriesList->count(); ++i) {
        QListWidgetItem * mPost = categoriesList->item(i);
        if (mPost->checkState() == Qt::Checked)
            categories <<  mPost->text();
    }

    //Settings up & create post
    KBloggerPost *post;
    post = new KBloggerPost( mBlogChooser->blogCombo->currentText(),
                             TitleLineEdit->text(),
                             mEditor->ContentTextHtmlEditor->toPlainText(),
                             categories,
                             !publishCheckBox->isChecked(),
                             static_cast<KDateTime>(timeStampKDateTime->dateTime()) );
    if (mPostToModify) {
        post->setPostId( mPostToModify->postId() );
    }

    post->setCommentAllowed(  commentCheckBox->isChecked() );
    post->setTrackBackAllowed( trackbackCheckBox->isChecked() );
    post->setStatus(KBlog::BlogPost::New);

    //mEditor->ContentTextHtmlEditor->clear();
    //mEditor->visualTextEditor->clear();
    //TitleLineEdit->clear();

    if ( mPostToModify ) {
        //Modify Post
        PostsList *containerWidget = 0;
        containerWidget = qobject_cast<PostsList*> (mPostToModify->container());
        if ( containerWidget ) {
            containerWidget->removePost(mPostToModify);
        }
    }
    mItemsManager->createNewPost(post);
    done(0);
}

void Composer::slotCategoryInfoRetrieved( const QList< QMap<QString, QString> >& categories)
{
    kDebug();

    mBackend->disconnect (
        SIGNAL(categoryInfoRetrieved( const QList<QMap<QString, QString> >&))
    );

    fillCategoriesWidgets(&categories);

    mBackend->showStatusBarMessage(i18n("Retrieved %1 categories from your blog...", categories.count()));

    //Saving categories;
    saveCategories(mBlogChooser->blogCombo->currentText(), &categories);
}

void Composer::fillCategoriesWidgets(const QList< QMap<QString, QString> >* categories)
{
    kDebug();
    QString name, description, htmlUrl, rssUrl;
    const QMap<QString, QString> *category;
    QListWidgetItem *categoriesListItem;
    for ( int i = 0; i < categories->count(); ++i) {
        category = &(categories->at(i));

        name = category->value("name");
        description = category->value("description"); //TODO UNUSED
        htmlUrl = category->value("htmlUrl"); //TODO UNUSED
        rssUrl = category->value("rssUrl"); //TODO UNUSED

        categoriesListItem = new QListWidgetItem(name, categoriesList);
        categoriesListItem->setCheckState(Qt::Unchecked);

        CategoryComboBox->insertItem (0, name );

    }
};

void Composer::updateBlogOptions(const QString& blogname, bool fetchCategoriesListFromServer)
{
    kDebug();
    if (!mBackend) return;
    if (!mBlogChooser->blogCombo->currentIndex()) return;

    //Clear
    CategoryComboBox->clear();
    categoriesList->clear();

    //Run fetch categories list.
    kDebug() << "BLOGNAME" << blogname
    << "USED API=" << mBackend->getKbloggerBlog(blogname).api();
    switch ( mBackend->getKbloggerBlog(blogname).api() ) {
    case Backend::BLOGGER_API: {
        // HACK for LiveJournal, if the url has livejournal in it, don't hide the title but hide publish
        if( mBackend->getKbloggerBlog(blogname).url().url().indexOf( "livejournal" ) == -1 ) {
            TitleLineEdit->hide(); 
            TitleLabel->hide();
            publishCheckBox->show();
        }
        else publishCheckBox->hide();

         // BLOGGER_API is impossible to do styling 
        mEditor->getStyleButton->hide();

        // TODO group that stuff in one widget
        CategoriesLabel->hide();
        CategoryComboBox->hide();
        label_2->hide();
        categoriesList->hide();
        line_3->hide();
        refreshCategoriesButton->hide();

        timeStampKDateTime->setEnabled ( false );
        categoriesList->setEnabled( false );
        refreshCategoriesButton->setEnabled( false );
        commentCheckBox->hide();
        trackbackCheckBox->hide();
        mBackend->showStatusBarMessage(i18n("Categories are not supported in Blogger API 1.0."));

        mEditor->enableMedia(false);
    }
    break;
    case Backend::METAWEBLOG_API: {
        TitleLineEdit->show();
        TitleLabel->show();

        CategoriesLabel->show();
        CategoryComboBox->show();
        label_2->show();
        categoriesList->show();
        line_3->show();
        refreshCategoriesButton->show();

        timeStampKDateTime->setEnabled ( true );
        categoriesList->setEnabled( true );
        refreshCategoriesButton->setEnabled( true );
        if (fetchCategoriesListFromServer)
            getCategories(blogname);
        else
            if ( !loadCategories(blogname))
                getCategories(blogname);
        publishCheckBox->show();
        commentCheckBox->show();
        trackbackCheckBox->hide();
        mBackend->showStatusBarMessage(i18n("You are using MetaWeblog API"));

        mEditor->enableMedia(true);
    }
    break;
    case Backend::MOVABLETYPE_API: {
        TitleLineEdit->show();
        TitleLabel->show();

        CategoriesLabel->show();
        CategoryComboBox->show();
        label_2->show();
        categoriesList->show();
        line_3->show();
        refreshCategoriesButton->show();

        timeStampKDateTime->setEnabled ( true );
        categoriesList->setEnabled( true );
        refreshCategoriesButton->setEnabled( true );
        if (fetchCategoriesListFromServer)
            getCategories(blogname);
        else
            if ( !loadCategories(blogname))
                getCategories(blogname);
        publishCheckBox->show();
        commentCheckBox->show();
        trackbackCheckBox->show();
        mBackend->showStatusBarMessage(i18n("You are using MovableType API"));

        mEditor->enableMedia(true);
    }
    break;
    case Backend::WORDPRESSBUGGY_API: {
        TitleLineEdit->show();
        TitleLabel->show();

        CategoriesLabel->show();
        CategoryComboBox->show();
        label_2->show();
        categoriesList->show();
        line_3->show();
        refreshCategoriesButton->show();

        timeStampKDateTime->setEnabled ( true );
        categoriesList->setEnabled( true );
        refreshCategoriesButton->setEnabled( true );
        if (fetchCategoriesListFromServer)
            getCategories(blogname);
        else
            if ( !loadCategories(blogname))
                getCategories(blogname);
        publishCheckBox->show();
        commentCheckBox->show();
        trackbackCheckBox->show();
        mBackend->showStatusBarMessage(i18n("You are using MT for Wordpress API"));

        mEditor->enableMedia(true);
    }
    break;
    case Backend::GDATA_API: {
        TitleLineEdit->show();
        TitleLabel->show();

        CategoriesLabel->hide();
        CategoryComboBox->hide();
        label_2->hide();
        categoriesList->hide();
        line_3->hide();
        refreshCategoriesButton->hide();

        timeStampKDateTime->setEnabled ( true );
        categoriesList->setEnabled( true );
        refreshCategoriesButton->setEnabled( true );
        publishCheckBox->show();
        commentCheckBox->show();
        trackbackCheckBox->show();
        mBackend->showStatusBarMessage(i18n("You are using GData API"));

        mEditor->enableMedia(false);
//TODO        mBackend->listCategories(blogname);
    }

    break;
    default:
        kError() << "API not supported." << endl;
        return;
    }

}

} //namespace

#include "composer.moc"

Generated by  Doxygen 1.6.0   Back to index