File indexing completed on 2024-05-05 04:49:29

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Téo Mrnjavac <teo@kde.org>                                        *
0003  * Copyright (c) 2008-2009 Seb Ruiz <ruiz@kde.org>                                      *
0004  * Copyright (c) 2009 Roman Jarosz <kedgedev@gmail.com>                                 *
0005  * Copyright (c) 2009 Daniel Dewald <Daniel.Dewald@time-shift.de>                       *
0006  * Copyright (c) 2012 Ralf Engels <ralf-engels@gmx.de>                                  *
0007  *                                                                                      *
0008  * This program is free software; you can redistribute it and/or modify it under        *
0009  * the terms of the GNU General Public License as published by the Free Software        *
0010  * Foundation; either version 2 of the License, or (at your option) any later           *
0011  * version.                                                                             *
0012  *                                                                                      *
0013  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0016  *                                                                                      *
0017  * You should have received a copy of the GNU General Public License along with         *
0018  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0019  ****************************************************************************************/
0020 
0021 #include "Token.h"
0022 #include "TokenDropTarget.h"
0023 
0024 #include <QApplication>
0025 
0026 #include <QHBoxLayout>
0027 #include <QPainter>
0028 #include <QPen>
0029 
0030 #include <QPixmap>
0031 #include <QMimeData>
0032 #include <QMouseEvent>
0033 #include <QDrag>
0034 
0035 
0036 Token*
0037 TokenFactory::createToken(const QString & text, const QString & iconName, qint64 value, QWidget * parent) const
0038 {
0039     return new Token( text, iconName, value, parent );
0040 }
0041 
0042 Token*
0043 TokenFactory::createTokenFromMime( const QMimeData* mimeData, QWidget* parent ) const
0044 {
0045     // decode the stream created in Token::mimeData
0046     QByteArray itemData = mimeData->data( Token::mimeType() );
0047     QDataStream dataStream(&itemData, QIODevice::ReadOnly);
0048 
0049     QString tokenName;
0050     QString tokenIconName;
0051     qint64 tokenValue;
0052     QColor tokenTextColor;
0053 
0054     dataStream >> tokenName;
0055     dataStream >> tokenIconName;
0056     dataStream >> tokenValue;
0057     dataStream >> tokenTextColor;
0058 
0059     Token* token = createToken( tokenName, tokenIconName, tokenValue, parent );
0060     token->setTextColor( tokenTextColor );
0061 
0062     return token;
0063 }
0064 
0065 
0066 Token::Token( const QString &name, const QString &iconName, qint64 value, QWidget *parent )
0067     : QWidget( parent )
0068     , m_name( name )
0069     , m_icon( QIcon::fromTheme( iconName ) )
0070     , m_iconName( iconName )
0071     , m_value( value )
0072     , m_customColor( false )
0073 {
0074     setFocusPolicy( Qt::StrongFocus );
0075 
0076     // Note: We set all the margins because we need a quite small size.
0077     // Vertically for the EditPlaylistLayoutDialog and horizontally for
0078     // the OrganizeTracksDialog
0079 
0080     m_label = new QLabel( this );
0081     m_label->setAlignment( Qt::AlignCenter );
0082     m_label->setContentsMargins( 0, 0, 0, 0 );
0083     m_label->setMargin( 0 );
0084     m_label->setText( name );
0085 
0086     m_iconContainer = new QLabel( this );
0087     m_iconContainer->setContentsMargins( 0, 0, 0, 0 );
0088     m_iconContainer->setMargin( 0 );
0089     QPixmap pixmap = QPixmap( icon().pixmap( 16, 16 ) );
0090     m_iconContainer->setPixmap( pixmap );
0091 
0092     QHBoxLayout *hlayout = new QHBoxLayout( this );
0093     hlayout->setSpacing( 3 );
0094     hlayout->setContentsMargins( 3, 0, 3, 0 ); // to allow the label to overwrite the border if space get's tight
0095     hlayout->addWidget( m_iconContainer );
0096     hlayout->addWidget( m_label );
0097     setLayout( hlayout );
0098 
0099     updateCursor();
0100 }
0101 
0102 QString
0103 Token::name() const
0104 {
0105     return m_name;
0106 }
0107 
0108 qint64
0109 Token::value() const
0110 {
0111     return m_value;
0112 }
0113 
0114 QIcon
0115 Token::icon() const
0116 {
0117     return m_icon;
0118 }
0119 
0120 QString Token::iconName() const
0121 {
0122     return m_iconName;
0123 }
0124 
0125 QColor Token::textColor() const
0126 {
0127     return m_label->palette().color( QPalette::WindowText );
0128 }
0129 
0130 void
0131 Token::setTextColor( QColor textColor )
0132 {
0133     m_customColor = true;
0134     if( textColor == this->textColor() )
0135         return;
0136     QPalette myPalette( m_label->palette() );
0137     myPalette.setColor( QPalette::WindowText, textColor );
0138     m_label->setPalette( myPalette );
0139 }
0140 
0141 QMimeData*
0142 Token::mimeData() const
0143 {
0144     QByteArray itemData;
0145 
0146     QDataStream dataStream( &itemData, QIODevice::WriteOnly );
0147     dataStream << name() << iconName() << value() << textColor();
0148 
0149     QMimeData *mimeData = new QMimeData;
0150     mimeData->setData( mimeType(), itemData );
0151 
0152     return mimeData;
0153 }
0154 
0155 QString
0156 Token::mimeType()
0157 {
0158     return QLatin1String( "application/x-amarok-tag-token" );
0159 }
0160 
0161 QSize
0162 Token::sizeHint() const
0163 {
0164     QSize result = QWidget::sizeHint();
0165     result += QSize( 6, 6 ); // the border
0166 
0167     return result;
0168 }
0169 
0170 QSize
0171 Token::minimumSizeHint() const
0172 {
0173     QSize result = QWidget::minimumSizeHint();
0174 
0175     return result;
0176 }
0177 
0178 void
0179 Token::changeEvent( QEvent *event )
0180 {
0181     QWidget::changeEvent( event );
0182     if( !event || event->type() == QEvent::EnabledChange )
0183         updateCursor();
0184 }
0185 
0186 void
0187 Token::focusInEvent( QFocusEvent* event )
0188 {
0189     QWidget::focusInEvent( event );
0190     Q_EMIT gotFocus( this );
0191 }
0192 
0193 void
0194 Token::updateCursor()
0195 {
0196     if( isEnabled() )
0197         setCursor( Qt::OpenHandCursor );
0198     else
0199         unsetCursor();
0200 }
0201 
0202 void
0203 Token::mousePressEvent( QMouseEvent* event )
0204 {
0205     if( event->button() == Qt::LeftButton )
0206         m_startPos = event->pos();            //store the start position
0207     QWidget::mousePressEvent( event );    //feed it to parent's event
0208 }
0209 
0210 void
0211 Token::mouseMoveEvent( QMouseEvent* event )
0212 {
0213     if( isEnabled() &&
0214         event->buttons() & Qt::LeftButton )
0215     {
0216         int distance = ( event->pos() - m_startPos ).manhattanLength();
0217         if ( distance >= QApplication::startDragDistance() )
0218             performDrag();
0219     }
0220     QWidget::mouseMoveEvent( event );
0221 }
0222 
0223 //Handles the creation of a QDrag object that carries the (text-only) QDataStream from an item in TokenPool
0224 void
0225 Token::performDrag()
0226 {
0227     bool stacked = parentWidget() && qobject_cast<TokenDropTarget*>( parentWidget() ); // true if token originated from a TokenDropTarget.
0228     if( stacked )
0229         hide();
0230 
0231     QDrag *drag = new QDrag( this );
0232     drag->setMimeData( mimeData() );
0233 
0234     // icon for pointer
0235     QPixmap pixmap( size() );
0236     render( &pixmap );
0237     drag->setPixmap( pixmap );
0238     drag->setHotSpot ( pixmap.rect().center() );
0239 
0240     Qt::DropAction dropAction = drag->exec( Qt::MoveAction | Qt::CopyAction, Qt::CopyAction );
0241 
0242     if( dropAction != Qt::MoveAction && dropAction != Qt::CopyAction ) // dragged out and not just dragged to another position.
0243     {
0244         // TODO: nice poof animation? ;-)
0245         Q_EMIT removed( this );
0246         deleteLater();
0247     }
0248 
0249 }
0250 
0251 void Token::paintEvent(QPaintEvent *pe)
0252 {
0253     Q_UNUSED( pe )
0254 
0255     QPainter p( this );
0256     p.setBrush( Qt::NoBrush );
0257     p.setRenderHint( QPainter::Antialiasing );
0258     QColor c;
0259     if( isEnabled() && hasFocus() )
0260     {
0261         c = palette().color( QPalette::Highlight );
0262     }
0263     else if( isEnabled() )
0264     {
0265         c = palette().color( foregroundRole() );
0266         c.setAlpha( c.alpha() * 0.5 );
0267     }
0268     else
0269     {
0270         c = palette().color( foregroundRole() );
0271         c.setAlpha( c.alpha() * 0.3 );
0272     }
0273     p.setPen( QPen( c, 2 ) );
0274     p.drawRoundedRect( rect().adjusted(1,1,-1,-1), 4, 4 );
0275     p.end();
0276 }
0277 
0278