kmail

favoritefolderview.cpp

00001 /*
00002     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "favoritefolderview.h"
00020 
00021 #include "kmfolder.h"
00022 #include "kmfoldermgr.h"
00023 #include "kmfolderseldlg.h"
00024 #include "kmmainwidget.h"
00025 #include "kmailicalifaceimpl.h"
00026 #include "folderstorage.h"
00027 #include "kmfolderimap.h"
00028 #include "kmfoldercachedimap.h"
00029 #include "kmacctcachedimap.h"
00030 #include "folderviewtooltip.h"
00031 #include "korghelper.h"
00032 
00033 #include <libkdepim/maillistdrag.h>
00034 #include <libkdepim/kaddrbook.h>
00035 
00036 #include <dcopclient.h>
00037 #include <kdebug.h>
00038 #include <kglobalsettings.h>
00039 #include <kiconloader.h>
00040 #include <kinputdialog.h>
00041 #include <klocale.h>
00042 #include <kpopupmenu.h>
00043 #include <kio/global.h>
00044 
00045 #include <qheader.h>
00046 #include <qtimer.h>
00047 
00048 #include <cassert>
00049 
00050 using namespace KMail;
00051 
00052 FavoriteFolderViewItem::FavoriteFolderViewItem(FavoriteFolderView * parent, const QString & name, KMFolder * folder)
00053   : KMFolderTreeItem( parent, name, folder ),
00054   mOldName( folder->label() )
00055 {
00056   // same stuff as in KMFolderTreeItem again, this time even with virtual methods working
00057   init();
00058   connect( folder, SIGNAL(nameChanged()), SLOT(nameChanged()) );
00059   connect( folder, SIGNAL(iconsChanged()), SLOT(slotIconsChanged()) );
00060 
00061   connect( folder, SIGNAL(msgAdded(KMFolder*,Q_UINT32)), SLOT(updateCount()) );
00062   connect( folder, SIGNAL(numUnreadMsgsChanged(KMFolder*)), SLOT(updateCount()) );
00063   connect( folder, SIGNAL(msgRemoved(KMFolder*)), SLOT(updateCount()) );
00064   connect( folder, SIGNAL(folderSizeChanged( KMFolder* )), SLOT(updateCount()) );
00065 
00066   QTimer::singleShot( 0, this, SLOT(updateCount()) );
00067 
00068   if ( unreadCount() > 0 )
00069     setPixmap( 0, unreadIcon( iconSize() ) );
00070   else
00071     setPixmap( 0, normalIcon( iconSize() ) );
00072 }
00073 
00074 void FavoriteFolderViewItem::nameChanged()
00075 {
00076   QString txt = text( 0 );
00077   txt.replace( mOldName, folder()->label() );
00078   setText( 0, txt );
00079   mOldName = folder()->label();
00080 }
00081 
00082 QValueList<FavoriteFolderView*> FavoriteFolderView::mInstances;
00083 
00084 FavoriteFolderView::FavoriteFolderView( KMMainWidget *mainWidget, QWidget * parent) :
00085     FolderTreeBase( mainWidget, parent ),
00086     mContextMenuItem( 0 ),
00087     mReadingConfig( false )
00088 {
00089   assert( mainWidget );
00090   addColumn( i18n("Favorite Folders") );
00091   setResizeMode( LastColumn );
00092   header()->setClickEnabled( false );
00093   setDragEnabled( true );
00094   setAcceptDrops( true );
00095   setRootIsDecorated( false );
00096   setSelectionModeExt( KListView::Single );
00097   setSorting( -1 );
00098   setShowSortIndicator( false );
00099 
00100   connect( this, SIGNAL(selectionChanged()), SLOT(selectionChanged()) );
00101   connect( this, SIGNAL(clicked(QListViewItem*)), SLOT(itemClicked(QListViewItem*)) );
00102   connect( this, SIGNAL(dropped(QDropEvent*,QListViewItem*)), SLOT(dropped(QDropEvent*,QListViewItem*)) );
00103   connect( this, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint &, int)),
00104            SLOT(contextMenu(QListViewItem*,const QPoint&)) );
00105   connect( this, SIGNAL(moved()), SLOT(notifyInstancesOnChange()) );
00106   connect( this, SIGNAL(triggerRefresh()), SLOT(refresh()) );
00107 
00108   connect( kmkernel->folderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00109   connect( kmkernel->dimapFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00110   connect( kmkernel->imapFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00111   connect( kmkernel->searchFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00112 
00113   connect( kmkernel->folderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00114   connect( kmkernel->dimapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00115   connect( kmkernel->imapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00116   connect( kmkernel->searchFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00117 
00118   QFont f = font();
00119   f.setItalic( true );
00120   setFont( f );
00121 
00122   new FolderViewToolTip( this );
00123 
00124   mInstances.append( this );
00125 }
00126 
00127 FavoriteFolderView::~FavoriteFolderView()
00128 {
00129   mInstances.remove( this );
00130 }
00131 
00132 void FavoriteFolderView::readConfig()
00133 {
00134   mReadingConfig = true;
00135   clear();
00136   QValueList<int> folderIds = GlobalSettings::self()->favoriteFolderIds();
00137   QStringList folderNames = GlobalSettings::self()->favoriteFolderNames();
00138   QListViewItem *afterItem = 0;
00139   for ( uint i = 0; i < folderIds.count(); ++i ) {
00140     KMFolder *folder = kmkernel->folderMgr()->findById( folderIds[i] );
00141     if ( !folder )
00142       folder = kmkernel->imapFolderMgr()->findById( folderIds[i] );
00143     if ( !folder )
00144       folder = kmkernel->dimapFolderMgr()->findById( folderIds[i] );
00145     if ( !folder )
00146       folder = kmkernel->searchFolderMgr()->findById( folderIds[i] );
00147     QString name;
00148     if ( folderNames.count() > i )
00149       name = folderNames[i];
00150     afterItem = addFolder( folder, name, afterItem );
00151   }
00152   if ( firstChild() )
00153     ensureItemVisible( firstChild() );
00154 
00155   // folder tree is not yet populated at this point
00156   QTimer::singleShot( 0, this, SLOT(initializeFavorites()) );
00157 
00158   readColorConfig();
00159   mReadingConfig = false;
00160 }
00161 
00162 void FavoriteFolderView::writeConfig()
00163 {
00164   QValueList<int> folderIds;
00165   QStringList folderNames;
00166   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00167     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00168     folderIds << fti->folder()->id();
00169     folderNames << fti->text( 0 );
00170   }
00171   GlobalSettings::self()->setFavoriteFolderIds( folderIds );
00172   GlobalSettings::self()->setFavoriteFolderNames( folderNames );
00173 }
00174 
00175 bool FavoriteFolderView::acceptDrag(QDropEvent * e) const
00176 {
00177   KMFolderTree *ft = mainWidget()->folderTree();
00178   assert( ft );
00179   if ( e->provides( "application/x-qlistviewitem" ) &&
00180        (e->source() == ft->viewport() || e->source() == viewport() ) )
00181     return true;
00182   return FolderTreeBase::acceptDrag( e );
00183 }
00184 
00185 KMFolderTreeItem* FavoriteFolderView::addFolder(KMFolder * folder, const QString &name, QListViewItem *after)
00186 {
00187   if ( !folder )
00188     return 0;
00189   KMFolderTreeItem *item = new FavoriteFolderViewItem( this, name.isEmpty() ? folder->label() : name, folder );
00190   if ( after )
00191     item->moveItem( after );
00192   else
00193     item->moveItem( lastItem() );
00194   ensureItemVisible( item );
00195   insertIntoFolderToItemMap( folder, item );
00196   notifyInstancesOnChange();
00197   return item;
00198 }
00199 
00200 void FavoriteFolderView::selectionChanged()
00201 {
00202   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( selectedItem() );
00203   if ( !fti )
00204     return;
00205   KMFolderTree *ft = mainWidget()->folderTree();
00206   assert( ft );
00207   assert( fti );
00208   ft->showFolder( fti->folder() );
00209   handleGroupwareFolder( fti );
00210 }
00211 
00212 void FavoriteFolderView::handleGroupwareFolder( KMFolderTreeItem *fti )
00213 {
00214   if ( !fti || !fti->folder() || !fti->folder()->storage() )
00215     return;
00216   switch ( fti->folder()->storage()->contentsType() ) {
00217     case KMail::ContentsTypeContact:
00218       KAddrBookExternal::openAddressBook( this );
00219       break;
00220     case KMail::ContentsTypeNote:
00221     {
00222       QByteArray arg;
00223       QDataStream s( arg, IO_WriteOnly );
00224       s << QString( "kontact_knotesplugin" );
00225       kapp->dcopClient()->send( "kontact", "KontactIface", "selectPlugin(QString)", arg );
00226       break;
00227     }
00228     case KMail::ContentsTypeCalendar:
00229     case KMail::ContentsTypeTask:
00230     case KMail::ContentsTypeJournal:
00231     {
00232       KMail::KorgHelper::ensureRunning();
00233       QByteArray arg;
00234       QDataStream s( arg, IO_WriteOnly );
00235       switch ( fti->folder()->storage()->contentsType() ) {
00236         case KMail::ContentsTypeCalendar:
00237           s << QString( "kontact_korganizerplugin" ); break;
00238         case KMail::ContentsTypeTask:
00239           s << QString( "kontact_todoplugin" ); break;
00240         case KMail::ContentsTypeJournal:
00241           s << QString( "kontact_journalplugin" ); break;
00242         default: assert( false );
00243       }
00244       kapp->dcopClient()->send( "kontact", "KontactIface", "selectPlugin(QString)", arg );
00245       break;
00246     }
00247     default: break;
00248   }
00249 }
00250 
00251 void FavoriteFolderView::itemClicked(QListViewItem * item)
00252 {
00253   if ( !item ) return;
00254   if ( !item->isSelected() )
00255     item->setSelected( true );
00256   item->repaint();
00257   handleGroupwareFolder( static_cast<KMFolderTreeItem*>( item ) );
00258 }
00259 
00260 void FavoriteFolderView::folderTreeSelectionChanged(KMFolder * folder)
00261 {
00262   blockSignals( true );
00263   bool found = false;
00264   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00265     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00266     if ( fti->folder() == folder && !fti->isSelected() ) {
00267       fti->setSelected( true );
00268       setCurrentItem( fti );
00269       ensureItemVisible( fti );
00270       fti->repaint();
00271       found = true;
00272     } else if ( fti->folder() != folder && fti->isSelected() ) {
00273       fti->setSelected( false );
00274       fti->repaint();
00275     }
00276   }
00277   blockSignals( false );
00278   if ( !found ) {
00279     clearSelection();
00280     setSelectionModeExt( KListView::NoSelection );
00281     setSelectionModeExt( KListView::Single );
00282   }
00283 }
00284 
00285 void FavoriteFolderView::folderRemoved(KMFolder * folder)
00286 {
00287   QValueList<KMFolderTreeItem*> delItems;
00288   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00289     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00290     if ( fti->folder() == folder )
00291       delItems << fti;
00292     if ( fti == mContextMenuItem )
00293       mContextMenuItem = 0;
00294   }
00295   for ( uint i = 0; i < delItems.count(); ++i )
00296     delete delItems[i];
00297   removeFromFolderToItemMap(folder);
00298 }
00299 
00300 void FavoriteFolderView::dropped(QDropEvent * e, QListViewItem * after)
00301 {
00302   QListViewItem* afterItem = after;
00303   KMFolderTree *ft = mainWidget()->folderTree();
00304   assert( ft );
00305   if ( e->source() == ft->viewport() && e->provides( "application/x-qlistviewitem" ) ) {
00306     for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00307       if ( !it.current()->isSelected() )
00308         continue;
00309       KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00310       if ( !fti->folder() )
00311         continue;
00312       if( !mFolderToItem.contains( fti->folder() ) )
00313          afterItem = addFolder( fti->folder(), prettyName( fti ), afterItem );
00314     }
00315     e->accept();
00316   }
00317 }
00318 
00319 void FavoriteFolderView::contextMenu(QListViewItem * item, const QPoint & point)
00320 {
00321   KMFolderTree *ft = mainWidget()->folderTree();
00322   assert( ft );
00323   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item );
00324   mContextMenuItem = fti;
00325   KPopupMenu contextMenu;
00326   if ( fti && fti->folder() ) {
00327     mainWidget()->action("mark_all_as_read")->plug( &contextMenu );
00328     if ( fti->folder()->folderType() == KMFolderTypeImap || fti->folder()->folderType() == KMFolderTypeCachedImap )
00329       mainWidget()->action("refresh_folder")->plug( &contextMenu );
00330     if ( fti->folder()->isMailingListEnabled() )
00331       mainWidget()->action("post_message")->plug( &contextMenu );
00332     mainWidget()->action("search_messages")->plug( &contextMenu );
00333     if ( fti->folder()->canDeleteMessages() && ( fti->folder()->count() > 0 ) )
00334        mainWidget()->action("empty")->plug( &contextMenu );
00335     contextMenu.insertSeparator();
00336 
00337     contextMenu.insertItem( SmallIconSet("configure_shortcuts"), i18n("&Assign Shortcut..."), fti, SLOT(assignShortcut()) );
00338     contextMenu.insertItem( i18n("Expire..."), fti, SLOT(slotShowExpiryProperties()) );
00339     mainWidget()->action("modify")->plug( &contextMenu );
00340     contextMenu.insertSeparator();
00341 
00342     contextMenu.insertItem( SmallIconSet("editdelete"), i18n("Remove From Favorites"),
00343                             this, SLOT(removeFolder()) );
00344     contextMenu.insertItem( SmallIconSet("edit"), i18n("Rename Favorite"), this, SLOT(renameFolder()) );
00345 
00346   } else {
00347     contextMenu.insertItem( SmallIconSet("bookmark_add"), i18n("Add Favorite Folder..."),
00348                             this, SLOT(addFolder()) );
00349   }
00350   contextMenu.exec( point, 0 );
00351 }
00352 
00353 void FavoriteFolderView::removeFolder()
00354 {
00355   KMFolderTreeItem *fti = mContextMenuItem;
00356   KMFolder *folder = 0;
00357   if( fti )
00358     folder = fti->folder();
00359   delete mContextMenuItem;
00360   mContextMenuItem = 0;
00361   removeFromFolderToItemMap(folder);
00362   notifyInstancesOnChange();
00363 }
00364 
00365 void FavoriteFolderView::initializeFavorites()
00366 {
00367   QValueList<int> seenInboxes = GlobalSettings::self()->favoriteFolderViewSeenInboxes();
00368   KMFolderTree *ft = mainWidget()->folderTree();
00369   assert( ft );
00370   for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00371     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00372     if ( fti->type() == KFolderTreeItem::Inbox && fti->folder() && !seenInboxes.contains( fti->folder()->id() ) ) {
00373       seenInboxes.append( fti->folder()->id() );
00374       if ( fti->folder() == kmkernel->inboxFolder() && hideLocalInbox() )
00375         continue;
00376       if ( kmkernel->iCalIface().hideResourceFolder( fti->folder() ) )
00377         continue;
00378       addFolder( fti->folder(), prettyName( fti ) );
00379     }
00380   }
00381   GlobalSettings::self()->setFavoriteFolderViewSeenInboxes( seenInboxes );
00382 }
00383 
00384 void FavoriteFolderView::renameFolder()
00385 {
00386   if ( !mContextMenuItem )
00387     return;
00388   bool ok;
00389   QString name = KInputDialog::getText( i18n("Rename Favorite"), i18n("Name"), mContextMenuItem->text( 0 ), &ok, this );
00390   if ( !ok )
00391     return;
00392   mContextMenuItem->setText( 0, name );
00393   notifyInstancesOnChange();
00394 }
00395 
00396 QString FavoriteFolderView::prettyName(KMFolderTreeItem * fti)
00397 {
00398   assert( fti );
00399   assert( fti->folder() );
00400   QString name = fti->folder()->label();
00401   QListViewItem *accountFti = fti;
00402   while ( accountFti->parent() )
00403     accountFti = accountFti->parent();
00404   if ( fti->type() == KFolderTreeItem::Inbox ) {
00405     if ( fti->protocol() == KFolderTreeItem::Local || fti->protocol() == KFolderTreeItem::NONE ) {
00406       name = i18n( "Local Inbox" );
00407     } else {
00408       name = i18n( "Inbox of %1" ).arg( accountFti->text( 0 ) );
00409     }
00410   } else {
00411     if ( fti->protocol() != KFolderTreeItem::Local && fti->protocol() != KFolderTreeItem::NONE ) {
00412       name = i18n( "%1 on %2" ).arg( fti->text( 0 ) ).arg( accountFti->text( 0 ) );
00413     } else {
00414       name = i18n( "%1 (local)" ).arg( fti->text( 0 ) );
00415     }
00416   }
00417   return name;
00418 }
00419 
00420 void FavoriteFolderView::contentsDragEnterEvent(QDragEnterEvent * e)
00421 {
00422   if ( e->provides( "application/x-qlistviewitem" ) ) {
00423     setDropVisualizer( true );
00424     setDropHighlighter( false );
00425   } else if ( e->provides( KPIM::MailListDrag::format() ) ) {
00426     setDropVisualizer( false );
00427     setDropHighlighter( true );
00428   } else {
00429     setDropVisualizer( false );
00430     setDropHighlighter( false );
00431   }
00432   FolderTreeBase::contentsDragEnterEvent( e );
00433 }
00434 
00435 void FavoriteFolderView::readColorConfig()
00436 {
00437   FolderTreeBase::readColorConfig();
00438   KConfig* conf = KMKernel::config();
00439   // Custom/System color support
00440   KConfigGroupSaver saver(conf, "Reader");
00441   QColor c = KGlobalSettings::alternateBackgroundColor();
00442   if ( !conf->readBoolEntry("defaultColors", true) )
00443     mPaintInfo.colBack = conf->readColorEntry( "AltBackgroundColor",&c );
00444   else
00445     mPaintInfo.colBack = c;
00446 
00447   QPalette newPal = palette();
00448   newPal.setColor( QColorGroup::Base, mPaintInfo.colBack );
00449   setPalette( newPal );
00450 }
00451 
00452 void FavoriteFolderView::addFolder()
00453 {
00454   KMFolderSelDlg dlg( mainWidget(), i18n("Add Favorite Folder"), false );
00455   if ( dlg.exec() != QDialog::Accepted )
00456     return;
00457   KMFolder *folder = dlg.folder();
00458   if ( !folder )
00459     return;
00460   if ( mFolderToItem.contains( folder ) )
00461     return;
00462 
00463   KMFolderTreeItem *fti = findFolderTreeItem( folder );
00464   addFolder( folder, fti ? prettyName( fti ) : folder->label() );
00465 }
00466 
00467 void KMail::FavoriteFolderView::addFolder(KMFolderTreeItem * fti)
00468 {
00469   if ( !fti || !fti->folder() )
00470     return;
00471   if ( !mFolderToItem.contains( fti->folder()  ) )
00472     addFolder( fti->folder(), prettyName( fti ) );
00473 }
00474 
00475 KMFolderTreeItem * FavoriteFolderView::findFolderTreeItem(KMFolder * folder) const
00476 {
00477   assert( folder );
00478   KMFolderTree *ft = mainWidget()->folderTree();
00479   assert( ft );
00480   for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00481     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00482     if ( fti->folder() == folder )
00483       return fti;
00484   }
00485   return 0;
00486 }
00487 
00488 void FavoriteFolderView::checkMail()
00489 {
00490   bool found = false;
00491   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00492     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00493     if ( fti->folder()->folderType() == KMFolderTypeImap || fti->folder()->folderType() == KMFolderTypeCachedImap ) {
00494       if ( !found )
00495         if ( !kmkernel->askToGoOnline() )
00496           break;
00497       found = true;
00498       if ( fti->folder()->folderType() == KMFolderTypeImap ) {
00499         KMFolderImap *imap = static_cast<KMFolderImap*>( fti->folder()->storage() );
00500         imap->getAndCheckFolder();
00501       } else if ( fti->folder()->folderType() == KMFolderTypeCachedImap ) {
00502         KMFolderCachedImap* f = static_cast<KMFolderCachedImap*>( fti->folder()->storage() );
00503         f->account()->processNewMailSingleFolder( fti->folder() );
00504       }
00505     }
00506   }
00507 }
00508 
00509 void FavoriteFolderView::notifyInstancesOnChange()
00510 {
00511   if ( mReadingConfig )
00512     return;
00513   writeConfig();
00514   for ( QValueList<FavoriteFolderView*>::ConstIterator it = mInstances.begin(); it != mInstances.end(); ++it ) {
00515     if ( (*it) == this || (*it)->mReadingConfig )
00516       continue;
00517     (*it)->readConfig();
00518   }
00519 }
00520 
00521 void FavoriteFolderView::refresh()
00522 {
00523   for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) {
00524     KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
00525     if (!fti || !fti->folder())
00526       continue;
00527     fti->repaint();
00528   }
00529   update();
00530 }
00531 
00532 #include "favoritefolderview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys