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