You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
543 lines
15 KiB
543 lines
15 KiB
// -*- c-basic-offset: 2 -*-
|
|
|
|
#include "kfoldertree.h"
|
|
#include <klocale.h>
|
|
#include <kio/global.h>
|
|
#include <kiconloader.h>
|
|
#include <kdebug.h>
|
|
#include <kstringhandler.h>
|
|
#include <tqpainter.h>
|
|
#include <tqapplication.h>
|
|
#include <tqheader.h>
|
|
#include <tqstyle.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KFolderTreeItem::KFolderTreeItem( KFolderTree *parent, const TQString & label,
|
|
Protocol protocol, Type type )
|
|
: KListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
|
|
mUnread(-1), mTotal(0), mSize(0), mFolderIsCloseToQuota( false )
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KFolderTreeItem::KFolderTreeItem( KFolderTreeItem *parent,
|
|
const TQString & label, Protocol protocol, Type type,
|
|
int unread, int total )
|
|
: KListViewItem( 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( TQListViewItem * 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
|
|
TQ_INT64 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;
|
|
|
|
TQString unread = TQString();
|
|
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;
|
|
|
|
TQString total = TQString();
|
|
if (mTotal == 0)
|
|
total = "- ";
|
|
else {
|
|
total.setNum(mTotal);
|
|
total += " ";
|
|
}
|
|
|
|
setText( static_cast<KFolderTree*>(listView())->totalIndex(),
|
|
total );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTreeItem::setFolderSize( TQ_INT64 aSize )
|
|
{
|
|
if ( aSize < 0 ) return; // we need to update even if nothing changed, kids ...
|
|
|
|
mSize = aSize;
|
|
|
|
TQString size;
|
|
if (mType != Root) {
|
|
if (mSize == 0 && (childCount() == 0 || isOpen() ) )
|
|
size = "- ";
|
|
else
|
|
size = KIO::convertSize(mSize);
|
|
}
|
|
if ( childCount() > 0 && !isOpen() ) {
|
|
TQ_INT64 recursiveSize = recursiveFolderSize();
|
|
if ( recursiveSize != mSize ) {
|
|
if ( mType != Root )
|
|
size += TQString::fromLatin1(" + %1").arg( KIO::convertSize( recursiveSize - mSize ) );
|
|
else
|
|
size = KIO::convertSize( recursiveSize );
|
|
}
|
|
}
|
|
size += " ";
|
|
|
|
setText( static_cast<KFolderTree*>(listView())->sizeIndex(), size );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
TQ_INT64 KFolderTreeItem::recursiveFolderSize() const
|
|
{
|
|
TQ_INT64 size = mSize;
|
|
|
|
for ( TQListViewItem *item = firstChild() ;
|
|
item ; item = item->nextSibling() )
|
|
{
|
|
size += static_cast<KFolderTreeItem*>(item)->recursiveFolderSize();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int KFolderTreeItem::countUnreadRecursive()
|
|
{
|
|
int count = (mUnread > 0) ? mUnread : 0;
|
|
|
|
for ( TQListViewItem *item = firstChild() ;
|
|
item ; item = item->nextSibling() )
|
|
{
|
|
count += static_cast<KFolderTreeItem*>(item)->countUnreadRecursive();
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTreeItem::paintCell( TQPainter * p, const TQColorGroup & 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
|
|
TQColorGroup mycg = cg;
|
|
if ( ( column == 0 || column == ft->sizeIndex() ) && folderIsCloseToQuota() )
|
|
{
|
|
mycg.setColor( TQColorGroup::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 ) ) )
|
|
{
|
|
TQFont f = p->font();
|
|
f.setWeight(TQFont::Bold);
|
|
p->setFont(f);
|
|
}
|
|
|
|
|
|
// most cells can be handled by KListView::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 ) {
|
|
KListViewItem::paintCell( p, mycg, column, width, align );
|
|
} else {
|
|
TQListView *lv = listView();
|
|
TQString oldText = text(column);
|
|
|
|
// set an empty text so that we can have our own implementation (see further down)
|
|
// but still benefit from KListView::paintCell
|
|
setText( column, "" );
|
|
|
|
KListViewItem::paintCell( p, mycg, column, width, align );
|
|
|
|
const TQPixmap *icon = pixmap( column );
|
|
int marg = lv ? lv->itemMargin() : 1;
|
|
int r = marg;
|
|
|
|
setText( column, oldText );
|
|
if ( isSelected() )
|
|
p->setPen( mycg.highlightedText() );
|
|
else
|
|
p->setPen( mycg.color( TQColorGroup::Text ) );
|
|
|
|
if ( icon ) {
|
|
r += icon->width() + marg;
|
|
}
|
|
TQString t = text( column );
|
|
if (t.isEmpty())
|
|
return;
|
|
|
|
// draw the unread-count if the unread-column is not active
|
|
TQString unread;
|
|
|
|
if ( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) {
|
|
if ( isOpen() )
|
|
unread = " (" + TQString::number( unreadCount ) + ")";
|
|
else if ( unreadRecursiveCount == unreadCount || mType == Root )
|
|
unread = " (" + TQString::number( unreadRecursiveCount ) + ")";
|
|
else
|
|
unread = " (" + TQString::number( unreadCount ) + " + " +
|
|
TQString::number( unreadRecursiveCount-unreadCount ) + ")";
|
|
}
|
|
|
|
// check if the text needs to be squeezed
|
|
TQFontMetrics fm( p->fontMetrics() );
|
|
int unreadWidth = fm.width( unread );
|
|
if ( fm.width( t ) + marg + r + unreadWidth > width )
|
|
t = squeezeFolderName( t, fm, width - marg - r - unreadWidth );
|
|
|
|
TQRect br;
|
|
p->drawText( r, 0, width-marg-r, height(),
|
|
align | AlignVCenter, t, -1, &br );
|
|
|
|
if ( !unread.isEmpty() ) {
|
|
if (!isSelected())
|
|
p->setPen( ft->paintInfo().colUnread );
|
|
p->drawText( br.right(), 0, width-marg-br.right(), height(),
|
|
align | AlignVCenter, unread );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TQString KFolderTreeItem::squeezeFolderName( const TQString &text,
|
|
const TQFontMetrics &fm,
|
|
uint width ) const
|
|
{
|
|
return KStringHandler::rPixelSqueeze( text, fm, width );
|
|
}
|
|
|
|
bool KFolderTreeItem::folderIsCloseToQuota() const
|
|
{
|
|
return mFolderIsCloseToQuota;
|
|
}
|
|
|
|
void KFolderTreeItem::setFolderIsCloseToQuota( bool v )
|
|
{
|
|
if ( mFolderIsCloseToQuota != v) {
|
|
mFolderIsCloseToQuota = v;
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
KFolderTree::KFolderTree( TQWidget *parent, const char* name )
|
|
: KListView( parent, name ), mUnreadIndex(-1), mTotalIndex(-1), mSizeIndex(-1)
|
|
{
|
|
// GUI-options
|
|
setStyleDependantFrameWidth();
|
|
setAcceptDrops(true);
|
|
setDropVisualizer(false);
|
|
setAllColumnsShowFocus(true);
|
|
setShowSortIndicator(true);
|
|
setUpdatesEnabled(true);
|
|
setItemsRenameable(false);
|
|
setRootIsDecorated(true);
|
|
setSelectionModeExt(Extended);
|
|
setAlternateBackground(TQColor());
|
|
#if KDE_IS_VERSION( 3, 3, 90 )
|
|
setShadeSortColumn ( false );
|
|
#endif
|
|
setFullWidth(true);
|
|
disableAutoSelection();
|
|
setColumnWidth( 0, 120 ); //reasonable default size
|
|
|
|
disconnect( header(), TQT_SIGNAL( sizeChange( int, int, int ) ) );
|
|
connect( header(), TQT_SIGNAL( sizeChange( int, int, int ) ),
|
|
TQT_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( style().isA("KeramikStyle") )
|
|
frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
|
|
else
|
|
frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
|
|
if ( frameWidth < 0 )
|
|
frameWidth = 0;
|
|
if ( frameWidth != lineWidth() )
|
|
setLineWidth( frameWidth );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::styleChange( TQStyle& oldStyle )
|
|
{
|
|
setStyleDependantFrameWidth();
|
|
KListView::styleChange( oldStyle );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::drawContentsOffset( TQPainter * p, int ox, int oy,
|
|
int cx, int cy, int cw, int ch )
|
|
{
|
|
bool oldUpdatesEnabled = isUpdatesEnabled();
|
|
setUpdatesEnabled(false);
|
|
KListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
|
|
setUpdatesEnabled(oldUpdatesEnabled);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::contentsMousePressEvent( TQMouseEvent *e )
|
|
{
|
|
setSelectionModeExt(Single);
|
|
KListView::contentsMousePressEvent(e);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::contentsMouseReleaseEvent( TQMouseEvent *e )
|
|
{
|
|
KListView::contentsMouseReleaseEvent(e);
|
|
setSelectionModeExt(Extended);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::addAcceptableDropMimetype( const char *mimeType, bool outsideOk )
|
|
{
|
|
int oldSize = mAcceptableDropMimetypes.size();
|
|
mAcceptableDropMimetypes.resize(oldSize+1);
|
|
mAcceptOutside.resize(oldSize+1);
|
|
|
|
mAcceptableDropMimetypes.at(oldSize) = mimeType;
|
|
mAcceptOutside.setBit(oldSize, outsideOk);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool KFolderTree::acceptDrag( TQDropEvent* event ) const
|
|
{
|
|
TQListViewItem* item = itemAt(contentsToViewport(event->pos()));
|
|
|
|
for (uint i = 0; i < mAcceptableDropMimetypes.size(); i++)
|
|
{
|
|
if (event->provides(mAcceptableDropMimetypes[i]))
|
|
{
|
|
if (item)
|
|
return (static_cast<KFolderTreeItem*>(item))->acceptDrag(event);
|
|
else
|
|
return mAcceptOutside[i];
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::addUnreadColumn( const TQString & name, int width )
|
|
{
|
|
mUnreadIndex = addColumn( name, width );
|
|
setColumnAlignment( mUnreadIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::AlignRight );
|
|
header()->adjustHeaderSize();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KFolderTree::addTotalColumn( const TQString & name, int width )
|
|
{
|
|
mTotalIndex = addColumn( name, width );
|
|
setColumnAlignment( mTotalIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::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 TQString & name, int width )
|
|
{
|
|
mSizeIndex = addColumn( name, width );
|
|
setColumnAlignment( mSizeIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::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(), false );
|
|
}
|
|
|
|
#include "kfoldertree.moc"
|