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 
00031 #include <libkdepim/maillistdrag.h>
00032 
00033 #include <kdebug.h>
00034 #include <kglobalsettings.h>
00035 #include <kiconloader.h>
00036 #include <kinputdialog.h>
00037 #include <klocale.h>
00038 #include <kpopupmenu.h>
00039 #include <kio/global.h>
00040 
00041 #include <qheader.h>
00042 #include <qtimer.h>
00043 #include <qtooltip.h>
00044 
00045 #include <cassert>
00046 
00047 namespace KMail {
00048 
00049 class FavoriteFolderViewToolTip : public QToolTip
00050 {
00051   public:
00052     FavoriteFolderViewToolTip( FavoriteFolderView* parent ) :
00053       QToolTip( parent->viewport() ),
00054       mListView( parent ) {}
00055 
00056   protected:
00057     void maybeTip( const QPoint &point )
00058     {
00059       FavoriteFolderViewItem *item = static_cast<FavoriteFolderViewItem*>( mListView->itemAt( point ) );
00060       if  ( !item )
00061         return;
00062       const QRect itemRect = mListView->itemRect( item );
00063       if ( !itemRect.isValid() )
00064         return;
00065       const QRect headerRect = mListView->header()->sectionRect( 0 );
00066       if ( !headerRect.isValid() )
00067         return;
00068       QString tipText = i18n("<qt><b>%1</b><br>Total: %2<br>Unread: %3<br>Size: %4" )
00069           .arg( item->folder()->prettyURL().replace( " ", "&nbsp;" ) )
00070           .arg( item->totalCount() < 0 ? "-" : QString::number( item->totalCount() ) )
00071           .arg( item->unreadCount() < 0 ? "-" : QString::number( item->unreadCount() ) )
00072           .arg( KIO::convertSize( item->folderSize() ) );
00073       tip( QRect( headerRect.left(), itemRect.top(), headerRect.width(), itemRect.height() ), tipText );
00074     }
00075 
00076   private:
00077     FavoriteFolderView *mListView;
00078 };
00079 
00080 }
00081 
00082 using namespace KMail;
00083 
00084 FavoriteFolderViewItem::FavoriteFolderViewItem(FavoriteFolderView * parent, const QString & name, KMFolder * folder)
00085   : KMFolderTreeItem( parent, name, folder ),
00086   mOldName( folder->label() )
00087 {
00088   // same stuff as in KMFolderTreeItem again, this time even with virtual methods working
00089   init();
00090   connect( folder, SIGNAL(nameChanged()), SLOT(nameChanged()) );
00091   connect( folder, SIGNAL(iconsChanged()), SLOT(slotIconsChanged()) );
00092 
00093   connect( folder, SIGNAL(msgAdded(KMFolder*,Q_UINT32)), SLOT(updateCount()) );
00094   connect( folder, SIGNAL(numUnreadMsgsChanged(KMFolder*)), SLOT(updateCount()) );
00095   connect( folder, SIGNAL(msgRemoved(KMFolder*)), SLOT(updateCount()) );
00096   connect( folder, SIGNAL(folderSizeChanged( KMFolder* )), SLOT(updateCount()) );
00097   connect( folder, SIGNAL(folderSizeChanged( KMFolder* )), SLOT(updateCount()) );
00098 
00099   updateCount();
00100   if ( unreadCount() > 0 )
00101     setPixmap( 0, unreadIcon( iconSize() ) );
00102   else
00103     setPixmap( 0, normalIcon( iconSize() ) );
00104 }
00105 
00106 void FavoriteFolderViewItem::updateCount()
00107 {
00108   // FIXME: share with KMFolderTree
00109   if ( !folder() ) {
00110     setTotalCount( -1 );
00111     return;
00112   }
00113 
00114   // get the unread count
00115   int count = 0;
00116   if (folder() && folder()->noContent()) // always empty
00117     count = -1;
00118   else {
00119     count = folder()->countUnread();
00120   }
00121    bool repaint = false;
00122   if ( unreadCount() != count ) {
00123      adjustUnreadCount( count );
00124      repaint = true;
00125   }
00126 
00127   // get the total-count
00128   if ( folder()->noContent() )
00129     count = -1;
00130   else {
00131     // get the cached count if the folder is not open
00132     count = folder()->count( !folder()->isOpened() );
00133   }
00134   if ( count != totalCount() ) {
00135     setTotalCount(count);
00136     repaint = true;
00137   }
00138 
00139   if ( !folder()->noContent() ) {
00140     int size = folder()->storage()->folderSize();
00141     if ( size != folderSize() ) {
00142       setFolderSize( size );
00143       repaint = true;
00144     }
00145   }
00146 
00147   if ( folderIsCloseToQuota() != folder()->storage()->isCloseToQuota() )
00148     setFolderIsCloseToQuota( folder()->storage()->isCloseToQuota() );
00149 
00150   if (repaint) {
00151     this->repaint();
00152   }
00153 }
00154 
00155 void FavoriteFolderViewItem::nameChanged()
00156 {
00157   QString txt = text( 0 );
00158   txt.replace( mOldName, folder()->label() );
00159   setText( 0, txt );
00160   mOldName = folder()->label();
00161 }
00162 
00163 
00164 QValueList<FavoriteFolderView*> FavoriteFolderView::mInstances;
00165 
00166 FavoriteFolderView::FavoriteFolderView( KMMainWidget *mainWidget, QWidget * parent) :
00167     FolderTreeBase( mainWidget, parent ),
00168     mContextMenuItem( 0 ),
00169     mReadingConfig( false )
00170 {
00171   assert( mainWidget );
00172   addColumn( i18n("Favorite Folders") );
00173   setResizeMode( LastColumn );
00174   header()->setClickEnabled( false );
00175   setDragEnabled( true );
00176   setAcceptDrops( true );
00177   setRootIsDecorated( false );
00178   setSelectionModeExt( KListView::Single );
00179   setSorting( -1 );
00180   setShowSortIndicator( false );
00181 
00182   connect( this, SIGNAL(selectionChanged()), SLOT(selectionChanged()) );
00183   connect( this, SIGNAL(clicked(QListViewItem*)), SLOT(itemClicked(QListViewItem*)) );
00184   connect( this, SIGNAL(dropped(QDropEvent*,QListViewItem*)), SLOT(dropped(QDropEvent*,QListViewItem*)) );
00185   connect( this, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint &, int)),
00186            SLOT(contextMenu(QListViewItem*,const QPoint&)) );
00187   connect( this, SIGNAL(moved()), SLOT(notifyInstancesOnChange()) );
00188 
00189   connect( kmkernel->folderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00190   connect( kmkernel->dimapFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00191   connect( kmkernel->imapFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00192   connect( kmkernel->searchFolderMgr(), SIGNAL(changed()), SLOT(initializeFavorites()) );
00193 
00194   connect( kmkernel->folderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00195   connect( kmkernel->dimapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00196   connect( kmkernel->imapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00197   connect( kmkernel->searchFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), SLOT(folderRemoved(KMFolder*)) );
00198 
00199   QFont f = font();
00200   f.setItalic( true );
00201   setFont( f );
00202 
00203   new FavoriteFolderViewToolTip( this );
00204 
00205   mInstances.append( this );
00206 }
00207 
00208 FavoriteFolderView::~FavoriteFolderView()
00209 {
00210   mInstances.remove( this );
00211 }
00212 
00213 void FavoriteFolderView::readConfig()
00214 {
00215   mReadingConfig = true;
00216   clear();
00217   QValueList<int> folderIds = GlobalSettings::self()->favoriteFolderIds();
00218   QStringList folderNames = GlobalSettings::self()->favoriteFolderNames();
00219   QListViewItem *afterItem = 0;
00220   for ( uint i = 0; i < folderIds.count(); ++i ) {
00221     KMFolder *folder = kmkernel->folderMgr()->findById( folderIds[i] );
00222     if ( !folder )
00223       folder = kmkernel->imapFolderMgr()->findById( folderIds[i] );
00224     if ( !folder )
00225       folder = kmkernel->dimapFolderMgr()->findById( folderIds[i] );
00226     if ( !folder )
00227       folder = kmkernel->searchFolderMgr()->findById( folderIds[i] );
00228     QString name;
00229     if ( folderNames.count() > i )
00230       name = folderNames[i];
00231     afterItem = addFolder( folder, name, afterItem );
00232   }
00233   if ( firstChild() )
00234     ensureItemVisible( firstChild() );
00235 
00236   // folder tree is not yet populated at this point
00237   QTimer::singleShot( 0, this, SLOT(initializeFavorites()) );
00238 
00239   readColorConfig();
00240   mReadingConfig = false;
00241 }
00242 
00243 void FavoriteFolderView::writeConfig()
00244 {
00245   QValueList<int> folderIds;
00246   QStringList folderNames;
00247   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00248     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00249     folderIds << fti->folder()->id();
00250     folderNames << fti->text( 0 );
00251   }
00252   GlobalSettings::self()->setFavoriteFolderIds( folderIds );
00253   GlobalSettings::self()->setFavoriteFolderNames( folderNames );
00254 }
00255 
00256 bool FavoriteFolderView::acceptDrag(QDropEvent * e) const
00257 {
00258   KMFolderTree *ft = mainWidget()->folderTree();
00259   assert( ft );
00260   if ( e->provides( "application/x-qlistviewitem" ) &&
00261        (e->source() == ft->viewport() || e->source() == viewport() ) )
00262     return true;
00263   return FolderTreeBase::acceptDrag( e );
00264 }
00265 
00266 KMFolderTreeItem* FavoriteFolderView::addFolder(KMFolder * folder, const QString &name, QListViewItem *after)
00267 {
00268   if ( !folder )
00269     return 0;
00270   KMFolderTreeItem *item = new FavoriteFolderViewItem( this, name.isEmpty() ? folder->label() : name, folder );
00271   if ( after )
00272     item->moveItem( after );
00273   else
00274     item->moveItem( lastItem() );
00275   ensureItemVisible( item );
00276   notifyInstancesOnChange();
00277   return item;
00278 }
00279 
00280 void FavoriteFolderView::selectionChanged()
00281 {
00282   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( selectedItem() );
00283   if ( !fti )
00284     return;
00285   KMFolderTree *ft = mainWidget()->folderTree();
00286   assert( ft );
00287   assert( fti );
00288   ft->showFolder( fti->folder() );
00289 }
00290 
00291 void FavoriteFolderView::itemClicked(QListViewItem * item)
00292 {
00293   if ( item && !item->isSelected() )
00294     item->setSelected( true );
00295   item->repaint();
00296 }
00297 
00298 void FavoriteFolderView::folderTreeSelectionChanged(KMFolder * folder)
00299 {
00300   blockSignals( true );
00301   bool found = false;
00302   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00303     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00304     if ( fti->folder() == folder && !fti->isSelected() ) {
00305       fti->setSelected( true );
00306       setCurrentItem( fti );
00307       ensureItemVisible( fti );
00308       fti->repaint();
00309       found = true;
00310     } else if ( fti->folder() != folder && fti->isSelected() ) {
00311       fti->setSelected( false );
00312       fti->repaint();
00313     }
00314   }
00315   blockSignals( false );
00316   if ( !found ) {
00317     clearSelection();
00318     setSelectionModeExt( KListView::NoSelection );
00319     setSelectionModeExt( KListView::Single );
00320   }
00321 }
00322 
00323 void FavoriteFolderView::folderRemoved(KMFolder * folder)
00324 {
00325   QValueList<KMFolderTreeItem*> delItems;
00326   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00327     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00328     if ( fti->folder() == folder )
00329       delItems << fti;
00330     if ( fti == mContextMenuItem )
00331       mContextMenuItem = 0;
00332   }
00333   for ( uint i = 0; i < delItems.count(); ++i )
00334     delete delItems[i];
00335 }
00336 
00337 void FavoriteFolderView::dropped(QDropEvent * e, QListViewItem * after)
00338 {
00339   QListViewItem* afterItem = after;
00340   KMFolderTree *ft = mainWidget()->folderTree();
00341   assert( ft );
00342   if ( e->source() == ft->viewport() && e->provides( "application/x-qlistviewitem" ) ) {
00343     for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00344       if ( !it.current()->isSelected() )
00345         continue;
00346       KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00347       if ( !fti->folder() )
00348         continue;
00349       afterItem = addFolder( fti->folder(), prettyName( fti ), afterItem );
00350     }
00351     e->accept();
00352   }
00353 }
00354 
00355 void FavoriteFolderView::contextMenu(QListViewItem * item, const QPoint & point)
00356 {
00357   KMFolderTree *ft = mainWidget()->folderTree();
00358   assert( ft );
00359   KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item );
00360   mContextMenuItem = fti;
00361   KPopupMenu contextMenu;
00362   if ( fti && fti->folder() ) {
00363     contextMenu.insertItem( SmallIconSet("editdelete"), i18n("Remove From Favorites"),
00364                             this, SLOT(removeFolder()) );
00365     contextMenu.insertItem( SmallIconSet("edit"), i18n("Rename Favorite"), this, SLOT(renameFolder()) );
00366     contextMenu.insertSeparator();
00367 
00368     mainWidget()->action("mark_all_as_read")->plug( &contextMenu );
00369     if ( fti->folder()->folderType() == KMFolderTypeImap || fti->folder()->folderType() == KMFolderTypeCachedImap )
00370       mainWidget()->action("refresh_folder")->plug( &contextMenu );
00371     if ( fti->folder()->isMailingListEnabled() )
00372       mainWidget()->action("post_message")->plug( &contextMenu );
00373 
00374     contextMenu.insertItem( SmallIconSet("configure_shortcuts"), i18n("&Assign Shortcut..."), fti, SLOT(assignShortcut()) );
00375     contextMenu.insertItem( i18n("Expire..."), fti, SLOT(slotShowExpiryProperties()) );
00376     mainWidget()->action("modify")->plug( &contextMenu );
00377   } else {
00378     contextMenu.insertItem( SmallIconSet("bookmark_add"), i18n("Add Favorite Folder..."),
00379                             this, SLOT(addFolder()) );
00380   }
00381   contextMenu.exec( point, 0 );
00382 }
00383 
00384 void FavoriteFolderView::removeFolder()
00385 {
00386   delete mContextMenuItem;
00387   mContextMenuItem = 0;
00388   notifyInstancesOnChange();
00389 }
00390 
00391 void FavoriteFolderView::initializeFavorites()
00392 {
00393   QValueList<int> seenInboxes = GlobalSettings::self()->favoriteFolderViewSeenInboxes();
00394   KMFolderTree *ft = mainWidget()->folderTree();
00395   assert( ft );
00396   for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00397     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00398     if ( fti->type() == KFolderTreeItem::Inbox && fti->folder() && !seenInboxes.contains( fti->folder()->id() ) ) {
00399       seenInboxes.append( fti->folder()->id() );
00400       if ( fti->folder() == kmkernel->inboxFolder() && hideLocalInbox() )
00401         continue;
00402       if ( kmkernel->iCalIface().hideResourceFolder( fti->folder() ) )
00403         continue;
00404       addFolder( fti->folder(), prettyName( fti ) );
00405     }
00406   }
00407   GlobalSettings::self()->setFavoriteFolderViewSeenInboxes( seenInboxes );
00408 }
00409 
00410 void FavoriteFolderView::renameFolder()
00411 {
00412   if ( !mContextMenuItem )
00413     return;
00414   bool ok;
00415   QString name = KInputDialog::getText( i18n("Rename Favorite"), i18n("Name"), mContextMenuItem->text( 0 ), &ok, this );
00416   if ( !ok )
00417     return;
00418   mContextMenuItem->setText( 0, name );
00419   notifyInstancesOnChange();
00420 }
00421 
00422 QString FavoriteFolderView::prettyName(KMFolderTreeItem * fti)
00423 {
00424   assert( fti );
00425   assert( fti->folder() );
00426   QString name = fti->folder()->label();
00427   QListViewItem *accountFti = fti;
00428   while ( accountFti->parent() )
00429     accountFti = accountFti->parent();
00430   if ( fti->type() == KFolderTreeItem::Inbox ) {
00431     if ( fti->protocol() == KFolderTreeItem::Local || fti->protocol() == KFolderTreeItem::NONE ) {
00432       name = i18n( "Local Inbox" );
00433     } else {
00434       name = i18n( "Inbox of %1" ).arg( accountFti->text( 0 ) );
00435     }
00436   } else {
00437     if ( fti->protocol() != KFolderTreeItem::Local && fti->protocol() != KFolderTreeItem::NONE ) {
00438       name = i18n( "%1 on %2" ).arg( fti->text( 0 ) ).arg( accountFti->text( 0 ) );
00439     } else {
00440       name = i18n( "%1 (local)" ).arg( fti->text( 0 ) );
00441     }
00442   }
00443   return name;
00444 }
00445 
00446 void FavoriteFolderView::contentsDragEnterEvent(QDragEnterEvent * e)
00447 {
00448   if ( e->provides( "application/x-qlistviewitem" ) ) {
00449     setDropVisualizer( true );
00450     setDropHighlighter( false );
00451   } else if ( e->provides( KPIM::MailListDrag::format() ) ) {
00452     setDropVisualizer( false );
00453     setDropHighlighter( true );
00454   } else {
00455     setDropVisualizer( false );
00456     setDropHighlighter( false );
00457   }
00458   FolderTreeBase::contentsDragEnterEvent( e );
00459 }
00460 
00461 void FavoriteFolderView::readColorConfig()
00462 {
00463   FolderTreeBase::readColorConfig();
00464   KConfig* conf = KMKernel::config();
00465   // Custom/System color support
00466   KConfigGroupSaver saver(conf, "Reader");
00467   QColor c = KGlobalSettings::alternateBackgroundColor();
00468   if ( !conf->readBoolEntry("defaultColors", true) )
00469     mPaintInfo.colBack = conf->readColorEntry( "AltBackgroundColor",&c );
00470   else
00471     mPaintInfo.colBack = c;
00472 
00473   QPalette newPal = palette();
00474   newPal.setColor( QColorGroup::Base, mPaintInfo.colBack );
00475   setPalette( newPal );
00476 }
00477 
00478 void FavoriteFolderView::addFolder()
00479 {
00480   KMFolderSelDlg dlg( mainWidget(), i18n("Add Favorite Folder"), false );
00481   if ( dlg.exec() != QDialog::Accepted )
00482     return;
00483   KMFolder *folder = dlg.folder();
00484   if ( !folder )
00485     return;
00486   KMFolderTreeItem *fti = findFolderTreeItem( folder );
00487   addFolder( folder, fti ? prettyName( fti ) : folder->label() );
00488 }
00489 
00490 KMFolderTreeItem * FavoriteFolderView::findFolderTreeItem(KMFolder * folder) const
00491 {
00492   assert( folder );
00493   KMFolderTree *ft = mainWidget()->folderTree();
00494   assert( ft );
00495   for ( QListViewItemIterator it( ft ); it.current(); ++it ) {
00496     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00497     if ( fti->folder() == folder )
00498       return fti;
00499   }
00500   return 0;
00501 }
00502 
00503 void FavoriteFolderView::checkMail()
00504 {
00505   bool found = false;
00506   for ( QListViewItemIterator it( this ); it.current(); ++it ) {
00507     KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
00508     if ( fti->folder()->folderType() == KMFolderTypeImap || fti->folder()->folderType() == KMFolderTypeCachedImap ) {
00509       if ( !found )
00510         if ( !kmkernel->askToGoOnline() )
00511           break;
00512       found = true;
00513       if ( fti->folder()->folderType() == KMFolderTypeImap ) {
00514         KMFolderImap *imap = static_cast<KMFolderImap*>( fti->folder()->storage() );
00515         imap->getAndCheckFolder();
00516       } else if ( fti->folder()->folderType() == KMFolderTypeCachedImap ) {
00517         KMFolderCachedImap* f = static_cast<KMFolderCachedImap*>( fti->folder()->storage() );
00518         f->account()->processNewMailSingleFolder( fti->folder() );
00519       }
00520     }
00521   }
00522 }
00523 
00524 void FavoriteFolderView::notifyInstancesOnChange()
00525 {
00526   if ( mReadingConfig )
00527     return;
00528   writeConfig();
00529   for ( QValueList<FavoriteFolderView*>::ConstIterator it = mInstances.begin(); it != mInstances.end(); ++it ) {
00530     if ( (*it) == this || (*it)->mReadingConfig )
00531       continue;
00532     (*it)->readConfig();
00533   }
00534 }
00535 
00536 #include "favoritefolderview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys