📄 mediabrowser.cpp
字号:
// (c) 2004 Christian Muehlhaeuser <chris@chris.de>// (c) 2005-2006 Martin Aumueller <aumuell@reserv.at>// (c) 2005 Seb Ruiz <me@sebruiz.net>// (c) 2006 T.R.Shashwath <trshash84@gmail.com>// See COPYING file for licensing information#define DEBUG_PREFIX "MediaBrowser"#include <config.h>#include "amarok.h"#include "amarokconfig.h"#include "app.h"#include "browserToolBar.h"#include "clicklineedit.h"#include "collectiondb.h"#include "colorgenerator.h"#include "contextbrowser.h"#include "debug.h"#include "editfilterdialog.h"#include "deviceconfiguredialog.h"#include "mediadevicemanager.h"#include "expression.h"#include "hintlineedit.h"#include "mediabrowser.h"#include "medium.h"#include "mediumpluginmanager.h"#include "metabundle.h"#include "mountpointmanager.h"#include "playlist.h"#include "playlistbrowser.h"#include "playlistbrowseritem.h"#include "playlistloader.h"#include "pluginmanager.h"#include "podcastbundle.h"#include "scriptmanager.h"#include "scrobbler.h"#include "statusbar.h"#include "transferdialog.h"#include "browserToolBar.h"#include <qvbuttongroup.h>#include <qcheckbox.h>#include <qdatetime.h>#include <qdir.h>#include <qdom.h>#include <qfileinfo.h>#include <qgroupbox.h>#include <qheader.h>#include <qimage.h>#include <qlabel.h>#include <qobjectlist.h>#include <qpainter.h>#include <qradiobutton.h>#include <qsimplerichtext.h>#include <qtimer.h>#include <qtooltip.h> //QToolTip::add()#include <kapplication.h> //kapp#include <kcombobox.h>#include <kdirlister.h>#include <kfiledialog.h>#include <kglobal.h>#include <kiconloader.h>#include <kinputdialog.h>#include <kio/job.h>#include <klocale.h>#include <kmessagebox.h>#include <kmultipledrag.h>#include <kpopupmenu.h>#include <kprocess.h>#include <kprogress.h>#include <kpushbutton.h>#include <krun.h>#include <kstandarddirs.h> //locate file#include <ktabbar.h>#include <ktempfile.h>#include <ktoolbarbutton.h> //ctor#include <kurldrag.h> //dragObject()#include <kactioncollection.h>MediaBrowser *MediaBrowser::s_instance = 0;QPixmap *MediaItem::s_pixUnknown = 0;QPixmap *MediaItem::s_pixArtist = 0;QPixmap *MediaItem::s_pixAlbum = 0;QPixmap *MediaItem::s_pixFile = 0;QPixmap *MediaItem::s_pixTrack = 0;QPixmap *MediaItem::s_pixPodcast = 0;QPixmap *MediaItem::s_pixPlaylist = 0;QPixmap *MediaItem::s_pixInvisible = 0;QPixmap *MediaItem::s_pixStale = 0;QPixmap *MediaItem::s_pixOrphaned = 0;QPixmap *MediaItem::s_pixDirectory = 0;QPixmap *MediaItem::s_pixRootItem = 0;QPixmap *MediaItem::s_pixTransferFailed = 0;QPixmap *MediaItem::s_pixTransferBegin = 0;QPixmap *MediaItem::s_pixTransferEnd = 0;bool MediaBrowser::isAvailable() //static{ if( !MediaBrowser::instance() ) return false; return true; //to re-enable hiding, uncomment this and get rid of the return true above: //return MediaBrowser::instance()->m_haveDevices;}class SpaceLabel : public QLabel { public: SpaceLabel(QWidget *parent) : QLabel(parent) { m_total = m_used = m_scheduled = 0; setBackgroundMode(Qt::NoBackground); } void paintEvent(QPaintEvent *e) { QPainter p(this); p.fillRect(e->rect(), colorGroup().brush(QColorGroup::Background)); if(m_total > 0) { int used = int(float(m_used)/float(m_total)*width()); int scheduled = int(float(m_used + m_scheduled)/float(m_total)*width()); if(m_used > 0) { QColor blueish(70,120,255); if(e->rect().left() < used) { int right = used; if(e->rect().right() < right) right = e->rect().right(); p.fillRect(e->rect().left(), e->rect().top(), used, e->rect().bottom()+1, QBrush(blueish, Qt::SolidPattern)); } } if(m_scheduled > 0) { QColor sched(70, 230, 120); if(m_used + m_scheduled > m_total - m_total/200) { sched.setRgb( 255, 120, 120 ); } int left = e->rect().left(); if(used > left) left = used; int right = e->rect().right(); if(scheduled < right) right = scheduled; p.fillRect(left, e->rect().top(), right, e->rect().bottom()+1, QBrush(sched, Qt::SolidPattern)); } if(m_used + m_scheduled < m_total) { QColor grey(180, 180, 180); int left = e->rect().left(); if(scheduled > left) left = scheduled; int right = e->rect().right(); p.fillRect(left, e->rect().top(), right, e->rect().bottom()+1, colorGroup().brush(QColorGroup::Background)); } } QLabel::paintEvent(e); } KIO::filesize_t m_total; KIO::filesize_t m_used; KIO::filesize_t m_scheduled;};class DummyMediaDevice : public MediaDevice{ public: DummyMediaDevice() : MediaDevice() { m_name = i18n( "No Device Available" ); m_type = "dummy-mediadevice"; m_medium = Medium( "DummyDevice", "DummyDevice" ); } void init( MediaBrowser *browser ) { MediaDevice::init( browser ); } virtual ~DummyMediaDevice() {} virtual bool isConnected() { return false; } virtual MediaItem* trackExists(const MetaBundle&) { return 0; } virtual bool lockDevice(bool) { return true; } virtual void unlockDevice() {} virtual bool openDevice( bool silent ) { if( !silent ) { //QString msg = i18n( "Sorry, you do not have a supported portable music player." ); //Amarok::StatusBar::instance()->longMessage( msg, KDE::StatusBar::Sorry ); } return false; } virtual bool closeDevice() { return false; } virtual void synchronizeDevice() {} virtual MediaItem* copyTrackToDevice(const MetaBundle&) { return 0; } virtual int deleteItemFromDevice(MediaItem*, int) { return -1; }};MediaBrowser::MediaBrowser( const char *name ) : QVBox( 0, name ) , m_timer( new QTimer( this ) ) , m_currentDevice( m_devices.end() ) , m_waitForTranscode( false ) , m_quitting( false ){ s_instance = this; // preload pixmaps used in browser KIconLoader iconLoader; MediaItem::s_pixUnknown = new QPixmap(iconLoader.loadIcon( Amarok::icon( "unknown" ), KIcon::Toolbar, KIcon::SizeSmall )); MediaItem::s_pixTrack = new QPixmap(iconLoader.loadIcon( Amarok::icon( "playlist" ), KIcon::Toolbar, KIcon::SizeSmall )); MediaItem::s_pixFile = new QPixmap(iconLoader.loadIcon( Amarok::icon( "sound" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixPodcast = new QPixmap(iconLoader.loadIcon( Amarok::icon( "podcast" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixPlaylist = new QPixmap(iconLoader.loadIcon( Amarok::icon( "playlist" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixRootItem = new QPixmap(iconLoader.loadIcon( Amarok::icon( "files2" ), KIcon::Toolbar, KIcon::SizeSmall ) ); // history // favorites // collection // folder // folder_red // player_playlist_2 // cancel // sound MediaItem::s_pixArtist = new QPixmap(iconLoader.loadIcon( Amarok::icon( "personal" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixAlbum = new QPixmap(iconLoader.loadIcon( Amarok::icon( "cdrom_unmount" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixInvisible = new QPixmap(iconLoader.loadIcon( Amarok::icon( "cancel" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixStale = new QPixmap(iconLoader.loadIcon( Amarok::icon( "cancel" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixOrphaned = new QPixmap(iconLoader.loadIcon( Amarok::icon( "cancel" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixDirectory = new QPixmap(iconLoader.loadIcon( Amarok::icon( "folder" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixTransferBegin = new QPixmap(iconLoader.loadIcon( Amarok::icon( "play" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixTransferEnd = new QPixmap(iconLoader.loadIcon( Amarok::icon( "stop" ), KIcon::Toolbar, KIcon::SizeSmall ) ); MediaItem::s_pixTransferFailed = new QPixmap(iconLoader.loadIcon( Amarok::icon( "cancel" ), KIcon::Toolbar, KIcon::SizeSmall ) ); setSpacing( 4 ); m_toolbar = new Browser::ToolBar( this ); m_toolbar->setIconText( KToolBar::IconTextRight, false ); m_toolbar->insertButton( "connect_creating", CONNECT, true, i18n("Connect") ); QToolTip::add( m_toolbar->getButton(CONNECT), i18n( "Connect media device" ) ); m_toolbar->insertButton( "player_eject", DISCONNECT, true, i18n("Disconnect") ); QToolTip::add( m_toolbar->getButton(DISCONNECT), i18n( "Disconnect media device" ) ); m_toolbar->insertButton( "rebuild", TRANSFER, true, i18n("Transfer") ); QToolTip::add( m_toolbar->getButton(TRANSFER), i18n( "Transfer tracks to media device" ) ); m_toolbar->insertLineSeparator(); // m_toolbar->setIconText( KToolBar::IconTextRight, true ); m_toolbar->insertButton( Amarok::icon( "add_playlist" ), CUSTOM, SIGNAL( clicked() ), this, SLOT( customClicked() ), true, "custom" ); QToolTip::add( m_toolbar->getButton(TRANSFER), i18n( "Transfer tracks to media device" ) ); m_toolbar->setIconText( KToolBar::IconOnly, false ); m_toolbar->insertButton( Amarok::icon( "configure" ), CONFIGURE, true, i18n("Configure") ); QToolTip::add( m_toolbar->getButton(CONFIGURE), i18n( "Configure device" ) ); m_deviceCombo = new KComboBox( this ); // searching/filtering { //<Search LineEdit> KToolBar* searchToolBar = new Browser::ToolBar( this ); KToolBarButton *button = new KToolBarButton( "locationbar_erase", 0, searchToolBar ); m_searchEdit = new ClickLineEdit( i18n( "Enter search terms here" ), searchToolBar ); KPushButton *filterButton = new KPushButton("...", searchToolBar, "filter"); searchToolBar->setStretchableWidget( m_searchEdit ); m_searchEdit->setFrame( QFrame::Sunken ); connect( button, SIGNAL( clicked() ), m_searchEdit, SLOT( clear() ) ); connect( filterButton, SIGNAL( clicked() ), SLOT( slotEditFilter() ) ); QToolTip::add( button, i18n( "Clear filter" ) ); QToolTip::add( m_searchEdit, i18n( "Enter space-separated terms to search" ) ); QToolTip::add( filterButton, i18n( "Click to edit filter" ) ); } //</Search LineEdit> connect( m_timer, SIGNAL( timeout() ), SLOT( slotSetFilter() ) ); connect( m_searchEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotSetFilterTimeout() ) ); connect( m_searchEdit, SIGNAL( returnPressed() ), SLOT( slotSetFilter() ) ); // connect to device manager connect( MediaDeviceManager::instance(), SIGNAL( mediumAdded(const Medium *, QString) ), SLOT( mediumAdded(const Medium *, QString) ) ); connect( MediaDeviceManager::instance(), SIGNAL( mediumChanged(const Medium *, QString) ), SLOT( mediumChanged(const Medium *, QString) ) ); connect( MediaDeviceManager::instance(), SIGNAL( mediumRemoved(const Medium *, QString) ), SLOT( mediumRemoved(const Medium *, QString) ) ); // we always have a dummy device m_pluginName[ i18n( "Disable" ) ] = "dummy-mediadevice"; m_pluginAmarokName["dummy-mediadevice"] = i18n( "Disable" ); m_pluginName[ i18n( "Do not handle" ) ] = "ignore"; m_pluginAmarokName["ignore"] = i18n( "Do not handle" ); // query available device plugins m_plugins = PluginManager::query( "[X-KDE-Amarok-plugintype] == 'mediadevice'" ); for( KTrader::OfferList::ConstIterator it = m_plugins.begin(); it != m_plugins.end(); ++it ) { // Save name properties in QMap for lookup m_pluginName[(*it)->name()] = (*it)->property( "X-KDE-Amarok-name" ).toString(); m_pluginAmarokName[(*it)->property( "X-KDE-Amarok-name" ).toString()] = (*it)->name(); } m_views = new QVBox( this ); m_queue = new MediaQueue( this ); m_progressBox = new QHBox( this ); m_progress = new KProgress( m_progressBox ); m_cancelButton = new KPushButton( SmallIconSet( Amarok::icon( "cancel" ) ), i18n("Cancel"), m_progressBox ); m_stats = new SpaceLabel(this); m_progressBox->hide(); MediaDevice *dev = new DummyMediaDevice(); dev->init( this ); addDevice( dev ); activateDevice( 0, false ); queue()->load( Amarok::saveLocation() + "transferlist.xml" ); queue()->computeSize(); setFocusProxy( m_queue ); updateStats(); QMap<QString, Medium*> mmap = MediaDeviceManager::instance()->getMediumMap(); bool newflag = false; //This deals with <strike>auto-detectable</strike> ALL devices! for( QMap<QString, Medium*>::Iterator it = mmap.begin(); it != mmap.end(); it++ ) { QString handler = Amarok::config( "MediaBrowser" )->readEntry( (*it)->id() ); //debug() << "[MediaBrowser] (*it)->id() = " << (*it)->id() << ", handler = " << handler << endl; if( handler.isEmpty() ) { //this should probably never be the case with a manually added device, unless amarokrc's been messed with Amarok::config( "MediaBrowser" )->writeEntry( (*it)->id(), "ignore" ); newflag = true; mediumAdded( *it, (*it)->name(), true ); } //and this definitely shouldn't! else if( handler != "deleted" ) mediumAdded( *it, (*it)->name(), true ); } if ( newflag ) Amarok::StatusBar::instance()->longMessageThreadSafe( i18n("Amarok has detected new portable media devices.\n" "Go to the \"Media Devices\" pane of the configuration\n" "dialog to choose a plugin for these devices.") ); connect( m_toolbar->getButton(CONNECT), SIGNAL( clicked() ), SLOT( connectClicked() ) ); connect( m_toolbar->getButton(DISCONNECT), SIGNAL( clicked() ), SLOT( disconnectClicked() ) ); connect( m_toolbar->getButton(TRANSFER), SIGNAL( clicked() ), SLOT( transferClicked() ) ); connect( m_toolbar->getButton(CONFIGURE), SIGNAL( clicked() ), SLOT( config() ) ); connect( m_deviceCombo, SIGNAL( activated( int ) ), SLOT( activateDevice( int ) ) ); connect( m_cancelButton, SIGNAL( clicked() ), SLOT( cancelClicked() ) ); connect( pApp, SIGNAL( prepareToQuit() ), SLOT( prepareToQuit() ) ); connect( CollectionDB::instance(), SIGNAL( tagsChanged( const MetaBundle& ) ), SLOT( tagsChanged( const MetaBundle& ) ) ); m_haveDevices = false; QMap<QString,QString> savedDevices = Amarok::config( "MediaBrowser" )->entryMap( "MediaBrowser" ); for( QMap<QString,QString>::Iterator it = savedDevices.begin(); it != savedDevices.end(); ++it ) { if( it.data() != "deleted" && it.data() != "ignore" ) { m_haveDevices = true; break; } } emit availabilityChanged( m_haveDevices );}boolMediaBrowser::blockQuit() const{ for( QValueList<MediaDevice *>::const_iterator it = m_devices.begin(); it != m_devices.end(); ++it ) { if( *it && (*it)->isConnected() ) return true; } return false;}voidMediaBrowser::tagsChanged( const MetaBundle &bundle ){ m_itemMapMutex.lock(); debug() << "tags changed for " << bundle.url().url() << endl; ItemMap::iterator it = m_itemMap.find( bundle.url().url() ); if( it != m_itemMap.end() ) { MediaItem *item = *it; m_itemMapMutex.unlock(); if( item->device() ) { item->device()->tagsChanged( item, bundle ); } else { // it's an item on the transfer queue item->setBundle( new MetaBundle( bundle ) ); QString text = item->bundle()->prettyTitle(); if( text.isEmpty() || (!item->bundle()->isValidMedia() && !item->bundle()->podcastBundle()) ) text = item->bundle()->url().prettyURL(); if( !item->m_playlistName.isNull() ) { text += " (" + item->m_playlistName + ')'; } item->setText( 0, text); } } else { m_itemMapMutex.unlock(); }}boolMediaBrowser::getBundle( const KURL &url, MetaBundle *bundle ) const{ QMutexLocker locker( &m_itemMapMutex ); ItemMap::const_iterator it = m_itemMap.find( url.url() ); if( it == m_itemMap.end() ) return false; if( bundle ) *bundle = QDeepCopy<MetaBundle>( *(*it)->bundle() ); return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -