add mp3 and ogg torrent url info to JamendoAlbum
[amarok.git] / src / directorylist.cpp
bloba374d191fc3afea0f4ddefd5b8ce2d826d47c484
1 /***************************************************************************
2 directorylist.cpp
3 -------------------
4 begin : Tue Feb 4 2003
5 copyright : (C) 2003 Scott Wheeler <wheeler@kde.org>
6 : (C) 2004 Max Howell <max.howell@methylblue.com>
7 : (C) 2004 Mark Kretschmann <markey@web.de>
8 ***************************************************************************/
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
19 #include "directorylist.h"
21 #include "amarokconfig.h"
22 #include "mountpointmanager.h"
24 #include <KFileItem>
25 #include <KLocale>
26 #include <KVBox>
28 #include <QFile>
29 #include <QLabel>
30 #include <QPainter>
31 #include <QToolTip>
34 CollectionSetup* CollectionSetup::s_instance;
37 CollectionSetup::CollectionSetup( QWidget *parent )
38 : KVBox( parent )
40 setObjectName( "CollectionSetup" );
41 s_instance = this;
43 (new QLabel( i18n(
44 "These folders will be scanned for "
45 "media to make up your collection:"), this ))->setAlignment( Qt::AlignJustify );
47 m_view = new QFixedListView( this );
48 m_recursive = new QCheckBox( i18n("&Scan folders recursively"), this );
49 m_monitor = new QCheckBox( i18n("&Watch folders for changes"), this );
51 m_recursive->setToolTip( i18n( "If selected, Amarok will read all subfolders." ) );
52 m_monitor->setToolTip( i18n( "If selected, folders will automatically get rescanned when the content is modified, e.g. when a new file was added." ) );
54 // Read config values
55 //we have to detect if this is the actual first run and not get the collectionFolders in that case
56 //there won't be any anyway and accessing them creates a Sqlite database, even if the user wants to
57 //use another database
58 //bug 131719 131724
59 if( !Amarok::config().readEntry( "First Run", true ) )
60 m_dirs = MountPointManager::instance()->collectionFolders();
62 m_recursive->setChecked( AmarokConfig::scanRecursively() );
63 m_monitor->setChecked( AmarokConfig::monitorChanges() );
65 m_view->addColumn( QString() );
66 m_view->setRootIsDecorated( true );
67 m_view->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
68 m_view->setResizeMode( Q3ListView::LastColumn );
70 reinterpret_cast<QWidget*>(m_view->header())->hide();
71 new CollectionFolder::Item( m_view );
73 setSpacing( 6 );
77 void
78 CollectionSetup::writeConfig()
80 //If we are in recursive mode then we don't need to store the names of the
81 //subdirectories of the selected directories
82 if ( recursive() )
84 for ( QStringList::iterator it=m_dirs.begin(); it!=m_dirs.end(); ++it )
86 QStringList::iterator jt=m_dirs.begin();
87 while ( jt!=m_dirs.end() )
89 if ( it==jt )
91 ++jt;
92 continue;
94 //Note: all directories except "/" lack a trailing '/'.
95 //If (*jt) is a subdirectory of (*it) it is redundant.
96 //As all directories are subdirectories of "/", if "/" is selected, we
97 //can delete everything else.
98 if ( ( *jt ).startsWith( *it + '/' ) || *it=="/" )
99 jt = m_dirs.erase( jt );
100 else
101 ++jt;
106 MountPointManager::instance()->setCollectionFolders( m_dirs );
107 AmarokConfig::setScanRecursively( recursive() );
108 AmarokConfig::setMonitorChanges( monitor() );
112 //////////////////////////////////////////////////////////////////////////////////////////
113 // CLASS Item
114 //////////////////////////////////////////////////////////////////////////////////////////
116 namespace CollectionFolder {
118 Item::Item( Q3ListView *parent )
119 : Q3CheckListItem( parent, "/", Q3CheckListItem::CheckBox )
120 , m_lister( this )
121 , m_url( "file:/" )
122 , m_listed( false )
123 , m_fullyDisabled( false )
125 m_lister.setDelayedMimeTypes( true );
126 //Since we create the "/" checklistitem here, we need to enable it if needed
127 if ( CollectionSetup::instance()->m_dirs.contains( "/" ) )
128 static_cast<Q3CheckListItem*>( this )->setOn(true);
129 m_lister.setDirOnlyMode( true );
130 connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) );
131 setOpen( true );
132 setVisible( true );
136 Item::Item( Q3ListViewItem *parent, const KUrl &url , bool full_disable /* default=false */ )
137 : Q3CheckListItem( parent, url.fileName(), Q3CheckListItem::CheckBox )
138 , m_lister( this )
139 , m_url( url )
140 , m_listed( false )
141 , m_fullyDisabled( full_disable )
143 m_lister.setDelayedMimeTypes( true );
144 m_lister.setDirOnlyMode( true );
145 setExpandable( true );
146 connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) );
147 connect( &m_lister, SIGNAL(completed()), SLOT(completed()) );
148 connect( &m_lister, SIGNAL(canceled()), SLOT(completed()) );
152 QString
153 Item::fullPath() const
155 QString path;
157 for( const Q3ListViewItem *item = this; item != listView()->firstChild(); item = item->parent() )
159 path.prepend( item->text( 0 ) );
160 path.prepend( '/' );
163 return path;
167 void
168 Item::setOpen( bool b )
170 if ( !m_listed )
172 m_lister.openUrl( m_url, KDirLister::Keep );
173 m_listed = true;
176 Q3ListViewItem::setOpen( b );
180 void
181 Item::stateChange( bool b )
183 QStringList &cs_m_dirs = CollectionSetup::instance()->m_dirs;
185 if ( isFullyDisabled() )
186 return;
188 if( CollectionSetup::instance()->recursive() )
189 for( Q3ListViewItem *item = firstChild(); item; item = item->nextSibling() )
190 if ( dynamic_cast<Item*>( item ) && !dynamic_cast<Item*>( item )->isFullyDisabled() )
191 static_cast<Q3CheckListItem*>(item)->Q3CheckListItem::setOn( b );
193 //If it is disabled, allow us to change its appearance (above code) but not add it
194 //to the list of folders (code below)
195 if ( isDisabled() )
196 return;
198 // Update folder list
199 QStringList::Iterator it = cs_m_dirs.find( m_url.path() );
200 if ( isOn() ) {
201 if ( it == cs_m_dirs.end() )
202 cs_m_dirs << m_url.path();
204 // Deselect subdirectories if we are in recursive mode as they are redundant
205 if ( CollectionSetup::instance()->recursive() )
207 QStringList::Iterator diriter = cs_m_dirs.begin();
208 while ( diriter != cs_m_dirs.end() )
210 // Since the dir "/" starts with '/', we need a hack to stop it removing
211 // itself (it being the only path with a trailing '/')
212 if ( (*diriter).startsWith( m_url.path( KUrl::AddTrailingSlash) ) && *diriter != "/" )
213 diriter = cs_m_dirs.erase(diriter);
214 else
215 ++diriter;
219 else {
220 //Deselect item and recurse through children but only deselect children if they
221 //do not exist unless we are in recursive mode (where no children should be
222 //selected if the parent is being unselected)
223 //Note this does not do anything to the checkboxes, but they should be doing
224 //the same thing as we are (hopefully)
225 //Note: all paths lack a trailing '/' except for "/", which must be handled as a
226 //special case
227 if ( it != cs_m_dirs.end() )
228 cs_m_dirs.erase( it );
229 QStringList::Iterator diriter = cs_m_dirs.begin();
230 while ( diriter != cs_m_dirs.end() )
232 if ( (*diriter).startsWith( m_url.path( KUrl::AddTrailingSlash ) ) ) //path(1) adds a trailing '/'
234 if ( CollectionSetup::instance()->recursive() ||
235 !QFile::exists( *diriter ) )
237 diriter = cs_m_dirs.erase(diriter);
239 else
240 ++diriter;
242 else
243 ++diriter;
247 // Redraw parent items
248 listView()->triggerUpdate();
252 void
253 Item::activate()
255 if( !isDisabled() )
256 Q3CheckListItem::activate();
260 void
261 Item::newItems( const KFileItemList &list ) //SLOT
263 for( KFileItemList::const_iterator it = list.begin(); it != list.end(); ++it )
265 //Fully disable (always appears off and grayed-out) if it is "/proc", "/sys" or
266 //"/dev" or one of their children. This is because we will never scan them, so we
267 //might as well show that.
268 //These match up with the skipped dirs in CollectionScanner::readDir.
269 bool fully_disable=false;
271 if ( this->m_url.fileName().isEmpty() && ( (*it).url().fileName()=="proc"
272 || (*it).url().fileName()=="dev" || (*it).url().fileName()=="sys" ) )
274 fully_disable=true;
277 Item *item = new Item( this, (*it).url() , fully_disable || this->isFullyDisabled() );
279 if ( !item->isFullyDisabled() )
281 if( CollectionSetup::instance()->recursive() && isOn() ||
282 CollectionSetup::instance()->m_dirs.contains( item->fullPath() ) )
284 item->setOn( true );
288 item->setPixmap( 0, (*it).pixmap( KIconLoader::SizeSmall ) );
293 void
294 Item::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align )
296 bool dirty = false;
297 QStringList &cs_m_dirs = CollectionSetup::instance()->m_dirs;
299 // Figure out if a child folder is activated
300 for ( QStringList::const_iterator iter = cs_m_dirs.begin(); iter != cs_m_dirs.end();
301 ++iter )
302 if ( ( *iter ).startsWith( m_url.path( KUrl::AddTrailingSlash ) ) )
303 if ( *iter != "/" ) // "/" should not match as a child of "/"
304 dirty = true;
306 // Use a different color if this folder has an activated child folder
307 const QFont f = p->font();
308 QColorGroup _cg = cg;
309 if ( dirty )
311 _cg.setColor( QColorGroup::Text, listView()->colorGroup().link() );
312 QFont font = p->font();
313 font.setBold( !font.bold() );
314 p->setFont( font );
317 Q3CheckListItem::paintCell( p, isDisabled() ? listView()->palette().disabled() : _cg, column, width, align );
318 p->setFont( f );
321 } //namespace Collection
323 #include "directorylist.moc"