akonadi
collectionpathresolver.cpp
00001 /* 00002 Copyright (c) 2007 Volker Krause <vkrause@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 00018 */ 00019 00020 #include "collectionpathresolver_p.h" 00021 00022 #include "collectionfetchjob.h" 00023 #include "job_p.h" 00024 00025 #include <klocale.h> 00026 00027 #include <QtCore/QStringList> 00028 00029 using namespace Akonadi; 00030 00031 //@cond PRIVATE 00032 00033 class Akonadi::CollectionPathResolverPrivate : public JobPrivate 00034 { 00035 public: 00036 CollectionPathResolverPrivate( CollectionPathResolver *parent ) 00037 : JobPrivate( parent ) 00038 { 00039 } 00040 00041 void jobResult( KJob* ); 00042 00043 QStringList splitPath( const QString &path ) 00044 { 00045 if ( path.isEmpty() ) // path is normalized, so non-empty means at least one hit 00046 return QStringList(); 00047 00048 QStringList rv; 00049 int begin = 0; 00050 for ( int i = 0; i < path.size(); ++i ) { 00051 if ( path[i] == QLatin1Char('/') ) { 00052 QString pathElement = path.mid( begin, i - begin ); 00053 pathElement = pathElement.replace( QLatin1String( "\\/" ), QLatin1String( "/" ) ); 00054 rv.append( pathElement ); 00055 begin = i + 1; 00056 } 00057 if ( i < path.size() - 2 && path[i] == QLatin1Char('\\') && path[i + 1] == QLatin1Char('/') ) 00058 ++i; 00059 } 00060 QString pathElement = path.mid( begin ); 00061 pathElement = pathElement.replace( QLatin1String( "\\/" ), QLatin1String( "/" ) ); 00062 rv.append( pathElement ); 00063 return rv; 00064 } 00065 00066 Q_DECLARE_PUBLIC( CollectionPathResolver ) 00067 00068 Collection::Id mColId; 00069 QString mPath; 00070 bool mPathToId; 00071 QStringList mPathParts; 00072 Collection mCurrentNode; 00073 }; 00074 00075 void CollectionPathResolverPrivate::jobResult(KJob *job ) 00076 { 00077 if ( job->error() ) 00078 return; 00079 00080 Q_Q( CollectionPathResolver ); 00081 00082 CollectionFetchJob *list = static_cast<CollectionFetchJob*>( job ); 00083 CollectionFetchJob *nextJob = 0; 00084 const Collection::List cols = list->collections(); 00085 if ( cols.isEmpty() ) { 00086 q->setError( CollectionPathResolver::Unknown ); 00087 q->setErrorText( i18n( "No such collection." ) ); 00088 q->emitResult(); 00089 return; 00090 } 00091 00092 if ( mPathToId ) { 00093 const QString currentPart = mPathParts.takeFirst(); 00094 bool found = false; 00095 foreach ( const Collection &c, cols ) { 00096 if ( c.name() == currentPart ) { 00097 mCurrentNode = c; 00098 found = true; 00099 break; 00100 } 00101 } 00102 if ( !found ) { 00103 q->setError( CollectionPathResolver::Unknown ); 00104 q->setErrorText( i18n( "No such collection." ) ); 00105 q->emitResult(); 00106 return; 00107 } 00108 if ( mPathParts.isEmpty() ) { 00109 mColId = mCurrentNode.id(); 00110 q->emitResult(); 00111 return; 00112 } 00113 nextJob = new CollectionFetchJob( mCurrentNode, CollectionFetchJob::FirstLevel, q ); 00114 } else { 00115 Collection col = list->collections().first(); 00116 mCurrentNode = col.parentCollection(); 00117 mPathParts.prepend( col.name() ); 00118 if ( mCurrentNode == Collection::root() ) { 00119 q->emitResult(); 00120 return; 00121 } 00122 nextJob = new CollectionFetchJob( mCurrentNode, CollectionFetchJob::Base, q ); 00123 } 00124 q->connect( nextJob, SIGNAL( result( KJob* ) ), q, SLOT( jobResult( KJob* ) ) ); 00125 } 00126 00127 CollectionPathResolver::CollectionPathResolver(const QString & path, QObject * parent) 00128 : Job( new CollectionPathResolverPrivate( this ), parent ) 00129 { 00130 Q_D( CollectionPathResolver ); 00131 00132 d->mPathToId = true; 00133 d->mPath = path; 00134 if ( d->mPath.startsWith( pathDelimiter() ) ) 00135 d->mPath = d->mPath.right( d->mPath.length() - pathDelimiter().length() ); 00136 if ( d->mPath.endsWith( pathDelimiter() ) ) 00137 d->mPath = d->mPath.left( d->mPath.length() - pathDelimiter().length() ); 00138 00139 d->mPathParts = d->splitPath( d->mPath ); 00140 d->mCurrentNode = Collection::root(); 00141 } 00142 00143 CollectionPathResolver::CollectionPathResolver(const Collection & collection, QObject * parent) 00144 : Job( new CollectionPathResolverPrivate( this ), parent ) 00145 { 00146 Q_D( CollectionPathResolver ); 00147 00148 d->mPathToId = false; 00149 d->mColId = collection.id(); 00150 d->mCurrentNode = collection; 00151 } 00152 00153 CollectionPathResolver::~CollectionPathResolver() 00154 { 00155 } 00156 00157 Collection::Id CollectionPathResolver::collection() const 00158 { 00159 Q_D( const CollectionPathResolver ); 00160 00161 return d->mColId; 00162 } 00163 00164 QString CollectionPathResolver::path() const 00165 { 00166 Q_D( const CollectionPathResolver ); 00167 00168 if ( d->mPathToId ) 00169 return d->mPath; 00170 return d->mPathParts.join( pathDelimiter() ); 00171 } 00172 00173 QString CollectionPathResolver::pathDelimiter() 00174 { 00175 return QLatin1String( "/" ); 00176 } 00177 00178 void CollectionPathResolver::doStart() 00179 { 00180 Q_D( CollectionPathResolver ); 00181 00182 CollectionFetchJob *job = 0; 00183 if ( d->mPathToId ) { 00184 if ( d->mPath.isEmpty() ) { 00185 d->mColId = Collection::root().id(); 00186 emitResult(); 00187 return; 00188 } 00189 job = new CollectionFetchJob( d->mCurrentNode, CollectionFetchJob::FirstLevel, this ); 00190 } else { 00191 if ( d->mColId == 0 ) { 00192 d->mColId = Collection::root().id(); 00193 emitResult(); 00194 return; 00195 } 00196 job = new CollectionFetchJob( d->mCurrentNode, CollectionFetchJob::Base, this ); 00197 } 00198 connect( job, SIGNAL( result( KJob* ) ), SLOT( jobResult( KJob* ) ) ); 00199 } 00200 00201 //@endcond 00202 00203 #include "collectionpathresolver_p.moc"