/*************************************************************************** directorylist.cpp ------------------- begin : Tue Feb 4 2003 copyright : (C) 2003 Scott Wheeler : (C) 2004 Max Howell : (C) 2004 Mark Kretschmann ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "directorylist.h" using Collection::Item; using Collection::DeviceItem; CollectionSetup* CollectionSetup::s_instance; CollectionSetup::CollectionSetup( TQWidget *parent, bool recursive, bool fullMode, TQStringList dirs ) : TQVBox( parent ) { s_instance = this; m_dirs = dirs; // (new TQLabel( i18n( // "Select the folder(s) to scan. "), this ))->setAlignment( TQt::WordBreak ); m_view = new TQListView( this ); /* m_recursive = new TQCheckBox( i18n("&Scan folders recursively"), this );*/ m_recursive = recursive; // m_monitor = new TQCheckBox( i18n("&Watch folders for changes"), this ); // m_playlists = new TQCheckBox( i18n("&Import playlists"), this ); // // TQToolTip::add( m_recursive, i18n( "If selected, amaroK reads all folders recursively." ) ); // TQToolTip::add( m_monitor, i18n( "If selected, folders will automatically get rescanned when the content is modified, e.g. when a new file was added." ) ); // TQToolTip::add( m_playlists, i18n( "If selected, playlist files (.m3u) will automatically be added to the Playlist-Browser." ) ); // Read config values // m_dirs = AmarokConfig::collectionFolders(); // m_recursive->setChecked( false ); // m_monitor->setChecked( AmarokConfig::monitorChanges() ); // m_playlists->setChecked( AmarokConfig::importPlaylists() ); m_view->addColumn( TQString::null ); m_view->setRootIsDecorated( true ); reinterpret_cast(m_view->header())->hide(); new Item( m_view, i18n( "System Folder" ), "/", "folder_red" ); new Item( m_view, i18n( "Home Folder" ), TQDir::homeDirPath(), "folder_home" ); if( fullMode ) new DeviceItem( m_view ); setSpacing( 6 ); } void CollectionSetup::slotRecursiveToggled(bool on) { m_recursive = on; } ////////////////////////////////////////////////////////////////////////////////////////// // CLASS Item ////////////////////////////////////////////////////////////////////////////////////////// Item::Item( TQListView *parent , const TQString &name, const TQString &path, const TQString &icon ) : TQCheckListItem( parent, name, TQCheckListItem::CheckBox ) , m_lister( true ) , m_url( "file:" + path ) , m_listed( false ) { m_lister.setDirOnlyMode( true ); m_lister.setShowingDotFiles( true ); connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) ); setText( 1, path ); setOpen( true ); if ( !icon.isNull() ) setPixmap( 0, SmallIcon( icon ) ); else setPixmap( 0, SmallIcon( "folder" ) ); setVisible( true ); } Item::Item( TQListViewItem *parent, const KURL &url ) : TQCheckListItem( parent, url.fileName(), TQCheckListItem::CheckBox ) , m_lister( true ) , m_url( url ) , m_listed( false ) { m_lister.setDirOnlyMode( true ); m_lister.setShowingDotFiles( true ); setText( 1, url.fileName() ); setExpandable( true ); connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) ); connect( &m_lister, SIGNAL(completed()), SLOT(completed()) ); connect( &m_lister, SIGNAL(canceled()), SLOT(completed()) ); } TQString Item::fullPath() const { TQString path; for ( const TQListViewItem *item = this; dynamic_cast( item ); item = item->parent() ) { path.prepend( '/' ); path.prepend( item->text( 1 ) ); } return path; } void Item::setOpen( bool b ) { if ( !m_listed ) { m_lister.openURL( m_url, true ); m_listed = true; } TQListViewItem::setOpen( b ); } void Item::stateChange( bool b ) { if( CollectionSetup::instance()->recursive() ) for( TQListViewItem *item = firstChild(); item; item = item->nextSibling() ) static_cast(item)->TQCheckListItem::setOn( b ); // Update folder list TQStringList::Iterator it = CollectionSetup::instance()->m_dirs.find( m_url.path() ); if ( isOn() ) { if ( it == CollectionSetup::instance()->m_dirs.end() ) { CollectionSetup::instance()->m_dirs << m_url.path(); CollectionSetup::instance()->m_refcount[ m_url.path() ] = 1; } else CollectionSetup::instance()->m_refcount[ m_url.path() ]++; } else if ( CollectionSetup::instance()->m_refcount.find( m_url.path() ) != CollectionSetup::instance()->m_refcount.end() ) { if ( --CollectionSetup::instance()->m_refcount[ m_url.path() ] == 0 ) { CollectionSetup::instance()->m_dirs.erase( it ); CollectionSetup::instance()->m_refcount.remove( m_url.path() ); } } // Redraw parent items listView()->triggerUpdate(); } void Item::activate() { if( !isDisabled() ) TQCheckListItem::activate(); } void Item::newItems( const KFileItemList &list ) //SLOT { for( KFileItemListIterator it( list ); *it; ++it ) { Item *item = new Item( this, (*it)->url() ); item->setOn( CollectionSetup::instance()->recursive() && isOn() || CollectionSetup::instance()->m_dirs.contains( item->fullPath() ) ); item->setPixmap( 0, (*it)->pixmap( TDEIcon::SizeSmall ) ); } } void Item::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int align ) { bool dirty = false; // Figure out if a child folder is activated for ( uint i = 0; i < CollectionSetup::instance()->m_dirs.count(); i++ ) { if ( CollectionSetup::instance()->m_dirs[ i ] == m_url.path() ) { dirty = true; } else if ( CollectionSetup::instance()->m_dirs[ i ].startsWith( m_url.path() ) ) dirty = true; } // Use a different color if this folder has an activated child folder TQColorGroup _cg = cg; if ( dirty ) _cg.setColor( TQColorGroup::Text, TQt::blue ); TQCheckListItem::paintCell( p, isDisabled() ? listView()->palette().disabled() : _cg, column, width, align ); if (!dirty) setOn(false); } ////////////////////////////////////////////////////////////////////////////////////////// // CLASS DeviceItem ////////////////////////////////////////////////////////////////////////////////////////// DeviceItem::DeviceItem( TQListView *parent ) : TQCheckListItem( parent, i18n("Devices"), TQCheckListItem::CheckBox ) , m_lister( true ) , m_listed( false ) { m_lister.setDirOnlyMode( true ); connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) ); if ( KDE::versionMajor() == 3 && KDE::versionMinor() < 4 ) { m_url = "devices:/"; } else m_url = "media:/"; setText(1, "devices"); setOpen( true ); setPixmap(0, SmallIcon("kfm") ); setVisible( true ); } DeviceItem::DeviceItem( TQListViewItem *parent, const TQString &name, const KURL &url ) : TQCheckListItem( parent, name, TQCheckListItem::CheckBox ) , m_lister( true ) , m_url( url ) , m_listed( false ) { if (!kapp->dcopClient()->isAttached()) kapp->dcopClient()->attach(); else ////kdDebug() << "attached" << endl; TQByteArray data; TQByteArray param; TQCString retType; TQStringList retVal; TQDataStream streamout(param,IO_WriteOnly); streamout<< url.fileName(); TQCString mediacall="mediamanager"; TQCString devicecall="properties"; if ( KDE::versionMajor() == 3 && KDE::versionMinor() < 4 ) { mediacall="mountwatcher"; devicecall="basicDeviceInfo"; } DCOPRef mediamanager("kded", mediacall); DCOPReply reply = mediamanager.call( devicecall, url.fileName() ); if ( !reply.isValid() ) { ////kdDebug() << "not valid" << endl; } retVal = reply; //KAutoMount* am = new KAutoMount( true, "", retVal[5], "","", false ); ////kdDebug() << retVal[6] << endl; setText(1, KURL(retVal[6]).path()); setText(2, url.fileName()); kdDebug() << "Device Item: " << name << " " << url.fileName() << " " << text(1) << endl; m_lister.setDirOnlyMode( true ); setExpandable( false ); connect( &m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(newItems( const KFileItemList& )) ); connect( &m_lister, SIGNAL(completed()), SLOT(completed()) ); connect( &m_lister, SIGNAL(canceled()), SLOT(completed()) ); } TQString DeviceItem::fullPath() const { TQString path = text(1); if (path != "devices") return path; return ""; } void DeviceItem::setOpen( bool b ) { if ( !m_listed && text(1) == "devices") { m_lister.openURL( m_url, true ); } m_listed = true; TQListViewItem::setOpen( b ); } void DeviceItem::stateChange( bool b ) { if( CollectionSetup::instance()->recursive() ) for( TQListViewItem *item = firstChild(); item; item = item->nextSibling() ) static_cast(item)->TQCheckListItem::setOn( b ); if (text(1) != "devices") { // Update folder list TQStringList::Iterator it = CollectionSetup::instance()->m_dirs.find( text(1) ); if ( isOn() ) { if ( it == CollectionSetup::instance()->m_dirs.end() ) { CollectionSetup::instance()->m_dirs << text(1); mountDevice(text(2)); CollectionSetup::instance()->m_refcount[text(1)] = 1; } else CollectionSetup::instance()->m_refcount[text(1)]++; } else if ( CollectionSetup::instance()->m_refcount.find(text(1)) != CollectionSetup::instance()->m_refcount.end() ) { if ( --CollectionSetup::instance()->m_refcount[text(1)] == 0 ) { CollectionSetup::instance()->m_dirs.erase( it ); CollectionSetup::instance()->m_refcount.remove(text(1)); } } } // Redraw parent items listView()->triggerUpdate(); } void DeviceItem::activate() { if( !isDisabled() ) TQCheckListItem::activate(); } void DeviceItem::newItems( const KFileItemList &list ) //SLOT { for( KFileItemListIterator it( list ); *it; ++it ) { kdDebug() << (*it)->name() << " " << (*it)->url() << " " << (*it)->text() << endl; if (this->listView()->findItem((*it)->name(),0) == 0){ DeviceItem *item = new DeviceItem( this, (*it)->name(), (*it)->url() ); item->setOn( CollectionSetup::instance()->recursive() && isOn() || CollectionSetup::instance()->m_dirs.contains( item->fullPath() ) ); item->setPixmap( 0, (*it)->pixmap( TDEIcon::SizeSmall ) ); } } } void DeviceItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int align ) { bool dirty = false; TQColorGroup _cg = cg; ////kdDebug() << text(1) << endl; if (text(1) != "devices") { // Figure out if a child folder is activated for ( uint i = 0; i < CollectionSetup::instance()->m_dirs.count(); i++ ) { if ( CollectionSetup::instance()->m_dirs[i] == text(1) ) { dirty = true; } else if ( CollectionSetup::instance()->m_dirs[i].startsWith( text(1) + "/" ) ) dirty = true; } } else { for( TQListViewItem *item = firstChild(); item; item = item->nextSibling() ) { DeviceItem *itm = dynamic_cast(item); for ( uint i = 0; i < CollectionSetup::instance()->m_dirs.count(); i++ ) { if ( CollectionSetup::instance()->m_dirs[i] == itm->fullPath() ) { dirty = true; break; } else if ( CollectionSetup::instance()->m_dirs[i].startsWith( itm->fullPath() ) ) { dirty = true; break; } } } } // Use a different color if this folder has an activated child folder if ( dirty ) _cg.setColor( TQColorGroup::Text, TQt::blue ); TQCheckListItem::paintCell( p, isDisabled() ? listView()->palette().disabled() : _cg, column, width, align ); } TQString DeviceItem::getMountPoint( const TQString & device ) { DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "properties", device ); TQStringList properties; reply.get( properties, "TQStringList" ); TQString mountpoint = * (properties.at(7) ); return mountpoint; } void DeviceItem::mountDevice( const TQString & device) { if (!kapp->dcopClient()->isAttached()) kapp->dcopClient()->attach(); TQString mountpoint; mountpoint = getMountPoint(device); if( mountpoint != TQString::null ) // already mounted return; DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "mountByNode", device ); bool success; reply.get( success, "bool" ); mountpoint = getMountPoint(device); if(! success || mountpoint == TQString::null ) { KMessageBox::sorry( 0, i18n("Cannot mount device '%1'. Please check that you have the permissions needed to mount the device, as well as the needed kernel modules loaded.").arg(device) ); } } TQStringList CollectionSetup::pruneSelectedDirs( TQStringList listOfUrls ){ // This gets rid of redundant sub-directories // from the list of dirs to be scanned. TQStringList filepattern; listOfUrls.sort(); TQString prev; TQStringList prevdirs; struct stat sb; for (TQStringList::Iterator it = listOfUrls.begin(); it != listOfUrls.end(); it++ ){ //kdDebug() << "dir: " << (*it) << endl; (*it) = (*it).stripWhiteSpace(); // replace block devices with mountpoints lstat( (*it).ascii(), &sb ); if ( (sb.st_mode & S_IFMT) == S_IFBLK ) { // This is actually from directorylist.cpp DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "properties", (*it) ); TQStringList properties; reply.get( properties, "TQStringList" ); (*it) = * (properties.at(7) ); } else { (*it) = (*it) + "/"; } if (prevdirs.isEmpty()){ //kdDebug() << (*it) << endl; filepattern.append(*it); prevdirs.append((*it)); }else{ filepattern.append(*it); bool shouldappend = true; for (TQStringList::Iterator it2 = prevdirs.begin(); it2 != prevdirs.end(); it2++ ){ if ((*it).contains(*it2)){ //kdDebug() << (*it) << endl; filepattern.remove((*it)); shouldappend = false; break; } } if (shouldappend) prevdirs.append((*it)); } } return filepattern; } void CollectionSetup::writeConfig( const char* optGroup, const char* optName ) { TDEConfig *config = TDEGlobal::config(); config->setGroup( optGroup ); config->writeEntry( optName, dirs() ); config->sync(); } #include "directorylist.moc"