File indexing completed on 2024-05-05 04:49:25
0001 /**************************************************************************************** 0002 * Copyright (c) 2006 Peter Penz <peter.penz@gmx.at> * 0003 * Copyright (c) 2006 Aaron Seigo <aseigo@kde.org> * 0004 * Copyright (c) 2009 Seb Ruiz <ruiz@kde.org> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #include "BreadcrumbItemButton.h" 0020 0021 #include "amarokurls/AmarokUrlAction.h" 0022 #include "amarokurls/AmarokUrlHandler.h" 0023 #include "core/support/Amarok.h" 0024 0025 #include <KColorScheme> 0026 #include <QIcon> 0027 #include <KLocalizedString> 0028 #include <QMenu> 0029 0030 #include <QApplication> 0031 #include <QClipboard> 0032 #include <QMimeData> 0033 #include <QMargins> 0034 #include <QPainter> 0035 #include <QStyle> 0036 #include <QStyleOptionFocusRect> 0037 0038 BreadcrumbItemButton::BreadcrumbItemButton( QWidget *parent ) 0039 : Amarok::ElidingButton( parent ) 0040 , m_displayHint( 0 ) 0041 { 0042 init(); 0043 } 0044 0045 BreadcrumbItemButton::BreadcrumbItemButton( const QString &text, QWidget *parent ) 0046 : Amarok::ElidingButton( text, parent ) 0047 , m_displayHint( 0 ) 0048 { 0049 init(); 0050 } 0051 0052 BreadcrumbItemButton::BreadcrumbItemButton( const QIcon &icon, const QString &text, QWidget *parent ) 0053 : Amarok::ElidingButton( icon, text, parent ) 0054 , m_displayHint( 0 ) 0055 { 0056 init(); 0057 } 0058 0059 void 0060 BreadcrumbItemButton::init() 0061 { 0062 setFocusPolicy( Qt::NoFocus ); 0063 setDisplayHintEnabled( HoverHint, false ); 0064 } 0065 0066 BreadcrumbItemButton::~BreadcrumbItemButton() 0067 { 0068 } 0069 0070 void 0071 BreadcrumbItemButton::setActive( const bool active ) 0072 { 0073 setDisplayHintEnabled( ActiveHint, active ); 0074 0075 QFont f = font(); 0076 f.setBold( active ); 0077 setFont( f ); 0078 } 0079 0080 void 0081 BreadcrumbItemButton::setDisplayHintEnabled( DisplayHint hint, bool enable ) 0082 { 0083 if( enable ) 0084 m_displayHint = m_displayHint | hint; 0085 else 0086 m_displayHint = m_displayHint & ~hint; 0087 0088 update(); 0089 } 0090 0091 bool 0092 BreadcrumbItemButton::isDisplayHintEnabled( DisplayHint hint ) const 0093 { 0094 return (m_displayHint & hint) > 0; 0095 } 0096 0097 void 0098 BreadcrumbItemButton::enterEvent( QEvent* event ) 0099 { 0100 QPushButton::enterEvent( event ); 0101 setDisplayHintEnabled( HoverHint, true ); 0102 update(); 0103 } 0104 0105 void 0106 BreadcrumbItemButton::leaveEvent( QEvent* event ) 0107 { 0108 QPushButton::leaveEvent( event ); 0109 setDisplayHintEnabled( HoverHint, false ); 0110 update(); 0111 } 0112 0113 void 0114 BreadcrumbItemButton::paintEvent( QPaintEvent* event ) 0115 { 0116 Q_UNUSED(event); 0117 0118 QPainter painter(this); 0119 0120 const int buttonHeight = height(); 0121 int buttonWidth = width(); 0122 int preferredWidth = sizeHint().width(); 0123 if (preferredWidth < minimumWidth()) { 0124 preferredWidth = minimumWidth(); 0125 } 0126 if (buttonWidth > preferredWidth) { 0127 buttonWidth = preferredWidth; 0128 } 0129 drawHoverBackground(&painter); 0130 0131 QMargins margins = contentsMargins(); 0132 const int padding = 2; 0133 int xoffset; 0134 0135 if( !icon().isNull() ) 0136 { 0137 const int iconWidth = iconSize().width(); 0138 const int iconHeight = iconSize().height(); 0139 const int iconTop = ( (buttonHeight - margins.top() - margins.bottom()) - iconHeight ) / 2; 0140 const QRect iconRect( margins.left() + padding, iconTop, iconWidth, iconHeight ); 0141 painter.drawPixmap( iconRect, icon().pixmap( iconSize() ) ); 0142 xoffset = margins.left() + (padding * 2) + iconWidth; 0143 } 0144 else 0145 xoffset = margins.left() + (padding * 2); 0146 0147 const QRect textRect( xoffset, margins.top(), buttonWidth, buttonHeight); 0148 painter.drawText(textRect, Qt::AlignVCenter, text()); 0149 } 0150 0151 0152 void 0153 BreadcrumbItemButton::drawHoverBackground(QPainter* painter) 0154 { 0155 const bool isHovered = isDisplayHintEnabled( HoverHint ); 0156 0157 if( isHovered ) 0158 { 0159 // QColor backgroundColor = palette().color(QPalette::Highlight); 0160 // TODO: the backgroundColor should be applied to the style 0161 QStyleOptionViewItem option; 0162 option.initFrom(this); 0163 option.state = QStyle::State_Enabled | QStyle::State_MouseOver; 0164 option.viewItemPosition = QStyleOptionViewItem::OnlyOne; 0165 style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter, this ); 0166 } 0167 } 0168 0169 QColor 0170 BreadcrumbItemButton::foregroundColor() const 0171 { 0172 const bool isHighlighted = isDisplayHintEnabled( HoverHint ); 0173 const bool isActive = isDisplayHintEnabled( ActiveHint ); 0174 0175 QColor foregroundColor = palette().color( foregroundRole() ); 0176 if( !isActive && !isHighlighted ) 0177 foregroundColor.setAlpha( 180 ); 0178 0179 return foregroundColor; 0180 } 0181 0182 QSize 0183 BreadcrumbItemButton::sizeHint() const 0184 { 0185 QSize size = Amarok::ElidingButton::sizeHint(); 0186 int width = 8; 0187 if( !icon().isNull() ) 0188 { 0189 width += iconSize().width(); 0190 } 0191 if( !text().isEmpty() ) 0192 { 0193 QFontMetrics fm( font() ); 0194 width += fm.horizontalAdvance( text() ); 0195 } 0196 size.setWidth( width ); 0197 return size; 0198 } 0199 0200 0201 BreadcrumbItemMenuButton::BreadcrumbItemMenuButton( QWidget* parent ) 0202 : BreadcrumbItemButton( parent ) 0203 { 0204 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); 0205 } 0206 0207 void 0208 BreadcrumbItemMenuButton::paintEvent( QPaintEvent* event ) 0209 { 0210 Q_UNUSED(event); 0211 0212 QPainter painter(this); 0213 drawHoverBackground(&painter); 0214 0215 const QColor fgColor = foregroundColor(); 0216 0217 QStyleOption option; 0218 option.initFrom(this); 0219 option.rect = QRect(0, 0, width(), height()); 0220 option.palette = palette(); 0221 option.palette.setColor(QPalette::Text, fgColor); 0222 option.palette.setColor(QPalette::WindowText, fgColor); 0223 option.palette.setColor(QPalette::ButtonText, fgColor); 0224 0225 if (layoutDirection() == Qt::LeftToRight) { 0226 style()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &option, &painter, this); 0227 } else { 0228 style()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &option, &painter, this); 0229 } 0230 } 0231 0232 0233 0234 BreadcrumbUrlMenuButton::BreadcrumbUrlMenuButton( const QString &urlsCommand, QWidget *parent ) 0235 : BreadcrumbItemButton( QIcon::fromTheme( "bookmark-new-list" ), QString(), parent ) 0236 , m_urlsCommand( urlsCommand ) 0237 , m_copyToClipboardAction( nullptr ) 0238 { 0239 setToolTip( i18n( "List and run bookmarks, or create new ones" ) ); 0240 0241 connect( this, &QAbstractButton::clicked, this, &BreadcrumbUrlMenuButton::showMenu ); 0242 } 0243 0244 BreadcrumbUrlMenuButton::~BreadcrumbUrlMenuButton() 0245 { 0246 } 0247 0248 void 0249 BreadcrumbUrlMenuButton::generateMenu( const QPoint &pos ) 0250 { 0251 0252 DEBUG_BLOCK 0253 0254 BookmarkList list = The::amarokUrlHandler()->urlsByCommand( m_urlsCommand ); 0255 0256 QMenu * menu = new QMenu(); 0257 menu->setTitle( i18n("Amarok Bookmarks" ) ); 0258 0259 if( m_urlsCommand == "navigate" ) 0260 menu->addAction( Amarok::actionCollection()->action( "bookmark_browser" ) ); 0261 else if( m_urlsCommand == "playlist" ) 0262 { 0263 menu->addAction( Amarok::actionCollection()->action( "bookmark_playlistview" ) ); 0264 debug()<<"Adding bookmark playlist action"; 0265 } 0266 else if( m_urlsCommand == "context" ) 0267 { 0268 menu->addAction( Amarok::actionCollection()->action( "bookmark_contextview" ) ); 0269 debug()<<"Adding bookmark context view action"; 0270 } 0271 else 0272 warning()<<"Bad URL command."; 0273 0274 if( !m_copyToClipboardAction ) 0275 { 0276 m_copyToClipboardAction = new QAction( QIcon::fromTheme( "klipper" ), i18n( "Copy Current View Bookmark to Clipboard" ), this ); 0277 connect( m_copyToClipboardAction, &QAction::triggered, this, &BreadcrumbUrlMenuButton::copyCurrentToClipboard ); 0278 } 0279 0280 menu->addAction( m_copyToClipboardAction ); 0281 0282 menu->addAction( Amarok::actionCollection()->action( "bookmark_manager" ) ); 0283 0284 menu->addSeparator(); 0285 0286 foreach( AmarokUrlPtr url, list ) 0287 { 0288 menu->addAction( new AmarokUrlAction( url, menu ) ); 0289 } 0290 0291 debug() << "showing menu at " << pos; 0292 menu->exec( pos ); 0293 delete menu; 0294 0295 } 0296 0297 void 0298 BreadcrumbUrlMenuButton::showMenu() 0299 { 0300 QPoint pos( 0, height() ); 0301 generateMenu( mapToGlobal( pos ) ); 0302 } 0303 0304 void 0305 BreadcrumbUrlMenuButton::copyCurrentToClipboard() 0306 { 0307 0308 QString urlString; 0309 0310 if( m_urlsCommand == "navigate" ) 0311 { 0312 AmarokUrl url = The::amarokUrlHandler()->createBrowserViewBookmark(); 0313 urlString = url.url(); 0314 } 0315 else if( m_urlsCommand == "playlist" ) 0316 { 0317 AmarokUrl url = The::amarokUrlHandler()->createPlaylistViewBookmark(); 0318 urlString = url.url(); 0319 } 0320 else if( m_urlsCommand == "context" ) 0321 { 0322 AmarokUrl url = The::amarokUrlHandler()->createContextViewBookmark(); 0323 urlString = url.url(); 0324 } 0325 0326 QApplication::clipboard()->setText( urlString ); 0327 0328 } 0329