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