00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qfile.h>
00022
00023 #include <kfileitem.h>
00024 #include <kdebug.h>
00025
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <unistd.h>
00029
00030 #include "kfiletreeviewitem.h"
00031 #include "kfiletreebranch.h"
00032
00033
00034
00035 KFileTreeBranch::KFileTreeBranch( KFileTreeView *parent, const KURL& url,
00036 const QString& name,
00037 const QPixmap& pix, bool showHidden,
00038 KFileTreeViewItem *branchRoot )
00039
00040 : KDirLister( false ),
00041 m_root( branchRoot ),
00042 m_startURL( url ),
00043 m_name ( name ),
00044 m_rootIcon( pix ),
00045 m_openRootIcon( pix ),
00046 m_recurseChildren(true),
00047 m_showExtensions(true)
00048 {
00049 kdDebug( 250) << "Creating branch for url " << url.prettyURL() << endl;
00050
00051
00052 if( ! branchRoot )
00053 {
00054 m_root = new KFileTreeViewItem( parent,
00055 new KFileItem( url, "inode/directory",
00056 S_IFDIR ),
00057 this );
00058 }
00059
00060 m_root->setExpandable( true );
00061 m_root->setPixmap( 0, pix );
00062 m_root->setText( 0, name );
00063
00064 setShowingDotFiles( showHidden );
00065
00066 connect( this, SIGNAL( newItems(const KFileItemList&)),
00067 this, SLOT ( addItems( const KFileItemList& )));
00068
00069 connect( this, SIGNAL( completed(const KURL& )),
00070 this, SLOT(slCompleted(const KURL&)));
00071
00072 connect( this, SIGNAL( started( const KURL& )),
00073 this, SLOT( slotListerStarted( const KURL& )));
00074
00075 connect( this, SIGNAL( deleteItem( KFileItem* )),
00076 this, SLOT( slotDeleteItem( KFileItem* )));
00077
00078 connect( this, SIGNAL( canceled(const KURL&) ),
00079 this, SLOT( slotCanceled(const KURL&) ));
00080
00081 connect( this, SIGNAL( clear()),
00082 this, SLOT( slotDirlisterClear()));
00083
00084 connect( this, SIGNAL( clear(const KURL&)),
00085 this, SLOT( slotDirlisterClearURL(const KURL&)));
00086
00087 connect( this, SIGNAL( redirection( const KURL& , const KURL& ) ),
00088 this, SLOT( slotRedirect( const KURL&, const KURL& )));
00089
00090 m_openChildrenURLs.append( url );
00091 }
00092
00093 void KFileTreeBranch::setOpenPixmap( const QPixmap& pix )
00094 {
00095 m_openRootIcon = pix;
00096
00097 if( root()->isOpen())
00098 {
00099 root()->setPixmap( 0, pix );
00100 }
00101 }
00102
00103 void KFileTreeBranch::slotListerStarted( const KURL &url )
00104 {
00105
00106 kdDebug( 250) << "Starting to list " << url.prettyURL() << endl;
00107 }
00108
00109
00110 KFileTreeViewItem *KFileTreeBranch::parentKFTVItem( KFileItem *item )
00111 {
00112 KFileTreeViewItem *parent = 0;
00113
00114 if( ! item ) return 0;
00115
00116
00117
00118
00119 KURL url = item->url();
00120
00121 KURL dirUrl( url );
00122 dirUrl.setFileName( QString::null );
00123
00124
00125 parent = findTVIByURL( dirUrl );
00126
00127 return( parent );
00128 }
00129
00130
00131 void KFileTreeBranch::addItems( const KFileItemList& list )
00132 {
00133 KFileItemListIterator it( list );
00134 kdDebug(250) << "Adding " << list.count() << " items !" << endl;
00135 KFileItem *currItem;
00136 KFileTreeViewItemList treeViewItList;
00137 KFileTreeViewItem *parentItem = 0;
00138
00139 while ( (currItem = it.current()) != 0 )
00140 {
00141 parentItem = parentKFTVItem( currItem );
00142
00143
00144 KFileTreeViewItem *newKFTVI =
00145 static_cast<KFileTreeViewItem *>(currItem->extraData( this ));
00146
00147 if( ! newKFTVI )
00148 {
00149 newKFTVI = createTreeViewItem( parentItem, currItem );
00150 currItem->setExtraData( this, newKFTVI );
00151
00152
00153
00154 if( !m_showExtensions && !currItem->isDir() )
00155 {
00156 QString name = currItem->text();
00157 int mPoint = name.findRev( '.' );
00158 if( mPoint > 0 )
00159 name = name.left( mPoint );
00160 newKFTVI->setText( 0, name );
00161 }
00162 }
00163
00164
00165
00166
00167 if( dirOnlyMode() && !m_recurseChildren && currItem->isLocalFile( ) && currItem->isDir() )
00168 {
00169 KURL url = currItem->url();
00170 QString filename = url.directory( false, true ) + url.fileName();
00171
00172
00173
00174 kdDebug(250) << "Doing stat on " << filename << endl;
00175 struct stat statBuf;
00176 if( stat( QFile::encodeName( filename ), &statBuf ) == 0 )
00177 {
00178 int hardLinks = statBuf.st_nlink;
00179 kdDebug(250) << "stat succeeded, hardlinks: " << hardLinks << endl;
00180
00181
00182
00183
00184 if( hardLinks != 2 )
00185 {
00186 newKFTVI->setExpandable(true);
00187 }
00188 else
00189 {
00190 newKFTVI->setExpandable(false);
00191 }
00192 if( hardLinks >= 2 )
00193 {
00194 kdDebug(250) << "Emitting for " << url.prettyURL() << endl;
00195 emit( directoryChildCount( newKFTVI, hardLinks-2));
00196 }
00197 }
00198 else
00199 {
00200 kdDebug(250) << "stat of " << filename << " failed !" << endl;
00201 }
00202 }
00203 ++it;
00204
00205 treeViewItList.append( newKFTVI );
00206 }
00207
00208 emit newTreeViewItems( this, treeViewItList );
00209 }
00210
00211 KFileTreeViewItem* KFileTreeBranch::createTreeViewItem( KFileTreeViewItem *parent,
00212 KFileItem *fileItem )
00213 {
00214 KFileTreeViewItem *tvi = 0;
00215 if( parent && fileItem )
00216 {
00217 tvi = new KFileTreeViewItem( parent,
00218 fileItem,
00219 this );
00220 }
00221 else
00222 {
00223 kdDebug(250) << "createTreeViewItem: Have no parent" << endl;
00224 }
00225 return( tvi );
00226 }
00227
00228 void KFileTreeBranch::setChildRecurse( bool t )
00229 {
00230 m_recurseChildren = t;
00231 if( t == false )
00232 m_openChildrenURLs.clear();
00233 }
00234
00235
00236 void KFileTreeBranch::setShowExtensions( bool visible )
00237 {
00238 m_showExtensions = visible;
00239 }
00240
00241 bool KFileTreeBranch::showExtensions( ) const
00242 {
00243 return( m_showExtensions );
00244 }
00245
00246
00247
00248
00249
00250
00251 void KFileTreeBranch::slotDeleteItem( KFileItem *it )
00252 {
00253 if( !it ) return;
00254 kdDebug(250) << "Slot Delete Item hitted for " << it->url().prettyURL() << endl;
00255
00256 KFileTreeViewItem *kfti = static_cast<KFileTreeViewItem*>(it->extraData(this));
00257
00258 if( kfti )
00259 {
00260 kdDebug( 250 ) << "Child count: " << kfti->childCount() << endl;
00261 if( kfti->childCount() > 0 )
00262 {
00263 KFileTreeViewItem *child = static_cast<KFileTreeViewItem*>(kfti->firstChild());
00264
00265 while( child )
00266 {
00267 kdDebug(250) << "Calling child to be deleted !" << endl;
00268 KFileTreeViewItem *nextChild = static_cast<KFileTreeViewItem*>(child->nextSibling());
00269 slotDeleteItem( child->fileItem());
00270 child = nextChild;
00271 }
00272 }
00273
00274 kdDebug(250) << "Found corresponding KFileTreeViewItem" << endl;
00275 delete( kfti );
00276 }
00277 else
00278 {
00279 kdDebug(250) << "Error: kfiletreeviewitem: "<< kfti << endl;
00280 }
00281 }
00282
00283
00284 void KFileTreeBranch::slotCanceled( const KURL& url )
00285 {
00286
00287
00288 m_openChildrenURLs.remove( url);
00289
00290
00291 emit populateFinished( findTVIByURL(url));
00292 }
00293
00294 void KFileTreeBranch::slotDirlisterClear()
00295 {
00296 kdDebug(250)<< "*** Clear all !" << endl;
00297
00298 if( m_root )
00299 deleteChildrenOf( m_root );
00300 }
00301
00302 void KFileTreeBranch::slotDirlisterClearURL( const KURL& url )
00303 {
00304 kdDebug(250)<< "*** Clear for URL !" << url.prettyURL() << endl;
00305 KFileItem *item = findByURL( url );
00306 if( item )
00307 {
00308 KFileTreeViewItem *ftvi =
00309 static_cast<KFileTreeViewItem *>(item->extraData( this ));
00310 deleteChildrenOf( ftvi );
00311 }
00312 }
00313 void KFileTreeBranch::deleteChildrenOf( QListViewItem *parent )
00314 {
00315
00316
00317 if ( !parent )
00318 return;
00319
00320 QListViewItem *child = parent->firstChild();
00321 QListViewItem *next = child;
00322
00323 while( child )
00324 {
00325 next = child->nextSibling();
00326 delete child;
00327 child = next;
00328 }
00329 }
00330
00331 void KFileTreeBranch::slotRedirect( const KURL& oldUrl, const KURL&newUrl )
00332 {
00333 if( oldUrl.equals( m_startURL, true ))
00334 {
00335 m_startURL = newUrl;
00336 }
00337 }
00338
00339 KFileTreeViewItem* KFileTreeBranch::findTVIByURL( const KURL& url )
00340 {
00341 KFileTreeViewItem *resultItem = 0;
00342
00343 if( m_startURL.equals(url, true) )
00344 {
00345 kdDebug(250) << "findByURL: Returning root as a parent !" << endl;
00346 resultItem = m_root;
00347 }
00348 else if( m_lastFoundURL.equals( url, true ))
00349 {
00350 kdDebug(250) << "findByURL: Returning from lastFoundURL!" << endl;
00351 resultItem = m_lastFoundItem;
00352 }
00353 else
00354 {
00355 kdDebug(250) << "findByURL: searching by dirlister: " << url.url() << endl;
00356
00357 KFileItem *it = findByURL( url );
00358
00359 if( it )
00360 {
00361 resultItem = static_cast<KFileTreeViewItem*>(it->extraData(this));
00362 m_lastFoundItem = resultItem;
00363 m_lastFoundURL = url;
00364 }
00365 }
00366
00367 return( resultItem );
00368 }
00369
00370
00371 void KFileTreeBranch::slCompleted( const KURL& url )
00372 {
00373 kdDebug(250) << "SlotCompleted hit for " << url.prettyURL() << endl;
00374 KFileTreeViewItem *currParent = findTVIByURL( url );
00375 if( ! currParent ) return;
00376
00377 kdDebug(250) << "current parent " << currParent << " is already listed: "
00378 << currParent->alreadyListed() << endl;
00379
00380 emit( populateFinished(currParent));
00381 emit( directoryChildCount(currParent, currParent->childCount()));
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 currParent->setListed(true);
00392
00393 kdDebug(250) << "recurseChildren: " << m_recurseChildren << endl;
00394 kdDebug(250) << "isLocalFile: " << m_startURL.isLocalFile() << endl;
00395 kdDebug(250) << "dirOnlyMode: " << dirOnlyMode() << endl;
00396
00397
00398 if( m_recurseChildren && (!m_startURL.isLocalFile() || ! dirOnlyMode()) )
00399 {
00400 bool wantRecurseUrl = false;
00401
00402 for ( KURL::List::Iterator it = m_openChildrenURLs.begin();
00403 it != m_openChildrenURLs.end(); ++it )
00404 {
00405
00406 if( (*it).equals( url, true ) )
00407 wantRecurseUrl = true;
00408 }
00409
00410 KFileTreeViewItem *nextChild = 0;
00411 kdDebug(250) << "Recursing " << url.prettyURL() << "? " << wantRecurseUrl << endl;
00412
00413 if( wantRecurseUrl && currParent )
00414 {
00415
00416
00417
00418
00419 nextChild = static_cast<KFileTreeViewItem*>
00420 (static_cast<QListViewItem*>(currParent)->firstChild());
00421
00422 if( ! nextChild )
00423 {
00424
00425 kdDebug( 250 ) << "No children to recuse" << endl;
00426 }
00427
00428
00429
00430
00431 m_openChildrenURLs.remove(url);
00432 }
00433
00434 if( nextChild )
00435 {
00436
00437
00438
00439
00440
00441
00442 while( nextChild )
00443 {
00444 if( nextChild->isDir() && ! nextChild->alreadyListed())
00445 {
00446 KFileItem *kfi = nextChild->fileItem();
00447 if( kfi && kfi->isReadable())
00448 {
00449 KURL recurseUrl = kfi->url();
00450 kdDebug(250) << "Starting to recurse NOW " << recurseUrl.prettyURL() << endl;
00451 openURL( recurseUrl, true );
00452 }
00453 }
00454 nextChild = static_cast<KFileTreeViewItem*>(static_cast<QListViewItem*>(nextChild->nextSibling()));
00455
00456 }
00457 }
00458 }
00459 else
00460 {
00461 kdDebug(250) << "skipping to recurse in complete-slot" << endl;
00462 }
00463 }
00464
00465
00466 bool KFileTreeBranch::populate( const KURL& url, KFileTreeViewItem *currItem )
00467 {
00468 bool ret = false;
00469 if( ! currItem )
00470 return ret;
00471
00472 kdDebug(250) << "Populating <" << url.prettyURL() << ">" << endl;
00473
00474
00475 if( m_recurseChildren )
00476 {
00477 m_openChildrenURLs.append( url );
00478 kdDebug(250) << "Appending to list " << url.prettyURL() << endl;
00479 }
00480
00481 if( ! currItem->alreadyListed() )
00482 {
00483
00484 ret = openURL( url, true );
00485 }
00486 else
00487 {
00488 kdDebug(250) << "Children already existing in treeview!" << endl;
00489 slCompleted( url );
00490 ret = true;
00491 }
00492 return ret;
00493 }
00494
00495 void KFileTreeBranch::virtual_hook( int id, void* data )
00496 { KDirLister::virtual_hook( id, data ); }
00497
00498 #include "kfiletreebranch.moc"
00499