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 "kmfolder.h" 00010 #include "kmfolderimap.h" 00011 #include "kmfoldercachedimap.h" 00012 #include "kmfolderdia.h" 00013 #include "kmheaders.h" 00014 #include "kmmainwidget.h" 00015 #include "kmailicalifaceimpl.h" 00016 #include "accountmanager.h" 00017 using KMail::AccountManager; 00018 #include "globalsettings.h" 00019 #include "kmcommands.h" 00020 #include "foldershortcutdialog.h" 00021 #include "expirypropertiesdialog.h" 00022 #include "newfolderdialog.h" 00023 #include "acljobs.h" 00024 #include "messagecopyhelper.h" 00025 using KMail::MessageCopyHelper; 00026 #include "favoritefolderview.h" 00027 #include "folderviewtooltip.h" 00028 using KMail::FolderViewToolTip; 00029 00030 #include <maillistdrag.h> 00031 using namespace KPIM; 00032 00033 #include <tdeapplication.h> 00034 #include <tdeglobalsettings.h> 00035 #include <kiconloader.h> 00036 #include <tdemessagebox.h> 00037 #include <tdeconfig.h> 00038 #include <tdepopupmenu.h> 00039 #include <kdebug.h> 00040 00041 #include <tqpainter.h> 00042 #include <tqcursor.h> 00043 #include <tqregexp.h> 00044 #include <tqpopupmenu.h> 00045 00046 #include <unistd.h> 00047 #include <assert.h> 00048 00049 #include <X11/Xlib.h> 00050 #include <fixx11h.h> 00051 00052 //============================================================================= 00053 00054 KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name, 00055 KFolderTreeItem::Protocol protocol ) 00056 : TQObject( parent, name.latin1() ), 00057 KFolderTreeItem( parent, name, protocol, Root ), 00058 mFolder( 0 ), mNeedsRepaint( true ) 00059 { 00060 init(); 00061 setPixmap( 0, normalIcon( iconSize() ) ); 00062 } 00063 00064 //----------------------------------------------------------------------------- 00065 KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name, 00066 KMFolder* folder ) 00067 : TQObject( parent, name.latin1() ), 00068 KFolderTreeItem( parent, name ), 00069 mFolder( folder ), mNeedsRepaint( true ) 00070 { 00071 init(); 00072 setPixmap( 0, normalIcon( iconSize() ) ); 00073 } 00074 00075 //----------------------------------------------------------------------------- 00076 KMFolderTreeItem::KMFolderTreeItem( KFolderTreeItem *parent, const TQString & name, 00077 KMFolder* folder ) 00078 : TQObject( 0, name.latin1() ), 00079 KFolderTreeItem( parent, name ), 00080 mFolder( folder ), mNeedsRepaint( true ) 00081 { 00082 init(); 00083 setPixmap( 0, normalIcon( iconSize() ) ); 00084 } 00085 00086 KMFolderTreeItem::~KMFolderTreeItem() 00087 { 00088 } 00089 00090 static KFolderTreeItem::Protocol protocolFor( KMFolderType t ) { 00091 switch ( t ) { 00092 case KMFolderTypeImap: 00093 return KFolderTreeItem::Imap; 00094 case KMFolderTypeCachedImap: 00095 return KFolderTreeItem::CachedImap; 00096 case KMFolderTypeMbox: 00097 case KMFolderTypeMaildir: 00098 return KFolderTreeItem::Local; 00099 case KMFolderTypeSearch: 00100 return KFolderTreeItem::Search; 00101 default: 00102 return KFolderTreeItem::NONE; 00103 } 00104 } 00105 00106 TQPixmap KMFolderTreeItem::normalIcon(int size) const 00107 { 00108 TQString icon; 00109 if ( (!mFolder && type() == Root) || useTopLevelIcon() ) { 00110 switch ( protocol() ) { 00111 case KFolderTreeItem::Imap: 00112 case KFolderTreeItem::CachedImap: 00113 case KFolderTreeItem::News: 00114 icon = "server"; break; 00115 case KFolderTreeItem::Search: 00116 icon = "viewmag";break; 00117 default: 00118 icon = "folder";break; 00119 } 00120 } else { 00121 // special folders 00122 switch ( type() ) { 00123 case Inbox: icon = "folder_inbox"; break; 00124 case Outbox: icon = "folder_outbox"; break; 00125 case SentMail: icon = "folder_sent_mail"; break; 00126 case Trash: icon = "trashcan_empty"; break; 00127 case Drafts: icon = "edit"; break; 00128 case Templates: icon = "document-new"; break; 00129 default: 00130 { 00131 //If not a resource folder don't try to use icalIface folder pixmap 00132 if(kmkernel->iCalIface().isResourceFolder( mFolder )) 00133 icon = kmkernel->iCalIface().folderPixmap( type() ); 00134 break; 00135 } 00136 } 00137 // non-root search folders 00138 if ( protocol() == KMFolderTreeItem::Search ) { 00139 icon = "mail_find"; 00140 } 00141 if ( mFolder && mFolder->noContent() ) { 00142 icon = "folder_grey"; 00143 } 00144 } 00145 00146 if ( icon.isEmpty() ) 00147 icon = "folder"; 00148 00149 if (mFolder && mFolder->useCustomIcons() ) { 00150 icon = mFolder->normalIconPath(); 00151 } 00152 TDEIconLoader * il = TDEGlobal::instance()->iconLoader(); 00153 TQPixmap pm = il->loadIcon( icon, TDEIcon::Small, size, 00154 TDEIcon::DefaultState, 0, true ); 00155 if ( mFolder && pm.isNull() ) { 00156 pm = il->loadIcon( mFolder->normalIconPath(), TDEIcon::Small, size, 00157 TDEIcon::DefaultState, 0, true ); 00158 } 00159 00160 return pm; 00161 } 00162 00163 TQPixmap KMFolderTreeItem::unreadIcon(int size) const 00164 { 00165 TQPixmap pm; 00166 00167 if ( !mFolder || useTopLevelIcon() || mFolder->isSystemFolder() || 00168 kmkernel->folderIsTrash( mFolder ) || 00169 kmkernel->folderIsTemplates( mFolder ) || 00170 kmkernel->folderIsDraftOrOutbox( mFolder ) ) 00171 pm = normalIcon( size ); 00172 00173 TDEIconLoader * il = TDEGlobal::instance()->iconLoader(); 00174 if ( mFolder && mFolder->useCustomIcons() ) { 00175 pm = il->loadIcon( mFolder->unreadIconPath(), TDEIcon::Small, size, 00176 TDEIcon::DefaultState, 0, true ); 00177 if ( pm.isNull() ) 00178 pm = il->loadIcon( mFolder->normalIconPath(), TDEIcon::Small, size, 00179 TDEIcon::DefaultState, 0, true ); 00180 } 00181 if ( pm.isNull() ) { 00182 if ( mFolder && mFolder->noContent() ) { 00183 pm = il->loadIcon( "folder_grey_open", TDEIcon::Small, size, 00184 TDEIcon::DefaultState, 0, true ); 00185 } else { 00186 if( kmkernel->iCalIface().isResourceFolder( mFolder ) ) 00187 pm = il->loadIcon( kmkernel->iCalIface().folderPixmap( type() ), 00188 TDEIcon::Small, size, TDEIcon::DefaultState, 0, true ); 00189 if ( pm.isNull() ) 00190 pm = il->loadIcon( "folder_open", TDEIcon::Small, size, 00191 TDEIcon::DefaultState, 0, true ); 00192 } 00193 } 00194 00195 return pm; 00196 } 00197 00198 void KMFolderTreeItem::init() 00199 { 00200 if ( !mFolder ) 00201 return; 00202 00203 setProtocol( protocolFor( mFolder->folderType() ) ); 00204 00205 if ( useTopLevelIcon() ) 00206 setType(Root); 00207 else { 00208 if ( mFolder == kmkernel->inboxFolder() ) 00209 setType( Inbox ); 00210 else if ( kmkernel->folderIsDraftOrOutbox( mFolder ) ) { 00211 if ( mFolder == kmkernel->outboxFolder() ) 00212 setType( Outbox ); 00213 else 00214 setType( Drafts ); 00215 } 00216 else if ( kmkernel->folderIsSentMailFolder( mFolder ) ) 00217 setType( SentMail ); 00218 else if ( kmkernel->folderIsTrash( mFolder ) ) 00219 setType( Trash ); 00220 else if ( kmkernel->folderIsTemplates( mFolder ) ) 00221 setType( Templates ); 00222 else if( kmkernel->iCalIface().isResourceFolder(mFolder) ) 00223 setType( kmkernel->iCalIface().folderType(mFolder) ); 00224 // System folders on dimap or imap which are not resource folders are 00225 // inboxes. Urgs. 00226 if ( mFolder->isSystemFolder() && 00227 !kmkernel->iCalIface().isResourceFolder( mFolder) && 00228 ( mFolder->folderType() == KMFolderTypeImap 00229 || mFolder->folderType() == KMFolderTypeCachedImap ) ) 00230 setType( Inbox ); 00231 } 00232 if ( !mFolder->isSystemFolder() ) 00233 setRenameEnabled( 0, false ); 00234 00235 KMFolderTree* tree = dynamic_cast<KMFolderTree*>( listView() ); 00236 if ( tree ) 00237 tree->insertIntoFolderToItemMap( mFolder, this ); 00238 } 00239 00240 void KMFolderTreeItem::adjustUnreadCount( int newUnreadCount ) { 00241 // adjust the icons if the folder is now newly unread or 00242 // now newly not-unread 00243 if ( newUnreadCount != 0 && unreadCount() == 0 ) 00244 setPixmap( 0, unreadIcon( iconSize() ) ); 00245 if ( unreadCount() != 0 && newUnreadCount == 0 ) 00246 setPixmap( 0, normalIcon( iconSize() ) ); 00247 00248 setUnreadCount( newUnreadCount ); 00249 } 00250 00251 void KMFolderTreeItem::slotIconsChanged() 00252 { 00253 kdDebug(5006) << k_funcinfo << endl; 00254 // this is prone to change, so better check 00255 KFolderTreeItem::Type newType = type(); 00256 if( kmkernel->iCalIface().isResourceFolder( mFolder ) ) 00257 newType = kmkernel->iCalIface().folderType(mFolder); 00258 00259 // reload the folder tree if the type changed, needed because of the 00260 // various type-dependent folder hiding options 00261 if ( type() != newType ) 00262 static_cast<KMFolderTree*>( listView() )->delayedReload(); 00263 setType( newType ); 00264 00265 if ( unreadCount() > 0 ) 00266 setPixmap( 0, unreadIcon( iconSize() ) ); 00267 else 00268 setPixmap( 0, normalIcon( iconSize() ) ); 00269 emit iconChanged( this ); 00270 repaint(); 00271 } 00272 00273 void KMFolderTreeItem::slotNameChanged() 00274 { 00275 setText( 0, mFolder->label() ); 00276 emit nameChanged( this ); 00277 repaint(); 00278 } 00279 00280 void KMFolderTreeItem::slotNoContentChanged() 00281 { 00282 // reload the folder tree if the no content state changed, needed because 00283 // we hide no-content folders if their child nodes are hidden 00284 TQTimer::singleShot( 0, static_cast<KMFolderTree*>( listView() ), TQT_SLOT(reload()) ); 00285 } 00286 00287 //----------------------------------------------------------------------------- 00288 bool KMFolderTreeItem::acceptDrag(TQDropEvent* e) const 00289 { 00290 // Do not allow drags from the favorite folder view, as they don't really 00291 // make sense and do not work. 00292 KMMainWidget *mainWidget = static_cast<KMFolderTree*>( listView() )->mainWidget(); 00293 assert( mainWidget ); 00294 if ( mainWidget->favoriteFolderView() && 00295 e->source() == mainWidget->favoriteFolderView()->viewport() ) 00296 return false; 00297 00298 if ( protocol() == KFolderTreeItem::Search ) 00299 return false; // nothing can be dragged into search folders 00300 00301 if ( e->provides( KPIM::MailListDrag::format() ) ) { 00302 if ( !mFolder || mFolder->moveInProgress() || mFolder->isReadOnly() || 00303 (mFolder->noContent() && childCount() == 0) || 00304 (mFolder->noContent() && isOpen()) ) { 00305 return false; 00306 } 00307 else { 00308 return true; 00309 } 00310 } else if ( e->provides("application/x-qlistviewitem") ) { 00311 // wtf: protocol() is NONE instead of Local for the local root folder 00312 if ( !mFolder && protocol() == KFolderTreeItem::NONE && type() == KFolderTreeItem::Root ) 00313 return true; // local top-level folder 00314 if ( !mFolder || mFolder->isReadOnly() || mFolder->noContent() ) 00315 return false; 00316 return true; 00317 } 00318 return false; 00319 } 00320 00321 //----------------------------------------------------------------------------- 00322 void KMFolderTreeItem::slotShowExpiryProperties() 00323 { 00324 if ( !mFolder ) 00325 return; 00326 00327 KMFolderTree* tree = static_cast<KMFolderTree*>( listView() ); 00328 KMail::ExpiryPropertiesDialog *dlg = 00329 new KMail::ExpiryPropertiesDialog( tree, mFolder ); 00330 dlg->show(); 00331 } 00332 00333 00334 //----------------------------------------------------------------------------- 00335 void KMFolderTreeItem::properties() 00336 { 00337 if ( !mFolder ) 00338 return; 00339 00340 KMail::FolderTreeBase* tree = static_cast<KMail::FolderTreeBase*>( listView() ); 00341 tree->mainWidget()->modifyFolder( this ); 00342 //Nothing here the above may actually delete this KMFolderTreeItem 00343 } 00344 00345 //----------------------------------------------------------------------------- 00346 void KMFolderTreeItem::assignShortcut() 00347 { 00348 if ( !mFolder ) 00349 return; 00350 00351 KMail::FolderShortcutDialog *shorty = 00352 new KMail::FolderShortcutDialog( mFolder, 00353 kmkernel->getKMMainWidget(), 00354 listView() ); 00355 shorty->exec(); 00356 delete shorty; 00357 } 00358 00359 //----------------------------------------------------------------------------- 00360 void KMFolderTreeItem::updateCount() 00361 { 00362 if ( !folder() ) { 00363 setTotalCount( -1 ); 00364 return; 00365 } 00366 KMail::FolderTreeBase* tree = dynamic_cast<KMail::FolderTreeBase*>( listView() ); 00367 if ( !tree ) return; 00368 00369 tree->slotUpdateCounts( folder(), true /* force update */ ); 00370 } 00371 00372 00373 //============================================================================= 00374 00375 00376 KMFolderTree::KMFolderTree( KMMainWidget *mainWidget, TQWidget *parent, 00377 const char *name ) 00378 : KMail::FolderTreeBase( mainWidget, parent, name ) 00379 , mUpdateTimer( 0, "mUpdateTimer" ) 00380 , autoopen_timer( 0, "autoopen_timer" ) 00381 { 00382 oldSelected = 0; 00383 oldCurrent = 0; 00384 mLastItem = 0; 00385 dropItem = 0; 00386 mMainWidget = mainWidget; 00387 mReloading = false; 00388 mCutFolder = false; 00389 00390 mUpdateCountTimer= new TQTimer( this, "mUpdateCountTimer" ); 00391 00392 setDragEnabled( true ); 00393 addAcceptableDropMimetype( "application/x-qlistviewitem", false ); 00394 00395 setSelectionModeExt( Extended ); 00396 00397 int namecol = addColumn( i18n("Folder"), 250 ); 00398 header()->setStretchEnabled( true, namecol ); 00399 setResizeMode( TQListView::NoColumn ); 00400 // connect 00401 connectSignals(); 00402 00403 // popup to switch columns 00404 header()->setClickEnabled(true); 00405 header()->installEventFilter(this); 00406 mPopup = new TDEPopupMenu(this); 00407 mPopup->insertTitle(i18n("View Columns")); 00408 mPopup->setCheckable(true); 00409 mUnreadPop = mPopup->insertItem(i18n("Unread Column"), this, TQT_SLOT(slotToggleUnreadColumn())); 00410 mTotalPop = mPopup->insertItem(i18n("Total Column"), this, TQT_SLOT(slotToggleTotalColumn())); 00411 mSizePop = mPopup->insertItem(i18n("Size Column"), this, TQT_SLOT(slotToggleSizeColumn())); 00412 00413 connect( this, TQT_SIGNAL( triggerRefresh() ), 00414 this, TQT_SLOT( refresh() ) ); 00415 00416 new FolderViewToolTip( this ); 00417 } 00418 00419 //----------------------------------------------------------------------------- 00420 // connects all needed signals to their slots 00421 void KMFolderTree::connectSignals() 00422 { 00423 connect( mUpdateCountTimer, TQT_SIGNAL(timeout()), 00424 this, TQT_SLOT(slotUpdateCountTimeout()) ); 00425 00426 connect(&mUpdateTimer, TQT_SIGNAL(timeout()), 00427 this, TQT_SLOT(delayedUpdate())); 00428 00429 connect(kmkernel->folderMgr(), TQT_SIGNAL(changed()), 00430 this, TQT_SLOT(doFolderListChanged())); 00431 00432 connect(kmkernel->folderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)), 00433 this, TQT_SLOT(slotFolderRemoved(KMFolder*))); 00434 00435 connect(kmkernel->folderMgr(), TQT_SIGNAL(folderMoveOrCopyOperationFinished()), 00436 this, TQT_SLOT(slotFolderMoveOrCopyOperationFinished())); 00437 00438 connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(changed()), 00439 this, TQT_SLOT(doFolderListChanged())); 00440 00441 connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)), 00442 this, TQT_SLOT(slotFolderRemoved(KMFolder*))); 00443 00444 connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(changed()), 00445 this, TQT_SLOT(doFolderListChanged())); 00446 00447 connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)), 00448 this, TQT_SLOT(slotFolderRemoved(KMFolder*))); 00449 00450 connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(changed()), 00451 this, TQT_SLOT(doFolderListChanged())); 00452 00453 connect(kmkernel->acctMgr(), TQT_SIGNAL(accountRemoved(KMAccount*)), 00454 this, TQT_SLOT(slotAccountRemoved(KMAccount*))); 00455 00456 connect(kmkernel->acctMgr(), TQT_SIGNAL(accountAdded(KMAccount*)), 00457 this, TQT_SLOT(slotUnhideLocalInbox())); 00458 00459 connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)), 00460 this, TQT_SLOT(slotFolderRemoved(KMFolder*))); 00461 00462 connect( &autoopen_timer, TQT_SIGNAL( timeout() ), 00463 this, TQT_SLOT( openFolder() ) ); 00464 00465 connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*, const TQPoint &, int ) ), 00466 this, TQT_SLOT( slotContextMenuRequested( TQListViewItem*, const TQPoint & ) ) ); 00467 00468 connect( this, TQT_SIGNAL( expanded( TQListViewItem* ) ), 00469 this, TQT_SLOT( slotFolderExpanded( TQListViewItem* ) ) ); 00470 00471 connect( this, TQT_SIGNAL( collapsed( TQListViewItem* ) ), 00472 this, TQT_SLOT( slotFolderCollapsed( TQListViewItem* ) ) ); 00473 00474 connect( this, TQT_SIGNAL( itemRenamed( TQListViewItem*, int, const TQString &)), 00475 this, TQT_SLOT( slotRenameFolder( TQListViewItem*, int, const TQString &))); 00476 00477 connect( this, TQT_SIGNAL(folderSelected(KMFolder*)), TQT_SLOT(updateCopyActions()) ); 00478 } 00479 00480 //----------------------------------------------------------------------------- 00481 void KMFolderTree::readConfig (void) 00482 { 00483 TDEConfig* conf = KMKernel::config(); 00484 00485 readColorConfig(); 00486 00487 // Custom/Ssystem font support 00488 { 00489 TDEConfigGroupSaver saver(conf, "Fonts"); 00490 if (!conf->readBoolEntry("defaultFonts",true)) { 00491 TQFont folderFont( TDEGlobalSettings::generalFont() ); 00492 setFont(conf->readFontEntry("folder-font", &folderFont)); 00493 } 00494 else 00495 setFont(TDEGlobalSettings::generalFont()); 00496 } 00497 00498 // restore the layout 00499 restoreLayout(conf, "Geometry"); 00500 } 00501 00502 //----------------------------------------------------------------------------- 00503 // Save the configuration file 00504 void KMFolderTree::writeConfig() 00505 { 00506 // save the current state of the folders 00507 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) { 00508 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00509 if (fti) 00510 writeIsListViewItemOpen(fti); 00511 } 00512 00513 // save the current layout 00514 saveLayout(KMKernel::config(), "Geometry"); 00515 } 00516 00517 //----------------------------------------------------------------------------- 00518 // Updates the count of unread messages (count of unread messages 00519 // is now cached in KMails config file) 00520 void KMFolderTree::updateUnreadAll() 00521 { 00522 bool upd = isUpdatesEnabled(); 00523 setUpdatesEnabled(false); 00524 00525 KMFolderDir* fdir; 00526 KMFolderNode* folderNode; 00527 KMFolder* folder; 00528 00529 fdir = &kmkernel->folderMgr()->dir(); 00530 for (folderNode = fdir->first(); 00531 folderNode != 0; 00532 folderNode =fdir->next()) 00533 { 00534 if (!folderNode->isDir()) { 00535 folder = static_cast<KMFolder*>(folderNode); 00536 00537 folder->open("updateunread"); 00538 folder->countUnread(); 00539 folder->close("updateunread"); 00540 } 00541 } 00542 00543 setUpdatesEnabled(upd); 00544 } 00545 00546 //----------------------------------------------------------------------------- 00547 // Reload the tree of items in the list view 00548 void KMFolderTree::reload(bool openFolders) 00549 { 00550 if ( mReloading ) { 00551 // no parallel reloads are allowed 00552 kdDebug(5006) << "KMFolderTree::reload - already reloading" << endl; 00553 return; 00554 } 00555 mReloading = true; 00556 00557 int top = contentsY(); 00558 mLastItem = 0; 00559 // invalidate selected drop item 00560 oldSelected = 0; 00561 // remember last 00562 KMFolder* last = currentFolder(); 00563 KMFolder* selected = 0; 00564 KMFolder* oldCurrentFolder = 00565 ( oldCurrent ? static_cast<KMFolderTreeItem*>(oldCurrent)->folder(): 0 ); 00566 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) { 00567 KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); 00568 writeIsListViewItemOpen( fti ); 00569 if ( fti->isSelected() ) 00570 selected = fti->folder(); 00571 } 00572 mFolderToItem.clear(); 00573 clear(); 00574 00575 // construct the root of the local folders 00576 KMFolderTreeItem * root = new KMFolderTreeItem( this, i18n("Local Folders") ); 00577 root->setOpen( readIsListViewItemOpen(root) ); 00578 00579 KMFolderDir * fdir = &kmkernel->folderMgr()->dir(); 00580 addDirectory(fdir, root); 00581 00582 fdir = &kmkernel->imapFolderMgr()->dir(); 00583 // each imap-account creates it's own root 00584 addDirectory(fdir, 0); 00585 00586 fdir = &kmkernel->dimapFolderMgr()->dir(); 00587 // each dimap-account creates it's own root 00588 addDirectory(fdir, 0); 00589 00590 // construct the root of the search folder hierarchy: 00591 root = new KMFolderTreeItem( this, i18n("Searches"), KFolderTreeItem::Search ); 00592 root->setOpen( readIsListViewItemOpen( root ) ); 00593 00594 fdir = &kmkernel->searchFolderMgr()->dir(); 00595 addDirectory(fdir, root); 00596 00597 if (openFolders) 00598 { 00599 // we open all folders to update the count 00600 mUpdateIterator = TQListViewItemIterator (this); 00601 TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) ); 00602 } 00603 00604 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) { 00605 KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); 00606 if ( !fti || !fti->folder() ) 00607 continue; 00608 00609 disconnect(fti->folder(),TQT_SIGNAL(iconsChanged()), 00610 fti,TQT_SLOT(slotIconsChanged())); 00611 connect(fti->folder(),TQT_SIGNAL(iconsChanged()), 00612 fti,TQT_SLOT(slotIconsChanged())); 00613 00614 disconnect(fti->folder(),TQT_SIGNAL(nameChanged()), 00615 fti,TQT_SLOT(slotNameChanged())); 00616 connect(fti->folder(),TQT_SIGNAL(nameChanged()), 00617 fti,TQT_SLOT(slotNameChanged())); 00618 00619 disconnect( fti->folder(), TQT_SIGNAL(noContentChanged()), 00620 fti, TQT_SLOT(slotNoContentChanged()) ); 00621 connect( fti->folder(), TQT_SIGNAL(noContentChanged()), 00622 fti, TQT_SLOT(slotNoContentChanged()) ); 00623 00624 disconnect( fti->folder(), TQT_SIGNAL(syncStateChanged()), 00625 this, TQT_SLOT(slotSyncStateChanged()) ); 00626 connect( fti->folder(), TQT_SIGNAL(syncStateChanged()), 00627 this, TQT_SLOT(slotSyncStateChanged()) ); 00628 00629 // we want to be noticed of changes to update the unread/total columns 00630 disconnect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)), 00631 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00632 connect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)), 00633 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00634 //} 00635 00636 disconnect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)), 00637 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00638 connect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)), 00639 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00640 disconnect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)), 00641 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00642 connect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)), 00643 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00644 00645 disconnect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )), 00646 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00647 connect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )), 00648 this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*))); 00649 00650 00651 00652 disconnect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)), 00653 mMainWidget, TQT_SLOT( slotShortcutChanged(KMFolder*))); 00654 connect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)), 00655 mMainWidget, TQT_SLOT( slotShortcutChanged(KMFolder*))); 00656 00657 00658 if (!openFolders) 00659 slotUpdateCounts(fti->folder()); 00660 00661 // populate the size column 00662 fti->setFolderSize( 0 ); 00663 fti->setFolderIsCloseToQuota( fti->folder()->storage()->isCloseToQuota() ); 00664 00665 } 00666 ensureVisible(0, top + visibleHeight(), 0, 0); 00667 // if current and selected folder did not change set it again 00668 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) 00669 { 00670 if ( last && 00671 static_cast<KMFolderTreeItem*>( it.current() )->folder() == last ) 00672 { 00673 mLastItem = static_cast<KMFolderTreeItem*>( it.current() ); 00674 setCurrentItem( it.current() ); 00675 } 00676 if ( selected && 00677 static_cast<KMFolderTreeItem*>( it.current() )->folder() == selected ) 00678 { 00679 setSelected( it.current(), true ); 00680 } 00681 if ( oldCurrentFolder && 00682 static_cast<KMFolderTreeItem*>( it.current() )->folder() == oldCurrentFolder ) 00683 { 00684 oldCurrent = it.current(); 00685 } 00686 } 00687 refresh(); 00688 mReloading = false; 00689 } 00690 00691 //----------------------------------------------------------------------------- 00692 void KMFolderTree::slotUpdateOneCount() 00693 { 00694 if ( !mUpdateIterator.current() ) return; 00695 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(mUpdateIterator.current()); 00696 ++mUpdateIterator; 00697 if ( !fti->folder() ) { 00698 // next one please 00699 TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) ); 00700 return; 00701 } 00702 00703 // open the folder and update the count 00704 bool open = fti->folder()->isOpened(); 00705 if (!open) fti->folder()->open("updatecount"); 00706 slotUpdateCounts(fti->folder()); 00707 // restore previous state 00708 if (!open) fti->folder()->close("updatecount"); 00709 00710 TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) ); 00711 } 00712 00713 //----------------------------------------------------------------------------- 00714 // Recursively add a directory of folders to the tree of folders 00715 void KMFolderTree::addDirectory( KMFolderDir *fdir, KMFolderTreeItem* parent ) 00716 { 00717 for ( KMFolderNode * node = fdir->first() ; node ; node = fdir->next() ) { 00718 if ( node->isDir() ) 00719 continue; 00720 00721 KMFolder * folder = static_cast<KMFolder*>(node); 00722 KMFolderTreeItem * fti = 0; 00723 if (!parent) 00724 { 00725 // create new root-item, but only if this is not the root of a 00726 // "groupware folders only" account 00727 if ( kmkernel->iCalIface().hideResourceAccountRoot( folder ) ) 00728 continue; 00729 // it needs a folder e.g. to save it's state (open/close) 00730 fti = new KMFolderTreeItem( this, folder->label(), folder ); 00731 fti->setExpandable( true ); 00732 00733 // add child-folders 00734 if (folder && folder->child()) { 00735 addDirectory( folder->child(), fti ); 00736 } 00737 } else { 00738 // hide local inbox if unused 00739 if ( kmkernel->inboxFolder() == folder && hideLocalInbox() ) { 00740 connect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)), TQT_SLOT(slotUnhideLocalInbox()) ); 00741 continue; 00742 } 00743 00744 // create new child 00745 fti = new KMFolderTreeItem( parent, folder->label(), folder ); 00746 // set folders explicitely to exandable when they have children 00747 // this way we can do a listing for IMAP folders when the user expands them 00748 // even when the child folders are not created yet 00749 if ( folder->storage()->hasChildren() == FolderStorage::HasChildren ) { 00750 fti->setExpandable( true ); 00751 } else { 00752 fti->setExpandable( false ); 00753 } 00754 00755 // add child-folders 00756 if (folder && folder->child()) { 00757 addDirectory( folder->child(), fti ); 00758 } 00759 00760 // Check if this is an IMAP resource folder or a no-content parent only 00761 // containing groupware folders 00762 if ( (kmkernel->iCalIface().hideResourceFolder( folder ) || folder->noContent()) 00763 && fti->childCount() == 0 ) { 00764 // It is 00765 removeFromFolderToItemMap( folder ); 00766 delete fti; 00767 // still, it might change in the future, so we better check the change signals 00768 connect ( folder, TQT_SIGNAL(noContentChanged()), TQT_SLOT(delayedReload()) ); 00769 continue; 00770 } 00771 00772 connect (fti, TQT_SIGNAL(iconChanged(KMFolderTreeItem*)), 00773 this, TQT_SIGNAL(iconChanged(KMFolderTreeItem*))); 00774 connect (fti, TQT_SIGNAL(nameChanged(KMFolderTreeItem*)), 00775 this, TQT_SIGNAL(nameChanged(KMFolderTreeItem*))); 00776 } 00777 // restore last open-state 00778 fti->setOpen( readIsListViewItemOpen(fti) ); 00779 } // for-end 00780 } 00781 00782 //----------------------------------------------------------------------------- 00783 // Initiate a delayed refresh of the tree 00784 void KMFolderTree::refresh() 00785 { 00786 mUpdateTimer.changeInterval(200); 00787 } 00788 00789 //----------------------------------------------------------------------------- 00790 // Updates the pixmap and extendedLabel information for items 00791 void KMFolderTree::delayedUpdate() 00792 { 00793 bool upd = isUpdatesEnabled(); 00794 if ( upd ) { 00795 setUpdatesEnabled(false); 00796 00797 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) { 00798 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00799 if (!fti || !fti->folder()) 00800 continue; 00801 00802 if ( fti->needsRepaint() ) { 00803 fti->repaint(); 00804 fti->setNeedsRepaint( false ); 00805 } 00806 } 00807 setUpdatesEnabled(upd); 00808 } 00809 mUpdateTimer.stop(); 00810 } 00811 00812 //----------------------------------------------------------------------------- 00813 // Folders have been added/deleted update the tree of folders 00814 void KMFolderTree::doFolderListChanged() 00815 { 00816 reload(); 00817 } 00818 00819 //----------------------------------------------------------------------------- 00820 void KMFolderTree::slotAccountRemoved(KMAccount *) 00821 { 00822 doFolderSelected( firstChild() ); 00823 } 00824 00825 //----------------------------------------------------------------------------- 00826 void KMFolderTree::slotFolderMoveOrCopyOperationFinished() 00827 { 00828 setDragEnabled( true ); 00829 } 00830 //----------------------------------------------------------------------------- 00831 void KMFolderTree::slotFolderRemoved(KMFolder *aFolder) 00832 { 00833 TQListViewItem *item = indexOfFolder(aFolder); 00834 if (!item) return; 00835 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*> ( item ); 00836 if ( oldCurrent == fti ) 00837 oldCurrent = 0; 00838 if ( oldSelected == fti ) 00839 oldSelected = 0; 00840 if (!fti || !fti->folder()) return; 00841 if (fti == currentItem()) 00842 { 00843 TQListViewItem *qlvi = fti->itemAbove(); 00844 if (!qlvi) qlvi = fti->itemBelow(); 00845 doFolderSelected( qlvi ); 00846 } 00847 removeFromFolderToItemMap( aFolder ); 00848 00849 if ( dropItem == fti ) { // The removed item is the dropItem 00850 dropItem = 0; // it becomes invalid 00851 } 00852 00853 delete fti; 00854 updateCopyActions(); 00855 } 00856 00857 //----------------------------------------------------------------------------- 00858 // Methods for navigating folders with the keyboard 00859 void KMFolderTree::prepareItem( KMFolderTreeItem* fti ) 00860 { 00861 for ( TQListViewItem * parent = fti->parent() ; parent ; parent = parent->parent() ) 00862 parent->setOpen( true ); 00863 ensureItemVisible( fti ); 00864 } 00865 00866 //----------------------------------------------------------------------------- 00867 void KMFolderTree::nextUnreadFolder() 00868 { 00869 nextUnreadFolder( false ); 00870 } 00871 00872 //----------------------------------------------------------------------------- 00873 void KMFolderTree::nextUnreadFolder(bool confirm) 00874 { 00875 TQListViewItemIterator it( currentItem() ? currentItem() : firstChild() ); 00876 if ( currentItem() ) 00877 ++it; // don't find current item 00878 for ( ; it.current() ; ++it ) { 00879 //check if folder is one to stop on 00880 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00881 if (checkUnreadFolder(fti,confirm)) return; 00882 } 00883 //Now if confirm is true we are doing "ReadOn" 00884 //we have got to the bottom of the folder list 00885 //so we have to start at the top 00886 if (confirm) { 00887 for ( it = firstChild() ; it.current() ; ++it ) { 00888 //check if folder is one to stop on 00889 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00890 if (checkUnreadFolder(fti,confirm)) return; 00891 } 00892 } 00893 } 00894 00895 //----------------------------------------------------------------------------- 00896 bool KMFolderTree::checkUnreadFolder (KMFolderTreeItem* fti, bool confirm) 00897 { 00898 if ( fti && fti->folder() && !fti->folder()->ignoreNewMail() && 00899 ( fti->folder()->countUnread() > 0 ) ) { 00900 00901 // Don't change into the trash or outbox folders. 00902 if (fti->type() == KFolderTreeItem::Trash || 00903 fti->type() == KFolderTreeItem::Outbox ) 00904 return false; 00905 00906 if (confirm) { 00907 // Skip drafts, sent mail and templates as well, when reading mail with 00908 // the space bar but not when changing into the next folder with unread 00909 // mail via ctrl+ or ctrl- so we do this only if (confirm == true), 00910 // which means we are doing readOn. 00911 if ( fti->type() == KFolderTreeItem::Drafts || 00912 fti->type() == KFolderTreeItem::Templates || 00913 fti->type() == KFolderTreeItem::SentMail ) 00914 return false; 00915 00916 // warn user that going to next folder - but keep track of 00917 // whether he wishes to be notified again in "AskNextFolder" 00918 // parameter (kept in the config file for kmail) 00919 if ( KMessageBox::questionYesNo( this, 00920 i18n( "<qt>Go to the next unread message in folder <b>%1</b>?</qt>" ) 00921 .arg( fti->folder()->label() ), 00922 i18n( "Go to Next Unread Message" ), 00923 i18n("Go To"), i18n("Do Not Go To"), // defaults 00924 "AskNextFolder", 00925 false) 00926 == KMessageBox::No ) return true; 00927 } 00928 prepareItem( fti ); 00929 blockSignals( true ); 00930 doFolderSelected( fti ); 00931 blockSignals( false ); 00932 emit folderSelectedUnread( fti->folder() ); 00933 return true; 00934 } 00935 return false; 00936 } 00937 00938 //----------------------------------------------------------------------------- 00939 void KMFolderTree::prevUnreadFolder() 00940 { 00941 TQListViewItemIterator it( currentItem() ? currentItem() : lastItem() ); 00942 if ( currentItem() ) 00943 --it; // don't find current item 00944 for ( ; it.current() ; --it ) { 00945 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00946 if (checkUnreadFolder(fti,false)) return; 00947 } 00948 } 00949 00950 //----------------------------------------------------------------------------- 00951 void KMFolderTree::incCurrentFolder() 00952 { 00953 TQListViewItemIterator it( currentItem() ); 00954 ++it; 00955 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00956 if (fti) { 00957 prepareItem( fti ); 00958 setFocus(); 00959 setCurrentItem( fti ); 00960 } 00961 } 00962 00963 //----------------------------------------------------------------------------- 00964 void KMFolderTree::decCurrentFolder() 00965 { 00966 TQListViewItemIterator it( currentItem() ); 00967 --it; 00968 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); 00969 if (fti) { 00970 prepareItem( fti ); 00971 setFocus(); 00972 setCurrentItem( fti ); 00973 } 00974 } 00975 00976 //----------------------------------------------------------------------------- 00977 void KMFolderTree::selectCurrentFolder() 00978 { 00979 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() ); 00980 if (fti) { 00981 prepareItem( fti ); 00982 doFolderSelected( fti ); 00983 } 00984 } 00985 00986 //----------------------------------------------------------------------------- 00987 KMFolder *KMFolderTree::currentFolder() const 00988 { 00989 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() ); 00990 if (fti ) 00991 return fti->folder(); 00992 else 00993 return 0; 00994 } 00995 00996 TQValueList<TQGuardedPtr<KMFolder> > KMFolderTree::selectedFolders() 00997 { 00998 TQValueList<TQGuardedPtr<KMFolder> > rv; 00999 for ( TQListViewItemIterator it( this ); it.current(); ++it ) { 01000 if ( it.current()->isSelected() ) { 01001 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() ); 01002 rv.append( fti->folder() ); 01003 } 01004 } 01005 return rv; 01006 } 01007 01008 //----------------------------------------------------------------------------- 01009 // When not dragging and dropping a change in the selected item 01010 // indicates the user has changed the active folder emit a signal 01011 // so that the header list and reader window can be udpated. 01012 void KMFolderTree::doFolderSelected( TQListViewItem* qlvi, bool keepSelection ) 01013 { 01014 if (!qlvi) return; 01015 if ( mLastItem && mLastItem == qlvi && (keepSelection || selectedFolders().count() == 1) ) 01016 return; 01017 01018 KMFolderTreeItem* fti = static_cast< KMFolderTreeItem* >(qlvi); 01019 KMFolder* folder = 0; 01020 if (fti) folder = fti->folder(); 01021 01022 if (mLastItem && mLastItem != fti && mLastItem->folder() 01023 && (mLastItem->folder()->folderType() == KMFolderTypeImap)) 01024 { 01025 KMFolderImap *imapFolder = static_cast<KMFolderImap*>(mLastItem->folder()->storage()); 01026 imapFolder->setSelected(false); 01027 } 01028 mLastItem = fti; 01029 01030 if ( !keepSelection ) 01031 clearSelection(); 01032 setCurrentItem( qlvi ); 01033 if ( !keepSelection ) 01034 setSelected( qlvi, true ); 01035 ensureItemVisible( qlvi ); 01036 if (!folder) { 01037 emit folderSelected(0); // Root has been selected 01038 } 01039 else { 01040 emit folderSelected(folder); 01041 slotUpdateCounts(folder); 01042 } 01043 } 01044 01045 //----------------------------------------------------------------------------- 01046 void KMFolderTree::resizeEvent(TQResizeEvent* e) 01047 { 01048 TDEConfig* conf = KMKernel::config(); 01049 01050 TDEConfigGroupSaver saver(conf, "Geometry"); 01051 conf->writeEntry(name(), size().width()); 01052 01053 TDEListView::resizeEvent(e); 01054 } 01055 01056 //----------------------------------------------------------------------------- 01057 // show context menu 01058 void KMFolderTree::slotContextMenuRequested( TQListViewItem *lvi, 01059 const TQPoint &p ) 01060 { 01061 if (!lvi) 01062 return; 01063 setCurrentItem( lvi ); 01064 01065 if (!mMainWidget) return; // safe bet 01066 01067 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(lvi); 01068 if ( !isSelected( fti ) ) 01069 doFolderSelected( fti ); 01070 else if ( fti != mLastItem ) 01071 doFolderSelected( fti, true ); 01072 01073 if (!fti ) 01074 return; 01075 01076 TDEPopupMenu *folderMenu = new TDEPopupMenu; 01077 bool multiFolder = selectedFolders().count() > 1; 01078 if (fti->folder()) folderMenu->insertTitle(fti->folder()->label()); 01079 01080 // outbox specific, but there it's the most used action 01081 if ( (fti->folder() == kmkernel->outboxFolder()) && fti->folder()->count() ) 01082 mMainWidget->action("send_queued")->plug( folderMenu ); 01083 // Mark all as read is supposedly used often, therefor it is first 01084 if ( fti->folder() && !fti->folder()->noContent() ) 01085 mMainWidget->action("mark_all_as_read")->plug( folderMenu ); 01086 01087 /* Treat the special case of the root and account folders */ 01088 if ((!fti->folder() || (fti->folder()->noContent() 01089 && !fti->parent()))) 01090 { 01091 TQString createChild = i18n("&New Subfolder..."); 01092 if (!fti->folder()) createChild = i18n("&New Folder..."); 01093 01094 if ( ( fti->folder() || (fti->text(0) != i18n("Searches")) ) && !multiFolder) 01095 folderMenu->insertItem(SmallIconSet("folder-new"), 01096 createChild, this, 01097 TQT_SLOT(addChildFolder())); 01098 01099 if (!fti->folder()) { 01100 mMainWidget->action("compact_all_folders")->plug(folderMenu); 01101 mMainWidget->action("expire_all_folders")->plug(folderMenu); 01102 } else if (fti->folder()->folderType() == KMFolderTypeImap) { 01103 folderMenu->insertItem(SmallIconSet("mail_get"), i18n("Check &Mail"), 01104 this, 01105 TQT_SLOT(slotCheckMail())); 01106 } 01107 } else { // regular folders 01108 01109 folderMenu->insertSeparator(); 01110 if ( !fti->folder()->noChildren() && !multiFolder ) { 01111 folderMenu->insertItem(SmallIconSet("folder-new"), 01112 i18n("&New Subfolder..."), this, 01113 TQT_SLOT(addChildFolder())); 01114 } 01115 01116 // copy folder 01117 TQPopupMenu *copyMenu = new TQPopupMenu( folderMenu ); 01118 folderToPopupMenu( CopyFolder, TQT_TQOBJECT(this), &mMenuToFolder, copyMenu ); 01119 folderMenu->insertItem( i18n("&Copy Folder To"), copyMenu ); 01120 01121 if ( fti->folder()->isMoveable() && fti->folder()->canDeleteMessages() ) 01122 { 01123 TQPopupMenu *moveMenu = new TQPopupMenu( folderMenu ); 01124 folderToPopupMenu( MoveFolder, TQT_TQOBJECT(this), &mMenuToFolder, moveMenu ); 01125 folderMenu->insertItem( i18n("&Move Folder To"), moveMenu ); 01126 } 01127 01128 // Want to be able to display properties for ALL folders, 01129 // so we can edit expiry properties. 01130 // -- smp. 01131 if (!fti->folder()->noContent()) 01132 { 01133 if ( !multiFolder ) 01134 mMainWidget->action("search_messages")->plug(folderMenu); 01135 01136 mMainWidget->action( "archive_folder" )->plug( folderMenu ); 01137 01138 mMainWidget->action("compact")->plug(folderMenu); 01139 01140 if ( GlobalSettings::self()->enableFavoriteFolderView() ) { 01141 folderMenu->insertItem( SmallIconSet("bookmark_add"), i18n("Add to Favorite Folders"), 01142 this, TQT_SLOT(slotAddToFavorites()) ); 01143 } 01144 01145 folderMenu->insertSeparator(); 01146 mMainWidget->action("empty")->plug(folderMenu); 01147 if ( !fti->folder()->isSystemFolder() ) { 01148 mMainWidget->action("delete_folder")->plug(folderMenu); 01149 } 01150 folderMenu->insertSeparator(); 01151 } 01152 } 01153 01154 /* plug in IMAP and DIMAP specific things */ 01155 if (fti->folder() && 01156 (fti->folder()->folderType() == KMFolderTypeImap || 01157 fti->folder()->folderType() == KMFolderTypeCachedImap )) 01158 { 01159 folderMenu->insertItem(SmallIconSet("bookmark_folder"), 01160 i18n("Serverside Subscription..."), mMainWidget, 01161 TQT_SLOT(slotSubscriptionDialog())); 01162 folderMenu->insertItem(SmallIcon("bookmark_folder"), 01163 i18n("Local Subscription..."), mMainWidget, 01164 TQT_SLOT(slotLocalSubscriptionDialog())); 01165 01166 if (!fti->folder()->noContent()) 01167 { 01168 mMainWidget->action("refresh_folder")->plug(folderMenu); 01169 if ( fti->folder()->folderType() == KMFolderTypeImap && !multiFolder ) { 01170 folderMenu->insertItem(SmallIconSet("reload"), i18n("Refresh Folder List"), this, 01171 TQT_SLOT(slotResetFolderList())); 01172 } 01173 } 01174 if ( fti->folder()->folderType() == KMFolderTypeCachedImap && !multiFolder ) { 01175 KMFolderCachedImap * folder = static_cast<KMFolderCachedImap*>( fti->folder()->storage() ); 01176 folderMenu->insertItem( SmallIconSet("wizard"), 01177 i18n("&Troubleshoot IMAP Cache..."), 01178 folder, TQT_SLOT(slotTroubleshoot()) ); 01179 } 01180 folderMenu->insertSeparator(); 01181 } 01182 01183 if ( fti->folder() && fti->folder()->isMailingListEnabled() && !multiFolder ) { 01184 mMainWidget->action("post_message")->plug(folderMenu); 01185 } 01186 01187 if (fti->folder() && fti->parent() && !multiFolder) 01188 { 01189 folderMenu->insertItem(SmallIconSet("configure_shortcuts"), 01190 i18n("&Assign Shortcut..."), 01191 fti, 01192 TQT_SLOT(assignShortcut())); 01193 01194 if ( !fti->folder()->noContent() && fti->folder()->canDeleteMessages() ) { 01195 folderMenu->insertItem( i18n("Expire..."), fti, 01196 TQT_SLOT( slotShowExpiryProperties() ) ); 01197 } 01198 mMainWidget->action("modify")->plug(folderMenu); 01199 } 01200 01201 01202 kmkernel->setContextMenuShown( true ); 01203 folderMenu->exec (p, 0); 01204 kmkernel->setContextMenuShown( false ); 01205 triggerUpdate(); 01206 delete folderMenu; 01207 folderMenu = 0; 01208 } 01209 01210 //----------------------------------------------------------------------------- 01211 void KMFolderTree::contentsMousePressEvent(TQMouseEvent * e) 01212 { 01213 // KFolderTree messes around with the selection mode 01214 TDEListView::contentsMousePressEvent( e ); 01215 } 01216 01217 // If middle button and folder holds mailing-list, create a message to that list 01218 void KMFolderTree::contentsMouseReleaseEvent(TQMouseEvent* me) 01219 { 01220 TQListViewItem *lvi = currentItem(); // Needed for when branches are clicked on 01221 ButtonState btn = me->button(); 01222 doFolderSelected(lvi, true); 01223 01224 // get underlying folder 01225 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>(lvi); 01226 01227 if (!fti || !fti->folder()) { 01228 KFolderTree::contentsMouseReleaseEvent(me); 01229 return; 01230 } 01231 01232 // react on middle-button only 01233 if (btn != Qt::MidButton) { 01234 KFolderTree::contentsMouseReleaseEvent(me); 01235 return; 01236 } 01237 01238 if ( fti->folder()->isMailingListEnabled() ) { 01239 KMCommand *command = new KMMailingListPostCommand( this, fti->folder() ); 01240 command->start(); 01241 } 01242 01243 KFolderTree::contentsMouseReleaseEvent(me); 01244 } 01245 01246 // little static helper 01247 static bool folderHasCreateRights( const KMFolder *folder ) 01248 { 01249 bool createRights = true; // we don't have acls for local folders yet 01250 if ( folder && folder->folderType() == KMFolderTypeImap ) { 01251 const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() ); 01252 createRights = imapFolder->userRightsState() != KMail::ACLJobs::Ok || // hack, we should get the acls 01253 ( imapFolder->userRightsState() == KMail::ACLJobs::Ok && 01254 ( imapFolder->userRights() & KMail::ACLJobs::Create ) ); 01255 } else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) { 01256 const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() ); 01257 createRights = dimapFolder->userRightsState() != KMail::ACLJobs::Ok || 01258 ( dimapFolder->userRightsState() == KMail::ACLJobs::Ok && 01259 ( dimapFolder->userRights() & KMail::ACLJobs::Create ) ); 01260 } 01261 return createRights; 01262 } 01263 01264 //----------------------------------------------------------------------------- 01265 // Create a subfolder. 01266 // Requires creating the appropriate subdirectory and show a dialog 01267 void KMFolderTree::addChildFolder( KMFolder *folder, TQWidget * parent ) 01268 { 01269 KMFolder *aFolder = folder; 01270 if ( !aFolder ) { 01271 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(currentItem()); 01272 if (!fti) 01273 return; 01274 aFolder = fti->folder(); 01275 } 01276 if (aFolder) { 01277 if (!aFolder->createChildFolder()) 01278 return; 01279 if ( !folderHasCreateRights( aFolder ) ) { 01280 const TQString message = i18n( "<qt>Cannot create folder under <b>%1</b> because of insufficient " 01281 "permissions on the server. If you think you should be able to create " 01282 "subfolders here, ask your administrator to grant you rights to do so." 01283 "</qt> " ).arg(aFolder->label()); 01284 KMessageBox::error( this, message ); 01285 return; 01286 } 01287 } 01288 01289 if ( parent ) 01290 ( new KMail::NewFolderDialog( parent, aFolder ) )->exec(); 01291 else 01292 ( new KMail::NewFolderDialog( this, aFolder ) )->show(); 01293 return; 01294 /* 01295 KMFolderDir *dir = &(kmkernel->folderMgr()->dir()); 01296 if (aFolder) 01297 dir = aFolder->child(); 01298 01299 KMFolderDialog *d = 01300 new KMFolderDialog(0, dir, this, i18n("Create Subfolder") ); 01301 01302 if (d->exec()) { // fti may be deleted here 01303 TQListViewItem *qlvi = indexOfFolder( aFolder ); 01304 if (qlvi) { 01305 qlvi->setOpen(true); 01306 blockSignals( true ); 01307 setCurrentItem( qlvi ); 01308 blockSignals( false ); 01309 } 01310 } 01311 delete d; 01312 // update if added to root Folder 01313 if (!aFolder || aFolder->noContent()) { 01314 doFolderListChanged(); 01315 } 01316 */ 01317 } 01318 01319 //----------------------------------------------------------------------------- 01320 // Returns whether a folder directory should be open as specified in the 01321 // config file. 01322 bool KMFolderTree::readIsListViewItemOpen(KMFolderTreeItem *fti) 01323 { 01324 TDEConfig* config = KMKernel::config(); 01325 KMFolder *folder = fti->folder(); 01326 TQString name; 01327 if (folder) 01328 { 01329 name = "Folder-" + folder->idString(); 01330 } else if (fti->type() == KFolderTreeItem::Root) 01331 { 01332 if (fti->protocol() == KFolderTreeItem::NONE) // local root 01333 name = "Folder_local_root"; 01334 else if (fti->protocol() == KFolderTreeItem::Search) 01335 name = "Folder_search"; 01336 else 01337 return false; 01338 } else { 01339 return false; 01340 } 01341 TDEConfigGroupSaver saver(config, name); 01342 01343 return config->readBoolEntry("isOpen", false); 01344 } 01345 01346 //----------------------------------------------------------------------------- 01347 // Saves open/closed state of a folder directory into the config file 01348 void KMFolderTree::writeIsListViewItemOpen(KMFolderTreeItem *fti) 01349 { 01350 TDEConfig* config = KMKernel::config(); 01351 KMFolder *folder = fti->folder(); 01352 TQString name; 01353 if (folder && !folder->idString().isEmpty()) 01354 { 01355 name = "Folder-" + folder->idString(); 01356 } else if (fti->type() == KFolderTreeItem::Root) 01357 { 01358 if (fti->protocol() == KFolderTreeItem::NONE) // local root 01359 name = "Folder_local_root"; 01360 else if (fti->protocol() == KFolderTreeItem::Search) 01361 name = "Folder_search"; 01362 else 01363 return; 01364 } else { 01365 return; 01366 } 01367 TDEConfigGroupSaver saver(config, name); 01368 config->writeEntry("isOpen", fti->isOpen() ); 01369 } 01370 01371 01372 //----------------------------------------------------------------------------- 01373 void KMFolderTree::cleanupConfigFile() 01374 { 01375 if ( childCount() == 0 ) 01376 return; // just in case reload wasn't called before 01377 TDEConfig* config = KMKernel::config(); 01378 TQStringList existingFolders; 01379 TQListViewItemIterator fldIt(this); 01380 TQMap<TQString,bool> folderMap; 01381 KMFolderTreeItem *fti; 01382 for (TQListViewItemIterator fldIt(this); fldIt.current(); fldIt++) 01383 { 01384 fti = static_cast<KMFolderTreeItem*>(fldIt.current()); 01385 if (fti && fti->folder()) 01386 folderMap.insert(fti->folder()->idString(), true); 01387 } 01388 TQStringList groupList = config->groupList(); 01389 TQString name; 01390 for (TQStringList::Iterator grpIt = groupList.begin(); 01391 grpIt != groupList.end(); grpIt++) 01392 { 01393 if ((*grpIt).left(7) != "Folder-") continue; 01394 name = (*grpIt).mid(7); 01395 if (folderMap.find(name) == folderMap.end()) 01396 { 01397 KMFolder* folder = kmkernel->findFolderById( name ); 01398 if ( folder ) { 01399 if ( kmkernel->iCalIface().hideResourceFolder( folder ) 01400 || kmkernel->iCalIface().hideResourceAccountRoot( folder ) ) 01401 continue; // hidden IMAP resource folder, don't delete info 01402 if ( folder->noContent() ) 01403 continue; // we hide nocontent folders if they have no child folders 01404 if ( folder == kmkernel->inboxFolder() ) 01405 continue; // local inbox can be hidden as well 01406 } 01407 01408 //KMessageBox::error( 0, "cleanupConfigFile: Deleting group " + *grpIt ); 01409 config->deleteGroup(*grpIt, true); 01410 kdDebug(5006) << "Deleting information about folder " << name << endl; 01411 } 01412 } 01413 } 01414 01415 01416 //----------------------------------------------------------------------------- 01417 void KMFolderTree::openFolder() 01418 { 01419 autoopen_timer.stop(); 01420 if ( dropItem && !dropItem->isOpen() ) { 01421 dropItem->setOpen( true ); 01422 dropItem->repaint(); 01423 } 01424 } 01425 01426 static const int autoopenTime = 750; 01427 01428 //----------------------------------------------------------------------------- 01429 void KMFolderTree::contentsDragEnterEvent( TQDragEnterEvent *e ) 01430 { 01431 oldCurrent = 0; 01432 oldSelected = 0; 01433 01434 oldCurrent = currentItem(); 01435 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) 01436 if ( it.current()->isSelected() ) 01437 oldSelected = it.current(); 01438 01439 setFocus(); 01440 01441 TQListViewItem *i = itemAt( contentsToViewport(e->pos()) ); 01442 if ( i ) { 01443 dropItem = i; 01444 autoopen_timer.start( autoopenTime ); 01445 } 01446 else 01447 dropItem = 0; 01448 01449 e->accept( acceptDrag(e) ); 01450 } 01451 01452 //----------------------------------------------------------------------------- 01453 void KMFolderTree::contentsDragMoveEvent( TQDragMoveEvent *e ) 01454 { 01455 TQPoint vp = contentsToViewport(e->pos()); 01456 TQListViewItem *i = itemAt( vp ); 01457 if ( i ) { 01458 bool dragAccepted = acceptDrag( e ); 01459 if ( dragAccepted ) { 01460 setCurrentItem( i ); 01461 } 01462 01463 if ( i != dropItem ) { 01464 autoopen_timer.stop(); 01465 dropItem = i; 01466 autoopen_timer.start( autoopenTime ); 01467 } 01468 01469 if ( dragAccepted ) { 01470 e->accept( itemRect(i) ); 01471 01472 switch ( e->action() ) { 01473 case TQDropEvent::Copy: 01474 break; 01475 case TQDropEvent::Move: 01476 e->acceptAction(); 01477 break; 01478 case TQDropEvent::Link: 01479 e->acceptAction(); 01480 break; 01481 default: 01482 ; 01483 } 01484 } else { 01485 e->accept( false ); 01486 } 01487 } else { 01488 e->accept( false ); 01489 autoopen_timer.stop(); 01490 dropItem = 0; 01491 } 01492 } 01493 01494 //----------------------------------------------------------------------------- 01495 void KMFolderTree::contentsDragLeaveEvent( TQDragLeaveEvent * ) 01496 { 01497 if (!oldCurrent) return; 01498 01499 autoopen_timer.stop(); 01500 dropItem = 0; 01501 01502 setCurrentItem( oldCurrent ); 01503 if ( oldSelected ) 01504 setSelected( oldSelected, true ); 01505 } 01506 01507 //----------------------------------------------------------------------------- 01508 void KMFolderTree::contentsDropEvent( TQDropEvent *e ) 01509 { 01510 autoopen_timer.stop(); 01511 01512 TQListViewItem *item = itemAt( contentsToViewport(e->pos()) ); 01513 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); 01514 // Check that each pointer is not null 01515 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin(); 01516 it != mCopySourceFolders.constEnd(); ++it ) { 01517 if ( ! (*it) ) { 01518 fti = 0; 01519 break; 01520 } 01521 } 01522 if (fti && mCopySourceFolders.count() == 1) 01523 { 01524 KMFolder *source = mCopySourceFolders.first(); 01525 // if we are dragging to ourselves or to our parent, set fti to 0 so nothing is done 01526 if (source == fti->folder() || source->parent()->owner() == fti->folder()) fti = 0; 01527 } 01528 if (fti && acceptDrag(e) && ( fti != oldSelected || e->source() != mMainWidget->headers()->viewport() ) ) 01529 { 01530 if ( e->provides("application/x-qlistviewitem") ) { 01531 int action = dndMode( true /* always ask */ ); 01532 if ( (action == DRAG_COPY || action == DRAG_MOVE) && !mCopySourceFolders.isEmpty() ) { 01533 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin(); 01534 it != mCopySourceFolders.constEnd(); ++it ) { 01535 if ( ! (*it)->isMoveable() ) 01536 action = DRAG_COPY; 01537 } 01538 moveOrCopyFolder( mCopySourceFolders, fti->folder(), (action == DRAG_MOVE) ); 01539 } 01540 } else { 01541 if ( e->source() == mMainWidget->headers()->viewport() ) { 01542 int action; 01543 if ( mMainWidget->headers()->folder() && mMainWidget->headers()->folder()->isReadOnly() ) 01544 action = DRAG_COPY; 01545 else 01546 action = dndMode(); 01547 // KMHeaders does copy/move itself 01548 if ( action == DRAG_MOVE && fti->folder() ) 01549 emit folderDrop( fti->folder() ); 01550 else if ( action == DRAG_COPY && fti->folder() ) 01551 emit folderDropCopy( fti->folder() ); 01552 } else { 01553 handleMailListDrop( e, fti->folder() ); 01554 } 01555 } 01556 e->accept( true ); 01557 } else 01558 e->accept( false ); 01559 01560 dropItem = 0; 01561 01562 setCurrentItem( oldCurrent ); 01563 if ( oldCurrent) mLastItem = static_cast<KMFolderTreeItem*>(oldCurrent); 01564 if ( oldSelected ) 01565 { 01566 clearSelection(); 01567 setSelected( oldSelected, true ); 01568 } 01569 01570 mCopySourceFolders.clear(); 01571 } 01572 01573 //----------------------------------------------------------------------------- 01574 void KMFolderTree::slotFolderExpanded( TQListViewItem * item ) 01575 { 01576 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); 01577 if ( !fti || !fti->folder() || !fti->folder()->storage() ) return; 01578 01579 fti->setFolderSize( fti->folder()->storage()->folderSize() ); 01580 01581 if( fti->folder()->folderType() == KMFolderTypeImap ) 01582 { 01583 KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() ); 01584 // if we should list all folders we limit this to the root folder 01585 if ( !folder->account() || ( !folder->account()->listOnlyOpenFolders() && 01586 fti->parent() ) ) 01587 return; 01588 if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation ) 01589 { 01590 // check if all parents are expanded 01591 TQListViewItem *parent = item->parent(); 01592 while ( parent ) 01593 { 01594 if ( !parent->isOpen() ) 01595 return; 01596 parent = parent->parent(); 01597 } 01598 // the tree will be reloaded after that 01599 bool success = folder->listDirectory(); 01600 if (!success) fti->setOpen( false ); 01601 if ( fti->childCount() == 0 && fti->parent() ) 01602 fti->setExpandable( false ); 01603 } 01604 } 01605 } 01606 01607 01608 //----------------------------------------------------------------------------- 01609 void KMFolderTree::slotFolderCollapsed( TQListViewItem * item ) 01610 { 01611 slotResetFolderList( item, false ); 01612 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); 01613 if ( !fti || !fti->folder() || !fti->folder()->storage() ) return; 01614 01615 fti->setFolderSize( fti->folder()->storage()->folderSize() ); 01616 } 01617 01618 //----------------------------------------------------------------------------- 01619 void KMFolderTree::slotRenameFolder(TQListViewItem *item, int col, 01620 const TQString &text) 01621 { 01622 01623 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); 01624 01625 if ((!fti) || (fti && fti->folder() && col != 0 && !currentFolder()->child())) 01626 return; 01627 01628 TQString fldName, oldFldName; 01629 01630 oldFldName = fti->name(0); 01631 01632 if (!text.isEmpty()) 01633 fldName = text; 01634 else 01635 fldName = oldFldName; 01636 01637 fldName.replace("/", ""); 01638 fldName.replace(TQRegExp("^\\."), ""); 01639 01640 if (fldName.isEmpty()) 01641 fldName = i18n("unnamed"); 01642 01643 fti->setText(0, fldName); 01644 fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir())); 01645 } 01646 01647 //----------------------------------------------------------------------------- 01648 void KMFolderTree::slotUpdateCountsDelayed(KMFolder * folder) 01649 { 01650 // kdDebug(5006) << "KMFolderTree::slotUpdateCountsDelayed()" << endl; 01651 if ( !mFolderToUpdateCount.contains( folder->idString() ) ) 01652 { 01653 // kdDebug( 5006 )<< "adding " << folder->idString() << " to updateCountList " << endl; 01654 mFolderToUpdateCount.insert( folder->idString(),folder ); 01655 } 01656 if ( !mUpdateCountTimer->isActive() ) 01657 mUpdateCountTimer->start( 500 ); 01658 } 01659 01660 01661 void KMFolderTree::slotUpdateCountTimeout() 01662 { 01663 // kdDebug(5006) << "KMFolderTree::slotUpdateCountTimeout()" << endl; 01664 01665 TQMap<TQString,KMFolder*>::iterator it; 01666 for ( it= mFolderToUpdateCount.begin(); 01667 it!=mFolderToUpdateCount.end(); 01668 ++it ) 01669 { 01670 slotUpdateCounts( it.data() ); 01671 } 01672 mFolderToUpdateCount.clear(); 01673 mUpdateCountTimer->stop(); 01674 01675 } 01676 01677 void KMFolderTree::updatePopup() const 01678 { 01679 mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); 01680 mPopup->setItemChecked( mTotalPop, isTotalActive() ); 01681 mPopup->setItemChecked( mSizePop, isSizeActive() ); 01682 } 01683 01684 //----------------------------------------------------------------------------- 01685 void KMFolderTree::toggleColumn(int column, bool openFolders) 01686 { 01687 if (column == unread) 01688 { 01689 // switch unread 01690 if ( isUnreadActive() ) 01691 { 01692 removeUnreadColumn(); 01693 reload(); 01694 } else { 01695 addUnreadColumn( i18n("Unread"), 70 ); 01696 reload(); 01697 } 01698 // toggle TDEPopupMenu 01699 mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); 01700 01701 } else if (column == total) { 01702 // switch total 01703 if ( isTotalActive() ) 01704 { 01705 removeTotalColumn(); 01706 reload(); 01707 } else { 01708 addTotalColumn( i18n("Total"), 70 ); 01709 reload(openFolders); 01710 } 01711 mPopup->setItemChecked( mTotalPop, isTotalActive() ); 01712 } else if (column == foldersize) { 01713 // switch total 01714 if ( isSizeActive() ) 01715 { 01716 removeSizeColumn(); 01717 reload(); 01718 } else { 01719 addSizeColumn( i18n("Size"), 70 ); 01720 reload( openFolders ); 01721 } 01722 // toggle TDEPopupMenu 01723 mPopup->setItemChecked( mSizePop, isSizeActive() ); 01724 01725 } else kdDebug(5006) << "unknown column:" << column << endl; 01726 01727 // toggles the switches of the mainwin 01728 emit columnsChanged(); 01729 } 01730 01731 //----------------------------------------------------------------------------- 01732 void KMFolderTree::slotToggleUnreadColumn() 01733 { 01734 toggleColumn(unread); 01735 } 01736 01737 //----------------------------------------------------------------------------- 01738 void KMFolderTree::slotToggleTotalColumn() 01739 { 01740 // activate the total-column and force the folders to be opened 01741 toggleColumn(total, true); 01742 } 01743 01744 //----------------------------------------------------------------------------- 01745 void KMFolderTree::slotToggleSizeColumn() 01746 { 01747 // activate the size-column and force the folders to be opened 01748 toggleColumn(foldersize, true); 01749 } 01750 01751 01752 //----------------------------------------------------------------------------- 01753 bool KMFolderTree::eventFilter( TQObject *o, TQEvent *e ) 01754 { 01755 if ( e->type() == TQEvent::MouseButtonPress && 01756 TQT_TQMOUSEEVENT(e)->button() == Qt::RightButton && 01757 o->isA(TQHEADER_OBJECT_NAME_STRING) ) 01758 { 01759 mPopup->popup( TQT_TQMOUSEEVENT(e)->globalPos() ); 01760 return true; 01761 } 01762 return KFolderTree::eventFilter(o, e); 01763 } 01764 01765 //----------------------------------------------------------------------------- 01766 void KMFolderTree::slotCheckMail() 01767 { 01768 if (!currentItem()) 01769 return; 01770 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(currentItem()); 01771 KMFolder* folder = fti->folder(); 01772 if (folder && folder->storage() ) { 01773 if ( KMAccount* acct = folder->storage()->account() ) { 01774 kmkernel->acctMgr()->singleCheckMail(acct, true); 01775 } 01776 } 01777 } 01778 01779 //----------------------------------------------------------------------------- 01780 void KMFolderTree::slotNewMessageToMailingList() 01781 { 01782 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( currentItem() ); 01783 if ( !fti || !fti->folder() ) 01784 return; 01785 KMCommand *command = new KMMailingListPostCommand( this, fti->folder() ); 01786 command->start(); 01787 } 01788 01789 //----------------------------------------------------------------------------- 01790 void KMFolderTree::createFolderList( TQStringList *str, 01791 TQValueList<TQGuardedPtr<KMFolder> > *folders, 01792 bool localFolders, 01793 bool imapFolders, 01794 bool dimapFolders, 01795 bool searchFolders, 01796 bool includeNoContent, 01797 bool includeNoChildren ) 01798 { 01799 for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) 01800 { 01801 KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); 01802 if (!fti || !fti->folder()) continue; 01803 // type checks 01804 KMFolder* folder = fti->folder(); 01805 if (!imapFolders && folder->folderType() == KMFolderTypeImap) continue; 01806 if (!dimapFolders && folder->folderType() == KMFolderTypeCachedImap) continue; 01807 if (!localFolders && (folder->folderType() == KMFolderTypeMbox || 01808 folder->folderType() == KMFolderTypeMaildir)) continue; 01809 if (!searchFolders && folder->folderType() == KMFolderTypeSearch) continue; 01810 if (!includeNoContent && folder->noContent()) continue; 01811 if (!includeNoChildren && folder->noChildren()) continue; 01812 TQString prefix; 01813 prefix.fill( ' ', 2 * fti->depth() ); 01814 str->append(prefix + fti->text(0)); 01815 folders->append(fti->folder()); 01816 } 01817 } 01818 01819 //----------------------------------------------------------------------------- 01820 void KMFolderTree::slotResetFolderList( TQListViewItem* item, bool startList ) 01821 { 01822 if ( !item ) 01823 item = currentItem(); 01824 01825 KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( item ); 01826 if ( fti && fti->folder() && 01827 fti->folder()->folderType() == KMFolderTypeImap ) 01828 { 01829 KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() ); 01830 folder->setSubfolderState( KMFolderImap::imapNoInformation ); 01831 if ( startList ) 01832 folder->listDirectory(); 01833 } 01834 } 01835 01836 //----------------------------------------------------------------------------- 01837 void KMFolderTree::showFolder( KMFolder* folder ) 01838 { 01839 if ( !folder ) return; 01840 TQListViewItem* item = indexOfFolder( folder ); 01841 if ( item ) 01842 { 01843 doFolderSelected( item ); 01844 ensureItemVisible( item ); 01845 } 01846 } 01847 01848 //----------------------------------------------------------------------------- 01849 void KMFolderTree::folderToPopupMenu( MenuAction action, TQObject *receiver, 01850 KMMenuToFolder *aMenuToFolder, TQPopupMenu *menu, TQListViewItem *item ) 01851 { 01852 while ( menu->count() ) 01853 { 01854 TQPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup(); 01855 if ( popup ) 01856 delete popup; 01857 else 01858 menu->removeItemAt( 0 ); 01859 } 01860 // connect the signals 01861 if ( action == MoveMessage || action == MoveFolder ) 01862 { 01863 disconnect( menu, TQT_SIGNAL(activated(int)), receiver, 01864 TQT_SLOT(moveSelectedToFolder(int)) ); 01865 connect( menu, TQT_SIGNAL(activated(int)), receiver, 01866 TQT_SLOT(moveSelectedToFolder(int)) ); 01867 } else { 01868 disconnect( menu, TQT_SIGNAL(activated(int)), receiver, 01869 TQT_SLOT(copySelectedToFolder(int)) ); 01870 connect( menu, TQT_SIGNAL(activated(int)), receiver, 01871 TQT_SLOT(copySelectedToFolder(int)) ); 01872 } 01873 if ( !item ) { 01874 item = firstChild(); 01875 01876 // avoid a popup menu with the single entry 'Local Folders' if there 01877 // are no IMAP accounts 01878 if ( childCount() == 2 && action != MoveFolder ) { // only 'Local Folders' and 'Searches' 01879 KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item ); 01880 if ( fti->protocol() == KFolderTreeItem::Search ) { 01881 // skip 'Searches' 01882 item = item->nextSibling(); 01883 fti = static_cast<KMFolderTreeItem*>( item ); 01884 } 01885 folderToPopupMenu( action, receiver, aMenuToFolder, menu, fti->firstChild() ); 01886 return; 01887 } 01888 } 01889 01890 while ( item ) 01891 { 01892 KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( item ); 01893 if ( fti->protocol() == KFolderTreeItem::Search ) 01894 { 01895 // skip search folders 01896 item = item->nextSibling(); 01897 continue; 01898 } 01899 TQString label = fti->text( 0 ); 01900 label.replace( "&","&&" ); 01901 if ( fti->firstChild() ) 01902 { 01903 // new level 01904 TQPopupMenu* popup = new TQPopupMenu( menu, "subMenu" ); 01905 folderToPopupMenu( action, receiver, aMenuToFolder, popup, fti->firstChild() ); 01906 bool subMenu = false; 01907 if ( ( action == MoveMessage || action == CopyMessage ) && 01908 fti->folder() && !fti->folder()->noContent() ) 01909 subMenu = true; 01910 if ( ( action == MoveFolder || action == CopyFolder ) 01911 && ( !fti->folder() || ( fti->folder() && !fti->folder()->noChildren() ) ) ) 01912 subMenu = true; 01913 01914 TQString sourceFolderName; 01915 KMFolderTreeItem* srcItem = dynamic_cast<KMFolderTreeItem*>( currentItem() ); 01916 if ( srcItem ) 01917 sourceFolderName = srcItem->text( 0 ); 01918 01919 if ( (action == MoveFolder || action == CopyFolder) 01920 && fti->folder() && fti->folder()->child() 01921 && fti->folder()->child()->hasNamedFolder( sourceFolderName ) ) { 01922 subMenu = false; 01923 } 01924 01925 if ( subMenu ) 01926 { 01927 int menuId; 01928 if ( action == MoveMessage || action == MoveFolder ) 01929 menuId = popup->insertItem( i18n("Move to This Folder"), -1, 0 ); 01930 else 01931 menuId = popup->insertItem( i18n("Copy to This Folder"), -1, 0 ); 01932 popup->insertSeparator( 1 ); 01933 aMenuToFolder->insert( menuId, fti->folder() ); 01934 } 01935 menu->insertItem( label, popup ); 01936 } else 01937 { 01938 // insert an item 01939 int menuId = menu->insertItem( label ); 01940 if ( fti->folder() ) 01941 aMenuToFolder->insert( menuId, fti->folder() ); 01942 bool enabled = (fti->folder() ? true : false); 01943 if ( fti->folder() && 01944 ( fti->folder()->isReadOnly() || fti->folder()->noContent() ) ) 01945 enabled = false; 01946 menu->setItemEnabled( menuId, enabled ); 01947 } 01948 01949 item = item->nextSibling(); 01950 } 01951 } 01952 01953 //----------------------------------------------------------------------------- 01954 void KMFolderTree::moveSelectedToFolder( int menuId ) 01955 { 01956 moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], true /*move*/ ); 01957 } 01958 01959 //----------------------------------------------------------------------------- 01960 void KMFolderTree::copySelectedToFolder( int menuId ) 01961 { 01962 moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], false /*copy, don't move*/ ); 01963 } 01964 01965 //----------------------------------------------------------------------------- 01966 void KMFolderTree::moveOrCopyFolder( TQValueList<TQGuardedPtr<KMFolder> > sources, KMFolder* destination, bool move ) 01967 { 01968 kdDebug(5006) << k_funcinfo << "source: " << sources << " destination: " << destination << " move: " << move << endl; 01969 01970 // Disable drag during copy operation since it prevents from many crashes 01971 setDragEnabled( false ); 01972 01973 KMFolderDir* parent = &(kmkernel->folderMgr()->dir()); 01974 if ( destination ) 01975 parent = destination->createChildFolder(); 01976 01977 TQStringList sourceFolderNames; 01978 01979 // check if move/copy is possible at all 01980 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) { 01981 KMFolder* source = *it; 01982 01983 // check if folder with same name already exits 01984 TQString sourceFolderName; 01985 if ( source ) 01986 sourceFolderName = source->label(); 01987 01988 if ( parent->hasNamedFolder( sourceFolderName ) || sourceFolderNames.contains( sourceFolderName ) ) { 01989 KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> here because a folder with the same name already exists.</qt>") 01990 .arg( sourceFolderName ) ); 01991 setDragEnabled( true ); 01992 return; 01993 } 01994 sourceFolderNames.append( sourceFolderName ); 01995 01996 // don't move/copy a folder that's still not completely moved/copied 01997 KMFolder *f = source; 01998 while ( f ) { 01999 if ( f->moveInProgress() ) { 02000 KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> because it is not completely copied itself.</qt>") 02001 .arg( sourceFolderName ) ); 02002 setDragEnabled( true ); 02003 return; 02004 } 02005 if ( f->parent() ) 02006 f = f->parent()->owner(); 02007 } 02008 02009 TQString message = 02010 i18n( "<qt>Cannot move or copy folder <b>%1</b> into a subfolder below itself.</qt>" ). 02011 arg( sourceFolderName ); 02012 KMFolderDir* folderDir = parent; 02013 // check that the folder can be moved 02014 if ( source && source->child() ) 02015 { 02016 while ( folderDir && ( folderDir != &kmkernel->folderMgr()->dir() ) && 02017 ( folderDir != source->parent() ) ) 02018 { 02019 if ( folderDir->findRef( source ) != -1 ) 02020 { 02021 KMessageBox::error( this, message ); 02022 setDragEnabled( true ); 02023 return; 02024 } 02025 folderDir = folderDir->parent(); 02026 } 02027 } 02028 02029 if( source && source->child() && parent && 02030 ( parent->path().find( source->child()->path() + "/" ) == 0 ) ) { 02031 KMessageBox::error( this, message ); 02032 setDragEnabled( true ); 02033 return; 02034 } 02035 02036 if( source && source->child() 02037 && ( parent == source->child() ) ) { 02038 KMessageBox::error( this, message ); 02039 setDragEnabled( true ); 02040 return; 02041 } 02042 } 02043 02044 // check if the source folders are independent of each other 02045 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); move && it != sources.constEnd(); ++it ) { 02046 KMFolderDir *parentDir = (*it)->child(); 02047 if ( !parentDir ) 02048 continue; 02049 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it2 = sources.constBegin(); it2 != sources.constEnd(); ++it2 ) { 02050 if ( *it == *it2 ) 02051 continue; 02052 KMFolderDir *childDir = (*it2)->parent(); 02053 do { 02054 if ( parentDir == childDir || parentDir->findRef( childDir->owner() ) != -1 ) { 02055 KMessageBox::error( this, i18n("Moving the selected folders is not possible") ); 02056 setDragEnabled( true ); 02057 return; 02058 } 02059 childDir = childDir->parent(); 02060 } 02061 while ( childDir && childDir != &kmkernel->folderMgr()->dir() ); 02062 } 02063 } 02064 02065 // de-select moved source folders (can cause crash due to unGetMsg() in KMHeaders) 02066 if ( move ) { 02067 doFolderSelected( indexOfFolder( destination ), false ); 02068 oldCurrent = currentItem(); 02069 } 02070 02071 // do the actual move/copy 02072 for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) { 02073 KMFolder* source = *it; 02074 if ( move ) { 02075 kdDebug(5006) << "move folder " << (source ? source->label(): "Unknown") << " to " 02076 << ( destination ? destination->label() : "Local Folders" ) << endl; 02077 kmkernel->folderMgr()->moveFolder( source, parent ); 02078 } else { 02079 kmkernel->folderMgr()->copyFolder( source, parent ); 02080 } 02081 } 02082 } 02083 02084 TQDragObject * KMFolderTree::dragObject() 02085 { 02086 KMFolderTreeItem *item = static_cast<KMFolderTreeItem*> 02087 (itemAt(viewport()->mapFromGlobal(TQCursor::pos()))); 02088 if ( !item || !item->parent() || !item->folder() ) // top-level items or something invalid 02089 return 0; 02090 mCopySourceFolders = selectedFolders(); 02091 02092 TQDragObject *drag = KFolderTree::dragObject(); 02093 if ( drag ) 02094 drag->setPixmap( SmallIcon("folder") ); 02095 return drag; 02096 } 02097 02098 void KMFolderTree::copyFolder() 02099 { 02100 KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); 02101 if ( item ) { 02102 mCopySourceFolders = selectedFolders(); 02103 mCutFolder = false; 02104 } 02105 updateCopyActions(); 02106 } 02107 02108 void KMFolderTree::cutFolder() 02109 { 02110 KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); 02111 if ( item ) { 02112 mCopySourceFolders = selectedFolders(); 02113 mCutFolder = true; 02114 } 02115 updateCopyActions(); 02116 } 02117 02118 void KMFolderTree::pasteFolder() 02119 { 02120 KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); 02121 if ( !mCopySourceFolders.isEmpty() && item && !mCopySourceFolders.contains( item->folder() ) ) { 02122 moveOrCopyFolder( mCopySourceFolders, item->folder(), mCutFolder ); 02123 if ( mCutFolder ) 02124 mCopySourceFolders.clear(); 02125 } 02126 updateCopyActions(); 02127 } 02128 02129 void KMFolderTree::updateCopyActions() 02130 { 02131 TDEAction *copy = mMainWidget->action("copy_folder"); 02132 TDEAction *cut = mMainWidget->action("cut_folder"); 02133 TDEAction *paste = mMainWidget->action("paste_folder"); 02134 KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); 02135 02136 if ( !item || !item->folder() ) { 02137 copy->setEnabled( false ); 02138 cut->setEnabled( false ); 02139 } else { 02140 copy->setEnabled( true ); 02141 cut->setEnabled( item->folder()->isMoveable() ); 02142 } 02143 02144 if ( mCopySourceFolders.isEmpty() ) 02145 paste->setEnabled( false ); 02146 else 02147 paste->setEnabled( true ); 02148 } 02149 02150 void KMFolderTree::slotSyncStateChanged() 02151 { 02152 // Only emit the signal when a selected folder changes, otherwise the folder menu is updated 02153 // too often 02154 TQValueList< TQGuardedPtr<KMFolder> > folders = selectedFolders(); 02155 TQValueList< TQGuardedPtr<KMFolder> >::const_iterator it = folders.constBegin(); 02156 TQValueList< TQGuardedPtr<KMFolder> >::const_iterator end = folders.constEnd(); 02157 while ( it != end ) { 02158 TQGuardedPtr<KMFolder> folder = *it; 02159 if ( folder == sender() ) { 02160 emit syncStateChanged(); 02161 break; 02162 } 02163 ++it; 02164 } 02165 } 02166 02167 void KMFolderTree::slotAddToFavorites() 02168 { 02169 KMail::FavoriteFolderView *favView = mMainWidget->favoriteFolderView(); 02170 assert( favView ); 02171 for ( TQListViewItemIterator it( this ); it.current(); ++it ) { 02172 if ( it.current()->isSelected() ) 02173 favView->addFolder( static_cast<KMFolderTreeItem*>( it.current() ) ); 02174 } 02175 } 02176 02177 void KMFolderTree::slotUnhideLocalInbox() 02178 { 02179 disconnect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)), 02180 this, TQT_SLOT(slotUnhideLocalInbox()) ); 02181 reload(); 02182 } 02183 02184 void KMFolderTree::delayedReload() 02185 { 02186 TQTimer::singleShot( 0, this, TQT_SLOT(reload()) ); 02187 } 02188 02189 #include "kmfoldertree.moc"