Blokkal
an Extendable KDE Blogging Client
SourceForge.net Logo

categorymanager.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2006 - 2008 by Martin Mueller                           *
00003  *   orvio@orvio.de                                                        *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "categorymanager.h"
00021 #include "categorymanager.moc"
00022 
00023 #include "../blokkalaccount.h"
00024 
00025 #include <kdebug.h>
00026 
00027 #include <QDomElement>
00028 #include <QFile>
00029 
00030 #include <QStringList>
00031 
00032 //---------------
00033 //CategoryManager
00034 //---------------
00035 class Blokkal::Io::CategoryManager::Private {
00036 public:
00037         Private( Blokkal::Account * account ) :
00038         account( account ),
00039         categoryMap( QMap<QString, CategoryList >() ),
00040         categoryDocument( QDomDocument( "Categories" ) )
00041         {
00042                 categoryDocument.appendChild( categoryDocument.createElement( "blogs" ) );
00043         }
00044 
00045         QDomElement categoryNode( const QString & blogId, const QString & categoryId ) {
00046                 QDomNode currentBlogNode = categoryDocument.firstChild().namedItem( "blog" );
00047                 QDomElement currentBlogElement;
00048                 while( !currentBlogNode.isNull() ) {
00049                         if( currentBlogNode.isElement() && currentBlogNode.nodeName() == "blog" ) {
00050                                 currentBlogElement = currentBlogNode.toElement();
00051                                 if( currentBlogElement.attribute( "name" ) == blogId ) {
00052                                         QDomNode currentCategoryNode = currentBlogNode.namedItem( "category" );
00053                                         QDomElement currentCategoryElement;
00054                                         while( !currentCategoryNode.isNull() ) {
00055                                                 if( currentCategoryNode.isElement() && currentCategoryNode.nodeName() == "category" ) {
00056                                                         currentCategoryElement = currentCategoryNode.toElement();
00057                                                         if( currentCategoryElement.attribute( "id" ) == categoryId ) {
00058                                                                 return currentCategoryNode.toElement();
00059                                                         }
00060                                                 }
00061                                                 currentCategoryNode = currentCategoryNode.nextSibling();
00062                                         }
00063                                         //insert category node
00064                                         currentCategoryElement = categoryDocument.createElement( "category" );
00065                                         currentCategoryElement.setAttribute( "id", categoryId );
00066                                         currentBlogNode.appendChild( currentCategoryElement );
00067                                         return currentCategoryElement;
00068                                 }
00069                                 
00070                         }
00071                         currentBlogNode = currentBlogNode.nextSibling();
00072                 }
00073 
00074                 //insert blog node
00075                 currentBlogElement = categoryDocument.createElement( "blog" );
00076                 currentBlogElement.setAttribute( "name", blogId );
00077                 currentBlogNode = currentBlogElement;
00078                 categoryDocument.firstChild().appendChild( currentBlogNode );
00079                 
00080                 //insert category node
00081                 QDomElement currentCategoryElement = categoryDocument.createElement( "category" );
00082                 currentCategoryElement.setAttribute( "id", categoryId );
00083                 currentBlogNode.appendChild( currentCategoryElement );
00084                 return currentCategoryElement;
00085         }
00086 
00087         Blokkal::Account * const account;
00088         
00089         QMap<QString, CategoryList > categoryMap;
00090 
00091         QDomDocument categoryDocument;
00092         QString categoryFileName;
00093 };
00094 
00095 Blokkal::Io::CategoryManager::CategoryManager( Blokkal::Account * account ):
00096 QObject( account ),
00097 d( new Private( account ) )
00098 {
00099         d->categoryFileName = account->dataDirectory() + QString::fromLatin1( "categories.xml" );
00100         
00101         //loading and parsing file
00102         QFile file( d->categoryFileName );
00103         if( file.open( QIODevice::ReadOnly ) ) {
00104                 if( !d->categoryDocument.setContent( &file ) ) {
00105                         kError() << k_funcinfo << "error parsing category file " << file.fileName() << endl;
00106                 }
00107                 file.close();
00108         }
00109 
00110         //build map
00111         QDomNode currentBlogNode = d->categoryDocument.firstChild().namedItem( "blog" );
00112         while( !currentBlogNode.isNull() ) {
00113                 QDomElement currentBlogElement;
00114                 QString blogName;
00115                 if( currentBlogNode.isElement() && currentBlogNode.nodeName() == "blog" ) {
00116                         currentBlogElement = currentBlogNode.toElement();
00117                         blogName = currentBlogElement.attribute( "name" );
00118                         d->categoryMap.insert( blogName, CategoryList() );
00119                         
00120                         CategoryList & currentCategoryList = d->categoryMap[ blogName ];
00121                         QDomNode currentCategoryNode = currentBlogNode.namedItem( "category" );
00122                         while( !currentCategoryNode.isNull() ) {
00123                                 if( currentCategoryNode.isElement() && currentCategoryNode.nodeName() == "category" ) {
00124                                         QDomElement currentCategoryElement = currentCategoryNode.toElement();
00125                                         Category * category  = new Category( this,
00126                                                                              blogName,
00127                                                                              currentCategoryElement.attribute( "id" ),
00128                                                                              currentCategoryElement.attribute( "name" ),
00129                                                                              currentCategoryElement.attribute( "html" ),
00130                                                                              currentCategoryElement.attribute( "rss" ) );
00131                                         currentCategoryList.append( category );
00132                                         //kdDebug() << "found  in file: " << currentElement.attribute( "name" ) << endl;
00133                                 }
00134                                 currentCategoryNode = currentCategoryNode.nextSibling();
00135                         }
00136                         
00137                 }
00138                 currentBlogNode = currentBlogNode.nextSibling();
00139         }
00140 }
00141 
00142 Blokkal::Io::CategoryManager::~CategoryManager( void )
00143 {
00144         QFile file( d->categoryFileName );
00145         if( !file.open( QIODevice::WriteOnly ) ) {
00146                 kError() << k_funcinfo << "error opening category file " << file.fileName() << endl;
00147         }
00148 
00149    QTextStream fileStream( &file );
00150         d->categoryDocument.save( fileStream, 3 );
00151  
00152         file.close();
00153         
00154         delete d;
00155         d = 0;
00156 }
00157 
00158 void Blokkal::Io::CategoryManager::setValidCategories( const QString & blogId, QStringList categories )
00159 {
00160         if( d->categoryMap.contains( blogId ) ) {
00161                 CategoryList & oldCategories = d->categoryMap[blogId];
00162                 for( int i = 0;
00163                      i < oldCategories.size(); )
00164                 {
00165                         if( !categories.contains( oldCategories.value( i )->id() ) ) {
00166                                 Category * removedCategory = oldCategories.takeAt( i );
00167                                 emit categoryRemoved( blogId, removedCategory, this );
00168                                 removedCategory->destroy();
00169                         }
00170                         else {
00171                                 ++i;
00172                         }
00173                 }
00174         }
00175 }
00176 
00177 Blokkal::Io::CategoryList Blokkal::Io::CategoryManager::categories( const QString & blogId ) const
00178 {
00179         if( d->categoryMap.contains( blogId ) ) {
00180                 return d->categoryMap[blogId];
00181         }
00182 
00183         CategoryList list;
00184         return list;
00185 }
00186 
00187 Blokkal::Io::Category * Blokkal::Io::CategoryManager::category( const QString & blogId, const QString & categoryId )
00188 {
00189         CategoryList & categoryList = d->categoryMap[ blogId ];
00190         for( CategoryList::ConstIterator it = categoryList.begin();
00191              it != categoryList.end();
00192              ++it )
00193         {
00194                 if( (*it)->id() == categoryId ) {
00195                         return *it;
00196                 }
00197         }
00198 
00199         Category * category = new Category( this, blogId, categoryId );
00200         categoryList.append( category );
00201         emit categoryAdded( blogId, category, this );
00202         return category;
00203 }
00204 
00205 //--------
00206 //Category
00207 //--------
00208 class Blokkal::Io::Category::Private {
00209 public:
00210         Private( QDomElement node ):
00211         node( node ){}
00212 
00213         QDomElement node;
00214 
00215 };
00216 
00217 Blokkal::Io::Category::Category( Blokkal::Io::CategoryManager * manager, const QString & blogId, const QString & id, const QString & name, const QString & htmlUrl, const QString & rssUrl ):
00218 QObject( manager ),
00219 d( new Private( manager->d->categoryNode( blogId, id ) ) )
00220 {
00221         d->node.setAttribute( "name", name );
00222         d->node.setAttribute( "html", htmlUrl );
00223         d->node.setAttribute( "rss", rssUrl );
00224 }
00225 
00226 Blokkal::Io::Category::~Category( void )
00227 {
00228         delete d;
00229         d = 0;
00230 }
00231 
00232 QString Blokkal::Io::Category::id( void ) const
00233 {
00234         return d->node.attribute( "id" );
00235 }
00236 
00237 QString Blokkal::Io::Category::name( void ) const
00238 {
00239         return d->node.attribute( "name" );
00240 }
00241 
00242 QString Blokkal::Io::Category::htmlUrl( void ) const
00243 {
00244         return d->node.attribute( "html" );
00245 }
00246 
00247 QString Blokkal::Io::Category::rssUrl( void ) const
00248 {
00249         return d->node.attribute( "rss" );
00250 }
00251 
00252 void Blokkal::Io::Category::destroy( void )
00253 {
00254         d->node.parentNode().removeChild( d->node );
00255         deleteLater();
00256 }
00257 
00258 void Blokkal::Io::Category::setName( const QString & name )
00259 {
00260         d->node.setAttribute( "name", name );
00261         emit updated( this );
00262 }
00263 
00264 void Blokkal::Io::Category::setHtmlUrl( const QString & htmlUrl )
00265 {
00266         d->node.setAttribute( "html", htmlUrl );
00267         emit updated( this );
00268 }
00269 
00270 void Blokkal::Io::Category::setRssUrl( const QString & rssUrl )
00271 {
00272         d->node.setAttribute( "rss", rssUrl );
00273         emit updated( this );
00274 }
00275 
00276 Blokkal::Account * Blokkal::Io::CategoryManager::account( void ) const
00277 {
00278         return d->account;
00279 }