?? playlistbrowseritem.cpp
字號:
/*************************************************************************** * copyright : (c) 2004 Pierpaolo Di Panfilo * * (c) 2004 Mark Kretschmann <markey@web.de> * * (c) 2005-2006 Seb Ruiz <me@sebruiz.net> * * (c) 2005 Christian Muehlhaeuser <chris@chris.de> * * (c) 2006 Bart Cerneels <bart.cerneels@gmail.com> * * (c) 2006 Ian Monroe <ian@monroe.nu> * * (c) 2006 Alexandre Oliveira <aleprj@gmail.com> * * (c) 2006 Adam Pigg <adam@piggz.co.uk> * * (c) 2006 Bonne Eggleston <b.eggleston@gmail.com> * * See COPYING file for licensing information * ***************************************************************************/#include "amarok.h"#include "collectiondb.h"#include "debug.h"#include "dynamicmode.h"#include "k3bexporter.h"#include "playlist.h"#include "playlistbrowser.h"#include "playlistbrowseritem.h"#include "playlistloader.h" //load()#include "playlistselection.h"#include "podcastbundle.h"#include "podcastsettings.h"#include "progressBar.h"#include "metabundle.h"#include "statusbar.h"#include "tagdialog.h"#include "threadmanager.h"#include "mediabrowser.h"#include <qdatetime.h>#include <qfileinfo.h>#include <qlabel.h>#include <qpainter.h> //paintCell()#include <qpixmap.h> //paintCell()#include <qregexp.h>#include <kapplication.h> //Used for Shoutcast random name generation#include <kdeversion.h> //KDE_VERSION ifndefs. Remove this once we reach a kde 4 dep#include <kiconloader.h> //smallIcon#include <kio/jobclasses.h> //podcast retrieval#include <kio/job.h> //podcast retrieval#include <klocale.h>#include <kmessagebox.h> //podcast info box#include <kmimetype.h>#include <kpopupmenu.h>#include <krun.h>#include <kstandarddirs.h> //podcast loading icons#include <kstringhandler.h>#include <ktrader.h>#include <kurlrequester.h>#include <cstdio> //rename//////////////////////////////////////////////////////////////////////////////// CLASS PlaylistReader////////////////////////////////////////////////////////////////////////////class PlaylistReader : public ThreadManager::DependentJob{ public: PlaylistReader( QObject *recipient, const QString &path ) : ThreadManager::DependentJob( recipient, "PlaylistReader" ) , m_path( QDeepCopy<QString>( path ) ) {} virtual bool doJob() { DEBUG_BLOCK PlaylistFile pf = PlaylistFile( m_path ); title = pf.title(); for( BundleList::iterator it = pf.bundles().begin(); it != pf.bundles().end(); ++it ) bundles += MetaBundle( (*it).url() ); return true; } virtual void completeJob() { DEBUG_BLOCK PlaylistFile pf = PlaylistFile( m_path ); bundles = QDeepCopy<BundleList>( bundles ); title = QDeepCopy<QString>( title ); for( BundleList::iterator it = bundles.begin(); it != bundles.end(); ++it ) *it = QDeepCopy<MetaBundle>( *it ); ThreadManager::DependentJob::completeJob(); } BundleList bundles; QString title; private: const QString m_path;};//////////////////////////////////////////////////////////////////////////////// CLASS PlaylistBrowserEntry////////////////////////////////////////////////////////////////////////////intPlaylistBrowserEntry::compare( QListViewItem* item, int col, bool ascending ) const{ bool i1 = rtti() == PlaylistCategory::RTTI; bool i2 = item->rtti() == PlaylistCategory::RTTI; // If only one of them is a category, make it show up before if ( i1 != i2 ) return i1 ? -1 : 1; else if ( i1 ) //both are categories { PlaylistBrowser * const pb = PlaylistBrowser::instance(); QValueList<PlaylistCategory*> toplevels; //define a static order for the toplevel categories toplevels << pb->m_playlistCategory << pb->m_smartCategory << pb->m_dynamicCategory << pb->m_streamsCategory << pb->m_podcastCategory; for( int i = 0, n = toplevels.count(); i < n; ++i ) { if( this == toplevels[i] ) return ascending ? -1 : 1; //same order whether or not it's ascending if( item == toplevels[i] ) return ascending ? 1 : -1; } } return KListViewItem::compare(item, col, ascending);}voidPlaylistBrowserEntry::setKept( bool k ){ m_kept = k; if ( !k ) //Disable renaming by two single clicks setRenameEnabled( 0, false );}voidPlaylistBrowserEntry::updateInfo(){ PlaylistBrowser::instance()->setInfo( QString::null, QString::null ); return;}voidPlaylistBrowserEntry::slotDoubleClicked(){ warning() << "No functionality for item double click implemented" << endl;}voidPlaylistBrowserEntry::slotRenameItem(){ QListViewItem *parent = KListViewItem::parent(); while( parent ) { if( !static_cast<PlaylistBrowserEntry*>( parent )->isKept() ) return; if( !parent->parent() ) break; parent = parent->parent(); } setRenameEnabled( 0, true ); static_cast<PlaylistBrowserView*>( listView() )->rename( this, 0 );}voidPlaylistBrowserEntry::slotPostRenameItem( const QString /*newName*/ ){ setRenameEnabled( 0, false );}//////////////////////////////////////////////////////////////////////////////// CLASS PlaylistCategory////////////////////////////////////////////////////////////////////////////PlaylistCategory::PlaylistCategory( QListView *parent, QListViewItem *after, const QString &t, bool isFolder ) : PlaylistBrowserEntry( parent, after ) , m_title( t ) , m_id( -1 ) , m_folder( isFolder ){ setDragEnabled( false ); setRenameEnabled( 0, isFolder ); setPixmap( 0, SmallIcon( Amarok::icon( "files2" ) ) ); setText( 0, t );}PlaylistCategory::PlaylistCategory( PlaylistCategory *parent, QListViewItem *after, const QString &t, bool isFolder ) : PlaylistBrowserEntry( parent, after ) , m_title( t ) , m_id( -1 ) , m_folder( isFolder ){ setDragEnabled( false ); setRenameEnabled( 0, isFolder ); setPixmap( 0, SmallIcon( Amarok::icon( "files" ) ) ); setText( 0, t );}PlaylistCategory::PlaylistCategory( QListView *parent, QListViewItem *after, const QDomElement &xmlDefinition, bool isFolder ) : PlaylistBrowserEntry( parent, after ) , m_id( -1 ) , m_folder( isFolder ){ setXml( xmlDefinition ); setDragEnabled( false ); setRenameEnabled( 0, isFolder ); setPixmap( 0, SmallIcon( Amarok::icon( "files2") ) );}PlaylistCategory::PlaylistCategory( PlaylistCategory *parent, QListViewItem *after, const QDomElement &xmlDefinition ) : PlaylistBrowserEntry( parent, after ) , m_id( -1 ) , m_folder( true ){ setXml( xmlDefinition ); setDragEnabled( false ); setRenameEnabled( 0, true ); setPixmap( 0, SmallIcon( Amarok::icon( "files" ) ) );}PlaylistCategory::PlaylistCategory( PlaylistCategory *parent, QListViewItem *after, const QString &t, const int id ) : PlaylistBrowserEntry( parent, after ) , m_title( t ) , m_id( id ) , m_folder( true ){ setDragEnabled( false ); setRenameEnabled( 0, true ); setPixmap( 0, SmallIcon( Amarok::icon( "files" ) ) ); setText( 0, t );}void PlaylistCategory::okRename( int col ){ QListViewItem::okRename( col ); if( m_id < 0 ) return; // update the database entry to have the correct name const int parentId = parent() ? static_cast<PlaylistCategory*>(parent())->id() : 0; CollectionDB::instance()->updatePodcastFolder( m_id, text(0), parentId, isOpen() );}void PlaylistCategory::setXml( const QDomElement &xml ){ PlaylistBrowser *pb = PlaylistBrowser::instance(); QString tname = xml.tagName(); if ( tname == "category" ) { setOpen( xml.attribute( "isOpen" ) == "true" ); m_title = xml.attribute( "name" ); setText( 0, m_title ); QListViewItem *last = 0; for( QDomNode n = xml.firstChild() ; !n.isNull(); n = n.nextSibling() ) { QDomElement e = n.toElement(); if ( e.tagName() == "category" ) last = new PlaylistCategory( this, last, e); else if ( e.tagName() == "default" ) { if( e.attribute( "type" ) == "stream" ) pb->m_coolStreamsOpen = (e.attribute( "isOpen" ) == "true"); if( e.attribute( "type" ) == "smartplaylist" ) pb->m_smartDefaultsOpen = (e.attribute( "isOpen" ) == "true"); if( e.attribute( "type" ) == "lastfm" ) pb->m_lastfmOpen = (e.attribute( "isOpen" ) == "true"); continue; } else if ( e.tagName() == "stream" ) last = new StreamEntry( this, last, e ); else if ( e.tagName() == "smartplaylist" ) last = new SmartPlaylist( this, last, e ); else if ( e.tagName() == "playlist" ) last = new PlaylistEntry( this, last, e ); else if ( e.tagName() == "lastfm" ) last = new LastFmEntry( this, last, e ); else if ( e.tagName() == "dynamic" ) { if ( e.attribute( "name" ) == i18n("Random Mix") || e.attribute( "name" ) == i18n("Suggested Songs" ) ) continue; last = new DynamicEntry( this, last, e ); } else if ( e.tagName() == "podcast" ) { const KURL url( n.namedItem( "url").toElement().text() ); QString xmlLocation = Amarok::saveLocation( "podcasts/" ); xmlLocation += n.namedItem( "cache" ).toElement().text(); QDomDocument xml; QFile xmlFile( xmlLocation ); QTextStream stream( &xmlFile ); stream.setEncoding( QTextStream::UnicodeUTF8 ); if( !xmlFile.open( IO_ReadOnly ) || !xml.setContent( stream.read() ) ) { // Invalid podcasts should still be added to the browser, which means there is no cached xml. last = new PodcastChannel( this, last, url, n ); } else last = new PodcastChannel( this, last, url, n, xml ); #define item static_cast<PodcastChannel*>(last) if( item->autoscan() ) pb->m_podcastItemsToScan.append( item ); #undef item } else if ( e.tagName() == "settings" ) PlaylistBrowser::instance()->registerPodcastSettings( title(), new PodcastSettings( e, title() ) ); if( !e.attribute( "isOpen" ).isNull() && last ) last->setOpen( e.attribute( "isOpen" ) == "true" ); //settings doesn't have an attribute "isOpen" } setText( 0, xml.attribute("name") ); }}QDomElement PlaylistCategory::xml() const{ QDomDocument d; QDomElement i = d.createElement("category"); i.setAttribute( "name", text(0) ); if( isOpen() ) i.setAttribute( "isOpen", "true" ); for( PlaylistBrowserEntry *it = static_cast<PlaylistBrowserEntry*>( firstChild() ); it; it = static_cast<PlaylistBrowserEntry*>( it->nextSibling() ) ) { if( it == PlaylistBrowser::instance()->m_coolStreams ) { QDomDocument doc; QDomElement e = doc.createElement("default"); e.setAttribute( "type", "stream" ); if( it->isOpen() ) e.setAttribute( "isOpen", "true" ); i.appendChild( d.importNode( e, true ) ); } else if( it == PlaylistBrowser::instance()->m_lastfmCategory ) { QDomDocument doc; QDomElement e = doc.createElement("default"); e.setAttribute( "type", "lastfm" ); if( it->isOpen() ) e.setAttribute( "isOpen", "true" ); i.appendChild( d.importNode( e, true ) ); } else if( it == PlaylistBrowser::instance()->m_smartDefaults ) { QDomDocument doc; QDomElement e = doc.createElement("default"); e.setAttribute( "type", "smartplaylist" ); if( it->isOpen() ) e.setAttribute( "isOpen", "true" ); i.appendChild( d.importNode( e, true ) ); } else if( it->isKept() ) i.appendChild( d.importNode( it->xml(), true ) ); } return i;}voidPlaylistCategory::slotDoubleClicked(){ setOpen( !isOpen() );}voidPlaylistCategory::slotRenameItem(){ if ( isKept() ) { setRenameEnabled( 0, true ); static_cast<PlaylistBrowserView*>( listView() )->rename( this, 0 ); }}voidPlaylistCategory::showContextMenu( const QPoint &position ){ KPopupMenu menu( listView() ); if( !isKept() ) return; enum Actions { RENAME, REMOVE, CREATE, PLAYLIST, PLAYLIST_IMPORT, SMART, STREAM, DYNAMIC, LASTFM, LASTFMCUSTOM, PODCAST, REFRESH, CONFIG, INTERVAL }; QListViewItem *parentCat = this; while( parentCat->parent() ) parentCat = parentCat->parent(); bool isPodcastFolder = false; if( isFolder() ) { menu.insertItem( SmallIconSet( Amarok::icon("edit") ), i18n( "&Rename" ), RENAME ); menu.insertItem( SmallIconSet( Amarok::icon("remove") ), i18n( "&Delete" ), REMOVE ); menu.insertSeparator(); } if( parentCat == static_cast<QListViewItem*>( PlaylistBrowser::instance()->m_playlistCategory) ) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -