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.
1630 lines
63 KiB
1630 lines
63 KiB
/****************************************************************************** |
|
* |
|
* Copyright 2008 Szymon Tomasz Stefanek <pragma@kvirc.net> |
|
* |
|
* This program is free softhisare; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Softhisare Foundation; either version 2 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program 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 General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Softhisare |
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
* |
|
*******************************************************************************/ |
|
|
|
#include "messagelistview/core/themedelegate.h" |
|
#include "messagelistview/core/messageitem.h" |
|
#include "messagelistview/core/groupheaderitem.h" |
|
#include "messagelistview/core/manager.h" |
|
|
|
#include <QStyle> |
|
#include <QPainter> |
|
#include <QFont> |
|
#include <QFontMetrics> |
|
#include <QAbstractItemView> |
|
#include <QPixmap> |
|
#include <QLinearGradient> |
|
#include <KColorScheme> |
|
|
|
namespace KMail |
|
{ |
|
|
|
namespace MessageListView |
|
{ |
|
|
|
namespace Core |
|
{ |
|
|
|
static const int gGroupHeaderOuterVerticalMargin = 1; |
|
static const int gGroupHeaderOuterHorizontalMargin = 1; |
|
static const int gGroupHeaderInnerVerticalMargin = 1; |
|
static const int gGroupHeaderInnerHorizontalMargin = 1; |
|
static const int gMessageVerticalMargin = 2; |
|
static const int gMessageHorizontalMargin = 2; |
|
static const int gHorizontalItemSpacing = 2; |
|
|
|
|
|
ThemeDelegate::ThemeDelegate( QAbstractItemView * parent, QPaintDevice * paintDevice ) |
|
: QStyledItemDelegate( parent ) |
|
{ |
|
mItemView = parent; |
|
mPaintDevice = paintDevice; |
|
mTheme = 0; |
|
} |
|
|
|
ThemeDelegate::~ThemeDelegate() |
|
{ |
|
} |
|
|
|
void ThemeDelegate::setTheme( const Theme * theme ) |
|
{ |
|
mTheme = theme; |
|
// yep..we're violating const here |
|
// But most of the QStyledItemDelegate virtual methods are const and expect |
|
// const behaviour. So we need the const pointer to avoid compiler complains |
|
// but on the other side we're NOT really const... well... |
|
const_cast< Theme * >( mTheme )->resetCache(); |
|
|
|
// Rebuild the group header background color cache |
|
switch( mTheme->groupHeaderBackgroundMode() ) |
|
{ |
|
case Theme::Transparent: |
|
mGroupHeaderBackgroundColor = QColor(); // invalid |
|
break; |
|
case Theme::CustomColor: |
|
mGroupHeaderBackgroundColor = mTheme->groupHeaderBackgroundColor(); |
|
break; |
|
case Theme::AutoColor: |
|
{ |
|
QPalette pal = mItemView->palette(); |
|
QColor txt = pal.color( QPalette::Normal, QPalette::Text ); |
|
QColor bck = pal.color( QPalette::Normal, QPalette::Base ); |
|
mGroupHeaderBackgroundColor = QColor( |
|
( txt.red() + ( bck.red() * 3 ) ) / 4, |
|
( txt.green() + ( bck.green() * 3 ) ) / 4, |
|
( txt.blue() + ( bck.blue() * 3 ) ) / 4 |
|
); |
|
} |
|
break; |
|
} |
|
mItemView->reset(); |
|
} |
|
|
|
// FIXME: gcc will refuse to inline these functions loudly complaining |
|
// about function growth limit reached. Consider using macros |
|
// or just convert to member functions. |
|
|
|
static inline void paint_right_aligned_elided_text( const QString &text, QPaintDevice * pd, Theme::ContentItem * ci, QPainter * painter, int &left, int top, int &right, Qt::LayoutDirection layoutDir ) |
|
{ |
|
if ( ci->lastPaintDevice() != pd ) |
|
ci->updateFontMetrics( pd ); |
|
painter->setFont( ci->font() ); |
|
int w = right - left; |
|
QString elidedText = ci->fontMetrics().elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); |
|
QRect rct( left, top, w, ci->lineSpacing() ); |
|
QRect outRct; |
|
|
|
if ( ci->softenByBlending() ) |
|
{ |
|
qreal oldOpacity = painter->opacity(); |
|
painter->setOpacity( 0.6 ); |
|
painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); |
|
painter->setOpacity( oldOpacity ); |
|
} else { |
|
painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); |
|
} |
|
if ( layoutDir == Qt::LeftToRight ) |
|
right -= outRct.width() + gHorizontalItemSpacing; |
|
else |
|
left += outRct.width() + gHorizontalItemSpacing; |
|
} |
|
|
|
static inline void compute_bounding_rect_for_right_aligned_elided_text( const QString &text, QPaintDevice * pd, Theme::ContentItem * ci, int &left, int top, int &right, QRect &outRect, Qt::LayoutDirection layoutDir ) |
|
{ |
|
if ( ci->lastPaintDevice() != pd ) |
|
ci->updateFontMetrics( pd ); |
|
int w = right - left; |
|
QString elidedText = ci->fontMetrics().elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); |
|
QRect rct( left, top, w, ci->lineSpacing() ); |
|
Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignRight : Qt::AlignLeft; |
|
outRect = ci->fontMetrics().boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); |
|
if ( layoutDir == Qt::LeftToRight ) |
|
right -= outRect.width() + gHorizontalItemSpacing; |
|
else |
|
left += outRect.width() + gHorizontalItemSpacing; |
|
} |
|
|
|
|
|
static inline void paint_left_aligned_elided_text( const QString &text, QPaintDevice * pd, Theme::ContentItem * ci, QPainter * painter, int &left, int top, int &right, Qt::LayoutDirection layoutDir ) |
|
{ |
|
if ( ci->lastPaintDevice() != pd ) |
|
ci->updateFontMetrics( pd ); |
|
painter->setFont( ci->font() ); |
|
int w = right - left; |
|
QString elidedText = ci->fontMetrics().elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); |
|
QRect rct( left, top, w, ci->lineSpacing() ); |
|
QRect outRct; |
|
if ( ci->softenByBlending() ) |
|
{ |
|
qreal oldOpacity = painter->opacity(); |
|
painter->setOpacity( 0.6 ); |
|
painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); |
|
painter->setOpacity( oldOpacity ); |
|
} else { |
|
painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); |
|
} |
|
if ( layoutDir == Qt::LeftToRight ) |
|
left += outRct.width() + gHorizontalItemSpacing; |
|
else |
|
right -= outRct.width() + gHorizontalItemSpacing; |
|
} |
|
|
|
static inline void compute_bounding_rect_for_left_aligned_elided_text( const QString &text, QPaintDevice * pd, Theme::ContentItem * ci, int &left, int top, int &right, QRect &outRect, Qt::LayoutDirection layoutDir ) |
|
{ |
|
if ( ci->lastPaintDevice() != pd ) |
|
ci->updateFontMetrics( pd ); |
|
int w = right - left; |
|
QString elidedText = ci->fontMetrics().elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); |
|
QRect rct( left, top, w, ci->lineSpacing() ); |
|
Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignLeft : Qt::AlignRight; |
|
outRect = ci->fontMetrics().boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); |
|
if ( layoutDir == Qt::LeftToRight ) |
|
left += outRect.width() + gHorizontalItemSpacing; |
|
else |
|
right -= outRect.width() + gHorizontalItemSpacing; |
|
} |
|
|
|
static inline const QPixmap * get_read_state_icon( Item * item ) |
|
{ |
|
if ( item->status().isQueued() ) |
|
return Manager::instance()->pixmapMessageQueued(); |
|
if ( item->status().isSent() ) |
|
return Manager::instance()->pixmapMessageSent(); |
|
if ( item->status().isNew() ) |
|
return Manager::instance()->pixmapMessageNew(); |
|
if ( item->status().isRead() || item->status().isOld() ) |
|
return Manager::instance()->pixmapMessageRead(); |
|
if ( item->status().isUnread() ) |
|
return Manager::instance()->pixmapMessageUnread(); |
|
if ( item->status().isDeleted() ) |
|
return Manager::instance()->pixmapMessageDeleted(); |
|
|
|
// Uhm... should never happen.. but fallback to "read"... |
|
return Manager::instance()->pixmapMessageRead(); |
|
} |
|
|
|
static inline const QPixmap * get_combined_read_replied_state_icon( MessageItem * messageItem ) |
|
{ |
|
if ( messageItem->status().isReplied() ) |
|
{ |
|
if ( messageItem->status().isForwarded() ) |
|
return Manager::instance()->pixmapMessageRepliedAndForwarded(); |
|
return Manager::instance()->pixmapMessageReplied(); |
|
} |
|
if ( messageItem->status().isForwarded() ) |
|
return Manager::instance()->pixmapMessageForwarded(); |
|
|
|
return get_read_state_icon( messageItem ); |
|
} |
|
|
|
static inline const QPixmap * get_encryption_state_icon( MessageItem * messageItem, bool *treatAsEnabled ) |
|
{ |
|
switch( messageItem->encryptionState() ) |
|
{ |
|
case MessageItem::FullyEncrypted: |
|
*treatAsEnabled = true; |
|
return Manager::instance()->pixmapMessageFullyEncrypted(); |
|
break; |
|
case MessageItem::PartiallyEncrypted: |
|
*treatAsEnabled = true; |
|
return Manager::instance()->pixmapMessagePartiallyEncrypted(); |
|
break; |
|
case MessageItem::EncryptionStateUnknown: |
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageUndefinedEncrypted(); |
|
break; |
|
case MessageItem::NotEncrypted: |
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageNotEncrypted(); |
|
break; |
|
default: |
|
// should never happen |
|
Q_ASSERT( false ); |
|
break; |
|
} |
|
|
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageUndefinedEncrypted(); |
|
} |
|
|
|
static inline const QPixmap * get_signature_state_icon( MessageItem * messageItem, bool *treatAsEnabled ) |
|
{ |
|
switch( messageItem->signatureState() ) |
|
{ |
|
case MessageItem::FullySigned: |
|
*treatAsEnabled = true; |
|
return Manager::instance()->pixmapMessageFullySigned(); |
|
break; |
|
case MessageItem::PartiallySigned: |
|
*treatAsEnabled = true; |
|
return Manager::instance()->pixmapMessagePartiallySigned(); |
|
break; |
|
case MessageItem::SignatureStateUnknown: |
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageUndefinedSigned(); |
|
break; |
|
case MessageItem::NotSigned: |
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageNotSigned(); |
|
break; |
|
default: |
|
// should never happen |
|
Q_ASSERT( false ); |
|
break; |
|
} |
|
|
|
*treatAsEnabled = false; |
|
return Manager::instance()->pixmapMessageUndefinedSigned(); |
|
} |
|
|
|
static inline const QPixmap * get_replied_state_icon( MessageItem * messageItem ) |
|
{ |
|
if ( messageItem->status().isReplied() ) |
|
{ |
|
if ( messageItem->status().isForwarded() ) |
|
return Manager::instance()->pixmapMessageRepliedAndForwarded(); |
|
return Manager::instance()->pixmapMessageReplied(); |
|
} |
|
if ( messageItem->status().isForwarded() ) |
|
return Manager::instance()->pixmapMessageForwarded(); |
|
|
|
return 0; |
|
} |
|
|
|
static inline const QPixmap * get_spam_ham_state_icon( MessageItem * messageItem ) |
|
{ |
|
if ( messageItem->status().isSpam() ) |
|
return Manager::instance()->pixmapMessageSpam(); |
|
if ( messageItem->status().isHam() ) |
|
return Manager::instance()->pixmapMessageHam(); |
|
return 0; |
|
} |
|
|
|
static inline const QPixmap * get_watched_ignored_state_icon( MessageItem * messageItem ) |
|
{ |
|
if ( messageItem->status().isIgnored() ) |
|
return Manager::instance()->pixmapMessageIgnored(); |
|
if ( messageItem->status().isWatched() ) |
|
return Manager::instance()->pixmapMessageWatched(); |
|
return 0; |
|
} |
|
|
|
static inline void paint_vertical_line( QPainter * painter, int &left, int top, int &right, int bottom, bool alignOnRight ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= 1; |
|
if ( right < 0 ) |
|
return; |
|
painter->drawLine( right, top, right, bottom ); |
|
right -= 2; |
|
right -= gHorizontalItemSpacing; |
|
} else { |
|
left += 1; |
|
if ( left > right ) |
|
return; |
|
painter->drawLine( left, top, left, bottom ); |
|
left += 2 + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
static inline void compute_bounding_rect_for_vertical_line( int &left, int top, int &right, int bottom, QRect &outRect, bool alignOnRight ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= 3; |
|
outRect = QRect( right, top, 3, bottom - top ); |
|
right -= gHorizontalItemSpacing; |
|
} else { |
|
outRect = QRect( left, top, 3, bottom - top ); |
|
left += 3 + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
static inline void paint_horizontal_spacer( int &left, int, int &right, int, bool alignOnRight ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= 3 + gHorizontalItemSpacing; |
|
} else { |
|
left += 3 + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
static inline void compute_bounding_rect_for_horizontal_spacer( int &left, int top, int &right, int bottom, QRect &outRect, bool alignOnRight ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= 3; |
|
outRect = QRect( right, top, 3, bottom - top ); |
|
right -= gHorizontalItemSpacing; |
|
} else { |
|
outRect = QRect( left, top, 3, bottom - top ); |
|
left += 3 + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
static inline void paint_permanent_icon( const QPixmap * pix, Theme::ContentItem *, |
|
QPainter * painter, int &left, int top, int &right, |
|
bool alignOnRight, int iconSize ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= iconSize; // this icon is always present |
|
if ( right < 0 ) |
|
return; |
|
painter->drawPixmap( right, top, iconSize, iconSize, *pix ); |
|
right -= gHorizontalItemSpacing; |
|
} else { |
|
if ( left > right - iconSize ) |
|
return; |
|
painter->drawPixmap( left, top, iconSize, iconSize, *pix ); |
|
left += iconSize + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
static inline void compute_bounding_rect_for_permanent_icon( Theme::ContentItem *, int &left, |
|
int top, int &right, |
|
QRect &outRect, bool alignOnRight, |
|
int iconSize ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
right -= iconSize; // this icon is always present |
|
outRect = QRect( right, top, iconSize, iconSize ); |
|
right -= gHorizontalItemSpacing; |
|
} else { |
|
outRect = QRect( left, top, iconSize, iconSize ); |
|
left += iconSize + gHorizontalItemSpacing; |
|
} |
|
} |
|
|
|
// Calculates the size for the icon, based on the size hint height. |
|
// Icons will not be bigger than 16. |
|
static inline int iconSizeFromSizeHint( int sizeHintHeight ) |
|
{ |
|
int iconSize = sizeHintHeight - 2; |
|
if ( iconSize > 16 ) |
|
iconSize = 16; |
|
return iconSize; |
|
} |
|
|
|
static inline void paint_boolean_state_icon( bool enabled, const QPixmap * pix, |
|
Theme::ContentItem * ci, QPainter * painter, int &left, |
|
int top, int &right, bool alignOnRight, |
|
int iconSize ) |
|
{ |
|
if ( enabled ) |
|
{ |
|
paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); |
|
return; |
|
} |
|
|
|
// off -> icon disabled |
|
if ( ci->hideWhenDisabled() ) |
|
return; // doesn't even take space |
|
|
|
if ( ci->softenByBlendingWhenDisabled() ) |
|
{ |
|
// still paint, but very soft |
|
qreal oldOpacity = painter->opacity(); |
|
painter->setOpacity( 0.3 ); |
|
paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); |
|
painter->setOpacity( oldOpacity ); |
|
return; |
|
} |
|
|
|
// just takes space |
|
if ( alignOnRight ) |
|
right -= iconSize + gHorizontalItemSpacing; |
|
else |
|
left += iconSize + gHorizontalItemSpacing; |
|
} |
|
|
|
static inline void compute_bounding_rect_for_boolean_state_icon( bool enabled, Theme::ContentItem * ci, |
|
int &left, int top, int &right, |
|
QRect &outRect, bool alignOnRight, |
|
int iconSize ) |
|
{ |
|
if ( ( !enabled ) && ci->hideWhenDisabled() ) |
|
{ |
|
outRect = QRect(); |
|
return; // doesn't even take space |
|
} |
|
|
|
compute_bounding_rect_for_permanent_icon( ci, left, top, right, outRect, alignOnRight, iconSize ); |
|
} |
|
|
|
static inline void paint_tag_list( QList< MessageItem::Tag * > * tagList, QPainter * painter, |
|
int &left, int top, int &right, bool alignOnRight, int iconSize ) |
|
{ |
|
if ( alignOnRight ) |
|
{ |
|
for ( QList< MessageItem::Tag * >::Iterator it = tagList->begin(); it != tagList->end(); ++it ) |
|
{ |
|
right -= iconSize; // this icon is always present |
|
if ( right < 0 ) |
|
return; |
|
painter->drawPixmap( right, top, ( *it )->pixmap() ); |
|
right -= gHorizontalItemSpacing; |
|
} |
|
} else { |
|
for ( QList< MessageItem::Tag * >::Iterator it = tagList->begin(); it != tagList->end(); ++it ) |
|
{ |
|
if ( left > right - iconSize ) |
|
return; |
|
painter->drawPixmap( left, top, ( *it )->pixmap() ); |
|
left += iconSize + gHorizontalItemSpacing; |
|
} |
|
} |
|
} |
|
|
|
static inline void compute_bounding_rect_for_tag_list( QList< MessageItem::Tag * > * tagList, |
|
int &left, int top, int &right, QRect &outRect, |
|
bool alignOnRight, int iconSize ) |
|
{ |
|
int width = tagList->count() * ( iconSize + gHorizontalItemSpacing ); |
|
if ( alignOnRight ) |
|
{ |
|
right -= width; |
|
outRect = QRect( right, top, width, iconSize ); |
|
} else { |
|
outRect = QRect( left, top, width, iconSize ); |
|
left += width; |
|
} |
|
} |
|
|
|
static inline void compute_size_hint_for_item( Theme::ContentItem * ci, QPaintDevice * pd, |
|
int &maxh, int &totalw, int iconSize ) |
|
{ |
|
if ( ci->displaysText() ) |
|
{ |
|
if ( ci->lastPaintDevice() != pd ) |
|
ci->updateFontMetrics( pd ); |
|
if ( ci->lineSpacing() > maxh ) |
|
maxh = ci->lineSpacing(); |
|
totalw += ci->displaysLongText() ? 128 : 64; |
|
return; |
|
} |
|
|
|
if ( ci->isIcon() ) |
|
{ |
|
totalw += iconSize + gHorizontalItemSpacing; |
|
return; |
|
} |
|
|
|
if ( ci->isSpacer() ) |
|
{ |
|
if ( 18 > maxh ) |
|
maxh = 18; |
|
totalw += 3 + gHorizontalItemSpacing; |
|
return; |
|
} |
|
|
|
// should never be reached |
|
if ( 18 > maxh ) |
|
maxh = 18; |
|
totalw += gHorizontalItemSpacing; |
|
} |
|
|
|
static inline void compute_size_hint_for_row( const Theme::Row * r, QPaintDevice * pd, int iconSize ) |
|
{ |
|
int maxh = 8; // at least 8 pixels for a pixmap |
|
int totalw = 0; |
|
|
|
// right aligned stuff first |
|
const QList< Theme::ContentItem * > * items = &( r->rightItems() ); |
|
QList< Theme::ContentItem * >::ConstIterator itemit; |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), pd, maxh, totalw, iconSize ); |
|
|
|
// then left aligned stuff |
|
items = &( r->leftItems() ); |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), pd, maxh, totalw, iconSize ); |
|
|
|
const_cast< Theme::Row * >( r )->setSizeHint( QSize( totalw, maxh ) ); |
|
} |
|
|
|
void ThemeDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const |
|
{ |
|
if ( !index.isValid() ) |
|
return; // bleah |
|
|
|
Item * item = itemFromIndex( index ); |
|
if ( !item ) |
|
return; // hm... |
|
|
|
QStyleOptionViewItemV4 opt = option; |
|
initStyleOption( &opt, index ); |
|
|
|
opt.text.clear(); // draw no text for me, please.. I'll do it in a while |
|
|
|
QStyle * style = mItemView->style(); |
|
style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); |
|
|
|
if ( !mTheme ) |
|
return; // hm hm... |
|
|
|
const Theme::Column * skcolumn = mTheme->column( index.column() ); |
|
if ( !skcolumn ) |
|
return; // bleah |
|
int iconSize = iconSizeFromSizeHint( skcolumn->messageSizeHint().height() ); |
|
|
|
const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... |
|
|
|
MessageItem * messageItem = 0; |
|
GroupHeaderItem * groupHeaderItem = 0; |
|
|
|
int top = opt.rect.top(); |
|
int right = opt.rect.left() + opt.rect.width(); // don't use opt.rect.right() since it's screwed |
|
int left = opt.rect.left(); |
|
|
|
// Storing the changed members one by one is faster than saving the painter state |
|
QFont oldFont = painter->font(); |
|
QPen oldPen = painter->pen(); |
|
qreal oldOpacity = painter->opacity(); |
|
|
|
QPen defaultPen; |
|
bool usingNonDefaultTextColor = false; |
|
|
|
switch ( item->type() ) |
|
{ |
|
case Item::Message: |
|
{ |
|
rows = &( skcolumn->messageRows() ); |
|
messageItem = static_cast< MessageItem * >( item ); |
|
|
|
|
|
if ( |
|
( ! ( opt.state & QStyle::State_Enabled ) ) || |
|
messageItem->aboutToBeRemoved() || |
|
( ! messageItem->isValid() ) |
|
) |
|
{ |
|
painter->setOpacity( 0.5 ); |
|
defaultPen = QPen( opt.palette.brush( QPalette::Disabled, QPalette::Text ), 0 ); |
|
} else { |
|
|
|
QPalette::ColorGroup cg; |
|
|
|
if ( opt.state & QStyle::State_Active ) |
|
cg = QPalette::Normal; |
|
else |
|
cg = QPalette::Inactive; |
|
|
|
if ( opt.state & QStyle::State_Selected ) |
|
{ |
|
defaultPen = QPen( opt.palette.brush( cg, QPalette::HighlightedText ), 0 ); |
|
} else { |
|
if ( messageItem->textColor().isValid() ) |
|
{ |
|
usingNonDefaultTextColor = true; |
|
defaultPen = QPen( messageItem->textColor(), 0 ); |
|
} else { |
|
defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); |
|
} |
|
} |
|
} |
|
|
|
top += gMessageVerticalMargin; |
|
right -= gMessageHorizontalMargin; |
|
left += gMessageHorizontalMargin; |
|
} |
|
break; |
|
case Item::GroupHeader: |
|
{ |
|
rows = &( skcolumn->groupHeaderRows() ); |
|
groupHeaderItem = static_cast< GroupHeaderItem * >( item ); |
|
|
|
QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; |
|
|
|
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) |
|
cg = QPalette::Inactive; |
|
|
|
QPalette::ColorRole cr; |
|
|
|
top += gGroupHeaderOuterVerticalMargin; |
|
right -= gGroupHeaderOuterHorizontalMargin; |
|
left += gGroupHeaderOuterHorizontalMargin; |
|
|
|
switch ( mTheme->groupHeaderBackgroundMode() ) |
|
{ |
|
case Theme::Transparent: |
|
cr = ( opt.state & QStyle::State_Selected ) ? QPalette::HighlightedText : QPalette::Text; |
|
defaultPen = QPen( opt.palette.brush( cg, cr ), 0 ); |
|
break; |
|
case Theme::AutoColor: |
|
case Theme::CustomColor: |
|
switch ( mTheme->groupHeaderBackgroundStyle() ) |
|
{ |
|
case Theme::PlainRect: |
|
{ |
|
painter->fillRect( |
|
QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( mGroupHeaderBackgroundColor ) |
|
); |
|
} |
|
break; |
|
case Theme::PlainJoinedRect: |
|
{ |
|
int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); |
|
int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); |
|
painter->fillRect( |
|
QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( mGroupHeaderBackgroundColor ) |
|
); |
|
} |
|
break; |
|
case Theme::RoundedJoinedRect: |
|
{ |
|
if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( mGroupHeaderBackgroundColor ) |
|
); |
|
break; // don't fall through |
|
} |
|
if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( mGroupHeaderBackgroundColor ) |
|
); |
|
} else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( mGroupHeaderBackgroundColor ) |
|
); |
|
} |
|
// fall through anyway |
|
} |
|
case Theme::RoundedRect: |
|
{ |
|
painter->setPen( Qt::NoPen ); |
|
bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; |
|
if ( !hadAntialiasing ) |
|
painter->setRenderHint( QPainter::Antialiasing, true ); |
|
painter->setBrush( QBrush( mGroupHeaderBackgroundColor ) ); |
|
painter->setBackgroundMode( Qt::OpaqueMode ); |
|
int w = right - left; |
|
if ( w > 0 ) |
|
painter->drawRoundedRect( |
|
QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
4.0, 4.0 |
|
); |
|
if ( !hadAntialiasing ) |
|
painter->setRenderHint( QPainter::Antialiasing, false ); |
|
painter->setBackgroundMode( Qt::TransparentMode ); |
|
} |
|
break; |
|
case Theme::GradientJoinedRect: |
|
{ |
|
// FIXME: Could cache this brush |
|
QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); |
|
gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); |
|
gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); |
|
if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( gradient ) |
|
); |
|
break; // don't fall through |
|
} |
|
if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( gradient ) |
|
); |
|
} else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) |
|
{ |
|
painter->fillRect( |
|
QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
QBrush( gradient ) |
|
); |
|
} |
|
// fall through anyway |
|
} |
|
case Theme::GradientRect: |
|
{ |
|
// FIXME: Could cache this brush |
|
QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); |
|
gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); |
|
gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); |
|
painter->setPen( Qt::NoPen ); |
|
bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; |
|
if ( !hadAntialiasing ) |
|
painter->setRenderHint( QPainter::Antialiasing, true ); |
|
painter->setBrush( QBrush( gradient ) ); |
|
painter->setBackgroundMode( Qt::OpaqueMode ); |
|
int w = right - left; |
|
if ( w > 0 ) |
|
painter->drawRoundedRect( |
|
QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), |
|
4.0, 4.0 |
|
); |
|
if ( !hadAntialiasing ) |
|
painter->setRenderHint( QPainter::Antialiasing, false ); |
|
painter->setBackgroundMode( Qt::TransparentMode ); |
|
} |
|
break; |
|
case Theme::StyledRect: |
|
{ |
|
// oxygen, for instance, has a nice graphics for selected items |
|
opt.rect = QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); |
|
opt.state |= QStyle::State_Selected; |
|
opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; |
|
opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); |
|
style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); |
|
} |
|
break; |
|
case Theme::StyledJoinedRect: |
|
{ |
|
int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); |
|
int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); |
|
opt.rect = QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); |
|
opt.state |= QStyle::State_Selected; |
|
opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); |
|
style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); |
|
} |
|
break; |
|
} |
|
|
|
defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); |
|
break; |
|
} |
|
top += gGroupHeaderInnerVerticalMargin; |
|
right -= gGroupHeaderInnerHorizontalMargin; |
|
left += gGroupHeaderInnerHorizontalMargin; |
|
} |
|
break; |
|
default: |
|
Q_ASSERT( false ); |
|
return; // bug |
|
break; |
|
} |
|
|
|
Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); |
|
|
|
for ( QList< Theme::Row * >::ConstIterator rowit = rows->begin(); rowit != rows->end(); ++rowit ) |
|
{ |
|
QSize rowSizeHint = ( *rowit )->sizeHint(); |
|
if ( !rowSizeHint.isValid() ) |
|
{ |
|
compute_size_hint_for_row( ( *rowit ), mPaintDevice, iconSize ); |
|
rowSizeHint = ( *rowit )->sizeHint(); |
|
} |
|
|
|
int bottom = top + rowSizeHint.height(); |
|
|
|
// paint right aligned stuff first |
|
const QList< Theme::ContentItem * > * items = &( ( *rowit )->rightItems() ); |
|
QList< Theme::ContentItem * >::ConstIterator itemit; |
|
|
|
int r = right; |
|
int l = left; |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
{ |
|
Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); |
|
|
|
if ( ci->canUseCustomColor() ) |
|
{ |
|
if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) |
|
{ |
|
if ( usingNonDefaultTextColor ) |
|
{ |
|
// merge the colors |
|
QColor nonDefault = defaultPen.color(); |
|
QColor custom = ci->customColor(); |
|
QColor merged( |
|
( nonDefault.red() + custom.red() ) >> 1, |
|
( nonDefault.green() + custom.green() ) >> 1, |
|
( nonDefault.blue() + custom.blue() ) >> 1 |
|
); |
|
painter->setPen( QPen( merged ) ); |
|
} else { |
|
painter->setPen( QPen( ci->customColor() ) ); |
|
} |
|
} else |
|
painter->setPen( defaultPen ); |
|
} // otherwise setting a pen is useless at this time |
|
|
|
switch ( ci->type() ) |
|
{ |
|
case Theme::ContentItem::Subject: |
|
paint_right_aligned_elided_text( item->subject(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::SenderOrReceiver: |
|
paint_right_aligned_elided_text( item->senderOrReceiver(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Receiver: |
|
paint_right_aligned_elided_text( item->receiver(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Sender: |
|
paint_right_aligned_elided_text( item->sender(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Date: |
|
paint_right_aligned_elided_text( item->formattedDate(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::MostRecentDate: |
|
paint_right_aligned_elided_text( item->formattedMaxDate(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Size: |
|
paint_right_aligned_elided_text( item->formattedSize(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::GroupHeaderLabel: |
|
if ( groupHeaderItem ) |
|
paint_right_aligned_elided_text( groupHeaderItem->label(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::ReadStateIcon: |
|
paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, |
|
layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::CombinedReadRepliedStateIcon: |
|
if ( messageItem ) |
|
paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, |
|
l, top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ExpandedStateIcon: |
|
{ |
|
const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), |
|
ci, painter, l, top, r, layoutDir == Qt::LeftToRight, |
|
iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::RepliedStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_replied_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), |
|
ci, painter, l, top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::EncryptionStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); |
|
paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, |
|
layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SignatureStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); |
|
paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, |
|
layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SpamHamStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_spam_ham_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), |
|
ci, painter, l, top, r, layoutDir == Qt::LeftToRight, |
|
iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::WatchedIgnoredStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), |
|
ci, painter, l, top, r, layoutDir == Qt::LeftToRight, |
|
iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::AttachmentStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().hasAttachment(), |
|
Manager::instance()->pixmapMessageAttachment(), ci, painter, |
|
l, top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ActionItemStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().isToAct(), |
|
Manager::instance()->pixmapMessageActionItem(), ci, painter, |
|
l, top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ImportantStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().isImportant(), |
|
Manager::instance()->pixmapMessageImportant(), ci, painter, l, |
|
top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::VerticalLine: |
|
paint_vertical_line( painter, l, top, r, bottom, layoutDir == Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::HorizontalSpacer: |
|
paint_horizontal_spacer( l, top, r, bottom, layoutDir == Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::TagList: |
|
if ( messageItem ) |
|
{ |
|
QList< MessageItem::Tag * > * tagList = messageItem->tagList(); |
|
if ( tagList ) |
|
paint_tag_list( tagList, painter, l, top, r, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
// then paint left aligned stuff |
|
items = &( ( *rowit )->leftItems() ); |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
{ |
|
Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); |
|
|
|
if ( ci->canUseCustomColor() ) |
|
{ |
|
if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) |
|
{ |
|
if ( usingNonDefaultTextColor ) |
|
{ |
|
// merge the colors |
|
QColor nonDefault = defaultPen.color(); |
|
QColor custom = ci->customColor(); |
|
QColor merged( |
|
( nonDefault.red() + custom.red() ) >> 1, |
|
( nonDefault.green() + custom.green() ) >> 1, |
|
( nonDefault.blue() + custom.blue() ) >> 1 |
|
); |
|
painter->setPen( QPen( merged ) ); |
|
} else { |
|
painter->setPen( QPen( ci->customColor() ) ); |
|
} |
|
} else { |
|
painter->setPen( defaultPen ); |
|
} |
|
} // otherwise setting a pen is useless at this time |
|
|
|
switch ( ci->type() ) |
|
{ |
|
case Theme::ContentItem::Subject: |
|
paint_left_aligned_elided_text( item->subject(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::SenderOrReceiver: |
|
paint_left_aligned_elided_text( item->senderOrReceiver(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Receiver: |
|
paint_left_aligned_elided_text( item->receiver(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Sender: |
|
paint_left_aligned_elided_text( item->sender(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Date: |
|
paint_left_aligned_elided_text( item->formattedDate(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::MostRecentDate: |
|
paint_left_aligned_elided_text( item->formattedMaxDate(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Size: |
|
paint_left_aligned_elided_text( item->formattedSize(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::GroupHeaderLabel: |
|
if ( groupHeaderItem ) |
|
paint_left_aligned_elided_text( groupHeaderItem->label(), mPaintDevice, ci, painter, l, top, r, layoutDir ); |
|
break; |
|
case Theme::ContentItem::ReadStateIcon: |
|
paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, |
|
layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::CombinedReadRepliedStateIcon: |
|
if ( messageItem ) |
|
paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, |
|
l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ExpandedStateIcon: |
|
{ |
|
const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), |
|
ci, painter, l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::RepliedStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_replied_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), |
|
ci, painter, l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::EncryptionStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); |
|
paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, |
|
layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SignatureStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); |
|
paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, |
|
layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SpamHamStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_spam_ham_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), |
|
ci, painter, l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::WatchedIgnoredStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); |
|
paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), |
|
ci, painter, l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::AttachmentStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().hasAttachment(), |
|
Manager::instance()->pixmapMessageAttachment(), ci, painter, |
|
l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ActionItemStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().isToAct(), |
|
Manager::instance()->pixmapMessageActionItem(), ci, painter, |
|
l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ImportantStateIcon: |
|
if ( messageItem ) |
|
paint_boolean_state_icon( messageItem->status().isImportant(), |
|
Manager::instance()->pixmapMessageImportant(), ci, painter, l, |
|
top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::VerticalLine: |
|
paint_vertical_line( painter, l, top, r, bottom, layoutDir != Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::HorizontalSpacer: |
|
paint_horizontal_spacer( l, top, r, bottom, layoutDir != Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::TagList: |
|
if ( messageItem ) |
|
{ |
|
QList< MessageItem::Tag * > * tagList = messageItem->tagList(); |
|
if ( tagList ) |
|
paint_tag_list( tagList, painter, l, top, r, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
top = bottom; |
|
} |
|
|
|
painter->setFont( oldFont ); |
|
painter->setPen( oldPen ); |
|
painter->setOpacity( oldOpacity ); |
|
} |
|
|
|
bool ThemeDelegate::hitTest( const QPoint &viewportPoint, bool exact ) |
|
{ |
|
if ( !mTheme ) |
|
return false; // hm hm... |
|
|
|
mHitIndex = mItemView->indexAt( viewportPoint ); |
|
|
|
if ( !mHitIndex.isValid() ) |
|
return false; // bleah |
|
|
|
mHitItem = itemFromIndex( mHitIndex ); |
|
if ( !mHitItem ) |
|
return false; // hm... |
|
|
|
mHitItemRect = mItemView->visualRect( mHitIndex ); |
|
|
|
mHitColumn = mTheme->column( mHitIndex.column() ); |
|
if ( !mHitColumn ) |
|
return false; // bleah |
|
int iconSize = iconSizeFromSizeHint( mHitColumn->messageSizeHint().height() ); |
|
const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... |
|
|
|
MessageItem * messageItem = 0; |
|
GroupHeaderItem * groupHeaderItem = 0; |
|
|
|
int top = mHitItemRect.top(); |
|
int right = mHitItemRect.right(); |
|
int left = mHitItemRect.left(); |
|
|
|
mHitRow = 0; |
|
mHitRowIndex = -1; |
|
mHitContentItem = 0; |
|
|
|
switch ( mHitItem->type() ) |
|
{ |
|
case Item::Message: |
|
mHitRowIsMessageRow = true; |
|
rows = &( mHitColumn->messageRows() ); |
|
messageItem = static_cast< MessageItem * >( mHitItem ); |
|
// FIXME: paint eventual background here |
|
|
|
top += gMessageVerticalMargin; |
|
right -= gMessageHorizontalMargin; |
|
left += gMessageHorizontalMargin; |
|
break; |
|
case Item::GroupHeader: |
|
mHitRowIsMessageRow = false; |
|
rows = &( mHitColumn->groupHeaderRows() ); |
|
groupHeaderItem = static_cast< GroupHeaderItem * >( mHitItem ); |
|
|
|
top += gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin; |
|
right -= gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; |
|
left += gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; |
|
break; |
|
default: |
|
return false; // bug |
|
break; |
|
} |
|
|
|
int rowIdx = 0; |
|
int bestInexactDistance = 0xffffff; |
|
bool bestInexactItemRight = false; |
|
QRect bestInexactRect; |
|
const Theme::ContentItem * bestInexactContentItem = 0; |
|
|
|
Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); |
|
|
|
for ( QList< Theme::Row * >::ConstIterator rowit = rows->begin(); rowit != rows->end(); ++rowit ) |
|
{ |
|
QSize rowSizeHint = ( *rowit )->sizeHint(); |
|
if ( !rowSizeHint.isValid() ) |
|
{ |
|
compute_size_hint_for_row( ( *rowit ), mPaintDevice, iconSize ); |
|
rowSizeHint = ( *rowit )->sizeHint(); |
|
} |
|
|
|
if ( ( viewportPoint.y() < top ) && ( rowIdx > 0 ) ) |
|
break; // not this row (tough we should have already found it... probably clicked upper margin) |
|
|
|
int bottom = top + rowSizeHint.height(); |
|
|
|
if ( viewportPoint.y() > bottom ) |
|
{ |
|
top += rowSizeHint.height(); |
|
rowIdx++; |
|
continue; // not this row |
|
} |
|
|
|
bestInexactItemRight = false; |
|
bestInexactDistance = 0xffffff; |
|
bestInexactContentItem = 0; |
|
|
|
// this row! |
|
mHitRow = *rowit; |
|
mHitRowIndex = rowIdx; |
|
mHitRowRect = QRect( left, top, right - left, bottom - top ); |
|
|
|
// check right aligned stuff first |
|
const QList< Theme::ContentItem * > * items = &( mHitRow->rightItems() ); |
|
QList< Theme::ContentItem * >::ConstIterator itemit; |
|
|
|
mHitContentItemRight = true; |
|
|
|
int r = right; |
|
int l = left; |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
{ |
|
Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); |
|
|
|
mHitContentItemRect = QRect(); |
|
|
|
switch ( ci->type() ) |
|
{ |
|
case Theme::ContentItem::Subject: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->subject(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::SenderOrReceiver: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->senderOrReceiver(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Receiver: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->receiver(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Sender: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->sender(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Date: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedDate(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::MostRecentDate: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedMaxDate(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Size: |
|
compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedSize(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::GroupHeaderLabel: |
|
if ( groupHeaderItem ) |
|
compute_bounding_rect_for_right_aligned_elided_text( groupHeaderItem->label(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::ReadStateIcon: |
|
compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::CombinedReadRepliedStateIcon: |
|
compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ExpandedStateIcon: |
|
compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::RepliedStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_replied_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::EncryptionStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
get_encryption_state_icon( messageItem, &enabled ); |
|
compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SignatureStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
get_signature_state_icon( messageItem, &enabled ); |
|
compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SpamHamStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_spam_ham_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::WatchedIgnoredStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::AttachmentStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ActionItemStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ImportantStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::VerticalLine: |
|
compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::HorizontalSpacer: |
|
compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::TagList: |
|
if ( messageItem ) |
|
{ |
|
QList< MessageItem::Tag * > * tagList = messageItem->tagList(); |
|
if ( tagList ) |
|
compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
} |
|
|
|
if ( mHitContentItemRect.isValid() ) |
|
{ |
|
if ( mHitContentItemRect.contains( viewportPoint ) ) |
|
{ |
|
// caught! |
|
mHitContentItem = ci; |
|
return true; |
|
} |
|
if ( !exact ) |
|
{ |
|
QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); |
|
if ( inexactRect.contains( viewportPoint ) ) |
|
{ |
|
mHitContentItem = ci; |
|
return true; |
|
} |
|
|
|
int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); |
|
if ( inexactDistance < bestInexactDistance ) |
|
{ |
|
bestInexactDistance = inexactDistance; |
|
bestInexactRect = mHitContentItemRect; |
|
bestInexactItemRight = true; |
|
bestInexactContentItem = ci; |
|
} |
|
} |
|
} |
|
} |
|
|
|
// then check left aligned stuff |
|
items = &( mHitRow->leftItems() ); |
|
|
|
mHitContentItemRight = false; |
|
|
|
for ( itemit = items->begin(); itemit != items->end() ; ++itemit ) |
|
{ |
|
Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); |
|
|
|
mHitContentItemRect = QRect(); |
|
|
|
switch ( ci->type() ) |
|
{ |
|
case Theme::ContentItem::Subject: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->subject(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::SenderOrReceiver: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->senderOrReceiver(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Receiver: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->receiver(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Sender: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->sender(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Date: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedDate(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::MostRecentDate: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedMaxDate(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::Size: |
|
compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedSize(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::GroupHeaderLabel: |
|
if ( groupHeaderItem ) |
|
compute_bounding_rect_for_left_aligned_elided_text( groupHeaderItem->label(), mPaintDevice, ci, l, top, r, mHitContentItemRect, layoutDir ); |
|
break; |
|
case Theme::ContentItem::ReadStateIcon: |
|
compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::CombinedReadRepliedStateIcon: |
|
compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ExpandedStateIcon: |
|
compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::RepliedStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_replied_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::EncryptionStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
get_encryption_state_icon( messageItem, &enabled ); |
|
compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SignatureStateIcon: |
|
if ( messageItem ) |
|
{ |
|
bool enabled; |
|
get_signature_state_icon( messageItem, &enabled ); |
|
compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::SpamHamStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_spam_ham_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::WatchedIgnoredStateIcon: |
|
if ( messageItem ) |
|
{ |
|
const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); |
|
compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
case Theme::ContentItem::AttachmentStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ActionItemStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::ImportantStateIcon: |
|
if ( messageItem ) |
|
compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
break; |
|
case Theme::ContentItem::VerticalLine: |
|
compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::HorizontalSpacer: |
|
compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); |
|
break; |
|
case Theme::ContentItem::TagList: |
|
if ( messageItem ) |
|
{ |
|
QList< MessageItem::Tag * > * tagList = messageItem->tagList(); |
|
if ( tagList ) |
|
compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, iconSize ); |
|
} |
|
break; |
|
} |
|
|
|
if ( mHitContentItemRect.isValid() ) |
|
{ |
|
if ( mHitContentItemRect.contains( viewportPoint ) ) |
|
{ |
|
// caught! |
|
mHitContentItem = ci; |
|
return true; |
|
} |
|
if ( !exact ) |
|
{ |
|
QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); |
|
if ( inexactRect.contains( viewportPoint ) ) |
|
{ |
|
mHitContentItem = ci; |
|
return true; |
|
} |
|
|
|
int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); |
|
if ( inexactDistance < bestInexactDistance ) |
|
{ |
|
bestInexactDistance = inexactDistance; |
|
bestInexactRect = mHitContentItemRect; |
|
bestInexactItemRight = false; |
|
bestInexactContentItem = ci; |
|
} |
|
} |
|
} |
|
} |
|
|
|
top += rowSizeHint.height(); |
|
rowIdx++; |
|
} |
|
|
|
mHitContentItem = bestInexactContentItem; |
|
mHitContentItemRight = bestInexactItemRight; |
|
mHitContentItemRect = bestInexactRect; |
|
return true; |
|
} |
|
|
|
QSize ThemeDelegate::sizeHintForItemTypeAndColumn( Item::Type type, int column ) const |
|
{ |
|
if ( !mTheme ) |
|
return QSize( 16, 16 ); // bleah |
|
|
|
const Theme::Column * skcolumn = mTheme->column( column ); |
|
if ( !skcolumn ) |
|
return QSize( 16, 16 ); // bleah |
|
|
|
const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... |
|
|
|
// The sizeHint() is layout direction independent. |
|
|
|
int marginw; |
|
int marginh; |
|
|
|
switch ( type ) |
|
{ |
|
case Item::Message: |
|
{ |
|
QSize cached = skcolumn->messageSizeHint(); |
|
if ( cached.isValid() ) |
|
return cached; |
|
rows = &( skcolumn->messageRows() ); |
|
|
|
marginh = gMessageVerticalMargin << 1; |
|
marginw = gMessageHorizontalMargin << 1; |
|
} |
|
break; |
|
case Item::GroupHeader: |
|
{ |
|
QSize cached = skcolumn->groupHeaderSizeHint(); |
|
if ( cached.isValid() ) |
|
return cached; |
|
rows = &( skcolumn->groupHeaderRows() ); |
|
|
|
marginh = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; |
|
marginw = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; |
|
} |
|
break; |
|
default: |
|
return QSize( 16, 16 ); // bug |
|
break; |
|
} |
|
|
|
int totalh = 0; |
|
int maxw = 0; |
|
|
|
for ( QList< Theme::Row * >::ConstIterator rowit = rows->begin(); rowit != rows->end(); ++rowit ) |
|
{ |
|
int iconSize = iconSizeFromSizeHint( skcolumn->messageSizeHint().height() ); |
|
compute_size_hint_for_row( *rowit, mPaintDevice, iconSize ); |
|
|
|
QSize sh = ( *rowit )->sizeHint(); |
|
totalh += sh.height(); |
|
if ( sh.width() > maxw ) |
|
maxw = sh.width(); |
|
} |
|
|
|
QSize ret( maxw + marginw , totalh + marginh ); |
|
|
|
// cache it |
|
switch ( type ) |
|
{ |
|
case Item::Message: |
|
const_cast< Theme::Column * >( skcolumn )->setMessageSizeHint( ret ); |
|
break; |
|
case Item::GroupHeader: |
|
const_cast< Theme::Column * >( skcolumn )->setGroupHeaderSizeHint( ret ); |
|
break; |
|
default: |
|
// make gcc happy |
|
break; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
|
|
QSize ThemeDelegate::sizeHint( const QStyleOptionViewItem &, const QModelIndex & index ) const |
|
{ |
|
if ( !mTheme ) |
|
return QSize( 16, 16 ); // hm hm... |
|
|
|
if ( !index.isValid() ) |
|
return QSize( 16, 16 ); // bleah |
|
|
|
Item * item = itemFromIndex( index ); |
|
if ( !item ) |
|
return QSize( 16, 16 ); // hm... |
|
|
|
//Item::Type type = item->type(); |
|
|
|
return sizeHintForItemTypeAndColumn( item->type(), index.column() ); |
|
} |
|
|
|
} // namespace Core |
|
|
|
} // namespace MessageListView |
|
|
|
} // namespace KMail |
|
|
|
|