File indexing completed on 2024-04-28 04:49:53
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"