kmail Library API Documentation

subscriptiondialog.cpp

00001 /*  -*- c++ -*-
00002     subscriptiondialog.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (C) 2002 Carsten Burghardt <burghardt@kde.org>
00006 
00007     KMail is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMail is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this program with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include "subscriptiondialog.h"
00037 #include "kmmessage.h"
00038 #include "folderstorage.h"
00039 #include "listjob.h"
00040 using KMail::ListJob;
00041 
00042 #include <klocale.h>
00043 #include <kdebug.h>
00044 
00045 
00046 namespace KMail {
00047 
00048 SubscriptionDialogBase::SubscriptionDialogBase( QWidget *parent, const QString &caption,
00049     KAccount *acct, QString startPath )
00050   : KSubscription( parent, caption, acct, User1, QString::null, false ),
00051     mStartPath( startPath )
00052 {
00053   // hide unneeded checkboxes
00054   hideTreeCheckbox();
00055   hideNewOnlyCheckbox();
00056 
00057   // ok-button
00058   connect(this, SIGNAL(okClicked()), SLOT(slotSave()));
00059 
00060   // reload-list button
00061   connect(this, SIGNAL(user1Clicked()), SLOT(slotLoadFolders()));
00062 
00063   // get the folders, delayed execution style, otherwise there's bother
00064   // with virtuals from ctors and whatnot
00065   QTimer::singleShot(0, this, SLOT(slotLoadFolders()));
00066 }
00067 
00068 //------------------------------------------------------------------------------
00069 void SubscriptionDialogBase::slotListDirectory( const QStringList& subfolderNames,
00070                                             const QStringList& subfolderPaths,
00071                                             const QStringList& subfolderMimeTypes,
00072                                             const QStringList& subfolderAttributes,
00073                                             const ImapAccountBase::jobData& jobData )
00074 {
00075   mFolderNames = subfolderNames;
00076   mFolderPaths = subfolderPaths;
00077   mFolderMimeTypes = subfolderMimeTypes;
00078   mFolderAttributes = subfolderAttributes;
00079   mJobData = jobData;
00080 
00081   mCount = 0;
00082   mCheckForExisting = false;
00083 
00084   processFolderListing();
00085 }
00086 
00087 void SubscriptionDialogBase::moveChildrenToNewParent( GroupItem *oldItem, GroupItem *item  )
00088 {
00089   if ( !oldItem || !item ) return;
00090 
00091   QPtrList<QListViewItem> itemsToMove;
00092   QListViewItem * myChild = oldItem->firstChild();
00093   while (myChild)
00094   {
00095     itemsToMove.append(myChild);
00096     myChild = myChild->nextSibling();
00097   }
00098   QPtrListIterator<QListViewItem> it( itemsToMove );
00099   QListViewItem *cur;
00100   while ((cur = it.current()))
00101   {
00102     oldItem->takeItem(cur);
00103     item->insertItem(cur);
00104     if ( cur->isSelected() ) // we have new parents so open them
00105       folderTree()->ensureItemVisible( cur );
00106     ++it;
00107   }
00108   delete oldItem;
00109   itemsToMove.clear();
00110 }
00111 
00112 void SubscriptionDialogBase::createListViewItem( int i )
00113 {
00114   ImapAccountBase* ai = static_cast<ImapAccountBase*>(mAcct);
00115   GroupItem *item = 0;
00116   GroupItem *parent = 0;
00117   // the account does not know the delimiter
00118   if (mDelimiter.isEmpty())
00119   {
00120     int start = mFolderPaths[i].findRev(mFolderNames[i]);
00121     if (start > 1)
00122       mDelimiter = mFolderPaths[i].mid(start-1, 1);
00123   }
00124 
00125   // get the parent
00126   GroupItem *oldItem = 0;
00127   QString parentPath;
00128   findParentItem( mFolderNames[i], mFolderPaths[i], parentPath, &parent, &oldItem );
00129 
00130   if (!parent && parentPath != "/")
00131   {
00132     // the parent is not available and it's no root-item
00133     // this happens when the folders do not arrive in hierarchical order
00134     // so we create each parent in advance
00135     // as a result we have to check from now on if the folder already exists
00136     mCheckForExisting = true;
00137     QStringList folders = QStringList::split(mDelimiter, parentPath);
00138     uint i = 0;
00139     for ( QStringList::Iterator it = folders.begin(); it != folders.end(); ++it )
00140     {
00141       QString name = *it;
00142       if (name.startsWith("/"))
00143         name = name.right(name.length()-1);
00144       if (name.endsWith("/"))
00145         name.truncate(name.length()-1);
00146       KGroupInfo info(name);
00147       if (("/"+name+"/") == ai->prefix())
00148       {
00149         ++i;
00150         continue;
00151       }
00152       info.subscribed = false;
00153 
00154       QStringList tmpPath;
00155       for ( uint j = 0; j <= i; ++j )
00156         tmpPath << folders[j];
00157       QString path = tmpPath.join(mDelimiter);
00158       if (!path.startsWith("/"))
00159         path = "/" + path;
00160       if (!path.endsWith("/"))
00161         path = path + "/";
00162       info.path = path;
00163       item = 0;
00164       if (folders.count() > 1)
00165       {
00166         // we have to create more then one level, so better check if this
00167         // folder already exists somewhere
00168         item = mItemDict[path];
00169       }
00170       // as these items are "dummies" we create them non-checkable
00171       if (!item)
00172       {
00173         if (parent)
00174           item = new GroupItem(parent, info, this, false);
00175         else
00176           item = new GroupItem(folderTree(), info, this, false);
00177         mItemDict.insert(info.path, item);
00178       }
00179 
00180       parent = item;
00181       ++i;
00182     } // folders
00183   } // parent
00184 
00185   KGroupInfo info(mFolderNames[i]);
00186   if (mFolderNames[i].upper() == "INBOX" &&
00187       mFolderPaths[i] == "/INBOX/")
00188     info.name = i18n("inbox");
00189   info.subscribed = false;
00190   info.path = mFolderPaths[i];
00191   // only checkable when the folder is selectable
00192   bool checkable = ( mFolderMimeTypes[i] == "inode/directory" ) ? false : true;
00193   // create a new item
00194   if (parent)
00195     item = new GroupItem(parent, info, this, checkable);
00196   else
00197     item = new GroupItem(folderTree(), info, this, checkable);
00198 
00199   if (oldItem) // remove old item
00200     mItemDict.remove(info.path);
00201 
00202   mItemDict.insert(info.path, item);
00203   if (oldItem)
00204     moveChildrenToNewParent( oldItem, item );
00205 
00206   // select the start item
00207   if ( mFolderPaths[i] == mStartPath )
00208   {
00209     item->setSelected( true );
00210     folderTree()->ensureItemVisible( item );
00211   }
00212 }
00213 
00214 
00215 
00216 //------------------------------------------------------------------------------
00217 void SubscriptionDialogBase::findParentItem( QString &name, QString &path, QString &parentPath,
00218     GroupItem **parent, GroupItem **oldItem )
00219 {
00220   // remove the name (and the separator) from the path to get the parent path
00221   int start = path.length() - (name.length()+2);
00222   int length = name.length()+1;
00223   if (start < 0) start = 0;
00224   parentPath = path;
00225   parentPath.remove(start, length);
00226 
00227   if (mDelimiter.isEmpty())
00228     return;
00229 
00230   // find the parent by it's path
00231   *parent = mItemDict[parentPath];
00232 
00233   // check if the item already exists
00234   if (mCheckForExisting)
00235     *oldItem = mItemDict[path];
00236 }
00237 
00238 //------------------------------------------------------------------------------
00239 void SubscriptionDialogBase::slotSave()
00240 {
00241   if (!account())
00242     return;
00243   doSave();
00244 }
00245 
00246 //------------------------------------------------------------------------------
00247 void SubscriptionDialogBase::slotLoadFolders()
00248 {
00249   // clear the views
00250   KSubscription::slotLoadFolders();
00251   if ( !account() )
00252     return;
00253   ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
00254   if ( ai->prefix().isEmpty() )
00255     return;
00256   mItemDict.clear();
00257 
00258   // first step is to load a list of all available folders and create listview
00259   // items for them
00260   listAllAvailableAndCreateItems();
00261 
00262 }
00263 
00264 
00265 //------------------------------------------------------------------------------
00266 // implementation for server side subscription 
00267 //------------------------------------------------------------------------------
00268 
00269 SubscriptionDialog::SubscriptionDialog( QWidget *parent, const QString &caption,
00270     KAccount *acct, QString startPath )
00271   : SubscriptionDialogBase( parent, caption, acct, startPath )
00272 {
00273 }
00274 
00275 /* virtual */
00276 SubscriptionDialog::~SubscriptionDialog()
00277 {
00278     
00279 }
00280 
00281 /* virtual */
00282 void SubscriptionDialog::listAllAvailableAndCreateItems()
00283 {
00284   ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
00285   // only do a complete listing (*) when the user did not enter a prefix
00286   // otherwise the complete listing will be done in second step
00287   bool complete = (ai->prefix() == "/") ? true : false;
00288   // get all folders
00289   ListJob* job = new ListJob( 0, ai, ImapAccountBase::List, false,
00290       complete, false, ai->prefix() );
00291   connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00292           const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00293       this, SLOT(slotListDirectory(const QStringList&, const QStringList&,
00294           const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00295   job->start();
00296 }
00297 
00298 /* virtual */
00299 void SubscriptionDialog::processFolderListing()
00300 {
00301     processItems();
00302 }
00303 
00304 /* virtual */
00305 void SubscriptionDialog::doSave()
00306 {
00307   // subscribe
00308   QListViewItemIterator it(subView);
00309   for ( ; it.current(); ++it)
00310   {
00311     static_cast<ImapAccountBase*>(account())->changeSubscription(true,
00312         static_cast<GroupItem*>(it.current())->info().path);
00313   }
00314 
00315   // unsubscribe
00316   QListViewItemIterator it2(unsubView);
00317   for ( ; it2.current(); ++it2)
00318   {
00319     static_cast<ImapAccountBase*>(account())->changeSubscription(false,
00320         static_cast<GroupItem*>(it2.current())->info().path);
00321   }
00322 }
00323 
00324 void SubscriptionDialog::processItems()
00325 {
00326   bool onlySubscribed = mJobData.onlySubscribed;
00327   ImapAccountBase* ai = static_cast<ImapAccountBase*>(mAcct);
00328   uint done = 0;
00329   for (uint i = mCount; i < mFolderNames.count(); ++i)
00330   {
00331     // give the dialog a chance to repaint
00332     if (done == 1000)
00333     {
00334       emit listChanged();
00335       QTimer::singleShot(0, this, SLOT(processItems()));
00336       return;
00337     }
00338     ++mCount;
00339     ++done;
00340     if (!onlySubscribed && mFolderPaths.size() > 0)
00341     {
00342       createListViewItem( i );
00343     } else if (onlySubscribed)
00344     {
00345       // find the item
00346       if ( mItemDict[mFolderPaths[i]] )
00347       {
00348         GroupItem* item = mItemDict[mFolderPaths[i]];
00349         item->setOn( true );
00350       }
00351     }
00352   }
00353   if ( mJobData.inboxOnly )
00354   {
00355     // list again (secondStep=true) with prefix
00356     ImapAccountBase::ListType type = ImapAccountBase::List;
00357     // the below can't happen, can it? - till
00358     if ( onlySubscribed )
00359       type = ImapAccountBase::ListSubscribedNoCheck;
00360     ListJob* job = new ListJob( 0, ai, type, true, true,
00361                                 false, ai->prefix() );
00362     connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00363             const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00364         this, SLOT(slotListDirectory(const QStringList&, const QStringList&,
00365             const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00366     job->start();
00367   } else if (!onlySubscribed)
00368   {
00369     // get subscribed folders
00370     // only do a complete listing (*) when the user did not enter a prefix
00371     // otherwise the complete listing will be done in second step
00372     // we use the 'SubscribedNoCheck' feature so that the kioslave doesn't check
00373     // for every folder if it actually exists
00374     bool complete = (ai->prefix() == "/") ? true : false;
00375     ListJob* job = new ListJob( 0, ai, ImapAccountBase::ListSubscribedNoCheck,
00376         false, complete, false, ai->prefix() );
00377     connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00378             const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00379         this, SLOT(slotListDirectory(const QStringList&, const QStringList&,
00380             const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00381     job->start();
00382   } else if (onlySubscribed)
00383   {
00384     // activate buttons and stuff
00385     slotLoadingComplete();
00386   }
00387 }
00388 } // namespace
00389 
00390 #include "subscriptiondialog.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 4 14:42:33 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003