File indexing completed on 2024-05-19 04:48:39

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Daniel Jones <danielcjones@gmail.com>                             *
0003  * Copyright (c) 2009-2010 Leo Franchi <lfranchi@kde.org>                               *
0004  * Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org>                            *
0005  * Copyright (c) 2010-2011 Ralf Engels <ralf-engels@gmx.de>                             *
0006  *                                                                                      *
0007  * This program is free software; you can redistribute it and/or modify it under        *
0008  * the terms of the GNU General Public License as published by the Free Software        *
0009  * Foundation; either version 2 of the License, or (at your option) any later           *
0010  * version.                                                                             *
0011  *                                                                                      *
0012  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0013  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0014  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0015  *                                                                                      *
0016  * You should have received a copy of the GNU General Public License along with         *
0017  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0018  ****************************************************************************************/
0019 
0020 #include "DynamicCategory.h"
0021 #include "DynamicView.h"
0022 
0023 #include "amarokconfig.h"
0024 #include "core/support/Amarok.h"
0025 #include "core/support/Debug.h"
0026 #include "playlist/PlaylistActions.h"
0027 #include "playlist/PlaylistModelStack.h"
0028 #include "dynamic/DynamicModel.h"
0029 #include "dynamic/BiasedPlaylist.h"
0030 
0031 #include <QCheckBox>
0032 #include <QIcon>
0033 #include <QInputDialog>
0034 #include <QLabel>
0035 #include <QPushButton>
0036 #include <QSpinBox>
0037 #include <QStandardPaths>
0038 #include <QToolButton>
0039 
0040 #include <KToolBar>
0041 
0042 
0043 PlaylistBrowserNS::DynamicCategory::DynamicCategory( QWidget* parent )
0044     : BrowserCategory( QStringLiteral("dynamic category"), parent )
0045 {
0046     setPrettyName( i18n( "Dynamic Playlists" ) );
0047     setShortDescription( i18n( "Dynamically updating parameter based playlists" ) );
0048     setIcon( QIcon::fromTheme( QStringLiteral("dynamic-amarok") ) );
0049 
0050     setLongDescription( i18n( "With a dynamic playlist, Amarok becomes your own personal dj, automatically selecting tracks for you, based on a number of parameters that you select." ) );
0051 
0052     setImagePath( QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("amarok/images/hover_info_dynamic_playlists.png") ) );
0053 
0054     // set background
0055     if( AmarokConfig::showBrowserBackgroundImage() )
0056         setBackgroundImage( imagePath() );
0057 
0058     bool enabled = AmarokConfig::dynamicMode();
0059 
0060     setContentsMargins( 0, 0, 0, 0 );
0061 
0062     BoxWidget* controls2Layout = new BoxWidget( false, this );
0063 
0064     QLabel *label;
0065     label = new QLabel( i18n( "Previous:" ), controls2Layout );
0066     label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
0067 
0068     m_previous = new QSpinBox( controls2Layout );
0069     m_previous->setMinimum( 0 );
0070     m_previous->setToolTip( i18n( "Number of previous tracks to remain in the playlist." ) );
0071     m_previous->setValue( AmarokConfig::previousTracks() );
0072     connect( m_previous, QOverload<int>::of(&QSpinBox::valueChanged),
0073              this, &PlaylistBrowserNS::DynamicCategory::setPreviousTracks );
0074 
0075     label = new QLabel( i18n( "Upcoming:" ), controls2Layout );
0076     // label->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
0077     label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
0078 
0079     m_upcoming = new QSpinBox( controls2Layout );
0080     m_upcoming->setMinimum( 1 );
0081     m_upcoming->setToolTip( i18n( "Number of upcoming tracks to add to the playlist." ) );
0082     m_upcoming->setValue( AmarokConfig::upcomingTracks() );
0083     connect( m_upcoming, QOverload<int>::of(&QSpinBox::valueChanged),
0084              this, &PlaylistBrowserNS::DynamicCategory::setUpcomingTracks );
0085 
0086 
0087     connect( Amarok::actionCollection()->action( QStringLiteral("playlist_clear") ),  &QAction::triggered,  this, &DynamicCategory::playlistCleared );
0088     connect( Amarok::actionCollection()->action( QStringLiteral("disable_dynamic") ),  &QAction::triggered,  this, &DynamicCategory::playlistCleared, Qt::DirectConnection );
0089 
0090 
0091     // -- the tool bar
0092 
0093     BoxWidget* presetLayout = new BoxWidget( false, this );
0094     KToolBar* presetToolbar = new KToolBar( presetLayout );
0095     presetToolbar->setIconSize( QSize( 22, 22 ) );
0096 
0097     presetToolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
0098     presetToolbar->setMovable( false );
0099     presetToolbar->setFloatable( false );
0100     presetToolbar->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
0101 
0102     m_onOffButton = new QToolButton( presetToolbar );
0103     m_onOffButton->setText( i18nc( "Turn dynamic mode on", "On") );
0104     m_onOffButton->setCheckable( true );
0105     m_onOffButton->setIcon( QIcon::fromTheme( QStringLiteral("dynamic-amarok") ) );
0106     m_onOffButton->setToolTip( i18n( "Turn dynamic mode on." ) );
0107     presetToolbar->addWidget( m_onOffButton );
0108 
0109     m_duplicateButton = new QToolButton( presetToolbar );
0110     m_duplicateButton->setText( i18n("Duplicates") );
0111     m_duplicateButton->setCheckable( true );
0112     m_duplicateButton->setChecked( allowDuplicates() );
0113     m_duplicateButton->setIcon( QIcon::fromTheme( QStringLiteral("edit-copy") ) );
0114     m_duplicateButton->setToolTip( i18n( "Allow duplicate songs in result" ) );
0115     presetToolbar->addWidget( m_duplicateButton );
0116 
0117     m_addButton = new QToolButton( presetToolbar );
0118     m_addButton->setText( i18n("New") );
0119     m_addButton->setIcon( QIcon::fromTheme( QStringLiteral("document-new") ) );
0120     m_addButton->setToolTip( i18n( "New playlist" ) );
0121     presetToolbar->addWidget( m_addButton );
0122 
0123     m_editButton = new QToolButton( presetToolbar );
0124     m_editButton->setText( i18n("Edit") );
0125     m_editButton->setIcon( QIcon::fromTheme( QStringLiteral("document-properties-amarok") ) );
0126     m_editButton->setToolTip( i18n( "Edit the selected playlist or bias" ) );
0127     presetToolbar->addWidget( m_editButton );
0128 
0129     m_deleteButton = new QToolButton( presetToolbar );
0130     m_deleteButton->setText( i18n("Delete") );
0131     m_deleteButton->setEnabled( false );
0132     m_deleteButton->setIcon( QIcon::fromTheme( QStringLiteral("edit-delete") ) );
0133     m_deleteButton->setToolTip( i18n( "Delete the selected playlist or bias") );
0134     presetToolbar->addWidget( m_deleteButton );
0135 
0136     m_repopulateButton = new QPushButton( presetLayout );
0137     m_repopulateButton->setText( i18n("Repopulate") );
0138     m_repopulateButton->setToolTip( i18n("Replace the upcoming tracks with fresh ones.") );
0139     m_repopulateButton->setIcon( QIcon::fromTheme( QStringLiteral("view-refresh-amarok") ) );
0140     m_repopulateButton->setEnabled( enabled );
0141     // m_repopulateButton->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
0142     QObject::connect( m_repopulateButton, &QAbstractButton::clicked, The::playlistActions(), &Playlist::Actions::repopulateDynamicPlaylist );
0143 
0144 
0145     // -- the tree view
0146 
0147     m_tree = new DynamicView( this );
0148     connect( m_tree->selectionModel(), &QItemSelectionModel::selectionChanged,
0149              this, &DynamicCategory::selectionChanged );
0150 
0151     connect( m_onOffButton, &QAbstractButton::toggled, The::playlistActions(), &Playlist::Actions::enableDynamicMode );
0152     connect( m_duplicateButton, &QAbstractButton::toggled, this, &DynamicCategory::setAllowDuplicates );
0153 
0154     connect( m_addButton, &QAbstractButton::clicked, m_tree, &DynamicView::addPlaylist );
0155     connect( m_editButton, &QAbstractButton::clicked, m_tree, &DynamicView::editSelected );
0156     connect( m_deleteButton, &QAbstractButton::clicked, m_tree, &DynamicView::removeSelected );
0157 
0158     navigatorChanged();
0159     selectionChanged();
0160 
0161     connect( The::playlistActions(), &Playlist::Actions::navigatorChanged,
0162              this, &DynamicCategory::navigatorChanged );
0163 }
0164 
0165 
0166 PlaylistBrowserNS::DynamicCategory::~DynamicCategory()
0167 { }
0168 
0169 void
0170 PlaylistBrowserNS::DynamicCategory::navigatorChanged()
0171 {
0172     m_onOffButton->setChecked( AmarokConfig::dynamicMode() );
0173     m_repopulateButton->setEnabled( AmarokConfig::dynamicMode() );
0174 }
0175 
0176 void
0177 PlaylistBrowserNS::DynamicCategory::selectionChanged()
0178 {
0179     DEBUG_BLOCK;
0180 
0181     QModelIndexList indexes = m_tree->selectionModel()->selectedIndexes();
0182 
0183     if( indexes.isEmpty() )
0184     {
0185         m_addButton->setEnabled( true );
0186         m_editButton->setEnabled( false );
0187         m_deleteButton->setEnabled( false );
0188         return;
0189     }
0190 
0191     QVariant v = m_tree->model()->data( indexes.first(), Dynamic::DynamicModel::PlaylistRole );
0192     if( v.isValid() )
0193     {
0194         m_addButton->setEnabled( true );
0195         m_editButton->setEnabled( true );
0196         m_deleteButton->setEnabled( true );
0197         return;
0198     }
0199 
0200     v = m_tree->model()->data( indexes.first(), Dynamic::DynamicModel::BiasRole );
0201     if( v.isValid() )
0202     {
0203         m_addButton->setEnabled( true );
0204         m_editButton->setEnabled( true );
0205         m_deleteButton->setEnabled( false ); // TODO
0206         return;
0207     }
0208 }
0209 
0210 bool
0211 PlaylistBrowserNS::DynamicCategory::allowDuplicates() const
0212 {
0213     return AmarokConfig::dynamicDuplicates();
0214 }
0215 
0216 
0217 void
0218 PlaylistBrowserNS::DynamicCategory::playlistCleared() // SLOT
0219 {
0220     The::playlistActions()->enableDynamicMode( false );
0221 }
0222 
0223 void
0224 PlaylistBrowserNS::DynamicCategory::setUpcomingTracks( int n ) // SLOT
0225 {
0226     if( n >= 1 )
0227         AmarokConfig::setUpcomingTracks( n );
0228 }
0229 
0230 void
0231 PlaylistBrowserNS::DynamicCategory::setPreviousTracks( int n ) // SLOT
0232 {
0233     if( n >= 0 )
0234         AmarokConfig::setPreviousTracks( n );
0235 }
0236 
0237 void
0238 PlaylistBrowserNS::DynamicCategory::setAllowDuplicates( bool value ) // SLOT
0239 {
0240     if( AmarokConfig::dynamicDuplicates() == value )
0241         return;
0242 
0243     AmarokConfig::setDynamicDuplicates( value );
0244     AmarokConfig::self()->save();
0245 
0246     m_duplicateButton->setChecked( value );
0247 }
0248 
0249 
0250