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