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 if ( !fti->folder()->isSystemFolder() )
01024 mMainWidget->action("delete_folder")->plug(folderMenu);
01025
01026 folderMenu->insertSeparator();
01027 mMainWidget->action("empty")->plug(folderMenu);
01028 folderMenu->insertSeparator();
01029 }
01030 }
01031
01032
01033 if (fti->folder() &&
01034 (fti->folder()->folderType() == KMFolderTypeImap ||
01035 fti->folder()->folderType() == KMFolderTypeCachedImap ))
01036 {
01037 folderMenu->insertItem(SmallIconSet("bookmark_folder"),
01038 i18n("Subscription..."), mMainWidget,
01039 SLOT(slotSubscriptionDialog()));
01040
01041 if (!fti->folder()->noContent())
01042 {
01043 mMainWidget->action("refresh_folder")->plug(folderMenu);
01044 if ( fti->folder()->folderType() == KMFolderTypeImap ) {
01045 folderMenu->insertItem(SmallIconSet("reload"), i18n("Refresh Folder List"), this,
01046 SLOT(slotResetFolderList()));
01047 }
01048 }
01049 if ( fti->folder()->folderType() == KMFolderTypeCachedImap ) {
01050 KMFolderCachedImap * folder = static_cast<KMFolderCachedImap*>( fti->folder()->storage() );
01051 folderMenu->insertItem( SmallIconSet("wizard"),
01052 i18n("&Troubleshoot IMAP Cache..."),
01053 folder, SLOT(slotTroubleshoot()) );
01054 }
01055 folderMenu->insertSeparator();
01056 }
01057
01058 if ( fti->folder() && fti->folder()->isMailingListEnabled() ) {
01059 mMainWidget->action("post_message")->plug(folderMenu);
01060 }
01061
01062 if (fti->folder() && fti->parent())
01063 {
01064 folderMenu->insertItem(SmallIconSet("configure_shortcuts"),
01065 i18n("&Assign Shortcut..."),
01066 fti,
01067 SLOT(assignShortcut()));
01068
01069 if ( !fti->folder()->noContent() ) {
01070 folderMenu->insertItem( i18n("Expire..."), fti,
01071 SLOT( slotShowExpiryProperties() ) );
01072 }
01073 mMainWidget->action("modify")->plug(folderMenu);
01074 }
01075
01076
01077 kmkernel->setContextMenuShown( true );
01078 folderMenu->exec (p, 0);
01079 kmkernel->setContextMenuShown( false );
01080 triggerUpdate();
01081 delete folderMenu;
01082 folderMenu = 0;
01083 }
01084
01085
01086
01087 void KMFolderTree::contentsMouseReleaseEvent(QMouseEvent* me)
01088 {
01089 QListViewItem *lvi = currentItem();
01090 ButtonState btn = me->button();
01091 doFolderSelected(lvi);
01092
01093
01094 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>(lvi);
01095
01096 if (!fti || !fti->folder()) {
01097 KFolderTree::contentsMouseReleaseEvent(me);
01098 return;
01099 }
01100
01101
01102 if (btn != Qt::MidButton) {
01103 KFolderTree::contentsMouseReleaseEvent(me);
01104 return;
01105 }
01106
01107 if ( fti->folder()->isMailingListEnabled() ) {
01108 KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
01109 command->start();
01110 }
01111
01112 KFolderTree::contentsMouseReleaseEvent(me);
01113 }
01114
01115
01116 static bool folderHasCreateRights( const KMFolder *folder )
01117 {
01118 bool createRights = true;
01119 if ( folder && folder->folderType() == KMFolderTypeImap ) {
01120 const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
01121 createRights = imapFolder->userRights() == 0 ||
01122 ( imapFolder->userRights() > 0 && ( imapFolder->userRights() & KMail::ACLJobs::Create ) );
01123 } else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) {
01124 const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
01125 createRights = dimapFolder->userRights() == 0 ||
01126 ( dimapFolder->userRights() > 0 && ( dimapFolder->userRights() & KMail::ACLJobs::Create ) );
01127 }
01128 return createRights;
01129 }
01130
01131
01132
01133
01134 void KMFolderTree::addChildFolder( KMFolder *folder, QWidget * parent )
01135 {
01136 KMFolder *aFolder = folder;
01137 if ( !aFolder ) {
01138 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(currentItem());
01139 if (!fti)
01140 return;
01141 aFolder = fti->folder();
01142 }
01143 if (aFolder) {
01144 if (!aFolder->createChildFolder())
01145 return;
01146 if ( !folderHasCreateRights( aFolder ) ) {
01147
01148 const QString message = i18n( "<qt>Cannot create folder <b>%1</b> because of insufficient "
01149 "permissions on the server. If you think you should be able to create "
01150 "subfolders here, ask your administrator to grant you rights to do so."
01151 "</qt> " ).arg(aFolder->label());
01152 KMessageBox::error( this, message );
01153 return;
01154 }
01155 }
01156
01157 if ( parent )
01158 ( new KMail::NewFolderDialog( parent, aFolder ) )->exec();
01159 else
01160 ( new KMail::NewFolderDialog( this, aFolder ) )->show();
01161 return;
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
01187
01188
01189
01190 bool KMFolderTree::readIsListViewItemOpen(KMFolderTreeItem *fti)
01191 {
01192 KConfig* config = KMKernel::config();
01193 KMFolder *folder = fti->folder();
01194 QString name;
01195 if (folder)
01196 {
01197 name = "Folder-" + folder->idString();
01198 } else if (fti->type() == KFolderTreeItem::Root)
01199 {
01200 if (fti->protocol() == KFolderTreeItem::NONE)
01201 name = "Folder_local_root";
01202 else if (fti->protocol() == KFolderTreeItem::Search)
01203 name = "Folder_search";
01204 else
01205 return false;
01206 } else {
01207 return false;
01208 }
01209 KConfigGroupSaver saver(config, name);
01210
01211 return config->readBoolEntry("isOpen", false);
01212 }
01213
01214
01215
01216 void KMFolderTree::writeIsListViewItemOpen(KMFolderTreeItem *fti)
01217 {
01218 KConfig* config = KMKernel::config();
01219 KMFolder *folder = fti->folder();
01220 QString name;
01221 if (folder && !folder->idString().isEmpty())
01222 {
01223 name = "Folder-" + folder->idString();
01224 } else if (fti->type() == KFolderTreeItem::Root)
01225 {
01226 if (fti->protocol() == KFolderTreeItem::NONE)
01227 name = "Folder_local_root";
01228 else if (fti->protocol() == KFolderTreeItem::Search)
01229 name = "Folder_search";
01230 else
01231 return;
01232 } else {
01233 return;
01234 }
01235 KConfigGroupSaver saver(config, name);
01236 config->writeEntry("isOpen", fti->isOpen() );
01237 }
01238
01239
01240
01241 void KMFolderTree::cleanupConfigFile()
01242 {
01243 if ( childCount() == 0 )
01244 return;
01245 KConfig* config = KMKernel::config();
01246 QStringList existingFolders;
01247 QListViewItemIterator fldIt(this);
01248 QMap<QString,bool> folderMap;
01249 KMFolderTreeItem *fti;
01250 for (QListViewItemIterator fldIt(this); fldIt.current(); fldIt++)
01251 {
01252 fti = static_cast<KMFolderTreeItem*>(fldIt.current());
01253 if (fti && fti->folder())
01254 folderMap.insert(fti->folder()->idString(), true);
01255 }
01256 QStringList groupList = config->groupList();
01257 QString name;
01258 for (QStringList::Iterator grpIt = groupList.begin();
01259 grpIt != groupList.end(); grpIt++)
01260 {
01261 if ((*grpIt).left(7) != "Folder-") continue;
01262 name = (*grpIt).mid(7);
01263 if (folderMap.find(name) == folderMap.end())
01264 {
01265 KMFolder* folder = kmkernel->findFolderById( name );
01266 if ( folder && kmkernel->iCalIface().hideResourceFolder( folder ) )
01267 continue;
01268
01269
01270 config->deleteGroup(*grpIt, TRUE);
01271 kdDebug(5006) << "Deleting information about folder " << name << endl;
01272 }
01273 }
01274 }
01275
01276
01277
01278
01279
01280 enum {
01281 DRAG_COPY = 0,
01282 DRAG_MOVE = 1,
01283 DRAG_CANCEL = 2
01284 };
01285
01286
01287 void KMFolderTree::openFolder()
01288 {
01289 autoopen_timer.stop();
01290 if ( dropItem && !dropItem->isOpen() ) {
01291 dropItem->setOpen( TRUE );
01292 dropItem->repaint();
01293 }
01294 }
01295
01296 static const int autoopenTime = 750;
01297
01298
01299 void KMFolderTree::contentsDragEnterEvent( QDragEnterEvent *e )
01300 {
01301 oldCurrent = 0;
01302 oldSelected = 0;
01303
01304 oldCurrent = currentItem();
01305 for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
01306 if ( it.current()->isSelected() )
01307 oldSelected = it.current();
01308
01309 setFocus();
01310
01311 QListViewItem *i = itemAt( contentsToViewport(e->pos()) );
01312 if ( i ) {
01313 dropItem = i;
01314 autoopen_timer.start( autoopenTime );
01315 }
01316 e->accept( acceptDrag(e) );
01317 }
01318
01319
01320 void KMFolderTree::contentsDragMoveEvent( QDragMoveEvent *e )
01321 {
01322 QPoint vp = contentsToViewport(e->pos());
01323 QListViewItem *i = itemAt( vp );
01324 if ( i ) {
01325 bool dragAccepted = acceptDrag( e );
01326 if ( dragAccepted ) {
01327 setCurrentItem( i );
01328 }
01329
01330 if ( i != dropItem ) {
01331 autoopen_timer.stop();
01332 dropItem = i;
01333 autoopen_timer.start( autoopenTime );
01334 }
01335
01336 if ( dragAccepted ) {
01337 e->accept( itemRect(i) );
01338
01339 switch ( e->action() ) {
01340 case QDropEvent::Copy:
01341 break;
01342 case QDropEvent::Move:
01343 e->acceptAction();
01344 break;
01345 case QDropEvent::Link:
01346 e->acceptAction();
01347 break;
01348 default:
01349 ;
01350 }
01351 } else {
01352 e->accept( false );
01353 }
01354 } else {
01355 e->accept( false );
01356 autoopen_timer.stop();
01357 dropItem = 0;
01358 }
01359 }
01360
01361
01362 void KMFolderTree::contentsDragLeaveEvent( QDragLeaveEvent * )
01363 {
01364 if (!oldCurrent) return;
01365
01366 autoopen_timer.stop();
01367 dropItem = 0;
01368
01369 setCurrentItem( oldCurrent );
01370 if ( oldSelected )
01371 setSelected( oldSelected, TRUE );
01372 }
01373
01374
01375 void KMFolderTree::contentsDropEvent( QDropEvent *e )
01376 {
01377 autoopen_timer.stop();
01378
01379 QListViewItem *item = itemAt( contentsToViewport(e->pos()) );
01380 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01381 if (fti && (fti != oldSelected) && (fti->folder()) && acceptDrag(e))
01382 {
01383 int keybstate = kapp->keyboardModifiers();
01384 if ( keybstate & KApplication::ControlModifier ) {
01385 emit folderDropCopy(fti->folder());
01386 } else if ( keybstate & KApplication::ShiftModifier ) {
01387 emit folderDrop(fti->folder());
01388 } else {
01389 if ( GlobalSettings::self()->showPopupAfterDnD() ) {
01390 KPopupMenu *menu = new KPopupMenu( this );
01391 menu->insertItem( i18n("&Move Here"), DRAG_MOVE, 0 );
01392 menu->insertItem( SmallIcon("editcopy"), i18n("&Copy Here"), DRAG_COPY, 1 );
01393 menu->insertSeparator();
01394 menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), DRAG_CANCEL, 3 );
01395 int id = menu->exec( QCursor::pos(), 0 );
01396 switch(id) {
01397 case DRAG_COPY:
01398 emit folderDropCopy(fti->folder());
01399 break;
01400 case DRAG_MOVE:
01401 emit folderDrop(fti->folder());
01402 break;
01403 case DRAG_CANCEL:
01404 case -1:
01405
01406 break;
01407 default:
01408 kdDebug(5006) << "Unknown dnd-type! " << id << endl;
01409 }
01410 }
01411 else
01412 emit folderDrop(fti->folder());
01413 }
01414 e->accept( true );
01415 } else
01416 e->accept( false );
01417
01418 dropItem = 0;
01419
01420 setCurrentItem( oldCurrent );
01421 if ( oldCurrent) mLastItem = static_cast<KMFolderTreeItem*>(oldCurrent);
01422 if ( oldSelected )
01423 {
01424 clearSelection();
01425 setSelected( oldSelected, TRUE );
01426 }
01427 }
01428
01429
01430 void KMFolderTree::slotFolderExpanded( QListViewItem * item )
01431 {
01432 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01433
01434 if ( fti && fti->folder() &&
01435 fti->folder()->folderType() == KMFolderTypeImap )
01436 {
01437 KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
01438
01439 if ( !folder->account()->listOnlyOpenFolders() &&
01440 fti->parent() )
01441 return;
01442 if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation )
01443 {
01444
01445 QListViewItem *parent = item->parent();
01446 while ( parent )
01447 {
01448 if ( !parent->isOpen() )
01449 return;
01450 parent = parent->parent();
01451 }
01452
01453 bool success = folder->listDirectory();
01454 if (!success) fti->setOpen( false );
01455 if ( fti->childCount() == 0 && fti->parent() )
01456 fti->setExpandable( false );
01457 }
01458 }
01459 }
01460
01461
01462
01463 void KMFolderTree::slotFolderCollapsed( QListViewItem * item )
01464 {
01465 slotResetFolderList( item, false );
01466 }
01467
01468
01469 void KMFolderTree::slotRenameFolder(QListViewItem *item, int col,
01470 const QString &text)
01471 {
01472
01473 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
01474
01475 if (fti && fti->folder() && col != 0 && !currentFolder()->child())
01476 return;
01477
01478 QString fldName, oldFldName;
01479
01480 oldFldName = fti->name(0);
01481
01482 if (!text.isEmpty())
01483 fldName = text;
01484 else
01485 fldName = oldFldName;
01486
01487 fldName.replace("/", "");
01488 fldName.replace(QRegExp("^\\."), "");
01489
01490 if (fldName.isEmpty())
01491 fldName = i18n("unnamed");
01492
01493 fti->setText(0, fldName);
01494 fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir()));
01495 }
01496
01497
01498 void KMFolderTree::slotUpdateCounts(KMFolderImap * folder, bool success)
01499 {
01500 if (success) slotUpdateCounts(folder->folder());
01501 }
01502
01503
01504 void KMFolderTree::slotUpdateCountsDelayed(KMFolder * folder)
01505 {
01506
01507 if ( !mFolderToUpdateCount.contains( folder->idString() ) )
01508 {
01509
01510 mFolderToUpdateCount.insert( folder->idString(),folder );
01511 }
01512 if ( !mUpdateCountTimer->isActive() )
01513 mUpdateCountTimer->start( 500 );
01514 }
01515
01516
01517 void KMFolderTree::slotUpdateCountTimeout()
01518 {
01519
01520
01521 QMap<QString,KMFolder*>::iterator it;
01522 for ( it= mFolderToUpdateCount.begin();
01523 it!=mFolderToUpdateCount.end();
01524 ++it )
01525 {
01526 slotUpdateCounts( it.data() );
01527 }
01528 mFolderToUpdateCount.clear();
01529 mUpdateCountTimer->stop();
01530
01531 }
01532
01533 void KMFolderTree::slotUpdateCounts(KMFolder * folder)
01534 {
01535
01536 QListViewItem * current;
01537 if (folder)
01538 current = indexOfFolder(folder);
01539 else
01540 current = currentItem();
01541
01542 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(current);
01543
01544 if (!fti) return;
01545 if (!fti->folder()) fti->setTotalCount(-1);
01546
01547
01548 int count = 0;
01549 if (folder->noContent())
01550 count = -1;
01551 else
01552 count = fti->folder()->countUnread();
01553
01554
01555 bool repaint = false;
01556 if (fti->unreadCount() != count) {
01557 fti->adjustUnreadCount( count );
01558 repaint = true;
01559 }
01560 if (isTotalActive())
01561 {
01562
01563 if (fti->folder()->noContent())
01564 count = -1;
01565 else {
01566
01567 count = fti->folder()->count( !fti->folder()->isOpened() );
01568 }
01569
01570 if ( count != fti->totalCount() ) {
01571 fti->setTotalCount(count);
01572 repaint = true;
01573 }
01574 }
01575 if (fti->parent() && !fti->parent()->isOpen())
01576 repaint = false;
01577 if (repaint) {
01578 fti->setNeedsRepaint( true );
01579 refresh();
01580 }
01581
01582 kmkernel->messageCountChanged();
01583 }
01584
01585 void KMFolderTree::updatePopup() const
01586 {
01587 mPopup->setItemChecked( mUnreadPop, isUnreadActive() );
01588 mPopup->setItemChecked( mTotalPop, isTotalActive() );
01589 }
01590
01591
01592 void KMFolderTree::toggleColumn(int column, bool openFolders)
01593 {
01594 if (column == unread)
01595 {
01596
01597 if ( isUnreadActive() )
01598 {
01599 removeUnreadColumn();
01600 reload();
01601 } else {
01602 addUnreadColumn( i18n("Unread"), 70 );
01603 reload();
01604 }
01605
01606 mPopup->setItemChecked( mUnreadPop, isUnreadActive() );
01607
01608 } else if (column == total) {
01609
01610 if ( isTotalActive() )
01611 {
01612 removeTotalColumn();
01613 reload();
01614 } else {
01615 addTotalColumn( i18n("Total"), 70 );
01616 reload(openFolders);
01617 }
01618
01619 mPopup->setItemChecked( mTotalPop, isTotalActive() );
01620
01621 } else kdDebug(5006) << "unknown column:" << column << endl;
01622
01623
01624 emit columnsChanged();
01625 }
01626
01627
01628 void KMFolderTree::slotToggleUnreadColumn()
01629 {
01630 toggleColumn(unread);
01631 }
01632
01633
01634 void KMFolderTree::slotToggleTotalColumn()
01635 {
01636
01637 toggleColumn(total, true);
01638 }
01639
01640
01641 bool KMFolderTree::eventFilter( QObject *o, QEvent *e )
01642 {
01643 if ( e->type() == QEvent::MouseButtonPress &&
01644 static_cast<QMouseEvent*>(e)->button() == RightButton &&
01645 o->isA("QHeader") )
01646 {
01647 mPopup->popup( static_cast<QMouseEvent*>(e)->globalPos() );
01648 return true;
01649 }
01650 return KFolderTree::eventFilter(o, e);
01651 }
01652
01653
01654 void KMFolderTree::slotCheckMail()
01655 {
01656 if (!currentItem())
01657 return;
01658 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(currentItem());
01659 KMFolder* folder = fti->folder();
01660 if (folder && folder->folderType() == KMFolderTypeImap)
01661 {
01662 KMAccount* acct = static_cast<KMFolderImap*>(folder->storage())->account();
01663 kmkernel->acctMgr()->singleCheckMail(acct, true);
01664 }
01665 }
01666
01667
01668 void KMFolderTree::slotNewMessageToMailingList()
01669 {
01670 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( currentItem() );
01671 if ( !fti || !fti->folder() )
01672 return;
01673 KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
01674 command->start();
01675 }
01676
01677
01678 void KMFolderTree::createFolderList( QStringList *str,
01679 QValueList<QGuardedPtr<KMFolder> > *folders,
01680 bool localFolders,
01681 bool imapFolders,
01682 bool dimapFolders,
01683 bool searchFolders,
01684 bool includeNoContent,
01685 bool includeNoChildren )
01686 {
01687 for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
01688 {
01689 KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
01690 if (!fti || !fti->folder()) continue;
01691
01692 KMFolder* folder = fti->folder();
01693 if (!imapFolders && folder->folderType() == KMFolderTypeImap) continue;
01694 if (!dimapFolders && folder->folderType() == KMFolderTypeCachedImap) continue;
01695 if (!localFolders && (folder->folderType() == KMFolderTypeMbox ||
01696 folder->folderType() == KMFolderTypeMaildir)) continue;
01697 if (!searchFolders && folder->folderType() == KMFolderTypeSearch) continue;
01698 if (!includeNoContent && folder->noContent()) continue;
01699 if (!includeNoChildren && folder->noChildren()) continue;
01700 QString prefix;
01701 prefix.fill( ' ', 2 * fti->depth() );
01702 str->append(prefix + fti->text(0));
01703 folders->append(fti->folder());
01704 }
01705 }
01706
01707
01708 void KMFolderTree::slotResetFolderList( QListViewItem* item, bool startList )
01709 {
01710 if ( !item )
01711 item = currentItem();
01712
01713 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( item );
01714 if ( fti && fti->folder() &&
01715 fti->folder()->folderType() == KMFolderTypeImap )
01716 {
01717 KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
01718 folder->setSubfolderState( KMFolderImap::imapNoInformation );
01719 if ( startList )
01720 folder->listDirectory();
01721 }
01722 }
01723
01724
01725 void KMFolderTree::showFolder( KMFolder* folder )
01726 {
01727 if ( !folder ) return;
01728 QListViewItem* item = indexOfFolder( folder );
01729 if ( item )
01730 {
01731 doFolderSelected( item );
01732 ensureItemVisible( item );
01733 }
01734 }
01735
01736
01737 void KMFolderTree::folderToPopupMenu( MenuAction action, QObject *receiver,
01738 KMMenuToFolder *aMenuToFolder, QPopupMenu *menu, QListViewItem *item )
01739 {
01740 while ( menu->count() )
01741 {
01742 QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
01743 if ( popup )
01744 delete popup;
01745 else
01746 menu->removeItemAt( 0 );
01747 }
01748
01749 if ( action == MoveMessage || action == MoveFolder )
01750 {
01751 disconnect( menu, SIGNAL(activated(int)), receiver,
01752 SLOT(moveSelectedToFolder(int)) );
01753 connect( menu, SIGNAL(activated(int)), receiver,
01754 SLOT(moveSelectedToFolder(int)) );
01755 } else {
01756 disconnect( menu, SIGNAL(activated(int)), receiver,
01757 SLOT(copySelectedToFolder(int)) );
01758 connect( menu, SIGNAL(activated(int)), receiver,
01759 SLOT(copySelectedToFolder(int)) );
01760 }
01761 if ( !item ) {
01762 item = firstChild();
01763
01764
01765
01766 if ( childCount() == 2 && action != MoveFolder ) {
01767 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item );
01768 if ( fti->protocol() == KFolderTreeItem::Search ) {
01769
01770 item = item->nextSibling();
01771 fti = static_cast<KMFolderTreeItem*>( item );
01772 }
01773 folderToPopupMenu( action, receiver, aMenuToFolder, menu, fti->firstChild() );
01774 return;
01775 }
01776 }
01777
01778 while ( item )
01779 {
01780 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( item );
01781 if ( fti->protocol() == KFolderTreeItem::Search )
01782 {
01783
01784 item = item->nextSibling();
01785 continue;
01786 }
01787 if ( action == MoveFolder ) {
01788
01789
01790
01791
01792 if ( fti->protocol() != KFolderTreeItem::Local
01793 && fti->protocol() != KFolderTreeItem::NONE )
01794 {
01795 item = item->nextSibling();
01796 continue;
01797 }
01798 }
01799 QString label = fti->text( 0 );
01800 label.replace( "&","&&" );
01801 if ( fti->firstChild() )
01802 {
01803
01804 QPopupMenu* popup = new QPopupMenu( menu, "subMenu" );
01805 folderToPopupMenu( action, receiver, aMenuToFolder, popup, fti->firstChild() );
01806 bool subMenu = false;
01807 if ( ( action == MoveMessage || action == CopyMessage ) &&
01808 fti->folder() && !fti->folder()->noContent() )
01809 subMenu = true;
01810 if ( action == MoveFolder && ( !fti->folder() ||
01811 ( fti->folder() && !fti->folder()->noChildren() ) ) )
01812 subMenu = true;
01813 if ( subMenu )
01814 {
01815 int menuId;
01816 if ( action == MoveMessage || action == MoveFolder )
01817 menuId = popup->insertItem( i18n("Move to This Folder"), -1, 0 );
01818 else
01819 menuId = popup->insertItem( i18n("Copy to This Folder"), -1, 0 );
01820 popup->insertSeparator( 1 );
01821 aMenuToFolder->insert( menuId, fti->folder() );
01822 }
01823 menu->insertItem( label, popup );
01824 } else
01825 {
01826
01827 int menuId = menu->insertItem( label );
01828 if ( fti->folder() )
01829 aMenuToFolder->insert( menuId, fti->folder() );
01830 bool enabled = (fti->folder() ? true : false);
01831 if ( fti->folder() &&
01832 ( fti->folder()->isReadOnly() || fti->folder()->noContent() ) )
01833 enabled = false;
01834 menu->setItemEnabled( menuId, enabled );
01835 }
01836
01837 item = item->nextSibling();
01838 }
01839 }
01840
01841
01842 void KMFolderTree::moveSelectedToFolder( int menuId )
01843 {
01844 moveFolder( mMenuToFolder[menuId] );
01845 }
01846
01847
01848 void KMFolderTree::moveFolder( KMFolder* destination )
01849 {
01850 KMFolder* folder = currentFolder();
01851 KMFolderDir* parent = &(kmkernel->folderMgr()->dir());
01852 if ( destination )
01853 parent = destination->createChildFolder();
01854 QString message =
01855 i18n( "<qt>Cannot move folder <b>%1</b> into a subfolder below itself.</qt>" ).
01856 arg( folder->label() );
01857
01858 KMFolderDir* folderDir = parent;
01859
01860 if ( folder && folder->child() )
01861 {
01862 while ( folderDir && ( folderDir != &kmkernel->folderMgr()->dir() ) &&
01863 ( folderDir != folder->parent() ) )
01864 {
01865 if ( folderDir->findRef( folder ) != -1 )
01866 {
01867 KMessageBox::error( this, message );
01868 return;
01869 }
01870 folderDir = folderDir->parent();
01871 }
01872 }
01873
01874 if( folder && folder->child() && parent &&
01875 ( parent->path().find( folder->child()->path() + "/" ) == 0 ) ) {
01876 KMessageBox::error( this, message );
01877 return;
01878 }
01879
01880 if( folder && folder->child()
01881 && ( parent == folder->child() ) ) {
01882 KMessageBox::error( this, message );
01883 return;
01884 }
01885
01886 kdDebug(5006) << "move folder " << currentFolder()->label() << " to "
01887 << ( destination ? destination->label() : "Local Folders" ) << endl;
01888 kmkernel->folderMgr()->moveFolder( folder, parent );
01889 }
01890
01891 #include "kmfoldertree.moc"
01892