00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kfiletreebranch.h"
00022
00023 #include <QtCore/QFile>
00024
00025 #include <kfileitem.h>
00026 #include <kdebug.h>
00027 #include <kde_file.h>
00028
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <unistd.h>
00032
00033
00034 KFileTreeBranch::KFileTreeBranch( K3FileTreeView *parent, const KUrl& url,
00035 const QString& name,
00036 const QPixmap& pix, bool showHidden,
00037 K3FileTreeViewItem *branchRoot )
00038
00039 : KDirLister(),
00040 m_root( branchRoot ),
00041 m_startURL( url ),
00042 m_name ( name ),
00043 m_rootIcon( pix ),
00044 m_openRootIcon( pix ),
00045 m_recurseChildren(true),
00046 m_showExtensions(true)
00047 {
00048 kDebug( 250) << "Creating branch for url " << url.prettyUrl();
00049
00050
00051 if( ! branchRoot )
00052 {
00053 m_root = new K3FileTreeViewItem( parent,
00054 KFileItem( url, "inode/directory",
00055 S_IFDIR ),
00056 this );
00057 }
00058
00059 m_root->setExpandable( true );
00060 m_root->setPixmap( 0, pix );
00061 m_root->setText( 0, name );
00062
00063 setShowingDotFiles( showHidden );
00064
00065 connect( this, SIGNAL( refreshItems(const QList<QPair<KFileItem, KFileItem> >&)),
00066 this, SLOT ( slotRefreshItems( const QList<QPair<KFileItem, KFileItem> >& )));
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( const KFileItem& )),
00078 this, SLOT( slotDeleteItem( const 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 KUrl KFileTreeBranch::rootUrl() const
00096 {
00097 return( m_startURL );
00098 }
00099
00100 void KFileTreeBranch::setRoot( K3FileTreeViewItem *r )
00101 {
00102 m_root = r;
00103 }
00104
00105 K3FileTreeViewItem *KFileTreeBranch::root( )
00106 {
00107 return( m_root );
00108 }
00109
00110 QString KFileTreeBranch::name() const
00111 {
00112 return( m_name );
00113 }
00114
00115 void KFileTreeBranch::setName( const QString n )
00116 {
00117 m_name = n;
00118 }
00119
00120 QPixmap KFileTreeBranch::pixmap() const
00121 {
00122 return m_rootIcon;
00123 }
00124
00125 QPixmap KFileTreeBranch::openPixmap() const
00126 {
00127 return m_openRootIcon;
00128 }
00129
00130 void KFileTreeBranch::setOpen( bool setopen )
00131 {
00132 if ( root() ) {
00133 root()->setOpen( setopen );
00134 }
00135 }
00136
00137 void KFileTreeBranch::setOpenPixmap( const QPixmap& pix )
00138 {
00139 m_openRootIcon = pix;
00140
00141 if( root()->isOpen())
00142 {
00143 root()->setPixmap( 0, pix );
00144 }
00145 }
00146
00147 void KFileTreeBranch::slotListerStarted( const KUrl &url )
00148 {
00149
00150 kDebug( 250) << "Starting to list " << url.prettyUrl();
00151 }
00152
00153
00154 K3FileTreeViewItem* KFileTreeBranch::treeItemForFileItem(const KFileItem &it)
00155 {
00156 return
00157 const_cast<K3FileTreeViewItem *>(
00158 static_cast<const K3FileTreeViewItem*>(it.extraData(this)));
00159 }
00160
00161 K3FileTreeViewItem *KFileTreeBranch::parentKFTVItem( const KFileItem &item )
00162 {
00163 K3FileTreeViewItem *parent = 0;
00164
00165 if( item.isNull() ) return 0;
00166
00167
00168
00169
00170 KUrl url = item.url();
00171
00172 KUrl dirUrl( url );
00173 dirUrl.setFileName( QString() );
00174
00175
00176 parent = findTVIByUrl( dirUrl );
00177
00178 return( parent );
00179 }
00180
00181
00182 void KFileTreeBranch::slotRefreshItems( const QList<QPair<KFileItem, KFileItem> > &list )
00183 {
00184 kDebug(250) << "Refreshing " << list.count() << " items !";
00185
00186 for ( int i = 0; i < list.count(); ++i )
00187 {
00188 const KFileItem fileItem = list[ i ].second;
00189
00190 K3FileTreeViewItem *item = findTVIByUrl(fileItem.url());
00191 if (item) {
00192 item->setPixmap(0, item->fileItem().pixmap( KIconLoader::SizeSmall ));
00193 item->setText( 0, item->fileItem().text());
00194 }
00195 }
00196 }
00197
00198 void KFileTreeBranch::addItems( const KFileItemList& list )
00199 {
00200 kDebug(250) << "Adding " << list.count() << " items !";
00201 K3FileTreeViewItemList treeViewItList;
00202 K3FileTreeViewItem *parentItem = 0;
00203
00204 KFileItemList::const_iterator kit = list.begin();
00205 const KFileItemList::const_iterator kend = list.end();
00206 for ( ; kit != kend; ++kit )
00207 {
00208 KFileItem currItem = *kit;
00209 parentItem = parentKFTVItem( currItem );
00210
00211
00212 K3FileTreeViewItem *newKFTVI = treeItemForFileItem(currItem);
00213
00214 if( ! newKFTVI )
00215 {
00216 newKFTVI = createTreeViewItem( parentItem, currItem );
00217 if (!newKFTVI)
00218 {
00219
00220 continue;
00221 }
00222 currItem.setExtraData( this, newKFTVI );
00223
00224
00225 if( !m_showExtensions && !currItem.isDir() )
00226 {
00227 QString name = currItem.text();
00228 int mPoint = name.lastIndexOf( '.' );
00229 if( mPoint > 0 )
00230 name = name.left( mPoint );
00231 newKFTVI->setText( 0, name );
00232 }
00233 }
00234
00235
00236
00237
00238 if( dirOnlyMode() && !m_recurseChildren && currItem.isLocalFile( ) && currItem.isDir() )
00239 {
00240 KUrl url = currItem.url();
00241 QString filename = url.directory( KUrl::ObeyTrailingSlash ) + url.fileName();
00242
00243
00244
00245 kDebug(250) << "Doing stat on " << filename;
00246 KDE_struct_stat statBuf;
00247 if( KDE::stat( filename , &statBuf ) == 0 )
00248 {
00249 int hardLinks = statBuf.st_nlink;
00250 kDebug(250) << "stat succeeded, hardlinks: " << hardLinks;
00251
00252
00253
00254
00255 if( hardLinks != 2 )
00256 {
00257 newKFTVI->setExpandable(true);
00258 }
00259 else
00260 {
00261 newKFTVI->setExpandable(false);
00262 }
00263 if( hardLinks >= 2 )
00264 {
00265 kDebug(250) << "Emitting for " << url.prettyUrl();
00266 emit( directoryChildCount( newKFTVI, hardLinks-2));
00267 }
00268 }
00269 else
00270 {
00271 kDebug(250) << "stat of " << filename << " failed !";
00272 }
00273 }
00274 treeViewItList.append( newKFTVI );
00275 }
00276
00277 emit newTreeViewItems( this, treeViewItList );
00278 }
00279
00280 K3FileTreeViewItem* KFileTreeBranch::createTreeViewItem( K3FileTreeViewItem *parent,
00281 const KFileItem &fileItem )
00282 {
00283 K3FileTreeViewItem *tvi = 0;
00284 if( parent && !fileItem.isNull() )
00285 {
00286 tvi = new K3FileTreeViewItem( parent,
00287 fileItem,
00288 this );
00289 }
00290 else
00291 {
00292 kDebug(250) << "createTreeViewItem: Have no parent";
00293 }
00294 return( tvi );
00295 }
00296
00297 void KFileTreeBranch::setChildRecurse( bool t )
00298 {
00299 m_recurseChildren = t;
00300 if( t == false )
00301 m_openChildrenURLs.clear();
00302 }
00303
00304 bool KFileTreeBranch::childRecurse()
00305 {
00306 return m_recurseChildren;
00307 }
00308
00309
00310 void KFileTreeBranch::setShowExtensions( bool visible )
00311 {
00312 m_showExtensions = visible;
00313 }
00314
00315 bool KFileTreeBranch::showExtensions( ) const
00316 {
00317 return( m_showExtensions );
00318 }
00319
00320
00321
00322
00323
00324
00325 void KFileTreeBranch::slotDeleteItem( const KFileItem &it )
00326 {
00327 if( it.isNull() ) return;
00328 kDebug(250) << "Slot Delete Item hitted for " << it.url().prettyUrl();
00329
00330 K3FileTreeViewItem *kfti = treeItemForFileItem(it);
00331
00332 if( kfti )
00333 {
00334 kDebug( 250 ) << "Child count: " << kfti->childCount();
00335 if( kfti->childCount() > 0 )
00336 {
00337 K3FileTreeViewItem *child = static_cast<K3FileTreeViewItem*>(kfti->firstChild());
00338
00339 while( child )
00340 {
00341 kDebug(250) << "Calling child to be deleted !";
00342 K3FileTreeViewItem *nextChild = static_cast<K3FileTreeViewItem*>(child->nextSibling());
00343 slotDeleteItem( child->fileItem());
00344 child = nextChild;
00345 }
00346 }
00347
00348 kDebug(250) << "Found corresponding K3FileTreeViewItem";
00349 if( m_lastFoundURL.equals(it.url(), KUrl::CompareWithoutTrailingSlash ))
00350 {
00351 m_lastFoundURL = KUrl();
00352 m_lastFoundItem = 0L;
00353 }
00354 delete( kfti );
00355 }
00356 else
00357 {
00358 kDebug(250) << "Error: kfiletreeviewitem: "<< kfti;
00359 }
00360 }
00361
00362
00363 void KFileTreeBranch::slotCanceled( const KUrl& url )
00364 {
00365
00366
00367 m_openChildrenURLs.removeAll( url);
00368
00369
00370 K3FileTreeViewItem *item = findTVIByUrl(url);
00371 if (!item) return;
00372 emit populateFinished(item);
00373 }
00374
00375 void KFileTreeBranch::slotDirlisterClear()
00376 {
00377 kDebug(250)<< "*** Clear all !";
00378
00379 if( m_root )
00380 deleteChildrenOf( m_root );
00381 }
00382
00383 void KFileTreeBranch::slotDirlisterClearUrl( const KUrl& url )
00384 {
00385 kDebug(250)<< "*** Clear for URL !" << url.prettyUrl();
00386 const KFileItem item = findByUrl( url );
00387 if( !item.isNull() )
00388 {
00389 K3FileTreeViewItem *ftvi = treeItemForFileItem(item);
00390 deleteChildrenOf( ftvi );
00391 }
00392 }
00393
00394 void KFileTreeBranch::deleteChildrenOf( Q3ListViewItem *parent )
00395 {
00396
00397
00398 if ( !parent )
00399 return;
00400
00401 while ( parent->firstChild() )
00402 delete parent->firstChild();
00403 }
00404
00405 void KFileTreeBranch::slotRedirect( const KUrl& oldUrl, const KUrl&newUrl )
00406 {
00407 if( oldUrl.equals( m_startURL, KUrl::CompareWithoutTrailingSlash ))
00408 {
00409 m_startURL = newUrl;
00410 }
00411 }
00412
00413 K3FileTreeViewItem* KFileTreeBranch::findTVIByUrl( const KUrl& url )
00414 {
00415 K3FileTreeViewItem *resultItem = 0;
00416
00417 if( m_startURL.equals(url, KUrl::CompareWithoutTrailingSlash) )
00418 {
00419 kDebug(250) << "findByURL: Returning root as a parent !";
00420 resultItem = m_root;
00421 }
00422 else if( m_lastFoundURL.equals( url, KUrl::CompareWithoutTrailingSlash ))
00423 {
00424 kDebug(250) << "findByURL: Returning from lastFoundURL!";
00425 resultItem = m_lastFoundItem;
00426 }
00427 else
00428 {
00429 kDebug(250) << "findByURL: searching by dirlister: " << url.url();
00430
00431 const KFileItem it = findByUrl( url );
00432
00433 if( !it.isNull() )
00434 {
00435 resultItem = treeItemForFileItem(it);
00436 m_lastFoundItem = resultItem;
00437 m_lastFoundURL = url;
00438 }
00439 }
00440
00441 return( resultItem );
00442 }
00443
00444
00445 void KFileTreeBranch::slCompleted( const KUrl& url )
00446 {
00447 kDebug(250) << "SlotCompleted hit for " << url.prettyUrl();
00448 K3FileTreeViewItem *currParent = findTVIByUrl( url );
00449 if( ! currParent ) return;
00450
00451 kDebug(250) << "current parent " << currParent << " is already listed: "
00452 << currParent->alreadyListed() << endl;
00453
00454 emit( populateFinished(currParent));
00455 emit( directoryChildCount(currParent, currParent->childCount()));
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 currParent->setListed(true);
00466
00467 kDebug(250) << "recurseChildren: " << m_recurseChildren;
00468 kDebug(250) << "isLocalFile: " << m_startURL.isLocalFile();
00469 kDebug(250) << "dirOnlyMode: " << dirOnlyMode();
00470
00471
00472 if( m_recurseChildren && (!m_startURL.isLocalFile() || ! dirOnlyMode()) )
00473 {
00474 bool wantRecurseUrl = false;
00475
00476 for ( KUrl::List::Iterator it = m_openChildrenURLs.begin();
00477 it != m_openChildrenURLs.end(); ++it )
00478 {
00479
00480 if( (*it).equals( url, KUrl::CompareWithoutTrailingSlash ) )
00481 wantRecurseUrl = true;
00482 }
00483
00484 K3FileTreeViewItem *nextChild = 0;
00485 kDebug(250) << "Recursing " << url.prettyUrl() << "? " << wantRecurseUrl;
00486
00487 if( wantRecurseUrl && currParent )
00488 {
00489
00490
00491
00492
00493 nextChild = static_cast<K3FileTreeViewItem*>
00494 (static_cast<Q3ListViewItem*>(currParent)->firstChild());
00495
00496 if( ! nextChild )
00497 {
00498
00499 kDebug( 250 ) << "No children to recuse";
00500 }
00501
00502
00503
00504
00505 m_openChildrenURLs.removeAll(url);
00506 }
00507
00508 if( nextChild )
00509 {
00510
00511
00512
00513
00514
00515
00516 while( nextChild )
00517 {
00518 if( nextChild->isDir() && ! nextChild->alreadyListed())
00519 {
00520 const KFileItem kfi = nextChild->fileItem();
00521 if( !kfi.isNull() && kfi.isReadable())
00522 {
00523 KUrl recurseUrl = kfi.url();
00524 kDebug(250) << "Starting to recurse NOW " << recurseUrl.prettyUrl();
00525 openUrl( recurseUrl, KDirLister::Keep );
00526 }
00527 }
00528 nextChild = static_cast<K3FileTreeViewItem*>(nextChild->nextSibling());
00529
00530 }
00531 }
00532 }
00533 else
00534 {
00535 kDebug(250) << "skipping to recurse in complete-slot";
00536 }
00537 }
00538
00539
00540 bool KFileTreeBranch::populate( const KUrl& url, K3FileTreeViewItem *currItem )
00541 {
00542 bool ret = false;
00543 if( ! currItem )
00544 return ret;
00545
00546 kDebug(250) << "Populating <" << url.prettyUrl() << ">";
00547
00548
00549 if( m_recurseChildren )
00550 {
00551 m_openChildrenURLs.append( url );
00552 kDebug(250) << "Appending to list " << url.prettyUrl();
00553 }
00554
00555 if( ! currItem->alreadyListed() )
00556 {
00557
00558 ret = openUrl( url, KDirLister::Keep );
00559 }
00560 else
00561 {
00562 kDebug(250) << "Children already existing in treeview!";
00563 slCompleted( url );
00564 ret = true;
00565 }
00566 return ret;
00567 }
00568
00569 #include "kfiletreebranch.moc"
00570