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