File indexing completed on 2024-06-16 07:42:27

0001 /*
0002     SPDX-FileCopyrightText: 2003-2009 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl>
0004     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "k3btitlelabel.h"
0010 
0011 #include <QDebug>
0012 #include <QEvent>
0013 #include <QFont>
0014 #include <QFontMetrics>
0015 #include <QHelpEvent>
0016 #include <QPainter>
0017 #include <QStyle>
0018 #include <QToolTip>
0019 
0020 
0021 class K3b::TitleLabel::Private
0022 {
0023 public:
0024     Private()
0025     :
0026         alignment( Qt::AlignLeft | Qt::AlignVCenter ),
0027         titleLength( 0 ),
0028         subTitleLength( 0 ),
0029         displayTitleLength( 0 ),
0030         displaySubTitleLength( 0 ),
0031         titleBaseLine( 0 ),
0032         subTitleBaseLine( 0 ),
0033         margin( 2 ),
0034         spacing( 5 ),
0035         cachedMinimumWidth( 0 )
0036     {
0037     }
0038 
0039     QString title;
0040     QString subTitle;
0041 
0042     QString displayTitle;
0043     QString displaySubTitle;
0044 
0045     Qt::Alignment alignment;
0046 
0047     int titleLength;
0048     int subTitleLength;
0049     int displayTitleLength;
0050     int displaySubTitleLength;
0051     int titleBaseLine;
0052     int subTitleBaseLine;
0053     int margin;
0054     int spacing;
0055 
0056     int cachedMinimumWidth;
0057     
0058     QRect titleRect( const QRect& boundingRect ) const;
0059     QRect subTitleRect( const QRect& subTitleRect, const QRect& titleRect ) const;
0060 };
0061 
0062 
0063 QRect K3b::TitleLabel::Private::titleRect( const QRect& boundingRect ) const
0064 {
0065     int neededWidth = displayTitleLength;
0066     if( !displaySubTitle.isEmpty() )
0067         neededWidth += displaySubTitleLength + spacing;
0068     
0069     QRect titleRect;
0070     if( alignment & Qt::AlignHCenter )
0071         titleRect.setLeft( boundingRect.left() + ( boundingRect.width() - neededWidth ) / 2 );
0072     else if( alignment & Qt::AlignRight )
0073         titleRect.setLeft( boundingRect.right() - neededWidth );
0074     else
0075         titleRect.setLeft( boundingRect.left() );
0076     titleRect.setTop( boundingRect.top() );
0077     titleRect.setWidth( displayTitleLength );
0078     titleRect.setHeight( boundingRect.height() );
0079     return titleRect;
0080 }
0081 
0082 
0083 QRect K3b::TitleLabel::Private::subTitleRect( const QRect& boundingRect, const QRect& titleRect ) const
0084 {
0085     return QRect( titleRect.left() + displayTitleLength + spacing, boundingRect.top(),
0086                   displaySubTitleLength, boundingRect.height() );
0087 }
0088 
0089 
0090 K3b::TitleLabel::TitleLabel( QWidget* parent )
0091     : QFrame( parent )
0092 {
0093     d = new Private();
0094 }
0095 
0096 
0097 K3b::TitleLabel::~TitleLabel()
0098 {
0099     delete d;
0100 }
0101 
0102 
0103 void K3b::TitleLabel::setTitle( const QString& title, const QString& subTitle )
0104 {
0105     d->title = title;
0106     d->subTitle = subTitle;
0107     updatePositioning();
0108     update();
0109 }
0110 
0111 
0112 void K3b::TitleLabel::setSubTitle( const QString& subTitle )
0113 {
0114     d->subTitle = subTitle;
0115     updatePositioning();
0116     update();
0117 }
0118 
0119 
0120 void K3b::TitleLabel::setAlignment( Qt::Alignment alignment )
0121 {
0122     d->alignment = alignment;
0123     update();
0124 }
0125 
0126 
0127 QSize K3b::TitleLabel::sizeHint() const
0128 {
0129     return QSize( d->titleLength + d->subTitleLength + 2*d->margin, d->titleBaseLine );
0130 }
0131 
0132 
0133 QSize K3b::TitleLabel::minimumSizeHint() const
0134 {
0135     return QSize( d->cachedMinimumWidth, d->titleBaseLine );
0136 }
0137 
0138 
0139 void K3b::TitleLabel::resizeEvent( QResizeEvent* e )
0140 {
0141     QFrame::resizeEvent( e );
0142     updatePositioning();
0143     update();
0144 }
0145 
0146 
0147 void K3b::TitleLabel::paintEvent( QPaintEvent* e )
0148 {
0149     QPainter p( this );
0150     p.eraseRect( e->rect() );
0151     p.setLayoutDirection( layoutDirection() );
0152 
0153     const QRect rect = e->rect().adjusted( d->margin, d->margin, -d->margin, -d->margin );
0154     const QRect titleRect = d->titleRect( rect );
0155 
0156     QFont f( font() );
0157     f.setBold(true);
0158     f.setPointSize( f.pointSize() + 2 );
0159 
0160     // paint title
0161     p.setFont(f);
0162     p.drawText( QStyle::visualRect( layoutDirection(), rect, titleRect ),
0163                 QStyle::visualAlignment( layoutDirection(), d->alignment ),
0164                 d->displayTitle );
0165 
0166     if( !d->subTitle.isEmpty() ) {
0167         f.setBold(false);
0168         f.setPointSize( f.pointSize() - 4 );
0169         p.setFont(f);
0170         const QRect subTitleRect = d->subTitleRect( rect, titleRect );
0171         p.drawText( QStyle::visualRect( layoutDirection(), rect, subTitleRect ),
0172                     QStyle::visualAlignment( layoutDirection(), d->alignment ),
0173                     d->displaySubTitle );
0174     }
0175 }
0176 
0177 
0178 void K3b::TitleLabel::setMargin( int m )
0179 {
0180     d->margin = m;
0181     updatePositioning();
0182     update();
0183 }
0184 
0185 
0186 void K3b::TitleLabel::updatePositioning()
0187 {
0188     QFont f(font());
0189     f.setBold(true);
0190     f.setPointSize( f.pointSize() + 2 );
0191     QFontMetrics titleFm(f);
0192 
0193     f.setBold(false);
0194     f.setPointSize( f.pointSize() - 4 );
0195     QFontMetrics subTitleFm(f);
0196 
0197     d->titleBaseLine = contentsRect().height()/2 + titleFm.height()/2 - titleFm.descent();
0198     d->titleLength = titleFm.boundingRect( d->title ).width();
0199 
0200     d->subTitleBaseLine = d->titleBaseLine;
0201 
0202     d->subTitleLength = ( d->subTitle.isEmpty() ? 0 : subTitleFm.horizontalAdvance( d->subTitle ) );
0203 
0204     // cut the text to window width
0205     d->displayTitle = d->title;
0206     d->displaySubTitle = d->subTitle;
0207     //FIXME add margin
0208     int widthAvail = contentsRect().width() /*- 2*margin()*/;
0209 
0210     if( !d->subTitle.isEmpty() )
0211         widthAvail -= d->spacing;
0212 
0213     if( d->titleLength > widthAvail/2 ) {
0214         if( d->subTitleLength <= widthAvail/2 )
0215             d->displayTitle = titleFm.elidedText( d->title, Qt::ElideRight, widthAvail - d->subTitleLength );
0216         else
0217             d->displayTitle = titleFm.elidedText( d->title, Qt::ElideRight, widthAvail/2 );
0218     }
0219     if( d->subTitleLength > widthAvail/2 ) {
0220         if( d->titleLength <= widthAvail/2 )
0221             d->displaySubTitle = subTitleFm.elidedText( d->subTitle, Qt::ElideRight, widthAvail - d->titleLength );
0222         else
0223             d->displaySubTitle = subTitleFm.elidedText( d->subTitle, Qt::ElideRight, widthAvail/2 );
0224     }
0225 
0226     d->displayTitleLength = titleFm.horizontalAdvance( d->displayTitle );
0227     d->displaySubTitleLength = subTitleFm.horizontalAdvance( d->displaySubTitle );
0228 
0229 
0230     //
0231     // determine the minimum width for the minimum size hint
0232     //
0233     d->cachedMinimumWidth = 2*d->margin;
0234 
0235     QString cutTitle = d->title;
0236     if( cutTitle.length() > 2 ) {
0237         cutTitle.truncate( 2 );
0238         cutTitle += "...";
0239     }
0240     QString cutSubTitle = d->subTitle;
0241     if( cutSubTitle.length() > 2 ) {
0242         cutSubTitle.truncate( 2 );
0243         cutSubTitle += "...";
0244     }
0245 
0246     d->cachedMinimumWidth += titleFm.horizontalAdvance( cutTitle ) + subTitleFm.horizontalAdvance( cutSubTitle );
0247     if( !d->subTitle.isEmpty() )
0248         d->cachedMinimumWidth += d->spacing;
0249 
0250     qDebug() << d->titleBaseLine << d->subTitleBaseLine;
0251 }
0252 
0253 
0254 bool K3b::TitleLabel::event( QEvent* event )
0255 {
0256     if ( event->type() == QEvent::ToolTip ) {
0257         QHelpEvent* he = ( QHelpEvent* )event;
0258         QPoint pos = he->pos();
0259 
0260         const QRect rect = contentsRect().adjusted( d->margin, d->margin, -d->margin, -d->margin );
0261         const QRect titleRect = d->titleRect( rect );
0262         const QRect subTitleRect = d->subTitleRect( rect, titleRect );
0263         const QRect actualTitleRect = QStyle::visualRect( layoutDirection(), rect, titleRect );
0264         const QRect actualSubTitleRect = QStyle::visualRect( layoutDirection(), rect, subTitleRect );
0265 
0266         if( actualTitleRect.contains( pos ) && d->displayTitle != d->title ) {
0267             QToolTip::showText( he->globalPos(), d->title, this, actualTitleRect );
0268         }
0269         else if( actualSubTitleRect.contains( pos ) && d->displaySubTitle != d->subTitle ) {
0270             QToolTip::showText( he->globalPos(), d->subTitle, this, actualSubTitleRect );
0271         }
0272 
0273         event->accept();
0274 
0275         return true;
0276     }
0277 
0278     return QFrame::event( event );
0279 }
0280 
0281 #include "moc_k3btitlelabel.cpp"