File indexing completed on 2024-10-06 04:25:58

0001 /*
0002     SPDX-FileCopyrightText: 2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-FileCopyrightText: 2009-2010 Michal Malek <michalm@jabster.pl>
0004     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "k3bdevicedelegate.h"
0009 #include "k3bdevicemodel.h"
0010 
0011 #include <KIconEffect>
0012 #include <KIconLoader>
0013 
0014 #include <QPainter>
0015 #include <QApplication>
0016 #include <QStyle>
0017 
0018 
0019 // FIXME: Get the whole animated hovering code from KFileItemDelegate and put it into a generic class which we can then reuse here
0020 //        To keep KFileItemDelegate BC it could simply forward calls to a subclass of the new generic delegate.
0021 
0022 
0023 // A lot of code is from KFileItemDelegate. Sadly this is all hidden in the private stuff
0024 namespace {
0025     QPixmap decoration( const QStyleOptionViewItem& option, const QModelIndex& index, const QSize& size )
0026     {
0027         QIcon icon = qvariant_cast<QIcon>( index.data( Qt::DecorationRole ) );
0028         QPixmap pixmap = icon.pixmap( size );
0029         if (!pixmap.isNull())
0030         {
0031             // If the item is selected, and the selection rectangle only covers the
0032             // text label, blend the pixmap with the highlight color.
0033             if (!option.showDecorationSelected && option.state & QStyle::State_Selected)
0034             {
0035                 QPainter p(&pixmap);
0036                 QColor color = option.palette.color(QPalette::Highlight);
0037                 color.setAlphaF(0.5);
0038                 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
0039                 p.fillRect(pixmap.rect(), color);
0040             }
0041 
0042             if ( option.state & QStyle::State_MouseOver ) {
0043                 KIconEffect *effect = KIconLoader::global()->iconEffect();
0044 
0045                 // Note that in KIconLoader terminology, active = hover.
0046                 // ### We're assuming that the icon group is desktop/filemanager, since this
0047                 //     is KFileItemDelegate.
0048                 if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState))
0049                     return effect->apply(pixmap, KIconLoader::Desktop, KIconLoader::ActiveState);
0050             }
0051         }
0052 
0053         return pixmap;
0054     }
0055     
0056     QFont cloneFont( const QFont& font, int pointSize, bool bold, bool italic )
0057     {
0058         QFont cloned( font );
0059         cloned.setPointSize( pointSize );
0060         cloned.setBold( bold );
0061         cloned.setItalic( italic );
0062         return cloned;
0063     }
0064     
0065     struct FontsAndMetrics
0066     {
0067         FontsAndMetrics( const QFont& font );
0068         
0069         QFont mediumFont;
0070         QFont deviceFont;
0071         QFontMetrics fontM;
0072         QFontMetrics mediumFontM;
0073         QFontMetrics deviceFontM;
0074         int margin;
0075         int spacing;
0076     };
0077     
0078     FontsAndMetrics::FontsAndMetrics( const QFont& font )
0079     :
0080         mediumFont( cloneFont( font, font.pointSize()+2, true, false ) ),
0081         deviceFont( cloneFont( font, font.pointSize()-2, false, true ) ),
0082         fontM( font ),
0083         mediumFontM( mediumFont ),
0084         deviceFontM( deviceFont ),
0085         margin( fontM.descent() ),
0086         spacing( 0 )
0087     {
0088     }
0089     
0090 } // namespace
0091 
0092 
0093 K3b::DeviceDelegate::DeviceDelegate( QObject* parent )
0094     : KFileItemDelegate( parent )
0095 {
0096 }
0097 
0098 
0099 K3b::DeviceDelegate::~DeviceDelegate()
0100 {
0101 }
0102 
0103 
0104 QSize K3b::DeviceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
0105 {
0106     if ( index.data( K3b::DeviceModel::IsDevice ).toBool() ) {
0107         const FontsAndMetrics fam( option.font );
0108         // It seems that width-part of size hint is not used anyway so
0109         // we're omitting here a computation of text's width
0110         return QSize( 0, fam.margin + fam.mediumFontM.height() + fam.spacing + fam.deviceFontM.height() + fam.margin );
0111     }
0112     else {
0113         return KFileItemDelegate::sizeHint( option, index );
0114     }
0115 }
0116 
0117 
0118 void K3b::DeviceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& optionOrig, const QModelIndex& index ) const
0119 {
0120     if ( index.data( K3b::DeviceModel::IsDevice ).toBool() ) {
0121         painter->save();
0122         painter->setRenderHint(QPainter::Antialiasing);
0123 
0124         // HACK: we erase the branch
0125         QStyleOptionViewItem option( optionOrig );
0126         option.rect.setLeft( 0 );
0127         painter->fillRect( option.rect, option.palette.base() );
0128 
0129         QStyle* style = QApplication::style();
0130         const FontsAndMetrics fam( option.font );
0131         const QPalette::ColorRole textRole = (option.state & QStyle::State_Selected) ?
0132                                               QPalette::HighlightedText : QPalette::Text;
0133         
0134         const QRect itemRect( option.rect.left() + fam.margin, option.rect.top() + fam.margin,
0135                               option.rect.width() - 2*fam.margin, option.rect.height() - 2*fam.margin );
0136         const QSize iconSize( itemRect.height(), itemRect.height() );
0137         const QSize mediumSize( itemRect.width() - iconSize.width() - fam.margin,
0138                                 itemRect.height() - fam.spacing - fam.deviceFontM.height() );
0139         const QSize devicemSize( itemRect.width() - iconSize.width() - fam.margin,
0140                                  itemRect.height() - fam.spacing - fam.mediumFontM.height() );
0141         const QRect iconRect = style->alignedRect( option.direction, Qt::AlignLeft | Qt::AlignVCenter, iconSize, itemRect );
0142         const QRect mediumRect = style->alignedRect( option.direction, Qt::AlignRight | Qt::AlignTop, mediumSize, itemRect );
0143         const QRect deviceRect = style->alignedRect( option.direction, Qt::AlignRight | Qt::AlignBottom, devicemSize, itemRect );
0144         
0145         // draw background
0146         style->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
0147 
0148         // draw decoration
0149         QPixmap pixmap = decoration( option, index, iconSize );
0150         painter->drawPixmap( iconRect, pixmap );
0151 
0152         // draw medium text
0153         painter->setFont( fam.mediumFont );
0154         QString text = index.data( Qt::DisplayRole ).toString();
0155         style->drawItemText( painter, mediumRect, option.displayAlignment, option.palette,
0156                              option.state & QStyle::State_Enabled,
0157                              fam.mediumFontM.elidedText( text, option.textElideMode, mediumRect.width() ),
0158                              textRole );
0159 
0160         // draw fixed device text
0161         painter->setFont( fam.deviceFont );
0162         text = index.data( K3b::DeviceModel::Vendor ).toString() + " - " + index.data( K3b::DeviceModel::Description ).toString();
0163         style->drawItemText( painter, deviceRect, option.displayAlignment, option.palette,
0164                              option.state & QStyle::State_Enabled,
0165                              fam.deviceFontM.elidedText( text, option.textElideMode, deviceRect.width() ),
0166                              textRole );
0167 
0168         painter->restore();
0169     }
0170     else {
0171         KFileItemDelegate::paint( painter, optionOrig, index );
0172     }
0173 }
0174 
0175 #include "moc_k3bdevicedelegate.cpp"