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
00314
void KFileTreeBranch::deleteChildrenOf(
QListViewItem *parent )
00315 {
00316
00317
00318
if ( !parent )
00319
return;
00320
00321
while ( parent->firstChild() )
00322
delete parent->firstChild();
00323 }
00324
00325
void KFileTreeBranch::slotRedirect(
const KURL& oldUrl,
const KURL&newUrl )
00326 {
00327
if( oldUrl.
equals( m_startURL,
true ))
00328 {
00329 m_startURL = newUrl;
00330 }
00331 }
00332
00333 KFileTreeViewItem*
KFileTreeBranch::findTVIByURL(
const KURL& url )
00334 {
00335
KFileTreeViewItem *resultItem = 0;
00336
00337
if( m_startURL.
equals(url,
true) )
00338 {
00339
kdDebug(250) <<
"findByURL: Returning root as a parent !" <<
endl;
00340 resultItem = m_root;
00341 }
00342
else if( m_lastFoundURL.
equals( url,
true ))
00343 {
00344
kdDebug(250) <<
"findByURL: Returning from lastFoundURL!" <<
endl;
00345 resultItem = m_lastFoundItem;
00346 }
00347
else
00348 {
00349
kdDebug(250) <<
"findByURL: searching by dirlister: " << url.
url() <<
endl;
00350
00351
KFileItem *it = findByURL( url );
00352
00353
if( it )
00354 {
00355 resultItem = static_cast<KFileTreeViewItem*>(it->
extraData(
this));
00356 m_lastFoundItem = resultItem;
00357 m_lastFoundURL = url;
00358 }
00359 }
00360
00361
return( resultItem );
00362 }
00363
00364
00365
void KFileTreeBranch::slCompleted(
const KURL& url )
00366 {
00367
kdDebug(250) <<
"SlotCompleted hit for " << url.
prettyURL() <<
endl;
00368
KFileTreeViewItem *currParent = findTVIByURL( url );
00369
if( ! currParent )
return;
00370
00371
kdDebug(250) <<
"current parent " << currParent <<
" is already listed: "
00372 << currParent->
alreadyListed() <<
endl;
00373
00374 emit( populateFinished(currParent));
00375 emit( directoryChildCount(currParent, currParent->childCount()));
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 currParent->
setListed(
true);
00386
00387
kdDebug(250) <<
"recurseChildren: " << m_recurseChildren <<
endl;
00388
kdDebug(250) <<
"isLocalFile: " << m_startURL.
isLocalFile() <<
endl;
00389
kdDebug(250) <<
"dirOnlyMode: " <<
dirOnlyMode() <<
endl;
00390
00391
00392
if( m_recurseChildren && (!m_startURL.
isLocalFile() || !
dirOnlyMode()) )
00393 {
00394
bool wantRecurseUrl =
false;
00395
00396
for ( KURL::List::Iterator it = m_openChildrenURLs.begin();
00397 it != m_openChildrenURLs.end(); ++it )
00398 {
00399
00400
if( (*it).equals( url,
true ) )
00401 wantRecurseUrl =
true;
00402 }
00403
00404
KFileTreeViewItem *nextChild = 0;
00405
kdDebug(250) <<
"Recursing " << url.
prettyURL() <<
"? " << wantRecurseUrl <<
endl;
00406
00407
if( wantRecurseUrl && currParent )
00408 {
00409
00410
00411
00412
00413 nextChild = static_cast<KFileTreeViewItem*>
00414 (static_cast<QListViewItem*>(currParent)->firstChild());
00415
00416
if( ! nextChild )
00417 {
00418
00419
kdDebug( 250 ) <<
"No children to recuse" <<
endl;
00420 }
00421
00422
00423
00424
00425 m_openChildrenURLs.remove(url);
00426 }
00427
00428
if( nextChild )
00429 {
00430
00431
00432
00433
00434
00435
00436
while( nextChild )
00437 {
00438
if( nextChild->
isDir() && ! nextChild->
alreadyListed())
00439 {
00440
KFileItem *kfi = nextChild->
fileItem();
00441
if( kfi && kfi->
isReadable())
00442 {
00443
KURL recurseUrl = kfi->
url();
00444
kdDebug(250) <<
"Starting to recurse NOW " << recurseUrl.
prettyURL() <<
endl;
00445
openURL( recurseUrl,
true );
00446 }
00447 }
00448 nextChild = static_cast<KFileTreeViewItem*>(static_cast<QListViewItem*>(nextChild->nextSibling()));
00449
00450 }
00451 }
00452 }
00453
else
00454 {
00455
kdDebug(250) <<
"skipping to recurse in complete-slot" <<
endl;
00456 }
00457 }
00458
00459
00460 bool KFileTreeBranch::populate(
const KURL& url,
KFileTreeViewItem *currItem )
00461 {
00462
bool ret =
false;
00463
if( ! currItem )
00464
return ret;
00465
00466
kdDebug(250) <<
"Populating <" << url.
prettyURL() <<
">" <<
endl;
00467
00468
00469
if( m_recurseChildren )
00470 {
00471 m_openChildrenURLs.append( url );
00472
kdDebug(250) <<
"Appending to list " << url.
prettyURL() <<
endl;
00473 }
00474
00475
if( ! currItem->
alreadyListed() )
00476 {
00477
00478 ret = openURL( url,
true );
00479 }
00480
else
00481 {
00482
kdDebug(250) <<
"Children already existing in treeview!" <<
endl;
00483 slCompleted( url );
00484 ret =
true;
00485 }
00486
return ret;
00487 }
00488
00489
void KFileTreeBranch::virtual_hook(
int id,
void* data )
00490 { KDirLister::virtual_hook(
id, data ); }
00491
00492
#include "kfiletreebranch.moc"
00493