kmail Library API Documentation

kmfoldertree.cpp

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