kmail Library API Documentation

kmfoldertree.cpp

00001 // kmfoldertree.cpp
00002 #ifdef HAVE_CONFIG_H
00003 #include <config.h>
00004 #endif
00005 
00006 #include "kmfoldertree.h"
00007 
00008 #include "kmfoldermgr.h"
00009 #include "kmfolderimap.h"
00010 #include "kmfoldercachedimap.h"
00011 #include "kmfolderdia.h"
00012 #include "kmcomposewin.h"
00013 #include "kmmainwidget.h"
00014 #include "kmailicalifaceimpl.h"
00015 #include "kmacctmgr.h"
00016 #include "kmkernel.h"
00017 #include "globalsettings.h"
00018 #include "kmcommands.h"
00019 #include "acljobs.h"
00020 
00021 #include <maillistdrag.h>
00022 using namespace KPIM;
00023 
00024 #include <kapplication.h>
00025 #include <kglobalsettings.h>
00026 #include <kiconloader.h>
00027 #include <kmessagebox.h>
00028 #include <kconfig.h>
00029 #include <kdebug.h>
00030 
00031 #include <qpainter.h>
00032 #include <qcursor.h>
00033 #include <qregexp.h>
00034 #include <qtooltip.h>
00035 
00036 #include <unistd.h>
00037 #include <assert.h>
00038 
00039 #include <X11/Xlib.h>
00040 #include <fixx11h.h>
00041 
00042 namespace {
00043 
00044   class ItemToolTip : public QToolTip {
00045   public:
00046     ItemToolTip( KMFolderTree * parent );
00047     virtual ~ItemToolTip(){ }
00048     void updateTip( const QString & );
00049   protected:
00050     void maybeTip( const QPoint & p );
00051   private:
00052     KMFolderTree* mFolderTree;
00053     KMFolderImap* mLastImapFolder;
00054     QPoint mLastPoint;
00055     QString mCurrentTip;
00056   };
00057 
00058   ItemToolTip::ItemToolTip( KMFolderTree * parent )
00059     : QToolTip( parent->viewport() ), mFolderTree( parent )
00060     , mLastImapFolder( 0 ) {}
00061 
00062   void ItemToolTip::maybeTip( const QPoint & p ) {
00063     if ( !mFolderTree )
00064       return;
00065 
00066     const QListViewItem * item = mFolderTree->itemAt( p );
00067     if ( !item )
00068       return;
00069 
00070     const QRect itemRect = mFolderTree->itemRect( item );
00071     if ( !itemRect.isValid() )
00072       return;
00073 
00074     const int col = mFolderTree->header()->sectionAt( p.x() );
00075     if ( col == -1 )
00076       return;
00077 
00078     const QRect headerRect = mFolderTree->header()->sectionRect( col );
00079     if ( !headerRect.isValid() )
00080       return;
00081 
00082     const QRect cellRect( headerRect.left(), itemRect.top(),
00083               headerRect.width(), itemRect.height() );
00084 
00085     QString tipStr( mCurrentTip );
00086     mCurrentTip = QString();
00087     if ( tipStr.isEmpty() ) {
00088       if ( const KMFolderTreeItem * klvi = dynamic_cast<const KMFolderTreeItem*>( item ) ) {
00089         tipStr = klvi->toolTip( col );
00090         if ( klvi->folder() && klvi->folder()->storage() ) {
00091           KMFolderImap *imapFolder = dynamic_cast<KMFolderImap*>( klvi->folder()->storage() );
00092           if ( mLastImapFolder && mLastImapFolder->account() ) {
00093             QObject::disconnect( mLastImapFolder->account(),
00094                 SIGNAL(receivedStorageQuotaInfo( KMFolder*, KIO::Job*, const KMail::QuotaInfo& )),
00095                 mFolderTree,
00096                 SLOT(slotReceivedQuotaInfo( KMFolder*, KIO::Job*, const KMail::QuotaInfo& )) );
00097           }
00098           if ( imapFolder ) {
00099             QObject::connect( imapFolder->account(),
00100                 SIGNAL(receivedStorageQuotaInfo( KMFolder*, KIO::Job*, const KMail::QuotaInfo& )),
00101                 mFolderTree,
00102                 SLOT(slotReceivedQuotaInfo( KMFolder*, KIO::Job*, const KMail::QuotaInfo& )) );
00103           }
00104           mLastImapFolder = imapFolder;
00105         }
00106       }
00107       else
00108         tipStr = item->text( col ) ;
00109     }
00110 
00111     if ( !tipStr.isEmpty() ) {
00112       tip( cellRect, tipStr );
00113       mLastPoint = p;
00114     }
00115   }
00116 
00117   void ItemToolTip::updateTip( const QString& str )
00118   {
00119     mCurrentTip = str;
00120     maybeTip( mLastPoint );
00121   }
00122 
00123 } // anon namespace
00124 
00125 
00126 
00127 //=============================================================================
00128 
00129 KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const QString & name,
00130                                     KFolderTreeItem::Protocol protocol )
00131   : QObject( parent, name.latin1() ),
00132     KFolderTreeItem( parent, name, protocol, Root ),
00133     mFolder( 0 ), mNeedsRepaint( true )
00134 {
00135   init();
00136   setPixmap( 0, normalIcon() );
00137 }
00138 
00139 //-----------------------------------------------------------------------------
00140 KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const QString & name,
00141                     KMFolder* folder )
00142   : QObject( parent, name.latin1() ),
00143     KFolderTreeItem( parent, name ),
00144     mFolder( folder ), mNeedsRepaint( true )
00145 {
00146   init();
00147   setPixmap( 0, normalIcon() );
00148 }
00149 
00150 //-----------------------------------------------------------------------------
00151 KMFolderTreeItem::KMFolderTreeItem( KFolderTreeItem *parent, const QString & name,
00152                     KMFolder* folder )
00153   : QObject( 0, name.latin1() ),
00154     KFolderTreeItem( parent, name ),
00155     mFolder( folder ), mNeedsRepaint( true )
00156 {
00157   init();
00158   setPixmap( 0, normalIcon() );
00159 }
00160 
00161 KMFolderTreeItem::~KMFolderTreeItem()
00162 {
00163 }
00164 
00165 static KFolderTreeItem::Protocol protocolFor( KMFolderType t ) {
00166   switch ( t ) {
00167   case KMFolderTypeImap:
00168     return KFolderTreeItem::Imap;
00169   case KMFolderTypeCachedImap:
00170     return KFolderTreeItem::CachedImap;
00171   case KMFolderTypeMbox:
00172   case KMFolderTypeMaildir:
00173     return KFolderTreeItem::Local;
00174   case KMFolderTypeSearch:
00175     return KFolderTreeItem::Search;
00176   default:
00177     return KFolderTreeItem::NONE;
00178   }
00179 }
00180 
00181 
00182 QString KMFolderTreeItem::toolTip( int column ) const
00183 {
00184   QString tip;
00185   if ( column !=0 || !mFolder )
00186     return tip;
00187 
00188   tip = mFolder->label();
00189 
00190   QString quotaInfo;
00191   if ( KMFolderCachedImap* folder = dynamic_cast<KMFolderCachedImap*>( mFolder->storage() ) ) {
00192     QuotaInfo info( folder->quotaInfo() );
00193     quotaInfo = info.toString();
00194   } else if ( KMFolderImap* imapFolder = dynamic_cast<KMFolderImap*>( mFolder->storage() ) ) {
00195     imapFolder->account()->getStorageQuotaInfo( mFolder, imapFolder->imapPath() );
00196     quotaInfo = i18n( "Retrieving quota information" );
00197   }
00198 
00199   if ( !quotaInfo.isEmpty() ) {
00200     tip += " (" + quotaInfo  + ')';
00201   }
00202   return tip;
00203 }
00204 
00205 QPixmap KMFolderTreeItem::normalIcon(int size) const
00206 {
00207   QString icon;
00208   if ( (!mFolder && type() == Root) || depth() == 0 ) {
00209     switch ( protocol() ) {
00210       case KFolderTreeItem::Imap:
00211       case KFolderTreeItem::CachedImap:
00212       case KFolderTreeItem::News:
00213         icon = "server"; break;
00214       case KFolderTreeItem::Search:
00215         icon = "viewmag";break;
00216       default:
00217         icon = "folder";break;
00218     }
00219   } else {
00220     // special folders
00221     switch ( type() ) {
00222       case Inbox: icon = "folder_inbox"; break;
00223       case Outbox: icon = "folder_outbox"; break;
00224       case SentMail: icon = "folder_sent_mail"; break;
00225       case Trash: icon = "trashcan_empty"; break;
00226       case Drafts: icon = "edit";break;
00227       default: icon = kmkernel->iCalIface().folderPixmap( type() ); break;
00228     }
00229     // non-root search folders
00230     if ( protocol() == KMFolderTreeItem::Search) {
00231       icon = "mail_find";
00232     }
00233   }
00234 
00235   if ( icon.isEmpty() )
00236     icon = "folder";
00237 
00238   if (mFolder && mFolder->useCustomIcons() ) {
00239     icon = mFolder->normalIconPath();
00240   }
00241   KIconLoader * il = KGlobal::instance()->iconLoader();
00242   QPixmap pm = il->loadIcon( icon, KIcon::Small, size,
00243                              KIcon::DefaultState, 0, true );
00244   if ( pm.isNull() ) {
00245       pm = il->loadIcon( mFolder->normalIconPath(), KIcon::Small, size,
00246                          KIcon::DefaultState, 0, true );
00247   }
00248 
00249   return pm;
00250 }
00251 
00252 QPixmap KMFolderTreeItem::unreadIcon(int size) const
00253 {
00254   QPixmap pm;
00255 
00256   if ( !mFolder || depth() == 0 || mFolder->isSystemFolder()
00257     || kmkernel->folderIsTrash( mFolder )
00258     || kmkernel->folderIsDraftOrOutbox( mFolder ) )
00259     pm = normalIcon( size );
00260 
00261   KIconLoader * il = KGlobal::instance()->iconLoader();
00262   if ( mFolder->useCustomIcons() ) {
00263     pm = il->loadIcon( mFolder->unreadIconPath(), KIcon::Small, size,
00264                        KIcon::DefaultState, 0, true );
00265     if ( pm.isNull() )
00266       pm = il->loadIcon( mFolder->normalIconPath(), KIcon::Small, size,
00267                          KIcon::DefaultState, 0, true );
00268   }
00269   if ( pm.isNull() )
00270     pm = il->loadIcon( kmkernel->iCalIface().folderPixmap( type() ),
00271                        KIcon::Small, size, KIcon::DefaultState, 0, true );
00272   if ( pm.isNull() )
00273     pm = il->loadIcon( "folder_open", KIcon::Small, size,
00274                            KIcon::DefaultState, 0, true );
00275   return pm;
00276 }
00277 
00278 void KMFolderTreeItem::init()
00279 {
00280   if ( !mFolder )
00281     return;
00282 
00283   setProtocol( protocolFor( mFolder->folderType() ) );
00284 
00285   if ( depth() == 0 )
00286     setType(Root);
00287   else {
00288     if ( mFolder == kmkernel->inboxFolder() )
00289       setType( Inbox );
00290     else if ( kmkernel->folderIsDraftOrOutbox( mFolder ) ) {
00291       if ( mFolder == kmkernel->outboxFolder() )
00292         setType( Outbox );
00293       else
00294         setType( Drafts );
00295     }
00296     else if ( kmkernel->folderIsSentMailFolder( mFolder ) )
00297       setType( SentMail );
00298     else if ( kmkernel->folderIsTrash( mFolder ) )
00299       setType( Trash );
00300     else if( kmkernel->iCalIface().isResourceFolder(mFolder) )
00301       setType( kmkernel->iCalIface().folderType(mFolder) );
00302     // System folders on dimap or imap which are not resource folders are
00303     // inboxes. Urgs.
00304     if ( mFolder->isSystemFolder() &&
00305         !kmkernel->iCalIface().isResourceFolder( mFolder) &&
00306          ( mFolder->folderType() == KMFolderTypeImap
00307         || mFolder->folderType() == KMFolderTypeCachedImap ) )
00308       setType( Inbox );
00309   }
00310   if ( !mFolder->isSystemFolder() )
00311     setRenameEnabled( 0, false );
00312 
00313   KMFolderTree* tree = static_cast<KMFolderTree*>( listView() );
00314   tree->insertIntoFolderToItemMap( mFolder, this );
00315 }
00316 
00317 void KMFolderTreeItem::adjustUnreadCount( int newUnreadCount ) {
00318   // adjust the icons if the folder is now newly unread or
00319   // now newly not-unread
00320   if ( newUnreadCount != 0 && unreadCount() == 0 )
00321     setPixmap( 0, unreadIcon() );
00322   if ( unreadCount() != 0 && newUnreadCount == 0 )
00323     setPixmap( 0, normalIcon() );
00324 
00325   setUnreadCount( newUnreadCount );
00326 }
00327 
00328 void KMFolderTreeItem::slotRepaint() {
00329   kdDebug(5006) << k_funcinfo << endl;
00330   // this is prone to change, so better check
00331   if( kmkernel->iCalIface().isResourceFolder( mFolder ) )
00332       setType( kmkernel->iCalIface().folderType(mFolder) );
00333 
00334   if ( unreadCount() > 0 )
00335     setPixmap( 0, unreadIcon() );
00336   else
00337     setPixmap( 0, normalIcon() );
00338   emit iconChanged( this );
00339   repaint();
00340 }
00341 
00342 
00343 //-----------------------------------------------------------------------------
00344 bool KMFolderTreeItem::acceptDrag(QDropEvent*) const
00345 {
00346   if ( !mFolder || mFolder->isReadOnly() ||
00347       (mFolder->noContent() && childCount() == 0) ||
00348        (mFolder->noContent() && isOpen()) ) {
00349     return false;
00350   }
00351   else {
00352     return true;
00353   }
00354 }
00355 
00356 //-----------------------------------------------------------------------------
00357 void KMFolderTreeItem::properties()
00358 {
00359   if ( !mFolder )
00360     return;
00361 
00362   KMFolderTree* tree = static_cast<KMFolderTree*>( listView() );
00363   tree->mainWidget()->modifyFolder( this );
00364   //Nothing here the above may actually delete this KMFolderTreeItem
00365 }
00366 
00367 //=============================================================================
00368 
00369 
00370 KMFolderTree::KMFolderTree( KMMainWidget *mainWidget, QWidget *parent,
00371                             const char *name )
00372   : KFolderTree( parent, name )
00373 {
00374   oldSelected = 0;
00375   oldCurrent = 0;
00376   mLastItem = 0;
00377   mMainWidget = mainWidget;
00378   mReloading = false;
00379 
00380   addAcceptableDropMimetype(MailListDrag::format(), false);
00381 
00382   int namecol = addColumn( i18n("Folder"), 250 );
00383   header()->setStretchEnabled( true, namecol );
00384 
00385   // connect
00386   connectSignals();
00387 
00388   // popup to switch columns
00389   header()->setClickEnabled(true);
00390   header()->installEventFilter(this);
00391   mPopup = new KPopupMenu(this);
00392   mPopup->insertTitle(i18n("View Columns"));
00393   mPopup->setCheckable(true);
00394   mUnreadPop = mPopup->insertItem(i18n("Unread Column"), this, SLOT(slotToggleUnreadColumn()));
00395   mTotalPop = mPopup->insertItem(i18n("Total Column"), this, SLOT(slotToggleTotalColumn()));
00396 
00397   QToolTip::remove( this );
00398   QToolTip::remove( viewport() ); // make double sure :)
00399   mToolTip = new ItemToolTip( this );
00400 }
00401 
00402 //-----------------------------------------------------------------------------
00403 // connects all needed signals to their slots
00404 void KMFolderTree::connectSignals()
00405 {
00406   connect(&mUpdateTimer, SIGNAL(timeout()),
00407           this, SLOT(delayedUpdate()));
00408 
00409   connect(kmkernel->folderMgr(), SIGNAL(changed()),
00410           this, SLOT(doFolderListChanged()));
00411 
00412   connect(kmkernel->folderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00413           this, SLOT(slotFolderRemoved(KMFolder*)));
00414 
00415   connect(kmkernel->imapFolderMgr(), SIGNAL(changed()),
00416           this, SLOT(doFolderListChanged()));
00417 
00418   connect(kmkernel->imapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00419           this, SLOT(slotFolderRemoved(KMFolder*)));
00420 
00421   connect(kmkernel->dimapFolderMgr(), SIGNAL(changed()),
00422           this, SLOT(doFolderListChanged()));
00423 
00424   connect(kmkernel->dimapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00425           this, SLOT(slotFolderRemoved(KMFolder*)));
00426 
00427   connect(kmkernel->searchFolderMgr(), SIGNAL(changed()),
00428           this, SLOT(doFolderListChanged()));
00429 
00430   connect(kmkernel->acctMgr(), SIGNAL(accountRemoved(KMAccount*)),
00431           this, SLOT(slotAccountRemoved(KMAccount*)));
00432 
00433   connect(kmkernel->searchFolderMgr(), SIGNAL(folderRemoved(KMFolder*)),
00434           this, SLOT(slotFolderRemoved(KMFolder*)));
00435 
00436   connect( &autoopen_timer, SIGNAL( timeout() ),
00437            this, SLOT( openFolder() ) );
00438 
00439   connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int ) ),
00440            this, SLOT( slotContextMenuRequested( QListViewItem*, const QPoint & ) ) );
00441 
00442   connect( this, SIGNAL( expanded( QListViewItem* ) ),
00443            this, SLOT( slotFolderExpanded( QListViewItem* ) ) );
00444 
00445   connect( this, SIGNAL( collapsed( QListViewItem* ) ),
00446            this, SLOT( slotFolderCollapsed( QListViewItem* ) ) );
00447 
00448   connect( this, SIGNAL( itemRenamed( QListViewItem*, int, const QString &)),
00449            this, SLOT( slotRenameFolder( QListViewItem*, int, const QString &)));
00450 }
00451 
00452 //-----------------------------------------------------------------------------
00453 bool KMFolderTree::event(QEvent *e)
00454 {
00455   if (e->type() == QEvent::ApplicationPaletteChange)
00456   {
00457      readColorConfig();
00458      return true;
00459   }
00460   return KListView::event(e);
00461 }
00462 
00463 //-----------------------------------------------------------------------------
00464 void KMFolderTree::readColorConfig (void)
00465 {
00466   KConfig* conf = KMKernel::config();
00467   // Custom/System color support
00468   KConfigGroupSaver saver(conf, "Reader");
00469   QColor c1=QColor(kapp->palette().active().text());
00470   QColor c2=QColor("blue");
00471   QColor c4=QColor(kapp->palette().active().base());
00472 
00473   if (!conf->readBoolEntry("defaultColors",TRUE)) {
00474     mPaintInfo.colFore = conf->readColorEntry("ForegroundColor",&c1);
00475     mPaintInfo.colUnread = conf->readColorEntry("UnreadMessage",&c2);
00476     mPaintInfo.colBack = conf->readColorEntry("BackgroundColor",&c4);
00477   }
00478   else {
00479     mPaintInfo.colFore = c1;
00480     mPaintInfo.colUnread = c2;
00481     mPaintInfo.colBack = c4;
00482   }
00483   QPalette newPal = kapp->palette();
00484   newPal.setColor( QColorGroup::Base, mPaintInfo.colBack );
00485   newPal.setColor( QColorGroup::Text, mPaintInfo.colFore );
00486   setPalette( newPal );
00487 }
00488 
00489 //-----------------------------------------------------------------------------
00490 void KMFolderTree::readConfig (void)
00491 {
00492   KConfig* conf = KMKernel::config();
00493 
00494   readColorConfig();
00495 
00496   // Custom/Ssystem font support
00497   {
00498     KConfigGroupSaver saver(conf, "Fonts");
00499     if (!conf->readBoolEntry("defaultFonts",TRUE)) {
00500       QFont folderFont( KGlobalSettings::generalFont() );
00501       setFont(conf->readFontEntry("folder-font", &folderFont));
00502     }
00503     else
00504       setFont(KGlobalSettings::generalFont());
00505   }
00506 
00507   // restore the layout
00508   restoreLayout(conf, "Geometry");
00509 }
00510 
00511 //-----------------------------------------------------------------------------
00512 // Save the configuration file
00513 void KMFolderTree::writeConfig()
00514 {
00515   // save the current state of the folders
00516   for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) {
00517     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00518     if (fti)
00519       writeIsListViewItemOpen(fti);
00520   }
00521 
00522   // save the current layout
00523   saveLayout(KMKernel::config(), "Geometry");
00524 }
00525 
00526 //-----------------------------------------------------------------------------
00527 // Updates the count of unread messages (count of unread messages
00528 // is now cached in KMails config file)
00529 void KMFolderTree::updateUnreadAll()
00530 {
00531   bool upd = isUpdatesEnabled();
00532   setUpdatesEnabled(FALSE);
00533 
00534   KMFolderDir* fdir;
00535   KMFolderNode* folderNode;
00536   KMFolder* folder;
00537 
00538   fdir = &kmkernel->folderMgr()->dir();
00539   for (folderNode = fdir->first();
00540     folderNode != 0;
00541     folderNode =fdir->next())
00542   {
00543     if (!folderNode->isDir()) {
00544       folder = static_cast<KMFolder*>(folderNode);
00545 
00546       folder->open();
00547       folder->countUnread();
00548       folder->close();
00549     }
00550   }
00551 
00552   setUpdatesEnabled(upd);
00553 }
00554 
00555 //-----------------------------------------------------------------------------
00556 // Reload the tree of items in the list view
00557 void KMFolderTree::reload(bool openFolders)
00558 {
00559   if ( mReloading ) {
00560     // no parallel reloads are allowed
00561     kdDebug(5006) << "KMFolderTree::reload - already reloading" << endl;
00562     return;
00563   }
00564   mReloading = true;
00565 
00566   int top = contentsY();
00567   mLastItem = 0;
00568   // invalidate selected drop item
00569   oldSelected = 0;
00570   // remember last
00571   KMFolder* last = currentFolder();
00572   KMFolder* selected = 0;
00573   KMFolder* oldCurrentFolder =
00574     ( oldCurrent ? static_cast<KMFolderTreeItem*>(oldCurrent)->folder(): 0 );
00575   for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) {
00576     KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
00577     writeIsListViewItemOpen( fti );
00578     if ( fti->isSelected() )
00579       selected = fti->folder();
00580   }
00581   mFolderToItem.clear();
00582   clear();
00583 
00584   // construct the root of the local folders
00585   KMFolderTreeItem * root = new KMFolderTreeItem( this, i18n("Local Folders") );
00586   root->setOpen( readIsListViewItemOpen(root) );
00587 
00588   KMFolderDir * fdir = &kmkernel->folderMgr()->dir();
00589   addDirectory(fdir, root);
00590 
00591   fdir = &kmkernel->imapFolderMgr()->dir();
00592   // each imap-account creates it's own root
00593   addDirectory(fdir, 0);
00594 
00595   fdir = &kmkernel->dimapFolderMgr()->dir();
00596   // each dimap-account creates it's own root
00597   addDirectory(fdir, 0);
00598 
00599   // construct the root of the search folder hierarchy:
00600   root = new KMFolderTreeItem( this, i18n("Searches"), KFolderTreeItem::Search );
00601   root->setOpen( readIsListViewItemOpen( root ) );
00602 
00603   fdir = &kmkernel->searchFolderMgr()->dir();
00604   addDirectory(fdir, root);
00605 
00606   if (openFolders)
00607   {
00608     // we open all folders to update the count
00609     mUpdateIterator = QListViewItemIterator (this);
00610     QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) );
00611   }
00612 
00613   for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) {
00614     KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
00615     if ( !fti || !fti->folder() )
00616       continue;
00617 
00618     disconnect(fti->folder(),SIGNAL(iconsChanged()),
00619                fti,SLOT(slotRepaint()));
00620     connect(fti->folder(),SIGNAL(iconsChanged()),
00621             fti,SLOT(slotRepaint()));
00622 
00623     disconnect(fti->folder(),SIGNAL(nameChanged()),
00624                fti,SLOT(slotNameChanged()));
00625     connect(fti->folder(),SIGNAL(nameChanged()),
00626             fti,SLOT(slotNameChanged()));
00627 
00628     if (fti->folder()->folderType() == KMFolderTypeImap) {
00629       // imap-only
00630       KMFolderImap *imapFolder =
00631         dynamic_cast<KMFolderImap*> ( fti->folder()->storage() );
00632       disconnect( imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00633           this,SLOT(slotUpdateCounts(KMFolderImap*, bool)));
00634       connect( imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)),
00635           this,SLOT(slotUpdateCounts(KMFolderImap*, bool)));
00636     } else {
00637       // others-only, imap doesn't need this because of the folderComplete-signal
00638       // we want to be noticed of changes to update the unread/total columns
00639       disconnect(fti->folder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)),
00640           this,SLOT(slotUpdateCounts(KMFolder*)));
00641       connect(fti->folder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)),
00642           this,SLOT(slotUpdateCounts(KMFolder*)));
00643     }
00644 
00645     disconnect(fti->folder(), SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00646                this,SLOT(slotUpdateCounts(KMFolder*)));
00647     connect(fti->folder(), SIGNAL(numUnreadMsgsChanged(KMFolder*)),
00648             this,SLOT(slotUpdateCounts(KMFolder*)));
00649     disconnect(fti->folder(), SIGNAL(msgRemoved(KMFolder*)),
00650                this,SLOT(slotUpdateCounts(KMFolder*)));
00651     connect(fti->folder(), SIGNAL(msgRemoved(KMFolder*)),
00652             this,SLOT(slotUpdateCounts(KMFolder*)));
00653 
00654     if (!openFolders)
00655       slotUpdateCounts(fti->folder());
00656   }
00657   ensureVisible(0, top + visibleHeight(), 0, 0);
00658   // if current and selected folder did not change set it again
00659   for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
00660   {
00661     if ( last &&
00662         static_cast<KMFolderTreeItem*>( it.current() )->folder() == last )
00663     {
00664       mLastItem = static_cast<KMFolderTreeItem*>( it.current() );
00665       setCurrentItem( it.current() );
00666     }
00667     if ( selected &&
00668         static_cast<KMFolderTreeItem*>( it.current() )->folder() == selected )
00669     {
00670       setSelected( it.current(), true );
00671     }
00672     if ( oldCurrentFolder &&
00673         static_cast<KMFolderTreeItem*>( it.current() )->folder() == oldCurrentFolder )
00674     {
00675       oldCurrent = it.current();
00676     }
00677   }
00678   refresh();
00679   mReloading = false;
00680 }
00681 
00682 //-----------------------------------------------------------------------------
00683 void KMFolderTree::slotUpdateOneCount()
00684 {
00685   if ( !mUpdateIterator.current() ) return;
00686   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(mUpdateIterator.current());
00687   ++mUpdateIterator;
00688   if ( !fti->folder() ) {
00689     // next one please
00690     QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) );
00691     return;
00692   }
00693 
00694   // open the folder and update the count
00695   bool open = fti->folder()->isOpened();
00696   if (!open) fti->folder()->open();
00697   slotUpdateCounts(fti->folder());
00698   // restore previous state
00699   if (!open) fti->folder()->close();
00700 
00701   QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) );
00702 }
00703 
00704 //-----------------------------------------------------------------------------
00705 // Recursively add a directory of folders to the tree of folders
00706 void KMFolderTree::addDirectory( KMFolderDir *fdir, KMFolderTreeItem* parent )
00707 {
00708   for ( KMFolderNode * node = fdir->first() ; node ; node = fdir->next() ) {
00709     if ( node->isDir() )
00710       continue;
00711 
00712     KMFolder * folder = static_cast<KMFolder*>(node);
00713     KMFolderTreeItem * fti = 0;
00714     if (!parent)
00715     {
00716       // create new root-item, but only if this is not the root of a 
00717       // "groupware folders only" account
00718       if ( kmkernel->iCalIface().hideResourceAccountRoot( folder ) )
00719         continue;
00720       // it needs a folder e.g. to save it's state (open/close)
00721       fti = new KMFolderTreeItem( this, folder->label(), folder );
00722       fti->setExpandable( true );
00723     } else {
00724       // Check if this is an IMAP resource folder
00725       if ( kmkernel->iCalIface().hideResourceImapFolder( folder ) )
00726         // It is
00727         continue;
00728 
00729       // create new child
00730       fti = new KMFolderTreeItem( parent, folder->label(), folder );
00731       // set folders explicitely to exandable even with unknown child state
00732       // this way we can do a listing for IMAP folders when they're expanded
00733       if ( folder->storage()->hasChildren() != FolderStorage::HasNoChildren )
00734         fti->setExpandable( true );
00735       else
00736         fti->setExpandable( false );
00737 
00738       connect (fti, SIGNAL(iconChanged(KMFolderTreeItem*)),
00739                this, SIGNAL(iconChanged(KMFolderTreeItem*)));
00740       connect (fti, SIGNAL(nameChanged(KMFolderTreeItem*)),
00741                this, SIGNAL(nameChanged(KMFolderTreeItem*)));
00742     }
00743     // restore last open-state
00744     fti->setOpen( readIsListViewItemOpen(fti) );
00745 
00746     // add child-folders
00747     if (folder && folder->child()) {
00748       addDirectory( folder->child(), fti );
00749     }
00750    } // for-end
00751 }
00752 
00753 //-----------------------------------------------------------------------------
00754 // Initiate a delayed refresh of the tree
00755 void KMFolderTree::refresh()
00756 {
00757   mUpdateTimer.changeInterval(200);
00758 }
00759 
00760 //-----------------------------------------------------------------------------
00761 // Updates the pixmap and extendedLabel information for items
00762 void KMFolderTree::delayedUpdate()
00763 {
00764   bool upd = isUpdatesEnabled();
00765   if ( upd ) {
00766     setUpdatesEnabled(FALSE);
00767 
00768     for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) {
00769       KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00770       if (!fti || !fti->folder())
00771         continue;
00772 
00773       if ( fti->needsRepaint() ) {
00774         fti->repaint();
00775         fti->setNeedsRepaint( false );
00776       }
00777     }
00778     setUpdatesEnabled(upd);
00779   }
00780   mUpdateTimer.stop();
00781 }
00782 
00783 //-----------------------------------------------------------------------------
00784 // Folders have been added/deleted update the tree of folders
00785 void KMFolderTree::doFolderListChanged()
00786 {
00787   reload();
00788 }
00789 
00790 //-----------------------------------------------------------------------------
00791 void KMFolderTree::slotAccountRemoved(KMAccount *)
00792 {
00793   doFolderSelected( firstChild() );
00794 }
00795 
00796 //-----------------------------------------------------------------------------
00797 void KMFolderTree::slotFolderRemoved(KMFolder *aFolder)
00798 {
00799   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>
00800     (indexOfFolder(aFolder));
00801   if (!fti || !fti->folder()) return;
00802   if (fti == currentItem())
00803   {
00804     QListViewItem *qlvi = fti->itemAbove();
00805     if (!qlvi) qlvi = fti->itemBelow();
00806     doFolderSelected( qlvi );
00807   }
00808   removeFromFolderToItemMap( aFolder );
00809   delete fti;
00810 }
00811 
00812 //-----------------------------------------------------------------------------
00813 // Methods for navigating folders with the keyboard
00814 void KMFolderTree::prepareItem( KMFolderTreeItem* fti )
00815 {
00816   for ( QListViewItem * parent = fti->parent() ; parent ; parent = parent->parent() )
00817     parent->setOpen( TRUE );
00818   ensureItemVisible( fti );
00819 }
00820 
00821 //-----------------------------------------------------------------------------
00822 void KMFolderTree::nextUnreadFolder()
00823 {
00824     nextUnreadFolder( false );
00825 }
00826 
00827 //-----------------------------------------------------------------------------
00828 void KMFolderTree::nextUnreadFolder(bool confirm)
00829 {
00830   QListViewItemIterator it( currentItem() ? currentItem() : firstChild() );
00831   if ( currentItem() )
00832     ++it; // don't find current item
00833   for ( ; it.current() ; ++it ) {
00834     //check if folder is one to stop on
00835     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00836     if (checkUnreadFolder(fti,confirm)) return;
00837   }
00838   //Now if confirm is true we are doing "ReadOn"
00839   //we have got to the bottom of the folder list
00840   //so we have to start at the top
00841   if (confirm) {
00842     for ( it = firstChild() ; it.current() ; ++it ) {
00843       //check if folder is one to stop on
00844       KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00845       if (checkUnreadFolder(fti,confirm)) return;
00846     }
00847   }
00848 }
00849 
00850 //-----------------------------------------------------------------------------
00851 bool KMFolderTree::checkUnreadFolder (KMFolderTreeItem* fti, bool confirm)
00852 {
00853   if (fti && fti->folder()  &&
00854       (fti->folder()->countUnread() > 0)) {
00855 
00856     // Don't change into the trash or outbox folders.
00857     if (fti->type() == KFolderTreeItem::Trash ||
00858         fti->type() == KFolderTreeItem::Outbox )
00859       return false;
00860 
00861     if (confirm) {
00862       // Skip drafts and sent mail as well, when reading mail with the space bar
00863       // but not when changing into the next folder with unread mail via ctrl+ or
00864       // ctrl- so we do this only if (confirm == true), which means we are doing
00865       // readOn.
00866       if ( fti->type() == KFolderTreeItem::Drafts ||
00867            fti->type() == KFolderTreeItem::SentMail )
00868         return false;
00869 
00870       //  warn user that going to next folder - but keep track of
00871       //  whether he wishes to be notified again in "AskNextFolder"
00872       //  parameter (kept in the config file for kmail)
00873       if ( KMessageBox::questionYesNo( this,
00874             i18n( "<qt>Go to the next unread message in folder <b>%1</b>?</qt>" )
00875             .arg( fti->folder()->label() ),
00876             i18n( "Go to the Next Unread Message" ),
00877             KStdGuiItem::yes(), KStdGuiItem::no(), // defaults
00878             "AskNextFolder",
00879             false)
00880           == KMessageBox::No ) return true;
00881     }
00882     prepareItem( fti );
00883     blockSignals( true );
00884     doFolderSelected( fti );
00885     blockSignals( false );
00886     emit folderSelectedUnread( fti->folder() );
00887     return true;
00888   }
00889   return false;
00890 }
00891 
00892 //-----------------------------------------------------------------------------
00893 void KMFolderTree::prevUnreadFolder()
00894 {
00895   QListViewItemIterator it( currentItem() ? currentItem() : lastItem() );
00896   if ( currentItem() )
00897     --it; // don't find current item
00898   for ( ; it.current() ; --it ) {
00899     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00900     if (checkUnreadFolder(fti,false)) return;
00901   }
00902 }
00903 
00904 //-----------------------------------------------------------------------------
00905 void KMFolderTree::incCurrentFolder()
00906 {
00907   QListViewItemIterator it( currentItem() );
00908   ++it;
00909   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00910   if (fti && fti->folder()) {
00911       prepareItem( fti );
00912       setFocus();
00913       setCurrentItem( fti );
00914   }
00915 }
00916 
00917 //-----------------------------------------------------------------------------
00918 void KMFolderTree::decCurrentFolder()
00919 {
00920   QListViewItemIterator it( currentItem() );
00921   --it;
00922   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00923   if (fti && fti->folder()) {
00924       prepareItem( fti );
00925       setFocus();
00926       setCurrentItem( fti );
00927   }
00928 }
00929 
00930 //-----------------------------------------------------------------------------
00931 void KMFolderTree::selectCurrentFolder()
00932 {
00933   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() );
00934   if (fti && fti->folder()) {
00935       prepareItem( fti );
00936       doFolderSelected( fti );
00937   }
00938 }
00939 
00940 //-----------------------------------------------------------------------------
00941 KMFolder *KMFolderTree::currentFolder() const
00942 {
00943     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() );
00944     if (fti )
00945         return fti->folder();
00946     else
00947         return 0;
00948 }
00949 
00950 //-----------------------------------------------------------------------------
00951 // When not dragging and dropping a change in the selected item
00952 // indicates the user has changed the active folder emit a signal
00953 // so that the header list and reader window can be udpated.
00954 void KMFolderTree::doFolderSelected( QListViewItem* qlvi )
00955 {
00956   if (!qlvi) return;
00957   if ( mLastItem && mLastItem == qlvi )
00958     return;
00959 
00960   KMFolderTreeItem* fti = static_cast< KMFolderTreeItem* >(qlvi);
00961   KMFolder* folder = 0;
00962   if (fti) folder = fti->folder();
00963 
00964 
00965   if (mLastItem && mLastItem != fti && mLastItem->folder()
00966      && (mLastItem->folder()->folderType() == KMFolderTypeImap))
00967   {
00968     KMFolderImap *imapFolder = static_cast<KMFolderImap*>(mLastItem->folder()->storage());
00969     imapFolder->setSelected(FALSE);
00970   }
00971   mLastItem = fti;
00972 
00973   clearSelection();
00974   setCurrentItem( qlvi );
00975   setSelected( qlvi, TRUE );
00976   if (!folder) {
00977     emit folderSelected(0); // Root has been selected
00978   }
00979   else {
00980     emit folderSelected(folder);
00981     slotUpdateCounts(folder);
00982   }
00983 }
00984 
00985 //-----------------------------------------------------------------------------
00986 void KMFolderTree::resizeEvent(QResizeEvent* e)
00987 {
00988   KConfig* conf = KMKernel::config();
00989 
00990   KConfigGroupSaver saver(conf, "Geometry");
00991   conf->writeEntry(name(), size().width());
00992 
00993   KListView::resizeEvent(e);
00994 }
00995 
00996 //-----------------------------------------------------------------------------
00997 // show context menu
00998 void KMFolderTree::slotContextMenuRequested( QListViewItem *lvi,
00999                                              const QPoint &p )
01000 {
01001   if (!lvi)
01002     return;
01003   setCurrentItem( lvi );
01004   setSelected( lvi, TRUE );
01005 
01006   if (!mMainWidget) return; // safe bet
01007 
01008   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(lvi);
01009   if ( fti != mLastItem )
01010     doFolderSelected( fti );
01011 
01012   if (!fti )
01013     return;
01014 
01015   KPopupMenu *folderMenu = new KPopupMenu;
01016   if (fti->folder()) folderMenu->insertTitle(fti->folder()->label());
01017 
01018   if ((!fti->folder() || (fti->folder()->noContent()
01019     && !fti->parent())))
01020   {
01021     QString createChild = i18n("&New Subfolder...");
01022     if (!fti->folder()) createChild = i18n("&New Folder...");
01023 
01024     if (fti->folder() || (fti->text(0) != i18n("Searches")))
01025         folderMenu->insertItem(SmallIcon("folder_new"),
01026                                createChild, this,
01027                                SLOT(addChildFolder()));
01028 
01029     if (!fti->folder()) {
01030       folderMenu->insertItem(i18n("&Compact All Folders"),
01031                              kmkernel->folderMgr(), SLOT(compactAll()));
01032       folderMenu->insertItem(i18n("&Expire All Folders"),
01033                              kmkernel->folderMgr(), SLOT(expireAll()));
01034     } else if (fti->folder()->folderType() == KMFolderTypeImap) {
01035       folderMenu->insertItem(SmallIcon("mail_get"), i18n("Check &Mail"),
01036         this,
01037         SLOT(slotCheckMail()));
01038     }
01039   } else {
01040     if ((fti->folder() == kmkernel->outboxFolder()) && (fti->folder()->count()) )
01041         folderMenu->insertItem(SmallIcon("mail_send"),
01042                                i18n("&Send Queued Messages"), mMainWidget,
01043                                SLOT(slotSendQueued()));
01044     if (!fti->folder()->noChildren())
01045     {
01046       folderMenu->insertItem(SmallIcon("folder_new"),
01047                              i18n("&New Subfolder..."), this,
01048                              SLOT(addChildFolder()));
01049     }
01050 #ifdef DISABLED_BECAUSE_IT_IS_BUGGY
01051     if ( fti->folder()->isMoveable() )
01052     {
01053       QPopupMenu *moveMenu = new QPopupMenu( folderMenu );
01054       folderToPopupMenu( MoveFolder, this, &mMenuToFolder, moveMenu );
01055       folderMenu->insertItem( i18n("&Move Folder To"), moveMenu );
01056     }
01057 #endif
01058     if ( fti->folder()
01059        && fti->folder()->folderType() != KMFolderTypeImap  ) {
01060 //       && fti->folder()->folderType() != KMFolderTypeSearch ) {
01061       // copy folder
01062       QPopupMenu *copyMenu = new QPopupMenu( folderMenu );
01063       folderToPopupMenu( CopyFolder, this, &mMenuToFolder, copyMenu );
01064       folderMenu->insertItem( i18n("&Copy Folder To"), copyMenu );
01065     }
01066 
01067     // Want to be able to display properties for ALL folders,
01068     // so we can edit expiry properties.
01069     // -- smp.
01070     if (!fti->folder()->noContent())
01071     {
01072       int itemId = folderMenu->insertItem( SmallIcon("goto"),
01073                                            i18n("Mark All Messages as &Read"),
01074                                            mMainWidget,
01075                                            SLOT( slotMarkAllAsRead() ) );
01076       folderMenu->setItemEnabled( itemId, fti->folder()->countUnread() > 0 );
01077 
01078       folderMenu->insertItem(i18n("&Compact"), mMainWidget,
01079                              SLOT(slotCompactFolder()));
01080 
01081       itemId = folderMenu->insertItem(i18n("&Expire"), mMainWidget,
01082                                       SLOT(slotExpireFolder()));
01083       folderMenu->setItemEnabled( itemId, fti->folder()->isAutoExpire() && !fti->folder()->isReadOnly() );
01084 
01085 
01086       folderMenu->insertSeparator();
01087 
01088       itemId = folderMenu->insertItem(SmallIcon("edittrash"),
01089         (kmkernel->folderIsTrash(fti->folder())) ? i18n("&Empty") :
01090                              i18n("&Move All Messages to Trash"), mMainWidget,
01091                              SLOT(slotEmptyFolder()));
01092       folderMenu->setItemEnabled( itemId, fti->folder()->count() > 0 && !fti->folder()->isReadOnly() );
01093     }
01094     if ( !fti->folder()->isSystemFolder() )
01095       folderMenu->insertItem(SmallIcon("editdelete"),
01096                              i18n("&Delete Folder"), mMainWidget,
01097                              SLOT(slotRemoveFolder()));
01098 
01099   }
01100   if (fti->folder() &&
01101       (fti->folder()->folderType() == KMFolderTypeImap ||
01102        fti->folder()->folderType() == KMFolderTypeCachedImap ))
01103   {
01104     folderMenu->insertSeparator();
01105     folderMenu->insertItem(SmallIcon("bookmark_folder"),
01106         i18n("Subscription..."), mMainWidget,
01107         SLOT(slotSubscriptionDialog()));
01108     folderMenu->insertItem(SmallIcon("bookmark_folder"),
01109         i18n("Local Subscription..."), mMainWidget,
01110         SLOT(slotLocalSubscriptionDialog()));
01111 
01112     if (!fti->folder()->noContent())
01113     {
01114       int id = folderMenu->insertItem(SmallIcon("kmmsgnew"), i18n("Check Mail in This Folder"), mMainWidget,
01115                                       SLOT(slotRefreshFolder()));
01116       if ( fti->folder()->folderType() == KMFolderTypeImap ) {
01117         folderMenu->insertItem(SmallIcon("reload"), i18n("Refresh Folder List"), this,
01118             SLOT(slotResetFolderList()));
01119       } else {
01120         bool knownImapPath = !static_cast<KMFolderCachedImap*>( fti->folder()->storage() )->imapPath().isEmpty();
01121         folderMenu->setItemEnabled( id, knownImapPath );
01122 
01123       }
01124     }
01125     if ( fti->folder()->folderType() == KMFolderTypeCachedImap ) {
01126       KMFolderCachedImap * folder = static_cast<KMFolderCachedImap*>( fti->folder()->storage() );
01127       folderMenu->insertItem( SmallIcon("wizard"),
01128                               i18n("&Troubleshoot IMAP Cache..."),
01129                               folder, SLOT(slotTroubleshoot()) );
01130     }
01131   }
01132 
01133   if ( fti->folder() && fti->folder()->isMailingListEnabled() ) {
01134     folderMenu->insertSeparator();
01135     folderMenu->insertItem( i18n("New Message to Mailing-List..."),
01136                             this,
01137                             SLOT( slotNewMessageToMailingList() ) );
01138   }
01139 
01140   if (fti->folder() && fti->parent())
01141   {
01142     folderMenu->insertSeparator();
01143     folderMenu->insertItem(SmallIcon("configure"),
01144         i18n("&Properties"),
01145         fti,
01146         SLOT(properties()));
01147   }
01148 
01149 
01150   kmkernel->setContextMenuShown( true );
01151   folderMenu->exec (p, 0);
01152   kmkernel->setContextMenuShown( false );
01153   triggerUpdate();
01154   delete folderMenu;
01155   folderMenu = 0;
01156 }
01157 
01158 //-----------------------------------------------------------------------------
01159 // If middle button and folder holds mailing-list, create a message to that list
01160 void KMFolderTree::contentsMouseReleaseEvent(QMouseEvent* me)
01161 {
01162   QListViewItem *lvi = currentItem(); // Needed for when branches are clicked on
01163   ButtonState btn = me->button();
01164   doFolderSelected(lvi);
01165 
01166   // get underlying folder
01167   KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>(lvi);
01168 
01169   if (!fti || !fti->folder()) {
01170     KFolderTree::contentsMouseReleaseEvent(me);
01171     return;
01172   }
01173 
01174   // react on middle-button only
01175   if (btn != Qt::MidButton) {
01176     KFolderTree::contentsMouseReleaseEvent(me);
01177     return;
01178   }
01179 
01180   if ( fti->folder()->isMailingListEnabled() ) {
01181     KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
01182     command->start();
01183   }
01184 
01185   KFolderTree::contentsMouseReleaseEvent(me);
01186 }
01187 
01188 // little static helper
01189 static bool folderHasCreateRights( const KMFolder *folder )
01190 {
01191   bool createRights = true; // we don't have acls for local folders yet
01192   if ( folder && folder->folderType() == KMFolderTypeImap ) {
01193     // for online IMAP we assume things will work out, initially
01194     const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
01195     createRights =
01196       imapFolder->userRights() == 0 || ( imapFolder->userRights() & KMail::ACLJobs::Create );
01197   } else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) {
01198     const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
01199     createRights =
01200       dimapFolder->userRights() > 0 && ( dimapFolder->userRights() & KMail::ACLJobs::Create );
01201   }
01202   return createRights;
01203 }
01204 
01205 //-----------------------------------------------------------------------------
01206 // Create a subfolder.
01207 // Requires creating the appropriate subdirectory and show a dialog
01208 void KMFolderTree::addChildFolder()
01209 {
01210   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(currentItem());
01211   if (!fti)
01212     return;
01213   KMFolder *aFolder = fti->folder();
01214   if (aFolder) {
01215     if (!aFolder->createChildFolder())
01216       return;
01217     if ( !folderHasCreateRights( aFolder ) ) {
01218       const QString message = i18n( "<qt>Cannot create folder <b>%1</b> because of insufficient "
01219                                     "permissions on the server. If you think you should be able to create "
01220                                     "subfolders here, ask your administrator to grant you rights to do so."
01221                                     "</qt> " ).arg(aFolder->name());
01222       KMessageBox::error( this, message );
01223       return;
01224     }
01225   }
01226 
01227   KMFolderDir *dir = &(kmkernel->folderMgr()->dir());
01228   if (aFolder)
01229     dir = aFolder->child();
01230 
01231   KMFolderDialog *d =
01232     new KMFolderDialog(0, dir, this, i18n("Create Subfolder") );
01233 
01234   if (d->exec()) /* fti may be deleted here */ {
01235     QListViewItem *qlvi = indexOfFolder( aFolder );
01236     if (qlvi) {
01237       qlvi->setOpen(TRUE);
01238       blockSignals( true );
01239       setCurrentItem( qlvi );
01240       blockSignals( false );
01241     }
01242   }
01243   delete d;
01244   // update if added to root Folder
01245   if (!aFolder || aFolder->noContent()) {
01246      doFolderListChanged();
01247   }
01248 }
01249 
01250 //-----------------------------------------------------------------------------
01251 // Returns whether a folder directory should be open as specified in the
01252 // config file.
01253 bool KMFolderTree::readIsListViewItemOpen(KMFolderTreeItem *fti)
01254 {
01255   KConfig* config = KMKernel::config();
01256   KMFolder *folder = fti->folder();
01257   QString name;
01258   if (folder)
01259   {
01260     name = "Folder-" + folder->idString();
01261   } else if (fti->type() == KFolderTreeItem::Root)
01262   {
01263     if (fti->protocol() == KFolderTreeItem::NONE) // local root
01264       name = "Folder_local_root";
01265     else if (fti->protocol() == KFolderTreeItem::Search)
01266       name = "Folder_search";
01267     else
01268       return false;
01269   } else {
01270     return false;
01271   }
01272   KConfigGroupSaver saver(config, name);
01273 
01274   return config->readBoolEntry("isOpen", false);
01275 }
01276 
01277 //-----------------------------------------------------------------------------
01278 // Saves open/closed state of a folder directory into the config file
01279 void KMFolderTree::writeIsListViewItemOpen(KMFolderTreeItem *fti)
01280 {
01281   KConfig* config = KMKernel::config();
01282   KMFolder *folder = fti->folder();
01283   QString name;
01284   if (folder)
01285   {
01286     name = "Folder-" + folder->idString();
01287   } else if (fti->type() == KFolderTreeItem::Root)
01288   {
01289     if (fti->protocol() == KFolderTreeItem::NONE) // local root
01290       name = "Folder_local_root";
01291     else if (fti->protocol() == KFolderTreeItem::Search)
01292       name = "Folder_search";
01293     else
01294       return;
01295   } else {
01296     return;
01297   }
01298   KConfigGroupSaver saver(config, name);
01299   config->writeEntry("isOpen", fti->isOpen() );
01300 }
01301 
01302 
01303 //-----------------------------------------------------------------------------
01304 void KMFolderTree::cleanupConfigFile()
01305 {
01306   if ( childCount() == 0 )
01307     return; // just in case reload wasn't called before
01308   KConfig* config = KMKernel::config();
01309   QStringList existingFolders;
01310   QListViewItemIterator fldIt(this);
01311   QMap<QString,bool> folderMap;
01312   KMFolderTreeItem *fti;
01313   for (QListViewItemIterator fldIt(this); fldIt.current(); fldIt++)
01314   {
01315     fti = static_cast<KMFolderTreeItem*>(fldIt.current());
01316     if (fti && fti->folder())
01317       folderMap.insert(fti->folder()->idString(), true);
01318   }
01319   QStringList groupList = config->groupList();
01320   QString name;
01321   for (QStringList::Iterator grpIt = groupList.begin();
01322     grpIt != groupList.end(); grpIt++)
01323   {
01324     if ((*grpIt).left(7) != "Folder-") continue;
01325     name = (*grpIt).mid(7);
01326     if (folderMap.find(name) == folderMap.end())
01327     {
01328       KMFolder* folder = kmkernel->findFolderById( name );
01329       if ( folder ) {
01330           if ( kmkernel->iCalIface().hideResourceImapFolder( folder )
01331            ||  kmkernel->iCalIface().hideResourceAccountRoot( folder ) )
01332         continue; // hidden IMAP resource folder, don't delete info
01333       }
01334 
01335       config->deleteGroup(*grpIt, TRUE);
01336       kdDebug(5006) << "Deleting information about folder " << name << endl;
01337     }
01338   }
01339 }
01340 
01341 
01342 //-----------------------------------------------------------------------------
01343 // Drag and Drop handling -- based on the Troll Tech dirview example
01344 
01345 enum {
01346   DRAG_COPY = 0,
01347   DRAG_MOVE = 1,
01348   DRAG_CANCEL = 2
01349 };
01350 
01351 //-----------------------------------------------------------------------------
01352 void KMFolderTree::openFolder()
01353 {
01354     autoopen_timer.stop();
01355     if ( dropItem && !dropItem->isOpen() ) {
01356         dropItem->setOpen( TRUE );
01357         dropItem->repaint();
01358     }
01359 }
01360 
01361 static const int autoopenTime = 750;
01362 
01363 //-----------------------------------------------------------------------------
01364 void KMFolderTree::contentsDragEnterEvent( QDragEnterEvent *e )
01365 {
01366   oldCurrent = 0;
01367   oldSelected = 0;
01368 
01369   oldCurrent = currentItem();
01370   for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
01371     if ( it.current()->isSelected() )
01372       oldSelected = it.current();
01373 
01374   setFocus();
01375 
01376   QListViewItem *i = itemAt( contentsToViewport(e->pos()) );
01377   if ( i ) {
01378     dropItem = i;
01379     autoopen_timer.start( autoopenTime );
01380   }
01381   e->accept( acceptDrag(e) );
01382 }
01383 
01384 //-----------------------------------------------------------------------------
01385 void KMFolderTree::contentsDragMoveEvent( QDragMoveEvent *e )
01386 {
01387     QPoint vp = contentsToViewport(e->pos());
01388     QListViewItem *i = itemAt( vp );
01389     if ( i ) {
01390         bool dragAccepted = acceptDrag( e );
01391         if ( dragAccepted ) {
01392             setCurrentItem( i );
01393         }
01394 
01395         if ( i != dropItem ) {
01396             autoopen_timer.stop();
01397             dropItem = i;
01398             autoopen_timer.start( autoopenTime );
01399         }
01400 
01401         if ( dragAccepted ) {
01402             e->accept( itemRect(i) );
01403 
01404             switch ( e->action() ) {
01405                 case QDropEvent::Copy:
01406                 break;
01407                 case QDropEvent::Move:
01408                 e->acceptAction();
01409                 break;
01410                 case QDropEvent::Link:
01411                 e->acceptAction();
01412                 break;
01413                 default:
01414                 ;
01415             }
01416         } else {
01417             e->accept( false );
01418         }
01419     } else {
01420         e->accept( false );
01421         autoopen_timer.stop();
01422         dropItem = 0;
01423     }
01424 }
01425 
01426 //-----------------------------------------------------------------------------
01427 void KMFolderTree::contentsDragLeaveEvent( QDragLeaveEvent * )
01428 {
01429     if (!oldCurrent) return;
01430 
01431     autoopen_timer.stop();
01432     dropItem = 0;
01433 
01434     setCurrentItem( oldCurrent );
01435     if ( oldSelected )
01436       setSelected( oldSelected, TRUE );
01437 }
01438 
01439 //-----------------------------------------------------------------------------
01440 void KMFolderTree::contentsDropEvent( QDropEvent *e )
01441 {
01442     autoopen_timer.stop();
01443 
01444     QListViewItem *item = itemAt( contentsToViewport(e->pos()) );
01445     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01446     if (fti && (fti != oldSelected) && (fti->folder()) && acceptDrag(e))
01447     {
01448       int keybstate = kapp->keyboardModifiers();
01449       if ( keybstate & KApplication::ControlModifier ) {
01450         emit folderDropCopy(fti->folder());
01451       } else if ( keybstate & KApplication::ShiftModifier ) {
01452         emit folderDrop(fti->folder());
01453       } else {
01454         if ( GlobalSettings::self()->showPopupAfterDnD() ) {
01455           KPopupMenu *menu = new KPopupMenu( this );
01456           menu->insertItem( i18n("&Move Here"), DRAG_MOVE, 0 );
01457           menu->insertItem( SmallIcon("editcopy"), i18n("&Copy Here"), DRAG_COPY, 1 );
01458           menu->insertSeparator();
01459           menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), DRAG_CANCEL, 3 );
01460           int id = menu->exec( QCursor::pos(), 0 );
01461           switch(id) {
01462             case DRAG_COPY:
01463               emit folderDropCopy(fti->folder());
01464               break;
01465             case DRAG_MOVE:
01466               emit folderDrop(fti->folder());
01467               break;
01468             case DRAG_CANCEL: // cancelled by menuitem
01469             case -1: // cancelled by Esc
01470               //just chill, doing nothing
01471               break;
01472             default:
01473               kdDebug(5006) << "Unknown dnd-type! " << id << endl;
01474           }
01475         }
01476         else
01477           emit folderDrop(fti->folder());
01478       }
01479       e->accept( true );
01480     } else
01481       e->accept( false );
01482 
01483     dropItem = 0;
01484 
01485     setCurrentItem( oldCurrent );
01486     if ( oldCurrent) mLastItem = static_cast<KMFolderTreeItem*>(oldCurrent);
01487     if ( oldSelected )
01488     {
01489       clearSelection();
01490       setSelected( oldSelected, TRUE );
01491     }
01492 }
01493 
01494 //-----------------------------------------------------------------------------
01495 void KMFolderTree::slotFolderExpanded( QListViewItem * item )
01496 {
01497   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01498 
01499   if ( fti && fti->folder() &&
01500        fti->folder()->folderType() == KMFolderTypeImap )
01501   {
01502     KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
01503     // if we should list all folders we limit this to the root folder
01504     if ( !folder->account()->listOnlyOpenFolders() &&
01505          fti->parent() )
01506       return;
01507     if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation )
01508     {
01509       // check if all parents are expanded
01510       QListViewItem *parent = item->parent();
01511       while ( parent )
01512       {
01513         if ( !parent->isOpen() )
01514           return;
01515         parent = parent->parent();
01516       }
01517       // the tree will be reloaded after that
01518       bool success = folder->listDirectory();
01519       if (!success) fti->setOpen( false );
01520       if ( fti->childCount() == 0 && fti->parent() )
01521         fti->setExpandable( false );
01522     }
01523   }
01524 }
01525 
01526 
01527 //-----------------------------------------------------------------------------
01528 void KMFolderTree::slotFolderCollapsed( QListViewItem * item )
01529 {
01530   slotResetFolderList( item, false );
01531 }
01532 
01533 //-----------------------------------------------------------------------------
01534 void KMFolderTree::slotRenameFolder(QListViewItem *item, int col,
01535                 const QString &text)
01536 {
01537 
01538   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01539 
01540   if (fti && fti->folder() && col != 0 && !currentFolder()->child())
01541           return;
01542 
01543   QString fldName, oldFldName;
01544 
01545   oldFldName = fti->name(0);
01546 
01547   if (!text.isEmpty())
01548           fldName = text;
01549   else
01550           fldName = oldFldName;
01551 
01552   fldName.replace("/", "");
01553   fldName.replace(QRegExp("^\\."), "");
01554 
01555   if (fldName.isEmpty())
01556           fldName = i18n("unnamed");
01557 
01558   fti->setText(0, fldName);
01559   fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir()));
01560 }
01561 
01562 //-----------------------------------------------------------------------------
01563 void KMFolderTree::slotUpdateCounts(KMFolderImap * folder, bool success)
01564 {
01565   if (success) slotUpdateCounts(folder->folder());
01566 }
01567 
01568 //-----------------------------------------------------------------------------
01569 void KMFolderTree::slotUpdateCounts(KMFolder * folder)
01570 {
01571   QListViewItem * current;
01572 
01573   if (folder)
01574     current = indexOfFolder(folder);
01575   else
01576     current = currentItem();
01577 
01578   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(current);
01579   // sanity check
01580   if (!fti) return;
01581   if (!fti->folder()) fti->setTotalCount(-1);
01582 
01583   // get the unread count
01584   int count = 0;
01585   if (folder->noContent()) // always empty
01586     count = -1;
01587   else
01588     count = fti->folder()->countUnread();
01589 
01590   // set it
01591   bool repaint = false;
01592   if (fti->unreadCount() != count) {
01593      fti->adjustUnreadCount( count );
01594      repaint = true;
01595   }
01596 
01597   if (isTotalActive())
01598   {
01599     // get the total-count
01600     if (fti->folder()->noContent())
01601       count = -1;
01602     else {
01603       // get the cached count if the folder is not open
01604       count = fti->folder()->count( !fti->folder()->isOpened() );
01605     }
01606     // set it
01607     if ( count != fti->totalCount() ) {
01608       fti->setTotalCount(count);
01609       repaint = true;
01610     }
01611   }
01612   if (fti->parent() && !fti->parent()->isOpen())
01613     repaint = false; // we're not visible
01614   if (repaint) {
01615     fti->setNeedsRepaint( true );
01616     refresh();
01617   }
01618   // tell the kernel that one of the counts has changed
01619   kmkernel->messageCountChanged();
01620 }
01621 
01622 void KMFolderTree::updatePopup() const
01623 {
01624    mPopup->setItemChecked( mUnreadPop, isUnreadActive() );
01625    mPopup->setItemChecked( mTotalPop, isTotalActive() );
01626 }
01627 
01628 //-----------------------------------------------------------------------------
01629 void KMFolderTree::toggleColumn(int column, bool openFolders)
01630 {
01631   if (column == unread)
01632   {
01633     // switch unread
01634     if ( isUnreadActive() )
01635     {
01636       removeUnreadColumn();
01637       reload();
01638     } else {
01639       addUnreadColumn( i18n("Unread"), 70 );
01640       reload();
01641     }
01642     // toggle KPopupMenu
01643     mPopup->setItemChecked( mUnreadPop, isUnreadActive() );
01644 
01645   } else if (column == total) {
01646     // switch total
01647     if ( isTotalActive() )
01648     {
01649       removeTotalColumn();
01650       reload();
01651     } else {
01652       addTotalColumn( i18n("Total"), 70 );
01653       reload(openFolders);
01654     }
01655     // toggle KPopupMenu
01656     mPopup->setItemChecked( mTotalPop, isTotalActive() );
01657 
01658   } else kdDebug(5006) << "unknown column:" << column << endl;
01659 
01660   // toggles the switches of the mainwin
01661   emit columnsChanged();
01662 }
01663 
01664 //-----------------------------------------------------------------------------
01665 void KMFolderTree::slotToggleUnreadColumn()
01666 {
01667   toggleColumn(unread);
01668 }
01669 
01670 //-----------------------------------------------------------------------------
01671 void KMFolderTree::slotToggleTotalColumn()
01672 {
01673   // activate the total-column and force the folders to be opened
01674   toggleColumn(total, true);
01675 }
01676 
01677 //-----------------------------------------------------------------------------
01678 bool KMFolderTree::eventFilter( QObject *o, QEvent *e )
01679 {
01680   if ( e->type() == QEvent::MouseButtonPress &&
01681       static_cast<QMouseEvent*>(e)->button() == RightButton &&
01682       o->isA("QHeader") )
01683   {
01684     mPopup->popup( static_cast<QMouseEvent*>(e)->globalPos() );
01685     return true;
01686   }
01687   return KFolderTree::eventFilter(o, e);
01688 }
01689 
01690 //-----------------------------------------------------------------------------
01691 void KMFolderTree::slotCheckMail()
01692 {
01693   if (!currentItem())
01694     return;
01695   KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(currentItem());
01696   KMFolder* folder = fti->folder();
01697   if (folder && folder->folderType() == KMFolderTypeImap)
01698   {
01699     KMAccount* acct = static_cast<KMFolderImap*>(folder->storage())->account();
01700     kmkernel->acctMgr()->singleCheckMail(acct, true);
01701   }
01702 }
01703 
01704 //-----------------------------------------------------------------------------
01705 void KMFolderTree::slotNewMessageToMailingList()
01706 {
01707   KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( currentItem() );
01708   if ( !fti || !fti->folder() )
01709     return;
01710   KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
01711   command->start();
01712 }
01713 
01714 //-----------------------------------------------------------------------------
01715 void KMFolderTree::createFolderList( QStringList *str,
01716                                      QValueList<QGuardedPtr<KMFolder> > *folders,
01717                                      bool localFolders,
01718                                      bool imapFolders,
01719                                      bool dimapFolders,
01720                                      bool searchFolders,
01721                                      bool includeNoContent,
01722                                      bool includeNoChildren )
01723 {
01724   for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
01725   {
01726     KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
01727     if (!fti || !fti->folder()) continue;
01728     // type checks
01729     KMFolder* folder = fti->folder();
01730     if (!imapFolders && folder->folderType() == KMFolderTypeImap) continue;
01731     if (!dimapFolders && folder->folderType() == KMFolderTypeCachedImap) continue;
01732     if (!localFolders && (folder->folderType() == KMFolderTypeMbox ||
01733                           folder->folderType() == KMFolderTypeMaildir)) continue;
01734     if (!searchFolders && folder->folderType() == KMFolderTypeSearch) continue;
01735     if (!includeNoContent && folder->noContent()) continue;
01736     if (!includeNoChildren && folder->noChildren()) continue;
01737     QString prefix;
01738     prefix.fill( ' ', 2 * fti->depth() );
01739     str->append(prefix + fti->text(0));
01740     folders->append(fti->folder());
01741   }
01742 }
01743 
01744 //-----------------------------------------------------------------------------
01745 void KMFolderTree::slotResetFolderList( QListViewItem* item, bool startList )
01746 {
01747   if ( !item )
01748     item = currentItem();
01749 
01750   KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( item );
01751   if ( fti && fti->folder() &&
01752        fti->folder()->folderType() == KMFolderTypeImap )
01753   {
01754     KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
01755     folder->setSubfolderState( KMFolderImap::imapNoInformation );
01756     if ( startList )
01757       folder->listDirectory();
01758   }
01759 }
01760 
01761 //-----------------------------------------------------------------------------
01762 void KMFolderTree::showFolder( KMFolder* folder )
01763 {
01764   if ( !folder ) return;
01765   QListViewItem* item = indexOfFolder( folder );
01766   if ( item )
01767   {
01768     doFolderSelected( item );
01769     ensureItemVisible( item );
01770   }
01771 }
01772 
01773 //-----------------------------------------------------------------------------
01774 void KMFolderTree::folderToPopupMenu( MenuAction action, QObject *receiver,
01775     KMMenuToFolder *aMenuToFolder, QPopupMenu *menu, QListViewItem *item )
01776 {
01777   while ( menu->count() )
01778   {
01779     QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01780     if ( popup )
01781       delete popup;
01782     else
01783       menu->removeItemAt( 0 );
01784   }
01785   // connect the signals
01786   if ( action == MoveMessage || action == MoveFolder )
01787   {
01788     disconnect( menu, SIGNAL(activated(int)), receiver,
01789         SLOT(moveSelectedToFolder(int)) );
01790     connect( menu, SIGNAL(activated(int)), receiver,
01791         SLOT(moveSelectedToFolder(int)) );
01792   } else {
01793     disconnect( menu, SIGNAL(activated(int)), receiver,
01794         SLOT(copySelectedToFolder(int)) );
01795     connect( menu, SIGNAL(activated(int)), receiver,
01796         SLOT(copySelectedToFolder(int)) );
01797   }
01798   if ( !item ) {
01799     item = firstChild();
01800 
01801     // avoid a popup menu with the single entry 'Local Folders' if there
01802     // are no IMAP accounts
01803     if ( childCount() == 2 && action != MoveFolder ) { // only 'Local Folders' and 'Searches'
01804       KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item );
01805       if ( fti->protocol() == KFolderTreeItem::Search ) {
01806         // skip 'Searches'
01807         item = item->nextSibling();
01808         fti = static_cast<KMFolderTreeItem*>( item );
01809       }
01810       folderToPopupMenu( action, receiver, aMenuToFolder, menu, fti->firstChild() );
01811       return;
01812     }
01813   }
01814 
01815   while ( item )
01816   {
01817     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( item );
01818     if ( fti->protocol() == KFolderTreeItem::Search )
01819     {
01820       // skip search folders
01821       item = item->nextSibling();
01822       continue;
01823     }
01824     QString label = fti->text( 0 );
01825     label.replace( "&","&&" );
01826     if ( fti->firstChild() )
01827     {
01828       // new level
01829       QPopupMenu* popup = new QPopupMenu( menu, "subMenu" );
01830       folderToPopupMenu( action, receiver, aMenuToFolder, popup, fti->firstChild() );
01831       bool subMenu = false;
01832       if ( ( action == MoveMessage || action == CopyMessage ) &&
01833            fti->folder() && !fti->folder()->noContent() )
01834         subMenu = true;
01835       if ( ( action == MoveFolder || action == CopyFolder )
01836           && ( !fti->folder() || ( fti->folder() && !fti->folder()->noChildren() ) ) )
01837         subMenu = true;
01838       if ( subMenu )
01839       {
01840         int menuId;
01841         if ( action == MoveMessage || action == MoveFolder )
01842           menuId = popup->insertItem( i18n("Move to This Folder"), -1, 0 );
01843         else
01844           menuId = popup->insertItem( i18n("Copy to This Folder"), -1, 0 );
01845         popup->insertSeparator( 1 );
01846         aMenuToFolder->insert( menuId, fti->folder() );
01847       }
01848       menu->insertItem( label, popup );
01849     } else
01850     {
01851       // insert an item
01852       int menuId = menu->insertItem( label );
01853       if ( fti->folder() )
01854         aMenuToFolder->insert( menuId, fti->folder() );
01855       bool enabled = (fti->folder() ? true : false);
01856       if ( fti->folder() &&
01857            ( fti->folder()->isReadOnly() || fti->folder()->noContent() ) )
01858         enabled = false;
01859       menu->setItemEnabled( menuId, enabled );
01860     }
01861 
01862     item = item->nextSibling();
01863   }
01864 }
01865 
01866 //-----------------------------------------------------------------------------
01867 void KMFolderTree::moveSelectedToFolder( int menuId )
01868 {
01869   moveOrCopyCurrentFolder( mMenuToFolder[ menuId ], true /*move*/ );
01870 }
01871 
01872 //-----------------------------------------------------------------------------
01873 void KMFolderTree::copySelectedToFolder( int menuId )
01874 {
01875   moveOrCopyCurrentFolder( mMenuToFolder[ menuId ], false /*copy, don't move*/ );
01876 }
01877 
01878 //-----------------------------------------------------------------------------
01879 void KMFolderTree::moveOrCopyCurrentFolder( KMFolder* destination, bool move )
01880 {
01881   KMFolder* folder = currentFolder();
01882   KMFolderDir* parent = &(kmkernel->folderMgr()->dir());
01883   if ( destination )
01884     parent = destination->createChildFolder();
01885   QString message =
01886     i18n( "<qt>Cannot move or copy folder <b>%1</b> into a subfolder below itself.</qt>" ).
01887         arg( folder->label() );
01888 
01889   KMFolderDir* folderDir = parent;
01890   // check that the folder can be moved
01891   if ( folder && folder->child() )
01892   {
01893     while ( folderDir && ( folderDir != &kmkernel->folderMgr()->dir() ) &&
01894         ( folderDir != folder->parent() ) )
01895     {
01896       if ( folderDir->findRef( folder ) != -1 )
01897       {
01898         KMessageBox::error( this, message );
01899         return;
01900       }
01901       folderDir = folderDir->parent();
01902     }
01903   }
01904 
01905   if( folder && folder->child() && parent &&
01906       ( parent->path().find( folder->child()->path() + "/" ) == 0 ) ) {
01907     KMessageBox::error( this, message );
01908     return;
01909   }
01910 
01911   if( folder && folder->child()
01912       && ( parent == folder->child() ) ) {
01913     KMessageBox::error( this, message );
01914     return;
01915   }
01916 
01917   if ( move ) {
01918     kdDebug(5006) << "move folder " << currentFolder()->label() << " to "
01919       << ( destination ? destination->label() : "Local Folders" ) << endl;
01920     kmkernel->folderMgr()->moveFolder( folder, parent );
01921   } else {
01922     kmkernel->folderMgr()->copyFolder( folder, parent );
01923   }
01924 }
01925 
01926 void KMFolderTree::slotReceivedQuotaInfo( KMFolder* folder,
01927                                           KIO::Job*,
01928                                           const KMail::QuotaInfo& info )
01929 {
01930  // kdDebug( 5006 ) << "KMFolderTree::slotReceivedQuotaInfo() - Updating quota info!" << endl;
01931   QString str( folder->label() );
01932   QString infoString = info.toString();
01933   if ( !infoString.isEmpty() ) {
01934     str += " (" + infoString + ')';
01935   }
01936   mToolTip->updateTip( str );
01937 }
01938 
01939 
01940 #include "kmfoldertree.moc"
01941 
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 Fri Dec 21 14:24:54 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003