Page MenuHomePhorge

kfoldertree.cpp
No OneTemporary

kfoldertree.cpp

/* -*- mode: C++; c-file-style: "gnu" -*-
This file is part of libkdepim.
Copyright (C) 2002 Carsten Burghardt <burghardt@kde.org>
Copyright (C) 2002 Marc Mutz <mutz@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfoldertree.h"
#include <KDebug>
#include <KLocale>
#include <KIconLoader>
#include <kio/global.h>
#include <QApplication>
#include <QDropEvent>
#include <QFontMetrics>
#include <QMouseEvent>
#include <QPainter>
#include <QPixmap>
#include <QStyle>
#include <Q3Header>
using namespace KPIM;
//-----------------------------------------------------------------------------
KFolderTreeItem::KFolderTreeItem( KFolderTree *parent, const QString & label,
Protocol protocol, Type type )
: K3ListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
mUnread( -1 ), mTotal( 0 ), mSize( 0 ), mFolderIsCloseToQuota( false )
{
}
//-----------------------------------------------------------------------------
KFolderTreeItem::KFolderTreeItem( KFolderTreeItem *parent, const QString &label,
Protocol protocol, Type type, int unread,
int total )
: K3ListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
mUnread( unread ), mTotal( total ), mSize( 0 ),
mFolderIsCloseToQuota( false )
{
}
//-----------------------------------------------------------------------------
int KFolderTreeItem::protocolSortingKey() const
{
// protocol dependant sorting order:
// local < imap < news < search < other
switch ( mProtocol ) {
case Local:
return 1;
case CachedImap:
case Imap:
return 2;
case News:
return 3;
case Search:
return 4;
default:
return 42;
}
}
//-----------------------------------------------------------------------------
int KFolderTreeItem::typeSortingKey() const
{
// type dependant sorting order:
// inbox < outbox < sent-mail < trash < drafts
// < calendar < contacts < notes < tasks
// < normal folders
switch ( mType ) {
case Inbox:
return 1;
case Outbox:
return 2;
case SentMail:
return 3;
case Trash:
return 4;
case Drafts:
return 5;
case Templates:
return 6;
case Calendar:
return 7;
case Contacts:
return 8;
case Notes:
return 9;
case Tasks:
return 10;
default:
return 42;
}
}
//-----------------------------------------------------------------------------
int KFolderTreeItem::compare( Q3ListViewItem *i, int col, bool ) const
{
KFolderTreeItem* other = static_cast<KFolderTreeItem*>( i );
if ( col == 0 ) {
// sort by folder
// local root-folder
if ( depth() == 0 && mProtocol == NONE ) {
return -1;
}
if ( other->depth() == 0 && other->protocol() == NONE ) {
return 1;
}
// first compare by protocol
int thisKey = protocolSortingKey();
int thatKey = other->protocolSortingKey();
if ( thisKey < thatKey ) {
return -1;
}
if ( thisKey > thatKey ) {
return 1;
}
// then compare by type
thisKey = typeSortingKey();
thatKey = other->typeSortingKey();
if ( thisKey < thatKey ) {
return -1;
}
if ( thisKey > thatKey ) {
return 1;
}
// and finally compare by name
return text( 0 ).localeAwareCompare( other->text( 0 ) );
} else {
// sort by unread or total-column
qint64 a = 0, b = 0;
if ( col == static_cast<KFolderTree*>( listView() )->unreadIndex() ) {
a = mUnread;
b = other->unreadCount();
} else if ( col == static_cast<KFolderTree*>( listView() )->totalIndex() ) {
a = mTotal;
b = other->totalCount();
} else if ( col == static_cast<KFolderTree*>( listView() )->sizeIndex() ) {
a = mSize;
b = other->folderSize();
}
if ( a == b ) {
return 0;
} else {
return ( a < b ? -1 : 1 );
}
}
}
//-----------------------------------------------------------------------------
void KFolderTreeItem::setUnreadCount( int aUnread )
{
if ( aUnread < 0 ) {
return;
}
mUnread = aUnread;
QString unread;
if ( mUnread == 0 ) {
unread = "- ";
} else {
unread.setNum( mUnread );
unread += ' ';
}
setText( static_cast<KFolderTree*>( listView() )->unreadIndex(), unread );
}
//-----------------------------------------------------------------------------
void KFolderTreeItem::setTotalCount( int aTotal )
{
if ( aTotal < 0 ) {
return;
}
mTotal = aTotal;
QString total;
if ( mTotal == 0 ) {
total = "- ";
} else {
total.setNum( mTotal );
total += ' ';
}
setText( static_cast<KFolderTree*>( listView() )->totalIndex(), total );
}
//-----------------------------------------------------------------------------
void KFolderTreeItem::setFolderSize( qint64 aSize )
{
if ( aSize < 0 ) {
return; // we need to update even if nothing changed, kids ...
}
mSize = aSize;
QString size;
qint64 recursiveSize = 0;
if ( childCount() > 0 && !isOpen() ) {
recursiveSize = recursiveFolderSize();
}
if ( mType != Root ) {
if ( mSize == 0 && ( childCount() == 0 || isOpen() || recursiveSize == 0 ) ) {
size = "- ";
} else {
size = KIO::convertSize( mSize );
}
}
if ( childCount() > 0 && !isOpen() && recursiveSize != mSize ) {
if ( mType != Root ) {
size += QString::fromLatin1( " + %1" ).arg( KIO::convertSize( recursiveSize - mSize ) );
} else {
size = KIO::convertSize( recursiveSize );
}
}
size += ' ';
setText( static_cast<KFolderTree*>( listView() )->sizeIndex(), size );
}
//-----------------------------------------------------------------------------
qint64 KFolderTreeItem::recursiveFolderSize() const
{
qint64 size = mSize;
for ( Q3ListViewItem *item = firstChild(); item; item = item->nextSibling() ) {
size += static_cast<KFolderTreeItem*>( item )->recursiveFolderSize();
}
return size;
}
//-----------------------------------------------------------------------------
int KFolderTreeItem::countUnreadRecursive()
{
int count = ( mUnread > 0 ) ? mUnread : 0;
for ( Q3ListViewItem *item = firstChild(); item; item = item->nextSibling() ) {
count += static_cast<KFolderTreeItem*>( item )->countUnreadRecursive();
}
return count;
}
//-----------------------------------------------------------------------------
void KFolderTreeItem::paintCell( QPainter *p, const QColorGroup &cg,
int column, int width, int align )
{
KFolderTree *ft = static_cast<KFolderTree*>( listView() );
const int unreadRecursiveCount = countUnreadRecursive();
const int unreadCount = ( mUnread > 0 ) ? mUnread : 0;
// use a special color for folders which are close to their quota
QColorGroup mycg = cg;
if ( ( column == 0 || column == ft->sizeIndex() ) && folderIsCloseToQuota() ) {
mycg.setColor( QColorGroup::Text, ft->paintInfo().colCloseToQuota );
}
// use a bold-font for the folder- and the unread-columns
if ( ( column == 0 || column == ft->unreadIndex() ) &&
( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) ) {
QFont f = p->font();
f.setWeight( QFont::Bold );
p->setFont( f );
}
// most cells can be handled by K3ListView::paintCell, we only need to
// deal with the folder column if the unread column is not shown
/* The below is exceedingly silly, but Ingo insists that the unread
* count that is shown in parenthesis after the folder name must
* be configurable in color. That means that paintCell needs to do
* two painting passes which flickers. Since that flicker is not
* needed when there is the unread column, special case that. */
if (/*ft->isUnreadActive() ||*/ column != 0 ) {
K3ListViewItem::paintCell( p, mycg, column, width, align );
} else {
Q3ListView *lv = listView();
K3ListViewItem::paintCell( p, mycg, column, width, align );
const QPixmap *icon = pixmap( column );
int marg = lv ? lv->itemMargin() : 1;
int r = marg;
if ( isSelected() ) {
p->setPen( mycg.color( QPalette::HighlightedText ) );
} else {
p->setPen( mycg.color( QPalette::Text ) );
}
if ( icon ) {
r += icon->width() + marg;
}
//Remove any text that K3ListViewItem::paintCell() has drawn. We will
//draw that ourselves below.
if ( isSelected() ) {
p->fillRect( r, 0, width-marg-r, height(), mycg.brush( QPalette::Highlight ) );
} else {
p->fillRect( r, 0, width-marg-r, height(), mycg.brush( QPalette::Base ) );
}
QString t = text( column );
if ( t.isEmpty() ) {
return;
}
// draw the unread-count if the unread-column is not active
QString unread;
if ( !ft->isUnreadActive() &&
( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) ) {
if ( isOpen() ) {
unread = " (" + QString::number( unreadCount ) + ')';
} else if ( unreadRecursiveCount == unreadCount || mType == Root ) {
unread = " (" + QString::number( unreadRecursiveCount ) + ')';
} else {
unread = " (" + QString::number( unreadCount ) + " + " +
QString::number( unreadRecursiveCount - unreadCount ) + ')';
}
}
// check if the text needs to be squeezed
QFontMetrics fm( p->fontMetrics() );
int unreadWidth = fm.width( unread );
if ( fm.width( t ) + marg + r + unreadWidth > width ) {
t = squeezeFolderName( t, fm, width - marg - r - unreadWidth );
}
QRect br;
p->drawText( r, 0, width-marg-r, height(), align | Qt::AlignVCenter, t, &br );
if ( !unread.isEmpty() ) {
if ( !isSelected() ) {
p->setPen( ft->paintInfo().colUnread );
}
p->drawText( br.right(), 0, width-marg-br.right(), height(),
align | Qt::AlignVCenter, unread );
}
}
}
QString KFolderTreeItem::squeezeFolderName( const QString &text,
const QFontMetrics &fm,
uint width ) const
{
return fm.elidedText( text, Qt::ElideRight, width );
}
bool KFolderTreeItem::folderIsCloseToQuota() const
{
return mFolderIsCloseToQuota;
}
void KFolderTreeItem::setFolderIsCloseToQuota( bool v )
{
if ( mFolderIsCloseToQuota != v ) {
mFolderIsCloseToQuota = v;
repaint();
}
}
//=============================================================================
KFolderTree::KFolderTree( QWidget *parent, const char *name )
: K3ListView( parent ), mUnreadIndex( -1 ), mTotalIndex( -1 ), mSizeIndex( -1 )
{
setObjectName( name );
// GUI-options
setStyleDependantFrameWidth();
setAcceptDrops( true );
setDropVisualizer( false );
setAllColumnsShowFocus( true );
setShowSortIndicator( true );
setUpdatesEnabled( true );
setItemsRenameable( false );
setRootIsDecorated( true );
setSelectionModeExt( Extended );
setAlternateBackground( QColor() );
setShadeSortColumn ( false );
setFullWidth( true );
disableAutoSelection();
setColumnWidth( 0, 120 ); //reasonable default size
disconnect( header(), SIGNAL(sizeChange(int,int,int)) );
connect( header(), SIGNAL(sizeChange(int,int,int)),
SLOT(slotSizeChanged(int,int,int)) );
}
//-----------------------------------------------------------------------------
void KFolderTree::setStyleDependantFrameWidth()
{
// set the width of the frame to a reasonable value for the current GUI style
int frameWidth;
if ( QString( style()->metaObject()->className() ) == "KeramikStyle" ) {
frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) - 1;
} else {
frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
}
if ( frameWidth < 0 ) {
frameWidth = 0;
}
if ( frameWidth != lineWidth() ) {
setLineWidth( frameWidth );
}
}
//-----------------------------------------------------------------------------
void KFolderTree::styleChange( QStyle &oldStyle )
{
setStyleDependantFrameWidth();
K3ListView::styleChange( oldStyle );
}
//-----------------------------------------------------------------------------
void KFolderTree::drawContentsOffset( QPainter *p, int ox, int oy,
int cx, int cy, int cw, int ch )
{
// bool oldUpdatesEnabled = updatesEnabled();
// setUpdatesEnabled(false);
K3ListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
// WARNING:This will trigger a repaint and thus an infinite loop!
// setUpdatesEnabled(oldUpdatesEnabled);
}
//-----------------------------------------------------------------------------
void KFolderTree::contentsMousePressEvent( QMouseEvent *e )
{
setSelectionModeExt( Single );
K3ListView::contentsMousePressEvent( e );
}
//-----------------------------------------------------------------------------
void KFolderTree::contentsMouseReleaseEvent( QMouseEvent *e )
{
K3ListView::contentsMouseReleaseEvent( e );
setSelectionModeExt( Extended );
}
//-----------------------------------------------------------------------------
void KFolderTree::addAcceptableDropMimetype( const QString &mimeType, bool outsideOk )
{
mAcceptableDropMimetypes.append( mimeType );
mAcceptOutside.append( outsideOk );
}
//-----------------------------------------------------------------------------
bool KFolderTree::acceptDrag( QDropEvent *event ) const
{
Q3ListViewItem *item = itemAt( contentsToViewport( event->pos() ) );
for ( int i=0; i < mAcceptableDropMimetypes.size(); i++ ) {
if ( event->provides( mAcceptableDropMimetypes[i].toLatin1().constData() ) ) {
if ( item ) {
KFolderTreeItem *ft = static_cast<KFolderTreeItem*>( item );
return ft->acceptDrag( event );
} else {
return mAcceptOutside[i];
}
}
}
return false;
}
//-----------------------------------------------------------------------------
void KFolderTree::addUnreadColumn( const QString &name, int width )
{
mUnreadIndex = addColumn( name, width );
setColumnAlignment( mUnreadIndex, qApp->isRightToLeft() ? Qt::AlignLeft : Qt::AlignRight );
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::addTotalColumn( const QString &name, int width )
{
mTotalIndex = addColumn( name, width );
setColumnAlignment( mTotalIndex, qApp->isRightToLeft() ? Qt::AlignLeft : Qt::AlignRight );
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::removeUnreadColumn()
{
if ( !isUnreadActive() ) {
return;
}
removeColumn( mUnreadIndex );
if ( isTotalActive() && mTotalIndex > mUnreadIndex ) {
mTotalIndex--;
}
if ( isSizeActive() && mSizeIndex > mUnreadIndex ) {
mSizeIndex--;
}
mUnreadIndex = -1;
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::removeTotalColumn()
{
if ( !isTotalActive() ) {
return;
}
removeColumn( mTotalIndex );
if ( isUnreadActive() && mTotalIndex < mUnreadIndex ) {
mUnreadIndex--;
}
if ( isSizeActive() && mTotalIndex < mSizeIndex ) {
mSizeIndex--;
}
mTotalIndex = -1;
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::addSizeColumn( const QString &name, int width )
{
mSizeIndex = addColumn( name, width );
setColumnAlignment( mSizeIndex,
( qApp->layoutDirection() == Qt::RightToLeft ) ?
Qt::AlignLeft : Qt::AlignRight );
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::removeSizeColumn()
{
if ( !isSizeActive() ) {
return;
}
removeColumn( mSizeIndex );
if ( isUnreadActive() && mSizeIndex < mUnreadIndex ) {
mUnreadIndex--;
}
if ( isTotalActive() && mSizeIndex < mTotalIndex ) {
mTotalIndex--;
}
mSizeIndex = -1;
header()->adjustHeaderSize();
}
//-----------------------------------------------------------------------------
void KFolderTree::setFullWidth( bool fullWidth )
{
if ( fullWidth ) {
header()->setStretchEnabled( true, 0 );
}
}
//-----------------------------------------------------------------------------
void KFolderTree::slotSizeChanged( int section, int, int newSize )
{
viewport()->repaint( header()->sectionPos( section ), 0, newSize, visibleHeight() );
}
#include "kfoldertree.moc"

File Metadata

Mime Type
text/x-c
Expires
Fri, Nov 1, 9:58 AM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10067556
Default Alt Text
kfoldertree.cpp (16 KB)

Event Timeline