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