|
|
|
/***************************************************************************
|
|
|
|
* 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) 2006 Adam Pigg <adam@piggz.co.uk> *
|
|
|
|
* See COPYING file for licensing information *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#ifndef PLAYLISTBROWSER_H
|
|
|
|
#define PLAYLISTBROWSER_H
|
|
|
|
|
|
|
|
#include "amarokconfig.h"
|
|
|
|
#include "playlistbrowseritem.h"
|
|
|
|
#include "podcastsettings.h"
|
|
|
|
|
|
|
|
#include <kaction.h>
|
|
|
|
#include <klistview.h>
|
|
|
|
#include <kpushbutton.h>
|
|
|
|
#include <kurl.h>
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqptrlist.h>
|
|
|
|
#include <tqvbox.h>
|
|
|
|
|
|
|
|
class KTextBrowser;
|
|
|
|
class KToolBar;
|
|
|
|
|
|
|
|
class TQCustomEvent;
|
|
|
|
class TQColorGroup;
|
|
|
|
class TQDragObject;
|
|
|
|
class TQPainter;
|
|
|
|
class TQPixmap;
|
|
|
|
class TQPoint;
|
|
|
|
class TQSplitter;
|
|
|
|
class TQTimer;
|
|
|
|
|
|
|
|
class HTMLView;
|
|
|
|
class InfoPane;
|
|
|
|
class PlaylistBrowserView;
|
|
|
|
class PlaylistTrackItem;
|
|
|
|
|
|
|
|
|
|
|
|
class PlaylistBrowser : public TQVBox
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
TQ_OBJECT
|
|
|
|
friend class DynamicMode;
|
|
|
|
friend class PlaylistBrowserView;
|
|
|
|
|
|
|
|
friend class PlaylistBrowserEntry;
|
|
|
|
friend class PlaylistCategory;
|
|
|
|
friend class PlaylistEntry;
|
|
|
|
friend class PlaylistTrackItem;
|
|
|
|
friend class PodcastChannel; //for changing podcast timer list
|
|
|
|
friend class PodcastEpisode;
|
|
|
|
friend class DynamicEntry;
|
|
|
|
friend class StreamEntry;
|
|
|
|
friend class SmartPlaylist;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
enum AddMode { PLAYLIST, PLAYLIST_IMPORT, STREAM, SMARTPLAYLIST, PODCAST, ADDDYNAMIC };
|
|
|
|
|
|
|
|
~PlaylistBrowser();
|
|
|
|
|
|
|
|
void setInfo( const TQString &title, const TQString &info );
|
|
|
|
|
|
|
|
void addStream( TQListViewItem *parent = 0 );
|
|
|
|
void addSmartPlaylist( TQListViewItem *parent = 0 );
|
|
|
|
void addDynamic( TQListViewItem *parent = 0 );
|
|
|
|
void addPlaylist( const TQString &path, TQListViewItem *parent = 0, bool force=false, bool imported=false );
|
|
|
|
PlaylistEntry *findPlaylistEntry( const TQString &url, TQListViewItem *parent=0 ) const;
|
|
|
|
int loadPlaylist( const TQString &playlist, bool force=false );
|
|
|
|
|
|
|
|
void addPodcast( TQListViewItem *parent = 0 );
|
|
|
|
void addPodcast( const KURL &url, TQListViewItem *parent = 0 );
|
|
|
|
void loadPodcastsFromDatabase( PlaylistCategory *p = 0 );
|
|
|
|
void registerPodcastSettings( const TQString &title, const PodcastSettings *settings );
|
|
|
|
|
|
|
|
static bool savePlaylist( const TQString &path, const TQValueList<KURL> &urls,
|
|
|
|
const TQValueList<TQString> &titles = TQValueList<TQString>(),
|
|
|
|
const TQValueList<int> &lengths = TQValueList<int>(),
|
|
|
|
bool relative = AmarokConfig::relativePlaylist() );
|
|
|
|
|
|
|
|
TQString dynamicBrowserCache() const;
|
|
|
|
TQString playlistBrowserCache() const;
|
|
|
|
TQString podcastBrowserCache() const;
|
|
|
|
TQString streamBrowserCache() const;
|
|
|
|
TQString smartplaylistBrowserCache() const;
|
|
|
|
|
|
|
|
PlaylistBrowserEntry *findItem( TQString &t, int c ) const;
|
|
|
|
TQListViewItem *findItemInTree( const TQString &searchstring, int c ) const;
|
|
|
|
PodcastEpisode *findPodcastEpisode( const KURL &episode, const KURL &feed ) const;
|
|
|
|
|
|
|
|
TQPtrList<PlaylistBrowserEntry> dynamicEntries() const { return m_dynamicEntries; }
|
|
|
|
DynamicMode *findDynamicModeByTitle( const TQString &title );
|
|
|
|
TQListViewItem *podcastCategory() const { return m_podcastCategory; }
|
|
|
|
|
|
|
|
static PlaylistBrowser *instance() {
|
|
|
|
if(!s_instance) s_instance = new PlaylistBrowser("PlaylistBrowser");
|
|
|
|
return s_instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
//following used by PlaylistSelection.cpp
|
|
|
|
PlaylistBrowserView* getListView() const { return m_listview; }
|
|
|
|
PlaylistCategory* getDynamicCategory() const { return m_dynamicCategory; }
|
|
|
|
void saveDynamics();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void resizeEvent( TQResizeEvent * );
|
|
|
|
|
|
|
|
signals:
|
|
|
|
void selectionChanged();
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void openPlaylist( TQListViewItem *parent = 0 );
|
|
|
|
void scanPodcasts();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void abortPodcastQueue();
|
|
|
|
void addSelectedToPlaylist( int options = -1 );
|
|
|
|
void collectionScanDone();
|
|
|
|
void currentItemChanged( TQListViewItem * );
|
|
|
|
void downloadPodcastQueue();
|
|
|
|
void editStreamURL( StreamEntry *item, const bool readOnly=false );
|
|
|
|
void removeSelectedItems();
|
|
|
|
void renamePlaylist( TQListViewItem*, const TQString&, int );
|
|
|
|
void renameSelectedItem();
|
|
|
|
void invokeItem( TQListViewItem*, const TQPoint &, int column );
|
|
|
|
void slotDoubleClicked( TQListViewItem *item );
|
|
|
|
|
|
|
|
void slotAddMenu( int id );
|
|
|
|
void slotAddPlaylistMenu( int id );
|
|
|
|
void showContextMenu( TQListViewItem*, const TQPoint&, int );
|
|
|
|
|
|
|
|
void loadDynamicItems();
|
|
|
|
|
|
|
|
private:
|
|
|
|
PlaylistBrowser( const char* name=0 );
|
|
|
|
void polish();
|
|
|
|
|
|
|
|
bool m_polished;
|
|
|
|
|
|
|
|
PlaylistCategory* loadStreams();
|
|
|
|
void loadCoolStreams();
|
|
|
|
void saveStreams();
|
|
|
|
|
|
|
|
void loadLastfmStreams( const bool subscriber = false );
|
|
|
|
void addLastFmRadio( TQListViewItem *parent );
|
|
|
|
void addLastFmCustomRadio( TQListViewItem *parent );
|
|
|
|
void saveLastFm();
|
|
|
|
|
|
|
|
PlaylistCategory* loadSmartPlaylists();
|
|
|
|
void loadDefaultSmartPlaylists();
|
|
|
|
void editSmartPlaylist( SmartPlaylist* );
|
|
|
|
void saveSmartPlaylists( PlaylistCategory *smartCategory = NULL );
|
|
|
|
void updateSmartPlaylists( TQListViewItem *root );
|
|
|
|
void updateSmartPlaylistElement( TQDomElement& query );
|
|
|
|
|
|
|
|
PlaylistCategory* loadDynamics();
|
|
|
|
void fixDynamicPlaylistPath( TQListViewItem *item );
|
|
|
|
TQString guessPathFromPlaylistName( TQString name );
|
|
|
|
|
|
|
|
PlaylistCategory* loadPodcasts();
|
|
|
|
TQMap<int,PlaylistCategory*> loadPodcastFolders( PlaylistCategory *p );
|
|
|
|
void changePodcastInterval();
|
|
|
|
void configurePodcasts( TQListViewItem *parent );
|
|
|
|
void configurePodcasts( TQPtrList<PodcastChannel> &podcastChannelList, const TQString &caption );
|
|
|
|
void configureSelectedPodcasts();
|
|
|
|
bool deleteSelectedPodcastItems( const bool removeItem=false, const bool silent=false );
|
|
|
|
bool deletePodcasts( TQPtrList<PodcastChannel> items );
|
|
|
|
void downloadSelectedPodcasts();
|
|
|
|
void refreshPodcasts( TQListViewItem *category );
|
|
|
|
void removePodcastFolder( PlaylistCategory *item );
|
|
|
|
void savePodcastFolderStates( PlaylistCategory *folder );
|
|
|
|
PodcastChannel *findPodcastChannel( const KURL &feed, TQListViewItem *parent=0 ) const;
|
|
|
|
|
|
|
|
void markDynamicEntries();
|
|
|
|
PlaylistBrowserEntry* findByName( TQString name );
|
|
|
|
|
|
|
|
PlaylistCategory* loadPlaylists();
|
|
|
|
void savePlaylists();
|
|
|
|
void savePlaylist( PlaylistEntry * );
|
|
|
|
bool createPlaylist( TQListViewItem *parent = 0, bool current = true, TQString title = 0 );
|
|
|
|
bool deletePlaylists( TQPtrList<PlaylistEntry> items );
|
|
|
|
bool deletePlaylists( KURL::List items );
|
|
|
|
|
|
|
|
void customEvent( TQCustomEvent* e );
|
|
|
|
void saveM3U( PlaylistEntry *, bool append );
|
|
|
|
void savePLS( PlaylistEntry *, bool append );
|
|
|
|
void saveXSPF( PlaylistEntry *, bool append );
|
|
|
|
|
|
|
|
static KURL::List recurse( const KURL &url );
|
|
|
|
|
|
|
|
static PlaylistBrowser *s_instance;
|
|
|
|
|
|
|
|
PlaylistCategory *m_playlistCategory;
|
|
|
|
PlaylistCategory *m_streamsCategory;
|
|
|
|
PlaylistCategory *m_smartCategory;
|
|
|
|
PlaylistCategory *m_dynamicCategory;
|
|
|
|
PlaylistCategory *m_podcastCategory;
|
|
|
|
PlaylistCategory *m_coolStreams;
|
|
|
|
PlaylistCategory *m_smartDefaults;
|
|
|
|
PlaylistCategory *m_lastfmCategory;
|
|
|
|
ShoutcastBrowser *m_shoutcastCategory;
|
|
|
|
PlaylistEntry *m_lastPlaylist;
|
|
|
|
|
|
|
|
DynamicEntry *m_randomDynamic;
|
|
|
|
DynamicEntry *m_suggestedDynamic;
|
|
|
|
|
|
|
|
bool m_coolStreamsOpen;
|
|
|
|
bool m_smartDefaultsOpen;
|
|
|
|
bool m_lastfmOpen;
|
|
|
|
|
|
|
|
PlaylistBrowserView *m_listview;
|
|
|
|
KActionCollection *m_ac;
|
|
|
|
KAction *removeButton;
|
|
|
|
KAction *renameButton;
|
|
|
|
KActionMenu *viewMenuButton;
|
|
|
|
KActionMenu *addMenuButton;
|
|
|
|
KToolBar *m_toolbar;
|
|
|
|
TQValueList<int> m_dynamicSizeSave;
|
|
|
|
|
|
|
|
TQDict<PodcastSettings> m_podcastSettings;
|
|
|
|
TQPtrList<PlaylistBrowserEntry> m_dynamicEntries;
|
|
|
|
|
|
|
|
TQTimer *m_podcastTimer;
|
|
|
|
int m_podcastTimerInterval; //in ms
|
|
|
|
TQPtrList<PodcastChannel> m_podcastItemsToScan;
|
|
|
|
TQPtrList<PodcastEpisode> m_podcastDownloadQueue;
|
|
|
|
|
|
|
|
InfoPane *m_infoPane;
|
|
|
|
|
|
|
|
bool m_removeDirt;
|
|
|
|
|
|
|
|
TQSplitter *m_splitter;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PlaylistBrowserView : public KListView
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
TQ_OBJECT
|
|
|
|
|
|
|
|
friend class PlaylistEntry;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PlaylistBrowserView( TQWidget *parent, const char *name=0 );
|
|
|
|
~PlaylistBrowserView();
|
|
|
|
|
|
|
|
void rename( TQListViewItem *item, int c );
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void keyPressEvent( TQKeyEvent * );
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void mousePressed( int, TQListViewItem *, const TQPoint &, int );
|
|
|
|
void moveSelectedItems( TQListViewItem* newParent );
|
|
|
|
|
|
|
|
private:
|
|
|
|
void startDrag();
|
|
|
|
void contentsDropEvent( TQDropEvent* );
|
|
|
|
void contentsDragEnterEvent( TQDragEnterEvent* );
|
|
|
|
void contentsDragMoveEvent( TQDragMoveEvent* );
|
|
|
|
void contentsDragLeaveEvent( TQDragLeaveEvent* );
|
|
|
|
void viewportPaintEvent( TQPaintEvent* );
|
|
|
|
void eraseMarker();
|
|
|
|
|
|
|
|
TQListViewItem *m_marker; //track that has the drag/drop marker under it
|
|
|
|
};
|
|
|
|
|
|
|
|
class PlaylistDialog: public KDialogBase
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
TQ_OBJECT
|
|
|
|
public:
|
|
|
|
static TQString getSaveFileName( const TQString &suggestion = TQString(), bool proposeOverwriting = false );
|
|
|
|
|
|
|
|
private:
|
|
|
|
KLineEdit *edit;
|
|
|
|
bool customChosen;
|
|
|
|
TQString result;
|
|
|
|
PlaylistDialog();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void slotOk();
|
|
|
|
|
|
|
|
void slotTextChanged( const TQString &s );
|
|
|
|
|
|
|
|
void slotCustomPath();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Returns true if item is Playlist, Stream, Smart Playlist or DynamicMode.
|
|
|
|
inline bool
|
|
|
|
isElement( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == ( PlaylistEntry::RTTI || StreamEntry::RTTI ||
|
|
|
|
SmartPlaylist::RTTI /*|| DynamicEntry::RTTI */) ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isCategory( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == PlaylistCategory::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isDynamic( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == DynamicEntry::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isPlaylist( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == PlaylistEntry::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isSmartPlaylist( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == SmartPlaylist::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isPlaylistTrackItem( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == PlaylistTrackItem::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isPodcastChannel( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == PodcastChannel::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isPodcastEpisode( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == PodcastEpisode::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isStream( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == StreamEntry::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isLastFm( TQListViewItem *item )
|
|
|
|
{
|
|
|
|
if( !item )
|
|
|
|
return false;
|
|
|
|
return item->rtti() == LastFmEntry::RTTI ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline TQString
|
|
|
|
fileBaseName( const TQString &filePath )
|
|
|
|
{
|
|
|
|
// this function returns the file name without extension
|
|
|
|
// (e.g. if the file path is "/home/user/playlist.m3u", "playlist" is returned
|
|
|
|
TQString fileName = filePath.right( filePath.length() - filePath.findRev( '/' ) - 1 );
|
|
|
|
return fileName.mid( 0, fileName.findRev( '.' ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline TQString
|
|
|
|
fileDirPath( const TQString &filePath )
|
|
|
|
{
|
|
|
|
return filePath.left( filePath.findRev( '/' )+1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class InfoPane : public TQVBox
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
TQ_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
InfoPane( TQWidget *parent );
|
|
|
|
~InfoPane();
|
|
|
|
int getHeight();
|
|
|
|
void setStoredHeight( const int newHeight );
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
void setInfo( const TQString &title, const TQString &info );
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void toggle( bool );
|
|
|
|
|
|
|
|
private:
|
|
|
|
HTMLView *m_infoBrowser;
|
|
|
|
KPushButton *m_pushButton;
|
|
|
|
bool m_enable;
|
|
|
|
int m_storedHeight;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|