00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00063
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
00083
00084
00085
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
00119
00120
00121 if ( depth() == 0 && mProtocol == NONE ) {
00122 return -1;
00123 }
00124 if ( other->depth() == 0 && other->protocol() == NONE ) {
00125 return 1;
00126 }
00127
00128
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
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
00149 return text( 0 ).localeAwareCompare( other->text( 0 ) );
00150 } else {
00151
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;
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
00282 QColorGroup mycg = cg;
00283 if ( ( column == 0 || column == ft->sizeIndex() ) && folderIsCloseToQuota() ) {
00284 mycg.setColor( QColorGroup::Text, ft->paintInfo().colCloseToQuota );
00285 }
00286
00287
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
00296
00297
00298
00299
00300
00301
00302
00303 if ( 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
00323
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
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
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
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 );
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
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
00447
00448 K3ListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
00449
00450
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"