?? playlistbrowser.cpp
字號:
/*************************************************************************** * copyright : (c) 2004 Pierpaolo Di Panfilo * * (c) 2004 Mark Kretschmann <markey@web.de> * * (c) 2005-2006 Seb Ruiz <me@sebruiz.net> * * (c) 2005 Gábor Lehel <illissius@gmail.com> * * (c) 2005 Christian Muehlhaeuser <chris@chris.de> * * (c) 2006 Alexandre Oliveira <aleprj@gmail.com> * * (c) 2006 Adam Pigg <adam@piggz.co.uk> * * See COPYING file for licensing information * ***************************************************************************/#define DEBUG_PREFIX "PlaylistBrowser"#include "amarok.h" //actionCollection()#include "browserToolBar.h"#include "collectiondb.h" //smart playlists#include "debug.h"#include "htmlview.h"#include "k3bexporter.h"#include "mediabrowser.h"#include "dynamicmode.h"#include "lastfm.h"#include "playlist.h"#include "playlistbrowser.h"#include "playlistbrowseritem.h"#include "playlistselection.h"#include "podcastbundle.h"#include "podcastsettings.h"#include "scancontroller.h"#include "smartplaylisteditor.h"#include "tagdialog.h" //showContextMenu()#include "threadmanager.h"#include "statusbar.h"#include "contextbrowser.h"#include "xspfplaylist.h"#include <qevent.h> //customEvent()#include <qheader.h> //mousePressed()#include <qlabel.h>#include <qpainter.h> //paintCell()#include <qpixmap.h> //paintCell()#include <qtextstream.h> //loadPlaylists(), saveM3U(), savePLS()#include <kaction.h>#include <kactionclasses.h>#include <kactioncollection.h>#include <kapplication.h>#include <kfiledialog.h> //openPlaylist()#include <kio/job.h> //deleteSelectedPlaylists()#include <kiconloader.h> //smallIcon#include <kinputdialog.h>#include <klineedit.h> //rename()#include <klocale.h>#include <kmessagebox.h> //renamePlaylist(), deleteSelectedPlaylist()#include <kmimetype.h>#include <kmultipledrag.h> //dragObject()#include <kpopupmenu.h>#include <kpushbutton.h>#include <kstandarddirs.h> //KGlobal::dirs()#include <kurldrag.h> //dragObject()#include <cstdio> //rename() in renamePlaylist()namespace Amarok { QListViewItem* findItemByPath( QListView *view, QString name ) { const static QString escaped( "\\/" ); const static QChar sep( '/' ); debug() << "Searching " << name << endl; QStringList path = splitPath( name ); QListViewItem *prox = view->firstChild(); QListViewItem *item = 0; foreach( path ) { item = prox; QString text( *it ); text.replace( escaped, sep ); for ( ; item; item = item->nextSibling() ) { if ( text == item->text(0) ) { break; } } if ( !item ) return 0; prox = item->firstChild(); } return item; } QStringList splitPath( QString path ) { QStringList list; const static QChar sep( '/' ); int bOffset = 0, sOffset = 0; int pos = path.find( sep, bOffset ); while ( pos != -1 ) { if ( pos > sOffset && pos <= (int)path.length() ) { if ( pos > 0 && path[pos-1] != '\\' ) { list << path.mid( sOffset, pos - sOffset ); sOffset = pos + 1; } } bOffset = pos + 1; pos = path.find( sep, bOffset ); } int length = path.length() - 1; if ( path.mid( sOffset, length - sOffset + 1 ).length() > 0 ) list << path.mid( sOffset, length - sOffset + 1 ); return list; }}inline QStringfileExtension( const QString &fileName ){ return Amarok::extension( fileName );}PlaylistBrowser *PlaylistBrowser::s_instance = 0;PlaylistBrowser::PlaylistBrowser( const char *name ) : QVBox( 0, name ) , m_polished( false ) , m_playlistCategory( 0 ) , m_streamsCategory( 0 ) , m_smartCategory( 0 ) , m_dynamicCategory( 0 ) , m_podcastCategory( 0 ) , m_coolStreams( 0 ) , m_smartDefaults( 0 ) , m_lastfmCategory( 0 ) , m_shoutcastCategory( 0 ) , m_lastPlaylist( 0 ) , m_coolStreamsOpen( false ) , m_smartDefaultsOpen( false ) , m_lastfmOpen( false ) , m_ac( new KActionCollection( this ) ) , m_podcastTimer( new QTimer( this ) ){ s_instance = this; QVBox *browserBox = new QVBox( this ); browserBox->setSpacing( 3 ); //<Toolbar> addMenuButton = new KActionMenu( i18n("Add"), Amarok::icon( "add_playlist" ), m_ac ); addMenuButton->setDelayed( false ); KPopupMenu *playlistMenu = new KPopupMenu( this ); playlistMenu->insertItem( i18n("New..."), PLAYLIST ); playlistMenu->insertItem( i18n("Import Existing..."), PLAYLIST_IMPORT ); connect( playlistMenu, SIGNAL( activated(int) ), SLOT( slotAddPlaylistMenu(int) ) ); KPopupMenu *addMenu = addMenuButton->popupMenu(); addMenu->insertItem( i18n("Playlist"), playlistMenu ); addMenu->insertItem( i18n("Smart Playlist..."), SMARTPLAYLIST ); addMenu->insertItem( i18n("Dynamic Playlist..."), ADDDYNAMIC); addMenu->insertItem( i18n("Radio Stream..."), STREAM ); addMenu->insertItem( i18n("Podcast..."), PODCAST ); connect( addMenu, SIGNAL( activated(int) ), SLOT( slotAddMenu(int) ) ); renameButton = new KAction( i18n("Rename"), "editclear", 0, this, SLOT( renameSelectedItem() ), m_ac ); removeButton = new KAction( i18n("Delete"), Amarok::icon( "remove" ), 0, this, SLOT( removeSelectedItems() ), m_ac ); m_toolbar = new Browser::ToolBar( browserBox ); m_toolbar->setIconText( KToolBar::IconTextRight, false ); //we want the open button to have text on right addMenuButton->plug( m_toolbar ); m_toolbar->setIconText( KToolBar::IconOnly, false ); //default appearance m_toolbar->insertLineSeparator(); renameButton->plug( m_toolbar); removeButton->plug( m_toolbar ); renameButton->setEnabled( false ); removeButton->setEnabled( false ); //</Toolbar> m_splitter = new QSplitter( Qt::Vertical, browserBox ); m_splitter->setChildrenCollapsible( false ); // hiding the InfoPane entirely can only be confusing m_listview = new PlaylistBrowserView( m_splitter ); int sort = Amarok::config( "PlaylistBrowser" )->readNumEntry( "Sorting", Qt::Ascending ); m_listview->setSorting( 0, sort == Qt::Ascending ? true : false ); m_podcastTimerInterval = Amarok::config( "PlaylistBrowser" )->readNumEntry( "Podcast Interval", 14400000 ); connect( m_podcastTimer, SIGNAL(timeout()), this, SLOT(scanPodcasts()) ); // signals and slots connections connect( m_listview, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ), this, SLOT( showContextMenu( QListViewItem *, const QPoint &, int ) ) ); connect( m_listview, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ), this, SLOT( invokeItem( QListViewItem *, const QPoint &, int ) ) ); connect( m_listview, SIGNAL( itemRenamed( QListViewItem*, const QString&, int ) ), this, SLOT( renamePlaylist( QListViewItem*, const QString&, int ) ) ); connect( m_listview, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( currentItemChanged( QListViewItem * ) ) ); connect( CollectionDB::instance(), SIGNAL( scanDone( bool ) ), SLOT( collectionScanDone() ) ); setMinimumWidth( m_toolbar->sizeHint().width() ); m_infoPane = new InfoPane( m_splitter ); m_podcastCategory = loadPodcasts(); setSpacing( 4 ); setFocusProxy( m_listview );}voidPlaylistBrowser::polish(){ // we make startup faster by doing the slow bits for this // only when we are shown on screen DEBUG_FUNC_INFO Amarok::OverrideCursor cursor;// blockSignals( true );// BrowserBar::instance()->restoreWidth();// blockSignals( false ); QVBox::polish(); /// Podcasting is always initialised in the ctor because of autoscanning m_polished = true; m_playlistCategory = loadPlaylists(); if( !CollectionDB::instance()->isEmpty() ) { m_smartCategory = loadSmartPlaylists(); loadDefaultSmartPlaylists(); }#define config Amarok::config( "PlaylistBrowser" ) m_dynamicCategory = loadDynamics(); m_randomDynamic = new DynamicEntry( m_dynamicCategory, 0, i18n("Random Mix") ); m_randomDynamic->setKept( false ); //don't save it m_randomDynamic->setCycleTracks( config->readBoolEntry( "Dynamic Random Remove Played", true ) ); m_randomDynamic->setUpcomingCount( config->readNumEntry ( "Dynamic Random Upcoming Count", 15 ) ); m_randomDynamic->setPreviousCount( config->readNumEntry ( "Dynamic Random Previous Count", 5 ) ); m_suggestedDynamic = new DynamicEntry( m_dynamicCategory, m_randomDynamic, i18n("Suggested Songs" ) ); m_suggestedDynamic->setKept( false ); //don't save it m_suggestedDynamic->setAppendType( DynamicMode::SUGGESTION ); m_suggestedDynamic->setCycleTracks( config->readBoolEntry( "Dynamic Suggest Remove Played", true ) ); m_suggestedDynamic->setUpcomingCount( config->readNumEntry ( "Dynamic Suggest Upcoming Count", 15 ) ); m_suggestedDynamic->setPreviousCount( config->readNumEntry ( "Dynamic Suggest Previous Count", 5 ) );#undef config m_streamsCategory = loadStreams(); loadCoolStreams(); m_shoutcastCategory = new ShoutcastBrowser( m_streamsCategory ); if( !AmarokConfig::scrobblerUsername().isEmpty() ) { const bool subscriber = Amarok::config( "Scrobbler" )->readBoolEntry( "Subscriber", false ); loadLastfmStreams( subscriber ); } markDynamicEntries(); // ListView item state restoration: // First we check if the number of items in the listview is the same as it was on last // application exit. If true, we iterate over all items and restore their open/closed state. // Note: We ignore podcast items, because they are added dynamically added to the ListView. QValueList<int> stateList = Amarok::config( "PlaylistBrowser" )->readIntListEntry( "Item State" ); QListViewItemIterator it( m_listview ); uint count = 0; while ( it.current() ) { if( !isPodcastEpisode( it.current() ) ) ++count; ++it; } if ( count == stateList.count() ) { uint index = 0; it = QListViewItemIterator( m_listview ); while ( it.current() ) { if( !isPodcastEpisode( it.current() ) ) { it.current()->setOpen( stateList[index] ); ++index; } ++it; } } // Set height of InfoPane m_infoPane->setStoredHeight( Amarok::config( "PlaylistBrowser" )->readNumEntry( "InfoPane Height", 200 ) );}PlaylistBrowser::~PlaylistBrowser(){ DEBUG_BLOCK s_instance = 0; if( m_polished ) { savePlaylists(); saveSmartPlaylists(); saveDynamics(); saveStreams(); saveLastFm(); savePodcastFolderStates( m_podcastCategory ); QStringList list; for( uint i=0; i < m_dynamicEntries.count(); i++ ) { QListViewItem *item = m_dynamicEntries.at( i ); list.append( item->text(0) ); } Amarok::config( "PlaylistBrowser" )->writeEntry( "Sorting", m_listview->sortOrder() ); Amarok::config( "PlaylistBrowser" )->writeEntry( "Podcast Interval", m_podcastTimerInterval ); Amarok::config( "PlaylistBrowser" )->writeEntry( "Podcast Folder Open", m_podcastCategory->isOpen() ); Amarok::config( "PlaylistBrowser" )->writeEntry( "InfoPane Height", m_infoPane->getHeight() ); }}voidPlaylistBrowser::setInfo( const QString &title, const QString &info ){ m_infoPane->setInfo( title, info );}voidPlaylistBrowser::resizeEvent( QResizeEvent * ){ if( static_cast<QWidget*>( m_infoPane->child( "container" ) )->isShown() ) m_infoPane->setMaximumHeight( ( int )( m_splitter->height() / 1.5 ) );}voidPlaylistBrowser::markDynamicEntries(){ if( Amarok::dynamicMode() ) { QStringList playlists = Amarok::dynamicMode()->items(); for( uint i=0; i < playlists.count(); i++ ) { PlaylistBrowserEntry *item = dynamic_cast<PlaylistBrowserEntry*>( Amarok::findItemByPath( m_listview, playlists[i] ) ); if( item ) { m_dynamicEntries.append( item ); if( item->rtti() == PlaylistEntry::RTTI ) static_cast<PlaylistEntry*>( item )->setDynamic( true ); if( item->rtti() == SmartPlaylist::RTTI ) static_cast<SmartPlaylist*>( item )->setDynamic( true ); } } }}/** ************************************************************************* * STREAMS ************************************************************************* **/QString PlaylistBrowser::streamBrowserCache() const{ return Amarok::saveLocation() + "streambrowser_save.xml";}PlaylistCategory* PlaylistBrowser::loadStreams(){ QFile file( streamBrowserCache() ); QTextStream stream( &file ); stream.setEncoding( QTextStream::UnicodeUTF8 );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -