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