Make the ServiceListDelegate use less handcoded values and more general variables...
[amarok.git] / src / mediabrowser.h
blob20a0c81af9d8c419c1e2b6318272496d16536d5a
1 // (c) 2004 Christian Muehlhaeuser <chris@chris.de>
2 // (c) 2005 Martin Aumueller <aumuell@reserv.at>
3 // (c) 2005 Seb Ruiz <ruiz@kde.org>
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_export.h"
11 #include "amarok.h"
12 #include "browserToolBar.h"
13 #include "medium.h"
14 #include "metabundle.h"
15 #include "pluginmanager.h"
16 #include "plugin/plugin.h" //baseclass
17 #include "scrobbler.h" //SubmitItem
19 #include <k3listview.h> //baseclass
20 #include <KHBox>
21 #include <kio/global.h> //filesize_t
22 #include <KUrl> //stack allocated
23 #include <KVBox> //baseclass
25 #include <Q3PtrList>
26 #include <QDateTime>
27 #include <QLabel>
28 #include <QMutex>
29 #include <QPixmap>
30 #include <QWidget>
33 class MediaBrowser;
34 class MediaDevice;
35 class MediaItem;
36 class MediaView;
37 class SpaceLabel;
38 class TransferDialog;
39 class SearchWidget;
41 class KAction;
42 class KComboBox;
43 class KPushButton;
44 class K3ShellProcess;
46 class QDropEvent;
47 class QKeyEvent;
48 class QPaintEvent;
49 class Q3DragObject;
50 class QLabel;
51 class QProgressBar;
55 class MediaQueue : public K3ListView
57 Q_OBJECT
59 public:
60 MediaQueue(MediaBrowser *parent);
61 MediaItem *findPath( QString path );
63 KIO::filesize_t totalSize() const; // total size of items to transfer in KB
64 void computeSize() const; // compute total size of items to transfer in KB
65 void addItemToSize( const MediaItem *item ) const;
66 void subtractItemFromSize( const MediaItem *item, bool unconditonally=false ) const;
68 void removeSelected();
69 void clearItems();
71 void load( const QString &path );
72 void save( const QString &path );
73 void syncPlaylist( const QString &playlistName, const QString &sql, bool loading=false );
74 void syncPlaylist( const QString &playlistName, const KUrl &url, bool loading=false );
75 void addUrl( const KUrl& url, MetaBundle *bundle=NULL, const QString &playlistName=QString() );
76 void addUrl( const KUrl& url, MediaItem *item );
77 void addUrls( const KUrl::List urls, const QString &playlistName=QString() );
79 void URLsAdded(); // call after finishing adding single urls
81 void dropProxyEvent( QDropEvent *e );
82 // Reimplemented from K3ListView
83 bool acceptDrag( QDropEvent *e ) const;
84 Q3DragObject *dragObject();
86 public slots:
87 void itemCountChanged();
89 private slots:
90 void selectAll() {Q3ListView::selectAll(true); }
91 void slotShowContextMenu( Q3ListViewItem* item, const QPoint& point, int );
92 void slotDropped (QDropEvent* e, Q3ListViewItem* parent, Q3ListViewItem* after);
94 private:
95 void keyPressEvent( QKeyEvent *e );
96 MediaBrowser *m_parent;
97 mutable KIO::filesize_t m_totalSize;
101 class MediaBrowser : public QWidget
103 Q_OBJECT
104 friend class DeviceConfigureDialog;
105 friend class MediaDevice;
106 friend class MediaView;
107 friend class MediaQueue;
108 friend class MediumPluginChooser;
109 friend class MediaItem;
111 public:
112 static bool isAvailable();
113 AMAROK_EXPORT static MediaBrowser *instance() { return s_instance; }
114 AMAROK_EXPORT static MediaQueue *queue() { return s_instance ? s_instance->m_queue : 0; }
116 MediaBrowser( const char *name );
117 virtual ~MediaBrowser();
118 bool blockQuit() const;
119 MediaDevice *currentDevice() const { return m_currentDevice; }
120 MediaDevice *deviceFromId( const QString &id ) const;
121 QStringList deviceNames() const;
122 bool deviceSwitch( const QString &name );
124 QString getInternalPluginName ( const QString string ) { return m_pluginName[string]; }
125 QString getDisplayPluginName ( const QString string ) { return m_pluginAmarokName[string]; }
126 const KService::List &getPlugins() { return m_plugins; }
127 void transcodingFinished( const QString &src, const QString &dst );
128 bool isTranscoding() const { return m_waitForTranscode; }
129 void updateStats();
130 void updateButtons();
131 void updateDevices();
132 // return bundle for url if it is known to MediaBrowser
133 bool getBundle( const KUrl &url, MetaBundle *bundle ) const;
134 bool isQuitting() const { return m_quitting; }
136 KUrl getProxyUrl( const KUrl& daapUrl ) const;
137 KToolBar* getToolBar() const { return m_toolbar; }
138 KAction *connectAction() const { return m_connectAction; }
139 KAction *disconnectAction() const { return m_disconnectAction; }
140 KAction *transferAction() const { return m_transferAction; }
141 KAction *configAction() const { return m_configAction; }
142 KAction *customAction() const { return m_customAction; }
144 signals:
145 void availabilityChanged( bool isAvailable );
147 protected slots:
148 void transferClicked();
150 private slots:
151 void slotSetFilterTimeout();
152 void slotSetFilter();
153 void slotSetFilter( const QString &filter );
154 void slotEditFilter();
155 void deviceAdded( const QString &udi );
156 void deviceRemoved( const QString &udi );
157 void activateDevice( const MediaDevice *device );
158 void activateDevice( int index, bool skipDummy = true );
159 void cancelClicked();
160 void connectClicked();
161 void disconnectClicked();
162 void customClicked();
163 bool config(); // false if canceled by user
164 KUrl transcode( const KUrl &src, const QString &filetype );
165 void tagsChanged( const MetaBundle &bundle );
166 void prepareToQuit();
168 private:
169 MediaDevice *loadDevicePlugin( const QString &udi );
170 void unloadDevicePlugin( MediaDevice *device );
172 QTimer *m_timer;
173 AMAROK_EXPORT static MediaBrowser *s_instance;
175 QList<MediaDevice *> m_devices;
176 MediaDevice * m_currentDevice;
178 QMap<QString, QString> m_pluginName;
179 QMap<QString, QString> m_pluginAmarokName;
180 void addDevice( MediaDevice *device );
181 void removeDevice( MediaDevice *device );
183 MediaQueue* m_queue;
184 bool m_waitForTranscode;
185 KUrl m_transcodedUrl;
186 QString m_transcodeSrc;
188 SpaceLabel* m_stats;
189 KHBox* m_progressBox;
190 QProgressBar* m_progress;
191 QWidget* m_views;
192 KPushButton* m_cancelButton;
193 //KPushButton* m_playlistButton;
194 KVBox* m_configBox;
195 KComboBox* m_configPluginCombo;
196 KComboBox* m_deviceCombo;
197 Browser::ToolBar*m_toolbar;
198 typedef QMap<QString, MediaItem*> ItemMap;
199 mutable QMutex m_itemMapMutex;
200 ItemMap m_itemMap;
201 KService::List m_plugins;
202 bool m_haveDevices;
203 bool m_quitting;
204 KAction *m_connectAction;
205 KAction *m_disconnectAction;
206 KAction *m_customAction;
207 KAction *m_configAction;
208 KAction *m_transferAction;
209 SearchWidget *m_searchWidget;
212 class MediaView : public K3ListView
214 Q_OBJECT
215 friend class MediaBrowser;
216 friend class MediaDevice;
218 public:
219 enum Flags
221 None = 0,
222 OnlySelected = 1,
223 OnlyPlayed = 2
226 MediaView( QWidget *parent, MediaDevice *device );
227 virtual ~MediaView();
228 AMAROK_EXPORT KUrl::List nodeBuildDragList( MediaItem* item, int flags=OnlySelected );
229 int getSelectedLeaves(MediaItem *parent, Q3PtrList<MediaItem> *list, int flags=OnlySelected );
230 AMAROK_EXPORT MediaItem *newDirectory( MediaItem* parent );
231 bool setFilter( const QString &filter, MediaItem *parent=NULL );
233 private slots:
234 void rmbPressed( Q3ListViewItem*, const QPoint&, int );
235 void renameItem( Q3ListViewItem *item );
236 void slotExpand( Q3ListViewItem* );
237 void selectAll() { Q3ListView::selectAll(true); }
238 void invokeItem( Q3ListViewItem*, const QPoint &, int column );
239 void invokeItem( Q3ListViewItem* );
241 private:
242 void keyPressEvent( QKeyEvent *e );
243 // Reimplemented from K3ListView
244 void contentsDropEvent( QDropEvent *e );
245 void viewportPaintEvent( QPaintEvent* );
246 bool acceptDrag( QDropEvent *e ) const;
247 Q3DragObject *dragObject();
249 QWidget *m_parent;
250 MediaDevice *m_device;
254 /* at least the pure virtual functions have to be implemented by a media device,
255 all items are stored in a hierarchy of MediaItems,
256 when items are manipulated the MediaItems have to be updated accordingly */
258 class AMAROK_EXPORT MediaDevice : public QObject, public Amarok::Plugin
260 Q_OBJECT
261 friend class DeviceConfigureDialog;
262 friend class TransferDialog;
263 friend class MediaBrowser;
264 friend class MediaView;
265 friend class MediaQueue;
267 public:
268 enum Flags
270 None = 0,
271 OnlyPlayed = 1,
272 DeleteTrack = 2,
273 Recursing = 4
276 MediaDevice();
277 virtual void init( MediaBrowser* parent );
278 virtual ~MediaDevice();
280 MediaView *view();
283 * @return a KAction that will be plugged into the media device browser toolbar
285 virtual KAction *customAction() { return 0; }
287 virtual void rmbPressed( Q3ListViewItem *item, const QPoint &point, int ) { (void)item; (void) point; }
290 * @return list of filetypes playable on this device
291 * (empty list is interpreted as all types are good)
293 virtual QStringList supportedFiletypes() { return QStringList(); }
296 * @param bundle describes track that should be checked
297 * @return true if the device is capable of playing the track referred to by bundle
299 virtual bool isPlayable( const MetaBundle &bundle );
302 * @param bundle describes track that should be checked
303 * @return true if the track is in the preferred (first in list) format of the device
305 virtual bool isPreferredFormat( const MetaBundle &bundle );
308 * @return true if the device is connected
310 virtual bool isConnected() = 0;
313 * Adds particular tracks to a playlist
314 * @param playlist parent playlist for tracks to be added to
315 * @param after insert following this item
316 * @param items tracks to add to playlist
318 virtual void addToPlaylist(MediaItem *playlist, MediaItem *after, Q3PtrList<MediaItem> items) { Q_UNUSED(playlist); Q_UNUSED(after); Q_UNUSED(items); }
321 * Create a new playlist
322 * @param name playlist title
323 * @param parent parent MediaItem of the new playlist
324 * @param items tracks to add to the new playlist
325 * @return the newly created playlist
327 virtual MediaItem *newPlaylist(const QString &name, MediaItem *parent, Q3PtrList<MediaItem> items) { Q_UNUSED(name); Q_UNUSED(parent); Q_UNUSED(items); return 0; }
330 * Move items to a directory
331 * @param directory new parent of dropped items
332 * @param items tracks to add to the directory
334 virtual void addToDirectory( MediaItem *directory, Q3PtrList<MediaItem> items ) { Q_UNUSED(directory); Q_UNUSED(items); }
337 * Create a new directory
338 * @param name directory title
339 * @param parent parent MediaItem of the new directory
340 * @param items tracks to add to the new directory
341 * @return the newly created directory
343 virtual MediaItem *newDirectory( const QString &name, MediaItem *parent ) { Q_UNUSED(name); Q_UNUSED(parent); return 0; }
346 * Notify device of changed tags
347 * @param item item to be updated
348 * @param changed bundle containing new tags
349 * @return the changed MediaItem
351 virtual MediaItem *tagsChanged( MediaItem *item, const MetaBundle &changed ) { Q_UNUSED(item); Q_UNUSED(changed); return 0; }
354 * Indicate whether the device has a custom transfer dialog
355 * @return whether there is a custom dialog
357 virtual bool hasTransferDialog() { return false; }
360 * Run the transfer dialog to be used when Transfer is clicked
362 virtual void runTransferDialog() {}
365 * Get the transfer dialog, if any
366 * @return the transfer dialog, if any, else NULL;
368 virtual TransferDialog *getTransferDialog() { return NULL; }
371 * Can be used to explicitly indicate whether a device needs manual configuration
372 * @return whether manual configuration is needed
374 virtual bool needsManualConfig() { return true; }
376 virtual void addConfigElements( QWidget * /*parent*/ ) {}
377 virtual void removeConfigElements( QWidget * /*parent*/ ) {}
378 virtual void applyConfig() {}
379 virtual void loadConfig();
381 QString configString( const QString &name, const QString &defValue = QString() );
382 void setConfigString( const QString &name, const QString &value );
383 bool configBool( const QString &name, bool defValue=false );
384 void setConfigBool( const QString &name, bool value );
386 void setRequireMount( const bool b ) { m_requireMount = b; }
387 bool hasMountPoint() { return m_hasMountPoint; }
388 void setDeviceType( const QString &type ) { m_type = type; }
389 QString deviceType() { return m_type; }
390 virtual bool autoConnect() { return false; }
391 virtual bool asynchronousTransfer() { return false; }
392 bool isTransferring() { return m_transferring; }
393 bool isDeleting() { return m_deleting; }
394 bool isCanceled() { return m_canceled; }
395 void setCanceled( const bool b ) { m_canceled = b; }
397 int progress() const;
398 void setProgress( const int progress, const int total = -1 /* leave total unchanged by default */ );
399 void hideProgress();
403 * @return a unique identifier that is constant across sessions
405 QString uniqueId() const { return m_uid; }
408 * @return the name for the device that should be presented to the user
410 QString name() const { return m_name; }
413 * @return the device node
415 QString deviceNode() const { return m_medium.deviceNode(); }
418 * @return the device mount point (or empty if non-applicable or unknown)
420 QString mountPoint() const { return m_medium.mountPoint(); }
422 QString getTransferDir() { return m_transferDir; }
423 Medium &getMedium() { return m_medium; }
425 void setSpacesToUnderscores( bool yesno ) { m_spacesToUnderscores = yesno;
426 setConfigBool( "spacesToUnderscores", yesno); }
427 bool getSpacesToUnderscores() { return m_spacesToUnderscores; }
429 void setFirstSort( QString text ) { m_firstSort = text;
430 setConfigString( "firstGrouping", text ); }
431 void setSecondSort( QString text ) { m_secondSort = text;
432 setConfigString( "secondGrouping", text ); }
433 void setThirdSort( QString text ) { m_thirdSort = text;
434 setConfigString( "thirdGrouping", text ); }
436 virtual KUrl getProxyUrl( const KUrl& /*url*/) { return KUrl(); }
437 virtual void customClicked() { return; }
439 BundleList bundlesToSync( const QString &playlistName, const QString &sql );
440 BundleList bundlesToSync( const QString &playlistName, const KUrl &url );
441 void preparePlaylistForSync( const QString &playlistName, const BundleList &bundles );
442 bool isOnOtherPlaylist( const QString &playlistToAvoid, const MetaBundle &bundle );
443 bool isOnPlaylist( const MediaItem &playlist, const MetaBundle &bundle );
444 bool isInBundleList( const BundleList &bundles, const MetaBundle &bundle );
445 bool bundleMatch( const MetaBundle &b1, const MetaBundle &b2 );
447 public slots:
448 void abortTransfer();
449 void transferFiles();
450 virtual void renameItem( Q3ListViewItem *item ) {(void)item; }
451 virtual void expandItem( Q3ListViewItem *item ) {(void)item; }
452 bool connectDevice( bool silent=false );
453 bool disconnectDevice( bool postdisconnecthook=true );
454 void scheduleDisconnect() { m_scheduledDisconnect = true; }
456 protected slots:
457 void fileTransferred( KIO::Job *job );
458 void fileTransferFinished();
460 private:
461 int sysCall(const QString & command);
462 int runPreConnectCommand();
463 int runPostDisconnectCommand();
464 QString replaceVariables( const QString &cmd ); // replace %m with mount point and %d with device node
466 QString uid() { return m_uid; }
467 void setUid( const QString &uid ) { m_uid = uid; }
470 * Find a particular track
471 * @param bundle The metabundle of the requested media item
472 * @return The MediaItem of the item if found, otherwise NULL
473 * @note This may not be worth implementing for non database driven devices, as it could be slow
475 virtual MediaItem *trackExists( const MetaBundle& bundle ) = 0;
477 protected:
479 * Get the capacity and freespace available on the device, in bytes
480 * @return true if successful
482 virtual bool getCapacity( KIO::filesize_t *total, KIO::filesize_t *available ) { Q_UNUSED(total); Q_UNUSED(available); return false; }
485 * Lock device for exclusive access if possible
487 virtual bool lockDevice( bool tryOnly = false ) = 0;
490 * Unlock device
492 virtual void unlockDevice() = 0;
495 * Connect to device, and populate m_view with MediaItems
496 * @return true if successful
498 virtual bool openDevice( bool silent=false ) = 0;
501 * Wrap up any loose ends and close the device
502 * @return true if successful
504 virtual bool closeDevice() = 0;
507 * Write any pending changes to the device, such as database changes
509 virtual void synchronizeDevice() = 0;
512 * Copy a track to the device
513 * @param bundle The MetaBundle of the item to transfer. Will move the item specified by bundle().url().path()
514 * @return If successful, the created MediaItem in the media device view, else 0
516 virtual MediaItem *copyTrackToDevice(const MetaBundle& bundle) = 0;
519 * Copy track from device to computer
520 * @param item The MediaItem of the track to transfer.
521 * @param url The URL to transfer the track to.
522 * @return The MediaItem transfered.
524 virtual void copyTrackFromDevice(MediaItem *item);
527 * Recursively remove MediaItem from the tracklist and the device
528 * @param item MediaItem to remove
529 * @param onlyPlayed True if item should be deleted only if it has been played
530 * @return -1 on failure, number of files deleted otherwise
532 virtual int deleteItemFromDevice( MediaItem *item, int flags=DeleteTrack ) = 0;
535 * Abort the currently active track transfer
537 virtual void cancelTransfer() { /* often checking m_cancel is enough */ }
539 virtual void updateRootItems();
541 virtual bool isSpecialItem( MediaItem *item );
543 int deleteFromDevice( MediaItem *item=0, int flags=DeleteTrack );
545 void purgeEmptyItems( MediaItem *root=0 );
546 void syncStatsFromDevice( MediaItem *root=0 );
547 void syncStatsToDevice( MediaItem *root=0 );
549 bool kioCopyTrack( const KUrl &src, const KUrl &dst );
551 QString m_name;
553 bool m_hasMountPoint;
555 QString m_preconnectcmd;
556 QString m_postdisconnectcmd;
557 bool m_autoDeletePodcasts;
558 bool m_syncStats;
560 bool m_transcode;
561 bool m_transcodeAlways;
562 bool m_transcodeRemove;
564 K3ShellProcess *sysProc;
565 MediaBrowser *m_parent;
566 MediaView *m_view;
567 Medium m_medium;
568 QString m_transferDir;
569 QString m_firstSort;
570 QString m_secondSort;
571 QString m_thirdSort;
572 QString m_uid;
573 bool m_wait;
574 bool m_waitForDeletion;
575 bool m_copyFailed;
576 bool m_requireMount;
577 bool m_canceled;
578 bool m_transferring;
579 bool m_deleting;
580 bool m_deferredDisconnect;
581 bool m_scheduledDisconnect;
582 bool m_runDisconnectHook;
583 bool m_spacesToUnderscores;
584 bool m_transfer;
585 bool m_configure;
586 bool m_customButton;
588 QString m_type;
590 // root listview items
591 MediaItem *m_playlistItem;
592 MediaItem *m_podcastItem;
593 // items not on the master playlist and not on the podcast playlist are not visible on the ipod
594 MediaItem *m_invisibleItem;
595 // items in the database for which the file is missing
596 MediaItem *m_staleItem;
597 // files without database entry
598 MediaItem *m_orphanedItem;
600 // stow away all items below m_rootItems when device is not current
601 Q3PtrList<Q3ListViewItem> m_rootItems;
605 #endif /* AMAROK_MEDIABROWSER_H */