File indexing completed on 2025-01-19 04:24:07
0001 /**************************************************************************************** 0002 * Copyright (c) 2010 Daniel Faust <hessijames@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "LabelGraphicsItem.h" 0018 #include "LabelOverlayButton.h" 0019 0020 // Amarok 0021 #include "PaletteHandler.h" 0022 0023 // KDE 0024 #include <KIconLoader> 0025 0026 // Qt 0027 #include <QApplication> 0028 #include <QGraphicsBlurEffect> 0029 #include <QGraphicsSceneHoverEvent> 0030 #include <QGraphicsPixmapItem> 0031 #include <QGraphicsTextItem> 0032 #include <QPainter> 0033 #include <QPixmap> 0034 #include <QPropertyAnimation> 0035 0036 0037 LabelGraphicsItem::LabelGraphicsItem( const QString &text, qreal deltaPointSize, QGraphicsItem *parent ) 0038 : QGraphicsObject( parent ), 0039 m_selected( false ) 0040 { 0041 setAcceptHoverEvents( true ); 0042 0043 m_hoverColor = PaletteHandler::highlightColor( 0.7, 1.0 ); 0044 0045 m_hoverValueAnimation = new QPropertyAnimation( this, "hoverValue", this ); 0046 m_hoverValueAnimation.data()->setEasingCurve( QEasingCurve::InOutQuad ); 0047 0048 m_textItem = new QGraphicsTextItem( text, this ); 0049 m_textItem->setZValue( 10 ); 0050 m_textItem->setPos( qRound( m_textItem->boundingRect().height() / 4 ), 0 ); 0051 0052 m_backgroundItem = new QGraphicsPixmapItem( this ); 0053 m_backgroundItem->setZValue( 0 ); 0054 m_backgroundItem->setOpacity( 0.7 ); 0055 m_backgroundBlurEffect = new QGraphicsBlurEffect( this ); 0056 m_backgroundBlurEffect->setBlurRadius( 4.0 ); 0057 m_backgroundItem->setGraphicsEffect( m_backgroundBlurEffect ); 0058 0059 { 0060 KIconLoader iconLoader; 0061 m_addLabelItem = new LabelOverlayButton( this ); 0062 m_addLabelItem.data()->setZValue( 20 ); 0063 m_addLabelItem.data()->setPixmap( iconLoader.loadIcon( "list-add", KIconLoader::NoGroup, KIconLoader::SizeSmallMedium ) ); 0064 m_addLabelItem.data()->setToolTip( i18n( "Add label" ) ); 0065 m_addLabelItem.data()->setOpacity( 0.0 ); 0066 m_removeLabelItem = new LabelOverlayButton( this ); 0067 m_removeLabelItem.data()->setZValue( 20 ); 0068 m_removeLabelItem.data()->setPixmap( iconLoader.loadIcon( "list-remove", KIconLoader::NoGroup, KIconLoader::SizeSmallMedium ) ); 0069 m_removeLabelItem.data()->setToolTip( i18n( "Remove label" ) ); 0070 m_removeLabelItem.data()->setOpacity( 0.0 ); 0071 m_listLabelItem = new LabelOverlayButton( this ); 0072 m_listLabelItem.data()->setZValue( 20 ); 0073 m_listLabelItem.data()->setPixmap( iconLoader.loadIcon( "edit-find", KIconLoader::NoGroup, KIconLoader::SizeSmallMedium ) ); 0074 m_listLabelItem.data()->setToolTip( i18n( "Show in Media Sources" ) ); 0075 m_listLabelItem.data()->setOpacity( 0.0 ); 0076 m_blacklistLabelItem = new LabelOverlayButton( this ); 0077 m_blacklistLabelItem.data()->setZValue( 20 ); 0078 m_blacklistLabelItem.data()->setPixmap( iconLoader.loadIcon( "flag-black", KIconLoader::NoGroup, KIconLoader::SizeSmallMedium ) ); 0079 m_blacklistLabelItem.data()->setToolTip( i18n( "Add to blacklist" ) ); 0080 m_blacklistLabelItem.data()->setOpacity( 0.0 ); 0081 } 0082 0083 m_addLabelAnimation = new QPropertyAnimation( m_addLabelItem.data(), "opacity", this ); 0084 m_addLabelAnimation.data()->setEasingCurve( QEasingCurve::InOutQuad ); 0085 m_removeLabelAnimation = new QPropertyAnimation( m_removeLabelItem.data(), "opacity", this ); 0086 m_removeLabelAnimation.data()->setEasingCurve( QEasingCurve::InOutQuad ); 0087 m_listLabelAnimation = new QPropertyAnimation( m_listLabelItem.data(), "opacity", this ); 0088 m_listLabelAnimation.data()->setEasingCurve( QEasingCurve::InOutQuad ); 0089 m_blacklistLabelAnimation = new QPropertyAnimation( m_blacklistLabelItem.data(), "opacity", this ); 0090 m_blacklistLabelAnimation.data()->setEasingCurve( QEasingCurve::InOutQuad ); 0091 0092 setDeltaPointSize( deltaPointSize ); 0093 } 0094 0095 LabelGraphicsItem::~LabelGraphicsItem() 0096 {} 0097 0098 QString 0099 LabelGraphicsItem::text() 0100 { 0101 return m_textItem->toPlainText(); 0102 } 0103 0104 void 0105 LabelGraphicsItem::setText(const QString& text) 0106 { 0107 m_textItem->setPlainText( text ); 0108 } 0109 0110 void 0111 LabelGraphicsItem::setDeltaPointSize( qreal deltaPointSize ) 0112 { 0113 QFont f = qApp->font(); 0114 f.setPointSize( f.pointSizeF() + deltaPointSize ); 0115 f.setBold( m_selected ); 0116 m_textItem->setFont( f ); 0117 updateGeometry(); 0118 } 0119 0120 void 0121 LabelGraphicsItem::setSelected( bool selected ) 0122 { 0123 m_selected = selected; 0124 QFont f = m_textItem->font(); 0125 f.setBold( m_selected ); 0126 m_textItem->setFont( f ); 0127 setHoverValue( (float)isUnderMouse() ); 0128 updateGeometry(); 0129 } 0130 0131 void 0132 LabelGraphicsItem::setSelectedColor( QColor color ) 0133 { 0134 m_selectedColor = color; 0135 setSelected( m_selected ); 0136 update(); 0137 } 0138 0139 void 0140 LabelGraphicsItem::setBackgroundColor( QColor color ) 0141 { 0142 m_backgroundColor = color; 0143 update(); 0144 } 0145 0146 void 0147 LabelGraphicsItem::showBlacklistButton( bool enabled ) 0148 { 0149 m_showBlacklistButton = enabled; 0150 } 0151 0152 void 0153 LabelGraphicsItem::updateGeometry() 0154 { 0155 const QSizeF size = boundingRect().size(); 0156 0157 m_textItem->setPos( qRound( size.height() / 4 ), 0 ); 0158 0159 const qreal radius = size.height() / 4; 0160 0161 QPixmap pixmap( size.width(), size.height() ); 0162 pixmap.fill( Qt::transparent ); 0163 { 0164 QPainter painter( &pixmap ); 0165 painter.setRenderHint( QPainter::Antialiasing ); 0166 painter.setPen( QPen(m_backgroundColor) ); 0167 painter.setBrush( QBrush(m_backgroundColor) ); 0168 painter.drawRoundedRect( QRectF(2,2,size.width()-4,size.height()-4), radius, radius ); 0169 } 0170 m_backgroundItem->setPixmap( pixmap ); 0171 0172 // int iconsCount = m_selected ? 2 : 3; // don't show the blacklist flag for selected labels 0173 int iconsCount = m_showBlacklistButton ? 3 : 2; 0174 const int maxHeight = size.height() * 2 / 3; 0175 // minimum space between icnos is 2 pixels (number of spaces is iconsCount - 1) 0176 int maxWidth = ( size.width() - ( iconsCount - 1 ) * 2 ) / iconsCount; 0177 // minimum icon size is 14 pixels, hide icons until the remaining icons fit 0178 while( maxWidth < 14 && iconsCount > 0 ) 0179 { 0180 iconsCount--; 0181 maxWidth = ( size.width() - ( iconsCount - 1 ) * 2 ) / iconsCount; 0182 } 0183 const int iconsSize = qMin( maxHeight, maxWidth ); 0184 // maximum space between icons left 0185 const int iconsSpaceA = ( size.width() - iconsSize * iconsCount ) / ( iconsCount - 1 ); 0186 // optimal space 0187 const int iconsSpaceB = iconsSize / 2; 0188 const int iconsSpace = qMin( iconsSpaceA, iconsSpaceB ); 0189 // if there's enough space left, start the icons at the same position as the text 0190 // align buttons left 0191 // const int offset = qRound( qMin( ( size.width() - iconsSize * iconsCount - iconsSpace * ( iconsCount - 1 ) ) / 2, m_textItem->boundingRect().height() / 4 ) ); 0192 // align buttons centered 0193 const int offset = qRound( ( size.width() - iconsSize * iconsCount - iconsSpace * ( iconsCount - 1 ) ) / 2 ); 0194 0195 m_addLabelItem.data()->setSize( iconsSize ); 0196 m_addLabelItem.data()->setPos( offset, ( size.height() - iconsSize ) / 2 ); 0197 m_removeLabelItem.data()->setSize( iconsSize ); 0198 m_removeLabelItem.data()->setPos( offset, ( size.height() - iconsSize ) / 2 ); 0199 m_listLabelItem.data()->setSize( iconsSize ); 0200 m_listLabelItem.data()->setPos( offset + iconsSize + iconsSpace, ( size.height() - iconsSize ) / 2 ); 0201 m_listLabelItem.data()->setEnabled( iconsCount >= 2 ); 0202 m_blacklistLabelItem.data()->setSize( iconsSize ); 0203 m_blacklistLabelItem.data()->setPos( offset + iconsSize * 2 + iconsSpace * 2, ( size.height() - iconsSize ) / 2 ); 0204 m_blacklistLabelItem.data()->setEnabled( iconsCount >= 3 ); 0205 0206 updateHoverStatus(); 0207 } 0208 0209 void 0210 LabelGraphicsItem::updateHoverStatus() 0211 { 0212 if( m_addLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0213 m_addLabelAnimation.data()->stop(); 0214 if( m_removeLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0215 m_removeLabelAnimation.data()->stop(); 0216 if( m_listLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0217 m_listLabelAnimation.data()->stop(); 0218 if( m_blacklistLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0219 m_blacklistLabelAnimation.data()->stop(); 0220 0221 if( isUnderMouse() ) 0222 { 0223 if( m_selected ) 0224 { 0225 m_addLabelItem.data()->setOpacity( 0.0 ); 0226 m_removeLabelItem.data()->setOpacity( 1.0 ); 0227 m_removeLabelItem.data()->updateHoverStatus(); 0228 } 0229 else 0230 { 0231 m_addLabelItem.data()->setOpacity( 1.0 ); 0232 m_addLabelItem.data()->updateHoverStatus(); 0233 m_removeLabelItem.data()->setOpacity( 0.0 ); 0234 } 0235 0236 if( m_listLabelItem.data()->isEnabled() ) 0237 { 0238 m_listLabelItem.data()->setOpacity( 1.0 ); 0239 m_listLabelItem.data()->updateHoverStatus(); 0240 } 0241 0242 if( m_blacklistLabelItem.data()->isEnabled() ) 0243 { 0244 m_blacklistLabelItem.data()->setOpacity( 1.0 ); 0245 m_blacklistLabelItem.data()->updateHoverStatus(); 0246 } 0247 0248 setHoverValue( 1.0 ); 0249 } 0250 else 0251 { 0252 m_addLabelItem.data()->setOpacity( 0.0 ); 0253 m_removeLabelItem.data()->setOpacity( 0.0 ); 0254 m_listLabelItem.data()->setOpacity( 0.0 ); 0255 m_blacklistLabelItem.data()->setOpacity( 0.0 ); 0256 0257 setHoverValue( 0.0 ); 0258 } 0259 } 0260 0261 void 0262 LabelGraphicsItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event ) 0263 { 0264 Q_UNUSED( event ) 0265 0266 m_hoverValueAnimation.data()->setEndValue( 1.0 ); 0267 m_hoverValueAnimation.data()->start(); 0268 0269 if( m_addLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0270 m_addLabelAnimation.data()->stop(); 0271 if( m_removeLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0272 m_removeLabelAnimation.data()->stop(); 0273 if( m_listLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0274 m_listLabelAnimation.data()->stop(); 0275 if( m_blacklistLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0276 m_blacklistLabelAnimation.data()->stop(); 0277 0278 if( m_selected ) 0279 { 0280 m_removeLabelAnimation.data()->setEndValue( 1.0 ); 0281 m_removeLabelAnimation.data()->start(); 0282 } 0283 else 0284 { 0285 m_addLabelAnimation.data()->setEndValue( 1.0 ); 0286 m_addLabelAnimation.data()->start(); 0287 } 0288 0289 if( m_listLabelItem.data()->isEnabled() ) 0290 { 0291 m_listLabelAnimation.data()->setEndValue( 1.0 ); 0292 m_listLabelAnimation.data()->start(); 0293 } 0294 0295 if( m_blacklistLabelItem.data()->isEnabled() ) 0296 { 0297 m_blacklistLabelAnimation.data()->setEndValue( 1.0 ); 0298 m_blacklistLabelAnimation.data()->start(); 0299 } 0300 0301 update(); 0302 } 0303 0304 void 0305 LabelGraphicsItem::hoverLeaveEvent( QGraphicsSceneHoverEvent *event ) 0306 { 0307 Q_UNUSED( event ) 0308 0309 if( m_addLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0310 m_addLabelAnimation.data()->stop(); 0311 if( m_removeLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0312 m_removeLabelAnimation.data()->stop(); 0313 if( m_listLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0314 m_listLabelAnimation.data()->stop(); 0315 if( m_blacklistLabelAnimation.data()->state() != QAbstractAnimation::Stopped ) 0316 m_blacklistLabelAnimation.data()->stop(); 0317 0318 if( m_selected ) 0319 { 0320 m_removeLabelAnimation.data()->setEndValue( 0.0 ); 0321 m_removeLabelAnimation.data()->start(); 0322 } 0323 else 0324 { 0325 m_addLabelAnimation.data()->setEndValue( 0.0 ); 0326 m_addLabelAnimation.data()->start(); 0327 } 0328 0329 if( m_listLabelItem.data()->isEnabled() ) 0330 { 0331 m_listLabelAnimation.data()->setEndValue( 0.0 ); 0332 m_listLabelAnimation.data()->start(); 0333 } 0334 0335 if( m_blacklistLabelItem.data()->isEnabled() ) 0336 { 0337 m_blacklistLabelAnimation.data()->setEndValue( 0.0 ); 0338 m_blacklistLabelAnimation.data()->start(); 0339 } 0340 0341 m_hoverValueAnimation.data()->setEndValue( 0.0 ); 0342 m_hoverValueAnimation.data()->start(); 0343 0344 update(); 0345 } 0346 0347 void 0348 LabelGraphicsItem::mousePressEvent( QGraphicsSceneMouseEvent *event ) 0349 { 0350 if( m_addLabelItem.data()->boundingRect().contains( mapToItem( m_addLabelItem.data(), event->pos() ) ) || 0351 m_removeLabelItem.data()->boundingRect().contains( mapToItem( m_removeLabelItem.data(), event->pos() ) ) ) 0352 emit toggled( m_textItem->toPlainText() ); 0353 else if( m_listLabelItem.data()->isEnabled() && m_listLabelItem.data()->boundingRect().contains( mapToItem( m_listLabelItem.data(), event->pos() ) ) ) 0354 emit list( m_textItem->toPlainText() ); 0355 else if( m_blacklistLabelItem.data()->isEnabled() && m_blacklistLabelItem.data()->boundingRect().contains( mapToItem( m_blacklistLabelItem.data(), event->pos() ) ) ) 0356 emit blacklisted( m_textItem->toPlainText() ); 0357 } 0358 0359 qreal 0360 LabelGraphicsItem::hoverValue() 0361 { 0362 return m_hoverValue; 0363 } 0364 0365 void 0366 LabelGraphicsItem::setHoverValue( qreal value ) 0367 { 0368 m_hoverValue = value; 0369 const QPalette p; 0370 const QColor c = p.color( QPalette::WindowText ); 0371 const QColor defaultColor = m_selected ? m_selectedColor : c; 0372 0373 const int red = defaultColor.red() + ( m_hoverColor.red() - defaultColor.red() ) * m_hoverValue; 0374 const int green = defaultColor.green() + ( m_hoverColor.green() - defaultColor.green() ) * m_hoverValue; 0375 const int blue = defaultColor.blue() + ( m_hoverColor.blue() - defaultColor.blue() ) * m_hoverValue; 0376 0377 m_textItem->setDefaultTextColor( QColor( red, green, blue ) ); 0378 } 0379 0380 QRectF 0381 LabelGraphicsItem::boundingRect() const 0382 { 0383 QRectF rect = m_textItem->boundingRect(); 0384 rect.setWidth( rect.width() + qRound( rect.height() / 2 ) ); 0385 return rect; 0386 } 0387 0388 void 0389 LabelGraphicsItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ) 0390 { 0391 Q_UNUSED( painter ) 0392 Q_UNUSED( option ) 0393 Q_UNUSED( widget ) 0394 } 0395 0396