Header cleanup
[amarok.git] / src / mediabrowser.h
blobf2a1bd0b7b49ca216255b65d280bf41567c0cd42
1 // (c) 2004 Christian Muehlhaeuser <chris@chris.de>
2 // (c) 2005 Martin Aumueller <aumuell@reserv.at>
3 // (c) 2005 Seb Ruiz <me@sebruiz.net>
4 // (c) 2006 T.R.Shashwath <trshash84@gmail.com>
5 // See COPYING file for licensing information
7 #ifndef AMAROK_MEDIABROWSER_H
8 #define AMAROK_MEDIABROWSER_H
10 #include "amarok.h"
11 #include "amarok_export.h"
12 #include "browserToolBar.h"
13 #include "medium.h"
14 #include "plugin/plugin.h" //baseclass
15 #include "pluginmanager.h"
17 #include <QMutex>
18 #include <kvbox.h> //baseclass
19 #include <QDateTime>
20 //Added by qt3to4:
21 #include <QKeyEvent>
22 #include <Q3ValueList>
23 #include <QLabel>
24 #include <Q3PtrList>
25 #include <QPixmap>
26 #include <QDropEvent>
27 #include <QPaintEvent>
28 #include <khbox.h>
29 #include <k3listview.h> //baseclass
30 #include <kurl.h> //stack allocated
31 #include <kio/global.h> //filesize_t
32 #include "scrobbler.h" //SubmitItem
33 #include "metabundle.h"
35 class MediaBrowser;
36 class MediaDevice;
37 class MediaView;
38 class SpaceLabel;
39 class TransferDialog;
40 class SearchWidget;
42 class KAction;
43 class KComboBox;
44 class KDialog;
45 class KPushButton;
46 class K3ShellProcess;
48 class Q3DragObject;
49 class QLabel;
50 class QPalette;
51 class QProgressBar;
53 class AMAROK_EXPORT MediaItem : public K3ListViewItem
55 public:
56 MediaItem( Q3ListView* parent );
57 MediaItem( Q3ListViewItem* parent );
58 MediaItem( Q3ListView* parent, Q3ListViewItem* after );
59 MediaItem( Q3ListViewItem* parent, Q3ListViewItem* after );
60 void init();
61 virtual ~MediaItem();
63 MediaItem *lastChild() const;
65 virtual KUrl url() const;
66 const MetaBundle *bundle() const;
67 void setBundle( MetaBundle *bundle );
69 enum Type { UNKNOWN, ARTIST, ALBUM, TRACK, PODCASTSROOT, PODCASTCHANNEL,
70 PODCASTITEM, PLAYLISTSROOT, PLAYLIST, PLAYLISTITEM, INVISIBLEROOT,
71 INVISIBLE, STALEROOT, STALE, ORPHANEDROOT, ORPHANED, DIRECTORY };
73 enum Flags { Failed=1, BeginTransfer=2, StopTransfer=4, Transferring=8, SmartPlaylist=16 };
75 void setType( Type type );
76 void setFailed( bool failed=true );
77 Type type() const { return m_type; }
78 MediaItem *findItem(const QString &key, const MediaItem *after=0) const;
79 const QString &data() const { return m_data; }
80 void setData( const QString &data ) { m_data = data; }
82 virtual bool isLeafItem() const; // A leaf node of the tree
83 virtual bool isFileBacked() const; // Should the file be deleted of the device when removed
84 virtual QDateTime playTime() const { return QDateTime(); }
85 virtual int played() const { return 0; }
86 virtual int recentlyPlayed() const { return 0; } // no of times played on device since last sync
87 virtual void setPlayCount( int ) {}
88 virtual int rating() const { return 0; } // rating on device, normalized to 100
89 virtual void setRating( int /*rating*/ ) {}
90 virtual bool ratingChanged() const { return false; }
91 virtual void setLastPlayed( uint ) {}
92 virtual void syncStatsFromPath( const QString &path );
93 virtual long size() const;
94 virtual MediaDevice *device() const { return m_device; }
95 virtual bool listened() const { return m_listened; }
96 virtual void setListened( bool listened=true ) { m_listened = listened; }
98 int compare( Q3ListViewItem *i, int col, bool ascending ) const;
99 int flags() const { return m_flags; }
100 void createToolTip();
102 void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align );
104 //attributes:
105 int m_order;
106 Type m_type;
107 QString m_playlistName;
108 QString m_data;
109 MediaDevice *m_device;
110 int m_flags;
111 bool m_listened;
113 static QPixmap *s_pixUnknown;
114 static QPixmap *s_pixRootItem;
115 static QPixmap *s_pixFile;
116 static QPixmap *s_pixArtist;
117 static QPixmap *s_pixAlbum;
118 static QPixmap *s_pixPlaylist;
119 static QPixmap *s_pixPodcast;
120 static QPixmap *s_pixTrack;
121 static QPixmap *s_pixInvisible;
122 static QPixmap *s_pixStale;
123 static QPixmap *s_pixOrphaned;
124 static QPixmap *s_pixDirectory;
125 static QPixmap *s_pixTransferFailed;
126 static QPixmap *s_pixTransferBegin;
127 static QPixmap *s_pixTransferEnd;
129 private:
130 mutable MetaBundle *m_bundle;
133 class MediaQueue : public K3ListView
135 Q_OBJECT
137 public:
138 MediaQueue(MediaBrowser *parent);
139 MediaItem *findPath( QString path );
141 KIO::filesize_t totalSize() const; // total size of items to transfer in KB
142 void computeSize() const; // compute total size of items to transfer in KB
143 void addItemToSize( const MediaItem *item ) const;
144 void subtractItemFromSize( const MediaItem *item, bool unconditonally=false ) const;
146 void removeSelected();
147 void clearItems();
149 void load( const QString &path );
150 void save( const QString &path );
151 void syncPlaylist( const QString &playlistName, const QString &sql, bool loading=false );
152 void syncPlaylist( const QString &playlistName, const KUrl &url, bool loading=false );
153 void addUrl( const KUrl& url, MetaBundle *bundle=NULL, const QString &playlistName=QString() );
154 void addUrl( const KUrl& url, MediaItem *item );
155 void addUrls( const KUrl::List urls, const QString &playlistName=QString() );
157 void URLsAdded(); // call after finishing adding single urls
159 void dropProxyEvent( QDropEvent *e );
160 // Reimplemented from K3ListView
161 bool acceptDrag( QDropEvent *e ) const;
162 Q3DragObject *dragObject();
164 public slots:
165 void itemCountChanged();
167 private slots:
168 void selectAll() {Q3ListView::selectAll(true); }
169 void slotShowContextMenu( Q3ListViewItem* item, const QPoint& point, int );
170 void slotDropped (QDropEvent* e, Q3ListViewItem* parent, Q3ListViewItem* after);
172 private:
173 void keyPressEvent( QKeyEvent *e );
174 MediaBrowser *m_parent;
175 mutable KIO::filesize_t m_totalSize;
179 class MediaBrowser : public KVBox
181 Q_OBJECT
182 friend class DeviceConfigureDialog;
183 friend class MediaDevice;
184 friend class MediaView;
185 friend class MediaQueue;
186 friend class MediumPluginChooser;
187 friend class MediaItem;
189 public:
190 static bool isAvailable();
191 AMAROK_EXPORT static MediaBrowser *instance() { return s_instance; }
192 AMAROK_EXPORT static MediaQueue *queue() { return s_instance ? s_instance->m_queue : 0; }
194 MediaBrowser( const char *name );
195 virtual ~MediaBrowser();
196 bool blockQuit() const;
197 MediaDevice *currentDevice() const;
198 MediaDevice *deviceFromId( const QString &id ) const;
199 QStringList deviceNames() const;
200 bool deviceSwitch( const QString &name );
202 QString getInternalPluginName ( const QString string ) { return m_pluginName[string]; }
203 QString getDisplayPluginName ( const QString string ) { return m_pluginAmarokName[string]; }
204 const KService::List &getPlugins() { return m_plugins; }
205 void transcodingFinished( const QString &src, const QString &dst );
206 bool isTranscoding() const { return m_waitForTranscode; }
207 void updateStats();
208 void updateButtons();
209 void updateDevices();
210 // return bundle for url if it is known to MediaBrowser
211 bool getBundle( const KUrl &url, MetaBundle *bundle ) const;
212 bool isQuitting() const { return m_quitting; }
214 KUrl getProxyUrl( const KUrl& daapUrl ) const;
215 KToolBar* getToolBar() const { return m_toolbar; }
216 KAction *connectAction() const { return m_connectAction; }
217 KAction *disconnectAction() const { return m_disconnectAction; }
218 KAction *transferAction() const { return m_transferAction; }
219 KAction *configAction() const { return m_configAction; }
220 KAction *customAction() const { return m_customAction; }
222 signals:
223 void availabilityChanged( bool isAvailable );
225 protected slots:
226 void transferClicked();
228 private slots:
229 void slotSetFilterTimeout();
230 void slotSetFilter();
231 void slotSetFilter( const QString &filter );
232 void slotEditFilter();
233 void mediumAdded( const Medium *, QString , bool constructing = false);
234 void mediumChanged( const Medium *, QString );
235 void mediumRemoved( const Medium *, QString );
236 void activateDevice( const MediaDevice *device );
237 void activateDevice( int index, bool skipDummy = true );
238 void pluginSelected( const Medium *, const QString );
239 void showPluginManager();
240 void cancelClicked();
241 void connectClicked();
242 void disconnectClicked();
243 void customClicked();
244 void configSelectPlugin( int index );
245 bool config(); // false if canceled by user
246 KUrl transcode( const KUrl &src, const QString &filetype );
247 void tagsChanged( const MetaBundle &bundle );
248 void prepareToQuit();
250 private:
251 MediaDevice *loadDevicePlugin( const QString &deviceName );
252 void unloadDevicePlugin( MediaDevice *device );
254 QTimer *m_timer;
255 AMAROK_EXPORT static MediaBrowser *s_instance;
257 Q3ValueList<MediaDevice *> m_devices;
258 Q3ValueList<MediaDevice *>::iterator m_currentDevice;
260 QMap<QString, QString> m_pluginName;
261 QMap<QString, QString> m_pluginAmarokName;
262 void addDevice( MediaDevice *device );
263 void removeDevice( MediaDevice *device );
265 MediaQueue* m_queue;
266 bool m_waitForTranscode;
267 KUrl m_transcodedUrl;
268 QString m_transcodeSrc;
270 SpaceLabel* m_stats;
271 KHBox* m_progressBox;
272 QProgressBar* m_progress;
273 KVBox* m_views;
274 KPushButton* m_cancelButton;
275 //KPushButton* m_playlistButton;
276 KVBox* m_configBox;
277 KComboBox* m_configPluginCombo;
278 KComboBox* m_deviceCombo;
279 Browser::ToolBar*m_toolbar;
280 typedef QMap<QString, MediaItem*> ItemMap;
281 mutable QMutex m_itemMapMutex;
282 ItemMap m_itemMap;
283 KService::List m_plugins;
284 bool m_haveDevices;
285 bool m_quitting;
286 KAction *m_connectAction;
287 KAction *m_disconnectAction;
288 KAction *m_customAction;
289 KAction *m_configAction;
290 KAction *m_transferAction;
291 SearchWidget *m_searchWidget;
294 class MediaView : public K3ListView
296 Q_OBJECT
297 friend class MediaBrowser;
298 friend class MediaDevice;
300 public:
301 enum Flags
303 None = 0,
304 OnlySelected = 1,
305 OnlyPlayed = 2
308 MediaView( QWidget *parent, MediaDevice *device );
309 virtual ~MediaView();
310 AMAROK_EXPORT KUrl::List nodeBuildDragList( MediaItem* item, int flags=OnlySelected );
311 int getSelectedLeaves(MediaItem *parent, Q3PtrList<MediaItem> *list, int flags=OnlySelected );
312 AMAROK_EXPORT MediaItem *newDirectory( MediaItem* parent );
313 bool setFilter( const QString &filter, MediaItem *parent=NULL );
315 private slots:
316 void rmbPressed( Q3ListViewItem*, const QPoint&, int );
317 void renameItem( Q3ListViewItem *item );
318 void slotExpand( Q3ListViewItem* );
319 void selectAll() { Q3ListView::selectAll(true); }
320 void invokeItem( Q3ListViewItem*, const QPoint &, int column );
321 void invokeItem( Q3ListViewItem* );
323 private:
324 void keyPressEvent( QKeyEvent *e );
325 // Reimplemented from K3ListView
326 void contentsDropEvent( QDropEvent *e );
327 void viewportPaintEvent( QPaintEvent* );
328 bool acceptDrag( QDropEvent *e ) const;
329 Q3DragObject *dragObject();
331 QWidget *m_parent;
332 MediaDevice *m_device;
336 /* at least the pure virtual functions have to be implemented by a media device,
337 all items are stored in a hierarchy of MediaItems,
338 when items are manipulated the MediaItems have to be updated accordingly */
340 class AMAROK_EXPORT MediaDevice : public QObject, public Amarok::Plugin
342 Q_OBJECT
343 friend class DeviceConfigureDialog;
344 friend class TransferDialog;
345 friend class MediaBrowser;
346 friend class MediaView;
347 friend class MediaQueue;
349 public:
350 enum Flags
352 None = 0,
353 OnlyPlayed = 1,
354 DeleteTrack = 2,
355 Recursing = 4
358 MediaDevice();
359 virtual void init( MediaBrowser* parent );
360 virtual ~MediaDevice();
362 MediaView *view();
365 * @return a KAction that will be plugged into the media device browser toolbar
367 virtual KAction *customAction() { return 0; }
369 virtual void rmbPressed( Q3ListViewItem *item, const QPoint &point, int ) { (void)item; (void) point; }
372 * @return list of filetypes playable on this device
373 * (empty list is interpreted as all types are good)
375 virtual QStringList supportedFiletypes() { return QStringList(); }
378 * @param bundle describes track that should be checked
379 * @return true if the device is capable of playing the track referred to by bundle
381 virtual bool isPlayable( const MetaBundle &bundle );
384 * @param bundle describes track that should be checked
385 * @return true if the track is in the preferred (first in list) format of the device
387 virtual bool isPreferredFormat( const MetaBundle &bundle );
390 * @return true if the device is connected
392 virtual bool isConnected() = 0;
395 * Adds particular tracks to a playlist
396 * @param playlist parent playlist for tracks to be added to
397 * @param after insert following this item
398 * @param items tracks to add to playlist
400 virtual void addToPlaylist(MediaItem *playlist, MediaItem *after, Q3PtrList<MediaItem> items) { Q_UNUSED(playlist); Q_UNUSED(after); Q_UNUSED(items); }
403 * Create a new playlist
404 * @param name playlist title
405 * @param parent parent MediaItem of the new playlist
406 * @param items tracks to add to the new playlist
407 * @return the newly created playlist
409 virtual MediaItem *newPlaylist(const QString &name, MediaItem *parent, Q3PtrList<MediaItem> items) { Q_UNUSED(name); Q_UNUSED(parent); Q_UNUSED(items); return 0; }
412 * Move items to a directory
413 * @param directory new parent of dropped items
414 * @param items tracks to add to the directory
416 virtual void addToDirectory( MediaItem *directory, Q3PtrList<MediaItem> items ) { Q_UNUSED(directory); Q_UNUSED(items); }
419 * Create a new directory
420 * @param name directory title
421 * @param parent parent MediaItem of the new directory
422 * @param items tracks to add to the new directory
423 * @return the newly created directory
425 virtual MediaItem *newDirectory( const QString &name, MediaItem *parent ) { Q_UNUSED(name); Q_UNUSED(parent); return 0; }
428 * Notify device of changed tags
429 * @param item item to be updated
430 * @param changed bundle containing new tags
431 * @return the changed MediaItem
433 virtual MediaItem *tagsChanged( MediaItem *item, const MetaBundle &changed ) { Q_UNUSED(item); Q_UNUSED(changed); return 0; }
436 * Indicate whether the device has a custom transfer dialog
437 * @return whether there is a custom dialog
439 virtual bool hasTransferDialog() { return false; }
442 * Run the transfer dialog to be used when Transfer is clicked
444 virtual void runTransferDialog() {}
447 * Get the transfer dialog, if any
448 * @return the transfer dialog, if any, else NULL;
450 virtual TransferDialog *getTransferDialog() { return NULL; }
453 * Can be used to explicitly indicate whether a device needs manual configuration
454 * @return whether manual configuration is needed
456 virtual bool needsManualConfig() { return true; }
458 virtual void addConfigElements( QWidget * /*parent*/ ) {}
459 virtual void removeConfigElements( QWidget * /*parent*/ ) {}
460 virtual void applyConfig() {}
461 virtual void loadConfig();
463 QString configString( const QString &name, const QString &defValue = QString() );
464 void setConfigString( const QString &name, const QString &value );
465 bool configBool( const QString &name, bool defValue=false );
466 void setConfigBool( const QString &name, bool value );
468 void setRequireMount( const bool b ) { m_requireMount = b; }
469 bool hasMountPoint() { return m_hasMountPoint; }
470 void setDeviceType( const QString &type ) { m_type = type; }
471 QString deviceType() { return m_type; }
472 virtual bool autoConnect() { return false; }
473 virtual bool asynchronousTransfer() { return false; }
474 bool isTransferring() { return m_transferring; }
475 bool isDeleting() { return m_deleting; }
476 bool isCanceled() { return m_canceled; }
477 void setCanceled( const bool b ) { m_canceled = b; }
479 int progress() const;
480 void setProgress( const int progress, const int total = -1 /* leave total unchanged by default */ );
481 void hideProgress();
485 * @return a unique identifier that is constant across sessions
487 QString uniqueId() const { return m_medium.id(); }
490 * @return the name for the device that should be presented to the user
492 QString name() const { return m_name; }
495 * @return the device node
497 QString deviceNode() const { return m_medium.deviceNode(); }
500 * @return the device mount point (or empty if non-applicable or unknown)
502 QString mountPoint() const { return m_medium.mountPoint(); }
504 QString getTransferDir() { return m_transferDir; }
505 Medium &getMedium() { return m_medium; }
507 void setSpacesToUnderscores( bool yesno ) { m_spacesToUnderscores = yesno;
508 setConfigBool( "spacesToUnderscores", yesno); }
509 bool getSpacesToUnderscores() { return m_spacesToUnderscores; }
511 void setFirstSort( QString text ) { m_firstSort = text;
512 setConfigString( "firstGrouping", text ); }
513 void setSecondSort( QString text ) { m_secondSort = text;
514 setConfigString( "secondGrouping", text ); }
515 void setThirdSort( QString text ) { m_thirdSort = text;
516 setConfigString( "thirdGrouping", text ); }
518 virtual KUrl getProxyUrl( const KUrl& /*url*/) { return KUrl(); }
519 virtual void customClicked() { return; }
521 BundleList bundlesToSync( const QString &playlistName, const QString &sql );
522 BundleList bundlesToSync( const QString &playlistName, const KUrl &url );
523 void preparePlaylistForSync( const QString &playlistName, const BundleList &bundles );
524 bool isOnOtherPlaylist( const QString &playlistToAvoid, const MetaBundle &bundle );
525 bool isOnPlaylist( const MediaItem &playlist, const MetaBundle &bundle );
526 bool isInBundleList( const BundleList &bundles, const MetaBundle &bundle );
527 bool bundleMatch( const MetaBundle &b1, const MetaBundle &b2 );
529 public slots:
530 void abortTransfer();
531 void transferFiles();
532 virtual void renameItem( Q3ListViewItem *item ) {(void)item; }
533 virtual void expandItem( Q3ListViewItem *item ) {(void)item; }
534 bool connectDevice( bool silent=false );
535 bool disconnectDevice( bool postdisconnecthook=true );
536 void scheduleDisconnect() { m_scheduledDisconnect = true; }
538 protected slots:
539 void fileTransferred( KIO::Job *job );
540 void fileTransferFinished();
542 private:
543 int sysCall(const QString & command);
544 int runPreConnectCommand();
545 int runPostDisconnectCommand();
546 QString replaceVariables( const QString &cmd ); // replace %m with mount point and %d with device node
549 * Find a particular track
550 * @param bundle The metabundle of the requested media item
551 * @return The MediaItem of the item if found, otherwise NULL
552 * @note This may not be worth implementing for non database driven devices, as it could be slow
554 virtual MediaItem *trackExists( const MetaBundle& bundle ) = 0;
556 protected:
558 * Get the capacity and freespace available on the device, in bytes
559 * @return true if successful
561 virtual bool getCapacity( KIO::filesize_t *total, KIO::filesize_t *available ) { Q_UNUSED(total); Q_UNUSED(available); return false; }
564 * Lock device for exclusive access if possible
566 virtual bool lockDevice( bool tryOnly = false ) = 0;
569 * Unlock device
571 virtual void unlockDevice() = 0;
574 * Connect to device, and populate m_view with MediaItems
575 * @return true if successful
577 virtual bool openDevice( bool silent=false ) = 0;
580 * Wrap up any loose ends and close the device
581 * @return true if successful
583 virtual bool closeDevice() = 0;
586 * Write any pending changes to the device, such as database changes
588 virtual void synchronizeDevice() = 0;
591 * Copy a track to the device
592 * @param bundle The MetaBundle of the item to transfer. Will move the item specified by bundle().url().path()
593 * @return If successful, the created MediaItem in the media device view, else 0
595 virtual MediaItem *copyTrackToDevice(const MetaBundle& bundle) = 0;
598 * Copy track from device to computer
599 * @param item The MediaItem of the track to transfer.
600 * @param url The URL to transfer the track to.
601 * @return The MediaItem transfered.
603 virtual void copyTrackFromDevice(MediaItem *item);
606 * Recursively remove MediaItem from the tracklist and the device
607 * @param item MediaItem to remove
608 * @param onlyPlayed True if item should be deleted only if it has been played
609 * @return -1 on failure, number of files deleted otherwise
611 virtual int deleteItemFromDevice( MediaItem *item, int flags=DeleteTrack ) = 0;
614 * Abort the currently active track transfer
616 virtual void cancelTransfer() { /* often checking m_cancel is enough */ }
618 virtual void updateRootItems();
620 virtual bool isSpecialItem( MediaItem *item );
622 int deleteFromDevice( MediaItem *item=0, int flags=DeleteTrack );
624 void purgeEmptyItems( MediaItem *root=0 );
625 void syncStatsFromDevice( MediaItem *root=0 );
626 void syncStatsToDevice( MediaItem *root=0 );
628 bool kioCopyTrack( const KUrl &src, const KUrl &dst );
630 QString m_name;
632 bool m_hasMountPoint;
634 QString m_preconnectcmd;
635 QString m_postdisconnectcmd;
636 bool m_autoDeletePodcasts;
637 bool m_syncStats;
639 bool m_transcode;
640 bool m_transcodeAlways;
641 bool m_transcodeRemove;
643 K3ShellProcess *sysProc;
644 MediaBrowser *m_parent;
645 MediaView *m_view;
646 Medium m_medium;
647 QString m_transferDir;
648 QString m_firstSort;
649 QString m_secondSort;
650 QString m_thirdSort;
651 bool m_wait;
652 bool m_waitForDeletion;
653 bool m_copyFailed;
654 bool m_requireMount;
655 bool m_canceled;
656 bool m_transferring;
657 bool m_deleting;
658 bool m_deferredDisconnect;
659 bool m_scheduledDisconnect;
660 bool m_runDisconnectHook;
661 bool m_spacesToUnderscores;
662 bool m_transfer;
663 bool m_configure;
664 bool m_customButton;
666 QString m_type;
668 // root listview items
669 MediaItem *m_playlistItem;
670 MediaItem *m_podcastItem;
671 // items not on the master playlist and not on the podcast playlist are not visible on the ipod
672 MediaItem *m_invisibleItem;
673 // items in the database for which the file is missing
674 MediaItem *m_staleItem;
675 // files without database entry
676 MediaItem *m_orphanedItem;
678 // stow away all items below m_rootItems when device is not current
679 Q3PtrList<Q3ListViewItem> m_rootItems;
683 #endif /* AMAROK_MEDIABROWSER_H */