23 #include <QStyleOptionViewItem>
24 #include <QModelIndex>
25 #include <QAbstractItemView>
26 #include <QApplication>
31 #include <qimageblitz.h>
33 #include <KIconLoader>
35 #include "kopetemetacontact.h"
36 #include "kopetecontact.h"
37 #include "kopeteappearancesettings.h"
56 if ( Kopete::AppearanceSettings::self()->contactListUseCustomFont() )
57 return Kopete::AppearanceSettings::self()->contactListNormalFont();
64 if ( Kopete::AppearanceSettings::self()->contactListUseCustomFont() )
65 return Kopete::AppearanceSettings::self()->contactListSmallFont();
67 QFont font( naturalFont );
68 if ( font.pixelSize() != -1 )
69 font.setPixelSize( (font.pixelSize() * 3) / 4 );
71 font.setPointSizeF( font.pointSizeF() * 0.75 );
86 for (
int i = 0; i < rowCount; i++ )
87 height += calculateRowHeight( layout.
layout().
row( i ), normal, small );
90 return QSize( 120, height );
94 return QStyledItemDelegate::sizeHint( option, index );
102 QList< QPair<QRect, Kopete::Contact*> > contactPositionList;
103 paintItem( layout.
layout(), 0, option, index, &contactPositionList );
105 QPoint delegatePoint = point - option.rect.topLeft();
106 for (
int i = 0; i < contactPositionList.size(); ++i )
108 if ( contactPositionList.at(i).first.contains( delegatePoint ) )
109 return contactPositionList.at(i).second;
117 if ( !event || !view )
120 if ( event->type() == QEvent::ToolTip )
122 Kopete::Contact* contact =
contactAt( option, index, event->pos() );
125 QToolTip::showText( event->globalPos(), contact->toolTip(), view );
129 QVariant tooltip = index.data( Qt::ToolTipRole );
130 if ( qVariantCanConvert<QString>(tooltip) )
132 QToolTip::showText( event->globalPos(), tooltip.toString(), view );
138 return QStyledItemDelegate::helpEvent(event, view, option, index);
142 const QStyleOptionViewItem& option,
143 const QModelIndex& index )
const
147 QStyleOptionViewItem opt = option;
156 QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
158 painter->translate( option.rect.topLeft() );
160 QPalette::ColorGroup cg = QPalette::Active;
161 if (!(option.state & QStyle::State_Enabled))
162 cg = QPalette::Disabled;
163 else if (!(option.state & QStyle::State_Active))
164 cg = QPalette::Inactive;
167 painter->setPen( Kopete::AppearanceSettings::self()->idleContactColor() );
168 else if ( option.state & QStyle::State_Selected )
169 painter->setPen( option.palette.color( cg, QPalette::HighlightedText ) );
171 painter->setPen( option.palette.color( cg, QPalette::Text ) );
173 paintItem( layout.
layout(), painter, option, index, 0 );
179 QColor gc( Kopete::AppearanceSettings::self()->groupNameColor() );
180 opt.palette.setColor( QPalette::Text, gc );
181 QStyledItemDelegate::paint( painter, opt, index );
185 QStyledItemDelegate::paint( painter, opt, index );
189 QList<Kopete::Contact*> KopeteItemDelegate::filterContacts(
const QList<Kopete::Contact*> contacts )
const
191 if ( Kopete::AppearanceSettings::self()->showOfflineUsers() ||
192 Kopete::AppearanceSettings::self()->showOfflineGrouped() )
195 QAbstractItemView* itemView = qobject_cast<QAbstractItemView*>(parent());
199 if ( proxyModel && !proxyModel->filterRegExp().isEmpty() )
203 QList<Kopete::Contact*> filtered;
205 foreach( Kopete::Contact *contact, contacts )
207 if ( contact->isOnline() )
215 const QStyleOptionViewItem& option,
const QModelIndex& index,
216 QList<QPair<QRect, Kopete::Contact*> >* contactPositionList )
const
218 int rowCount = config.
rows();
222 const int hBorderMargin =
MARGIN * 2;
230 int imageSize = option.rect.height() - hBorderMargin;
234 QRectF nominalImageRect( rowOffsetX, rowOffsetY, imageSize, imageSize );
236 QVariant metaContactPicture;
238 metaContactPicture = QString::fromUtf8(
"mail-unread" );
242 if ( metaContactPicture.type() == QVariant::Image )
245 QImage metaContactImage = metaContactPicture.value<QImage>();
246 if ( !metaContactImage.isNull() )
248 metaContactImage = metaContactImage.scaled( imageSize, imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
251 if ( metaContactStatus == Kopete::OnlineStatus::Offline )
252 Blitz::grayscale( metaContactImage );
254 switch ( metaContactStatus )
256 case Kopete::OnlineStatus::Online:
258 case Kopete::OnlineStatus::Away:
259 case Kopete::OnlineStatus::Busy:
260 Blitz::fade( metaContactImage, 0.5, Qt::white );
262 case Kopete::OnlineStatus::Offline:
263 Blitz::fade( metaContactImage, 0.4, Qt::white );
265 case Kopete::OnlineStatus::Unknown:
267 Blitz::fade( metaContactImage, 0.8, Qt::white );
271 bool roundedIcons = Kopete::AppearanceSettings::self()->contactListIconRounded();
274 photoPixmap = QPixmap( metaContactImage.width(), metaContactImage.height() );
275 photoPixmap.fill( Qt::transparent );
276 QPainter p( &photoPixmap );
277 p.setRenderHint( QPainter::Antialiasing );
278 p.setPen( Qt::NoPen );
279 p.setBrush( QBrush( metaContactImage ) );
280 QRectF rectangle( 0.5, 0.5, photoPixmap.width()-1, photoPixmap.height()-1 );
281 p.drawRoundedRect( rectangle, 25, 25, Qt::RelativeSize );
285 photoPixmap = QPixmap::fromImage( metaContactImage );
288 if ( Kopete::AppearanceSettings::self()->contactListIconBorders() )
290 QPainter p( &photoPixmap );
291 p.setPen( Qt::black );
295 p.setRenderHint( QPainter::Antialiasing );
296 QRectF rectangle( 0.5, 0.5, photoPixmap.width()-1, photoPixmap.height()-1 );
297 p.drawRoundedRect( rectangle, 25, 25, Qt::RelativeSize );
301 p.drawRect( 0, 0, photoPixmap.width()-1, photoPixmap.height()-1 );
305 QPointF offset = centerImage( photoPixmap, nominalImageRect );
306 QRectF imageRect( nominalImageRect.x() + offset.x(),
307 nominalImageRect.y() + offset.y(),
308 nominalImageRect.width() - offset.x() * 2,
309 nominalImageRect.height() - offset.y() * 2 );
311 painter->drawPixmap( imageRect.topLeft(), photoPixmap );
317 QString metaContactImageName = metaContactPicture.value<QString>();
318 QPixmap metaContactImage = SmallIcon( metaContactImageName, imageSize );
319 if ( !metaContactImage.isNull() )
322 QPointF offset = centerImage( metaContactImage, nominalImageRect );
323 QRectF imageRect( nominalImageRect.x() + offset.x(),
324 nominalImageRect.y() + offset.y(),
325 nominalImageRect.width() - offset.x() * 2,
326 nominalImageRect.height() - offset.y() * 2 );
328 painter->drawPixmap( imageRect.topLeft(), metaContactImage );
333 rowOffsetX += imageSize +
MARGINH;
341 QList<Kopete::Contact*> contactList = filterContacts( metaContact->contacts() );
343 for (
int i = 0; i < rowCount; i++ )
346 const int rowHeight = calculateRowHeight( row, normal, small );
347 qreal itemOffsetX = rowOffsetX;
348 const int elementCount = row.
count();
349 qreal rowWidth = option.rect.width() - ( rowOffsetX +
MARGIN );
351 QRectF rowBox( itemOffsetX, rowOffsetY, rowWidth, rowHeight );
352 int currentItemX = itemOffsetX;
354 const qreal IconMarginH = 2.0;
355 const qreal IconMarginV = 1.0;
356 const qreal IconSize = rowHeight - 2 * IconMarginV;
358 QVector<DynamicLayoutItem> dynamicLayoutData( elementCount );
359 bool hasFixedTypeItem =
false;
362 for (
int j = 0; j < elementCount; ++j )
365 const int value = element.
value();
366 DynamicLayoutItem& dlItem = dynamicLayoutData[j];
371 dlItem.font = QFont( ( element.
small() ) ? small : normal );
372 dlItem.font.setBold( element.
bold() );
373 dlItem.font.setItalic( element.
italic() );
376 QString text = ( role > -1 ) ? index.data( role ).toString() : QString();
377 dlItem.text = element.
prefix() + text + element.
suffix();
382 qreal idealWidth = 0;
385 const int contactListSize = contactList.size();
386 idealWidth = contactListSize * IconSize;
387 if ( contactListSize > 1 )
388 idealWidth += (contactListSize - 1) * IconMarginH;
390 hasFixedTypeItem =
true;
391 dlItem.type = LayoutFixed;
395 dlItem.type = LayoutNormal;
399 QFontMetricsF fm( dlItem.font );
400 idealWidth = fm.width( dlItem.text );
401 dlItem.type = LayoutNormal;
404 if ( element.
size() >= 0.001 )
406 const qreal maxWidth = rowWidth * element.
size();
407 if ( maxWidth < idealWidth)
408 idealWidth = maxWidth;
410 dlItem.width = idealWidth;
414 if ( element.
size() >= 0.001 )
416 dlItem.type = LayoutNormal;
417 dlItem.width = rowWidth * element.
size();
421 dlItem.type = LayoutAuto;
428 qreal availableWidth = rowWidth;
429 if ( hasFixedTypeItem )
431 for (
int j = 0; j < elementCount; ++j )
433 DynamicLayoutItem& dlItem = dynamicLayoutData[j];
434 if ( dlItem.type == LayoutFixed )
436 availableWidth -= dlItem.width;
437 dlItem.dirty =
false;
438 if ( availableWidth < 0 )
440 dlItem.width += availableWidth;
449 int layoutAutoItemCount = 0;
450 if ( availableWidth > 0 )
452 for (
int j = 0; j < elementCount; ++j )
454 DynamicLayoutItem& dlItem = dynamicLayoutData[j];
455 if ( dlItem.type == LayoutAuto )
457 layoutAutoItemCount++;
459 else if ( dlItem.dirty )
461 dlItem.dirty =
false;
462 availableWidth -= dlItem.width;
463 if ( availableWidth < 0 )
465 dlItem.width += availableWidth;
473 const qreal layoutAutoItemWidth = ( layoutAutoItemCount > 0 ) ? (availableWidth / (qreal)layoutAutoItemCount) : 0;
474 for (
int j = 0; j < elementCount; ++j )
477 DynamicLayoutItem& dlItem = dynamicLayoutData[j];
480 if ( availableWidth > 0 )
481 dlItem.width = layoutAutoItemWidth;
486 qreal itemWidth = dlItem.width;
491 const int value = element.
value();
493 const int alignment = element.
alignment();
496 painter->setFont( dlItem.font );
501 if ( contactList.size() > 0 )
503 const qreal IconMarginH = 2.0;
504 const qreal IconMarginV = 1.0;
505 const qreal IconSize = rowHeight - 2 * IconMarginV;
506 qreal iconsWidth = contactList.size() * IconSize;
507 if ( contactList.size() > 1 )
508 iconsWidth += (contactList.size() - 1) * IconMarginH;
510 if (iconsWidth > itemWidth)
511 iconsWidth = itemWidth;
513 QRectF drawingRect( currentItemX, rowOffsetY + IconMarginV, iconsWidth, IconSize );
514 if ( (alignment & Qt::AlignRight) == Qt::AlignRight )
515 drawingRect.moveRight( currentItemX + itemWidth );
516 else if ( (alignment & Qt::AlignHCenter) == Qt::AlignHCenter )
517 drawingRect.moveLeft( currentItemX + (itemWidth - iconsWidth) / 2.0 );
520 foreach ( Kopete::Contact *contact, contactList )
522 QIcon contactIcon = contact->onlineStatus().iconFor( contact );
523 if ( contactIcon.isNull() )
526 QRectF pixmapRect( drawingRect.x() + offsetX, drawingRect.y(),
527 IconSize, IconSize );
529 if ( contactPositionList )
530 contactPositionList->append( QPair<QRect, Kopete::Contact*>( pixmapRect.toRect(), contact ) );
534 QPixmap contactPixmap = contactIcon.pixmap( IconSize, IconSize );
535 painter->setClipRect( pixmapRect.intersected( drawingRect ) );
536 painter->drawPixmap( pixmapRect.topLeft(), contactPixmap );
539 offsetX += IconSize + IconMarginH;
551 QString text = QFontMetricsF( dlItem.font ).elidedText( dlItem.text, Qt::ElideRight, itemWidth );
552 QRectF drawRect( currentItemX, rowOffsetY, itemWidth, rowHeight );
553 painter->setClipRect( drawRect );
554 painter->drawText( drawRect, alignment, text );
558 currentItemX += itemWidth;
561 rowOffsetY += rowHeight +
PADDING;
565 QPointF KopeteItemDelegate::centerImage(
const QImage& image,
const QRectF& rect )
const
567 qreal imageRatio = ( qreal )image.width() / ( qreal )image.height();
572 if ( imageRatio >= 1 )
573 moveByY = ( rect.height() - ( rect.width() / imageRatio ) ) / 2.0;
575 moveByX = ( rect.width() - ( rect.height() * imageRatio ) ) / 2.0;
577 return QPointF( moveByX, moveByY );
580 QPointF KopeteItemDelegate::centerImage(
const QPixmap& pixmap,
const QRectF& rect )
const
582 qreal pixmapRatio = ( qreal )pixmap.width() / ( qreal )pixmap.height();
587 if ( pixmapRatio >= 1 )
588 moveByY = ( rect.height() - ( rect.width() / pixmapRatio ) ) / 2.0;
590 moveByX = ( rect.width() - ( rect.height() * pixmapRatio ) ) / 2.0;
592 return QPointF( moveByX, moveByY );
599 const int elementCount = row.
count();
600 for (
int i = 0; i < elementCount; ++i )
603 QFont elementFont( ( element.
small() ) ? small : normal );
604 elementFont.setItalic( element.
italic() );
605 elementFont.setBold( element.
bold() );
606 rowHeight = qMax( rowHeight, QFontMetricsF( elementFont ).height() );
611 #include "kopeteitemdelegate.moc"
static QFont normalFont(const QFont &naturalFont)
Contains definitions common between model items.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
const int OnlineStatusRole
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
const int TypeRole
Qt Model Role Definitions.
Kopete::Contact * contactAt(const QStyleOptionViewItem &option, const QModelIndex &index, const QPoint &point) const
const int HasNewMessageRole
KopeteItemDelegate(QAbstractItemView *parent=0)
const int MetaContactImageRole
static QFont smallFont(const QFont &naturalFont)