• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

libkdepim

kfoldertree.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-file-style: "gnu" -*-
00002 
00003   This file is part of libkdepim.
00004 
00005   Copyright (C) 2002 Carsten Burghardt <burghardt@kde.org>
00006   Copyright (C) 2002 Marc Mutz <mutz@kde.org>
00007 
00008   This library is free software; you can redistribute it and/or
00009   modify it under the terms of the GNU Library General Public
00010   License version 2 as published by the Free Software Foundation.
00011 
00012   This library is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   Library General Public License for more details.
00016 
00017   You should have received a copy of the GNU Library General Public License
00018   along with this library; see the file COPYING.LIB.  If not, write to
00019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020   Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kfoldertree.h"
00024 
00025 #include <KDebug>
00026 #include <KLocale>
00027 #include <KIconLoader>
00028 #include <kio/global.h>
00029 
00030 #include <QApplication>
00031 #include <QDropEvent>
00032 #include <QFontMetrics>
00033 #include <QMouseEvent>
00034 #include <QPainter>
00035 #include <QPixmap>
00036 #include <QStyle>
00037 #include <Q3Header>
00038 
00039 using namespace KPIM;
00040 
00041 //-----------------------------------------------------------------------------
00042 KFolderTreeItem::KFolderTreeItem( KFolderTree *parent, const QString & label,
00043                                   Protocol protocol, Type type )
00044   : K3ListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
00045     mUnread( -1 ), mTotal( 0 ), mSize( 0 ), mFolderIsCloseToQuota( false )
00046 {
00047 }
00048 
00049 //-----------------------------------------------------------------------------
00050 KFolderTreeItem::KFolderTreeItem( KFolderTreeItem *parent, const QString &label,
00051                                   Protocol protocol, Type type, int unread,
00052                                   int total )
00053     : K3ListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
00054       mUnread( unread ), mTotal( total ), mSize( 0 ),
00055       mFolderIsCloseToQuota( false )
00056 {
00057 }
00058 
00059 //-----------------------------------------------------------------------------
00060 int KFolderTreeItem::protocolSortingKey() const
00061 {
00062   // protocol dependant sorting order:
00063   // local < imap < news < search < other
00064   switch ( mProtocol ) {
00065   case Local:
00066     return 1;
00067   case CachedImap:
00068   case Imap:
00069     return 2;
00070   case News:
00071     return 3;
00072   case Search:
00073     return 4;
00074   default:
00075     return 42;
00076   }
00077 }
00078 
00079 //-----------------------------------------------------------------------------
00080 int KFolderTreeItem::typeSortingKey() const
00081 {
00082   // type dependant sorting order:
00083   // inbox < outbox < sent-mail < trash < drafts
00084   // < calendar < contacts < notes < tasks
00085   // < normal folders
00086   switch ( mType ) {
00087   case Inbox:
00088     return 1;
00089   case Outbox:
00090     return 2;
00091   case SentMail:
00092     return 3;
00093   case Trash:
00094     return 4;
00095   case Drafts:
00096     return 5;
00097   case Templates:
00098     return 6;
00099   case Calendar:
00100     return 7;
00101   case Contacts:
00102     return 8;
00103   case Notes:
00104     return 9;
00105   case Tasks:
00106     return 10;
00107   default:
00108     return 42;
00109   }
00110 }
00111 
00112 //-----------------------------------------------------------------------------
00113 int KFolderTreeItem::compare( Q3ListViewItem *i, int col, bool ) const
00114 {
00115   KFolderTreeItem* other = static_cast<KFolderTreeItem*>( i );
00116 
00117   if ( col == 0 ) {
00118     // sort by folder
00119 
00120     // local root-folder
00121     if ( depth() == 0 && mProtocol == NONE ) {
00122       return -1;
00123     }
00124     if ( other->depth() == 0 && other->protocol() == NONE ) {
00125       return 1;
00126     }
00127 
00128     // first compare by protocol
00129     int thisKey = protocolSortingKey();
00130     int thatKey = other->protocolSortingKey();
00131     if ( thisKey < thatKey ) {
00132       return -1;
00133     }
00134     if ( thisKey > thatKey ) {
00135       return 1;
00136     }
00137 
00138     // then compare by type
00139     thisKey = typeSortingKey();
00140     thatKey = other->typeSortingKey();
00141     if ( thisKey < thatKey ) {
00142       return -1;
00143     }
00144     if ( thisKey > thatKey ) {
00145       return 1;
00146     }
00147 
00148     // and finally compare by name
00149     return text( 0 ).localeAwareCompare( other->text( 0 ) );
00150   } else {
00151     // sort by unread or total-column
00152     qint64 a = 0, b = 0;
00153     if ( col == static_cast<KFolderTree*>( listView() )->unreadIndex() ) {
00154       a = mUnread;
00155       b = other->unreadCount();
00156     } else if ( col == static_cast<KFolderTree*>( listView() )->totalIndex() ) {
00157       a = mTotal;
00158       b = other->totalCount();
00159     } else if ( col == static_cast<KFolderTree*>( listView() )->sizeIndex() ) {
00160       a = mSize;
00161       b = other->folderSize();
00162     }
00163 
00164     if ( a == b ) {
00165       return 0;
00166     } else {
00167       return ( a < b ? -1 : 1 );
00168     }
00169   }
00170 }
00171 
00172 //-----------------------------------------------------------------------------
00173 void KFolderTreeItem::setUnreadCount( int aUnread )
00174 {
00175   if ( aUnread < 0 ) {
00176     return;
00177   }
00178 
00179   mUnread = aUnread;
00180 
00181   QString unread;
00182   if ( mUnread == 0 ) {
00183     unread = "- ";
00184   } else {
00185     unread.setNum( mUnread );
00186     unread += ' ';
00187   }
00188 
00189   setText( static_cast<KFolderTree*>( listView() )->unreadIndex(), unread );
00190 }
00191 
00192 //-----------------------------------------------------------------------------
00193 void KFolderTreeItem::setTotalCount( int aTotal )
00194 {
00195   if ( aTotal < 0 ) {
00196     return;
00197   }
00198 
00199   mTotal = aTotal;
00200 
00201   QString total;
00202   if ( mTotal == 0 ) {
00203     total = "- ";
00204   } else {
00205     total.setNum( mTotal );
00206     total += ' ';
00207   }
00208 
00209   setText( static_cast<KFolderTree*>( listView() )->totalIndex(), total );
00210 }
00211 
00212 //-----------------------------------------------------------------------------
00213 void KFolderTreeItem::setFolderSize( qint64 aSize )
00214 {
00215   if ( aSize < 0 ) {
00216     return;  // we need to update even if nothing changed, kids ...
00217   }
00218 
00219   mSize = aSize;
00220 
00221   QString size;
00222   qint64 recursiveSize = 0;
00223 
00224   if ( childCount() > 0 && !isOpen() ) {
00225     recursiveSize = recursiveFolderSize();
00226   }
00227 
00228   if ( mType != Root ) {
00229     if ( mSize == 0 && ( childCount() == 0 || isOpen() || recursiveSize == 0 ) ) {
00230       size = "- ";
00231     } else {
00232       size = KIO::convertSize( mSize );
00233     }
00234   }
00235 
00236   if ( childCount() > 0 && !isOpen() && recursiveSize != mSize ) {
00237     if ( mType != Root ) {
00238       size += QString::fromLatin1( " + %1" ).arg( KIO::convertSize( recursiveSize - mSize ) );
00239     } else {
00240       size = KIO::convertSize( recursiveSize );
00241     }
00242   }
00243 
00244   size += ' ';
00245 
00246   setText( static_cast<KFolderTree*>( listView() )->sizeIndex(), size );
00247 }
00248 
00249 //-----------------------------------------------------------------------------
00250 qint64 KFolderTreeItem::recursiveFolderSize() const
00251 {
00252   qint64 size = mSize;
00253 
00254   for ( Q3ListViewItem *item = firstChild();  item; item = item->nextSibling() ) {
00255     size += static_cast<KFolderTreeItem*>( item )->recursiveFolderSize();
00256   }
00257   return size;
00258 }
00259 
00260 //-----------------------------------------------------------------------------
00261 int KFolderTreeItem::countUnreadRecursive()
00262 {
00263   int count = ( mUnread > 0 ) ? mUnread : 0;
00264 
00265   for ( Q3ListViewItem *item = firstChild(); item; item = item->nextSibling() ) {
00266     count += static_cast<KFolderTreeItem*>( item )->countUnreadRecursive();
00267   }
00268 
00269   return count;
00270 }
00271 
00272 //-----------------------------------------------------------------------------
00273 void KFolderTreeItem::paintCell( QPainter *p, const QColorGroup &cg,
00274                                  int column, int width, int align )
00275 {
00276   KFolderTree *ft = static_cast<KFolderTree*>( listView() );
00277 
00278   const int unreadRecursiveCount = countUnreadRecursive();
00279   const int unreadCount = ( mUnread > 0 ) ? mUnread : 0;
00280 
00281   // use a special color for folders which are close to their quota
00282   QColorGroup mycg = cg;
00283   if ( ( column == 0 || column == ft->sizeIndex() ) && folderIsCloseToQuota() ) {
00284     mycg.setColor( QColorGroup::Text, ft->paintInfo().colCloseToQuota );
00285   }
00286 
00287   // use a bold-font for the folder- and the unread-columns
00288   if ( ( column == 0 || column == ft->unreadIndex() ) &&
00289        ( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) ) {
00290     QFont f = p->font();
00291     f.setWeight( QFont::Bold );
00292     p->setFont( f );
00293   }
00294 
00295   // most cells can be handled by K3ListView::paintCell, we only need to
00296   // deal with the folder column if the unread column is not shown
00297 
00298   /* The below is exceedingly silly, but Ingo insists that the unread
00299    * count that is shown in parenthesis after the folder name must
00300    * be configurable in color. That means that paintCell needs to do
00301    * two painting passes which flickers. Since that flicker is not
00302    * needed when there is the unread column, special case that. */
00303   if (/*ft->isUnreadActive() ||*/ column != 0 ) {
00304     K3ListViewItem::paintCell( p, mycg, column, width, align );
00305   } else {
00306     Q3ListView *lv = listView();
00307     K3ListViewItem::paintCell( p, mycg, column, width, align );
00308 
00309     const QPixmap *icon = pixmap( column );
00310     int marg = lv ? lv->itemMargin() : 1;
00311     int r = marg;
00312 
00313     if ( isSelected() ) {
00314       p->setPen( mycg.color( QPalette::HighlightedText ) );
00315     } else {
00316       p->setPen( mycg.color( QPalette::Text ) );
00317     }
00318 
00319     if ( icon ) {
00320       r += icon->width() + marg;
00321     }
00322     //Remove any text that K3ListViewItem::paintCell() has drawn. We will
00323     //draw that ourselves below.
00324     if ( isSelected() ) {
00325       p->fillRect( r, 0, width-marg-r, height(), mycg.brush( QPalette::Highlight ) );
00326     } else {
00327       p->fillRect( r, 0, width-marg-r, height(), mycg.brush( QPalette::Base ) );
00328     }
00329 
00330     QString t = text( column );
00331     if ( t.isEmpty() ) {
00332       return;
00333     }
00334 
00335     // draw the unread-count if the unread-column is not active
00336     QString unread;
00337 
00338     if ( !ft->isUnreadActive() &&
00339          ( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) ) {
00340       if ( isOpen() ) {
00341         unread = " (" + QString::number( unreadCount ) + ')';
00342       } else if ( unreadRecursiveCount == unreadCount || mType == Root ) {
00343         unread = " (" + QString::number( unreadRecursiveCount ) + ')';
00344       } else {
00345         unread = " (" + QString::number( unreadCount ) + " + " +
00346                  QString::number( unreadRecursiveCount - unreadCount ) + ')';
00347       }
00348     }
00349 
00350     // check if the text needs to be squeezed
00351     QFontMetrics fm( p->fontMetrics() );
00352     int unreadWidth = fm.width( unread );
00353     if ( fm.width( t ) + marg + r + unreadWidth > width ) {
00354       t = squeezeFolderName( t, fm, width - marg - r - unreadWidth );
00355     }
00356 
00357     QRect br;
00358     p->drawText( r, 0, width-marg-r, height(), align | Qt::AlignVCenter, t, &br );
00359 
00360     if ( !unread.isEmpty() ) {
00361       if ( !isSelected() ) {
00362         p->setPen( ft->paintInfo().colUnread );
00363       }
00364       p->drawText( br.right(), 0, width-marg-br.right(), height(),
00365                    align | Qt::AlignVCenter, unread );
00366     }
00367   }
00368 }
00369 
00370 QString KFolderTreeItem::squeezeFolderName( const QString &text,
00371                                             const QFontMetrics &fm,
00372                                             uint width ) const
00373 {
00374   return fm.elidedText( text, Qt::ElideRight, width );
00375 }
00376 
00377 bool KFolderTreeItem::folderIsCloseToQuota() const
00378 {
00379   return mFolderIsCloseToQuota;
00380 }
00381 
00382 void KFolderTreeItem::setFolderIsCloseToQuota( bool v )
00383 {
00384   if ( mFolderIsCloseToQuota != v ) {
00385     mFolderIsCloseToQuota = v;
00386     repaint();
00387   }
00388 }
00389 
00390 //=============================================================================
00391 
00392 KFolderTree::KFolderTree( QWidget *parent, const char *name )
00393   : K3ListView( parent ), mUnreadIndex( -1 ), mTotalIndex( -1 ), mSizeIndex( -1 )
00394 {
00395   setObjectName( name );
00396   // GUI-options
00397   setStyleDependantFrameWidth();
00398   setAcceptDrops( true );
00399   setDropVisualizer( false );
00400   setAllColumnsShowFocus( true );
00401   setShowSortIndicator( true );
00402   setUpdatesEnabled( true );
00403   setItemsRenameable( false );
00404   setRootIsDecorated( true );
00405   setSelectionModeExt( Extended );
00406   setAlternateBackground( QColor() );
00407   setShadeSortColumn ( false );
00408   setFullWidth( true );
00409   disableAutoSelection();
00410   setColumnWidth( 0, 120 ); //reasonable default size
00411 
00412   disconnect( header(), SIGNAL(sizeChange(int,int,int)) );
00413   connect( header(), SIGNAL(sizeChange(int,int,int)),
00414            SLOT(slotSizeChanged(int,int,int)) );
00415 }
00416 
00417 //-----------------------------------------------------------------------------
00418 void KFolderTree::setStyleDependantFrameWidth()
00419 {
00420   // set the width of the frame to a reasonable value for the current GUI style
00421   int frameWidth;
00422   if ( QString( style()->metaObject()->className() ) == "KeramikStyle" ) {
00423     frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) - 1;
00424   } else {
00425     frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
00426   }
00427   if ( frameWidth < 0 ) {
00428     frameWidth = 0;
00429   }
00430   if ( frameWidth != lineWidth() ) {
00431     setLineWidth( frameWidth );
00432   }
00433 }
00434 
00435 //-----------------------------------------------------------------------------
00436 void KFolderTree::styleChange( QStyle &oldStyle )
00437 {
00438   setStyleDependantFrameWidth();
00439   K3ListView::styleChange( oldStyle );
00440 }
00441 
00442 //-----------------------------------------------------------------------------
00443 void KFolderTree::drawContentsOffset( QPainter *p, int ox, int oy,
00444                                        int cx, int cy, int cw, int ch )
00445 {
00446 //  bool oldUpdatesEnabled = updatesEnabled();
00447 //  setUpdatesEnabled(false);
00448   K3ListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
00449 // WARNING:This will trigger a repaint and thus an infinite loop!
00450 //  setUpdatesEnabled(oldUpdatesEnabled);
00451 }
00452 
00453 //-----------------------------------------------------------------------------
00454 void KFolderTree::contentsMousePressEvent( QMouseEvent *e )
00455 {
00456     setSelectionModeExt( Single );
00457     K3ListView::contentsMousePressEvent( e );
00458 }
00459 
00460 //-----------------------------------------------------------------------------
00461 void KFolderTree::contentsMouseReleaseEvent( QMouseEvent *e )
00462 {
00463     K3ListView::contentsMouseReleaseEvent( e );
00464     setSelectionModeExt( Extended );
00465 }
00466 
00467 //-----------------------------------------------------------------------------
00468 void KFolderTree::addAcceptableDropMimetype( const QString &mimeType, bool outsideOk )
00469 {
00470   mAcceptableDropMimetypes.append( mimeType );
00471   mAcceptOutside.append( outsideOk );
00472 }
00473 
00474 //-----------------------------------------------------------------------------
00475 bool KFolderTree::acceptDrag( QDropEvent *event ) const
00476 {
00477   Q3ListViewItem *item = itemAt( contentsToViewport( event->pos() ) );
00478 
00479   for ( int i=0; i < mAcceptableDropMimetypes.size(); i++ ) {
00480     if ( event->provides( mAcceptableDropMimetypes[i].toLatin1().constData() ) ) {
00481       if ( item ) {
00482         KFolderTreeItem *ft = static_cast<KFolderTreeItem*>( item );
00483         return ft->acceptDrag( event );
00484       } else {
00485         return mAcceptOutside[i];
00486       }
00487     }
00488   }
00489   return false;
00490 }
00491 
00492 //-----------------------------------------------------------------------------
00493 void KFolderTree::addUnreadColumn( const QString &name, int width )
00494 {
00495   mUnreadIndex = addColumn( name, width );
00496   setColumnAlignment( mUnreadIndex, qApp->isRightToLeft() ? Qt::AlignLeft : Qt::AlignRight );
00497   header()->adjustHeaderSize();
00498 }
00499 
00500 //-----------------------------------------------------------------------------
00501 void KFolderTree::addTotalColumn( const QString &name, int width )
00502 {
00503   mTotalIndex = addColumn( name, width );
00504   setColumnAlignment( mTotalIndex, qApp->isRightToLeft() ? Qt::AlignLeft : Qt::AlignRight );
00505   header()->adjustHeaderSize();
00506 }
00507 
00508 //-----------------------------------------------------------------------------
00509 void KFolderTree::removeUnreadColumn()
00510 {
00511   if ( !isUnreadActive() ) {
00512     return;
00513   }
00514   removeColumn( mUnreadIndex );
00515   if ( isTotalActive() && mTotalIndex > mUnreadIndex ) {
00516     mTotalIndex--;
00517   }
00518   if ( isSizeActive() && mSizeIndex > mUnreadIndex ) {
00519     mSizeIndex--;
00520   }
00521 
00522   mUnreadIndex = -1;
00523   header()->adjustHeaderSize();
00524 }
00525 
00526 //-----------------------------------------------------------------------------
00527 void KFolderTree::removeTotalColumn()
00528 {
00529   if ( !isTotalActive() ) {
00530     return;
00531   }
00532   removeColumn( mTotalIndex );
00533   if ( isUnreadActive() && mTotalIndex < mUnreadIndex ) {
00534     mUnreadIndex--;
00535   }
00536   if ( isSizeActive() && mTotalIndex < mSizeIndex ) {
00537     mSizeIndex--;
00538   }
00539   mTotalIndex = -1;
00540   header()->adjustHeaderSize();
00541 }
00542 
00543 //-----------------------------------------------------------------------------
00544 void KFolderTree::addSizeColumn( const QString &name, int width )
00545 {
00546   mSizeIndex = addColumn( name, width );
00547   setColumnAlignment( mSizeIndex,
00548                       ( qApp->layoutDirection() == Qt::RightToLeft ) ?
00549                       Qt::AlignLeft : Qt::AlignRight );
00550   header()->adjustHeaderSize();
00551 }
00552 
00553 //-----------------------------------------------------------------------------
00554 void KFolderTree::removeSizeColumn()
00555 {
00556   if ( !isSizeActive() ) {
00557     return;
00558   }
00559   removeColumn( mSizeIndex );
00560   if ( isUnreadActive() && mSizeIndex < mUnreadIndex ) {
00561     mUnreadIndex--;
00562   }
00563   if ( isTotalActive() && mSizeIndex < mTotalIndex ) {
00564     mTotalIndex--;
00565   }
00566   mSizeIndex = -1;
00567   header()->adjustHeaderSize();
00568 }
00569 
00570 //-----------------------------------------------------------------------------
00571 void KFolderTree::setFullWidth( bool fullWidth )
00572 {
00573   if ( fullWidth ) {
00574     header()->setStretchEnabled( true, 0 );
00575   }
00576 }
00577 
00578 //-----------------------------------------------------------------------------
00579 void KFolderTree::slotSizeChanged( int section, int, int newSize )
00580 {
00581   viewport()->repaint( header()->sectionPos( section ), 0, newSize, visibleHeight() );
00582 }
00583 
00584 #include "kfoldertree.moc"

libkdepim

Skip menu "libkdepim"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal