00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <qapplication.h>
00021
#include <qheader.h>
00022
#include <qtimer.h>
00023
#include <kdebug.h>
00024
#include <kdirnotify_stub.h>
00025
#include <kglobalsettings.h>
00026
#include <kfileitem.h>
00027
#include <kfileview.h>
00028
#include <kmimetype.h>
00029
#include <kstandarddirs.h>
00030
#include <stdlib.h>
00031
#include <assert.h>
00032
#include <kio/job.h>
00033
#include <kio/global.h>
00034
#include <kurldrag.h>
00035
#include <kiconloader.h>
00036
00037
00038
#include "kfiletreeview.h"
00039
#include "kfiletreebranch.h"
00040
#include "kfiletreeviewitem.h"
00041
00042 KFileTreeView::KFileTreeView(
QWidget *parent,
const char *name )
00043 :
KListView( parent,
name ),
00044 m_wantOpenFolderPixmaps( true ),
00045 m_toolTip( this )
00046 {
00047 setDragEnabled(
true);
00048 setSelectionModeExt( KListView::Single );
00049
00050 m_animationTimer =
new QTimer(
this );
00051 connect( m_animationTimer, SIGNAL( timeout() ),
00052
this, SLOT( slotAnimation() ) );
00053
00054 m_currentBeforeDropItem = 0;
00055 m_dropItem = 0;
00056
00057 m_autoOpenTimer =
new QTimer(
this );
00058 connect( m_autoOpenTimer, SIGNAL( timeout() ),
00059
this, SLOT( slotAutoOpenFolder() ) );
00060
00061
00062 connect(
this, SIGNAL( executed(
QListViewItem * ) ),
00063
this, SLOT( slotExecuted(
QListViewItem * ) ) );
00064 connect(
this, SIGNAL( expanded (
QListViewItem *) ),
00065
this, SLOT( slotExpanded( QListViewItem *) ));
00066 connect(
this, SIGNAL( collapsed( QListViewItem *) ),
00067
this, SLOT( slotCollapsed( QListViewItem* )));
00068
00069
00070
00071 connect(
this, SIGNAL( selectionChanged() ),
00072
this, SLOT( slotSelectionChanged() ) );
00073 connect(
this, SIGNAL( onItem( QListViewItem * )),
00074
this, SLOT( slotOnItem( QListViewItem * ) ) );
00075 connect(
this, SIGNAL(itemRenamed(QListViewItem*,
const QString &,
int)),
00076
this, SLOT(slotItemRenamed(QListViewItem*,
const QString &,
int)));
00077
00078
00079 m_bDrag =
false;
00080 m_branches.setAutoDelete(
true );
00081
00082 m_openFolderPixmap = SmallIcon(
"folder_open" );
00083 }
00084
00085 KFileTreeView::~KFileTreeView()
00086 {
00087
00088
00089
00090 hide();
00091
clear();
00092 m_branches.clear();
00093 }
00094
00095
00096
void KFileTreeView::contentsDragEnterEvent(
QDragEnterEvent *ev )
00097 {
00098
if ( !
acceptDrag( ev ) )
00099 {
00100 ev->ignore();
00101
return;
00102 }
00103 ev->acceptAction();
00104 m_currentBeforeDropItem = selectedItem();
00105
00106 QListViewItem *item = itemAt( contentsToViewport( ev->pos() ) );
00107
if( item )
00108 {
00109 m_dropItem = item;
00110 m_autoOpenTimer->start( KFileView::autoOpenDelay() );
00111 }
00112
else
00113 {
00114 m_dropItem = 0;
00115 }
00116 }
00117
00118
void KFileTreeView::contentsDragMoveEvent(
QDragMoveEvent *e )
00119 {
00120
if( !
acceptDrag( e ) )
00121 {
00122 e->ignore();
00123
return;
00124 }
00125 e->acceptAction();
00126
00127
00128 QListViewItem *afterme;
00129 QListViewItem *parent;
00130
00131
findDrop( e->pos(), parent, afterme );
00132
00133
00134 QListViewItem *item = afterme ? afterme : parent;
00135
00136
if( item && item->isSelectable() )
00137 {
00138 setSelected( item,
true );
00139
if( item != m_dropItem ) {
00140 m_autoOpenTimer->stop();
00141 m_dropItem = item;
00142 m_autoOpenTimer->start( KFileView::autoOpenDelay() );
00143 }
00144 }
00145
else
00146 {
00147 m_autoOpenTimer->stop();
00148 m_dropItem = 0;
00149 }
00150 }
00151
00152
void KFileTreeView::contentsDragLeaveEvent(
QDragLeaveEvent * )
00153 {
00154
00155
if ( m_currentBeforeDropItem )
00156 {
00157 setSelected( m_currentBeforeDropItem,
true );
00158 ensureItemVisible( m_currentBeforeDropItem );
00159 }
00160
else
00161 setSelected( m_dropItem,
false );
00162 m_currentBeforeDropItem = 0;
00163 m_dropItem = 0;
00164
00165 }
00166
00167
void KFileTreeView::contentsDropEvent(
QDropEvent *e )
00168 {
00169
00170 m_autoOpenTimer->stop();
00171 m_dropItem = 0;
00172
00173
kdDebug(250) <<
"contentsDropEvent !" <<
endl;
00174
if( !
acceptDrag( e ) ) {
00175 e->ignore();
00176
return;
00177 }
00178
00179 e->acceptAction();
00180 QListViewItem *afterme;
00181 QListViewItem *parent;
00182
findDrop(e->pos(), parent, afterme);
00183
00184
00185
00186
00187
if (e->source() == viewport() &&
itemsMovable())
00188
movableDropEvent(parent, afterme);
00189
else
00190 {
00191 emit dropped(e, afterme);
00192 emit dropped(
this, e, afterme);
00193 emit dropped(e, parent, afterme);
00194 emit dropped(
this, e, parent, afterme);
00195
00196
KURL::List urls;
00197
KURLDrag::decode( e, urls );
00198 emit dropped(
this, e, urls );
00199
00200
KURL parentURL;
00201
if( parent )
00202 parentURL = static_cast<KFileTreeViewItem*>(parent)->
url();
00203
else
00204
00205
00206
return;
00207
00208 emit dropped( urls, parentURL );
00209 emit dropped(
this , e, urls, parentURL );
00210 }
00211 }
00212
00213 bool KFileTreeView::acceptDrag(
QDropEvent* e )
const
00214
{
00215
00216
bool ancestOK= acceptDrops();
00217
00218 ancestOK = ancestOK &&
itemsMovable();
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
return ancestOK && KURLDrag::canDecode( e ) &&
00229
00230 ( e->action() == QDropEvent::Copy
00231 || e->action() == QDropEvent::Move
00232 || e->action() == QDropEvent::Link );
00233 }
00234
00235
00236
00237
QDragObject *
KFileTreeView::dragObject()
00238 {
00239
00240
KURL::List urls;
00241
const QPtrList<QListViewItem> fileList =
selectedItems();
00242
QPtrListIterator<QListViewItem> it( fileList );
00243
for ( ; it.current(); ++it )
00244 {
00245 urls.append( static_cast<KFileTreeViewItem*>(it.current())->url() );
00246 }
00247
QPoint hotspot;
00248
QPixmap pixmap;
00249
if( urls.count() > 1 ){
00250 pixmap = DesktopIcon(
"kmultiple", 16 );
00251 }
00252
if( pixmap.isNull() )
00253 pixmap =
currentKFileTreeViewItem()->
fileItem()->
pixmap( 16 );
00254 hotspot.setX( pixmap.width() / 2 );
00255 hotspot.setY( pixmap.height() / 2 );
00256
QDragObject* dragObject =
new KURLDrag( urls,
this );
00257
if( dragObject )
00258 dragObject->setPixmap( pixmap, hotspot );
00259
return dragObject;
00260 }
00261
00262
00263
00264
void KFileTreeView::slotCollapsed( QListViewItem *item )
00265 {
00266
KFileTreeViewItem *kftvi = static_cast<KFileTreeViewItem*>(item);
00267
kdDebug(250) <<
"hit slotCollapsed" <<
endl;
00268
if( kftvi && kftvi->
isDir())
00269 {
00270 item->setPixmap( 0, itemIcon(kftvi));
00271 }
00272 }
00273
00274
void KFileTreeView::slotExpanded( QListViewItem *item )
00275 {
00276
kdDebug(250) <<
"slotExpanded here !" <<
endl;
00277
00278
if( ! item )
return;
00279
00280
KFileTreeViewItem *it = static_cast<KFileTreeViewItem*>(item);
00281
KFileTreeBranch *
branch = it->
branch();
00282
00283
00284
if( it->
isDir() && branch && item->childCount() == 0 )
00285 {
00286
00287
kdDebug(250 ) <<
"starting to open " << it->
url().
prettyURL() <<
endl;
00288 startAnimation( it );
00289
bool branchAnswer = branch->
populate( it->
url(), it );
00290
kdDebug(250) <<
"Branches answer: " << branchAnswer <<
endl;
00291
if( ! branchAnswer )
00292 {
00293
kdDebug(250) <<
"ERR: Could not populate!" <<
endl;
00294 stopAnimation( it );
00295 }
00296 }
00297
00298
00299
if( it->
isDir() && isOpen( item ) )
00300 {
00301
kdDebug(250)<<
"Setting open Pixmap" <<
endl;
00302 item->setPixmap( 0, itemIcon( it ));
00303 }
00304 }
00305
00306
00307
00308
void KFileTreeView::slotExecuted( QListViewItem *item )
00309 {
00310
if ( !item )
00311
return;
00312
00313
00314
00315
if( static_cast<KFileTreeViewItem*>(item)->isDir())
00316 {
00317 item->setOpen( !item->isOpen() );
00318 }
00319 }
00320
00321
00322
void KFileTreeView::slotAutoOpenFolder()
00323 {
00324 m_autoOpenTimer->stop();
00325
00326
if ( !m_dropItem || m_dropItem->isOpen() )
00327
return;
00328
00329 m_dropItem->setOpen(
true );
00330 m_dropItem->repaint();
00331 }
00332
00333
00334
void KFileTreeView::slotSelectionChanged()
00335 {
00336
if ( !m_dropItem )
00337 {
00338 }
00339 }
00340
00341
00342 KFileTreeBranch*
KFileTreeView::addBranch(
const KURL &path,
const QString& name,
00343
bool showHidden )
00344 {
00345
const QPixmap& folderPix = KMimeType::mimeType(
"inode/directory")->pixmap( KIcon::Small );
00346
00347
return addBranch( path, name, folderPix, showHidden);
00348 }
00349
00350 KFileTreeBranch*
KFileTreeView::addBranch(
const KURL &path,
const QString& name,
00351
const QPixmap& pix,
bool showHidden )
00352 {
00353
kdDebug(250) <<
"adding another root " << path.
prettyURL() <<
endl;
00354
00355
00356
KFileTreeBranch *newBranch =
new KFileTreeBranch(
this, path, name, pix,
00357 showHidden );
00358
return addBranch(newBranch);
00359 }
00360
00361 KFileTreeBranch *
KFileTreeView::addBranch(
KFileTreeBranch *newBranch)
00362 {
00363 connect( newBranch, SIGNAL(populateFinished(
KFileTreeViewItem* )),
00364
this, SLOT( slotPopulateFinished(
KFileTreeViewItem* )));
00365
00366 connect( newBranch, SIGNAL( newTreeViewItems(
KFileTreeBranch*,
00367
const KFileTreeViewItemList& )),
00368
this, SLOT( slotNewTreeViewItems(
KFileTreeBranch*,
00369
const KFileTreeViewItemList& )));
00370
00371 m_branches.append( newBranch );
00372
return( newBranch );
00373 }
00374
00375 KFileTreeBranch *
KFileTreeView::branch(
const QString& searchName )
00376 {
00377
KFileTreeBranch *branch = 0;
00378
QPtrListIterator<KFileTreeBranch> it( m_branches );
00379
00380
while ( (branch = it.current()) != 0 ) {
00381 ++it;
00382
QString bname = branch->
name();
00383
kdDebug(250) <<
"This is the branches name: " << bname <<
endl;
00384
if( bname == searchName )
00385 {
00386
kdDebug(250) <<
"Found branch " << bname <<
" and return ptr" <<
endl;
00387
return( branch );
00388 }
00389 }
00390
return ( 0L );
00391 }
00392
00393 KFileTreeBranchList&
KFileTreeView::branches()
00394 {
00395
return( m_branches );
00396 }
00397
00398
00399 bool KFileTreeView::removeBranch(
KFileTreeBranch *branch )
00400 {
00401
if(m_branches.contains(branch))
00402 {
00403
delete (branch->
root());
00404 m_branches.remove( branch );
00405
return true;
00406 }
00407
else
00408 {
00409
return false;
00410 }
00411 }
00412
00413 void KFileTreeView::setDirOnlyMode(
KFileTreeBranch* branch,
bool bom )
00414 {
00415
if( branch )
00416 {
00417 branch->
setDirOnlyMode( bom );
00418 }
00419 }
00420
00421
00422
void KFileTreeView::slotPopulateFinished(
KFileTreeViewItem *it )
00423 {
00424
if( it && it->
isDir())
00425 stopAnimation( it );
00426 }
00427
00428
void KFileTreeView::slotNewTreeViewItems(
KFileTreeBranch* branch,
const KFileTreeViewItemList& itemList )
00429 {
00430
if( ! branch )
return;
00431
kdDebug(250) <<
"hitting slotNewTreeViewItems" <<
endl;
00432
00433
00434
00435
00436
00437
00438
00439
00440
if( ! m_nextUrlToSelect.
isEmpty() )
00441 {
00442
KFileTreeViewItemListIterator it( itemList );
00443
00444
bool end =
false;
00445
for( ; !
end && it.current(); ++it )
00446 {
00447
KURL url = (*it)->url();
00448
00449
if( m_nextUrlToSelect.
equals(url,
true ))
00450 {
00451 setCurrentItem( static_cast<QListViewItem*>(*it) );
00452 m_nextUrlToSelect =
KURL();
00453
end =
true;
00454 }
00455 }
00456 }
00457 }
00458
00459
QPixmap KFileTreeView::itemIcon(
KFileTreeViewItem *item,
int gap )
const
00460
{
00461
QPixmap pix;
00462
kdDebug(250) <<
"Setting icon for column " << gap <<
endl;
00463
00464
if( item )
00465 {
00466
00467
KFileTreeBranch *brnch = item->
branch();
00468
if( item == brnch->
root() )
00469 {
00470 pix = brnch->
pixmap();
00471
if( m_wantOpenFolderPixmaps && brnch->
root()->isOpen() )
00472 {
00473 pix = brnch->
openPixmap();
00474 }
00475 }
00476
else
00477 {
00478
00479 pix = item->
fileItem()->
pixmap( KIcon::SizeSmall );
00480
00481
00482
00483
if( item->
isDir() && m_wantOpenFolderPixmaps )
00484 {
00485
if( isOpen( static_cast<QListViewItem*>(item)))
00486 pix = m_openFolderPixmap;
00487 }
00488 }
00489 }
00490
00491
return pix;
00492 }
00493
00494
00495
void KFileTreeView::slotAnimation()
00496 {
00497 MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.begin();
00498 MapCurrentOpeningFolders::Iterator
end = m_mapCurrentOpeningFolders.end();
00499
for (; it !=
end; ++it )
00500 {
00501 uint & iconNumber = it.data().iconNumber;
00502
QString icon = QString::fromLatin1( it.data().iconBaseName ).append( QString::number( iconNumber ) );
00503
00504 it.key()->setPixmap( 0, SmallIcon( icon ));
00505
00506 iconNumber++;
00507
if ( iconNumber > it.data().iconCount )
00508 iconNumber = 1;
00509 }
00510 }
00511
00512
00513
void KFileTreeView::startAnimation(
KFileTreeViewItem * item,
const char * iconBaseName, uint iconCount )
00514 {
00515
00516
if( ! item )
00517 {
00518
kdDebug(250) <<
" startAnimation Got called without valid item !" <<
endl;
00519
return;
00520 }
00521
00522 m_mapCurrentOpeningFolders.insert( item,
00523 AnimationInfo( iconBaseName,
00524 iconCount,
00525 itemIcon(item, 0) ) );
00526
if ( !m_animationTimer->isActive() )
00527 m_animationTimer->start( 50 );
00528 }
00529
00530
void KFileTreeView::stopAnimation(
KFileTreeViewItem * item )
00531 {
00532
if( ! item )
return;
00533
00534
kdDebug(250) <<
"Stoping Animation !" <<
endl;
00535
00536 MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.find(item);
00537
if ( it != m_mapCurrentOpeningFolders.end() )
00538 {
00539
if( item->
isDir() && isOpen( item) )
00540 {
00541
kdDebug(250) <<
"Setting folder open pixmap !" <<
endl;
00542 item->setPixmap( 0, itemIcon( item ));
00543 }
00544
else
00545 {
00546 item->setPixmap( 0, it.data().originalPixmap );
00547 }
00548 m_mapCurrentOpeningFolders.remove( item );
00549 }
00550
else
00551 {
00552
if( item )
00553
kdDebug(250)<<
"StopAnimation - could not find item " << item->
url().
prettyURL()<<
endl;
00554
else
00555
kdDebug(250)<<
"StopAnimation - item is zero !" <<
endl;
00556 }
00557
if (m_mapCurrentOpeningFolders.isEmpty())
00558 m_animationTimer->stop();
00559 }
00560
00561 KFileTreeViewItem *
KFileTreeView::currentKFileTreeViewItem()
const
00562
{
00563
return static_cast<KFileTreeViewItem *>( selectedItem() );
00564 }
00565
00566 KURL KFileTreeView::currentURL()
const
00567
{
00568
KFileTreeViewItem *item =
currentKFileTreeViewItem();
00569
if ( item )
00570
return currentKFileTreeViewItem()->
url();
00571
else
00572
return KURL();
00573 }
00574
00575
void KFileTreeView::slotOnItem( QListViewItem *item )
00576 {
00577
KFileTreeViewItem *i = static_cast<KFileTreeViewItem *>( item );
00578
if( i )
00579 {
00580
const KURL url = i->
url();
00581
if ( url.
isLocalFile() )
00582 emit onItem( url.
path() );
00583
else
00584 emit onItem( url.
prettyURL() );
00585 }
00586 }
00587
00588
void KFileTreeView::slotItemRenamed(QListViewItem* item,
const QString &name,
int col)
00589 {
00590 (
void) item;
00591
kdDebug(250) <<
"Do not bother: " <<
name << col <<
endl;
00592 }
00593
00594 KFileTreeViewItem *
KFileTreeView::findItem(
const QString& branchName,
const QString& relUrl )
00595 {
00596
KFileTreeBranch *br = branch( branchName );
00597
return(
findItem( br, relUrl ));
00598 }
00599
00600 KFileTreeViewItem *
KFileTreeView::findItem(
KFileTreeBranch* brnch,
const QString& relUrl )
00601 {
00602
KFileTreeViewItem *ret = 0;
00603
if( brnch )
00604 {
00605
KURL url = brnch->
rootUrl();
00606
00607
if( ! relUrl.isEmpty() && relUrl != QString::fromLatin1(
"/") )
00608 {
00609
QString partUrl( relUrl );
00610
00611
if( partUrl.endsWith(
"/"))
00612 partUrl.truncate( relUrl.length()-1 );
00613
00614 url.
addPath( partUrl );
00615
00616
kdDebug(250) <<
"assembled complete dir string " << url.
prettyURL() <<
endl;
00617
00618
KFileItem *fi = brnch->
findByURL( url );
00619
if( fi )
00620 {
00621 ret = static_cast<KFileTreeViewItem*>( fi->
extraData( brnch ));
00622
kdDebug(250) <<
"Found item !" <<ret <<
endl;
00623 }
00624 }
00625
else
00626 {
00627 ret = brnch->
root();
00628 }
00629 }
00630
return( ret );
00631 }
00632
00635
00636
00637
void KFileTreeViewToolTip::maybeTip(
const QPoint & )
00638 {
00639
#if 0
00640
QListViewItem *item = m_view->itemAt( point );
00641
if ( item ) {
00642
QString text = static_cast<KFileViewItem*>( item )->toolTipText();
00643
if ( !text.isEmpty() )
00644 tip ( m_view->itemRect( item ), text );
00645 }
00646
#endif
00647
}
00648
00649
void KFileTreeView::virtual_hook(
int id,
void* data )
00650 {
KListView::virtual_hook(
id, data ); }
00651
00652
#include "kfiletreeview.moc"