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