File indexing completed on 2025-01-05 04:25:24

0001 /****************************************************************************************
0002  * Copyright (c) 2010 Emmanuel Wagner <manu.wagner@sfr.fr>                              *
0003  * Copyright (c) 2010 Mark Kretschmann <kretschmann@kde.org>                            *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #define DEBUG_PREFIX "CoverBlingApplet"
0019 
0020 #include "CoverBlingApplet.h"
0021 
0022 #include "EngineController.h"
0023 #include "context/ContextView.h"
0024 #include "context/widgets/RatingWidget.h"
0025 #include "context/widgets/TextScrollingWidget.h"
0026 #include "core/collections/Collection.h"
0027 #include "core/meta/Meta.h"
0028 #include "core/meta/Statistics.h"
0029 #include "core/support/Amarok.h"
0030 #include "core/support/Debug.h"
0031 #include "core-impl/collections/support/CollectionManager.h"
0032 #include "playlist/PlaylistModelStack.h"
0033 #include "SearchBarTextItem.h"
0034 #include "playlist/PlaylistController.h"
0035 
0036 #include <QAction>
0037 #include <KColorScheme>
0038 #include <KConfigDialog>
0039 #include <KGlobalSettings>
0040 #include <Plasma/BusyWidget>
0041 #include <Plasma/IconWidget>
0042 #include <Plasma/Theme>
0043 
0044 #include <QGraphicsLinearLayout>
0045 #include <QGraphicsProxyWidget>
0046 #include <QGraphicsSimpleTextItem>
0047 #include <QGraphicsWidget>
0048 #include <QLabel>
0049 #include <QPixmap>
0050 #include <QGraphicsPixmapItem>
0051 #include <KStandardDirs>
0052 #include <QDesktopWidget>
0053 
0054 CoverBlingApplet::CoverBlingApplet( QObject* parent, const QVariantList& args )
0055     : Context::Applet( parent, args )
0056 {
0057     DEBUG_BLOCK
0058 
0059     setHasConfigurationInterface( true );
0060 }
0061 
0062 void
0063 CoverBlingApplet::init()
0064 {
0065     // Call the base implementation.
0066     Context::Applet::init();
0067     setBackgroundHints( Plasma::Applet::NoBackground );
0068 
0069     m_fullsize = false;
0070 
0071     KConfigGroup config = Amarok::config( "CoverBling Applet" );
0072     m_coversize = config.readEntry( "CoverSize", 200 );
0073     int reflectioneffect = config.readEntry( "ReflectionEffect", 1 );
0074     if ( reflectioneffect == 0 )
0075         m_reflectionEffect = PictureFlow::NoReflection;
0076     else if ( reflectioneffect == 1 )
0077         m_reflectionEffect = PictureFlow::PlainReflection;
0078     else if ( reflectioneffect == 2 )
0079         m_reflectionEffect = PictureFlow::BlurredReflection;
0080     m_autojump = config.readEntry( "AutoJump", false );
0081     m_animatejump = config.readEntry( "AnimateJump", true );
0082     m_layout = new QGraphicsProxyWidget( this );
0083     m_openGL = false;
0084     //bool setting_opengl = config.readEntry( "OpenGL", false );
0085     //if (QGLFormat::hasOpenGL() && setting_opengl) m_openGL = true;
0086     
0087     m_pictureflow = new PhotoBrowser(0,m_openGL);
0088     m_layout->setWidget( m_pictureflow );
0089     
0090     m_pictureflow->setRenderHints( QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform );
0091 
0092     m_pictureflow->show();
0093 
0094     Collections::Collection *coll = CollectionManager::instance()->primaryCollection();
0095     Collections::QueryMaker *qm = coll->queryMaker();
0096     qm->setAutoDelete( true );
0097     qm->setQueryType( Collections::QueryMaker::Album );
0098     qm->orderBy( Meta::valArtist );
0099 
0100     connect( qm, SIGNAL(newResultReady(Meta::AlbumList)),
0101              this, SLOT(slotAlbumQueryResult(Meta::AlbumList)) );
0102     qm->run();
0103 
0104     m_label = new QGraphicsSimpleTextItem( this );
0105     m_label->setBrush( QBrush( Qt::white ) );
0106     QFont labelFont;
0107     QFont bigFont( labelFont );
0108     bigFont.setPointSize( bigFont.pointSize() + 4 );
0109     m_label->setFont( labelFont );
0110 
0111     m_ratingWidget = new RatingWidget( this );
0112     m_ratingWidget->setRating( 0 );
0113     m_ratingWidget->setEnabled( false );
0114 
0115     // Construct icon widgets
0116     m_blingtofirst = new Plasma::IconWidget( this );
0117     m_blingtofirst->setIcon( KStandardDirs::locate( "data", "amarok/images/blingtofirst.png" ) );
0118     m_blingtofirst->setMaximumSize( 16.0, 16.0 );
0119     m_blingtofirst->setToolTip( i18n( "Jump to First" ) );
0120 
0121     m_blingtolast = new Plasma::IconWidget( this );
0122     m_blingtolast->setIcon( KStandardDirs::locate( "data", "amarok/images/blingtolast.png" ) );
0123     m_blingtolast->setMaximumSize( 16.0, 16.0 );
0124     m_blingtolast->setToolTip( i18n( "Jump to Last" ) );
0125 
0126     m_blingfastback = new Plasma::IconWidget( this );
0127     m_blingfastback->setIcon( KStandardDirs::locate( "data", "amarok/images/blingfastback.png" ) );
0128     m_blingfastback->setMaximumSize( 16.0, 16.0 );
0129     m_blingfastback->setToolTip( i18n( "Fast Backward" ) );
0130 
0131     m_blingfastforward = new Plasma::IconWidget( this );
0132     m_blingfastforward->setIcon( KStandardDirs::locate( "data", "amarok/images/blingfastforward.png" ) );
0133     m_blingfastforward->setMaximumSize( 16.0, 16.0 );
0134     m_blingfastforward->setToolTip( i18n( "Fast Forward" ) );
0135 
0136     m_fullscreen = new Plasma::IconWidget( this );
0137     m_fullscreen->setIcon( KStandardDirs::locate( "data", "amarok/images/blingfullscreen.png" ) );
0138     m_fullscreen->setMaximumSize( 16.0, 16.0 );
0139     m_fullscreen->setToolTip( i18n( "Maximize/Minimize" ) );
0140 
0141     m_jumptoplaying = new Plasma::IconWidget( this );
0142     m_jumptoplaying->setIcon( KStandardDirs::locate( "data", "amarok/images/blingjumptoplaying.png" ) );
0143     m_jumptoplaying->setMaximumSize( 16.0, 16.0 );
0144     m_jumptoplaying->setToolTip( i18n( "Jump to Current" ) );
0145 
0146     m_albumsearch = new Plasma::IconWidget( this );
0147     m_albumsearch->setIcon( KStandardDirs::locate( "data", "amarok/images/blingsearchalbum.png" ) );
0148     m_albumsearch->setMaximumSize( 18.0, 18.0 );
0149     m_albumsearch->setToolTip( i18n( "Toggle Album/Artist search" ) );
0150     m_editsearch = new SearchBarTextItem( this );
0151     m_editsearch->setTextInteractionFlags( Qt::TextEditorInteraction );
0152     labelFont.setItalic( true );
0153     m_editsearch->setFont( labelFont );
0154     m_editsearch->setDefaultTextColor( Qt::white );
0155     m_album_or_artist = true;
0156     displaySearchName();
0157 
0158     m_initrandompos = config.readEntry( "RandomPos", false );
0159 
0160     if ( m_autojump )
0161     {
0162       EngineController *engine = The::engineController();
0163       connect( engine, SIGNAL(trackPlaying(Meta::TrackPtr)),
0164           this, SLOT(jumpToPlaying()) );
0165     }
0166 }
0167 
0168 CoverBlingApplet::~CoverBlingApplet()
0169 {
0170     delete m_ratingWidget;
0171     delete m_label;
0172     delete m_layout;
0173     delete m_blingfastback;
0174     delete m_blingfastforward;
0175     delete m_blingtofirst;
0176     delete m_blingtolast;
0177     delete m_jumptoplaying;
0178     delete m_albumsearch;
0179     delete m_editsearch;
0180 }
0181 
0182 void CoverBlingApplet::slotAlbumQueryResult( Meta::AlbumList albums ) //SLOT
0183 {
0184     DEBUG_BLOCK
0185     m_pictureflow->fillAlbums( albums );
0186 
0187     connect( m_pictureflow, SIGNAL(centerIndexChanged(int)), this, SLOT(slideChanged(int)) );
0188     connect( m_pictureflow, SIGNAL(doubleClicked(int)), this, SLOT(slotDoubleClicked(int)) );
0189     connect( m_blingtofirst, SIGNAL(clicked()), this, SLOT(skipToFirst()) );
0190     connect( m_blingtolast, SIGNAL(clicked()), this, SLOT(skipToLast()) );
0191     connect( m_blingfastback, SIGNAL(clicked()), m_pictureflow, SLOT(fastBackward()) );
0192     connect( m_blingfastforward, SIGNAL(clicked()), m_pictureflow, SLOT(fastForward()) );
0193     connect( m_fullscreen, SIGNAL(clicked()), this, SLOT(toggleFullscreen()) );
0194     connect( m_jumptoplaying, SIGNAL(clicked()), this, SLOT(jumpToPlaying()) );
0195     connect( m_albumsearch, SIGNAL(clicked()), this, SLOT(switchSearchIcon()) );
0196     connect( m_editsearch, SIGNAL(editionValidated(QString)), this, SLOT(albumSearch(QString)) );
0197     if (m_initrandompos)
0198     {
0199         int nbAlbums = m_pictureflow->slideCount() -1;
0200         int initial_pos = rand() % nbAlbums;
0201         if ( m_animatejump )
0202         {
0203         m_pictureflow->skipToSlide( initial_pos - 10 );
0204             m_pictureflow->showSlide( initial_pos );
0205         }
0206         else
0207            m_pictureflow->skipToSlide( initial_pos );
0208         slideChanged( initial_pos );
0209     }
0210     constraintsEvent();
0211 }
0212 
0213 void CoverBlingApplet::slideChanged( int islideindex )
0214 {
0215     Meta::AlbumPtr album = m_pictureflow->album( islideindex );
0216     if ( album )
0217     {
0218         Meta::ArtistPtr artist = album->albumArtist();
0219         QString label = album->prettyName();
0220         if ( artist ) label += " - " + artist->prettyName();
0221         m_label->setText( label );
0222 
0223         //center the label
0224         m_label->setPos( ( size().width() - m_label->boundingRect().width() ) / 2, m_label->y() );
0225  
0226         m_label->show();
0227         int nbtracks = 0;
0228         int rating = 0;
0229 
0230         foreach( Meta::TrackPtr track, album->tracks() )
0231         {
0232             nbtracks++;
0233             if ( track )
0234                 rating += track->statistics()->rating();
0235         }
0236 
0237         if ( nbtracks )
0238             rating = rating / nbtracks;
0239 
0240         m_ratingWidget->setRating( rating );
0241     }
0242 }
0243 
0244 void CoverBlingApplet::slotDoubleClicked( int islideindex )
0245 {
0246     Meta::AlbumPtr album = m_pictureflow->album( islideindex );
0247     if ( album )
0248         The::playlistController()->insertOptioned( album->tracks(), Playlist::OnDoubleClickOnSelectedItems );
0249 }
0250 
0251 void CoverBlingApplet::constraintsEvent( Plasma::Constraints constraints )
0252 {
0253     Q_UNUSED( constraints )
0254 
0255     prepareGeometryChange();
0256     const int vertical_size = boundingRect().height();
0257     const int horizontal_size = boundingRect().width();
0258     QSize slideSize( vertical_size / 2, vertical_size / 2 );
0259 
0260     if ( !m_fullsize )
0261     {
0262         slideSize.setWidth( m_coversize );
0263         slideSize.setHeight( m_coversize );
0264     }
0265     setMinimumHeight( 2 * m_coversize ); 
0266     m_pictureflow->setSlideSize( slideSize );
0267     m_pictureflow->setReflectionEffect( m_reflectionEffect );
0268     m_pictureflow->setAnimationTime( 10 );
0269     m_ratingWidget->setSpacing( 2 );
0270     m_ratingWidget->setPos( horizontal_size / 2 - 40, vertical_size - 30 );
0271     m_label ->setPos( horizontal_size / 2 - 40, vertical_size - 50 );
0272 
0273     m_blingtofirst->setPos( 20, vertical_size - 30 );
0274     m_blingtolast->setPos( horizontal_size - 30, vertical_size - 30 );
0275     m_blingfastback->setPos( 50, vertical_size - 30 );
0276     m_blingfastforward->setPos( horizontal_size - 60, vertical_size - 30 );
0277     m_fullscreen->setPos( horizontal_size - 30, 30 );
0278     m_jumptoplaying->setPos( horizontal_size - 60, 30 );
0279     m_albumsearch->setPos( 20, 30 );
0280     m_editsearch->setPos( 38, 28 );
0281     m_pictureflow->resize( horizontal_size, vertical_size );
0282 
0283     m_label->setPos( ( size().width() - m_label->boundingRect().width() ) / 2, m_label->y() );
0284 }
0285 
0286 void CoverBlingApplet::toggleFullscreen()
0287 {
0288     if ( m_fullsize )
0289     {
0290         resize( -1, -1 );
0291     }
0292     else
0293     {
0294         //QDesktopWidget* desktop = QApplication::desktop();
0295         //if (desktop)
0296         {
0297             //    QRect rect = desktop->screenGeometry();
0298             //    resize(rect.width(),rect.height());
0299             resize( -1, 2 * m_coversize );
0300         }
0301     }
0302     updateConstraints();
0303     //constraintsEvent();
0304     m_fullsize = !m_fullsize;
0305 }
0306 
0307 void CoverBlingApplet::createConfigurationInterface( KConfigDialog *parent )
0308 {
0309     KConfigGroup configuration = config();
0310     QWidget * const settings = new QWidget;
0311     ui_Settings.setupUi( settings );
0312 
0313     if ( m_reflectionEffect == PictureFlow::NoReflection )
0314         ui_Settings.reflectionEffectCombo->setCurrentIndex( 0 );
0315     else if ( m_reflectionEffect == PictureFlow::PlainReflection )
0316         ui_Settings.reflectionEffectCombo->setCurrentIndex( 1 );
0317     else if ( m_reflectionEffect == PictureFlow::BlurredReflection )
0318         ui_Settings.reflectionEffectCombo->setCurrentIndex( 2 );
0319     if ( m_coversize )
0320         ui_Settings.coversizeSpin->setValue( m_coversize );
0321     ui_Settings.autoJumpChk->setChecked( m_autojump );
0322     ui_Settings.animJumpChk->setChecked( m_animatejump );
0323     ui_Settings.randomPosChk->setChecked( m_initrandompos );
0324     //if (m_openGL) ui_Settings.renderingCombo->setCurrentIndex(1);
0325     //else ui_Settings.renderingCombo->setCurrentIndex(0);
0326     parent->addPage( settings, i18n( "Coverbling Settings" ), "preferences-system" );
0327     connect( parent, SIGNAL(accepted()), this, SLOT(saveSettings()) );
0328 }
0329 
0330 void CoverBlingApplet::saveSettings()
0331 {
0332     m_coversize = ui_Settings.coversizeSpin->value();
0333     if ( ui_Settings.reflectionEffectCombo->currentIndex() == 0 )
0334         m_reflectionEffect = PictureFlow::NoReflection;
0335     else if ( ui_Settings.reflectionEffectCombo->currentIndex() == 1 )
0336         m_reflectionEffect = PictureFlow::PlainReflection;
0337     else if ( ui_Settings.reflectionEffectCombo->currentIndex() == 2 )
0338         m_reflectionEffect = PictureFlow::BlurredReflection;
0339     //if (ui_Settings.renderingCombo->currentIndex()==1)
0340          //m_openGL = true;
0341     //else
0342          //m_openGL = false;
0343     m_autojump = ui_Settings.autoJumpChk->isChecked();
0344     m_animatejump = ui_Settings.animJumpChk->isChecked();
0345     m_initrandompos = ui_Settings.randomPosChk->isChecked();
0346     KConfigGroup config = Amarok::config( "CoverBling Applet" );
0347     config.writeEntry( "CoverSize", m_coversize );
0348     config.writeEntry( "ReflectionEffect", ( int ) m_reflectionEffect );
0349     config.writeEntry( "AutoJump", m_autojump );
0350     config.writeEntry( "AnimateJump", m_animatejump );
0351     config.writeEntry( "RandomPos", m_initrandompos );
0352     //config.writeEntry( "OpenGL", (int) m_openGL );
0353 
0354     constraintsEvent();
0355 }
0356 
0357 void CoverBlingApplet::jumpToPlaying()
0358 {
0359     Meta::TrackPtr track = The::engineController()->currentTrack();
0360 
0361     if ( !track )
0362         return;
0363     Meta::AlbumPtr album = track->album();
0364     if ( !album )
0365         return;
0366     int center = m_pictureflow->centerIndex();
0367     if ( m_pictureflow->album( center ) == album )
0368         return;
0369     int nbslides = m_pictureflow->slideCount();
0370     bool found = false;
0371     int index = 0;
0372     if ( nbslides > 0 )
0373     {
0374         for ( int i = 0; i < nbslides;i++ )
0375         {
0376             Meta::AlbumPtr current_album = m_pictureflow->album( i );
0377             if ( current_album == album )
0378             {
0379                 index = i;
0380                 found = true;
0381                 break;
0382             }
0383         }
0384         if ( found )
0385         {
0386             if ( m_animatejump )
0387             {
0388                 if ( center - index > 10 || index - center > 10 )
0389                 {
0390                     if ( index > center )
0391                         m_pictureflow->skipToSlide( index - 10 );
0392                     else
0393                         m_pictureflow->skipToSlide( index + 10 );
0394                 }
0395                 m_pictureflow->showSlide( index );
0396             }
0397             else
0398                 m_pictureflow->skipToSlide( index );
0399             slideChanged( index );
0400         }
0401     }
0402 }
0403 void CoverBlingApplet::skipToFirst()
0404 {
0405     m_pictureflow->skipToSlide( 0 );
0406     slideChanged( 0 );
0407 }
0408 
0409 void CoverBlingApplet::skipToLast()
0410 {
0411     int nbslides = m_pictureflow->slideCount();
0412     m_pictureflow->skipToSlide( nbslides - 1 );
0413     slideChanged( nbslides - 1 );
0414 }
0415 void CoverBlingApplet::albumSearch( QString ialbumName )
0416 {
0417     QString album_name = ialbumName.remove( QChar( ' ' ) );
0418     int center = m_pictureflow->centerIndex();
0419     int nbslides = m_pictureflow->slideCount();
0420     bool found = false;
0421     int index = 0;
0422     if ( nbslides > 0 )
0423     {
0424         for ( int i = 0; i < nbslides;i++ )
0425         {
0426             Meta::AlbumPtr current_album = m_pictureflow->album( i );
0427             if ( !current_album ) continue;
0428             QString current_name = "";
0429             if ( m_album_or_artist )
0430             {
0431                 current_name = current_album->prettyName();
0432             }
0433             else
0434             {
0435                 Meta::ArtistPtr artist = current_album->albumArtist();
0436                 if ( artist ) current_name = artist->prettyName();
0437             }
0438             current_name = current_name.remove( QChar( ' ' ) );
0439             if ( current_name.contains( album_name, Qt::CaseInsensitive ) )
0440             {
0441                 index = i;
0442                 found = true;
0443                 break;
0444             }
0445         }
0446         if ( found )
0447         {
0448             if ( m_animatejump )
0449             {
0450                 if ( center - index > 10 || index - center > 10 )
0451                 {
0452                     if ( index > center )
0453                         m_pictureflow->skipToSlide( index - 10 );
0454                     else
0455                         m_pictureflow->skipToSlide( index + 10 );
0456                 }
0457                 m_pictureflow->showSlide( index );
0458             }
0459             else
0460                 m_pictureflow->skipToSlide( index );
0461             slideChanged( index );
0462         }
0463     }
0464     displaySearchName();
0465 }
0466 
0467 void CoverBlingApplet::switchSearchIcon()
0468 {
0469     m_album_or_artist = !m_album_or_artist;
0470     if ( m_album_or_artist )
0471         m_albumsearch->setIcon( KStandardDirs::locate( "data", "amarok/images/blingsearchalbum.png" ) );
0472     else
0473         m_albumsearch->setIcon( KStandardDirs::locate( "data", "amarok/images/blingsearchartist.png" ) );
0474     displaySearchName();
0475 }
0476 void CoverBlingApplet::displaySearchName()
0477 {
0478     QString album_search_str = i18n( "Search for album..." );
0479     QString artist_search_str = i18n( "Search for artist..." );
0480     if ( m_album_or_artist)
0481         m_editsearch->setPlainText( album_search_str );
0482     else
0483         m_editsearch->setPlainText( artist_search_str );
0484 }
0485